rocq/theories/Interval.v
What ir.pl's offset intervals derive, and that they hold (Campaign 3; docs/rocq.md).
The reuse forms' rules bound the offset of a flight from its base by offset_interval/8 (Validate.v's oi): the interval of values an integer name can hold, walked through the single definitions of the function. This file states the same derivations as an inductive relation, iv, one constructor per clause of op_interval/9, and proves two things:
- whatever
oianswers,ivderives (offset_interval_iv), sooi's memo and depth limit need no further thought; - an
ivinterval holds of the value a run reads, wherever each name the derivation walks holds what its definition computes from its operands' values where it ran, and each single-definition operand still holds that value (iv_sound). Which names do, at a point of a run, is the run-level invariant's to say; here it is any predicate ok closed under single-definition operands.
Decisions
| Decision | Why |
|---|---|
| one constructor per clause, each a little more general | op_interval/9 commits to the first clause whose head matches; the relation needs no order, only that each derivation is sound |
the depth limit and the memo are not in iv | a memo keeps only answers derived earlier, so they need no depth; oi_sound carries the memo's invariant |
mul names its scaled operand, with the two orders as a premise | an iv under a disjunction gets no induction hypothesis |
| an interval holds modulo the class | an l interval is not wrapped (interval_fits/3 accepts any), so it bounds some integer congruent to the value; a w interval fits, so it bounds the signed word itself |
| a narrow load's relation does not mention memory | any loaded value, extended, lies in the narrow range, so the relation survives every store |
| an operand that is not a single definition is read where the definition ran | it may be defined again after; the clauses that walk an operand walk only single definitions, and the others (and's, urem's, a narrow ext's) bound the result whatever the operand holds |
Two classes k and k' that class_eqb finds equal are equal.
Explore proof 2 tactics
Closes the goal of a clause that answered no interval (H says so) and returned the old memo, derived by Hm: there is no interval to derive, and the memo is still derived.
no_answer_now, for a clause that answers none whatever an operand is: it takes the operands apart until each case closes.
The intervals of one function, read over its single definitions.
The function's single definitions, each name with its one definition, as single_definitions builds them.
The name n has a single definition, the let that defines n at the class k by the op o from args: let(tmp(n), k, o, args).
The offset intervals offset_interval/8 derives, as a relation: ivv k lo hi says the operand v read at the class k lies from lo to hi (for l, modulo 2^64). One constructor per clause of op_interval/9, each a little more general than its clause, with the interval_fits test the walk applies to each name.
The empty memo is derived.
Explore proof 2 tactics
Recording the answer r for the name n at the class k keeps a derived memo m derived, when r, if an interval, is derived.
Explore proof 10 tactics
Initial goal
intros n k r m Hm Hr n′ k′ lo hi H
simpl in H
destruct name_eqbn n′ && class_eqbk k′ eqn: E
2 open–apply andb_true_iff in E as E1 E2
2 openapply term_eqb_eq in E1
2 openapply class_eqb_true in E2
2 opensubst n′ k′
2 openinjection H as →
2 openexact Hr_ _ eq_refl
–exact Hm_ _ _ _ H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
What the walk rec of an operand promises op_interval: from a derived memo, an interval it answers is derived, and the memo it returns is derived too.
Each clause of op_interval (op_interval/9) is sound: where the name n is defined by the op o over args and the operand walk rec keeps rec_ok, an interval the clause answers that fits the class is derived for n, and the memo stays derived.
Proof 141 steps Qed
the cases where the op's operands' walks are the answer
add
sub
mul
urem
and
ir.pl tries the right operand's mask first, then the left's.
shl
copy
ext
Whatever its fuel and depth, from a derived memo, an interval the walk oi (offset_interval/8) answers for v at the class k is derived, and the memo it returns is derived. So the memo and the depth limit need no further thought.
Proof 45 steps Qed
An interval offset_interval (offset_interval/6, as the validator calls it) answers for v at the class k is derived: what oi_sound gives from the empty memo. Chain.v reads the validator's intervals back through it.
Explore proof 7 tactics
Initial goal
intros v k lo hi H
unfold offset_interval in H
destruct oionce 33 v k 0 [ ] as r m′ eqn: E
simpl in H
subst r
apply oi_sound_ _ _ _ _ _ _ memo_ok_nil E
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
What an interval means on a run
An interval speaks of the values the names it walks hold. Where each of those names holds what its definition computes from its operands' values, the value an iv derivation reads lies in its interval (iv_sound). Which names hold their definitions at a point of a run is the run-level invariant's to say; here it is a predicate ok closed under operands.
As interp:inst_result/5 of a let: the value of the temporary n in the environment e is what let(tmp(n), k, o, args) computes (interp:alu/4) from its operands' values in e0, the environment it ran in, with ge the global environment. For a narrow load it is some loaded value, extended (interp:extended_res/4).
The ops an interval derivation walks through, one per clause of op_interval/9: those whose results let_holds speaks of.
What an interval means of a value: the operand v, read at the integer class k in the environment e (ge the global environment), is some x from lo to hi, modulo the class's width.
Arithmetic
An interval that fits the class k (interval_fits) is of an integer class: k has a bit width bits, and its modulus is 2^bits, which is positive.
Explore proof 2 tactics
Initial goal
intros k lo hi H
destruct k ; try discriminate H ; eexists ; split ; reflexivity | split ; reflexivity | lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The signed value x of the constant c at a class of width bits (signed_value) is congruent to c modulo 2^bits and lies in the signed range of that width.
Explore proof 15 tactics
Initial goal
intros k c x bits H Hb
unfold signed_value in H
rewrite Hb in H
simpl in H
injection H as ←
assert Hp : 2 ^ bits = 2 × 2 ^ bits − 1 ∧ 0 < 2 ^ bits − 1
2 openfocused goal
{destruct k ; try discriminate Hb ; injection Hb as ← ; simpl ; lia
deferred goal
pose proof Z.mod_pos_boundc 2 ^ bits ltac:lia
destruct 2 ^ bits − 1 ≤? c mod 2 ^ bits eqn: E ; apply Z.leb_le in E | apply Z.leb_gt in E ; split ; try lia
2 openfocused goal
–replace c mod 2 ^ bits − 2 ^ bits with c mod 2 ^ bits + −1 × 2 ^ bits by lia
2 opendeferred goal
rewrite Z.mod_add by lia
2 opendeferred goal
apply Z.mod_mod
2 opendeferred goal
lia
deferred goal
–apply Z.mod_mod
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A constant's signed value fits its class (interval_fits) as an interval of one point.
Explore proof 6 tactics
Initial goal
intros k c x H
destruct k ; try unfold signed_value in H ; discriminate H ; | reflexivity
destruct signed_value_mod_ _ _ _ H eq_refl as _ Hr
simpl
apply andb_true_iff
split ; apply Z.leb_le | apply Z.leb_le ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Every interval derived (iv) fits its class (interval_fits).
Explore proof 3 tactics
Initial goal
intros v k lo hi H
destruct H ; try assumption
exact signed_value_fits_ _ _ H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Sign-extending u from the modulus m = 2h (sign_extension) gives at least -h and less than h.
Explore proof 4 tactics
Initial goal
intros m h u Hh Hm
unfold sign_extension
pose proof Z.mod_pos_boundu m ltac:lia
destruct h ≤? u mod m eqn: E ; apply Z.leb_le in E | apply Z.leb_gt in E ; lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Any x extended from the narrow type t (extension) lies in t's range (narrow_range), so a narrow ext or load is bounded whatever it reads.
Explore proof 10 tactics
Initial goal
intros t lo hi x H
destruct t ; simpl in H ; try discriminate H ; injection H as ← ← ; simpl
4 openfocused goal
–pose proof sign_extension_range65536 32768 x ltac:lia ltac:lia
4 opendeferred goal
lia
3 opendeferred goal
–pose proof Z.mod_pos_boundx 65536 ltac:lia
3 opendeferred goal
lia
2 opendeferred goal
–pose proof sign_extension_range256 128 x ltac:lia ltac:lia
2 openlia
–pose proof Z.mod_pos_boundx 256 ltac:lia
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A sign-extended word is the signed value it holds: a signed 32-bit x, taken modulo 2^32 and sign-extended, is x again.
Explore proof 11 tactics
Initial goal
intros x Hx
unfold sign_extension
rewrite Z.mod_mod by lia
destruct Z_lt_le_decx 0
2 open–replace x mod 2 ^ 32 with x + 2 ^ 32
3 open+rewrite proj2Z.leb_le_ _ by lia
3 openlia
2 open+apply Z.mod_unique with −1 ; lia
–rewrite Z.mod_small by lia
rewrite proj2Z.leb_gt_ _ by lia
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The bitwise and of two nonnegative integers x and y lies from 0 to y: a nonnegative mask bounds an and.
Explore proof 7 tactics
Initial goal
intros x y Hx Hy
split ; apply Z.land_nonneg ; auto |
apply Z.ldiff_le_ _ Hy
apply Z.bits_inj'
intros i Hi
rewrite Z.ldiff_spec , Z.land_spec , Z.bits_0
destruct Z.testbitx i , Z.testbity i ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A temporary n holding the integer w, read at an integer class of width bits, reads as w modulo 2^bits.
Explore proof 4 tactics
Initial goal
intros ge e k n w bits Hb H
simpl
rewrite H
destruct k ; try discriminate Hb ; injection Hb as ← ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Any operand that reads as an integer u at an integer class of width bits has u at least 0 and below 2^bits.
Explore proof 5 tactics
Initial goal
intros ge e k v u bits Hb H
destruct k ; try discriminate Hb ; injection Hb as ← ; destruct v as n | c | g ; simpl in H
6 openfocused goal
focused goal
focused goal
focused goal
all: try destruct lookupn e as w | | | ; simpl in H ; try discriminate H ; injection H as ← ; apply Z.mod_pos_bound ; lia
4 openfocused goal
focused goal
all: try injection H as ← ; apply Z.mod_pos_bound ; lia
2 openall: destruct lookupg ge_globalsge ; discriminate H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A temporary n holding w lies in the interval from lo to hi (in_iv) when some x in it is congruent to w modulo the class's width.
Explore proof 4 tactics
Initial goal
intros ge e k n w bits x lo hi Hb H Hw Hx
exists bits, w mod 2 ^ bits, x
rewrite read_tmp_ _ _ _ _ _ Hb H
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A constant c read at an integer class of width bits reads as c modulo 2^bits.
Explore proof 2 tactics
Initial goal
intros ge e k c bits Hb
destruct k ; try discriminate Hb ; injection Hb as ← ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
map2_option over two two-element lists succeeds only when f succeeds on each pair, and gives the two results.
Explore proof 6 tactics
Initial goal
intros X Y W f k1 k2 a b xs H
simpl in H
destruct fk1 a as x | ; | discriminate H
destruct fk2 b as y | ; | discriminate H
injection H as ←
eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The theorem
Soundness in one environment of a run: the names that hold their definitions there are a predicate ok, which the run-level invariant supplies (Chain.v's interval_at takes the names whose definitions dominate the point).
The global environment ge, the environment e the interval is read in, and ok, the names that hold their definitions there.
What ok must promise, the hypothesis of iv_sound: each name n that is ok and whose definition (defined) is one a derivation walks (iv_op), at an integer class, holds what that definition computed in some environment e0 (let_holds); each of its single-definition operands is ok and holds in e0 what it holds in e.
Explore proof 2 tactics
Initial goal
intros v k lo hi H n E
destruct H ; try discriminate E ; injection E as →;match goal withHd : defined_ _ _ _ |- _⇒destruct Hd as n′ & Hl & _end;unfold once_has;rewrite Hl;reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
An operand a of a definition that ran in e0, where a has a derived interval and the definition's single-definition operands are ok and unchanged since (Hok's conclusion): a, if a temporary, is ok, and a reads the same in e0 as in e, at any class.
Explore proof 5 tactics
Initial goal
intros e0 args a k′ lo hi Ha Hin Hiv
assert Hag : ∀n, a = Tmpn → okn ∧ lookupn e0 = lookupn e by intros n E ; subst a ; exact Ha_ Hin iv_once_ _ _ _ Hiv _ eq_refl
split ; intros n E ; exact proj1Hag_ E |
intros k′′
destruct a as n | c | g ; simpl ; rewrite proj2Hag_ eq_refl | | ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Takes apart every match in the statement of H, discarding the cases that make H contradictory.
Offset intervals are sound: if ivv k lo hi is derived and v, if a temporary, is ok, then the value v reads in e at the class k lies from lo to hi, modulo the class (in_iv). With offset_interval_iv, an interval the validator answers bounds the offset a run computes.
Proof 244 steps Qed
a constant
ext to a narrow type
ext(sw)
ext(uw)
a narrow load
copy
and with a mask
urem by a constant
shl by a constant
mul by a constant
add
sub a constant