(** The default abstraction: if the result is unused, the arguments are unused; otherwise, the arguments are needed in full. *)
Definition default (x: nval) :=
match x with
| Nothing => Nothing
| _ => All
end.
Section DEFAULT.
Variable ge: genv.
Variable sp: block.
Variables m1 m2: mem.
Hypothesis PERM: forall b ofs k p, Mem.perm m1 b ofs k p -> Mem.perm m2 b ofs k p.
Let valid_pointer_inj:
forall b1 ofs b2 delta,
inject_id b1 = Some(b2, delta) ->
Mem.valid_pointer m1 b1 (Ptrofs.unsigned ofs) = true ->
Mem.valid_pointer m2 b2 (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr delta))) = true.
Let weak_valid_pointer_inj:
forall b1 ofs b2 delta,
inject_id b1 = Some(b2, delta) ->
Mem.weak_valid_pointer m1 b1 (Ptrofs.unsigned ofs) = true ->
Mem.weak_valid_pointer m2 b2 (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr delta))) = true.
Let weak_valid_pointer_no_overflow:
forall b1 ofs b2 delta,
inject_id b1 = Some(b2, delta) ->
Mem.weak_valid_pointer m1 b1 (Ptrofs.unsigned ofs) = true ->
0 <= Ptrofs.unsigned ofs + Ptrofs.unsigned (Ptrofs.repr delta) <= Ptrofs.max_unsigned.
Let valid_different_pointers_inj:
forall b1 ofs1 b2 ofs2 b1' delta1 b2' delta2,
b1 <> b2 ->
Mem.valid_pointer m1 b1 (Ptrofs.unsigned ofs1) = true ->
Mem.valid_pointer m1 b2 (Ptrofs.unsigned ofs2) = true ->
inject_id b1 = Some (b1', delta1) ->
inject_id b2 = Some (b2', delta2) ->
b1' <> b2' \/
Ptrofs.unsigned (Ptrofs.add ofs1 (Ptrofs.repr delta1)) <> Ptrofs.unsigned (Ptrofs.add ofs2 (Ptrofs.repr delta2)).

Lemma default_needs_of_operation_sound:
forall op args1 v1 args2 nv,
eval_operation ge (Vptr sp Ptrofs.zero) op args1 m1 = Some v1 ->
vagree_list args1 args2 nil
\/ vagree_list args1 args2 (default nv :: nil)
\/ vagree_list args1 args2 (default nv :: default nv :: nil) ->
nv <> Nothing ->
exists v2,
eval_operation ge (Vptr sp Ptrofs.zero) op args2 m2 = Some v2
/\ vagree v1 v2 nv.