Section EVAL_COMPAT.
Variable F1 F2 V1 V2: Type.
Variable ge1: Genv.t F1 V1.
Variable ge2: Genv.t F2 V2.
Variable f: meminj.
Variable m1: mem.
Variable m2: mem.
Hypothesis valid_pointer_inj:
forall b1 ofs b2 delta,
f 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.
Hypothesis weak_valid_pointer_inj:
forall b1 ofs b2 delta,
f 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.
Hypothesis weak_valid_pointer_no_overflow:
forall b1 ofs b2 delta,
f 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.
Hypothesis 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 ->
f b1 = Some (b1', delta1) ->
f b2 = Some (b2', delta2) ->
b1' <> b2' \/
Ptrofs.unsigned (Ptrofs.add ofs1 (Ptrofs.repr delta1)) <> Ptrofs.unsigned (Ptrofs.add ofs2 (Ptrofs.repr delta2)).
Ltac InvInject :=
match goal with
| [ H: Val.inject _ (Vint _) _ |- _ ] =>
inv H; InvInject
| [ H: Val.inject _ (Vfloat _) _ |- _ ] =>
inv H; InvInject
| [ H: Val.inject _ (Vsingle _) _ |- _ ] =>
inv H; InvInject
| [ H: Val.inject _ (Vptr _ _) _ |- _ ] =>
inv H; InvInject
| [ H: Val.inject_list _ nil _ |- _ ] =>
inv H; InvInject
| [ H: Val.inject_list _ (_ :: _) _ |- _ ] =>
inv H; InvInject
| _ => idtac
end.
Remark eval_shift_inj:
forall s v v', Val.inject f v v' -> Val.inject f (eval_shift s v) (eval_shift s v').
Ltac TrivialExists :=
match goal with
| [ |- exists v2, Some ?v1 = Some v2 /\ Val.inject _ _ v2 ] =>
exists v1; split; auto
| _ => idtac
end.

Lemma eval_operation_inj:
forall op sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_operation op) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_operation ge1 sp1 op vl1 m1 = Some v1 ->
exists v2, eval_operation ge2 sp2 op vl2 m2 = Some v2 /\ Val.inject f v1 v2.