1mod backward;
10mod constraint;
11pub(crate) mod known;
12mod range;
13#[cfg(test)]
14mod tests;
15mod transfer;
16
17use core::fmt;
18use std::sync::Arc;
19
20pub(crate) use constraint::Env;
21pub use constraint::{Assumptions, ConstraintId, Reliance};
22pub use known::KnownBits;
23pub use range::{SRange, URange};
24
25use crate::error::Error;
26use crate::expr::{Context, Expr, OpCode};
27use crate::hash::IdMap;
28use crate::ops::{CmpOp, CmpOpExt, UnOp};
29use crate::{BitVec, Width};
30use range::{sle, slt, ule, ult};
31pub(crate) use transfer::decide as decide_cmp;
32use transfer::{TOp, decide, transfer};
33
34#[derive(Copy, Clone, PartialEq, Eq, Hash)]
37pub struct Facts {
38 pub(crate) known: KnownBits,
39 pub(crate) urange: URange,
40 pub(crate) srange: SRange,
41}
42
43impl fmt::Debug for Facts {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 write!(
46 f,
47 "Facts({:?}, u[{}, {}], s[{}, {}])",
48 self.known,
49 self.urange.lo(),
50 self.urange.hi(),
51 self.srange.lo(),
52 self.srange.hi()
53 )
54 }
55}
56
57impl Facts {
58 pub fn top(w: Width) -> Facts {
60 Facts {
61 known: KnownBits::unknown(w),
62 urange: URange::full(w),
63 srange: SRange::full(w),
64 }
65 }
66
67 pub fn constant(v: &BitVec) -> Facts {
69 Facts {
70 known: KnownBits::constant(v),
71 urange: URange::constant(v),
72 srange: SRange::constant(v),
73 }
74 }
75
76 pub fn new(known: KnownBits, urange: URange, srange: SRange) -> Option<Facts> {
79 if known.width() != urange.width() || known.width() != srange.width() {
80 return None;
81 }
82 Facts::reduce(known, urange, srange)
83 }
84
85 pub fn known(&self) -> KnownBits {
87 self.known
88 }
89
90 pub fn urange(&self) -> URange {
92 self.urange
93 }
94
95 pub fn srange(&self) -> SRange {
97 self.srange
98 }
99
100 pub fn from_known(k: KnownBits) -> Facts {
102 let w = k.width();
103 Facts::reduce(k, URange::full(w), SRange::full(w)).unwrap_or_else(|| Facts::top(w))
104 }
105
106 pub fn width(&self) -> Width {
108 self.known.width()
109 }
110
111 pub fn as_constant(&self) -> Option<BitVec> {
113 self.known.as_constant()
114 }
115
116 pub fn contains(&self, v: &BitVec) -> bool {
118 self.known.contains(v) && self.urange.contains(v) && self.srange.contains(v)
119 }
120
121 pub fn meet(&self, o: &Facts) -> Option<Facts> {
123 if self.width() != o.width() {
124 return None;
125 }
126 if self.refines(o) {
128 return Some(*self);
129 }
130 if o.refines(self) {
131 return Some(*o);
132 }
133 Facts::reduce(
134 self.known.meet(&o.known)?,
135 self.urange.meet(&o.urange)?,
136 self.srange.meet(&o.srange)?,
137 )
138 }
139
140 fn refines(&self, o: &Facts) -> bool {
142 let (k, ok) = (&self.known, &o.known);
143 let bits = |a: &BitVec, b: &BitVec| known::bv_and(a, &known::bv_not(b)).is_zero();
144 bits(&ok.known_zero(), &k.known_zero())
145 && bits(&ok.known_one(), &k.known_one())
146 && ule(&o.urange.lo(), &self.urange.lo())
147 && ule(&self.urange.hi(), &o.urange.hi())
148 && sle(&o.srange.lo(), &self.srange.lo())
149 && sle(&self.srange.hi(), &o.srange.hi())
150 }
151
152 pub fn join(&self, o: &Facts) -> Option<Facts> {
154 (self.width() == o.width()).then(|| self.hull(o))
155 }
156
157 pub(crate) fn hull(&self, o: &Facts) -> Facts {
159 let w = self.width();
160 Facts::reduce(
161 self.known.hull(&o.known),
162 self.urange.hull(&o.urange),
163 self.srange.hull(&o.srange),
164 )
165 .unwrap_or_else(|| Facts::top(w))
166 }
167
168 pub(crate) fn meet_known(&self, k: &KnownBits) -> Option<Facts> {
169 Facts::reduce(self.known.meet(k)?, self.urange, self.srange)
170 }
171
172 pub(crate) fn meet_urange(&self, u: &URange) -> Option<Facts> {
173 Facts::reduce(self.known, self.urange.meet(u)?, self.srange)
174 }
175
176 pub(crate) fn reduce(mut k: KnownBits, mut u: URange, mut s: SRange) -> Option<Facts> {
179 let w = k.width();
180 for round in 0..2 {
181 let before = (k, u, s);
182 u = u.meet(&URange::new(k.umin(), k.umax())?)?;
184 s = s.meet(&SRange::new(k.smin(), k.smax())?)?;
185 k = k.meet(&prefix_bits(&u.lo(), &u.hi()))?;
187 let zero = BitVec::zero(w);
189 let non_negative = sle(&zero, &s.lo());
190 let negative = slt(&s.hi(), &zero);
191 if non_negative || negative {
192 k = k.meet(&prefix_bits(&s.lo(), &s.hi()))?;
193 u = u.meet(&URange::new(s.lo(), s.hi())?)?;
194 }
195 let smax = BitVec::smax(w);
197 if ule(&u.hi(), &smax) || ult(&smax, &u.lo()) {
198 s = s.meet(&SRange::new(u.lo(), u.hi())?)?;
199 }
200 if round == 0 && before == (k, u, s) {
203 break;
204 }
205 }
206 Some(Facts {
207 known: k,
208 urange: u,
209 srange: s,
210 })
211 }
212}
213
214impl Facts {
218 pub fn apply_un(op: UnOp, a: &Facts) -> Result<Facts, crate::WidthError> {
220 BitVec::apply_un(op, &BitVec::zero(a.width()))?;
221 Ok(transfer(&TOp::Un(op), &[a]))
222 }
223
224 pub fn apply_bin(op: crate::BinOp, a: &Facts, b: &Facts) -> Result<Facts, crate::WidthError> {
226 same_width(a, b)?;
227 Ok(transfer(&TOp::Bin(op), &[a, b]))
228 }
229
230 pub fn apply_cmp(
232 op: impl Into<CmpOpExt>,
233 a: &Facts,
234 b: &Facts,
235 ) -> Result<Facts, crate::WidthError> {
236 same_width(a, b)?;
237 let (op, swap) = op.into().canonical();
238 let (a, b) = if swap { (b, a) } else { (a, b) };
239 Ok(transfer(&TOp::Cmp(op), &[a, b]))
240 }
241
242 pub fn zext(&self, to: Width) -> Result<Facts, crate::WidthError> {
244 if to == self.width() {
245 return Ok(*self);
246 }
247 crate::BitVec::zero(self.width()).zext(to)?;
248 Ok(transfer(&TOp::Zext(to), &[self]))
249 }
250
251 pub fn sext(&self, to: Width) -> Result<Facts, crate::WidthError> {
253 if to == self.width() {
254 return Ok(*self);
255 }
256 crate::BitVec::zero(self.width()).sext(to)?;
257 Ok(transfer(&TOp::Sext(to), &[self]))
258 }
259
260 pub fn extract(&self, lo: u16, len: Width) -> Result<Facts, crate::WidthError> {
262 crate::BitVec::zero(self.width()).extract(lo, len)?;
263 Ok(transfer(&TOp::Extract { lo, width: len }, &[self]))
264 }
265
266 pub fn concat(hi: &Facts, lo: &Facts) -> Result<Facts, crate::WidthError> {
268 crate::BitVec::concat(&BitVec::zero(hi.width()), &BitVec::zero(lo.width()))?;
269 Ok(transfer(&TOp::Concat, &[hi, lo]))
270 }
271
272 pub fn select(c: &Facts, t: &Facts, f: &Facts) -> Result<Facts, crate::WidthError> {
274 crate::BitVec::select(
275 &BitVec::zero(c.width()),
276 &BitVec::zero(t.width()),
277 &BitVec::zero(f.width()),
278 )?;
279 Ok(transfer(&TOp::Select, &[c, t, f]))
280 }
281}
282
283impl KnownBits {
286 pub fn apply_un(op: UnOp, a: &KnownBits) -> Result<KnownBits, crate::WidthError> {
288 Ok(Facts::apply_un(op, &Facts::from_known(*a))?.known)
289 }
290
291 pub fn apply_bin(
293 op: crate::BinOp,
294 a: &KnownBits,
295 b: &KnownBits,
296 ) -> Result<KnownBits, crate::WidthError> {
297 Ok(Facts::apply_bin(op, &Facts::from_known(*a), &Facts::from_known(*b))?.known)
298 }
299}
300
301fn same_width(a: &Facts, b: &Facts) -> Result<(), crate::WidthError> {
302 if a.width() == b.width() {
303 Ok(())
304 } else {
305 Err(crate::WidthError::Mismatch {
306 left: a.width().bits(),
307 right: b.width().bits(),
308 })
309 }
310}
311
312fn prefix_bits(lo: &BitVec, hi: &BitVec) -> KnownBits {
314 let w = lo.width();
315 let diff = known::bv_xor(lo, hi);
316 let p = known::leading_zeros(&diff);
317 let mask = known::high_mask(w, p);
318 KnownBits::from_masks(
319 known::bv_and(&known::bv_not(lo), &mask),
320 known::bv_and(lo, &mask),
321 )
322}
323
324#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
326pub enum Truth {
327 True,
329 False,
331 Unknown,
333}
334
335impl Truth {
336 fn from_opt(b: Option<bool>) -> Truth {
337 match b {
338 Some(true) => Truth::True,
339 Some(false) => Truth::False,
340 None => Truth::Unknown,
341 }
342 }
343}
344
345impl core::ops::Not for Truth {
346 type Output = Truth;
347 fn not(self) -> Truth {
349 match self {
350 Truth::True => Truth::False,
351 Truth::False => Truth::True,
352 Truth::Unknown => Truth::Unknown,
353 }
354 }
355}
356
357#[derive(Copy, Clone, Debug)]
359#[non_exhaustive]
360pub enum Query<'q> {
361 IsZero(Expr),
363 IsNonZero(Expr),
365 Bit {
367 e: Expr,
369 bit: u16,
371 value: bool,
373 },
374 Eq(Expr, Expr),
376 Cmp(CmpOpExt, Expr, Expr),
378 InURange {
380 e: Expr,
382 lo: &'q BitVec,
384 hi: &'q BitVec,
386 },
387 InSRange {
389 e: Expr,
391 lo: &'q BitVec,
393 hi: &'q BitVec,
395 },
396 Aligned {
398 e: Expr,
400 log2: u16,
402 },
403 MaskRedundant {
405 e: Expr,
407 mask: &'q BitVec,
409 },
410 FitsUnsigned {
412 e: Expr,
414 bits: u16,
416 },
417 FitsSigned {
419 e: Expr,
421 bits: u16,
423 },
424 IsConstant(Expr),
426}
427
428#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
431#[non_exhaustive]
432pub struct Proof {
433 pub truth: Truth,
435 pub relies_on: Reliance,
437}
438
439#[derive(Clone, Debug)]
442struct Pending {
443 root: u32,
444 order: Vec<u32>,
445 pos: usize,
446}
447
448#[derive(Clone, Debug, Default)]
451pub(crate) struct FactCache {
452 base: IdMap<u32, Facts>,
453 overlay: IdMap<u32, (Facts, Reliance)>,
454 overlay_key: Option<Assumptions>,
455 pending: Option<Pending>,
456 pub(crate) work: u64,
458 pub(crate) capped: u64,
460 pub(crate) walked: u64,
462}
463
464impl FactCache {
465 pub(crate) fn forget(&mut self, a: &Assumptions) {
467 if self
468 .overlay_key
469 .as_ref()
470 .is_some_and(|k| Arc::ptr_eq(&k.store, &a.store))
471 {
472 self.overlay_key = None;
473 self.overlay.clear();
474 }
475 }
476
477 pub(crate) fn clear(&mut self) {
478 self.base.clear();
479 self.overlay.clear();
480 self.overlay_key = None;
481 self.pending = None;
482 }
483}
484
485impl Context {
486 pub(crate) fn top_of(&self, i: u32) -> TOp {
487 let n = self.node(i);
488 let w = self.width_of(i);
489 match n.op {
490 OpCode::Const => TOp::Const(self.const_val(i).unwrap_or(BitVec::zero(w))),
491 OpCode::Sym => TOp::Top(w),
492 OpCode::Zext => TOp::Zext(w),
493 OpCode::Sext => TOp::Sext(w),
494 OpCode::Extract => TOp::Extract {
495 lo: n.b as u16,
496 width: w,
497 },
498 OpCode::Concat => TOp::Concat,
499 OpCode::Select => TOp::Select,
500 op => {
501 if let Some(u) = op.as_un() {
502 TOp::Un(u)
503 } else if let Some(b) = op.as_bin() {
504 TOp::Bin(b)
505 } else if let Some(c) = op.as_cmp() {
506 TOp::Cmp(c)
507 } else {
508 TOp::Top(w)
509 }
510 }
511 }
512 }
513
514 fn transfer_node(&self, i: u32, get: impl Fn(u32) -> Facts) -> Facts {
516 let op = self.top_of(i);
517 let n = self.node(i);
518 let mut kids = [Facts::top(Width::W1); 3];
519 let mut k = 0;
520 for c in n.children() {
521 kids[k] = get(c);
522 k += 1;
523 }
524 let refs: [&Facts; 3] = [&kids[0], &kids[1], &kids[2]];
525 self.transfer_at(i, &op, &refs[..k])
526 }
527
528 pub(crate) fn transfer_at(&self, i: u32, op: &TOp, args: &[&Facts]) -> Facts {
532 let n = self.node(i);
533 if n.op == OpCode::Select {
534 let f = transfer(op, args);
535 return self
536 .min_max_bound(i, args)
537 .and_then(|g| f.meet(&g))
538 .unwrap_or(f);
539 }
540 if n.op == OpCode::Concat {
541 let f = transfer(op, args);
542 return self
543 .wide_product_bound(i)
544 .and_then(|g| f.meet(&g))
545 .unwrap_or(f);
546 }
547 let Some((_, k)) = n.op.as_ext() else {
548 return transfer(op, args);
549 };
550 let w = self.width_of(i);
551 let Some(o) = self.registry.as_deref().and_then(|r| r.op_at(n.aux)) else {
552 return Facts::top(w);
553 };
554 let vals: Option<Vec<BitVec>> = args.iter().map(|f| f.as_constant()).collect();
556 if let Some(vals) = vals {
557 return match crate::ext::run_eval(o, &vals) {
558 Ok(out) if out.get(k).is_some_and(|v| v.width() == w) => Facts::constant(&out[k]),
559 _ => Facts::top(w),
560 };
561 }
562 let widths: Vec<Width> = args.iter().map(|f| f.width()).collect();
563 let Ok(sig) = o.signature(&widths) else {
564 return Facts::top(w);
565 };
566 let kb: Vec<KnownBits> = args.iter().map(|f| f.known).collect();
567 match crate::ext::run_known_bits(o, &sig, &kb) {
568 Ok(out) => out
569 .get(k)
570 .filter(|kb| kb.width() == w)
571 .map_or(Facts::top(w), |kb| Facts::from_known(*kb)),
572 Err(_) => Facts::top(w),
573 }
574 }
575
576 fn min_max_bound(&self, i: u32, args: &[&Facts]) -> Option<Facts> {
580 let n = self.node(i);
581 let c = self.node(n.a);
582 let op = c.op.as_cmp()?;
583 let min = if (n.b, n.c) == (c.a, c.b) {
584 true
585 } else if (n.b, n.c) == (c.b, c.a) {
586 false
587 } else {
588 return None;
589 };
590 let (t, f) = (args[1], args[2]);
591 let w = t.width();
592 let pick = |x: BitVec, y: BitVec, less: fn(&BitVec, &BitVec) -> bool, low: bool| {
593 if less(&x, &y) == low { x } else { y }
594 };
595 match op {
596 CmpOp::Ult | CmpOp::Ule => {
597 let (a, b) = (t.urange, f.urange);
598 let lo = pick(a.lo(), b.lo(), ult, min);
599 let hi = pick(a.hi(), b.hi(), ult, min);
600 Facts::new(KnownBits::unknown(w), URange::new(lo, hi)?, SRange::full(w))
601 }
602 CmpOp::Slt | CmpOp::Sle => {
603 let (a, b) = (t.srange, f.srange);
604 let lo = pick(a.lo(), b.lo(), slt, min);
605 let hi = pick(a.hi(), b.hi(), slt, min);
606 Facts::new(KnownBits::unknown(w), URange::full(w), SRange::new(lo, hi)?)
607 }
608 _ => None,
609 }
610 }
611
612 fn wide_product_bound(&self, i: u32) -> Option<Facts> {
616 let n = self.node(i);
617 let (hi, lo) = (self.node(n.a), self.node(n.b));
618 if lo.op != OpCode::Mul || (hi.a, hi.b) != (lo.a, lo.b) {
619 return None;
620 }
621 let signed = match hi.op {
622 OpCode::UMulHi => false,
623 OpCode::SMulHi => true,
624 _ => return None,
625 };
626 let w2 = self.width_of(i);
627 let fa = self.facts.base.get(&lo.a)?;
628 let fb = self.facts.base.get(&lo.b)?;
629 let mul = |x: &BitVec, y: &BitVec| BitVec::bin_unchecked(crate::BinOp::Mul, x, y);
630 if signed {
631 let ext = |v: BitVec| v.sext(w2).ok();
632 let (a, b) = (fa.srange, fb.srange);
633 let corners = [
634 mul(&ext(a.lo())?, &ext(b.lo())?),
635 mul(&ext(a.lo())?, &ext(b.hi())?),
636 mul(&ext(a.hi())?, &ext(b.lo())?),
637 mul(&ext(a.hi())?, &ext(b.hi())?),
638 ];
639 let lo = corners
640 .iter()
641 .copied()
642 .reduce(|x, y| if slt(&y, &x) { y } else { x })?;
643 let hi = corners
644 .iter()
645 .copied()
646 .reduce(|x, y| if slt(&x, &y) { y } else { x })?;
647 Facts::new(
648 KnownBits::unknown(w2),
649 URange::full(w2),
650 SRange::new(lo, hi)?,
651 )
652 } else {
653 let ext = |v: BitVec| v.zext(w2).ok();
654 let (a, b) = (fa.urange, fb.urange);
655 let lo = mul(&ext(a.lo())?, &ext(b.lo())?);
656 let hi = mul(&ext(a.hi())?, &ext(b.hi())?);
657 Facts::new(
658 KnownBits::unknown(w2),
659 URange::new(lo, hi)?,
660 SRange::full(w2),
661 )
662 }
663 }
664
665 fn uncached_order(&mut self, root: u32) -> Vec<u32> {
667 self.marks.begin(self.len());
668 let mut order = Vec::new();
669 let mut stack: Vec<(u32, u8)> = vec![(root, 0)];
670 self.marks.test_and_set(root);
671 while let Some(top) = stack.last_mut() {
672 let (i, k) = *top;
673 let n = self.node(i);
674 if (k as usize) < n.op.arity() {
675 top.1 += 1;
676 let c = [n.a, n.b, n.c][k as usize];
677 if !self.facts.base.contains_key(&c) && !self.marks.test_and_set(c) {
678 stack.push((c, 0));
679 }
680 } else {
681 stack.pop();
682 order.push(i);
683 }
684 }
685 order
686 }
687
688 fn compute_facts(&mut self, root: u32) -> Option<Facts> {
692 let cap = self.config().fact_work.max(1);
693 self.compute_facts_cap(root, cap)
694 }
695
696 fn compute_facts_cap(&mut self, root: u32, cap: u32) -> Option<Facts> {
698 if let Some(f) = self.facts.base.get(&root) {
699 return Some(*f);
700 }
701 let cap = cap.min(self.config().fact_work.max(1));
702 if cap == 0 {
703 self.facts.capped += 1;
704 return None;
705 }
706 let cap = cap as usize;
707 let mut pending = match self.facts.pending.take() {
708 Some(p) if p.root == root => p,
709 _ => Pending {
710 root,
711 order: self.uncached_order(root),
712 pos: 0,
713 },
714 };
715 let mut done = 0usize;
716 while pending.pos < pending.order.len() {
717 let i = pending.order[pending.pos];
718 if !self.facts.base.contains_key(&i) {
719 if done >= cap {
720 self.facts.pending = Some(pending);
721 self.facts.capped += 1;
722 return None;
723 }
724 let f = self.transfer_node(i, |c| self.facts.base[&c]);
725 self.facts.base.insert(i, f);
726 done += 1;
727 self.facts.work += 1;
728 }
729 pending.pos += 1;
730 }
731 self.facts.base.get(&root).copied()
732 }
733
734 pub fn facts(&mut self, e: Expr) -> Result<Facts, Error> {
737 let i = self.id(e)?;
738 Ok(self
739 .compute_facts(i)
740 .unwrap_or_else(|| Facts::top(self.width_of(i))))
741 }
742
743 pub fn try_facts(&mut self, e: Expr) -> Result<Option<Facts>, Error> {
746 let i = self.id(e)?;
747 Ok(self.compute_facts(i))
748 }
749
750 pub fn exact(&mut self, e: Expr) -> Result<Option<BitVec>, Error> {
752 if let Some(v) = self.as_const(e)? {
753 return Ok(Some(v));
754 }
755 Ok(self.facts(e)?.as_constant())
756 }
757
758 pub fn enumerate_values(&mut self, e: Expr, limit: u32) -> Result<Option<Vec<BitVec>>, Error> {
762 let f = self.facts(e)?;
763 let limit = u64::from(limit.min(1 << 20));
764 let span = BitVec::bin_unchecked(crate::BinOp::Sub, &f.urange.hi(), &f.urange.lo());
766 if span.to_u64().is_some_and(|d| d < limit) {
767 let mut out = Vec::new();
768 let mut v = f.urange.lo();
769 let one = BitVec::one(f.width());
770 loop {
771 if f.contains(&v) {
772 out.push(v);
773 }
774 if v == f.urange.hi() {
775 break;
776 }
777 v = BitVec::bin_unchecked(crate::BinOp::Add, &v, &one);
778 }
779 return Ok(Some(out));
780 }
781 Ok(f.known
783 .enumerate(20)
784 .map(|vs| vs.into_iter().filter(|v| f.contains(v)).collect::<Vec<_>>())
785 .filter(|vs| vs.len() as u64 <= limit))
786 }
787
788 pub fn facts_with(
791 &mut self,
792 e: Expr,
793 assumptions: &Assumptions,
794 ) -> Result<Option<Facts>, Error> {
795 let cap = self.config().fact_work;
796 self.facts_with_cap(e, assumptions, cap)
797 }
798
799 pub(crate) fn try_facts_cap(&mut self, e: Expr, cap: u32) -> Result<Option<Facts>, Error> {
801 let i = self.id(e)?;
802 Ok(self.compute_facts_cap(i, cap))
803 }
804
805 pub fn facts_under(
808 &mut self,
809 e: Expr,
810 assumptions: &Assumptions,
811 ) -> Result<Option<(Facts, Reliance)>, Error> {
812 let cap = self.config().fact_work;
813 Ok(self.facts_under_cap(e, assumptions, cap)?.ok())
814 }
815
816 pub(crate) fn facts_with_cap(
819 &mut self,
820 e: Expr,
821 assumptions: &Assumptions,
822 cap: u32,
823 ) -> Result<Option<Facts>, Error> {
824 Ok(self
825 .facts_under_cap(e, assumptions, cap)?
826 .ok()
827 .map(|(f, _)| f))
828 }
829
830 pub(crate) fn facts_under_cap(
833 &mut self,
834 e: Expr,
835 assumptions: &Assumptions,
836 cap: u32,
837 ) -> Result<Result<(Facts, Reliance), Reliance>, Error> {
838 let root = self.id(e)?;
839 self.overlay_for(assumptions)?;
840 let mut overlay = core::mem::take(&mut self.facts.overlay);
841 let r = self.overlay_facts(&assumptions.store.env, &mut overlay, root, cap);
842 self.facts.overlay = overlay;
843 Ok(r)
844 }
845
846 fn overlay_for(&mut self, assumptions: &Assumptions) -> Result<(), Error> {
848 if self.facts.overlay_key.as_ref() != Some(assumptions) {
849 assumptions.check_context(self)?;
850 self.facts.overlay.clear();
851 self.facts.overlay_key = Some(assumptions.clone());
852 }
853 Ok(())
854 }
855
856 pub(crate) fn assumed_order(
859 &self,
860 assumptions: &Assumptions,
861 op: CmpOp,
862 x: u32,
863 y: u32,
864 ) -> Option<(bool, Reliance)> {
865 let env = &assumptions.store.env;
866 if env.infeasible.is_some() || x == y {
867 return None;
868 }
869 let (m, r) = env.relation(x, y)?;
870 constraint::worlds::decide(m, op).map(|v| (v, r))
871 }
872
873 pub(crate) fn overlay_facts(
877 &mut self,
878 env: &Env,
879 overlay: &mut IdMap<u32, (Facts, Reliance)>,
880 root: u32,
881 cap: u32,
882 ) -> Result<(Facts, Reliance), Reliance> {
883 if let Some(rel) = env.infeasible {
884 return Err(rel);
885 }
886 let cap = cap.min(self.config().fact_work.max(1));
887 if let Some(f) = overlay.get(&root) {
888 return Ok(*f);
889 }
890 let base = |cx: &mut Context, i: u32| {
891 let f = cx
892 .compute_facts_cap(i, cap)
893 .unwrap_or_else(|| Facts::top(cx.width_of(i)));
894 (f, Reliance::NONE)
895 };
896 if env.is_empty() || root < env.min {
899 return Ok(base(self, root));
900 }
901 let min = env.min;
902 self.marks.begin(self.len());
906 let mut order = Vec::new();
907 let mut stack: Vec<(u32, u8)> = vec![(root, 0)];
908 self.marks.test_and_set(root);
909 while let Some(top) = stack.last_mut() {
910 let (i, k) = *top;
911 let n = self.node(i);
912 if (k as usize) < n.op.arity() {
913 top.1 += 1;
914 let c = [n.a, n.b, n.c][k as usize];
915 if c >= min && !overlay.contains_key(&c) && !self.marks.test_and_set(c) {
916 self.facts.walked += 1;
917 stack.push((c, 0));
918 }
919 } else {
920 stack.pop();
921 order.push(i);
922 }
923 }
924 let cap = cap as usize;
925 let mut work = 0usize;
926 for &i in &order {
927 let n = self.node(i);
928 let ordering = n.op.as_cmp().and_then(|_| env.relation(n.a, n.b));
929 let kid = |cx: &mut Context, overlay: &IdMap<u32, (Facts, Reliance)>, c: u32| {
931 overlay.get(&c).copied().unwrap_or_else(|| base(cx, c))
932 };
933 let mut kids = [(Facts::top(Width::W1), Reliance::NONE); 3];
934 for (k, c) in n.children().enumerate() {
935 kids[k] = kid(self, overlay, c);
936 }
937 let tainted = env.assumed.contains_key(&i)
938 || ordering.is_some()
939 || kids[..n.op.arity()].iter().any(|(_, r)| !r.is_none());
940 if !tainted {
941 let f = base(self, i);
942 overlay.insert(i, f);
943 continue;
944 }
945 if work >= cap {
946 self.facts.capped += 1;
947 return Ok((Facts::top(self.width_of(root)), Reliance::NONE));
948 }
949 work += 1;
950 self.facts.work += 1;
951 let mut rel = Reliance::NONE;
952 for (_, r) in &kids[..n.op.arity()] {
953 rel |= *r;
954 }
955 let refs: [&Facts; 3] = [&kids[0].0, &kids[1].0, &kids[2].0];
956 let mut f = self.transfer_at(i, &self.top_of(i), &refs[..n.op.arity()]);
957 if let (Some(op), Some((m, r))) = (n.op.as_cmp(), ordering)
958 && let Some(v) = constraint::worlds::decide(m, op)
959 {
960 let v = BitVec::from_bool(v);
961 if !f.contains(&v) {
962 return Err(rel | r);
963 }
964 f = Facts::constant(&v);
966 rel = r;
967 }
968 if let Some((a, r)) = env.assumed.get(&i) {
969 rel |= *r;
970 f = f.meet(a).ok_or(rel)?;
971 }
972 overlay.insert(i, (f, rel));
973 }
974 Ok(overlay
975 .get(&root)
976 .copied()
977 .unwrap_or_else(|| base(self, root)))
978 }
979
980 pub fn prove(&mut self, q: Query<'_>) -> Result<Truth, Error> {
982 Ok(self.prove_inner(q, None)?.truth)
983 }
984
985 pub fn prove_with(&mut self, q: Query<'_>, assumptions: &Assumptions) -> Result<Truth, Error> {
988 Ok(self.prove_under(q, assumptions)?.truth)
989 }
990
991 pub fn prove_under(&mut self, q: Query<'_>, assumptions: &Assumptions) -> Result<Proof, Error> {
993 self.prove_inner(q, Some(assumptions))
994 }
995
996 fn validate_query(&self, q: &Query<'_>) -> Result<Vec<Expr>, Error> {
998 let same = |a: Width, b: Width| -> Result<(), Error> {
999 if a != b {
1000 return Err(crate::WidthError::Mismatch {
1001 left: a.bits(),
1002 right: b.bits(),
1003 }
1004 .into());
1005 }
1006 Ok(())
1007 };
1008 Ok(match *q {
1009 Query::IsZero(e) | Query::IsNonZero(e) | Query::IsConstant(e) => {
1010 self.width(e)?;
1011 vec![e]
1012 }
1013 Query::Aligned { e, .. }
1014 | Query::FitsUnsigned { e, .. }
1015 | Query::FitsSigned { e, .. } => {
1016 self.width(e)?;
1017 vec![e]
1018 }
1019 Query::Bit { e, bit, .. } => {
1020 let w = self.width(e)?;
1021 if bit >= w.bits() {
1022 return Err(crate::WidthError::ExtractRange {
1023 width: w.bits(),
1024 lo: bit,
1025 len: 1,
1026 }
1027 .into());
1028 }
1029 vec![e]
1030 }
1031 Query::Eq(x, y) | Query::Cmp(_, x, y) => {
1032 same(self.width(x)?, self.width(y)?)?;
1033 vec![x, y]
1034 }
1035 Query::InURange { e, lo, hi } | Query::InSRange { e, lo, hi } => {
1036 let w = self.width(e)?;
1037 same(w, lo.width())?;
1038 same(w, hi.width())?;
1039 vec![e]
1040 }
1041 Query::MaskRedundant { e, mask } => {
1042 same(self.width(e)?, mask.width())?;
1043 vec![e]
1044 }
1045 })
1046 }
1047
1048 fn prove_inner(&mut self, q: Query<'_>, a: Option<&Assumptions>) -> Result<Proof, Error> {
1049 let exprs = self.validate_query(&q)?;
1050 let proof = |truth: Truth, relies_on: Reliance| Proof {
1051 truth,
1052 relies_on: if truth == Truth::Unknown {
1053 Reliance::NONE
1054 } else {
1055 relies_on
1056 },
1057 };
1058 if let Some(a) = a
1060 && let Query::Eq(x, y) | Query::Cmp(_, x, y) = q
1061 && x != y
1062 {
1063 let (op, swap) = match q {
1064 Query::Cmp(op, ..) => op.canonical(),
1065 _ => (CmpOp::Eq, false),
1066 };
1067 let (x, y) = if swap { (y, x) } else { (x, y) };
1068 a.check_context(self)?;
1069 let (x, y) = (self.id(x)?, self.id(y)?);
1070 if let Some((v, r)) = self.assumed_order(a, op, x, y) {
1071 return Ok(proof(Truth::from_opt(Some(v)), r));
1072 }
1073 }
1074 let mut fs = Vec::with_capacity(2);
1076 let mut rel = Reliance::NONE;
1077 for e in exprs {
1078 let f = match a {
1079 None => self.facts(e)?,
1080 Some(a) => {
1081 let cap = self.config().fact_work;
1082 match self.facts_under_cap(e, a, cap)? {
1083 Ok((f, r)) => {
1084 rel |= r;
1085 f
1086 }
1087 Err(r) => return Ok(proof(Truth::True, r)),
1089 }
1090 }
1091 };
1092 fs.push(f);
1093 }
1094 let f = fs[0];
1095 let w = f.width();
1096 let truth = match q {
1097 Query::IsZero(_) => {
1098 Truth::from_opt(decide(CmpOp::Eq, &f, &Facts::constant(&BitVec::zero(w))))
1099 }
1100 Query::IsNonZero(_) => {
1101 !Truth::from_opt(decide(CmpOp::Eq, &f, &Facts::constant(&BitVec::zero(w))))
1102 }
1103 Query::IsConstant(_) => {
1104 if f.as_constant().is_some() {
1105 Truth::True
1106 } else {
1107 Truth::Unknown
1108 }
1109 }
1110 Query::Bit { bit, value, .. } => Truth::from_opt(f.known.bit(bit).map(|b| b == value)),
1111 Query::Eq(x, y) => {
1112 if x == y {
1113 Truth::True
1114 } else {
1115 Truth::from_opt(decide(CmpOp::Eq, &fs[0], &fs[1]))
1116 }
1117 }
1118 Query::Cmp(op, x, y) => {
1119 let (op, swap) = op.canonical();
1120 if x == y {
1121 Truth::from_opt(Some(matches!(op, CmpOp::Eq | CmpOp::Ule | CmpOp::Sle)))
1122 } else {
1123 let (fx, fy) = if swap {
1124 (&fs[1], &fs[0])
1125 } else {
1126 (&fs[0], &fs[1])
1127 };
1128 Truth::from_opt(decide(op, fx, fy))
1129 }
1130 }
1131 Query::InURange { lo, hi, .. } => {
1132 if ule(lo, &f.urange.lo()) && ule(&f.urange.hi(), hi) {
1133 Truth::True
1134 } else if ult(hi, &f.urange.lo()) || ult(&f.urange.hi(), lo) {
1135 Truth::False
1136 } else {
1137 Truth::Unknown
1138 }
1139 }
1140 Query::InSRange { lo, hi, .. } => {
1141 if sle(lo, &f.srange.lo()) && sle(&f.srange.hi(), hi) {
1142 Truth::True
1143 } else if slt(hi, &f.srange.lo()) || slt(&f.srange.hi(), lo) {
1144 Truth::False
1145 } else {
1146 Truth::Unknown
1147 }
1148 }
1149 Query::Aligned { log2, .. } => {
1150 let low = known::low_mask(w, u32::from(log2));
1151 if known::bv_and(&f.known.maybe_one(), &low).is_zero() {
1152 Truth::True
1153 } else if !known::bv_and(&f.known.known_one(), &low).is_zero() {
1154 Truth::False
1155 } else {
1156 Truth::Unknown
1157 }
1158 }
1159 Query::MaskRedundant { mask, .. } => {
1160 let outside = known::bv_not(mask);
1161 if known::bv_and(&f.known.maybe_one(), &outside).is_zero() {
1162 Truth::True
1163 } else if !known::bv_and(&f.known.known_one(), &outside).is_zero() {
1164 Truth::False
1165 } else {
1166 Truth::Unknown
1167 }
1168 }
1169 Query::FitsUnsigned { bits, .. } => {
1170 if u32::from(bits) >= u32::from(w.bits()) {
1171 Truth::True
1172 } else {
1173 let limit = known::low_mask(w, u32::from(bits));
1174 if ule(&f.urange.hi(), &limit) {
1175 Truth::True
1176 } else if ult(&limit, &f.urange.lo()) {
1177 Truth::False
1178 } else {
1179 Truth::Unknown
1180 }
1181 }
1182 }
1183 Query::FitsSigned { bits, .. } => {
1184 if bits == 0 {
1185 Truth::False
1186 } else if u32::from(bits) >= u32::from(w.bits()) {
1187 Truth::True
1188 } else {
1189 let hi = known::low_mask(w, u32::from(bits) - 1);
1191 let lo = known::bv_not(&hi);
1192 if sle(&lo, &f.srange.lo()) && sle(&f.srange.hi(), &hi) {
1193 Truth::True
1194 } else if slt(&f.srange.hi(), &lo) || slt(&hi, &f.srange.lo()) {
1195 Truth::False
1196 } else {
1197 Truth::Unknown
1198 }
1199 }
1200 }
1201 };
1202 Ok(proof(truth, rel))
1203 }
1204}