Inductive Sfor_inv {cs: compspecs} (Delta: tycontext):
forall (_i: ident) (m: Z) (hi: expr) (n: Z)
(assert_callee: Z -> environ -> mpred)
(inv0: environ -> mpred)
(inv1 inv2: Z -> environ -> mpred), Prop :=
| construct_Sfor_inv: forall _i m hi n assert_callee inv0 inv1,
(forall i i', exists inv0' inv0'' inv1' inv1'', Sfor_inv_rec Delta _i i' m hi n (assert_callee i) inv0'' inv1'' /\ inv0' i' = inv0'' /\ inv0 i = inv0' /\ inv1' i' = inv1'' /\ inv1 i = inv1') ->
Sfor_inv Delta _i m hi n assert_callee (EX i: Z, inv0 i i) (fun i => inv1 i i) (fun i => inv1 (i+1) i).
(* need to export range_hi? no *)
Inductive Sfor_setup {cs: compspecs} {Espec: OracleKind} (Delta: tycontext):
forall (_i: ident) (Pre: environ -> mpred) (init: statement) (hi: expr) (type_i: type)
(m n: Z) (assert_callee: Z -> environ -> mpred)
(inv0: environ -> mpred), Prop :=
| Sfor_setup_const_init: forall m' m lo _i type_i hi n Pre assert_callee inv0 range,
range_init_hl (typeof lo) type_i (typeof hi) range ->
const_only_eval_expr lo = Some (Vint m') ->
Int_eqm_unsigned m' m ->
range m n ->
ENTAIL Delta, Pre |-- assert_callee m ->
Sfor_setup Delta _i Pre (Sset _i lo) hi type_i m n assert_callee inv0
| Sfor_setup_other: forall _i Pre init hi type_i m n assert_callee inv0 range,
range_init_h type_i (typeof hi) m range ->
range n ->
@semax cs Espec Delta Pre init (normal_ret_assert inv0) ->
Sfor_setup Delta _i Pre init hi type_i m n assert_callee inv0.

Lemma Sfor_setup_spec: forall {cs: compspecs} {Espec: OracleKind} (Delta: tycontext),
forall _i Pre init type_i hi m n assert_callee inv0 inv1,
Sfor_setup Delta _i Pre init hi type_i m n assert_callee inv0 ->
forall
(TI: (temp_types Delta) ! _i = Some type_i),
(forall i, local (locald_denote (temp _i (Vint (Int.repr i)))) && assert_callee i = inv1 i) ->
(EX i: Z, !! (m <= i <= n) && inv1 i = inv0) ->
(forall v i, subst _i (`v) (assert_callee i) = assert_callee i) ->
@semax cs Espec Delta Pre init (normal_ret_assert inv0) /\
exists int_min int_max,
int_type_min_max type_i (typeof hi) = Some (int_min, int_max) /\
is_int32_type type_i = true /\
int_min <= m <= int_max /\
int_min <= n <= int_max.