Section PRESERVATION.
Variable prog: program.
Hypothesis WTPROG: wt_program prog.
Let ge := globalenv prog.
Let gtenv := bind_globdef (PTree.empty _) prog.(prog_defs).
Inductive wt_expr_cont: typenv -> function -> cont -> Prop :=
| wt_Kdo: forall te f k,
wt_stmt_cont te f k ->
wt_expr_cont te f (Kdo k)
| wt_Kifthenelse: forall te f s1 s2 k,
wt_stmt_cont te f k ->
wt_stmt ge te f.(fn_return) s1 -> wt_stmt ge te f.(fn_return) s2 ->
wt_expr_cont te f (Kifthenelse s1 s2 k)
| wt_Kwhile1: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_expr_cont te f (Kwhile1 r s k)
| wt_Kdowhile2: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_expr_cont te f (Kdowhile2 r s k)
| wt_Kfor2: forall te f r s2 s3 k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s2 -> wt_stmt ge te f.(fn_return) s3 ->
classify_bool (typeof r) <> bool_default ->
wt_expr_cont te f (Kfor2 r s2 s3 k)
| wt_Kswitch1: forall te f ls k,
wt_stmt_cont te f k ->
wt_lblstmts ge te f.(fn_return) ls ->
wt_expr_cont te f (Kswitch1 ls k)
| wt_Kreturn: forall te f k,
wt_stmt_cont te f k ->
wt_expr_cont te f (Kreturn k)
with wt_stmt_cont: typenv -> function -> cont -> Prop :=
| wt_Kseq: forall te f s k,
wt_stmt_cont te f k ->
wt_stmt ge te f.(fn_return) s ->
wt_stmt_cont te f (Kseq s k)
| wt_Kwhile2: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_stmt_cont te f (Kwhile2 r s k)
| wt_Kdowhile1: forall te f r s k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s -> wt_bool (typeof r) ->
wt_stmt_cont te f (Kdowhile1 r s k)
| wt_Kfor3: forall te f r s2 s3 k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s2 -> wt_stmt ge te f.(fn_return) s3 ->
wt_bool (typeof r) ->
wt_stmt_cont te f (Kfor3 r s2 s3 k)
| wt_Kfor4: forall te f r s2 s3 k,
wt_stmt_cont te f k ->
wt_rvalue ge te r -> wt_stmt ge te f.(fn_return) s2 -> wt_stmt ge te f.(fn_return) s3 ->
wt_bool (typeof r) ->
wt_stmt_cont te f (Kfor4 r s2 s3 k)
| wt_Kswitch2: forall te f k,
wt_stmt_cont te f k ->
wt_stmt_cont te f (Kswitch2 k)
| wt_Kstop': forall te f,
wt_stmt_cont te f Kstop
| wt_Kcall': forall te f f' e C ty k,
wt_call_cont (Kcall f' e C ty k) ty ->
ty = f.(fn_return) ->
wt_stmt_cont te f (Kcall f' e C ty k)
with wt_call_cont: cont -> type -> Prop :=
| wt_Kstop: forall ty,
wt_call_cont Kstop ty
| wt_Kcall: forall te f e C ty k,
wt_expr_cont te f k ->
wt_stmt ge te f.(fn_return) f.(fn_body) ->
(forall v, wt_val v ty -> wt_rvalue ge te (C (Eval v ty))) ->
wt_call_cont (Kcall f e C ty k) ty.
Definition fundef_return (fd: fundef) : type :=
match fd with
| Internal f => f.(fn_return)
| External ef targs tres cc => tres
end.

Lemma wt_find_funct:
forall v fd, Genv.find_funct ge v = Some fd -> wt_fundef ge gtenv fd.