From c48b9097201dc9a1e326acdbce491fe16cab01e6 Mon Sep 17 00:00:00 2001
From: xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>
Date: Tue, 28 Aug 2007 12:57:58 +0000
Subject: [PATCH] Fusion de la branche restr-cminor.  En Clight, C#minor et
 Cminor, les expressions sont maintenant pures et les appels de fonctions sont
 des statements.  Ajout de semantiques coinductives pour la divergence en
 Clight, C#minor, Cminor.  Preuve de preservation semantique pour les
 programmes qui divergent.

git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@409 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
---
 .depend                    |   14 +-
 backend/Cminor.v           |  359 +++++-----
 backend/CminorSel.v        |  329 +++++----
 backend/RTLgen.v           |   54 +-
 backend/RTLgenproof.v      | 1024 ++++++++++++++++-----------
 backend/RTLgenspec.v       |  250 ++++---
 backend/Selection.v        |   25 +-
 backend/Selectionproof.v   | 1105 ++++++++++++++---------------
 caml/CMlexer.mll           |    1 +
 caml/CMparser.mly          |  279 +++++---
 caml/CMtypecheck.ml        |   76 +-
 caml/Cil2Csyntax.ml        |   88 ++-
 caml/PrintCsyntax.ml       |   43 +-
 cfrontend/Cminorgen.v      |   77 +-
 cfrontend/Cminorgenproof.v | 1293 ++++++++++++++++------------------
 cfrontend/Csem.v           |  477 ++++++++-----
 cfrontend/Csharpminor.v    |  415 ++++++-----
 cfrontend/Cshmgen.v        |   89 ++-
 cfrontend/Cshmgenproof1.v  |   63 +-
 cfrontend/Cshmgenproof2.v  |  182 +++--
 cfrontend/Cshmgenproof3.v  | 1357 ++++++++++++++++++++++--------------
 cfrontend/Csyntax.v        |    9 +-
 cfrontend/Ctyping.v        |   96 ++-
 common/Complements.v       |   73 +-
 common/Events.v            |   10 +-
 common/Main.v              |   14 +-
 common/Smallstep.v         |   31 +-
 doc/index.html             |    3 +-
 doc/removeproofs           |    4 +-
 extraction/.depend         |  244 ++++---
 extraction/Makefile        |    4 +-
 test/c/Results/lists       |    1 +
 test/cminor/sha1.cmp       |    6 +-
 33 files changed, 4572 insertions(+), 3523 deletions(-)

diff --git a/.depend b/.depend
index fb4ecb531..3a2036e6f 100644
--- a/.depend
+++ b/.depend
@@ -15,10 +15,10 @@ common/Values.vo: common/Values.v lib/Coqlib.vo common/AST.vo lib/Integers.vo li
 common/Smallstep.vo: common/Smallstep.v lib/Coqlib.vo common/AST.vo common/Events.vo common/Globalenvs.vo lib/Integers.vo
 common/Switch.vo: common/Switch.v lib/Coqlib.vo lib/Integers.vo
 common/Main.vo: common/Main.v lib/Coqlib.vo lib/Maps.vo common/Errors.vo common/AST.vo common/Values.vo common/Smallstep.vo cfrontend/Csyntax.vo cfrontend/Csem.vo cfrontend/Csharpminor.vo backend/Cminor.vo backend/CminorSel.vo backend/RTL.vo backend/LTL.vo backend/LTLin.vo backend/Linear.vo backend/Mach.vo backend/PPC.vo cfrontend/Cshmgen.vo cfrontend/Cminorgen.vo backend/Selection.vo backend/RTLgen.vo backend/Constprop.vo backend/CSE.vo backend/Allocation.vo backend/Tunneling.vo backend/Linearize.vo backend/Reload.vo backend/Stacking.vo backend/PPCgen.vo cfrontend/Ctyping.vo backend/RTLtyping.vo backend/LTLtyping.vo backend/LTLintyping.vo backend/Lineartyping.vo backend/Machtyping.vo cfrontend/Cshmgenproof3.vo cfrontend/Cminorgenproof.vo backend/Selectionproof.vo backend/RTLgenproof.vo backend/Constpropproof.vo backend/CSEproof.vo backend/Allocproof.vo backend/Alloctyping.vo backend/Tunnelingproof.vo backend/Tunnelingtyping.vo backend/Linearizeproof.vo backend/Linearizetyping.vo backend/Reloadproof.vo backend/Reloadtyping.vo backend/Stackingproof.vo backend/Stackingtyping.vo backend/Machabstr2concr.vo backend/PPCgenproof.vo
-common/Complements.vo: common/Complements.v lib/Coqlib.vo common/AST.vo lib/Integers.vo common/Values.vo common/Events.vo common/Globalenvs.vo common/Smallstep.vo backend/PPC.vo common/Main.vo common/Errors.vo
-backend/Cminor.vo: backend/Cminor.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Events.vo common/Values.vo common/Mem.vo common/Globalenvs.vo common/Switch.vo
+common/Complements.vo: common/Complements.v lib/Coqlib.vo common/AST.vo lib/Integers.vo common/Values.vo common/Events.vo common/Globalenvs.vo common/Smallstep.vo cfrontend/Csyntax.vo cfrontend/Csem.vo backend/PPC.vo common/Main.vo common/Errors.vo
+backend/Cminor.vo: backend/Cminor.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Events.vo common/Values.vo common/Mem.vo common/Globalenvs.vo common/Smallstep.vo common/Switch.vo
 backend/Op.vo: backend/Op.v lib/Coqlib.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Globalenvs.vo
-backend/CminorSel.vo: backend/CminorSel.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Events.vo common/Values.vo common/Mem.vo backend/Cminor.vo backend/Op.vo common/Globalenvs.vo common/Switch.vo
+backend/CminorSel.vo: backend/CminorSel.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Events.vo common/Values.vo common/Mem.vo backend/Cminor.vo backend/Op.vo common/Globalenvs.vo common/Switch.vo common/Smallstep.vo
 backend/Selection.vo: backend/Selection.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Globalenvs.vo backend/Cminor.vo backend/Op.vo backend/CminorSel.vo
 backend/Selectionproof.vo: backend/Selectionproof.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Events.vo common/Globalenvs.vo backend/Cminor.vo backend/Op.vo backend/CminorSel.vo backend/Selection.vo
 backend/Registers.vo: backend/Registers.v lib/Coqlib.vo common/AST.vo lib/Maps.vo lib/Ordered.vo
@@ -71,12 +71,12 @@ backend/PPCgenretaddr.vo: backend/PPCgenretaddr.v lib/Coqlib.vo lib/Maps.vo comm
 backend/PPCgenproof1.vo: backend/PPCgenproof1.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Globalenvs.vo backend/Op.vo backend/Locations.vo backend/Mach.vo backend/Machconcr.vo backend/Machtyping.vo backend/PPC.vo backend/PPCgen.vo backend/Conventions.vo
 backend/PPCgenproof.vo: backend/PPCgenproof.v lib/Coqlib.vo lib/Maps.vo common/Errors.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Events.vo common/Globalenvs.vo common/Smallstep.vo backend/Op.vo backend/Locations.vo backend/Mach.vo backend/Machconcr.vo backend/Machtyping.vo backend/PPC.vo backend/PPCgen.vo backend/PPCgenretaddr.vo backend/PPCgenproof1.vo
 cfrontend/Csyntax.vo: cfrontend/Csyntax.v lib/Coqlib.vo common/Errors.vo lib/Integers.vo lib/Floats.vo common/AST.vo
-cfrontend/Csem.vo: cfrontend/Csem.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/AST.vo common/Mem.vo common/Events.vo common/Globalenvs.vo cfrontend/Csyntax.vo
+cfrontend/Csem.vo: cfrontend/Csem.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/AST.vo common/Mem.vo common/Events.vo common/Globalenvs.vo cfrontend/Csyntax.vo common/Smallstep.vo
 cfrontend/Ctyping.vo: cfrontend/Ctyping.v lib/Coqlib.vo lib/Maps.vo common/AST.vo cfrontend/Csyntax.vo
 cfrontend/Cshmgen.vo: cfrontend/Cshmgen.v lib/Coqlib.vo common/Errors.vo lib/Integers.vo lib/Floats.vo common/AST.vo cfrontend/Csyntax.vo backend/Cminor.vo cfrontend/Csharpminor.vo
 cfrontend/Cshmgenproof1.vo: cfrontend/Cshmgenproof1.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Integers.vo lib/Floats.vo common/AST.vo common/Values.vo common/Events.vo common/Mem.vo common/Globalenvs.vo cfrontend/Csyntax.vo cfrontend/Csem.vo cfrontend/Ctyping.vo backend/Cminor.vo cfrontend/Csharpminor.vo cfrontend/Cshmgen.vo
 cfrontend/Cshmgenproof2.vo: cfrontend/Cshmgenproof2.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Integers.vo lib/Floats.vo common/AST.vo common/Values.vo common/Events.vo common/Mem.vo common/Globalenvs.vo cfrontend/Csyntax.vo cfrontend/Csem.vo cfrontend/Ctyping.vo backend/Cminor.vo cfrontend/Csharpminor.vo cfrontend/Cshmgen.vo cfrontend/Cshmgenproof1.vo
-cfrontend/Cshmgenproof3.vo: cfrontend/Cshmgenproof3.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Integers.vo lib/Floats.vo common/AST.vo common/Values.vo common/Events.vo common/Mem.vo common/Globalenvs.vo cfrontend/Csyntax.vo cfrontend/Csem.vo cfrontend/Ctyping.vo backend/Cminor.vo cfrontend/Csharpminor.vo cfrontend/Cshmgen.vo cfrontend/Cshmgenproof1.vo cfrontend/Cshmgenproof2.vo
-cfrontend/Csharpminor.vo: cfrontend/Csharpminor.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Events.vo common/Globalenvs.vo backend/Cminor.vo
+cfrontend/Cshmgenproof3.vo: cfrontend/Cshmgenproof3.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Integers.vo lib/Floats.vo common/AST.vo common/Values.vo common/Events.vo common/Mem.vo common/Globalenvs.vo common/Smallstep.vo cfrontend/Csyntax.vo cfrontend/Csem.vo cfrontend/Ctyping.vo backend/Cminor.vo cfrontend/Csharpminor.vo cfrontend/Cshmgen.vo cfrontend/Cshmgenproof1.vo cfrontend/Cshmgenproof2.vo
+cfrontend/Csharpminor.vo: cfrontend/Csharpminor.v lib/Coqlib.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Events.vo common/Globalenvs.vo backend/Cminor.vo common/Smallstep.vo
 cfrontend/Cminorgen.vo: cfrontend/Cminorgen.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo lib/Ordered.vo common/AST.vo lib/Integers.vo common/Mem.vo cfrontend/Csharpminor.vo backend/Op.vo backend/Cminor.vo
-cfrontend/Cminorgenproof.vo: cfrontend/Cminorgenproof.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Events.vo common/Globalenvs.vo cfrontend/Csharpminor.vo backend/Cminor.vo cfrontend/Cminorgen.vo
+cfrontend/Cminorgenproof.vo: cfrontend/Cminorgenproof.v lib/Coqlib.vo common/Errors.vo lib/Maps.vo common/AST.vo lib/Integers.vo lib/Floats.vo common/Values.vo common/Mem.vo common/Events.vo common/Globalenvs.vo cfrontend/Csharpminor.vo backend/Op.vo backend/Cminor.vo cfrontend/Cminorgen.vo
diff --git a/backend/Cminor.v b/backend/Cminor.v
index 2b9945ac7..1d2eea74d 100644
--- a/backend/Cminor.v
+++ b/backend/Cminor.v
@@ -9,6 +9,7 @@ Require Import Events.
 Require Import Values.
 Require Import Mem.
 Require Import Globalenvs.
+Require Import Smallstep.
 Require Import Switch.
 
 (** * Abstract syntax *)
@@ -61,12 +62,8 @@ Inductive binary_operation : Set :=
   | Ocmpf: comparison -> binary_operation. (**r float comparison *)
 
 (** Expressions include reading local variables, constants and
-  arithmetic operations, reading and writing store locations,
-  function calls, and conditional expressions
-  (similar to [e1 ? e2 : e3] in C).
-  The [Elet] and [Eletvar] constructs enable sharing the computations
-  of subexpressions.  De Bruijn notation is used: [Eletvar n] refers
-  to the value bound by then [n+1]-th enclosing [Elet] construct. *)
+  arithmetic operations, reading store locations, and conditional
+  expressions (similar to [e1 ? e2 : e3] in C). *)
 
 Inductive expr : Set :=
   | Evar : ident -> expr
@@ -74,26 +71,20 @@ Inductive expr : Set :=
   | Eunop : unary_operation -> expr -> expr
   | Ebinop : binary_operation -> expr -> expr -> expr
   | Eload : memory_chunk -> expr -> expr
-  | Estore : memory_chunk -> expr -> expr -> expr
-  | Ecall : signature -> expr -> exprlist -> expr
-  | Econdition : expr -> expr -> expr -> expr
-  | Elet : expr -> expr -> expr
-  | Eletvar : nat -> expr
-  | Ealloc : expr -> expr
-
-with exprlist : Set :=
-  | Enil: exprlist
-  | Econs: expr -> exprlist -> exprlist.
+  | Econdition : expr -> expr -> expr -> expr.
 
 (** Statements include expression evaluation, assignment to local variables,
-  an if/then/else conditional, infinite loops, blocks and early block
-  exits, and early function returns.  [Sexit n] terminates prematurely
-  the execution of the [n+1] enclosing [Sblock] statements. *)
+  memory stores, function calls, an if/then/else conditional, infinite
+  loops, blocks and early block exits, and early function returns.
+  [Sexit n] terminates prematurely the execution of the [n+1]
+  enclosing [Sblock] statements. *)
 
 Inductive stmt : Set :=
   | Sskip: stmt
-  | Sexpr: expr -> stmt
   | Sassign : ident -> expr -> stmt
+  | Sstore : memory_chunk -> expr -> expr -> stmt
+  | Scall : option ident -> signature -> expr -> list expr -> stmt
+  | Salloc : ident -> expr -> stmt
   | Sseq: stmt -> stmt -> stmt
   | Sifthenelse: expr -> stmt -> stmt -> stmt
   | Sloop: stmt -> stmt
@@ -101,7 +92,7 @@ Inductive stmt : Set :=
   | Sexit: nat -> stmt
   | Sswitch: expr -> list (int * nat) -> nat -> stmt
   | Sreturn: option expr -> stmt
-  | Stailcall: signature -> expr -> exprlist -> stmt.
+  | Stailcall: signature -> expr -> list expr -> stmt.
 
 (** Functions are composed of a signature, a list of parameter names,
   a list of local variables, and a  statement representing
@@ -163,15 +154,13 @@ Definition outcome_free_mem
   | _ => Mem.free m sp
   end.
 
-(** Three kinds of evaluation environments are involved:
+(** Two kinds of evaluation environments are involved:
 - [genv]: global environments, define symbols and functions;
-- [env]: local environments, map local variables to values;
-- [lenv]: let environments, map de Bruijn indices to values.
+- [env]: local environments, map local variables to values.
 *)
 
 Definition genv := Genv.t fundef.
 Definition env := PTree.t val.
-Definition letenv := list val.
 
 (** The following functions build the initial local environment at
   function entry, binding parameters to the provided arguments and
@@ -190,6 +179,12 @@ Fixpoint set_locals (il: list ident) (e: env) {struct il} : env :=
   | i1 :: is => PTree.set i1 Vundef (set_locals is e)
   end.
 
+Definition set_optvar (optid: option ident) (v: val) (e: env) : env :=
+  match optid with
+  | None => e
+  | Some id => PTree.set id v e
+  end.
+
 Section RELSEM.
 
 Variable ge: genv.
@@ -288,112 +283,62 @@ Definition eval_binop
   | _, _, _ => None
   end.
 
-(** Evaluation of an expression: [eval_expr ge sp le e m a t m' v]
-  states that expression [a], in initial local environment [e] and
-  memory state [m], evaluates to value [v].  [m'] is the final
-  memory state, reflecting memory stores possibly performed by [a].
-  [t] is the trace of I/O events generated during the evaluation.
-  Expressions do not assign variables, therefore the local environment
-  [e] is unchanged.  [ge] and [le] are the global environment and let
-  environment respectively, and are unchanged during evaluation.  [sp]
-  is the pointer to the memory block allocated for this function
+(** Evaluation of an expression: [eval_expr ge sp e m a v]
+  states that expression [a] evaluates to value [v].
+  [ge] is the global environment, [e] the local environment,
+  and [m] the current memory state.  They are unchanged during evaluation.
+  [sp] is the pointer to the memory block allocated for this function
   (stack frame).
 *)
 
-Inductive eval_expr:
-         val -> letenv -> env ->
-         mem -> expr -> trace -> mem -> val -> Prop :=
-  | eval_Evar:
-      forall sp le e m id v,
+Section EVAL_EXPR.
+
+Variable sp: val.
+Variable e: env.
+Variable m: mem.
+
+Inductive eval_expr: expr -> val -> Prop :=
+  | eval_Evar: forall id v,
       PTree.get id e = Some v ->
-      eval_expr sp le e m (Evar id) E0 m v
-  | eval_Econst:
-      forall sp le e m cst v,
+      eval_expr (Evar id) v
+  | eval_Econst: forall cst v,
       eval_constant sp cst = Some v ->
-      eval_expr sp le e m (Econst cst) E0 m v
-  | eval_Eunop:
-      forall sp le e m op a t m1 v1 v,
-      eval_expr sp le e m a t m1 v1 ->
+      eval_expr (Econst cst) v
+  | eval_Eunop: forall op a1 v1 v,
+      eval_expr a1 v1 ->
       eval_unop op v1 = Some v ->
-      eval_expr sp le e m (Eunop op a) t m1 v
-  | eval_Ebinop:
-      forall sp le e m op a1 a2 t1 m1 v1 t2 m2 v2 t v,
-      eval_expr sp le e m a1 t1 m1 v1 ->
-      eval_expr sp le e m1 a2 t2 m2 v2 ->
-      eval_binop op v1 v2 m2 = Some v ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Ebinop op a1 a2) t m2 v
-  | eval_Eload:
-      forall sp le e m chunk a t m1 v1 v,
-      eval_expr sp le e m a t m1 v1 ->
-      Mem.loadv chunk m1 v1 = Some v ->
-      eval_expr sp le e m (Eload chunk a) t m1 v
-  | eval_Estore:
-      forall sp le e m chunk a1 a2 t t1 m1 v1 t2 m2 v2 m3,
-      eval_expr sp le e m a1 t1 m1 v1 ->
-      eval_expr sp le e m1 a2 t2 m2 v2 ->
-      Mem.storev chunk m2 v1 v2 = Some m3 ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Estore chunk a1 a2) t m3 v2
-  | eval_Ecall:
-      forall sp le e m sig a bl t t1 m1 t2 m2 t3 m3 vf vargs vres f,
-      eval_expr sp le e m a t1 m1 vf ->
-      eval_exprlist sp le e m1 bl t2 m2 vargs ->
-      Genv.find_funct ge vf = Some f ->
-      funsig f = sig ->
-      eval_funcall m2 f vargs t3 m3 vres ->
-      t = t1 ** t2 ** t3 ->
-      eval_expr sp le e m (Ecall sig a bl) t m3 vres
-  | eval_Econdition:
-      forall sp le e m a1 a2 a3 t t1 m1 v1 b1 t2 m2 v2,
-      eval_expr sp le e m a1 t1 m1 v1 ->
+      eval_expr (Eunop op a1) v
+  | eval_Ebinop: forall op a1 a2 v1 v2 v,
+      eval_expr a1 v1 ->
+      eval_expr a2 v2 ->
+      eval_binop op v1 v2 m = Some v ->
+      eval_expr (Ebinop op a1 a2) v
+  | eval_Eload: forall chunk addr vaddr v,
+      eval_expr addr vaddr ->
+      Mem.loadv chunk m vaddr = Some v ->     
+      eval_expr (Eload chunk addr) v
+  | eval_Econdition: forall a1 a2 a3 v1 b1 v2,
+      eval_expr a1 v1 ->
       Val.bool_of_val v1 b1 ->
-      eval_expr sp le e m1 (if b1 then a2 else a3) t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Econdition a1 a2 a3) t m2 v2
-  | eval_Elet:
-      forall sp le e m a b t t1 m1 v1 t2 m2 v2,
-      eval_expr sp le e m a t1 m1 v1 ->
-      eval_expr sp (v1::le) e m1 b t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Elet a b) t m2 v2
-  | eval_Eletvar:
-      forall sp le e m n v,
-      nth_error le n = Some v ->
-      eval_expr sp le e m (Eletvar n) E0 m v
-  | eval_Ealloc:
-      forall sp le e m a t m1 n m2 b,
-      eval_expr sp le e m a t m1 (Vint n) ->
-      Mem.alloc m1 0 (Int.signed n) = (m2, b) ->
-      eval_expr sp le e m (Ealloc a) t m2 (Vptr b Int.zero)
-
-(** Evaluation of a list of expressions:
-  [eval_exprlist ge sp le al m a m' vl]
-  states that the list [al] of expressions evaluate 
-  to the list [vl] of values.
-  The other parameters are as in [eval_expr].
-*)
+      eval_expr (if b1 then a2 else a3) v2 ->
+      eval_expr (Econdition a1 a2 a3) v2.
 
-with eval_exprlist:
-         val -> letenv -> env ->
-         mem -> exprlist -> trace -> mem -> list val -> Prop :=
+Inductive eval_exprlist: list expr -> list val -> Prop :=
   | eval_Enil:
-      forall sp le e m,
-      eval_exprlist sp le e m Enil E0 m nil
-  | eval_Econs:
-      forall sp le e m a bl t t1 m1 v t2 m2 vl,
-      eval_expr sp le e m a t1 m1 v ->
-      eval_exprlist sp le e m1 bl t2 m2 vl ->
-      t = t1 ** t2 ->
-      eval_exprlist sp le e m (Econs a bl) t m2 (v :: vl)
+      eval_exprlist nil nil
+  | eval_Econs: forall a1 al v1 vl,
+      eval_expr a1 v1 -> eval_exprlist al vl ->
+      eval_exprlist (a1 :: al) (v1 :: vl).
+
+End EVAL_EXPR.
 
-(** Evaluation of a function invocation: [eval_funcall ge m f args m' res]
+(** Evaluation of a function invocation: [eval_funcall ge m f args t m' res]
   means that the function [f], applied to the arguments [args] in
   memory state [m], returns the value [res] in modified memory state [m'].
   [t] is the trace of observable events generated during the invocation.
 *)
 
-with eval_funcall:
+Inductive eval_funcall:
         mem -> fundef -> list val -> trace ->
         mem -> val -> Prop :=
   | eval_funcall_internal:
@@ -408,12 +353,13 @@ with eval_funcall:
       event_match ef args t res ->
       eval_funcall m (External ef) args t m res
 
-(** Execution of a statement: [exec_stmt ge sp e m s e' m' out]
+(** Execution of a statement: [exec_stmt ge sp e m s t e' m' out]
   means that statement [s] executes with outcome [out].
   [e] is the initial environment and [m] is the initial memory state.
   [e'] is the final environment, reflecting variable assignments performed
   by [s].  [m'] is the final memory state, reflecting memory stores
-  performed by [s].  The other parameters are as in [eval_expr]. *)
+  performed by [s].  [t] is the trace of I/O events performed during
+  the execution.  The other parameters are as in [eval_expr]. *)
 
 with exec_stmt:
          val ->
@@ -422,21 +368,37 @@ with exec_stmt:
   | exec_Sskip:
       forall sp e m,
       exec_stmt sp e m Sskip E0 e m Out_normal
-  | exec_Sexpr:
-      forall sp e m a t m1 v,
-      eval_expr sp nil e m a t m1 v ->
-      exec_stmt sp e m (Sexpr a) t e m1 Out_normal
   | exec_Sassign:
-      forall sp e m id a t m1 v,
-      eval_expr sp nil e m a t m1 v ->
-      exec_stmt sp e m (Sassign id a) t (PTree.set id v e) m1 Out_normal
+      forall sp e m id a v,
+      eval_expr sp e m a v ->
+      exec_stmt sp e m (Sassign id a) E0 (PTree.set id v e) m Out_normal
+  | exec_Sstore:
+      forall sp e m chunk addr a vaddr v m',
+      eval_expr sp e m addr vaddr ->
+      eval_expr sp e m a v ->
+      Mem.storev chunk m vaddr v = Some m' ->
+      exec_stmt sp e m (Sstore chunk addr a) E0 e m' Out_normal
+  | exec_Scall:
+      forall sp e m optid sig a bl vf vargs f t m' vres e',
+      eval_expr sp e m a vf ->
+      eval_exprlist sp e m bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      eval_funcall m f vargs t m' vres ->
+      e' = set_optvar optid vres e ->
+      exec_stmt sp e m (Scall optid sig a bl) t e' m' Out_normal
+  | exec_Salloc:
+      forall sp e m id a n m' b,
+      eval_expr sp e m a (Vint n) ->
+      Mem.alloc m 0 (Int.signed n) = (m', b) ->
+      exec_stmt sp e m (Salloc id a) 
+                E0 (PTree.set id (Vptr b Int.zero) e) m' Out_normal
   | exec_Sifthenelse:
-      forall sp e m a s1 s2 t t1 m1 v1 b1 t2 e2 m2 out,
-      eval_expr sp nil e m a t1 m1 v1 ->
-      Val.bool_of_val v1 b1 ->
-      exec_stmt sp e m1 (if b1 then s1 else s2) t2 e2 m2 out ->
-      t = t1 ** t2 ->
-      exec_stmt sp e m (Sifthenelse a s1 s2) t e2 m2 out
+      forall sp e m a s1 s2 v b t e' m' out,
+      eval_expr sp e m a v ->
+      Val.bool_of_val v b ->
+      exec_stmt sp e m (if b then s1 else s2) t e' m' out ->
+      exec_stmt sp e m (Sifthenelse a s1 s2) t e' m' out
   | exec_Sseq_continue:
       forall sp e m t s1 t1 e1 m1 s2 t2 e2 m2 out,
       exec_stmt sp e m s1 t1 e1 m1 Out_normal ->
@@ -467,46 +429,121 @@ with exec_stmt:
       forall sp e m n,
       exec_stmt sp e m (Sexit n) E0 e m (Out_exit n)
   | exec_Sswitch:
-      forall sp e m a cases default t1 m1 n,
-      eval_expr sp nil e m a t1 m1 (Vint n) ->
+      forall sp e m a cases default n,
+      eval_expr sp e m a (Vint n) ->
       exec_stmt sp e m (Sswitch a cases default)
-                t1 e m1 (Out_exit (switch_target n default cases))
+                E0 e m (Out_exit (switch_target n default cases))
   | exec_Sreturn_none:
       forall sp e m,
       exec_stmt sp e m (Sreturn None) E0 e m (Out_return None)
   | exec_Sreturn_some:
-      forall sp e m a t m1 v,
-      eval_expr sp nil e m a t m1 v ->
-      exec_stmt sp e m (Sreturn (Some a)) t e m1 (Out_return (Some v))
+      forall sp e m a v,
+      eval_expr sp e m a v ->
+      exec_stmt sp e m (Sreturn (Some a)) E0 e m (Out_return (Some v))
   | exec_Stailcall:
-      forall sp e m sig a bl t t1 m1 t2 m2 t3 m3 vf vargs vres f,
-      eval_expr (Vptr sp Int.zero) nil e m a t1 m1 vf ->
-      eval_exprlist (Vptr sp Int.zero) nil e m1 bl t2 m2 vargs ->
+      forall sp e m sig a bl vf vargs f t m' vres,
+      eval_expr (Vptr sp Int.zero) e m a vf ->
+      eval_exprlist (Vptr sp Int.zero) e m bl vargs ->
       Genv.find_funct ge vf = Some f ->
       funsig f = sig ->
-      eval_funcall (Mem.free m2 sp) f vargs t3 m3 vres ->
-      t = t1 ** t2 ** t3 ->
-      exec_stmt (Vptr sp Int.zero) e m (Stailcall sig a bl) t e m3 (Out_tailcall_return vres).
+      eval_funcall (Mem.free m sp) f vargs t m' vres ->
+      exec_stmt (Vptr sp Int.zero) e m (Stailcall sig a bl) t e m' (Out_tailcall_return vres).
 
-Scheme eval_expr_ind4 := Minimality for eval_expr Sort Prop
-  with eval_exprlist_ind4 := Minimality for eval_exprlist Sort Prop
-  with eval_funcall_ind4 := Minimality for eval_funcall Sort Prop
-  with exec_stmt_ind4 := Minimality for exec_stmt Sort Prop.
-
-End RELSEM.
+Scheme eval_funcall_ind2 := Minimality for eval_funcall Sort Prop
+  with exec_stmt_ind2 := Minimality for exec_stmt Sort Prop.
 
-(** Execution of a whole program: [exec_program p t r]
-  holds if the application of [p]'s main function to no arguments
-  in the initial memory state for [p] performs the input/output
-  operations described in the trace [t], and eventually returns value [r].
+(** Coinductive semantics for divergence.
+  [evalinf_funcall ge m f args t]
+  means that the function [f] diverges when applied to the arguments [args] in
+  memory state [m].  The infinite trace [t] is the trace of
+  observable events generated during the invocation.
 *)
 
-Definition exec_program (p: program) (t: trace) (r: val) : Prop :=
-  let ge := Genv.globalenv p in
-  let m0 := Genv.init_mem p in
-  exists b, exists f, exists m,
-  Genv.find_symbol ge p.(prog_main) = Some b /\
-  Genv.find_funct_ptr ge b = Some f /\
-  funsig f = mksignature nil (Some Tint) /\
-  eval_funcall ge m0 f nil t m r.
+CoInductive evalinf_funcall:
+        mem -> fundef -> list val -> traceinf -> Prop :=
+  | evalinf_funcall_internal:
+      forall m f vargs m1 sp e t,
+      Mem.alloc m 0 f.(fn_stackspace) = (m1, sp) ->
+      set_locals f.(fn_vars) (set_params vargs f.(fn_params)) = e ->
+      execinf_stmt (Vptr sp Int.zero) e m1 f.(fn_body) t ->
+      evalinf_funcall m (Internal f) vargs t
+
+(** [execinf_stmt ge sp e m s t] means that statement [s] diverges.
+  [e] is the initial environment, [m] is the initial memory state,
+  and [t] the trace of observable events performed during the execution. *)
+
+with execinf_stmt:
+         val -> env -> mem -> stmt -> traceinf -> Prop :=
+  | execinf_Scall:
+      forall sp e m optid sig a bl vf vargs f t,
+      eval_expr sp e m a vf ->
+      eval_exprlist sp e m bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      evalinf_funcall m f vargs t ->
+      execinf_stmt sp e m (Scall optid sig a bl) t
+  | execinf_Sifthenelse:
+      forall sp e m a s1 s2 v b t,
+      eval_expr sp e m a v ->
+      Val.bool_of_val v b ->
+      execinf_stmt sp e m (if b then s1 else s2) t ->
+      execinf_stmt sp e m (Sifthenelse a s1 s2) t
+  | execinf_Sseq_1:
+      forall sp e m t s1 s2,
+      execinf_stmt sp e m s1 t ->
+      execinf_stmt sp e m (Sseq s1 s2) t
+  | execinf_Sseq_2:
+      forall sp e m t s1 t1 e1 m1 s2 t2,
+      exec_stmt sp e m s1 t1 e1 m1 Out_normal ->
+      execinf_stmt sp e1 m1 s2 t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt sp e m (Sseq s1 s2) t
+  | execinf_Sloop_body:
+      forall sp e m s t,
+      execinf_stmt sp e m s t ->
+      execinf_stmt sp e m (Sloop s) t
+  | execinf_Sloop_loop:
+      forall sp e m s t t1 e1 m1 t2,
+      exec_stmt sp e m s t1 e1 m1 Out_normal ->
+      execinf_stmt sp e1 m1 (Sloop s) t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt sp e m (Sloop s) t
+  | execinf_Sblock:
+      forall sp e m s t,
+      execinf_stmt sp e m s t ->
+      execinf_stmt sp e m (Sblock s) t
+  | execinf_Stailcall:
+      forall sp e m sig a bl vf vargs f t,
+      eval_expr (Vptr sp Int.zero) e m a vf ->
+      eval_exprlist (Vptr sp Int.zero) e m bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      evalinf_funcall (Mem.free m sp) f vargs t ->
+      execinf_stmt (Vptr sp Int.zero) e m (Stailcall sig a bl) t.
+
+End RELSEM.
 
+(** Execution of a whole program: [exec_program p beh]
+  holds if the application of [p]'s main function to no arguments
+  in the initial memory state for [p] has [beh] as observable
+  behavior. *)
+
+Inductive exec_program (p: program): program_behavior -> Prop :=
+  | program_terminates:
+      forall b f t m r,
+      let ge := Genv.globalenv p in
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      funsig f = mksignature nil (Some Tint) ->
+      eval_funcall ge m0 f nil t m (Vint r) ->
+      exec_program p (Terminates t r)
+  | program_diverges:
+      forall b f t,
+      let ge := Genv.globalenv p in
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      funsig f = mksignature nil (Some Tint) ->
+      evalinf_funcall ge m0 f nil t ->
+      exec_program p (Diverges t).
diff --git a/backend/CminorSel.v b/backend/CminorSel.v
index 331105ead..859c46e75 100644
--- a/backend/CminorSel.v
+++ b/backend/CminorSel.v
@@ -12,6 +12,7 @@ Require Import Cminor.
 Require Import Op.
 Require Import Globalenvs.
 Require Import Switch.
+Require Import Smallstep.
 
 (** * Abstract syntax *)
 
@@ -19,7 +20,10 @@ Require Import Switch.
   functions, statements and expressions.  However, CminorSel uses
   machine-dependent operations, addressing modes and conditions,
   as defined in module [Op] and used in lower-level intermediate
-  languages ([RTL] and below).  Moreover, a variant [condexpr] of [expr]
+  languages ([RTL] and below).  Moreover, to express sharing of
+  sub-computations, a "let" binding is provided (constructions
+  [Elet] and [Eletvar]), using de Bruijn indices to refer to "let"-bound
+  variables.  Finally, a variant [condexpr] of [expr]
   is used to represent expressions which are evaluated for their
   boolean value only and not their exact value.
 *)
@@ -28,12 +32,9 @@ Inductive expr : Set :=
   | Evar : ident -> expr
   | Eop : operation -> exprlist -> expr
   | Eload : memory_chunk -> addressing -> exprlist -> expr
-  | Estore : memory_chunk -> addressing -> exprlist -> expr -> expr
-  | Ecall : signature -> expr -> exprlist -> expr
   | Econdition : condexpr -> expr -> expr -> expr
   | Elet : expr -> expr -> expr
   | Eletvar : nat -> expr
-  | Ealloc : expr -> expr
 
 with condexpr : Set :=
   | CEtrue: condexpr
@@ -46,12 +47,15 @@ with exprlist : Set :=
   | Econs: expr -> exprlist -> exprlist.
 
 (** Statements are as in Cminor, except that the condition of an
-  if/then/else conditional is a [condexpr]. *)
+  if/then/else conditional is a [condexpr], and the [Sstore] construct
+  uses a machine-dependent addressing mode. *)
 
 Inductive stmt : Set :=
   | Sskip: stmt
-  | Sexpr: expr -> stmt
   | Sassign : ident -> expr -> stmt
+  | Sstore : memory_chunk -> addressing -> exprlist -> expr -> stmt
+  | Scall : option ident -> signature -> expr -> exprlist -> stmt
+  | Salloc : ident -> expr -> stmt
   | Sseq: stmt -> stmt -> stmt
   | Sifthenelse: condexpr -> stmt -> stmt -> stmt
   | Sloop: stmt -> stmt
@@ -87,6 +91,7 @@ Definition funsig (fd: fundef) :=
 *)
 
 Definition genv := Genv.t fundef.
+Definition letenv := list val.
 
 Section RELSEM.
 
@@ -96,101 +101,68 @@ Variable ge: genv.
     of Cminor.  Refer to the description of Cminor semantics for
     the meaning of the parameters of the predicates.
     One additional predicate is introduced:
-    [eval_condexpr ge sp le e m a t m' b], meaning that the conditional
+    [eval_condexpr ge sp e m le a b], meaning that the conditional
     expression [a] evaluates to the boolean [b]. *)
 
-Inductive eval_expr:
-         val -> letenv -> env ->
-         mem -> expr -> trace -> mem -> val -> Prop :=
-  | eval_Evar:
-      forall sp le e m id v,
+Section EVAL_EXPR.
+
+Variable sp: val.
+Variable e: env.
+Variable m: mem.
+
+Inductive eval_expr: letenv -> expr -> val -> Prop :=
+  | eval_Evar: forall le id v,
       PTree.get id e = Some v ->
-      eval_expr sp le e m (Evar id) E0 m v
-  | eval_Eop:
-      forall sp le e m op al t m1 vl v,
-      eval_exprlist sp le e m al t m1 vl ->
-      eval_operation ge sp op vl m1 = Some v ->
-      eval_expr sp le e m (Eop op al) t m1 v
-  | eval_Eload:
-      forall sp le e m chunk addr al t m1 v vl a,
-      eval_exprlist sp le e m al t m1 vl ->
-      eval_addressing ge sp addr vl = Some a ->
-      Mem.loadv chunk m1 a = Some v ->
-      eval_expr sp le e m (Eload chunk addr al) t m1 v
-  | eval_Estore:
-      forall sp le e m chunk addr al b t t1 m1 vl t2 m2 m3 v a,
-      eval_exprlist sp le e m al t1 m1 vl ->
-      eval_expr sp le e m1 b t2 m2 v ->
-      eval_addressing ge sp addr vl = Some a ->
-      Mem.storev chunk m2 a v = Some m3 ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Estore chunk addr al b) t m3 v
-  | eval_Ecall:
-      forall sp le e m sig a bl t t1 m1 t2 m2 t3 m3 vf vargs vres f,
-      eval_expr sp le e m a t1 m1 vf ->
-      eval_exprlist sp le e m1 bl t2 m2 vargs ->
-      Genv.find_funct ge vf = Some f ->
-      funsig f = sig ->
-      eval_funcall m2 f vargs t3 m3 vres ->
-      t = t1 ** t2 ** t3 ->
-      eval_expr sp le e m (Ecall sig a bl) t m3 vres
-  | eval_Econdition:
-      forall sp le e m a b c t t1 m1 v1 t2 m2 v2,
-      eval_condexpr sp le e m a t1 m1 v1 ->
-      eval_expr sp le e m1 (if v1 then b else c) t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Econdition a b c) t m2 v2
-  | eval_Elet:
-      forall sp le e m a b t t1 m1 v1 t2 m2 v2,
-      eval_expr sp le e m a t1 m1 v1 ->
-      eval_expr sp (v1::le) e m1 b t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr sp le e m (Elet a b) t m2 v2
-  | eval_Eletvar:
-      forall sp le e m n v,
+      eval_expr le (Evar id) v
+  | eval_Eop: forall le op al vl v,
+      eval_exprlist le al vl ->
+      eval_operation ge sp op vl m = Some v ->
+      eval_expr le (Eop op al) v
+  | eval_Eload: forall le chunk addr al vl vaddr v,
+      eval_exprlist le al vl ->
+      eval_addressing ge sp addr vl = Some vaddr ->
+      Mem.loadv chunk m vaddr = Some v ->     
+      eval_expr le (Eload chunk addr al) v
+  | eval_Econdition: forall le a b c v1 v2,
+      eval_condexpr le a v1 ->
+      eval_expr le (if v1 then b else c) v2 ->
+      eval_expr le (Econdition a b c) v2
+  | eval_Elet: forall le a b v1 v2,
+      eval_expr le a v1 ->
+      eval_expr (v1 :: le) b v2 ->
+      eval_expr le (Elet a b) v2
+  | eval_Eletvar: forall le n v,
       nth_error le n = Some v ->
-      eval_expr sp le e m (Eletvar n) E0 m v
-  | eval_Ealloc:
-      forall sp le e m a t m1 n m2 b,
-      eval_expr sp le e m a t m1 (Vint n) ->
-      Mem.alloc m1 0 (Int.signed n) = (m2, b) ->
-      eval_expr sp le e m (Ealloc a) t m2 (Vptr b Int.zero)
-
-with eval_condexpr:
-         val -> letenv -> env ->
-         mem -> condexpr -> trace -> mem -> bool -> Prop :=
-  | eval_CEtrue:
-      forall sp le e m,
-      eval_condexpr sp le e m CEtrue E0 m true
-  | eval_CEfalse:
-      forall sp le e m,
-      eval_condexpr sp le e m CEfalse E0 m false
-  | eval_CEcond:
-      forall sp le e m cond al t1 m1 vl b,
-      eval_exprlist sp le e m al t1 m1 vl ->
-      eval_condition cond vl m1 = Some b ->
-      eval_condexpr sp le e m (CEcond cond al) t1 m1 b
-  | eval_CEcondition:
-      forall sp le e m a b c t t1 m1 vb1 t2 m2 vb2,
-      eval_condexpr sp le e m a t1 m1 vb1 ->
-      eval_condexpr sp le e m1 (if vb1 then b else c) t2 m2 vb2 ->
-      t = t1 ** t2 ->
-      eval_condexpr sp le e m (CEcondition a b c) t m2 vb2
-
-with eval_exprlist:
-         val -> letenv -> env ->
-         mem -> exprlist -> trace -> mem -> list val -> Prop :=
-  | eval_Enil:
-      forall sp le e m,
-      eval_exprlist sp le e m Enil E0 m nil
-  | eval_Econs:
-      forall sp le e m a bl t t1 m1 v t2 m2 vl,
-      eval_expr sp le e m a t1 m1 v ->
-      eval_exprlist sp le e m1 bl t2 m2 vl ->
-      t = t1 ** t2 ->
-      eval_exprlist sp le e m (Econs a bl) t m2 (v :: vl)
+      eval_expr le (Eletvar n) v
+
+with eval_condexpr: letenv -> condexpr -> bool -> Prop :=
+  | eval_CEtrue: forall le,
+      eval_condexpr le CEtrue true
+  | eval_CEfalse: forall le,
+      eval_condexpr le CEfalse false
+  | eval_CEcond: forall le cond al vl b,
+      eval_exprlist le al vl ->
+      eval_condition cond vl m = Some b ->
+      eval_condexpr le (CEcond cond al) b
+  | eval_CEcondition: forall le a b c vb1 vb2,
+      eval_condexpr le a vb1 ->
+      eval_condexpr le (if vb1 then b else c) vb2 ->
+      eval_condexpr le (CEcondition a b c) vb2
+
+with eval_exprlist: letenv -> exprlist -> list val -> Prop :=
+  | eval_Enil: forall le,
+      eval_exprlist le Enil nil
+  | eval_Econs: forall le a1 al v1 vl,
+      eval_expr le a1 v1 -> eval_exprlist le al vl ->
+      eval_exprlist le (Econs a1 al) (v1 :: vl).
 
-with eval_funcall:
+Scheme eval_expr_ind3 := Minimality for eval_expr Sort Prop
+  with eval_condexpr_ind3 := Minimality for eval_condexpr Sort Prop
+  with eval_exprlist_ind3 := Minimality for eval_exprlist Sort Prop.
+
+End EVAL_EXPR.
+
+Inductive eval_funcall:
         mem -> fundef -> list val -> trace ->
         mem -> val -> Prop :=
   | eval_funcall_internal:
@@ -212,20 +184,37 @@ with exec_stmt:
   | exec_Sskip:
       forall sp e m,
       exec_stmt sp e m Sskip E0 e m Out_normal
-  | exec_Sexpr:
-      forall sp e m a t m1 v,
-      eval_expr sp nil e m a t m1 v ->
-      exec_stmt sp e m (Sexpr a) t e m1 Out_normal
   | exec_Sassign:
-      forall sp e m id a t m1 v,
-      eval_expr sp nil e m a t m1 v ->
-      exec_stmt sp e m (Sassign id a) t (PTree.set id v e) m1 Out_normal
+      forall sp e m id a v,
+      eval_expr sp e m nil a v ->
+      exec_stmt sp e m (Sassign id a) E0 (PTree.set id v e) m Out_normal
+  | exec_Sstore:
+      forall sp e m chunk addr al b vl v vaddr m',
+      eval_exprlist sp e m nil al vl ->
+      eval_expr sp e m nil b v ->
+      eval_addressing ge sp addr vl = Some vaddr ->
+      Mem.storev chunk m vaddr v = Some m' ->
+      exec_stmt sp e m (Sstore chunk addr al b) E0 e m' Out_normal
+  | exec_Scall:
+      forall sp e m optid sig a bl vf vargs f t m' vres e',
+      eval_expr sp e m nil a vf ->
+      eval_exprlist sp e m nil bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      eval_funcall m f vargs t m' vres ->
+      e' = set_optvar optid vres e ->
+      exec_stmt sp e m (Scall optid sig a bl) t e' m' Out_normal
+  | exec_Salloc:
+      forall sp e m id a n m' b,
+      eval_expr sp e m nil a (Vint n) ->
+      Mem.alloc m 0 (Int.signed n) = (m', b) ->
+      exec_stmt sp e m (Salloc id a) 
+                E0 (PTree.set id (Vptr b Int.zero) e) m' Out_normal
   | exec_Sifthenelse:
-      forall sp e m a s1 s2 t t1 m1 v1 t2 e2 m2 out,
-      eval_condexpr sp nil e m a t1 m1 v1 ->
-      exec_stmt sp e m1 (if v1 then s1 else s2) t2 e2 m2 out ->
-      t = t1 ** t2 ->
-      exec_stmt sp e m (Sifthenelse a s1 s2) t e2 m2 out
+      forall sp e m a s1 s2 v t e' m' out,
+      eval_condexpr sp e m nil a v ->
+      exec_stmt sp e m (if v then s1 else s2) t e' m' out ->
+      exec_stmt sp e m (Sifthenelse a s1 s2) t e' m' out
   | exec_Sseq_continue:
       forall sp e m t s1 t1 e1 m1 s2 t2 e2 m2 out,
       exec_stmt sp e m s1 t1 e1 m1 Out_normal ->
@@ -256,41 +245,115 @@ with exec_stmt:
       forall sp e m n,
       exec_stmt sp e m (Sexit n) E0 e m (Out_exit n)
   | exec_Sswitch:
-      forall sp e m a cases default t1 m1 n,
-      eval_expr sp nil e m a t1 m1 (Vint n) ->
+      forall sp e m a cases default n,
+      eval_expr sp e m nil a (Vint n) ->
       exec_stmt sp e m (Sswitch a cases default)
-                t1 e m1 (Out_exit (switch_target n default cases))
+                E0 e m (Out_exit (switch_target n default cases))
   | exec_Sreturn_none:
       forall sp e m,
       exec_stmt sp e m (Sreturn None) E0 e m (Out_return None)
   | exec_Sreturn_some:
-      forall sp e m a t m1 v,
-      eval_expr sp nil e m a t m1 v ->
-      exec_stmt sp e m (Sreturn (Some a)) t e m1 (Out_return (Some v))
+      forall sp e m a v,
+      eval_expr sp e m nil a v ->
+      exec_stmt sp e m (Sreturn (Some a)) E0 e m (Out_return (Some v))
   | exec_Stailcall:
-      forall sp e m sig a bl t t1 m1 t2 m2 t3 m3 vf vargs vres f,
-      eval_expr (Vptr sp Int.zero) nil e m a t1 m1 vf ->
-      eval_exprlist (Vptr sp Int.zero) nil e m1 bl t2 m2 vargs ->
+      forall sp e m sig a bl vf vargs f t m' vres,
+      eval_expr (Vptr sp Int.zero) e m nil a vf ->
+      eval_exprlist (Vptr sp Int.zero) e m nil bl vargs ->
       Genv.find_funct ge vf = Some f ->
       funsig f = sig ->
-      eval_funcall (Mem.free m2 sp) f vargs t3 m3 vres ->
-      t = t1 ** t2 ** t3 ->
-      exec_stmt (Vptr sp Int.zero) e m (Stailcall sig a bl) t e m3 (Out_tailcall_return vres).
+      eval_funcall (Mem.free m sp) f vargs t m' vres ->
+      exec_stmt (Vptr sp Int.zero) e m (Stailcall sig a bl) t e m' (Out_tailcall_return vres).
+
+Scheme eval_funcall_ind2 := Minimality for eval_funcall Sort Prop
+  with exec_stmt_ind2 := Minimality for exec_stmt Sort Prop.
+
+(** Coinductive semantics for divergence. *)
+
+CoInductive evalinf_funcall:
+        mem -> fundef -> list val -> traceinf -> Prop :=
+  | evalinf_funcall_internal:
+      forall m f vargs m1 sp e t,
+      Mem.alloc m 0 f.(fn_stackspace) = (m1, sp) ->
+      set_locals f.(fn_vars) (set_params vargs f.(fn_params)) = e ->
+      execinf_stmt (Vptr sp Int.zero) e m1 f.(fn_body) t ->
+      evalinf_funcall m (Internal f) vargs t
 
-Scheme eval_expr_ind5 := Minimality for eval_expr Sort Prop
-  with eval_condexpr_ind5 := Minimality for eval_condexpr Sort Prop
-  with eval_exprlist_ind5 := Minimality for eval_exprlist Sort Prop
-  with eval_funcall_ind5 := Minimality for eval_funcall Sort Prop
-  with exec_stmt_ind5 := Minimality for exec_stmt Sort Prop.
+(** [execinf_stmt ge sp e m s t] means that statement [s] diverges.
+  [e] is the initial environment, [m] is the initial memory state,
+  and [t] the trace of observable events performed during the execution. *)
+
+with execinf_stmt:
+         val -> env -> mem -> stmt -> traceinf -> Prop :=
+  | execinf_Scall:
+      forall sp e m optid sig a bl vf vargs f t,
+      eval_expr sp e m nil a vf ->
+      eval_exprlist sp e m nil bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      evalinf_funcall m f vargs t ->
+      execinf_stmt sp e m (Scall optid sig a bl) t
+  | execinf_Sifthenelse:
+      forall sp e m a s1 s2 v t,
+      eval_condexpr sp e m nil a v ->
+      execinf_stmt sp e m (if v then s1 else s2) t ->
+      execinf_stmt sp e m (Sifthenelse a s1 s2) t
+  | execinf_Sseq_1:
+      forall sp e m t s1 s2,
+      execinf_stmt sp e m s1 t ->
+      execinf_stmt sp e m (Sseq s1 s2) t
+  | execinf_Sseq_2:
+      forall sp e m t s1 t1 e1 m1 s2 t2,
+      exec_stmt sp e m s1 t1 e1 m1 Out_normal ->
+      execinf_stmt sp e1 m1 s2 t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt sp e m (Sseq s1 s2) t
+  | execinf_Sloop_body:
+      forall sp e m s t,
+      execinf_stmt sp e m s t ->
+      execinf_stmt sp e m (Sloop s) t
+  | execinf_Sloop_loop:
+      forall sp e m s t t1 e1 m1 t2,
+      exec_stmt sp e m s t1 e1 m1 Out_normal ->
+      execinf_stmt sp e1 m1 (Sloop s) t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt sp e m (Sloop s) t
+  | execinf_Sblock:
+      forall sp e m s t,
+      execinf_stmt sp e m s t ->
+      execinf_stmt sp e m (Sblock s) t
+  | execinf_Stailcall:
+      forall sp e m sig a bl vf vargs f t,
+      eval_expr (Vptr sp Int.zero) e m nil a vf ->
+      eval_exprlist (Vptr sp Int.zero) e m nil bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      evalinf_funcall (Mem.free m sp) f vargs t ->
+      execinf_stmt (Vptr sp Int.zero) e m (Stailcall sig a bl) t.
 
 End RELSEM.
 
-Definition exec_program (p: program) (t: trace) (r: val) : Prop :=
-  let ge := Genv.globalenv p in
-  let m0 := Genv.init_mem p in
-  exists b, exists f, exists m,
-  Genv.find_symbol ge p.(prog_main) = Some b /\
-  Genv.find_funct_ptr ge b = Some f /\
-  funsig f = mksignature nil (Some Tint) /\
-  eval_funcall ge m0 f nil t m r.
+(** Execution of a whole program: [exec_program p beh]
+  holds if the application of [p]'s main function to no arguments
+  in the initial memory state for [p] has [beh] as observable
+  behavior. *)
 
+Inductive exec_program (p: program): program_behavior -> Prop :=
+  | program_terminates:
+      forall b f t m r,
+      let ge := Genv.globalenv p in
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      funsig f = mksignature nil (Some Tint) ->
+      eval_funcall ge m0 f nil t m (Vint r) ->
+      exec_program p (Terminates t r)
+  | program_diverges:
+      forall b f t,
+      let ge := Genv.globalenv p in
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      funsig f = mksignature nil (Some Tint) ->
+      evalinf_funcall ge m0 f nil t ->
+      exec_program p (Diverges t).
diff --git a/backend/RTLgen.v b/backend/RTLgen.v
index 117631eff..2fe13e5cd 100644
--- a/backend/RTLgen.v
+++ b/backend/RTLgen.v
@@ -266,17 +266,6 @@ Fixpoint transl_expr (map: mapping) (a: expr) (rd: reg) (nd: node)
       do rl <- alloc_regs map al;
       do no <- add_instr (Iload chunk addr rl rd nd);
          transl_exprlist map al rl no
-  | Estore chunk addr al b =>
-      do rl <- alloc_regs map al;
-      do no <- add_instr (Istore chunk addr rl rd nd);
-      do ns <- transl_expr map b rd no;
-         transl_exprlist map al rl ns
-  | Ecall sig b cl =>
-      do rf <- alloc_reg map b;
-      do rargs <- alloc_regs map cl;
-      do n1 <- add_instr (Icall sig (inl _ rf) rargs rd nd);
-      do n2 <- transl_exprlist map cl rargs n1;
-         transl_expr map b rf n2
   | Econdition b c d =>
       do nfalse <- transl_expr map d rd nd;
       do ntrue  <- transl_expr map c rd nd;
@@ -287,10 +276,6 @@ Fixpoint transl_expr (map: mapping) (a: expr) (rd: reg) (nd: node)
          transl_expr map b r nc
   | Eletvar n =>
       do r <- find_letvar map n; add_move r rd nd
-  | Ealloc a =>
-      do r <- alloc_reg map a;
-      do no <- add_instr (Ialloc r rd nd);
-         transl_expr map a r no
   end
 
 (** Translation of a conditional expression.  Similar to [transl_expr],
@@ -329,6 +314,20 @@ with transl_exprlist (map: mapping) (al: exprlist) (rl: list reg) (nd: node)
       error node (Errors.msg "RTLgen.transl_exprlist")
   end.
 
+(** Generation of code for variable assignments. *)
+
+Definition store_var
+       (map: mapping) (rs: reg) (id: ident) (nd: node) : mon node :=
+  do rv <- find_var map id;
+  add_move rs rv nd.
+
+Definition store_optvar
+       (map: mapping) (rs: reg) (optid: option ident) (nd: node) : mon node :=
+  match optid with
+  | None => ret nd
+  | Some id => store_var map rs id nd
+  end.
+
 (** Auxiliary for branch prediction.  When compiling an if/then/else
   statement, we have a choice between translating the ``then'' branch
   first or the ``else'' branch first.  Linearization of RTL control-flow
@@ -379,13 +378,30 @@ Fixpoint transl_stmt (map: mapping) (s: stmt) (nd: node)
   match s with
   | Sskip =>
       ret nd
-  | Sexpr a =>
-      do r <- alloc_reg map a; transl_expr map a r nd
   | Sassign v b =>
-      do rv <- find_var map v;
       do rt <- alloc_reg map b;
-      do no <- add_move rt rv nd;
+      do no <- store_var map rt v nd;
       transl_expr map b rt no
+  | Sstore chunk addr al b =>
+      do rl <- alloc_regs map al;
+      do r <- alloc_reg map b;
+      do no <- add_instr (Istore chunk addr rl r nd);
+      do ns <- transl_expr map b r no;
+         transl_exprlist map al rl ns
+  | Scall optid sig b cl =>
+      do rf <- alloc_reg map b;
+      do rargs <- alloc_regs map cl;
+      do r <- new_reg;
+      do n1 <- store_optvar map r optid nd;
+      do n2 <- add_instr (Icall sig (inl _ rf) rargs r n1);
+      do n3 <- transl_exprlist map cl rargs n2;
+         transl_expr map b rf n3
+  | Salloc id a =>
+      do ra <- alloc_reg map a;
+      do rr <- new_reg;
+      do n1 <- store_var map rr id nd;
+      do n2 <- add_instr (Ialloc ra rr n1);
+         transl_expr map a ra n2
   | Sseq s1 s2 =>
       do ns <- transl_stmt map s2 nd nexits nret rret;
       transl_stmt map s1 ns nexits nret rret
diff --git a/backend/RTLgenproof.v b/backend/RTLgenproof.v
index 15f305a8b..e9a04fcc5 100644
--- a/backend/RTLgenproof.v
+++ b/backend/RTLgenproof.v
@@ -94,13 +94,13 @@ Proof.
   eauto.
 Qed.
 
-(** An RTL register environment matches a Cminor local environment and
+(** An RTL register environment matches a CminorSel local environment and
   let-environment if the value of every local or let-bound variable in
-  the Cminor environments is identical to the value of the
+  the CminorSel environments is identical to the value of the
   corresponding pseudo-register in the RTL register environment. *)
 
 Record match_env
-      (map: mapping) (e: Cminor.env) (le: Cminor.letenv) (rs: regset) : Prop :=
+      (map: mapping) (e: env) (le: letenv) (rs: regset) : Prop :=
   mk_match_env {
     me_vars:
       (forall id v,
@@ -367,6 +367,51 @@ Proof.
   split. apply Regmap.gss. intros; apply Regmap.gso; auto.
 Qed.
 
+(** Correctness of the code generated by [store_var] and [store_optvar]. *)
+
+Lemma tr_store_var_correct:
+  forall rs cs code map r id ns nd e sp m,
+  tr_store_var code map r id ns nd ->
+  map_wf map ->
+  match_env map e nil rs ->
+  exists rs',
+     star step tge (State cs code sp ns rs m)
+                E0 (State cs code sp nd rs' m)
+  /\ match_env map (PTree.set id rs#r e) nil rs'.
+Proof.
+  intros. destruct H as [rv [A B]].
+  exploit tr_move_correct; eauto. intros [rs' [EX [RES OTHER]]].
+  exists rs'; split. eexact EX.
+  apply match_env_invariant with (rs#rv <- (rs#r)).
+  apply match_env_update_var; auto.
+  intros. rewrite Regmap.gsspec. destruct (peq r0 rv).
+  subst r0; auto.
+  auto.
+Qed.
+
+Lemma tr_store_optvar_correct:
+  forall rs cs code map r optid ns nd e sp m,
+  tr_store_optvar code map r optid ns nd ->
+  map_wf map ->
+  match_env map e nil rs ->
+  exists rs',
+     star step tge (State cs code sp ns rs m)
+                E0 (State cs code sp nd rs' m)
+  /\ match_env map (set_optvar optid rs#r e) nil rs'.
+Proof.
+  intros. destruct optid; simpl in *.
+  eapply tr_store_var_correct; eauto.
+  exists rs; split. subst nd. apply star_refl. auto.  
+Qed.
+
+(** ** Semantic preservation for the translation of expressions *)
+
+Section CORRECTNESS_EXPR.
+
+Variable sp: val.
+Variable e: env.
+Variable m: mem.
+
 (** The proof of semantic preservation for the translation of expressions
   is a simulation argument based on diagrams of the following form:
 <<
@@ -380,16 +425,14 @@ Qed.
                     I /\ Q
 >>
   where [tr_expr code map pr a ns nd rd] is assumed to hold.
-  The left vertical arrow represents an evaluation of the expression [a]
-  to value [v].
+  The left vertical arrow represents an evaluation of the expression [a].
   The right vertical arrow represents the execution of zero, one or
   several instructions in the generated RTL flow graph [code].
 
-  The invariant [I] is the agreement between CminorSel environments
-  [e], [le] and the RTL register environment [rs],
-  as captured by [match_envs].
+  The invariant [I] is the agreement between Cminor environments and
+  RTL register environment, as captured by [match_envs].
 
-  The precondition [P] is the well-formedness of the compilation
+  The precondition [P] includes the well-formedness of the compilation
   environment [mut].
 
   The postconditions [Q] state that in the final register environment
@@ -400,15 +443,14 @@ Qed.
   We formalize this simulation property by the following predicate
   parameterized by the CminorSel evaluation (left arrow).  *)
 
-Definition transl_expr_correct 
-  (sp: val) (le: letenv) (e: env) (m: mem) (a: expr)
-              (t: trace) (m': mem) (v: val) : Prop :=
+Definition transl_expr_prop 
+     (le: letenv) (a: expr) (v: val) : Prop :=
   forall cs code map pr ns nd rd rs
     (MWF: map_wf map)
     (TE: tr_expr code map pr a ns nd rd)
     (ME: match_env map e le rs),
   exists rs',
-     star step tge (State cs code sp ns rs m) t (State cs code sp nd rs' m')
+     star step tge (State cs code sp ns rs m) E0 (State cs code sp nd rs' m)
   /\ match_env map e le rs'
   /\ rs'#rd = v
   /\ (forall r, reg_in_map map r \/ In r pr -> rs'#r = rs#r).
@@ -416,123 +458,44 @@ Definition transl_expr_correct
 (** The simulation properties for lists of expressions and for
   conditional expressions are similar. *)
 
-Definition transl_exprlist_correct 
-  (sp: val) (le: letenv) (e: env) (m: mem) (al: exprlist)
-              (t: trace) (m': mem) (vl: list val) : Prop :=
+Definition transl_exprlist_prop 
+     (le: letenv) (al: exprlist) (vl: list val) : Prop :=
   forall cs code map pr ns nd rl rs
     (MWF: map_wf map)
     (TE: tr_exprlist code map pr al ns nd rl)
     (ME: match_env map e le rs),
   exists rs',
-     star step tge (State cs code sp ns rs m) t (State cs code sp nd rs' m')
+     star step tge (State cs code sp ns rs m) E0 (State cs code sp nd rs' m)
   /\ match_env map e le rs'
   /\ rs'##rl = vl
   /\ (forall r, reg_in_map map r \/ In r pr -> rs'#r = rs#r).
 
-Definition transl_condition_correct 
-  (sp: val) (le: letenv) (e: env) (m: mem) (a: condexpr)
-              (t: trace) (m': mem) (vb: bool) : Prop :=
+Definition transl_condition_prop 
+     (le: letenv) (a: condexpr) (vb: bool) : Prop :=
   forall cs code map pr ns ntrue nfalse rs
     (MWF: map_wf map)
     (TE: tr_condition code map pr a ns ntrue nfalse)
     (ME: match_env map e le rs),
   exists rs',
-     star step tge (State cs code sp ns rs m) t
-                   (State cs code sp (if vb then ntrue else nfalse) rs' m')
+     star step tge (State cs code sp ns rs m) E0
+                   (State cs code sp (if vb then ntrue else nfalse) rs' m)
   /\ match_env map e le rs'
   /\ (forall r, reg_in_map map r \/ In r pr -> rs'#r = rs#r).
 
 
-(** The simulation diagram for the translation of statements
-  is of the following form:
-<<
-                    I /\ P
-      e, m, a -------------- State cs code sp ns rs m
-         ||                      |
-        t||                     t|*
-         ||                      |
-         \/                      v
-     e', m', out -------------- st'
-                    I /\ Q
->>
-  where [tr_stmt code map a ns ncont nexits nret rret] holds.
-  The left vertical arrow represents an execution of the statement [a]
-  with outcome [out].
-  The right vertical arrow represents the execution of
-  zero, one or several instructions in the generated RTL flow graph [code].
-
-  The invariant [I] is the agreement between CminorSel environments and
-  RTL register environment, as captured by [match_envs].
-
-  The precondition [P] is the well-formedness of the compilation
-  environment [mut].
-
-  The postcondition [Q] characterizes the final RTL state [st'].
-  It must have memory state [m'] and a register state [rs'] that matches
-  [e'].  Moreover, the program point reached must correspond to the outcome
-  [out].  This is captured by the following [state_for_outcome] predicate. *)
-
-Inductive state_for_outcome
-           (ncont: node) (nexits: list node) (nret: node) (rret: option reg)
-           (cs: list stackframe) (c: code) (sp: val) (rs: regset) (m: mem):
-           outcome -> RTL.state -> Prop :=
-  | state_for_normal:
-      state_for_outcome ncont nexits nret rret cs c sp rs m
-                        Out_normal (State cs c sp ncont rs m)
-  | state_for_exit: forall n nexit,
-      nth_error nexits n = Some nexit ->
-      state_for_outcome ncont nexits nret rret cs c sp rs m
-                        (Out_exit n) (State cs c sp nexit rs m)
-  | state_for_return_none:
-      rret = None ->
-      state_for_outcome ncont nexits nret rret cs c sp rs m
-                        (Out_return None) (State cs c sp nret rs m)
-  | state_for_return_some: forall r v,
-      rret = Some r ->
-      rs#r = v ->
-      state_for_outcome ncont nexits nret rret cs c sp rs m
-                        (Out_return (Some v)) (State cs c sp nret rs m)
-  | state_for_return_tail: forall v,
-      state_for_outcome ncont nexits nret rret cs c sp rs m
-                        (Out_tailcall_return v) (Returnstate cs v m).
-
-Definition transl_stmt_correct 
-  (sp: val) (e: env) (m: mem) (a: stmt)
-  (t: trace) (e': env) (m': mem) (out: outcome) : Prop :=
-  forall cs code map ns ncont nexits nret rret rs
-    (MWF: map_wf map)
-    (TE: tr_stmt code map a ns ncont nexits nret rret)
-    (ME: match_env map e nil rs),
-  exists rs', exists st,
-     state_for_outcome ncont nexits nret rret cs code sp rs' m' out st
-  /\ star step tge (State cs code sp ns rs m) t st
-  /\ match_env map e' nil rs'.
-
-(** Finally, the correctness condition for the translation of functions
-  is that the translated RTL function, when applied to the same arguments
-  as the original CminorSel function, returns the same value, produces
-  the same trace of events, and performs the same modifications on the
-  memory state. *)
-
-Definition transl_function_correct
-    (m: mem) (f: CminorSel.fundef) (vargs: list val)
-    (t: trace) (m': mem) (vres: val) : Prop :=
-  forall cs tf
-    (TE: transl_fundef f = OK tf),
-  star step tge (Callstate cs tf vargs m) t (Returnstate cs vres m').
 
 (** The correctness of the translation is a huge induction over
-  the CminorSel evaluation derivation for the source program.  To keep
+  the Cminor evaluation derivation for the source program.  To keep
   the proof manageable, we put each case of the proof in a separate
-  lemma.  There is one lemma for each CminorSel evaluation rule.
-  It takes as hypotheses the premises of the CminorSel evaluation rule,
-  plus the induction hypotheses, that is, the [transl_expr_correct], etc,
+  lemma.  There is one lemma for each Cminor evaluation rule.
+  It takes as hypotheses the premises of the Cminor evaluation rule,
+  plus the induction hypotheses, that is, the [transl_expr_prop], etc,
   corresponding to the evaluations of sub-expressions or sub-statements. *)
 
 Lemma transl_expr_Evar_correct:
-  forall (sp: val) (le: letenv) (e: env) (m: mem) (id: ident) (v: val),
-  e!id = Some v ->
-  transl_expr_correct sp le e m (Evar id) E0 m v.
+  forall (le : letenv) (id : positive) (v : val),
+  e ! id = Some v ->
+  transl_expr_prop le (Evar id) v.
 Proof.
   intros; red; intros. inv TE.
   exploit tr_move_correct; eauto. intros [rs' [A [B C]]]. 
@@ -553,13 +516,12 @@ Proof.
 Qed.
 
 Lemma transl_expr_Eop_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem) (op : operation)
-         (al : exprlist) (t: trace) (m1 : mem) (vl : list val)
-         (v: val),
-  eval_exprlist ge sp le e m al t m1 vl ->
-  transl_exprlist_correct sp le e m al t m1 vl ->
-  eval_operation ge sp op vl m1 = Some v ->
-  transl_expr_correct sp le e m (Eop op al) t m1 v.
+  forall (le : letenv) (op : operation) (args : exprlist)
+         (vargs : list val) (v : val),
+  eval_exprlist ge sp e m le args vargs ->
+  transl_exprlist_prop le args vargs ->
+  eval_operation ge sp op vargs m = Some v ->
+  transl_expr_prop le (Eop op args) v.
 Proof.
   intros; red; intros. inv TE. 
   exploit H0; eauto. intros [rs1 [EX1 [ME1 [RR1 RO1]]]].
@@ -567,7 +529,7 @@ Proof.
 (* Exec *)
   split. eapply star_right. eexact EX1.
   eapply exec_Iop; eauto.  
-  subst vl. 
+  subst vargs.
   rewrite (@eval_operation_preserved CminorSel.fundef RTL.fundef ge tge). 
   auto. 
   exact symbols_preserved. traceEq.
@@ -580,15 +542,13 @@ Proof.
 Qed.
 
 Lemma transl_expr_Eload_correct:
- forall (sp: val) (le : letenv) (e : env) (m : mem)
-    (chunk : memory_chunk) (addr : addressing) 
-    (al : exprlist) (t: trace) (m1 : mem) (v : val) 
-    (vl : list val) (a: val),
-  eval_exprlist ge sp le e m al t m1 vl ->
-  transl_exprlist_correct sp le e m al t m1 vl ->
-  eval_addressing ge sp addr vl = Some a ->
-  Mem.loadv chunk m1 a = Some v ->
-  transl_expr_correct sp le e m (Eload chunk addr al) t m1 v.
+  forall (le : letenv) (chunk : memory_chunk) (addr : Op.addressing)
+         (args : exprlist) (vargs : list val) (vaddr v : val),
+  eval_exprlist ge sp e m le args vargs ->
+  transl_exprlist_prop le args vargs ->
+  Op.eval_addressing ge sp addr vargs = Some vaddr ->
+  loadv chunk m vaddr = Some v ->
+  transl_expr_prop le (Eload chunk addr args) v.
 Proof.
   intros; red; intros. inv TE.
   exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
@@ -605,105 +565,19 @@ Proof.
   intros. rewrite Regmap.gso. auto. intuition congruence. 
 Qed.
 
-Lemma transl_expr_Estore_correct:
- forall (sp: val) (le : letenv) (e : env) (m : mem)
-    (chunk : memory_chunk) (addr : addressing) 
-    (al : exprlist) (b : expr) (t t1: trace) (m1 : mem) 
-    (vl : list val) (t2: trace) (m2 m3 : mem) 
-    (v : val) (a: val),
-  eval_exprlist ge sp le e m al t1 m1 vl ->
-  transl_exprlist_correct sp le e m al t1 m1 vl ->
-  eval_expr ge sp le e m1 b t2 m2 v ->
-  transl_expr_correct sp le e m1 b t2 m2 v ->
-  eval_addressing ge sp addr vl = Some a -> 
-  Mem.storev chunk m2 a v = Some m3 ->
-  t = t1 ** t2 ->
-  transl_expr_correct sp le e m (Estore chunk addr al b) t m3 v.
-Proof.
-  intros; red; intros; inv TE. 
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
-  exploit H2; eauto. intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
-  exists rs2.
-(* Exec *)
-  split. eapply star_trans. eexact EX1. 
-  eapply star_right. eexact EX2. 
-  eapply exec_Istore; eauto.
-  assert (rs2##rl = rs1##rl).
-    apply list_map_exten. intros r' IN. symmetry. apply OTHER2.
-    right. apply in_or_app. auto.
-  rewrite H5; rewrite RES1. 
-  rewrite (@eval_addressing_preserved _ _ ge tge).
-  eexact H3. exact symbols_preserved. 
-  rewrite RES2. assumption.
-  reflexivity. traceEq. 
-(* Match-env *)
-  split. assumption.
-(* Result *)
-  split. assumption.
-(* Other regs *)
-  intro r'; intros. transitivity (rs1#r'). 
-  apply OTHER2. intuition.
-  auto.
-Qed.
-
-Lemma transl_expr_Ecall_correct:
- forall (sp: val) (le : letenv) (e : env) (m : mem) 
-    (sig : signature) (a : expr) (bl : exprlist) (t t1: trace)
-    (m1: mem) (t2: trace) (m2 : mem) 
-    (t3: trace) (m3: mem) (vf : val) 
-    (vargs : list val) (vres : val) (f : CminorSel.fundef),
-  eval_expr ge sp le e m a t1 m1 vf ->
-  transl_expr_correct sp le e m a t1 m1 vf ->
-  eval_exprlist ge sp le e m1 bl t2 m2 vargs ->
-  transl_exprlist_correct sp le e m1 bl t2 m2 vargs ->
-  Genv.find_funct ge vf = Some f ->
-  CminorSel.funsig f = sig ->
-  eval_funcall ge m2 f vargs t3 m3 vres ->
-  transl_function_correct m2 f vargs t3 m3 vres ->
-  t = t1 ** t2 ** t3 ->
-  transl_expr_correct sp le e m (Ecall sig a bl) t m3 vres.
-Proof.
-  intros; red; intros; inv TE. 
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
-  exploit H2; eauto. intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
-  exploit functions_translated; eauto. intros [tf [TFIND TF]].
-  exploit H6; eauto. intro EXF.
-  exists (rs2#rd <- vres).
-(* Exec *)
-  split. eapply star_trans. eexact EX1. 
-  eapply star_trans. eexact EX2. 
-  eapply star_left. eapply exec_Icall; eauto. 
-  simpl. rewrite OTHER2. rewrite RES1. eauto. simpl; tauto. 
-  eapply sig_transl_function; eauto.
-  eapply star_right. rewrite RES2. eexact EXF.
-  apply exec_return. reflexivity. reflexivity. reflexivity. traceEq.  
-(* Match env *)
-  split. eauto with rtlg. 
-(* Result *)
-  split. apply Regmap.gss.
-(* Other regs *)
-  intros.
-  rewrite Regmap.gso. transitivity (rs1#r). 
-  apply OTHER2. simpl; tauto.
-  apply OTHER1; auto. 
-  intuition congruence.
-Qed.
-
 Lemma transl_expr_Econdition_correct:
- forall (sp: val) (le : letenv) (e : env) (m : mem) 
-    (a : condexpr) (b c : expr) (t t1: trace) (m1 : mem) 
-    (v1 : bool) (t2: trace) (m2 : mem) (v2 : val),
-  eval_condexpr ge sp le e m a t1 m1 v1 ->
-  transl_condition_correct sp le e m a t1 m1 v1 ->
-  eval_expr ge sp le e m1 (if v1 then b else c) t2 m2 v2 ->
-  transl_expr_correct sp le e m1 (if v1 then b else c) t2 m2 v2 ->
-  t = t1 ** t2 ->
-  transl_expr_correct sp le e m (Econdition a b c) t m2 v2.
+  forall (le : letenv) (cond : condexpr) (ifso ifnot : expr)
+         (vcond : bool) (v : val),
+  eval_condexpr ge sp e m le cond vcond ->
+  transl_condition_prop le cond vcond ->
+  eval_expr ge sp e m le (if vcond then ifso else ifnot) v ->
+  transl_expr_prop le (if vcond then ifso else ifnot) v ->
+  transl_expr_prop le (Econdition cond ifso ifnot) v.
 Proof.
   intros; red; intros; inv TE. 
   exploit H0; eauto. intros [rs1 [EX1 [ME1 OTHER1]]].
-  assert (tr_expr code map pr (if v1 then b else c) (if v1 then ntrue else nfalse) nd rd).
-    destruct v1; auto.
+  assert (tr_expr code map pr (if vcond then ifso else ifnot) (if vcond then ntrue else nfalse) nd rd).
+    destruct vcond; auto.
   exploit H2; eauto. intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
   exists rs2.
 (* Exec *)
@@ -717,15 +591,12 @@ Proof.
 Qed.
 
 Lemma transl_expr_Elet_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem) 
-    (a b : expr) (t t1: trace) (m1 : mem) (v1 : val) 
-    (t2: trace) (m2 : mem) (v2 : val),
-  eval_expr ge sp le e m a t1 m1 v1 ->
-  transl_expr_correct sp le e m a t1 m1 v1 ->
-  eval_expr ge sp (v1 :: le) e m1 b t2 m2 v2 ->
-  transl_expr_correct sp (v1 :: le) e m1 b t2 m2 v2 ->
-  t = t1 ** t2 ->
-  transl_expr_correct sp le e m (Elet a b) t m2 v2.
+  forall (le : letenv) (a1 a2 : expr) (v1 v2 : val),
+  eval_expr ge sp e m le a1 v1 ->
+  transl_expr_prop le a1 v1 ->
+  eval_expr ge sp e m (v1 :: le) a2 v2 ->
+  transl_expr_prop (v1 :: le) a2 v2 ->
+  transl_expr_prop le (Elet a1 a2) v2.
 Proof.
   intros; red; intros; inv TE. 
   exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
@@ -744,15 +615,14 @@ Proof.
   intros. transitivity (rs1#r0). 
   apply OTHER2. elim H4; intro; auto.
   unfold reg_in_map, add_letvar; simpl.
-  unfold reg_in_map in H5; tauto.
+  unfold reg_in_map in H6; tauto.
   auto.
 Qed.
 
 Lemma transl_expr_Eletvar_correct:
-  forall (sp: val) (le : list val) (e : env) 
-    (m : mem) (n : nat) (v : val),
+  forall (le : list val) (n : nat) (v : val),
   nth_error le n = Some v ->
-  transl_expr_correct sp le e m (Eletvar n) E0 m v.
+  transl_expr_prop le (Eletvar n) v.
 Proof.
   intros; red; intros; inv TE.
   exploit tr_move_correct; eauto. intros [rs1 [EX1 [RES1 OTHER1]]].
@@ -772,54 +642,29 @@ Proof.
   apply OTHER1. intuition congruence.
 Qed.
 
-Lemma transl_expr_Ealloc_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem) 
-    (a : expr) (t: trace) (m1 : mem) (n: int)
-    (m2: mem) (b: block),
-  eval_expr ge sp le e m a t m1 (Vint n) ->
-  transl_expr_correct sp le e m a t m1 (Vint n) ->
-  Mem.alloc m1 0 (Int.signed n) = (m2, b) ->
-  transl_expr_correct sp le e m (Ealloc a) t m2 (Vptr b Int.zero).
-Proof.
-  intros; red; intros; inv TE. 
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RR1 RO1]]]].
-  exists (rs1#rd <- (Vptr b Int.zero)).
-(* Exec *)
-  split. eapply star_right. eexact EX1. 
-  eapply exec_Ialloc. eauto with rtlg.
-  eexact RR1. assumption. traceEq. 
-(* Match-env *)
-  split. eauto with rtlg. 
-(* Result *)
-  split. apply Regmap.gss.
-(* Other regs *)
-  intros. rewrite Regmap.gso. auto. intuition congruence.
-Qed.
-
 Lemma transl_condition_CEtrue_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem),
-  transl_condition_correct sp le e m CEtrue E0 m true.
+  forall (le : letenv),
+  transl_condition_prop le CEtrue true.
 Proof.
   intros; red; intros; inv TE. 
   exists rs. split. apply star_refl. split. auto. auto.
 Qed.    
 
 Lemma transl_condition_CEfalse_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem),
-  transl_condition_correct sp le e m CEfalse E0 m false.
+  forall (le : letenv),
+  transl_condition_prop le CEfalse false.
 Proof.
   intros; red; intros; inv TE. 
   exists rs. split. apply star_refl. split. auto. auto.
 Qed.    
 
 Lemma transl_condition_CEcond_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem)
-    (cond : condition) (al : exprlist) (t1: trace)
-    (m1 : mem) (vl : list val) (b : bool),
-  eval_exprlist ge sp le e m al t1 m1 vl ->
-  transl_exprlist_correct sp le e m al t1 m1 vl ->
-  eval_condition cond vl m1 = Some b ->
-  transl_condition_correct sp le e m (CEcond cond al) t1 m1 b.
+  forall (le : letenv) (cond : condition) (args : exprlist)
+         (vargs : list val) (b : bool),
+  eval_exprlist ge sp e m le args vargs ->
+  transl_exprlist_prop le args vargs ->
+  eval_condition cond vargs m = Some b ->
+  transl_condition_prop le (CEcond cond args) b.
 Proof.
   intros; red; intros; inv TE.
   exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
@@ -839,21 +684,18 @@ Proof.
 Qed.
 
 Lemma transl_condition_CEcondition_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem)
-    (a b c : condexpr) (t t1: trace) (m1 : mem) 
-    (vb1 : bool) (t2: trace) (m2 : mem) (vb2 : bool),
-  eval_condexpr ge sp le e m a t1 m1 vb1 ->
-  transl_condition_correct sp le e m a t1 m1 vb1 ->
-  eval_condexpr ge sp le e m1 (if vb1 then b else c) t2 m2 vb2 ->
-  transl_condition_correct sp le e m1 (if vb1 then b else c) t2 m2 vb2 ->
-  t = t1 ** t2 ->
-  transl_condition_correct sp le e m (CEcondition a b c) t m2 vb2.
+  forall (le : letenv) (cond ifso ifnot : condexpr) (vcond v : bool),
+  eval_condexpr ge sp e m le cond vcond ->
+  transl_condition_prop le cond vcond ->
+  eval_condexpr ge sp e m le (if vcond then ifso else ifnot) v ->
+  transl_condition_prop le (if vcond then ifso else ifnot) v ->
+  transl_condition_prop le (CEcondition cond ifso ifnot) v.
 Proof.
   intros; red; intros; inv TE. 
   exploit H0; eauto. intros [rs1 [EX1 [ME1 OTHER1]]].
-  assert (tr_condition code map pr (if vb1 then b else c)
-             (if vb1 then ntrue' else nfalse') ntrue nfalse).
-    destruct vb1; auto.
+  assert (tr_condition code map pr (if vcond then ifso else ifnot)
+             (if vcond then ntrue' else nfalse') ntrue nfalse).
+    destruct vcond; auto.
   exploit H2; eauto. intros [rs2 [EX2 [ME2 OTHER2]]].
   exists rs2.
 (* Execution *)
@@ -865,8 +707,8 @@ Proof.
 Qed.
  
 Lemma transl_exprlist_Enil_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem),
-  transl_exprlist_correct sp le e m Enil E0 m nil.
+  forall (le : letenv),
+  transl_exprlist_prop le Enil nil.
 Proof.
   intros; red; intros; inv TE.
   exists rs.
@@ -877,15 +719,13 @@ Proof.
 Qed.
 
 Lemma transl_exprlist_Econs_correct:
-  forall (sp: val) (le : letenv) (e : env) (m : mem) 
-    (a : expr) (bl : exprlist) (t t1: trace) (m1 : mem) 
-    (v : val) (t2: trace) (m2 : mem) (vl : list val),
-  eval_expr ge sp le e m a t1 m1 v ->
-  transl_expr_correct sp le e m a t1 m1 v ->
-  eval_exprlist ge sp le e m1 bl t2 m2 vl ->
-  transl_exprlist_correct sp le e m1 bl t2 m2 vl ->
-  t = t1 ** t2 ->
-  transl_exprlist_correct sp le e m (Econs a bl) t m2 (v :: vl).
+  forall (le : letenv) (a1 : expr) (al : exprlist) (v1 : val)
+         (vl : list val),
+  eval_expr ge sp e m le a1 v1 ->
+  transl_expr_prop le a1 v1 ->
+  eval_exprlist ge sp e m le al vl ->
+  transl_exprlist_prop le al vl ->
+  transl_exprlist_prop le (Econs a1 al) (v1 :: vl).
 Proof.
   intros; red; intros; inv TE.
   exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
@@ -904,6 +744,153 @@ Proof.
   apply OTHER1; auto.
 Qed.
 
+Theorem transl_expr_correct:
+  forall le a v,
+  eval_expr ge sp e m le a v ->
+  transl_expr_prop le a v.
+Proof
+  (eval_expr_ind3 ge sp e m
+     transl_expr_prop
+     transl_condition_prop
+     transl_exprlist_prop
+     transl_expr_Evar_correct
+     transl_expr_Eop_correct
+     transl_expr_Eload_correct
+     transl_expr_Econdition_correct
+     transl_expr_Elet_correct
+     transl_expr_Eletvar_correct
+     transl_condition_CEtrue_correct
+     transl_condition_CEfalse_correct
+     transl_condition_CEcond_correct
+     transl_condition_CEcondition_correct
+     transl_exprlist_Enil_correct
+     transl_exprlist_Econs_correct).
+
+Theorem transl_condexpr_correct:
+  forall le a v,
+  eval_condexpr ge sp e m le a v ->
+  transl_condition_prop le a v.
+Proof
+  (eval_condexpr_ind3 ge sp e m
+     transl_expr_prop
+     transl_condition_prop
+     transl_exprlist_prop
+     transl_expr_Evar_correct
+     transl_expr_Eop_correct
+     transl_expr_Eload_correct
+     transl_expr_Econdition_correct
+     transl_expr_Elet_correct
+     transl_expr_Eletvar_correct
+     transl_condition_CEtrue_correct
+     transl_condition_CEfalse_correct
+     transl_condition_CEcond_correct
+     transl_condition_CEcondition_correct
+     transl_exprlist_Enil_correct
+     transl_exprlist_Econs_correct).
+
+
+Theorem transl_exprlist_correct:
+  forall le a v,
+  eval_exprlist ge sp e m le a v ->
+  transl_exprlist_prop le a v.
+Proof
+  (eval_exprlist_ind3 ge sp e m
+     transl_expr_prop
+     transl_condition_prop
+     transl_exprlist_prop
+     transl_expr_Evar_correct
+     transl_expr_Eop_correct
+     transl_expr_Eload_correct
+     transl_expr_Econdition_correct
+     transl_expr_Elet_correct
+     transl_expr_Eletvar_correct
+     transl_condition_CEtrue_correct
+     transl_condition_CEfalse_correct
+     transl_condition_CEcond_correct
+     transl_condition_CEcondition_correct
+     transl_exprlist_Enil_correct
+     transl_exprlist_Econs_correct).
+
+End CORRECTNESS_EXPR.
+
+(** ** Semantic preservation for the translation of terminating statements *)   
+
+(** The simulation diagram for the translation of statements
+  is of the following form:
+<<
+                    I /\ P
+       e, m, a ---------------- State cs code sp ns rs m
+         ||                          |
+        t||                         t|*
+         ||                          |
+         \/                          v
+     e', m', out ------------------ st'
+                    I /\ Q
+>>
+  where [tr_stmt code map a ns ncont nexits nret rret] holds.
+  The left vertical arrow represents an execution of the statement [a].
+  The right vertical arrow represents the execution of
+  zero, one or several instructions in the generated RTL flow graph [code].
+
+  The invariant [I] is the agreement between Cminor environments and
+  RTL register environment, as captured by [match_envs].
+
+  The precondition [P] is the well-formedness of the compilation
+  environment [mut].
+
+  The postcondition [Q] characterizes the final RTL state [st'].
+  It must have memory state [m'] and register state [rs'] that matches
+  [e'].  Moreover, the program point reached must correspond to the outcome
+  [out].  This is captured by the following [state_for_outcome] predicate. *)
+
+Inductive state_for_outcome
+           (ncont: node) (nexits: list node) (nret: node) (rret: option reg)
+           (cs: list stackframe) (c: code) (sp: val) (rs: regset) (m: mem):
+           outcome -> RTL.state -> Prop :=
+  | state_for_normal:
+      state_for_outcome ncont nexits nret rret cs c sp rs m
+                        Out_normal (State cs c sp ncont rs m)
+  | state_for_exit: forall n nexit,
+      nth_error nexits n = Some nexit ->
+      state_for_outcome ncont nexits nret rret cs c sp rs m
+                        (Out_exit n) (State cs c sp nexit rs m)
+  | state_for_return_none:
+      rret = None ->
+      state_for_outcome ncont nexits nret rret cs c sp rs m
+                        (Out_return None) (State cs c sp nret rs m)
+  | state_for_return_some: forall r v,
+      rret = Some r ->
+      rs#r = v ->
+      state_for_outcome ncont nexits nret rret cs c sp rs m
+                        (Out_return (Some v)) (State cs c sp nret rs m)
+  | state_for_return_tail: forall v,
+      state_for_outcome ncont nexits nret rret cs c sp rs m
+                        (Out_tailcall_return v) (Returnstate cs v m).
+
+Definition transl_stmt_prop 
+  (sp: val) (e: env) (m: mem) (a: stmt)
+  (t: trace) (e': env) (m': mem) (out: outcome) : Prop :=
+  forall cs code map ns ncont nexits nret rret rs
+    (MWF: map_wf map)
+    (TE: tr_stmt code map a ns ncont nexits nret rret)
+    (ME: match_env map e nil rs),
+  exists rs', exists st,
+     state_for_outcome ncont nexits nret rret cs code sp rs' m' out st
+  /\ star step tge (State cs code sp ns rs m) t st
+  /\ match_env map e' nil rs'.
+
+(** Finally, the correctness condition for the translation of functions
+  is that the translated RTL function, when applied to the same arguments
+  as the original Cminor function, returns the same value and performs
+  the same modifications on the memory state. *)
+
+Definition transl_function_prop
+    (m: mem) (f: CminorSel.fundef) (vargs: list val)
+    (t: trace) (m': mem) (vres: val) : Prop :=
+  forall cs tf
+    (TE: transl_fundef f = OK tf),
+  star step tge (Callstate cs tf vargs m) t (Returnstate cs vres m').
+
 Lemma transl_funcall_internal_correct:
   forall (m : mem) (f : CminorSel.function)
          (vargs : list val) (m1 : mem) (sp : block) (e : env) (t : trace)
@@ -911,9 +898,9 @@ Lemma transl_funcall_internal_correct:
   Mem.alloc m 0 (fn_stackspace f) = (m1, sp) ->
   set_locals (fn_vars f) (set_params vargs (CminorSel.fn_params f)) = e ->
   exec_stmt ge (Vptr sp Int.zero) e m1 (fn_body f) t e2 m2 out ->
-  transl_stmt_correct (Vptr sp Int.zero) e m1 (fn_body f) t e2 m2 out ->
+  transl_stmt_prop (Vptr sp Int.zero) e m1 (fn_body f) t e2 m2 out ->
   outcome_result_value out f.(CminorSel.fn_sig).(sig_res) vres ->
-  transl_function_correct m (Internal f) vargs t 
+  transl_function_prop m (Internal f) vargs t 
                             (outcome_free_mem out m2 sp) vres.
 Proof.
   intros; red; intros.
@@ -976,7 +963,7 @@ Qed.
 Lemma transl_funcall_external_correct:
   forall (ef : external_function) (m : mem) (args : list val) (t: trace) (res : val),
   event_match ef args t res ->
-  transl_function_correct m (External ef) args t m res.
+  transl_function_prop m (External ef) args t m res.
 Proof.
   intros; red; intros. unfold transl_function in TE; simpl in TE.
   inversion TE; subst tf. 
@@ -985,7 +972,7 @@ Qed.
 
 Lemma transl_stmt_Sskip_correct:
   forall (sp: val) (e : env) (m : mem),
-  transl_stmt_correct sp e m Sskip E0 e m Out_normal.
+  transl_stmt_prop sp e m Sskip E0 e m Out_normal.
 Proof.
   intros; red; intros; inv TE.
   exists rs; econstructor.
@@ -1008,11 +995,11 @@ Lemma transl_stmt_Sseq_continue_correct:
          (t1: trace) (e1 : env) (m1 : mem) (s2 : stmt) (t2: trace)
          (e2 : env) (m2 : mem) (out : outcome),
   exec_stmt ge sp e m s1 t1 e1 m1 Out_normal ->
-  transl_stmt_correct sp e m s1 t1 e1 m1 Out_normal ->
+  transl_stmt_prop sp e m s1 t1 e1 m1 Out_normal ->
   exec_stmt ge sp e1 m1 s2 t2 e2 m2 out ->
-  transl_stmt_correct sp e1 m1 s2 t2 e2 m2 out ->
+  transl_stmt_prop sp e1 m1 s2 t2 e2 m2 out ->
   t = t1 ** t2 ->
-  transl_stmt_correct sp e m (Sseq s1 s2) t e2 m2 out.
+  transl_stmt_prop sp e m (Sseq s1 s2) t e2 m2 out.
 Proof.
   intros; red; intros; inv TE. 
   exploit H0; eauto. intros [rs1 [st1 [OUT1 [EX1 ME1]]]]. inv OUT1. 
@@ -1027,9 +1014,9 @@ Lemma transl_stmt_Sseq_stop_correct:
   forall (sp : val) (e : env) (m : mem) (t: trace) (s1 s2 : stmt) (e1 : env)
          (m1 : mem) (out : outcome),
   exec_stmt ge sp e m s1 t e1 m1 out ->
-  transl_stmt_correct sp e m s1 t e1 m1 out ->
+  transl_stmt_prop sp e m s1 t e1 m1 out ->
   out <> Out_normal ->
-  transl_stmt_correct sp e m (Sseq s1 s2) t e1 m1 out.
+  transl_stmt_prop sp e m (Sseq s1 s2) t e1 m1 out.
 Proof.
   intros; red; intros; inv TE.
   exploit H0; eauto. intros [rs1 [st1 [OUT1 [EX1 ME1]]]].
@@ -1038,56 +1025,135 @@ Proof.
   auto.
 Qed.
 
-Lemma transl_stmt_Sexpr_correct:
-  forall (sp: val) (e : env) (m : mem) (a : expr) (t: trace)
-    (m1 : mem) (v : val),
-  eval_expr ge sp nil e m a t m1 v ->
-  transl_expr_correct sp nil e m a t m1 v ->
-  transl_stmt_correct sp e m (Sexpr a) t e m1 Out_normal.
+Lemma transl_stmt_Sassign_correct:
+  forall (sp : val) (e : env) (m : mem) (id : ident) (a : expr)
+         (v : val),
+  eval_expr ge sp e m nil a v ->
+  transl_stmt_prop sp e m (Sassign id a) E0 (PTree.set id v e) m Out_normal.
 Proof.
   intros; red; intros; inv TE.
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
-  exists rs1; econstructor. 
+  exploit transl_expr_correct; eauto.
+  intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit tr_store_var_correct; eauto. intros [rs2 [EX2 ME2]].
+  exists rs2; econstructor.
   split. constructor.
-  eauto.
+  split. eapply star_trans. eexact EX1. eexact EX2. traceEq.
+  congruence. 
 Qed.
 
-Lemma transl_stmt_Sassign_correct:
- forall (sp: val) (e : env) (m : mem) 
-    (id : ident) (a : expr) (t: trace) (m1 : mem) (v : val),
-  eval_expr ge sp nil e m a t m1 v ->
-  transl_expr_correct sp nil e m a t m1 v ->
-  transl_stmt_correct sp e m (Sassign id a) t (PTree.set id v e) m1 Out_normal.
+Lemma transl_stmt_Sstore_correct:
+  forall (sp : val) (e : env) (m : mem) (chunk : memory_chunk)
+         (addr: addressing) (al: exprlist) (b: expr)
+         (vl: list val) (v: val) (vaddr: val) (m' : mem),
+  eval_exprlist ge sp e m nil al vl ->
+  eval_expr ge sp e m nil b v ->
+  eval_addressing ge sp addr vl = Some vaddr ->
+  storev chunk m vaddr v = Some m' ->
+  transl_stmt_prop sp e m (Sstore chunk addr al b) E0 e m' Out_normal.
 Proof.
-  intros; red; intros; inv TE. 
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
-  exploit tr_move_correct; eauto. intros [rs2 [EX2 [RES2 OTHER2]]].
+  intros; red; intros; inv TE.
+  exploit transl_exprlist_correct; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit transl_expr_correct; eauto. intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
   exists rs2; econstructor.
+  (* Outcome *)
   split. constructor.
-  split. eapply star_trans. eexact EX1. eexact EX2. traceEq.
-  apply match_env_invariant with (rs1#rv <- v). 
-  apply match_env_update_var; auto. 
-  intros. rewrite Regmap.gsspec. destruct (peq r rv). 
-  subst r. congruence.
+  (* Exec *)
+  split. eapply star_trans. eexact EX1. 
+  eapply star_right. eexact EX2.
+  eapply exec_Istore; eauto.
+  assert (rs2##rl = rs1##rl).
+    apply list_map_exten. intros r' IN. symmetry. apply OTHER2. auto.
+  rewrite H3; rewrite RES1. 
+  rewrite (@eval_addressing_preserved _ _ ge tge). eexact H1.
+  exact symbols_preserved.
+  rewrite RES2. auto.
+  reflexivity. traceEq.
+  (* Match-env *)
   auto.
 Qed.
 
+Lemma transl_stmt_Scall_correct:
+  forall (sp : val) (e : env) (m : mem) (optid : option ident)
+         (sig : signature) (a : expr) (bl : exprlist) (vf : val)
+         (vargs : list val) (f : CminorSel.fundef) (t : trace) (m' : mem)
+         (vres : val) (e' : env),
+  eval_expr ge sp e m nil a vf ->
+  eval_exprlist ge sp e m nil bl vargs ->
+  Genv.find_funct ge vf = Some f ->
+  CminorSel.funsig f = sig ->
+  eval_funcall ge m f vargs t m' vres ->
+  transl_function_prop m f vargs t m' vres ->
+  e' = set_optvar optid vres e ->
+  transl_stmt_prop sp e m (Scall optid sig a bl) t e' m' Out_normal.
+Proof.
+  intros; red; intros; inv TE.
+  exploit transl_expr_correct; eauto.
+  intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit transl_exprlist_correct; eauto.
+  intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
+  exploit functions_translated; eauto. intros [tf [TFIND TF]].
+  exploit H4; eauto. intro EXF.
+  exploit (tr_store_optvar_correct (rs2#rd <- vres)); eauto.
+    apply match_env_update_temp; eauto.
+  intros [rs3 [EX3 ME3]].
+  exists rs3; econstructor.
+  (* Outcome *)
+  split. constructor.
+  (* Exec *)
+  split. eapply star_trans. eexact EX1.
+  eapply star_trans. eexact EX2. 
+  eapply star_left. eapply exec_Icall; eauto.
+  simpl. rewrite OTHER2. rewrite RES1. eauto. simpl; tauto. 
+  eapply sig_transl_function; eauto.
+  eapply star_trans. rewrite RES2. eexact EXF.
+  eapply star_left. apply exec_return.
+  eexact EX3. 
+  reflexivity. reflexivity. reflexivity. reflexivity. traceEq.
+  (* Match-env *)
+  rewrite Regmap.gss in ME3. auto.
+Qed. 
+
+Lemma transl_stmt_Salloc_correct:
+  forall (sp : val) (e : env) (m : mem) (id : ident) (a : expr)
+         (n : int) (m' : mem) (b : block),
+  eval_expr ge sp e m nil a (Vint n) ->
+  alloc m 0 (Int.signed n) = (m', b) ->
+  transl_stmt_prop sp e m (Salloc id a) E0
+                      (PTree.set id (Vptr b Int.zero) e) m' Out_normal.
+Proof.
+  intros; red; intros; inv TE.
+  exploit transl_expr_correct; eauto.
+  intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit (tr_store_var_correct (rs1#rd <- (Vptr b Int.zero))); eauto.
+    apply match_env_update_temp; eauto.
+  intros [rs2 [EX2 ME2]].
+  exists rs2; econstructor.
+  (* Outcome *)
+  split. constructor.
+  (* Execution *)
+  split. eapply star_trans. eexact EX1. 
+  eapply star_left. 2: eexact EX2. 
+  eapply exec_Ialloc; eauto. 
+  reflexivity. traceEq.
+  (* Match-env *)
+  rewrite Regmap.gss in ME2. auto.
+Qed.
+
 Lemma transl_stmt_Sifthenelse_correct:
-  forall (sp: val) (e : env) (m : mem) (a : condexpr)
-    (s1 s2 : stmt) (t t1: trace) (m1 : mem) 
-    (v1 : bool) (t2: trace) (e2 : env) (m2 : mem) (out : outcome),
-  eval_condexpr ge sp nil e m a t1 m1 v1 ->
-  transl_condition_correct sp nil e m a t1 m1 v1 ->
-  exec_stmt ge sp e m1 (if v1 then s1 else s2) t2 e2 m2 out ->
-  transl_stmt_correct sp e m1 (if v1 then s1 else s2) t2 e2 m2 out ->
-  t = t1 ** t2 ->
-  transl_stmt_correct sp e m (Sifthenelse a s1 s2) t e2 m2 out.
+  forall (sp : val) (e : env) (m : mem) (a : condexpr) (s1 s2 : stmt)
+         (v : bool) (t : trace) (e' : env) (m' : mem) (out : outcome),
+  eval_condexpr ge sp e m nil a v ->
+  exec_stmt ge sp e m (if v then s1 else s2) t e' m' out ->
+  transl_stmt_prop sp e m (if v then s1 else s2) t e' m' out ->
+  transl_stmt_prop sp e m (Sifthenelse a s1 s2) t e' m' out.
 Proof.
   intros; red; intros; inv TE.
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 OTHER1]]].
-  assert (tr_stmt code map (if v1 then s1 else s2) (if v1 then ntrue else nfalse) ncont nexits nret rret).
-    destruct v1; auto.
-  exploit H2; eauto. intros [rs2 [st2 [OUT2 [EX2 ME2]]]].
+  exploit transl_condexpr_correct; eauto.
+  intros [rs1 [EX1 [ME1 OTHER1]]].
+  assert (tr_stmt code map (if v then s1 else s2) (if v then ntrue else nfalse)
+                  ncont nexits nret rret).
+    destruct v; auto. 
+  exploit H1; eauto. intros [rs2 [st2 [OUT2 [EX2 ME2]]]].
   exists rs2; exists st2.
   split. eauto.
   split. eapply star_trans. eexact EX1. eexact EX2. auto.
@@ -1099,11 +1165,11 @@ Lemma transl_stmt_Sloop_loop_correct:
     (e1 : env) (m1 : mem) (t2: trace) (e2 : env) (m2 : mem) 
     (out : outcome),
   exec_stmt ge sp e m sl t1 e1 m1 Out_normal ->
-  transl_stmt_correct sp e m sl t1 e1 m1 Out_normal ->
+  transl_stmt_prop sp e m sl t1 e1 m1 Out_normal ->
   exec_stmt ge sp e1 m1 (Sloop sl) t2 e2 m2 out ->
-  transl_stmt_correct sp e1 m1 (Sloop sl) t2 e2 m2 out ->
+  transl_stmt_prop sp e1 m1 (Sloop sl) t2 e2 m2 out ->
   t = t1 ** t2 ->
-  transl_stmt_correct sp e m (Sloop sl) t e2 m2 out.
+  transl_stmt_prop sp e m (Sloop sl) t e2 m2 out.
 Proof.
   intros; red; intros; inversion TE. subst. 
   exploit H0; eauto. intros [rs1 [st1 [OUT1 [EX1 ME1]]]]. inv OUT1.
@@ -1120,9 +1186,9 @@ Lemma transl_stmt_Sloop_stop_correct:
   forall (sp: val) (e : env) (m : mem) (t: trace) (sl : stmt) 
     (e1 : env) (m1 : mem) (out : outcome),
   exec_stmt ge sp e m sl t e1 m1 out ->
-  transl_stmt_correct sp e m sl t e1 m1 out ->
+  transl_stmt_prop sp e m sl t e1 m1 out ->
   out <> Out_normal ->
-  transl_stmt_correct sp e m (Sloop sl) t e1 m1 out.
+  transl_stmt_prop sp e m (Sloop sl) t e1 m1 out.
 Proof.
   intros; red; intros; inv TE. 
   exploit H0; eauto. intros [rs1 [st1 [OUT1 [EX1 ME1]]]].
@@ -1135,8 +1201,8 @@ Lemma transl_stmt_Sblock_correct:
   forall (sp: val) (e : env) (m : mem) (sl : stmt) (t: trace)
     (e1 : env) (m1 : mem) (out : outcome),
   exec_stmt ge sp e m sl t e1 m1 out ->
-  transl_stmt_correct sp e m sl t e1 m1 out ->
-  transl_stmt_correct sp e m (Sblock sl) t e1 m1 (outcome_block out).
+  transl_stmt_prop sp e m sl t e1 m1 out ->
+  transl_stmt_prop sp e m (Sblock sl) t e1 m1 (outcome_block out).
 Proof.
   intros; red; intros; inv TE.
   exploit H0; eauto. intros [rs1 [st1 [OUT1 [EX1 ME1]]]].
@@ -1150,7 +1216,7 @@ Qed.
 
 Lemma transl_stmt_Sexit_correct:
   forall (sp: val) (e : env) (m : mem) (n : nat),
-  transl_stmt_correct sp e m (Sexit n) E0 e m (Out_exit n).
+  transl_stmt_prop sp e m (Sexit n) E0 e m (Out_exit n).
 Proof.
   intros; red; intros; inv TE.
   exists rs; econstructor.
@@ -1195,26 +1261,25 @@ Qed.
 
 Lemma transl_stmt_Sswitch_correct:
   forall (sp : val) (e : env) (m : mem) (a : expr)
-         (cases : list (int * nat)) (default : nat) 
-         (t1 : trace) (m1 : mem) (n : int),
-  eval_expr ge sp nil e m a t1 m1 (Vint n) ->
-  transl_expr_correct sp nil e m a t1 m1 (Vint n) ->
-  transl_stmt_correct sp e m (Sswitch a cases default) t1 e m1
+         (cases : list (int * nat)) (default : nat) (n : int),
+  eval_expr ge sp e m nil a (Vint n) ->
+  transl_stmt_prop sp e m (Sswitch a cases default) E0 e m
          (Out_exit (switch_target n default cases)).
 Proof.
   intros; red; intros; inv TE.
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit transl_expr_correct; eauto. 
+  intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
   exploit transl_switch_correct; eauto. intros [nd [EX2 MO2]].
   exists rs1; econstructor.
   split. econstructor. 
-  rewrite (validate_switch_correct _ _ _ H4 n). eauto.  
+  rewrite (validate_switch_correct _ _ _ H3 n). eauto.  
   split. eapply star_trans. eexact EX1. eexact EX2. traceEq.
   auto.
 Qed.
 
 Lemma transl_stmt_Sreturn_none_correct:
   forall (sp: val) (e : env) (m : mem),
-  transl_stmt_correct sp e m (Sreturn None) E0 e m (Out_return None).
+  transl_stmt_prop sp e m (Sreturn None) E0 e m (Out_return None).
 Proof.
   intros; red; intros; inv TE.
   exists rs; econstructor.
@@ -1224,14 +1289,13 @@ Proof.
 Qed.
 
 Lemma transl_stmt_Sreturn_some_correct:
-  forall (sp: val) (e : env) (m : mem) (a : expr) (t: trace)
-    (m1 : mem) (v : val),
-  eval_expr ge sp nil e m a t m1 v ->
-  transl_expr_correct sp nil e m a t m1 v ->
-  transl_stmt_correct sp e m (Sreturn (Some a)) t e m1 (Out_return (Some v)).
+  forall (sp : val) (e : env) (m : mem) (a : expr) (v : val),
+  eval_expr ge sp e m nil a v ->
+  transl_stmt_prop sp e m (Sreturn (Some a)) E0 e m (Out_return (Some v)).
 Proof.
   intros; red; intros; inv TE. 
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit transl_expr_correct; eauto.
+  intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
   exists rs1; econstructor.
   split. econstructor. reflexivity. auto.
   eauto.
@@ -1239,26 +1303,22 @@ Qed.
 
 Lemma transl_stmt_Stailcall_correct:
   forall (sp : block) (e : env) (m : mem) (sig : signature) (a : expr)
-         (bl : exprlist) (t t1 : trace) (m1 : mem) (t2 : trace) (m2 : mem)
-         (t3 : trace) (m3 : mem) (vf : val) (vargs : list val) (vres : val)
-         (f : CminorSel.fundef),
-  eval_expr ge (Vptr sp Int.zero) nil e m a t1 m1 vf ->
-  transl_expr_correct (Vptr sp Int.zero) nil e m a t1 m1 vf ->
-  eval_exprlist ge (Vptr sp Int.zero) nil e m1 bl t2 m2 vargs ->
-  transl_exprlist_correct (Vptr sp Int.zero) nil e m1 bl t2 m2 vargs ->
+         (bl : exprlist) (vf : val) (vargs : list val) (f : CminorSel.fundef)
+         (t : trace) (m' : mem) (vres : val),
+  eval_expr ge (Vptr sp Int.zero) e m nil a vf ->
+  eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
   Genv.find_funct ge vf = Some f ->
   CminorSel.funsig f = sig ->
-  eval_funcall ge (free m2 sp) f vargs t3 m3 vres ->
-  transl_function_correct (free m2 sp) f vargs t3 m3 vres ->
-  t = t1 ** t2 ** t3 ->
-  transl_stmt_correct (Vptr sp Int.zero) e m (Stailcall sig a bl)
-                                       t e m3 (Out_tailcall_return vres).
+  eval_funcall ge (free m sp) f vargs t m' vres ->
+  transl_function_prop (free m sp) f vargs t m' vres ->
+  transl_stmt_prop (Vptr sp Int.zero) e m (Stailcall sig a bl) t e
+          m' (Out_tailcall_return vres).
 Proof.
   intros; red; intros; inv TE.
-  exploit H0; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
-  exploit H2; eauto. intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
+  exploit transl_expr_correct; eauto. intros [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  exploit transl_exprlist_correct; eauto. intros [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
   exploit functions_translated; eauto. intros [tf [TFIND TF]].
-  exploit H6; eauto. intro EXF.
+  exploit H4; eauto. intro EXF.
   exists rs2; econstructor. 
   split. constructor. 
   split. 
@@ -1274,41 +1334,25 @@ Proof.
 Qed.
 
 (** The correctness of the translation then follows by application
-  of the mutual induction principle for CminorSel evaluation derivations
+  of the mutual induction principle for Cminor evaluation derivations
   to the lemmas above. *)
 
-Theorem transl_function_correctness:
+Theorem transl_function_correct:
   forall m f vargs t m' vres,
   eval_funcall ge m f vargs t m' vres ->
-  transl_function_correct m f vargs t m' vres.
+  transl_function_prop m f vargs t m' vres.
 Proof
-  (eval_funcall_ind5 ge
-    transl_expr_correct
-    transl_condition_correct
-    transl_exprlist_correct
-    transl_function_correct
-    transl_stmt_correct
-
-    transl_expr_Evar_correct
-    transl_expr_Eop_correct
-    transl_expr_Eload_correct
-    transl_expr_Estore_correct
-    transl_expr_Ecall_correct
-    transl_expr_Econdition_correct
-    transl_expr_Elet_correct
-    transl_expr_Eletvar_correct
-    transl_expr_Ealloc_correct
-    transl_condition_CEtrue_correct
-    transl_condition_CEfalse_correct
-    transl_condition_CEcond_correct
-    transl_condition_CEcondition_correct
-    transl_exprlist_Enil_correct
-    transl_exprlist_Econs_correct
+  (eval_funcall_ind2 ge
+    transl_function_prop
+    transl_stmt_prop
+
     transl_funcall_internal_correct
     transl_funcall_external_correct
     transl_stmt_Sskip_correct
-    transl_stmt_Sexpr_correct
     transl_stmt_Sassign_correct
+    transl_stmt_Sstore_correct
+    transl_stmt_Scall_correct
+    transl_stmt_Salloc_correct
     transl_stmt_Sifthenelse_correct
     transl_stmt_Sseq_continue_correct
     transl_stmt_Sseq_stop_correct
@@ -1321,21 +1365,171 @@ Proof
     transl_stmt_Sreturn_some_correct
     transl_stmt_Stailcall_correct).
 
-Require Import Smallstep.
+Theorem transl_stmt_correct:
+  forall sp e m s t e' m' out,
+  exec_stmt ge sp e m s t e' m' out ->
+  transl_stmt_prop sp e m s t e' m' out.
+Proof
+  (exec_stmt_ind2 ge
+    transl_function_prop
+    transl_stmt_prop
+
+    transl_funcall_internal_correct
+    transl_funcall_external_correct
+    transl_stmt_Sskip_correct
+    transl_stmt_Sassign_correct
+    transl_stmt_Sstore_correct
+    transl_stmt_Scall_correct
+    transl_stmt_Salloc_correct
+    transl_stmt_Sifthenelse_correct
+    transl_stmt_Sseq_continue_correct
+    transl_stmt_Sseq_stop_correct
+    transl_stmt_Sloop_loop_correct
+    transl_stmt_Sloop_stop_correct
+    transl_stmt_Sblock_correct
+    transl_stmt_Sexit_correct
+    transl_stmt_Sswitch_correct
+    transl_stmt_Sreturn_none_correct
+    transl_stmt_Sreturn_some_correct
+    transl_stmt_Stailcall_correct).
 
-(** The correctness of the translation follows: if the original CminorSel
-  program executes with trace [t] and exit code [r], then the generated
-  RTL program terminates with the same trace and exit code. *)
+(** ** Semantic preservation for the translation of divering statements *)   
+
+Fixpoint size_stmt (s: stmt) : nat :=
+  match s with
+  | Sseq s1 s2 => (1 + size_stmt s1 + size_stmt s2)%nat
+  | Sifthenelse e s1 s2 => (1 + size_stmt s1 + size_stmt s2)%nat
+  | Sloop s1 => (1 + size_stmt s1)%nat
+  | Sblock s1 => (1 + size_stmt s1)%nat
+  | _ => 1%nat
+  end.
+
+Theorem transl_function_correct_divergence:
+  forall m fd vargs t tfd cs,
+  evalinf_funcall ge m fd vargs t ->
+  transl_fundef fd = OK tfd ->
+  forever_N step tge O (Callstate cs tfd vargs m) t.
+Proof.
+  cofix FUNCALL.
+  assert (STMT: forall sp e m s t,
+     execinf_stmt ge sp e m s t ->
+     forall cs code map ns ncont nexits nret rret rs
+       (MWF: map_wf map)
+       (TE: tr_stmt code map s ns ncont nexits nret rret)
+       (ME: match_env map e nil rs),
+     forever_N step tge (size_stmt s) (State cs code sp ns rs m) t).
+  cofix STMT; intros. 
+  inv H; inversion TE; subst.
+  (* Scall *)
+  destruct (transl_expr_correct _ _ _ _ _ _ H0
+              cs _ _ _ _ _ _ _ MWF H7 ME)
+  as [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  destruct (transl_exprlist_correct _ _ _ _ _ _ H1
+              cs _ _ _ _ _ _ _ MWF H8 ME1)
+  as [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
+  destruct (functions_translated _ _ H2) as [tf [TFIND TF]].
+  eapply forever_N_star with (p := O).
+  eapply star_trans. eexact EX1. eexact EX2. reflexivity.
+  simpl; omega. 
+  eapply forever_N_plus with (p := O).
+  apply plus_one. eapply exec_Icall; eauto. 
+  simpl. rewrite OTHER2. rewrite RES1. eauto. simpl; tauto. 
+  eapply sig_transl_function; eauto.
+  eapply FUNCALL. rewrite RES2. eexact H4. assumption.
+  reflexivity. traceEq.    
+  (* Sifthenelse *)
+  destruct (transl_condexpr_correct _ _ _ _ _ _ H0
+              cs _ _ _ _ _ _ _ MWF H11 ME)
+  as [rs1 [EX1 [ME1 OTHER1]]].
+  eapply forever_N_star with (p := size_stmt (if v then s1 else s2)).
+  eexact EX1. destruct v; simpl; omega.
+  eapply STMT. eexact H1. eauto. destruct v; eauto. eauto.
+  traceEq. 
+  (* Sseq, 1 *)
+  eapply forever_N_star with (p := size_stmt s1).
+  apply star_refl. simpl; omega.
+  eapply STMT; eauto.
+  traceEq.
+  (* Sseq, 2 *)
+  destruct (transl_stmt_correct _ _ _ _ _ _ _ _ H0
+              cs _ _ _ _ _ _ _ _ MWF H9 ME)
+  as [rs1 [st1 [OUT1 [EX1 ME1]]]].
+  inv OUT1. 
+  eapply forever_N_star with (p := size_stmt s2).
+  eexact EX1. simpl; omega.
+  eapply STMT; eauto.
+  traceEq.
+  (* Sloop, body *)
+  eapply forever_N_star with (p := size_stmt s0).
+  apply star_refl. simpl; omega.
+  eapply STMT; eauto.
+  traceEq.
+  (* Sloop, loop *)
+  destruct (transl_stmt_correct _ _ _ _ _ _ _ _ H0
+              cs _ _ _ _ _ _ _ _ MWF H2 ME)
+  as [rs1 [st1 [OUT1 [EX1 ME1]]]].
+  inv OUT1. 
+  eapply forever_N_plus with (p := size_stmt (Sloop s0)).
+  eapply plus_right. eexact EX1. eapply exec_Inop; eauto. reflexivity.
+  eapply STMT; eauto.
+  traceEq. 
+  (* Sblock *)
+  eapply forever_N_star with (p := size_stmt s0).
+  apply star_refl. simpl; omega.
+  eapply STMT; eauto.
+  traceEq.
+  (* Stailcall *)
+  destruct (transl_expr_correct _ _ _ _ _ _ H0
+              cs _ _ _ _ _ _ _ MWF H6 ME)
+  as [rs1 [EX1 [ME1 [RES1 OTHER1]]]].
+  destruct (transl_exprlist_correct _ _ _ _ _ _ H1
+              cs _ _ _ _ _ _ _ MWF H12 ME1)
+  as [rs2 [EX2 [ME2 [RES2 OTHER2]]]].
+  destruct (functions_translated _ _ H2) as [tf [TFIND TF]].
+  eapply forever_N_star with (p := O).
+  eapply star_trans. eexact EX1. eexact EX2. reflexivity.
+  simpl; omega. 
+  eapply forever_N_plus with (p := O).
+  apply plus_one. eapply exec_Itailcall; eauto. 
+  simpl. rewrite OTHER2. rewrite RES1. eauto. simpl; tauto. 
+  eapply sig_transl_function; eauto.
+  eapply FUNCALL. rewrite RES2. eexact H4. assumption.
+  reflexivity. traceEq.
+  (* funcall *)
+  intros. inversion H. subst m0 fd vargs0 t0. 
+  generalize H0; simpl. caseEq (transl_function f); simpl. 2: congruence.
+  intros tfi EQ1 EQ2. injection EQ2; clear EQ2; intro EQ2.
+  assert (TR: tr_function f tfi). apply transl_function_charact; auto.
+  rewrite <- EQ2. inversion TR. subst f0. 
+  pose (rs := init_regs vargs rparams).
+  assert (ME: match_env map2 e nil rs).
+  rewrite <- H2. unfold rs. 
+  eapply match_init_env_init_reg; eauto.
+  assert (MWF: map_wf map2).
+    assert (map_valid init_mapping init_state) by apply init_mapping_valid.
+    exploit (add_vars_valid (CminorSel.fn_params f)); eauto. intros [A B].
+    eapply add_vars_wf; eauto. eapply add_vars_wf; eauto. apply init_mapping_wf.
+  eapply forever_N_plus with (p := size_stmt (fn_body f)).
+  apply plus_one. eapply exec_function_internal; eauto.
+  simpl. eapply STMT; eauto.
+  traceEq.
+Qed.
+
+(** ** Semantic preservation for whole programs. *)
+
+(** The correctness of the translation follows: 
+  if the original Cminor program executes with observable behavior [beh],
+  then the generated RTL program executes with the same behavior. *)
 
 Theorem transl_program_correct:
-  forall (t: trace) (r: int),
-  CminorSel.exec_program prog t (Vint r) ->
-  RTL.exec_program tprog (Terminates t r).
+  forall (beh: program_behavior),
+  CminorSel.exec_program prog beh ->
+  RTL.exec_program tprog beh.
 Proof.
-  intros t r [b [f [m [SYMB [FUNC [SIG EVAL]]]]]].
-  generalize (function_ptr_translated _ _ FUNC).
-  intros [tf [TFIND TRANSLF]].
-  exploit transl_function_correctness; eauto. intro EX.
+  intros. inv H.
+  (* termination *)
+  exploit function_ptr_translated; eauto. intros [tf [TFIND TRANSLF]].
+  exploit transl_function_correct; eauto. intro EX.
   econstructor.
   econstructor. 
   rewrite symbols_preserved. 
@@ -1347,6 +1541,20 @@ Proof.
   unfold fundef; rewrite (Genv.init_mem_transf_partial transl_fundef prog TRANSL).
   eexact EX. 
   constructor.
+  (* divergence *)
+  exploit function_ptr_translated; eauto. intros [tf [TFIND TRANSLF]].
+  exploit transl_function_correct_divergence; eauto. intro EX.
+  econstructor.
+  econstructor. 
+  rewrite symbols_preserved. 
+  replace (prog_main tprog) with (prog_main prog). eauto.
+  symmetry; apply transform_partial_program_main with transl_fundef.
+  exact TRANSL.
+  eexact TFIND.
+  generalize (sig_transl_function _ _ TRANSLF). congruence.
+  eapply forever_N_forever. 
+  unfold fundef; rewrite (Genv.init_mem_transf_partial transl_fundef prog TRANSL).
+  eexact EX. 
 Qed.
 
 End CORRECTNESS.
diff --git a/backend/RTLgenspec.v b/backend/RTLgenspec.v
index c46bdbbaf..a291d3219 100644
--- a/backend/RTLgenspec.v
+++ b/backend/RTLgenspec.v
@@ -799,17 +799,6 @@ Inductive tr_expr (c: code):
       c!n1 = Some (Iload chunk addr rl rd nd) ->
       ~reg_in_map map rd -> ~In rd pr ->
       tr_expr c map pr (Eload chunk addr al) ns nd rd
-  | tr_Estore: forall map pr chunk addr al b ns nd rd n1 rl n2,
-      tr_exprlist c map pr al ns n1 rl ->
-      tr_expr c map (rl ++ pr) b n1 n2 rd ->
-      c!n2 = Some (Istore chunk addr rl rd nd) ->
-      tr_expr c map pr (Estore chunk addr al b) ns nd rd
-  | tr_Ecall: forall map pr sig b cl ns nd rd n1 rf n2 rargs,
-      tr_expr c map pr b ns n1 rf ->
-      tr_exprlist c map (rf :: pr) cl n1 n2 rargs ->
-      c!n2 = Some (Icall sig (inl _ rf) rargs rd nd) ->
-      ~reg_in_map map rd -> ~In rd pr ->
-      tr_expr c map pr (Ecall sig b cl) ns nd rd
   | tr_Econdition: forall map pr b ifso ifnot ns nd rd ntrue nfalse,
       tr_condition c map pr b ns ntrue nfalse ->
       tr_expr c map pr ifso ntrue nd rd ->
@@ -825,13 +814,8 @@ Inductive tr_expr (c: code):
       (rd = r \/ ~reg_in_map map rd /\ ~In rd pr) ->
       tr_move c ns r nd rd ->
       tr_expr c map pr (Eletvar n) ns nd rd
-  | tr_Ealloc: forall map pr a ns nd rd n1 r,
-      tr_expr c map pr a ns n1 r ->
-      c!n1 = Some (Ialloc r rd nd) ->
-      ~reg_in_map map rd -> ~In rd pr ->
-      tr_expr c map pr (Ealloc a) ns nd rd
 
-(** [tr_expr c map pr cond ns ntrue nfalse rd] holds if the graph [c],
+(** [tr_condition c map pr cond ns ntrue nfalse rd] holds if the graph [c],
   starting at node [ns], contains instructions that compute the truth
   value of the Cminor conditional expression [cond] and terminate
   on node [ntrue] if the condition holds and on node [nfalse] otherwise. *)
@@ -866,6 +850,19 @@ with tr_exprlist (c: code):
       tr_exprlist c map (r1 :: pr) al n1 nd rl ->
       tr_exprlist c map pr (Econs a1 al) ns nd (r1 :: rl).
 
+(** Auxiliary for the compilation of variable assignments. *)
+
+Definition tr_store_var (c: code) (map: mapping)
+                        (rs: reg) (id: ident) (ns nd: node): Prop :=
+  exists rv, map.(map_vars)!id = Some rv /\ tr_move c ns rs nd rv.
+
+Definition tr_store_optvar (c: code) (map: mapping)
+                 (rs: reg) (optid: option ident) (ns nd: node): Prop :=
+  match optid with
+  | None => ns = nd
+  | Some id => tr_store_var c map rs id ns nd
+  end.
+
 (** Auxiliary for the compilation of [switch] statements. *)
 
 Inductive tr_switch
@@ -898,14 +895,28 @@ Inductive tr_stmt (c: code) (map: mapping):
      stmt -> node -> node -> list node -> node -> option reg -> Prop :=
   | tr_Sskip: forall ns nexits nret rret,
      tr_stmt c map Sskip ns ns nexits nret rret
-  | tr_Sexpr: forall a ns nd nexits nret rret r,
-     tr_expr c map nil a ns nd r ->
-     tr_stmt c map (Sexpr a) ns nd nexits nret rret
-  | tr_Sassign: forall id a ns nd nexits nret rret rv rt n,
-     map.(map_vars)!id = Some rv ->
-     tr_move c n rt nd rv ->
+  | tr_Sassign: forall id a ns nd nexits nret rret rt n,
      tr_expr c map nil a ns n rt ->
+     tr_store_var c map rt id n nd ->
      tr_stmt c map (Sassign id a) ns nd nexits nret rret
+  | tr_Sstore: forall chunk addr al b ns nd nexits nret rret rd n1 rl n2,
+     tr_exprlist c map nil al ns n1 rl ->
+     tr_expr c map rl b n1 n2 rd ->
+     c!n2 = Some (Istore chunk addr rl rd nd) ->
+     tr_stmt c map (Sstore chunk addr al b) ns nd nexits nret rret
+  | tr_Scall: forall optid sig b cl ns nd nexits nret rret rd n1 rf n2 n3 rargs,
+     tr_expr c map nil b ns n1 rf ->
+     tr_exprlist c map (rf :: nil) cl n1 n2 rargs ->
+     c!n2 = Some (Icall sig (inl _ rf) rargs rd n3) ->
+     tr_store_optvar c map rd optid n3 nd ->
+     ~reg_in_map map rd ->
+     tr_stmt c map (Scall optid sig b cl) ns nd nexits nret rret
+  | tr_Salloc: forall id a ns nd nexits nret rret rd n1 n2 r,
+     tr_expr c map nil a ns n1 r ->
+     c!n1 = Some (Ialloc r rd n2) ->
+     tr_store_var c map rd id n2 nd ->
+     ~reg_in_map map rd ->
+     tr_stmt c map (Salloc id a) ns nd nexits nret rret
   | tr_Sseq: forall s1 s2 ns nd nexits nret rret n,
      tr_stmt c map s2 n nd nexits nret rret ->
      tr_stmt c map s1 ns n nexits nret rret ->
@@ -975,10 +986,10 @@ Definition tr_expr_condition_exprlist_ind3
   (P : mapping -> list reg -> expr -> node -> node -> reg -> Prop)
   (P0 : mapping -> list reg -> condexpr -> node -> node -> node -> Prop)
   (P1 : mapping -> list reg -> exprlist -> node -> node -> list reg -> Prop) :=
-  fun a b c' d e f g h i j k l m n o =>
-  conj (tr_expr_ind3 c P P0 P1 a b c' d e f g h i j k l m n o)
-       (conj (tr_condition_ind3 c P P0 P1 a b c' d e f g h i j k l m n o)
-             (tr_exprlist_ind3 c P P0 P1 a b c' d e f g h i j k l m n o)).
+  fun a b c' d e f g h i j k l =>
+  conj (tr_expr_ind3 c P P0 P1 a b c' d e f g h i j k l)
+       (conj (tr_condition_ind3 c P P0 P1 a b c' d e f g h i j k l)
+             (tr_exprlist_ind3 c P P0 P1 a b c' d e f g h i j k l)).
 
 Lemma tr_move_extends:
   forall s1 s2, state_extends s1 s2 ->
@@ -1048,10 +1059,10 @@ Scheme expr_ind3 := Induction for expr Sort Prop
 
 Definition expr_condexpr_exprlist_ind 
     (P1: expr -> Prop) (P2: condexpr -> Prop) (P3: exprlist -> Prop) :=
-  fun a b c d e f g h i j k l m n o =>
-  conj (expr_ind3 P1 P2 P3 a b c d e f g h i j k l m n o)
-    (conj (condexpr_ind3 P1 P2 P3 a b c d e f g h i j k l m n o)
-          (exprlist_ind3 P1 P2 P3 a b c d e f g h i j k l m n o)).
+  fun a b c d e f g h i j k l =>
+  conj (expr_ind3 P1 P2 P3 a b c d e f g h i j k l)
+    (conj (condexpr_ind3 P1 P2 P3 a b c d e f g h i j k l)
+          (exprlist_ind3 P1 P2 P3 a b c d e f g h i j k l)).
 
 Lemma add_move_charact:
   forall s ns rs nd rd s',
@@ -1109,49 +1120,6 @@ Proof.
   split. econstructor; eauto.
   eapply instr_at_incr; eauto.
   apply state_incr_trans with s1; eauto with rtlg.
-  (* Estore *)
-  inv OK.
-  assert (state_incr s s1). eauto with rtlg. 
-  exploit (H0 _ _ _ _ _ _ (x ++ pr) EQ0).
-  eauto with rtlg.
-  apply target_reg_ok_append. constructor; auto. 
-  intros. exploit alloc_regs_fresh_or_in_map; eauto.
-  intros [A|B]. auto. right. apply sym_not_equal.
-  eapply valid_fresh_different; eauto with rtlg. 
-  red; intros. elim (in_app_or _ _ _ H4); intro. 
-  exploit alloc_regs_valid; eauto with rtlg.
-  generalize (VALID _ H5). eauto with rtlg. 
-  eauto with rtlg. 
-  intros [A B].
-  exploit (H _ _ _ _ _ _ pr EQ3); eauto with rtlg. 
-  intros [C D].
-  split. econstructor; eauto.
-  apply tr_expr_incr with s2; eauto with rtlg. 
-  apply instr_at_incr with s1; eauto with rtlg. 
-  eauto with rtlg.
-  (* Ecall *)
-  inv OK.
-  assert (state_incr s0 s3).
-    apply state_incr_trans with s1. eauto with rtlg.
-    apply state_incr_trans with s2; eauto with rtlg.
-  assert (regs_valid (x :: pr) s1).
-    apply regs_valid_cons; eauto with rtlg. 
-  exploit (H0 _ _ _ _ _ _ (x :: pr) EQ2).
-  eauto with rtlg. 
-  apply alloc_regs_target_ok with s1 s2; eauto with rtlg.
-  eauto with rtlg.
-  apply regs_valid_incr with s2; eauto with rtlg.
-  intros [A B].
-  exploit (H _ _ _ _ _ _ pr EQ4).
-  eauto with rtlg.
-  eauto with rtlg.
-  apply regs_valid_incr with s0; eauto with rtlg.
-  apply reg_valid_incr with s1; eauto with rtlg.
-  intros [C D].
-  split. econstructor; eauto.
-  apply tr_exprlist_incr with s4; eauto.
-  apply instr_at_incr with s3; eauto with rtlg. 
-  eauto with rtlg.
   (* Econdition *)
   inv OK.
   exploit (H1 _ _ _ _ _ _ pr EQ); eauto with rtlg.
@@ -1192,13 +1160,6 @@ Proof.
     inv OK. left; congruence. right; eauto.
   auto.
   monadInv EQ1.
-  (* Ealloc *)
-  inv OK. 
-  exploit (H _ _ _ _ _ _ pr EQ2); eauto with rtlg.
-  intros [A B].
-  split. econstructor; eauto.
-  eapply instr_at_incr; eauto.
-  apply state_incr_trans with s1; eauto with rtlg.
 
   (* CEtrue *)
   split. constructor. auto with rtlg.
@@ -1264,6 +1225,27 @@ Proof.
   intros. eapply B; eauto with rtlg.
 Qed.
 
+Lemma tr_store_var_extends:
+  forall s1 s2, state_extends s1 s2 ->
+  forall map rs id ns nd,
+  tr_store_var s1.(st_code) map rs id ns nd ->
+  tr_store_var s2.(st_code) map rs id ns nd.
+Proof.
+  intros. destruct H0 as [rv [A B]]. 
+  econstructor; split. eauto. eapply tr_move_extends; eauto.
+Qed.
+ 
+Lemma tr_store_optvar_extends:
+  forall s1 s2, state_extends s1 s2 ->
+  forall map rs optid ns nd,
+  tr_store_optvar s1.(st_code) map rs optid ns nd ->
+  tr_store_optvar s2.(st_code) map rs optid ns nd.
+Proof.
+  intros until nd. destruct optid; simpl. 
+  apply tr_store_var_extends; auto.
+  auto.
+Qed.
+
 Lemma tr_switch_extends:
   forall s1 s2, state_extends s1 s2 ->
   forall r nexits t ns,
@@ -1284,8 +1266,9 @@ Proof.
   intros s1 s2 EXT.
   destruct (tr_expr_condition_exprlist_extends s1 s2 EXT) as [A [B C]].
   pose (AT := fun pc i => instr_at_extends s1 s2 pc i EXT).
+  pose (STV := tr_store_var_extends s1 s2 EXT).
+  pose (STOV := tr_store_optvar_extends s1 s2 EXT).
   induction 1; econstructor; eauto.
-  eapply tr_move_extends; eauto.
   eapply tr_switch_extends; eauto.
 Qed.
 
@@ -1298,6 +1281,28 @@ Proof.
   intros. eapply tr_stmt_extends; eauto with rtlg.
 Qed.
 
+
+Lemma store_var_charact:
+  forall map rs id nd s ns s',
+  store_var map rs id nd s = OK ns s' ->
+  tr_store_var s'.(st_code) map rs id ns nd /\ state_incr s s'.
+Proof.
+  intros. monadInv H. generalize EQ. unfold find_var.
+  caseEq ((map_vars map)!id). 2: intros; discriminate. intros. monadInv EQ1.
+  exploit add_move_charact; eauto. intros [A B]. 
+  split; auto. exists x; auto.
+Qed.
+
+Lemma store_optvar_charact:
+  forall map rs optid nd s ns s',
+  store_optvar map rs optid nd s = OK ns s' ->
+  tr_store_optvar s'.(st_code) map rs optid ns nd /\ state_incr s s'.
+Proof.
+  intros. destruct optid; simpl in H; simpl.
+  eapply store_var_charact; eauto.
+  monadInv H. split. auto. apply state_incr_refl. 
+Qed. 
+
 Lemma transl_exit_charact:
   forall nexits n s ne s',
   transl_exit nexits n s = OK ne s' ->
@@ -1344,18 +1349,85 @@ Proof.
   induction stmt; intros; simpl in TR; try (monadInv TR).
   (* Sskip *)
   split. constructor. auto with rtlg.
-  (* Sexpr *)
-  exploit transl_expr_charact; eauto with rtlg. intros [A B].
-  split. econstructor; eauto. eauto with rtlg.
   (* Sassign *)
-  exploit add_move_charact; eauto. intros [A B].
+  exploit store_var_charact; eauto. intros [A B].
   exploit transl_expr_charact; eauto with rtlg. 
-    apply map_valid_incr with s; eauto with rtlg. 
   intros [C D].
-  generalize EQ. unfold find_var. caseEq (map_vars map)!i; intros; inv EQ2.
   split. econstructor; eauto.
-  apply tr_move_extends with s2; eauto with rtlg.
+  apply tr_store_var_extends with s1; eauto with rtlg.
   eauto with rtlg. 
+  (* Sstore *)
+  assert (state_incr s s1). eauto with rtlg.
+  assert (state_incr s s2). eauto with rtlg.
+  assert (map_valid map s2). eauto with rtlg. 
+  destruct transl_expr_condexpr_list_charact as [P1 [P2 P3]].
+  exploit (P1 _ _ _ _ _ _ _ x EQ2).
+    auto.
+    eapply alloc_reg_target_ok with (s1 := s0); eauto with rtlg.  
+    apply regs_valid_incr with s0; eauto with rtlg. 
+    apply reg_valid_incr with s1; eauto with rtlg.
+  intros [A B].
+  exploit (P3 _ _ _ _ _ _ _ nil EQ4).
+    apply map_valid_incr with s2; auto.
+    eapply alloc_regs_target_ok with (s1 := s); eauto with rtlg.
+    auto with rtlg.
+    apply regs_valid_incr with s0; eauto with rtlg. 
+  intros [C D].
+  split. econstructor; eauto.
+  apply tr_expr_incr with s3; eauto with rtlg. 
+  apply instr_at_incr with s2; eauto with rtlg.
+  eauto with rtlg.
+  (* Scall *)
+  assert (state_incr s0 s3).
+    apply state_incr_trans with s1. eauto with rtlg.
+    apply state_incr_trans with s2; eauto with rtlg.
+  exploit store_optvar_charact; eauto. intros [A B].
+  assert (state_incr s0 s5) by eauto with rtlg.
+  destruct transl_expr_condexpr_list_charact as [P1 [P2 P3]].
+  exploit (P3 _ _ _ _ _ _ _ (x :: nil) EQ4).
+    apply map_valid_incr with s0; auto.
+    eapply alloc_regs_target_ok with (s1 := s1); eauto with rtlg.
+    apply regs_valid_cons; eauto with rtlg.
+    apply regs_valid_incr with s1. 
+    apply state_incr_trans with s3; eauto with rtlg. 
+    apply regs_valid_cons; eauto with rtlg.
+    apply regs_valid_incr with s2.
+    apply state_incr_trans with s3; eauto with rtlg.
+    eauto with rtlg.
+  intros [C D].
+  exploit (P1 _ _ _ _ _ _ _ nil EQ6).
+    apply map_valid_incr with s0; eauto with rtlg.
+    eapply alloc_reg_target_ok with (s1 := s0); eauto with rtlg.
+    auto with rtlg.
+    apply reg_valid_incr with s1.
+    apply state_incr_trans with s3; eauto with rtlg. 
+    eauto with rtlg.
+  intros [E F].
+  split. econstructor; eauto. 
+  apply tr_exprlist_incr with s6; eauto. 
+  apply instr_at_incr with s5; eauto with rtlg.
+  apply tr_store_optvar_extends with s4; eauto with rtlg.
+  red; intro.
+  apply valid_fresh_absurd with x1 s2. 
+  apply reg_valid_incr with s0; eauto with rtlg. 
+  eauto with rtlg.
+  eauto with rtlg.
+  (* Salloc *)
+  exploit store_var_charact; eauto. intros [A B].
+  exploit transl_expr_charact; eauto.
+    apply map_valid_incr with s; auto.
+    apply state_incr_trans with s1; eauto with rtlg.
+    eapply alloc_reg_target_ok with (s1 := s); eauto with rtlg.
+    apply reg_valid_incr with s0; eauto with rtlg.
+  intros [C D].
+  split. econstructor; eauto.
+  apply instr_at_incr with s3; eauto with rtlg.
+  apply tr_store_var_extends with s2; eauto with rtlg.
+  red; intro.
+  apply valid_fresh_absurd with x0 s0. 
+  apply reg_valid_incr with s; eauto with rtlg. 
+  eauto with rtlg.
+  apply state_incr_trans with s2; eauto with rtlg. 
   (* Sseq *)
   exploit IHstmt2; eauto with rtlg. intros [A B].
   exploit IHstmt1; eauto with rtlg. intros [C D].
diff --git a/backend/Selection.v b/backend/Selection.v
index c98e55e4f..0183ee7d9 100644
--- a/backend/Selection.v
+++ b/backend/Selection.v
@@ -38,16 +38,11 @@ Fixpoint lift_expr (p: nat) (a: expr) {struct a}: expr :=
   | Evar id => Evar id
   | Eop op bl => Eop op (lift_exprlist p bl)
   | Eload chunk addr bl => Eload chunk addr (lift_exprlist p bl)
-  | Estore chunk addr bl c =>
-      Estore chunk addr (lift_exprlist p bl) (lift_expr p c)
-  | Ecall sig b cl => Ecall sig (lift_expr p b) (lift_exprlist p cl)
   | Econdition b c d =>
       Econdition (lift_condexpr p b) (lift_expr p c) (lift_expr p d)
   | Elet b c => Elet (lift_expr p b) (lift_expr (S p) c)
   | Eletvar n =>
       if le_gt_dec p n then Eletvar (S n) else Eletvar n
-  | Ealloc b =>
-      Ealloc (lift_expr p b)
   end
 
 with lift_condexpr (p: nat) (a: condexpr) {struct a}: condexpr :=
@@ -981,7 +976,7 @@ Definition load (chunk: memory_chunk) (e1: expr) :=
 
 Definition store (chunk: memory_chunk) (e1 e2: expr) :=
   match addressing e1 with
-  | (mode, args) => Estore chunk mode args e2
+  | (mode, args) => Sstore chunk mode args e2
   end.
 
 (** * Translation from Cminor to CminorSel *)
@@ -1046,20 +1041,15 @@ Fixpoint sel_expr (a: Cminor.expr) : expr :=
   | Cminor.Eunop op arg => sel_unop op (sel_expr arg)
   | Cminor.Ebinop op arg1 arg2 => sel_binop op (sel_expr arg1) (sel_expr arg2)
   | Cminor.Eload chunk addr => load chunk (sel_expr addr)
-  | Cminor.Estore chunk addr rhs => store chunk (sel_expr addr) (sel_expr rhs)
-  | Cminor.Ecall sg fn args => Ecall sg (sel_expr fn) (sel_exprlist args)
   | Cminor.Econdition cond ifso ifnot =>
       Econdition (condexpr_of_expr (sel_expr cond))
                  (sel_expr ifso) (sel_expr ifnot)
-  | Cminor.Elet b c => Elet (sel_expr b) (sel_expr c)
-  | Cminor.Eletvar n => Eletvar n
-  | Cminor.Ealloc b => Ealloc (sel_expr b)
-  end
+  end.
 
-with sel_exprlist (al: Cminor.exprlist) : exprlist :=
+Fixpoint sel_exprlist (al: list Cminor.expr) : exprlist :=
   match al with
-  | Cminor.Enil => Enil
-  | Cminor.Econs a bl => Econs (sel_expr a) (sel_exprlist bl)
+  | nil => Enil
+  | a :: bl => Econs (sel_expr a) (sel_exprlist bl)
   end.
 
 (** Conversion from Cminor statements to Cminorsel statements. *)
@@ -1067,8 +1057,11 @@ with sel_exprlist (al: Cminor.exprlist) : exprlist :=
 Fixpoint sel_stmt (s: Cminor.stmt) : stmt :=
   match s with
   | Cminor.Sskip => Sskip
-  | Cminor.Sexpr e => Sexpr (sel_expr e)
   | Cminor.Sassign id e => Sassign id (sel_expr e)
+  | Cminor.Sstore chunk addr rhs => store chunk (sel_expr addr) (sel_expr rhs)
+  | Cminor.Scall optid sg fn args =>
+      Scall optid sg (sel_expr fn) (sel_exprlist args)
+  | Cminor.Salloc id b => Salloc id (sel_expr b)
   | Cminor.Sseq s1 s2 => Sseq (sel_stmt s1) (sel_stmt s2)
   | Cminor.Sifthenelse e ifso ifnot =>
       Sifthenelse (condexpr_of_expr (sel_expr e))
diff --git a/backend/Selectionproof.v b/backend/Selectionproof.v
index e41765a76..177e32118 100644
--- a/backend/Selectionproof.v
+++ b/backend/Selectionproof.v
@@ -19,6 +19,9 @@ Open Local Scope selection_scope.
 Section CMCONSTR.
 
 Variable ge: genv.
+Variable sp: val.
+Variable e: env.
+Variable m: mem.
 
 (** * Lifting of let-bound variables *)
 
@@ -57,72 +60,34 @@ Proof.
   apply IHinsert_lenv. exact H0. omega.
 Qed.
 
-Scheme eval_expr_ind_3 := Minimality for eval_expr Sort Prop
-  with eval_condexpr_ind_3 := Minimality for eval_condexpr Sort Prop
-  with eval_exprlist_ind_3 := Minimality for eval_exprlist Sort Prop.
-
-Hint Resolve eval_Evar eval_Eop eval_Eload eval_Estore
-             eval_Ecall eval_Econdition eval_Ealloc
+Hint Resolve eval_Evar eval_Eop eval_Eload eval_Econdition
              eval_Elet eval_Eletvar 
              eval_CEtrue eval_CEfalse eval_CEcond
              eval_CEcondition eval_Enil eval_Econs: evalexpr.
 
-Lemma eval_list_one:
-  forall sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_exprlist ge sp le e m1 (a ::: Enil) t m2 (v :: nil).
-Proof.
-  intros. econstructor. eauto. constructor. traceEq.
-Qed.
-
-Lemma eval_list_two:
-  forall sp le e m1 a1 t1 m2 v1 a2 t2 m3 v2 t,
-  eval_expr ge sp le e m1 a1 t1 m2 v1 ->
-  eval_expr ge sp le e m2 a2 t2 m3 v2 ->
-  t = t1 ** t2 ->
-  eval_exprlist ge sp le e m1 (a1 ::: a2 ::: Enil) t m3 (v1 :: v2 :: nil).
-Proof.
-  intros. econstructor. eauto. econstructor. eauto. constructor. 
-  reflexivity. traceEq.
-Qed.
-
-Lemma eval_list_three:
-  forall sp le e m1 a1 t1 m2 v1 a2 t2 m3 v2 a3 t3 m4 v3 t,
-  eval_expr ge sp le e m1 a1 t1 m2 v1 ->
-  eval_expr ge sp le e m2 a2 t2 m3 v2 ->
-  eval_expr ge sp le e m3 a3 t3 m4 v3 ->
-  t = t1 ** t2 ** t3 ->
-  eval_exprlist ge sp le e m1 (a1 ::: a2 ::: a3 ::: Enil) t m4 (v1 :: v2 :: v3 :: nil).
-Proof.
-  intros. econstructor. eauto. econstructor. eauto. econstructor. eauto. constructor. 
-  reflexivity. reflexivity. traceEq.
-Qed.
-
-Hint Resolve eval_list_one eval_list_two eval_list_three: evalexpr.
-
 Lemma eval_lift_expr:
-  forall w sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
+  forall w le a v,
+  eval_expr ge sp e m le a v ->
   forall p le', insert_lenv le p w le' ->
-  eval_expr ge sp le' e m1 (lift_expr p a) t m2 v.
+  eval_expr ge sp e m le' (lift_expr p a) v.
 Proof.
-  intros w.
-  apply (eval_expr_ind_3 ge
-    (fun sp le e m1 a t m2 v =>
+  intro w.
+  apply (eval_expr_ind3 ge sp e m
+    (fun le a v =>
       forall p le', insert_lenv le p w le' ->
-      eval_expr ge sp le' e m1 (lift_expr p a) t m2 v)
-    (fun sp le e m1 a t m2 vb =>
+      eval_expr ge sp e m le' (lift_expr p a) v)
+    (fun le a v =>
       forall p le', insert_lenv le p w le' ->
-      eval_condexpr ge sp le' e m1 (lift_condexpr p a) t m2 vb)
-    (fun sp le e m1 al t m2 vl =>
+      eval_condexpr ge sp e m le' (lift_condexpr p a) v)
+    (fun le al vl =>
       forall p le', insert_lenv le p w le' ->
-      eval_exprlist ge sp le' e m1 (lift_exprlist p al) t m2 vl));
+      eval_exprlist ge sp e m le' (lift_exprlist p al) vl));
   simpl; intros; eauto with evalexpr.
 
   destruct v1; eapply eval_Econdition;
   eauto with evalexpr; simpl; eauto with evalexpr.
 
-  eapply eval_Elet. eauto. apply H2. apply insert_lenv_S; auto. auto.
+  eapply eval_Elet. eauto. apply H2. apply insert_lenv_S; auto.
 
   case (le_gt_dec p n); intro. 
   apply eval_Eletvar. eapply insert_lenv_lookup2; eauto.
@@ -133,13 +98,14 @@ Proof.
 Qed.
 
 Lemma eval_lift:
-  forall sp le e m1 a t m2 v w,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_expr ge sp (w::le) e m1 (lift a) t m2 v.
+  forall le a v w,
+  eval_expr ge sp e m le a v ->
+  eval_expr ge sp e m (w::le) (lift a) v.
 Proof.
   intros. unfold lift. eapply eval_lift_expr.
   eexact H. apply insert_lenv_0. 
 Qed.
+
 Hint Resolve eval_lift: evalexpr.
 
 (** * Useful lemmas and tactics *)
@@ -152,75 +118,37 @@ Ltac EvalOp := eapply eval_Eop; eauto with evalexpr.
 
 Ltac TrivialOp cstr := unfold cstr; intros; EvalOp.
 
-Lemma inv_eval_Eop_0:
-  forall sp le e m1 op t m2 v,
-  eval_expr ge sp le e m1 (Eop op Enil) t m2 v ->
-  t = E0 /\ m2 = m1 /\ eval_operation ge sp op nil m1 = Some v.
-Proof.
-  intros. inversion H. inversion H6. 
-  intuition. congruence.
-Qed.
-  
-Lemma inv_eval_Eop_1:
-  forall sp le e m1 op t a1 m2 v,
-  eval_expr ge sp le e m1 (Eop op (a1 ::: Enil)) t m2 v ->
-  exists v1,
-  eval_expr ge sp le e m1 a1 t m2 v1 /\
-  eval_operation ge sp op (v1 :: nil) m2 = Some v.
-Proof.
-  intros. 
-  inversion H. inversion H6. inversion H18. 
-  subst. exists v1; intuition. rewrite E0_right. auto.
-Qed.
-
-Lemma inv_eval_Eop_2:
-  forall sp le e m1 op a1 a2 t3 m3 v,
-  eval_expr ge sp le e m1 (Eop op (a1 ::: a2 ::: Enil)) t3 m3 v ->
-  exists t1, exists t2, exists m2, exists v1, exists v2,
-  eval_expr ge sp le e m1 a1 t1 m2 v1 /\
-  eval_expr ge sp le e m2 a2 t2 m3 v2 /\
-  t3 = t1 ** t2 /\
-  eval_operation ge sp op (v1 :: v2 :: nil) m3 = Some v.
-Proof.
-  intros. 
-  inversion H. subst. inversion H6. subst. inversion H8. subst.
-  inversion H11. subst. 
-  exists t1; exists t0; exists m0; exists v0; exists v1.
-  intuition. traceEq.
-Qed.
+Ltac InvEval1 :=
+  match goal with
+  | [ H: (eval_expr _ _ _ _ _ (Eop _ Enil) _) |- _ ] =>
+      inv H; InvEval1
+  | [ H: (eval_expr _ _ _ _ _ (Eop _ (_ ::: Enil)) _) |- _ ] =>
+      inv H; InvEval1
+  | [ H: (eval_expr _ _ _ _ _ (Eop _ (_ ::: _ ::: Enil)) _) |- _ ] =>
+      inv H; InvEval1
+  | [ H: (eval_exprlist _ _ _ _ _ Enil _) |- _ ] =>
+      inv H; InvEval1
+  | [ H: (eval_exprlist _ _ _ _ _ (_ ::: _) _) |- _ ] =>
+      inv H; InvEval1
+  | _ =>
+      idtac
+  end.
 
-Ltac SimplEval :=
+Ltac InvEval2 :=
   match goal with
-  | [ |- (eval_expr _ ?sp ?le ?e ?m1 (Eop ?op Enil) ?t ?m2 ?v) -> _] =>
-      intro XX1;
-      generalize (inv_eval_Eop_0 sp le e m1 op t m2 v XX1);
-      clear XX1;
-      intros [XX1 [XX2 XX3]];
-      subst t m2; simpl in XX3; 
-      try (simplify_eq XX3; clear XX3;
-      let EQ := fresh "EQ" in (intro EQ; rewrite EQ))
-  | [ |- (eval_expr _ ?sp ?le ?e ?m1 (Eop ?op (?a1 ::: Enil)) ?t ?m2 ?v) -> _] =>
-      intro XX1;
-      generalize (inv_eval_Eop_1 sp le e m1 op t a1 m2 v XX1);
-      clear XX1;
-      let v1 := fresh "v" in let EV := fresh "EV" in
-      let EQ := fresh "EQ" in
-      (intros [v1 [EV EQ]]; simpl in EQ)
-  | [ |- (eval_expr _ ?sp ?le ?e ?m1 (Eop ?op (?a1 ::: ?a2 ::: Enil)) ?t ?m2 ?v) -> _] =>
-      intro XX1;
-      generalize (inv_eval_Eop_2 sp le e m1 op a1 a2 t m2 v XX1);
-      clear XX1;
-      let t1 := fresh "t" in let t2 := fresh "t" in
-      let m := fresh "m" in
-      let v1 := fresh "v" in let v2 := fresh "v" in
-      let EV1 := fresh "EV" in let EV2 := fresh "EV" in
-      let EQ := fresh "EQ" in let TR := fresh "TR" in
-      (intros [t1 [t2 [m [v1 [v2 [EV1 [EV2 [TR EQ]]]]]]]]; simpl in EQ)
-  | _ => idtac
+  | [ H: (eval_operation _ _ _ nil _ = Some _) |- _ ] =>
+      simpl in H; inv H
+  | [ H: (eval_operation _ _ _ (_ :: nil) _ = Some _) |- _ ] =>
+      simpl in H; FuncInv
+  | [ H: (eval_operation _ _ _ (_ :: _ :: nil) _ = Some _) |- _ ] =>
+      simpl in H; FuncInv
+  | [ H: (eval_operation _ _ _ (_ :: _ :: _ :: nil) _ = Some _) |- _ ] =>
+      simpl in H; FuncInv
+  | _ =>
+      idtac
   end.
 
-Ltac InvEval H :=
-  generalize H; SimplEval; clear H.
+Ltac InvEval := InvEval1; InvEval2; InvEval2.
 
 (** * Correctness of the smart constructors *)
 
@@ -244,31 +172,31 @@ Ltac InvEval H :=
   by the smart constructor.
 *)
 
-Lemma eval_notint:
-  forall sp le e m1 a t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
-  eval_expr ge sp le e m1 (notint a) t m2 (Vint (Int.not x)).
+Theorem eval_notint:
+  forall le a x,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le (notint a) (Vint (Int.not x)).
 Proof.
-  unfold notint; intros until x; case (notint_match a); intros.
-  InvEval H. FuncInv. EvalOp. simpl. congruence. 
-  InvEval H. FuncInv. EvalOp. simpl. congruence. 
-  InvEval H. FuncInv. EvalOp. simpl. congruence. 
+  unfold notint; intros until x; case (notint_match a); intros; InvEval.
+  EvalOp. simpl. congruence.
+  EvalOp. simpl. congruence.
+  EvalOp. simpl. congruence.
   eapply eval_Elet. eexact H. 
   eapply eval_Eop.
   eapply eval_Econs. apply eval_Eletvar. simpl. reflexivity.
   eapply eval_Econs. apply eval_Eletvar. simpl. reflexivity.
-  apply eval_Enil. reflexivity. reflexivity. 
-  simpl. rewrite Int.or_idem. auto. traceEq.
+  apply eval_Enil.  
+  simpl. rewrite Int.or_idem. auto.
 Qed.
 
 Lemma eval_notbool_base:
-  forall sp le e m1 a t m2 v b,
-  eval_expr ge sp le e m1 a t m2 v ->
+  forall le a v b,
+  eval_expr ge sp e m le a v ->
   Val.bool_of_val v b ->
-  eval_expr ge sp le e m1 (notbool_base a) t m2 (Val.of_bool (negb b)).
+  eval_expr ge sp e m le (notbool_base a) (Val.of_bool (negb b)).
 Proof. 
   TrivialOp notbool_base. simpl. 
-  inversion H0. 
+  inv H0. 
   rewrite Int.eq_false; auto.
   rewrite Int.eq_true; auto.
   reflexivity.
@@ -277,245 +205,203 @@ Qed.
 Hint Resolve Val.bool_of_true_val Val.bool_of_false_val
              Val.bool_of_true_val_inv Val.bool_of_false_val_inv: valboolof.
 
-Lemma eval_notbool:
-  forall a sp le e m1 t m2 v b,
-  eval_expr ge sp le e m1 a t m2 v ->
+Theorem eval_notbool:
+  forall le a v b,
+  eval_expr ge sp e m le a v ->
   Val.bool_of_val v b ->
-  eval_expr ge sp le e m1 (notbool a) t m2 (Val.of_bool (negb b)).
+  eval_expr ge sp e m le (notbool a) (Val.of_bool (negb b)).
 Proof.
-  assert (N1: forall v b, Val.is_false v -> Val.bool_of_val v b -> Val.is_true (Val.of_bool (negb b))).
-    intros. inversion H0; simpl; auto; subst v; simpl in H.
-    congruence. apply Int.one_not_zero. contradiction.
-  assert (N2: forall v b, Val.is_true v -> Val.bool_of_val v b -> Val.is_false (Val.of_bool (negb b))).
-    intros. inversion H0; simpl; auto; subst v; simpl in H.
-    congruence. 
-
   induction a; simpl; intros; try (eapply eval_notbool_base; eauto).
   destruct o; try (eapply eval_notbool_base; eauto).
 
-  destruct e. InvEval H. injection XX3; clear XX3; intro; subst v.
-  inversion H0. rewrite Int.eq_false; auto. 
+  destruct e0. InvEval. 
+  inv H0. rewrite Int.eq_false; auto. 
   simpl; eauto with evalexpr.
   rewrite Int.eq_true; simpl; eauto with evalexpr.
   eapply eval_notbool_base; eauto.
 
-  inversion H. subst. 
-  simpl in H11. eapply eval_Eop; eauto.
-  simpl. caseEq (eval_condition c vl m2); intros.
-  rewrite H1 in H11. 
-  assert (b0 = b). 
-  destruct b0; inversion H11; subst v; inversion H0; auto.
-  subst b0. rewrite (Op.eval_negate_condition _ _ _ H1). 
+  inv H. eapply eval_Eop; eauto.
+  simpl. assert (eval_condition c vl m = Some b).
+  generalize H6. simpl. 
+  case (eval_condition c vl m); intros.
+  destruct b0; inv H1; inversion H0; auto; congruence.
+  congruence.
+  rewrite (Op.eval_negate_condition _ _ _ H). 
   destruct b; reflexivity.
-  rewrite H1 in H11; discriminate.
 
-  inversion H; eauto 10 with evalexpr valboolof.
-  inversion H; eauto 10 with evalexpr valboolof.
-
-  inversion H. subst. eapply eval_Econdition with (t2 := t8). eexact H34.
-  destruct v4; eauto. auto.
+  inv H. eapply eval_Econdition; eauto. 
+  destruct v1; eauto.
 Qed.
 
-Lemma eval_addimm:
-  forall sp le e m1 n a t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
-  eval_expr ge sp le e m1 (addimm n a) t m2 (Vint (Int.add x n)).
+Theorem eval_addimm:
+  forall le n a x,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le (addimm n a) (Vint (Int.add x n)).
 Proof.
   unfold addimm; intros until x.
   generalize (Int.eq_spec n Int.zero). case (Int.eq n Int.zero); intro.
   subst n. rewrite Int.add_zero. auto.
-  case (addimm_match a); intros.
-  InvEval H0. EvalOp. simpl. rewrite Int.add_commut. auto.
-  InvEval H0. destruct (Genv.find_symbol ge s); discriminate.
-  InvEval H0. 
-  destruct sp; simpl in XX3; discriminate.
-  InvEval H0. FuncInv. EvalOp. simpl. subst x. 
-  rewrite Int.add_assoc. decEq; decEq; decEq. apply Int.add_commut.
-  EvalOp. 
+  case (addimm_match a); intros; InvEval; EvalOp; simpl.
+  rewrite Int.add_commut. auto.
+  destruct (Genv.find_symbol ge s); discriminate.
+  destruct sp; simpl in H1; discriminate.
+  subst x. rewrite Int.add_assoc. decEq; decEq; decEq. apply Int.add_commut.
 Qed. 
 
-Lemma eval_addimm_ptr:
-  forall sp le e m1 n t a m2 b ofs,
-  eval_expr ge sp le e m1 a t m2 (Vptr b ofs) ->
-  eval_expr ge sp le e m1 (addimm n a) t m2 (Vptr b (Int.add ofs n)).
+Theorem eval_addimm_ptr:
+  forall le n a b ofs,
+  eval_expr ge sp e m le a (Vptr b ofs) ->
+  eval_expr ge sp e m le (addimm n a) (Vptr b (Int.add ofs n)).
 Proof.
   unfold addimm; intros until ofs.
   generalize (Int.eq_spec n Int.zero). case (Int.eq n Int.zero); intro.
   subst n. rewrite Int.add_zero. auto.
-  case (addimm_match a); intros.
-  InvEval H0. 
-  InvEval H0. EvalOp. simpl. 
-    destruct (Genv.find_symbol ge s). 
-    rewrite Int.add_commut. congruence.
-    discriminate.
-  InvEval H0. destruct sp; simpl in XX3; try discriminate.
-  inversion XX3. EvalOp. simpl. decEq. decEq. 
+  case (addimm_match a); intros; InvEval; EvalOp; simpl.
+  destruct (Genv.find_symbol ge s). 
+  rewrite Int.add_commut. congruence.
+  discriminate.
+  destruct sp; simpl in H1; try discriminate.
+  inv H1. simpl. decEq. decEq. 
   rewrite Int.add_assoc. decEq. apply Int.add_commut.
-  InvEval H0. FuncInv. subst b0; subst ofs. EvalOp. simpl. 
-    rewrite (Int.add_commut n m). rewrite Int.add_assoc. auto.
-  EvalOp. 
+  subst. rewrite (Int.add_commut n m0). rewrite Int.add_assoc. auto.
 Qed.
 
-Lemma eval_add:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (add a b) (t1**t2) m3 (Vint (Int.add x y)).
+Theorem eval_add:
+  forall le a b x y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (add a b) (Vint (Int.add x y)).
 Proof.
-  intros until y. unfold add; case (add_match a b); intros.
-  InvEval H. rewrite Int.add_commut. apply eval_addimm. 
-  rewrite E0_left; assumption.
-  InvEval H. FuncInv. InvEval H0. FuncInv. 
-    replace (Int.add x y) with (Int.add (Int.add i i0) (Int.add n1 n2)).
-    apply eval_addimm. EvalOp. 
+  intros until y.
+  unfold add; case (add_match a b); intros; InvEval.
+  rewrite Int.add_commut. apply eval_addimm. auto. 
+  replace (Int.add x y) with (Int.add (Int.add i0 i) (Int.add n1 n2)).
+    apply eval_addimm. EvalOp.  
     subst x; subst y. 
     repeat rewrite Int.add_assoc. decEq. apply Int.add_permut. 
-  InvEval H. FuncInv. 
-    replace (Int.add x y) with (Int.add (Int.add i y) n1).
+  replace (Int.add x y) with (Int.add (Int.add i y) n1).
     apply eval_addimm. EvalOp.
     subst x. repeat rewrite Int.add_assoc. decEq. apply Int.add_commut.
-  InvEval H0. FuncInv.
-    apply eval_addimm. rewrite E0_right. auto.
-  InvEval H0. FuncInv. 
-    replace (Int.add x y) with (Int.add (Int.add x i) n2).
+  apply eval_addimm. auto.
+  replace (Int.add x y) with (Int.add (Int.add x i) n2).
     apply eval_addimm. EvalOp.
     subst y. rewrite Int.add_assoc. auto.
   EvalOp.
 Qed.
 
-Lemma eval_add_ptr:
-  forall sp le e m1 a t1 m2 p x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vptr p x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (add a b) (t1**t2) m3 (Vptr p (Int.add x y)).
+Theorem eval_add_ptr:
+  forall le a b p x y,
+  eval_expr ge sp e m le a (Vptr p x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (add a b) (Vptr p (Int.add x y)).
 Proof.
-  intros until y. unfold add; case (add_match a b); intros.
-  InvEval H. 
-  InvEval H. FuncInv. InvEval H0. FuncInv. 
-    replace (Int.add x y) with (Int.add (Int.add i i0) (Int.add n1 n2)).
+  intros until y. unfold add; case (add_match a b); intros; InvEval.
+  replace (Int.add x y) with (Int.add (Int.add i0 i) (Int.add n1 n2)).
     apply eval_addimm_ptr. subst b0. EvalOp. 
     subst x; subst y.
     repeat rewrite Int.add_assoc. decEq. apply Int.add_permut. 
-  InvEval H. FuncInv. 
-    replace (Int.add x y) with (Int.add (Int.add i y) n1).
+  replace (Int.add x y) with (Int.add (Int.add i y) n1).
     apply eval_addimm_ptr. subst b0. EvalOp.
     subst x. repeat rewrite Int.add_assoc. decEq. apply Int.add_commut.
-  InvEval H0. apply eval_addimm_ptr. rewrite E0_right. auto.
-  InvEval H0. FuncInv. 
-    replace (Int.add x y) with (Int.add (Int.add x i) n2).
+  apply eval_addimm_ptr. auto.
+  replace (Int.add x y) with (Int.add (Int.add x i) n2).
     apply eval_addimm_ptr. EvalOp.
     subst y. rewrite Int.add_assoc. auto.
   EvalOp.
 Qed.
 
-Lemma eval_add_ptr_2:
-  forall sp le e m1 a t1 m2 p x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vptr p y) ->
-  eval_expr ge sp le e m1 (add a b) (t1**t2) m3 (Vptr p (Int.add y x)).
+Theorem eval_add_ptr_2:
+  forall le a b x p y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vptr p y) ->
+  eval_expr ge sp e m le (add a b) (Vptr p (Int.add y x)).
 Proof.
-  intros until y. unfold add; case (add_match a b); intros.
-  InvEval H. 
-    apply eval_addimm_ptr. rewrite E0_left. auto.
-  InvEval H. FuncInv. InvEval H0. FuncInv. 
-    replace (Int.add y x) with (Int.add (Int.add i0 i) (Int.add n1 n2)).
+  intros until y. unfold add; case (add_match a b); intros; InvEval.
+  apply eval_addimm_ptr. auto.
+  replace (Int.add y x) with (Int.add (Int.add i i0) (Int.add n1 n2)).
     apply eval_addimm_ptr. subst b0. EvalOp. 
     subst x; subst y.
     repeat rewrite Int.add_assoc. decEq. 
     rewrite (Int.add_commut n1 n2). apply Int.add_permut. 
-  InvEval H. FuncInv. 
-    replace (Int.add y x) with (Int.add (Int.add y i) n1).
+  replace (Int.add y x) with (Int.add (Int.add y i) n1).
     apply eval_addimm_ptr. EvalOp. 
     subst x. repeat rewrite Int.add_assoc. auto.
-  InvEval H0. 
-  InvEval H0. FuncInv. 
-    replace (Int.add y x) with (Int.add (Int.add i x) n2).
+  replace (Int.add y x) with (Int.add (Int.add i x) n2).
     apply eval_addimm_ptr. EvalOp. subst b0; reflexivity.
     subst y. repeat rewrite Int.add_assoc. decEq. apply Int.add_commut.
   EvalOp.
 Qed.
 
-Lemma eval_sub:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (sub a b) (t1**t2) m3 (Vint (Int.sub x y)).
+Theorem eval_sub:
+  forall le a b x y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (sub a b) (Vint (Int.sub x y)).
 Proof.
   intros until y.
-  unfold sub; case (sub_match a b); intros.
-  InvEval H0. rewrite Int.sub_add_opp. 
-    apply eval_addimm. rewrite E0_right. assumption.
-  InvEval H. FuncInv. InvEval H0. FuncInv.
-    replace (Int.sub x y) with (Int.add (Int.sub i i0) (Int.sub n1 n2)).
+  unfold sub; case (sub_match a b); intros; InvEval.
+  rewrite Int.sub_add_opp. 
+    apply eval_addimm. assumption.
+  replace (Int.sub x y) with (Int.add (Int.sub i0 i) (Int.sub n1 n2)).
     apply eval_addimm. EvalOp.
     subst x; subst y.
     repeat rewrite Int.sub_add_opp.
     repeat rewrite Int.add_assoc. decEq. 
     rewrite Int.add_permut. decEq. symmetry. apply Int.neg_add_distr.
-  InvEval H. FuncInv. 
-    replace (Int.sub x y) with (Int.add (Int.sub i y) n1).
+  replace (Int.sub x y) with (Int.add (Int.sub i y) n1).
     apply eval_addimm. EvalOp.
     subst x. rewrite Int.sub_add_l. auto.
-  InvEval H0. FuncInv. 
-    replace (Int.sub x y) with (Int.add (Int.sub x i) (Int.neg n2)).
+  replace (Int.sub x y) with (Int.add (Int.sub x i) (Int.neg n2)).
     apply eval_addimm. EvalOp.
     subst y. rewrite (Int.add_commut i n2). symmetry. apply Int.sub_add_r. 
   EvalOp.
 Qed.
 
-Lemma eval_sub_ptr_int:
-  forall sp le e m1 a t1 m2 p x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vptr p x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (sub a b) (t1**t2) m3 (Vptr p (Int.sub x y)).
+Theorem eval_sub_ptr_int:
+  forall le a b p x y,
+  eval_expr ge sp e m le a (Vptr p x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (sub a b) (Vptr p (Int.sub x y)).
 Proof.
   intros until y.
-  unfold sub; case (sub_match a b); intros.
-  InvEval H0. rewrite Int.sub_add_opp. 
-    apply eval_addimm_ptr. rewrite E0_right. assumption.
-  InvEval H. FuncInv. InvEval H0. FuncInv.
-    subst b0.
-    replace (Int.sub x y) with (Int.add (Int.sub i i0) (Int.sub n1 n2)).
+  unfold sub; case (sub_match a b); intros; InvEval.
+  rewrite Int.sub_add_opp. 
+    apply eval_addimm_ptr. assumption.
+  subst b0. replace (Int.sub x y) with (Int.add (Int.sub i0 i) (Int.sub n1 n2)).
     apply eval_addimm_ptr. EvalOp.
     subst x; subst y.
     repeat rewrite Int.sub_add_opp.
     repeat rewrite Int.add_assoc. decEq. 
     rewrite Int.add_permut. decEq. symmetry. apply Int.neg_add_distr.
-  InvEval H. FuncInv. subst b0.
-    replace (Int.sub x y) with (Int.add (Int.sub i y) n1).
+  subst b0. replace (Int.sub x y) with (Int.add (Int.sub i y) n1).
     apply eval_addimm_ptr. EvalOp.
     subst x. rewrite Int.sub_add_l. auto.
-  InvEval H0. FuncInv. 
-    replace (Int.sub x y) with (Int.add (Int.sub x i) (Int.neg n2)).
+  replace (Int.sub x y) with (Int.add (Int.sub x i) (Int.neg n2)).
     apply eval_addimm_ptr. EvalOp.
     subst y. rewrite (Int.add_commut i n2). symmetry. apply Int.sub_add_r. 
   EvalOp.
 Qed.
 
-Lemma eval_sub_ptr_ptr:
-  forall sp le e m1 a t1 m2 p x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vptr p x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vptr p y) ->
-  eval_expr ge sp le e m1 (sub a b) (t1**t2) m3 (Vint (Int.sub x y)).
+Theorem eval_sub_ptr_ptr:
+  forall le a b p x y,
+  eval_expr ge sp e m le a (Vptr p x) ->
+  eval_expr ge sp e m le b (Vptr p y) ->
+  eval_expr ge sp e m le (sub a b) (Vint (Int.sub x y)).
 Proof.
   intros until y.
-  unfold sub; case (sub_match a b); intros.
-  InvEval H0. 
-  InvEval H. FuncInv. InvEval H0. FuncInv.
-    replace (Int.sub x y) with (Int.add (Int.sub i i0) (Int.sub n1 n2)).
+  unfold sub; case (sub_match a b); intros; InvEval.
+  replace (Int.sub x y) with (Int.add (Int.sub i0 i) (Int.sub n1 n2)).
     apply eval_addimm. EvalOp. 
     simpl; unfold eq_block. subst b0; subst b1; rewrite zeq_true. auto.
     subst x; subst y.
     repeat rewrite Int.sub_add_opp.
     repeat rewrite Int.add_assoc. decEq. 
     rewrite Int.add_permut. decEq. symmetry. apply Int.neg_add_distr.
-  InvEval H. FuncInv. subst b0.
-    replace (Int.sub x y) with (Int.add (Int.sub i y) n1).
+  subst b0. replace (Int.sub x y) with (Int.add (Int.sub i y) n1).
     apply eval_addimm. EvalOp.
     simpl. unfold eq_block. rewrite zeq_true. auto.
     subst x. rewrite Int.sub_add_l. auto.
-  InvEval H0. FuncInv. subst b0.
-    replace (Int.sub x y) with (Int.add (Int.sub x i) (Int.neg n2)).
+  subst b0. replace (Int.sub x y) with (Int.add (Int.sub x i) (Int.neg n2)).
     apply eval_addimm. EvalOp.
     simpl. unfold eq_block. rewrite zeq_true. auto.
     subst y. rewrite (Int.add_commut i n2). symmetry. apply Int.sub_add_r. 
@@ -523,29 +409,29 @@ Proof.
 Qed.
 
 Lemma eval_rolm:
-  forall sp le e m1 a amount mask t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
-  eval_expr ge sp le e m1 (rolm a amount mask) t m2 (Vint (Int.rolm x amount mask)).
+  forall le a amount mask x,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le (rolm a amount mask) (Vint (Int.rolm x amount mask)).
 Proof.
-  intros until x. unfold rolm; case (rolm_match a); intros.
-  InvEval H. eauto with evalexpr. 
+  intros until x. unfold rolm; case (rolm_match a); intros; InvEval.
+  eauto with evalexpr. 
   case (Int.is_rlw_mask (Int.and (Int.rol mask1 amount) mask)).
-  InvEval H. FuncInv. EvalOp. simpl. subst x. 
+  EvalOp. simpl. subst x. 
   decEq. decEq. 
   replace (Int.and (Int.add amount1 amount) (Int.repr 31))
      with (Int.modu (Int.add amount1 amount) (Int.repr 32)).
   symmetry. apply Int.rolm_rolm. 
   change (Int.repr 31) with (Int.sub (Int.repr 32) Int.one).
   apply Int.modu_and with (Int.repr 5). reflexivity.
-  EvalOp. 
+  EvalOp. econstructor. EvalOp. simpl. rewrite H. reflexivity. constructor. auto.  
   EvalOp.
 Qed.
 
-Lemma eval_shlimm:
-  forall sp le e m1 a n t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
+Theorem eval_shlimm:
+  forall le a n x,
+  eval_expr ge sp e m le a (Vint x) ->
   Int.ltu n (Int.repr 32) = true ->
-  eval_expr ge sp le e m1 (shlimm a n) t m2 (Vint (Int.shl x n)).
+  eval_expr ge sp e m le (shlimm a n) (Vint (Int.shl x n)).
 Proof.
   intros.  unfold shlimm.
   generalize (Int.eq_spec n Int.zero); case (Int.eq n Int.zero); intro.
@@ -555,11 +441,11 @@ Proof.
   apply eval_rolm. auto. symmetry. apply Int.shl_rolm. exact H0.
 Qed.
 
-Lemma eval_shruimm:
-  forall sp le e m1 a n t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
+Theorem eval_shruimm:
+  forall le a n x,
+  eval_expr ge sp e m le a (Vint x) ->
   Int.ltu n (Int.repr 32) = true ->
-  eval_expr ge sp le e m1 (shruimm a n) t m2 (Vint (Int.shru x n)).
+  eval_expr ge sp e m le (shruimm a n) (Vint (Int.shru x n)).
 Proof.
   intros.  unfold shruimm.
   generalize (Int.eq_spec n Int.zero); case (Int.eq n Int.zero); intro.
@@ -570,9 +456,9 @@ Proof.
 Qed.
 
 Lemma eval_mulimm_base:
-  forall sp le e m1 a t n m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
-  eval_expr ge sp le e m1 (mulimm_base n a) t m2 (Vint (Int.mul x n)).
+  forall le a n x,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le (mulimm_base n a) (Vint (Int.mul x n)).
 Proof.
   intros; unfold mulimm_base. 
   generalize (Int.one_bits_decomp n). 
@@ -585,7 +471,7 @@ Proof.
   rewrite Int.add_zero. rewrite <- Int.shl_mul.
   apply eval_shlimm. auto. auto with coqlib. 
   destruct l.
-  intros. apply eval_Elet with t m2 (Vint x) E0. auto.
+  intros. apply eval_Elet with (Vint x). auto.
   rewrite H1. simpl. rewrite Int.add_zero. 
   rewrite Int.mul_add_distr_r.
   rewrite <- Int.shl_mul.
@@ -597,50 +483,48 @@ Proof.
   apply eval_shlimm. apply eval_Eletvar. simpl. reflexivity.
   auto with coqlib.
   auto with evalexpr.
-  reflexivity. traceEq. reflexivity. traceEq. 
+  reflexivity.
   intros. EvalOp. 
 Qed.
 
-Lemma eval_mulimm:
-  forall sp le e m1 a n t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
-  eval_expr ge sp le e m1 (mulimm n a) t m2 (Vint (Int.mul x n)).
+Theorem eval_mulimm:
+  forall le a n x,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le (mulimm n a) (Vint (Int.mul x n)).
 Proof.
   intros until x; unfold mulimm.
   generalize (Int.eq_spec n Int.zero); case (Int.eq n Int.zero); intro.
   subst n. rewrite Int.mul_zero. 
-  intro. eapply eval_Elet; eauto with evalexpr. traceEq.
+  intro. eapply eval_Elet; eauto with evalexpr. 
   generalize (Int.eq_spec n Int.one); case (Int.eq n Int.one); intro.
   subst n. rewrite Int.mul_one. auto.
-  case (mulimm_match a); intros.
-  InvEval H1. EvalOp. rewrite Int.mul_commut. reflexivity.
-  InvEval H1. FuncInv. 
+  case (mulimm_match a); intros; InvEval.
+  EvalOp. rewrite Int.mul_commut. reflexivity.
   replace (Int.mul x n) with (Int.add (Int.mul i n) (Int.mul n n2)).
   apply eval_addimm. apply eval_mulimm_base. auto.
   subst x. rewrite Int.mul_add_distr_l. decEq. apply Int.mul_commut.
   apply eval_mulimm_base. assumption.
 Qed.
 
-Lemma eval_mul:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (mul a b) (t1**t2) m3 (Vint (Int.mul x y)).
+Theorem eval_mul:
+  forall le a b x y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (mul a b) (Vint (Int.mul x y)).
 Proof.
   intros until y.
-  unfold mul; case (mul_match a b); intros.
-  InvEval H. rewrite Int.mul_commut. apply eval_mulimm. 
-  rewrite E0_left; auto.
-  InvEval H0. rewrite E0_right. apply eval_mulimm. auto.
+  unfold mul; case (mul_match a b); intros; InvEval.
+  rewrite Int.mul_commut. apply eval_mulimm. auto. 
+  apply eval_mulimm. auto.
   EvalOp.
 Qed.
 
-Lemma eval_divs:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+Theorem eval_divs:
+  forall le a b x y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   y <> Int.zero ->
-  eval_expr ge sp le e m1 (divs a b) (t1**t2) m3 (Vint (Int.divs x y)).
+  eval_expr ge sp e m le (divs a b) (Vint (Int.divs x y)).
 Proof.
   TrivialOp divs. simpl. 
   predSpec Int.eq Int.eq_spec y Int.zero. contradiction. auto.
@@ -652,11 +536,11 @@ Lemma eval_mod_aux:
    y <> Int.zero ->
    eval_operation ge sp divop (Vint x :: Vint y :: nil) m =
    Some (Vint (semdivop x y))) ->
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+  forall le a b x y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   y <> Int.zero ->
-  eval_expr ge sp le e m1 (mod_aux divop a b) (t1**t2) m3
+  eval_expr ge sp e m le (mod_aux divop a b)
    (Vint (Int.sub x (Int.mul (semdivop x y) y))).
 Proof.
   intros; unfold mod_aux.
@@ -668,21 +552,20 @@ Proof.
   eapply eval_Econs. eapply eval_Eop.
   eapply eval_Econs. apply eval_Eletvar. simpl; reflexivity.
   eapply eval_Econs. apply eval_Eletvar. simpl; reflexivity.
-  apply eval_Enil. reflexivity. reflexivity. 
+  apply eval_Enil.  
   apply H. assumption.
   eapply eval_Econs. apply eval_Eletvar. simpl; reflexivity.
-  apply eval_Enil. reflexivity. reflexivity. 
+  apply eval_Enil.  
   simpl; reflexivity. apply eval_Enil. 
-  reflexivity. reflexivity. reflexivity.
-  reflexivity. traceEq.
+  reflexivity.
 Qed.
 
-Lemma eval_mods:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+Theorem eval_mods:
+  forall le a b x y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   y <> Int.zero ->
-  eval_expr ge sp le e m1 (mods a b) (t1**t2) m3 (Vint (Int.mods x y)).
+  eval_expr ge sp e m le (mods a b) (Vint (Int.mods x y)).
 Proof.
   intros; unfold mods. 
   rewrite Int.mods_divs. 
@@ -692,232 +575,217 @@ Proof.
 Qed.
 
 Lemma eval_divu_base:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   y <> Int.zero ->
-  eval_expr ge sp le e m1 (Eop Odivu (a ::: b ::: Enil)) (t1**t2) m3 (Vint (Int.divu x y)).
+  eval_expr ge sp e m le (Eop Odivu (a ::: b ::: Enil)) (Vint (Int.divu x y)).
 Proof.
   intros. EvalOp. simpl. 
   predSpec Int.eq Int.eq_spec y Int.zero. contradiction. auto.
 Qed.
 
-Lemma eval_divu:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+Theorem eval_divu:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   y <> Int.zero ->
-  eval_expr ge sp le e m1 (divu a b) (t1**t2) m3 (Vint (Int.divu x y)).
+  eval_expr ge sp e m le (divu a b) (Vint (Int.divu x y)).
 Proof.
   intros until y.
-  unfold divu; case (divu_match b); intros.
-  InvEval H0. caseEq (Int.is_power2 y). 
+  unfold divu; case (divu_match b); intros; InvEval.
+  caseEq (Int.is_power2 y). 
   intros. rewrite (Int.divu_pow2 x y i H0).
-  apply eval_shruimm. rewrite E0_right. auto.
+  apply eval_shruimm. auto.
   apply Int.is_power2_range with y. auto.
-  intros. subst n2. eapply eval_divu_base. eexact H. EvalOp. auto.
+  intros. apply eval_divu_base. auto. EvalOp. auto.
   eapply eval_divu_base; eauto.
 Qed.
 
-Lemma eval_modu:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+Theorem eval_modu:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   y <> Int.zero ->
-  eval_expr ge sp le e m1 (modu a b) (t1**t2) m3 (Vint (Int.modu x y)).
+  eval_expr ge sp e m le (modu a b) (Vint (Int.modu x y)).
 Proof.
-  intros until y; unfold modu; case (divu_match b); intros.
-  InvEval H0. caseEq (Int.is_power2 y). 
+  intros until y; unfold modu; case (divu_match b); intros; InvEval.
+  caseEq (Int.is_power2 y). 
   intros. rewrite (Int.modu_and x y i H0).
-  rewrite <- Int.rolm_zero. apply eval_rolm. rewrite E0_right; auto.
+  rewrite <- Int.rolm_zero. apply eval_rolm. auto.
   intro. rewrite Int.modu_divu. eapply eval_mod_aux. 
   intros. simpl. predSpec Int.eq Int.eq_spec y0 Int.zero.
   contradiction. auto.
-  eexact H. EvalOp. auto. auto.
+  auto. EvalOp. auto. auto.
   rewrite Int.modu_divu. eapply eval_mod_aux. 
   intros. simpl. predSpec Int.eq Int.eq_spec y0 Int.zero.
-  contradiction. auto.
-  eexact H. eexact H0. auto. auto.
+  contradiction. auto. auto. auto. auto. auto.
 Qed.
 
-Lemma eval_andimm:
-  forall sp le e m1 n a t m2 x,
-  eval_expr ge sp le e m1 a t m2 (Vint x) ->
-  eval_expr ge sp le e m1 (andimm n a) t m2 (Vint (Int.and x n)).
+Theorem eval_andimm:
+  forall le n a x,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le (andimm n a) (Vint (Int.and x n)).
 Proof.
   intros.  unfold andimm. case (Int.is_rlw_mask n).
   rewrite <- Int.rolm_zero. apply eval_rolm; auto.
   EvalOp. 
 Qed.
 
-Lemma eval_and:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (and a b) (t1**t2) m3 (Vint (Int.and x y)).
+Theorem eval_and:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (and a b) (Vint (Int.and x y)).
 Proof.
-  intros until y; unfold and; case (mul_match a b); intros.
-  InvEval H. rewrite Int.and_commut. 
-  rewrite E0_left; apply eval_andimm; auto.
-  InvEval H0. rewrite E0_right; apply eval_andimm; auto.
+  intros until y; unfold and; case (mul_match a b); intros; InvEval.
+  rewrite Int.and_commut. apply eval_andimm; auto.
+  apply eval_andimm; auto.
   EvalOp.
 Qed.
 
-Remark eval_same_expr_pure:
-  forall a1 a2 sp le e m1 t1 m2 v1 t2 m3 v2,
+Remark eval_same_expr:
+  forall a1 a2 le v1 v2,
   same_expr_pure a1 a2 = true ->
-  eval_expr ge sp le e m1 a1 t1 m2 v1 ->
-  eval_expr ge sp le e m2 a2 t2 m3 v2 ->
-  t1 = E0 /\ t2 = E0 /\ a2 = a1 /\ v2 = v1 /\ m2 = m1.
+  eval_expr ge sp e m le a1 v1 ->
+  eval_expr ge sp e m le a2 v2 ->
+  a1 = a2 /\ v1 = v2.
 Proof.
   intros until v2.
   destruct a1; simpl; try (intros; discriminate). 
   destruct a2; simpl; try (intros; discriminate).
   case (ident_eq i i0); intros.
-  subst i0. inversion H0. inversion H1. 
-  assert (v2 = v1). congruence. tauto.
+  subst i0. inversion H0. inversion H1. split. auto. congruence. 
   discriminate.
 Qed.
 
 Lemma eval_or:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
-  eval_expr ge sp le e m1 (or a b) (t1**t2) m3 (Vint (Int.or x y)).
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
+  eval_expr ge sp e m le (or a b) (Vint (Int.or x y)).
 Proof.
-  intros until y; unfold or; case (or_match a b); intros.
-  generalize (Int.eq_spec amount1 amount2); case (Int.eq amount1 amount2); intro.
-  case (Int.is_rlw_mask (Int.or mask1 mask2)).
-  caseEq (same_expr_pure t0 t3); intro.
-  simpl. InvEval H. FuncInv. InvEval H0. FuncInv. 
-  generalize (eval_same_expr_pure _ _ _ _ _ _ _ _ _ _ _ _ H2 EV EV0).
-  intros [EQ1 [EQ2 [EQ3 [EQ4 EQ5]]]]. 
-  injection EQ4; intro EQ7. subst.
-  EvalOp. simpl. rewrite Int.or_rolm. auto.
-  simpl. EvalOp. 
-  simpl. EvalOp. 
-  simpl. EvalOp. 
+  intros until y; unfold or; case (or_match a b); intros; InvEval.
+  caseEq (Int.eq amount1 amount2 
+          && Int.is_rlw_mask (Int.or mask1 mask2) 
+          && same_expr_pure t1 t2); intro.
+  destruct (andb_prop _ _ H1). destruct (andb_prop _ _ H4).
+  generalize (Int.eq_spec amount1 amount2). rewrite H6. intro. subst amount2.
+  exploit eval_same_expr; eauto. intros [EQ1 EQ2]. inv EQ1. inv EQ2. 
+  simpl. EvalOp. simpl. rewrite Int.or_rolm. auto.
+  simpl. apply eval_Eop with (Vint x :: Vint y :: nil).
+  econstructor. EvalOp. simpl. congruence. 
+  econstructor. EvalOp. simpl. congruence. constructor. auto.
   EvalOp.
 Qed.
 
-Lemma eval_shl:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+Theorem eval_shl:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   Int.ltu y (Int.repr 32) = true ->
-  eval_expr ge sp le e m1 (shl a b) (t1**t2) m3 (Vint (Int.shl x y)).
+  eval_expr ge sp e m le (shl a b) (Vint (Int.shl x y)).
 Proof.
   intros until y; unfold shl; case (shift_match b); intros.
-  InvEval H0. rewrite E0_right. apply eval_shlimm; auto.
+  InvEval. apply eval_shlimm; auto.
   EvalOp. simpl. rewrite H1. auto.
 Qed.
 
-Lemma eval_shru:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vint x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vint y) ->
+Theorem eval_shru:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vint x) ->
+  eval_expr ge sp e m le b (Vint y) ->
   Int.ltu y (Int.repr 32) = true ->
-  eval_expr ge sp le e m1 (shru a b) (t1**t2) m3 (Vint (Int.shru x y)).
+  eval_expr ge sp e m le (shru a b) (Vint (Int.shru x y)).
 Proof.
   intros until y; unfold shru; case (shift_match b); intros.
-  InvEval H0. rewrite E0_right; apply eval_shruimm; auto.
+  InvEval. apply eval_shruimm; auto.
   EvalOp. simpl. rewrite H1. auto.
 Qed.
 
-Lemma eval_addf:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vfloat x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vfloat y) ->
-  eval_expr ge sp le e m1 (addf a b) (t1**t2) m3 (Vfloat (Float.add x y)).
+Theorem eval_addf:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vfloat x) ->
+  eval_expr ge sp e m le b (Vfloat y) ->
+  eval_expr ge sp e m le (addf a b) (Vfloat (Float.add x y)).
 Proof.
-  intros until y; unfold addf; case (addf_match a b); intros.
-  InvEval H. FuncInv. EvalOp. 
-  econstructor; eauto. econstructor; eauto. econstructor; eauto. constructor.
-  traceEq. simpl. subst x. reflexivity.
-  InvEval H0. FuncInv. eapply eval_Elet. eexact H. EvalOp. 
-  econstructor; eauto with evalexpr. 
-  econstructor; eauto with evalexpr. 
-  econstructor. apply eval_Eletvar. simpl; reflexivity.
-  constructor. reflexivity. traceEq.
-  subst y. rewrite Float.addf_commut. reflexivity. auto.
+  intros until y; unfold addf; case (addf_match a b); intros; InvEval.
+  EvalOp. simpl. congruence.
+  econstructor. eauto. EvalOp. econstructor. eauto with evalexpr. 
+  econstructor. eauto with evalexpr. econstructor. 
+  econstructor. simpl. reflexivity. constructor.
+  simpl. subst y. rewrite Float.addf_commut. auto.
   EvalOp.
 Qed.
  
-Lemma eval_subf:
-  forall sp le e m1 a t1 m2 x b t2 m3 y,
-  eval_expr ge sp le e m1 a t1 m2 (Vfloat x) ->
-  eval_expr ge sp le e m2 b t2 m3 (Vfloat y) ->
-  eval_expr ge sp le e m1 (subf a b) (t1**t2) m3 (Vfloat (Float.sub x y)).
+Theorem eval_subf:
+  forall le a x b y,
+  eval_expr ge sp e m le a (Vfloat x) ->
+  eval_expr ge sp e m le b (Vfloat y) ->
+  eval_expr ge sp e m le (subf a b) (Vfloat (Float.sub x y)).
 Proof.
   intros until y; unfold subf; case (subf_match a b); intros.
-  InvEval H. FuncInv. EvalOp. 
-  econstructor; eauto. econstructor; eauto. econstructor; eauto. constructor.
-  traceEq. subst x. reflexivity.
+  InvEval. EvalOp. simpl. congruence. 
   EvalOp.
 Qed.
 
-Lemma eval_cast8signed:
-  forall sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_expr ge sp le e m1 (cast8signed a) t m2 (Val.cast8signed v).
+Theorem eval_cast8signed:
+  forall le a v,
+  eval_expr ge sp e m le a v ->
+  eval_expr ge sp e m le (cast8signed a) (Val.cast8signed v).
 Proof. 
-  intros until v; unfold cast8signed; case (cast8signed_match a); intros.
-  replace (Val.cast8signed v) with v. auto. 
-  InvEval H. inversion EQ. destruct v0; simpl; auto. rewrite Int.cast8_signed_idem. reflexivity.
+  intros until v; unfold cast8signed; case (cast8signed_match a); intros; InvEval.
+  EvalOp. simpl. subst v. destruct v1; simpl; auto. rewrite Int.cast8_signed_idem. reflexivity.
   EvalOp.
 Qed.
 
-Lemma eval_cast8unsigned:
-  forall sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_expr ge sp le e m1 (cast8unsigned a) t m2 (Val.cast8unsigned v).
+Theorem eval_cast8unsigned:
+  forall le a v,
+  eval_expr ge sp e m le a v ->
+  eval_expr ge sp e m le (cast8unsigned a) (Val.cast8unsigned v).
 Proof. 
-  intros until v; unfold cast8unsigned; case (cast8unsigned_match a); intros.
-  replace (Val.cast8unsigned v) with v. auto. 
-  InvEval H. inversion EQ. destruct v0; simpl; auto. rewrite Int.cast8_unsigned_idem. reflexivity.
+  intros until v; unfold cast8unsigned; case (cast8unsigned_match a); intros; InvEval.
+  EvalOp. simpl. subst v. destruct v1; simpl; auto. rewrite Int.cast8_unsigned_idem. reflexivity.
   EvalOp.
 Qed.
 
-Lemma eval_cast16signed:
-  forall sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_expr ge sp le e m1 (cast16signed a) t m2 (Val.cast16signed v).
+Theorem eval_cast16signed:
+  forall le a v,
+  eval_expr ge sp e m le a v ->
+  eval_expr ge sp e m le (cast16signed a) (Val.cast16signed v).
 Proof. 
-  intros until v; unfold cast16signed; case (cast16signed_match a); intros.
-  replace (Val.cast16signed v) with v. auto. 
-  InvEval H. inversion EQ. destruct v0; simpl; auto. rewrite Int.cast16_signed_idem. reflexivity.
+  intros until v; unfold cast16signed; case (cast16signed_match a); intros; InvEval.
+  EvalOp. simpl. subst v. destruct v1; simpl; auto. rewrite Int.cast16_signed_idem. reflexivity.
   EvalOp.
 Qed.
 
-Lemma eval_cast16unsigned:
-  forall sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_expr ge sp le e m1 (cast16unsigned a) t m2 (Val.cast16unsigned v).
+Theorem eval_cast16unsigned:
+  forall le a v,
+  eval_expr ge sp e m le a v ->
+  eval_expr ge sp e m le (cast16unsigned a) (Val.cast16unsigned v).
 Proof. 
-  intros until v; unfold cast16unsigned; case (cast16unsigned_match a); intros.
-  replace (Val.cast16unsigned v) with v. auto. 
-  InvEval H. inversion EQ. destruct v0; simpl; auto. rewrite Int.cast16_unsigned_idem. reflexivity.
+  intros until v; unfold cast16unsigned; case (cast16unsigned_match a); intros; InvEval.
+  EvalOp. simpl. subst v. destruct v1; simpl; auto. rewrite Int.cast16_unsigned_idem. reflexivity.
   EvalOp.
 Qed.
 
-Lemma eval_singleoffloat:
-  forall sp le e m1 a t m2 v,
-  eval_expr ge sp le e m1 a t m2 v ->
-  eval_expr ge sp le e m1 (singleoffloat a) t m2 (Val.singleoffloat v).
+Theorem eval_singleoffloat:
+  forall le a v,
+  eval_expr ge sp e m le a v ->
+  eval_expr ge sp e m le (singleoffloat a) (Val.singleoffloat v).
 Proof. 
-  intros until v; unfold singleoffloat; case (singleoffloat_match a); intros.
-  replace (Val.singleoffloat v) with v. auto. 
-  InvEval H. inversion EQ. destruct v0; simpl; auto. rewrite Float.singleoffloat_idem. reflexivity.
+  intros until v; unfold singleoffloat; case (singleoffloat_match a); intros; InvEval.
+  EvalOp. simpl. subst v. destruct v1; simpl; auto. rewrite Float.singleoffloat_idem. reflexivity.
   EvalOp.
 Qed.
 
 Lemma eval_base_condition_of_expr:
-  forall sp le a e m1 t m2 v (b: bool),
-  eval_expr ge sp le e m1 a t m2 v ->
+  forall le a v b,
+  eval_expr ge sp e m le a v ->
   Val.bool_of_val v b ->
-  eval_condexpr ge sp le e m1 
+  eval_condexpr ge sp e m le 
                 (CEcond (Ccompimm Cne Int.zero) (a ::: Enil))
-                t m2 b.
+                b.
 Proof.
   intros. 
   eapply eval_CEcond. eauto with evalexpr. 
@@ -925,90 +793,81 @@ Proof.
 Qed.
 
 Lemma eval_condition_of_expr:
-  forall a sp le e m1 t m2 v (b: bool),
-  eval_expr ge sp le e m1 a t m2 v ->
+  forall a le v b,
+  eval_expr ge sp e m le a v ->
   Val.bool_of_val v b ->
-  eval_condexpr ge sp le e m1 (condexpr_of_expr a) t m2 b.
+  eval_condexpr ge sp e m le (condexpr_of_expr a) b.
 Proof.
   induction a; simpl; intros;
     try (eapply eval_base_condition_of_expr; eauto; fail).
+  
   destruct o; try (eapply eval_base_condition_of_expr; eauto; fail).
 
-  destruct e. InvEval H. inversion XX3; subst v.
+  destruct e0. InvEval. 
   inversion H0. 
   rewrite Int.eq_false; auto. constructor.
   subst i; rewrite Int.eq_true. constructor.
   eapply eval_base_condition_of_expr; eauto.
 
-  inversion H. subst. eapply eval_CEcond; eauto. simpl in H11.
-  destruct (eval_condition c vl); try discriminate.
-  destruct b0; inversion H11; subst; inversion H0; congruence.
+  inv H. eapply eval_CEcond; eauto. simpl in H6. 
+  destruct (eval_condition c vl m); try discriminate.
+  destruct b0; inv H6; inversion H0; congruence.
 
-  inversion H. subst.
-  destruct v1; eauto with evalexpr.
+  inv H. destruct v1; eauto with evalexpr.
 Qed.
 
 Lemma eval_addressing:
-  forall sp le e m1 a t m2 v b ofs,
-  eval_expr ge sp le e m1 a t m2 v ->
+  forall le a v b ofs,
+  eval_expr ge sp e m le a v ->
   v = Vptr b ofs ->
   match addressing a with (mode, args) =>
     exists vl,
-    eval_exprlist ge sp le e m1 args t m2 vl /\ 
+    eval_exprlist ge sp e m le args vl /\ 
     eval_addressing ge sp mode vl = Some v
   end.
 Proof.
-  intros until v. unfold addressing; case (addressing_match a); intros.
-  InvEval H. exists (@nil val). split. eauto with evalexpr. 
-  simpl. auto.
-  InvEval H. exists (@nil val). split. eauto with evalexpr. 
-  simpl. auto.
-  InvEval H. InvEval EV. rewrite E0_left in TR. subst t1. FuncInv. 
-    congruence.
-    destruct (Genv.find_symbol ge s); congruence.
-    exists (Vint i0 :: nil). split. eauto with evalexpr. 
-    simpl. subst v. destruct (Genv.find_symbol ge s). congruence.
-    discriminate.
-  InvEval H. FuncInv. 
-    congruence.
-    exists (Vptr b0 i :: nil). split. eauto with evalexpr. 
+  intros until v. unfold addressing; case (addressing_match a); intros; InvEval.
+  exists (@nil val). split. eauto with evalexpr. simpl. auto.
+  exists (@nil val). split. eauto with evalexpr. simpl. auto.
+  destruct (Genv.find_symbol ge s); congruence.
+  exists (Vint i0 :: nil). split. eauto with evalexpr. 
+    simpl. destruct (Genv.find_symbol ge s). congruence. discriminate.
+  exists (Vptr b0 i :: nil). split. eauto with evalexpr. 
     simpl. congruence.
-  InvEval H. FuncInv. 
-    congruence.
-    exists (Vint i :: Vptr b0 i0 :: nil).
+  exists (Vint i :: Vptr b0 i0 :: nil).
     split. eauto with evalexpr. simpl. 
     rewrite Int.add_commut. congruence.
-    exists (Vptr b0 i :: Vint i0 :: nil).
+  exists (Vptr b0 i :: Vint i0 :: nil).
     split. eauto with evalexpr. simpl. congruence.
   exists (v :: nil). split. eauto with evalexpr. 
     subst v. simpl. rewrite Int.add_zero. auto.
 Qed.
 
 Lemma eval_load:
-  forall sp le e m1 a t m2 v chunk v',
-  eval_expr ge sp le e m1 a t m2 v ->
-  Mem.loadv chunk m2 v = Some v' ->
-  eval_expr ge sp le e m1 (load chunk a) t m2 v'.
+  forall le a v chunk v',
+  eval_expr ge sp e m le a v ->
+  Mem.loadv chunk m v = Some v' ->
+  eval_expr ge sp e m le (load chunk a) v'.
 Proof.
   intros. generalize H0; destruct v; simpl; intro; try discriminate.
   unfold load. 
-  generalize (eval_addressing _ _ _ _ _ _ _ _ _ _ H (refl_equal _)).
+  generalize (eval_addressing _ _ _ _ _ H (refl_equal _)).
   destruct (addressing a). intros [vl [EV EQ]]. 
   eapply eval_Eload; eauto. 
 Qed.
 
 Lemma eval_store:
-  forall sp le e m1 a1 t1 m2 v1 a2 t2 m3 v2 chunk m4,
-  eval_expr ge sp le e m1 a1 t1 m2 v1 ->
-  eval_expr ge sp le e m2 a2 t2 m3 v2 ->
-  Mem.storev chunk m3 v1 v2 = Some m4 ->
-  eval_expr ge sp le e m1 (store chunk a1 a2) (t1**t2) m4 v2.
+  forall chunk a1 a2 v1 v2 m',
+  eval_expr ge sp e m nil a1 v1 ->
+  eval_expr ge sp e m nil a2 v2 ->
+  Mem.storev chunk m v1 v2 = Some m' ->
+  exec_stmt ge sp e m (store chunk a1 a2) E0 e m' Out_normal.
 Proof.
   intros. generalize H1; destruct v1; simpl; intro; try discriminate.
   unfold store.
-  generalize (eval_addressing _ _ _ _ _ _ _ _ _ _ H (refl_equal _)).
+  generalize (eval_addressing _ _ _ _ _ H (refl_equal _)).
   destruct (addressing a1). intros [vl [EV EQ]]. 
-  eapply eval_Estore; eauto. 
+  eapply exec_Sstore; eauto. 
 Qed.
 
 (** * Correctness of instruction selection for operators *)
@@ -1018,10 +877,10 @@ Qed.
   the results of the previous section. *)
 
 Lemma eval_sel_unop:
-  forall sp le e m op a1 t m1 v1 v,
-  eval_expr ge sp le e m a1 t m1 v1 ->
+  forall le op a1 v1 v,
+  eval_expr ge sp e m le a1 v1 ->
   eval_unop op v1 = Some v ->
-  eval_expr ge sp le e m (sel_unop op a1) t m1 v.
+  eval_expr ge sp e m le (sel_unop op a1) v.
 Proof.
   destruct op; simpl; intros; FuncInv; try subst v.
   apply eval_cast8unsigned; auto.
@@ -1044,39 +903,39 @@ Proof.
 Qed.
 
 Lemma eval_sel_binop:
-  forall sp le e m op a1 a2 t1 m1 v1 t2 m2 v2 v,
-  eval_expr ge sp le e m a1 t1 m1 v1 ->
-  eval_expr ge sp le e m1 a2 t2 m2 v2 ->
-  eval_binop op v1 v2 m2 = Some v ->
-  eval_expr ge sp le e m (sel_binop op a1 a2) (t1 ** t2) m2 v.
+  forall le op a1 a2 v1 v2 v,
+  eval_expr ge sp e m le a1 v1 ->
+  eval_expr ge sp e m le a2 v2 ->
+  eval_binop op v1 v2 m = Some v ->
+  eval_expr ge sp e m le (sel_binop op a1 a2) v.
 Proof.
   destruct op; simpl; intros; FuncInv; try subst v.
-  eapply eval_add; eauto.
-  eapply eval_add_ptr_2; eauto.
-  eapply eval_add_ptr; eauto.
-  eapply eval_sub; eauto.
-  eapply eval_sub_ptr_int; eauto.
+  apply eval_add; auto.
+  apply eval_add_ptr_2; auto.
+  apply eval_add_ptr; auto.
+  apply eval_sub; auto.
+  apply eval_sub_ptr_int; auto.
   destruct (eq_block b b0); inv H1. 
   eapply eval_sub_ptr_ptr; eauto.
-  eapply eval_mul; eauto.
-  generalize (Int.eq_spec i0 Int.zero). intro. destruct (Int.eq i0 Int.zero); inv H1.
-  eapply eval_divs; eauto.
-  generalize (Int.eq_spec i0 Int.zero). intro. destruct (Int.eq i0 Int.zero); inv H1.
-  eapply eval_divu; eauto.
-  generalize (Int.eq_spec i0 Int.zero). intro. destruct (Int.eq i0 Int.zero); inv H1.
-  eapply eval_mods; eauto.
-  generalize (Int.eq_spec i0 Int.zero). intro. destruct (Int.eq i0 Int.zero); inv H1.
-  eapply eval_modu; eauto.
-  eapply eval_and; eauto.
-  eapply eval_or; eauto.
+  apply eval_mul; eauto.
+  generalize (Int.eq_spec i0 Int.zero). destruct (Int.eq i0 Int.zero); inv H1.
+  apply eval_divs; eauto.
+  generalize (Int.eq_spec i0 Int.zero). destruct (Int.eq i0 Int.zero); inv H1.
+  apply eval_divu; eauto.
+  generalize (Int.eq_spec i0 Int.zero). destruct (Int.eq i0 Int.zero); inv H1.
+  apply eval_mods; eauto.
+  generalize (Int.eq_spec i0 Int.zero). destruct (Int.eq i0 Int.zero); inv H1.
+  apply eval_modu; eauto.
+  apply eval_and; auto.
+  apply eval_or; auto.
   EvalOp.
   caseEq (Int.ltu i0 (Int.repr 32)); intro; rewrite H2 in H1; inv H1.
-  eapply eval_shl; eauto.
+  apply eval_shl; auto.
   EvalOp.
   caseEq (Int.ltu i0 (Int.repr 32)); intro; rewrite H2 in H1; inv H1.
-  eapply eval_shru; eauto.
-  eapply eval_addf; eauto.
-  eapply eval_subf; eauto.
+  apply eval_shru; auto.
+  apply eval_addf; auto.
+  apply eval_subf; auto.
   EvalOp.
   EvalOp.
   EvalOp. simpl. destruct (Int.cmp c i i0); auto. 
@@ -1087,7 +946,7 @@ Proof.
   destruct (Int.eq i0 Int.zero). destruct c; intro EQ; inv EQ; auto.
   auto.
   EvalOp. simpl. 
-  destruct (valid_pointer m2 b (Int.signed i) && valid_pointer m2 b0 (Int.signed i0)).
+  destruct (valid_pointer m b (Int.signed i) && valid_pointer m b0 (Int.signed i0)).
   destruct (eq_block b b0); inv H1. 
   destruct (Int.cmp c i i0); auto.
   auto.
@@ -1141,21 +1000,15 @@ Proof.
   intros. destruct f; reflexivity.
 Qed.
 
-(** This is the main semantic preservation theorem:
-  instruction selection preserves the semantics of function invocations.
-  The proof is an induction over the Cminor evaluation derivation. *)
+(** Semantic preservation for expressions. *)
 
-Lemma sel_function_correct:
-  forall m fd vargs t m' vres,
-  Cminor.eval_funcall ge m fd vargs t m' vres ->
-  CminorSel.eval_funcall tge m (sel_fundef fd) vargs t m' vres.
+Lemma sel_expr_correct:
+  forall sp e m a v,
+  Cminor.eval_expr ge sp e m a v ->
+  forall le,
+  eval_expr tge sp e m le (sel_expr a) v.
 Proof.
-  apply (Cminor.eval_funcall_ind4 ge
-          (fun sp le e m a t m' v => eval_expr tge sp le e m (sel_expr a) t m' v)
-          (fun sp le e m a t m' v => eval_exprlist tge sp le e m (sel_exprlist a) t m' v)
-          (fun m fd vargs t m' vres => eval_funcall tge m (sel_fundef fd) vargs t m' vres)
-          (fun sp e m s t e' m' out => exec_stmt tge sp e m (sel_stmt s) t e' m' out));
-  intros; simpl.
+  induction 1; intros; simpl.
   (* Evar *)
   constructor; auto.
   (* Econst *)
@@ -1164,40 +1017,65 @@ Proof.
   (* Eunop *)
   eapply eval_sel_unop; eauto.
   (* Ebinop *)
-  subst t. eapply eval_sel_binop; eauto.
+  eapply eval_sel_binop; eauto.
   (* Eload *)
   eapply eval_load; eauto.
-  (* Estore *)
-  subst t. eapply eval_store; eauto.
-  (* Ecall *)
-  econstructor; eauto. apply functions_translated; auto.
-  rewrite <- H4. apply sig_function_translated.
   (* Econdition *)
   econstructor; eauto. eapply eval_condition_of_expr; eauto. 
   destruct b1; auto.
-  (* Elet *)
-  econstructor; eauto.
-  (* Eletvar *)
-  constructor; auto.
-  (* Ealloc *)
-  econstructor; eauto.
-  (* Enil *)
-  constructor.
-  (* Econs *)
-  econstructor; eauto.
+Qed.
+
+Hint Resolve sel_expr_correct: evalexpr.
+
+Lemma sel_exprlist_correct:
+  forall sp e m a v,
+  Cminor.eval_exprlist ge sp e m a v ->
+  forall le,
+  eval_exprlist tge sp e m le (sel_exprlist a) v.
+Proof.
+  induction 1; intros; simpl; constructor; auto with evalexpr.
+Qed.
+
+Hint Resolve sel_exprlist_correct: evalexpr.
+
+(** Semantic preservation for terminating function calls and statements. *)
+
+Definition eval_funcall_exec_stmt_ind2
+  (P1 : mem -> Cminor.fundef -> list val -> trace -> mem -> val -> Prop)
+  (P2 : val -> env -> mem -> Cminor.stmt -> trace -> env -> mem -> outcome -> Prop) :=
+  fun a b c d e f g h i j k l m n o p q r =>
+  conj (Cminor.eval_funcall_ind2 ge P1 P2 a b c d e f g h i j k l m n o p q r)
+       (Cminor.exec_stmt_ind2 ge P1 P2 a b c d e f g h i j k l m n o p q r).
+
+Lemma sel_function_stmt_correct:
+     (forall m fd vargs t m' vres,
+      Cminor.eval_funcall ge m fd vargs t m' vres ->
+      CminorSel.eval_funcall tge m (sel_fundef fd) vargs t m' vres)
+  /\ (forall sp e m s t e' m' out,
+      Cminor.exec_stmt ge sp e m s t e' m' out ->
+      CminorSel.exec_stmt tge sp e m (sel_stmt s) t e' m' out).
+Proof.
+  apply eval_funcall_exec_stmt_ind2; intros; simpl.
   (* Internal function *)
   econstructor; eauto. 
   (* External function *)
   econstructor; eauto.
   (* Sskip *)
   constructor.
-  (* Sexpr *)
-  econstructor; eauto.
   (* Sassign *)
-  econstructor; eauto.
+  econstructor; eauto with evalexpr. 
+  (* Sstore *)
+  eapply eval_store; eauto with evalexpr. 
+  (* Scall *)
+  econstructor; eauto with evalexpr.
+  apply functions_translated; auto.
+  rewrite <- H2. apply sig_function_translated.
+  (* Salloc *)
+  econstructor; eauto with evalexpr.
   (* Sifthenelse *)
-  econstructor; eauto. eapply eval_condition_of_expr; eauto.
-  destruct b1; auto.
+  econstructor; eauto with evalexpr.
+  eapply eval_condition_of_expr; eauto with evalexpr.
+  destruct b; auto.
   (* Sseq *)
   eapply exec_Sseq_continue; eauto.
   eapply exec_Sseq_stop; eauto.
@@ -1209,32 +1087,97 @@ Proof.
   (* Sexit *)
   constructor.
   (* Sswitch *)
-  econstructor; eauto.
+  econstructor; eauto with evalexpr.
   (* Sreturn *)
   constructor.
-  econstructor; eauto.
+  econstructor; eauto with evalexpr.
   (* Stailcall *)
-  econstructor; eauto. apply functions_translated; auto.
-  rewrite <- H4. apply sig_function_translated.
+  econstructor; eauto with evalexpr.
+  apply functions_translated; auto.
+  rewrite <- H2. apply sig_function_translated.
 Qed.
 
+Lemma sel_function_correct:
+      forall m fd vargs t m' vres,
+      Cminor.eval_funcall ge m fd vargs t m' vres ->
+      CminorSel.eval_funcall tge m (sel_fundef fd) vargs t m' vres.
+Proof (proj1 sel_function_stmt_correct).
+
+Lemma sel_stmt_correct:
+      forall sp e m s t e' m' out,
+      Cminor.exec_stmt ge sp e m s t e' m' out ->
+      CminorSel.exec_stmt tge sp e m (sel_stmt s) t e' m' out.
+Proof (proj2 sel_function_stmt_correct).
+
+Hint Resolve sel_stmt_correct: evalexpr.
+
+(** Semantic preservation for diverging function calls and statements. *)
+
+Lemma sel_function_divergence_correct:
+  forall m fd vargs t,
+  Cminor.evalinf_funcall ge m fd vargs t ->
+  CminorSel.evalinf_funcall tge m (sel_fundef fd) vargs t.
+Proof.
+  cofix FUNCALL.
+  assert (STMT: forall sp e m s t,
+            Cminor.execinf_stmt ge sp e m s t ->
+            CminorSel.execinf_stmt tge sp e m (sel_stmt s) t).
+  cofix STMT; intros.
+  inversion H; subst; simpl.
+  (* Call *)
+  econstructor; eauto with evalexpr.
+  apply functions_translated; auto.
+  apply sig_function_translated.
+  (* Ifthenelse *)
+  econstructor; eauto with evalexpr.
+  eapply eval_condition_of_expr; eauto with evalexpr.
+  destruct b; eapply STMT; eauto.
+  (* Seq *)
+  apply execinf_Sseq_1; eauto.
+  eapply execinf_Sseq_2; eauto with evalexpr.
+  (* Loop *)
+  eapply execinf_Sloop_body; eauto.
+  eapply execinf_Sloop_loop; eauto with evalexpr.
+  change (Sloop (sel_stmt s0)) with (sel_stmt (Cminor.Sloop s0)).
+  apply STMT. auto.
+  (* Block *)
+  apply execinf_Sblock; eauto.
+  (* Tailcall *)
+  econstructor; eauto with evalexpr.
+  apply functions_translated; auto.
+  apply sig_function_translated.
+
+  intros. inv H; simpl.
+  (* Internal functions *)
+  econstructor; eauto with evalexpr.
+  unfold sel_function; simpl. eapply STMT; eauto. 
+Qed. 
+
 End PRESERVATION.
 
 (** As a corollary, instruction selection preserves the observable
    behaviour of programs. *)
 
 Theorem sel_program_correct:
-  forall prog t r,
-  Cminor.exec_program prog t r ->
-  CminorSel.exec_program (sel_program prog) t r.
+  forall prog beh,
+  Cminor.exec_program prog beh ->
+  CminorSel.exec_program (sel_program prog) beh.
 Proof.
-  intros.
-  destruct H as [b [f [m [FINDS [FINDF [SIG EXEC]]]]]].
-  exists b; exists (sel_fundef f); exists m.
-  split. simpl. rewrite <- FINDS. apply symbols_preserved.
-  split. apply function_ptr_translated. auto.
-  split. rewrite <- SIG. apply sig_function_translated. 
+  intros. inv H. 
+  (* Terminating *)
+  apply program_terminates with b (sel_fundef f) m.
+  simpl. rewrite <- H0. unfold ge. apply symbols_preserved.
+  apply function_ptr_translated. auto.
+  rewrite <- H2. apply sig_function_translated. 
   replace (Genv.init_mem (sel_program prog)) with (Genv.init_mem prog).
   apply sel_function_correct; auto.
   symmetry. unfold sel_program. apply Genv.init_mem_transf.
+  (* Diverging *)
+  apply program_diverges with b (sel_fundef f).
+  simpl. rewrite <- H0. unfold ge. apply symbols_preserved.
+  apply function_ptr_translated. auto.
+  rewrite <- H2. apply sig_function_translated. 
+  replace (Genv.init_mem (sel_program prog)) with (Genv.init_mem prog).
+  apply sel_function_divergence_correct; auto.
+  symmetry. unfold sel_program. apply Genv.init_mem_transf.
 Qed.
diff --git a/caml/CMlexer.mll b/caml/CMlexer.mll
index ae71e0c13..7951982f2 100644
--- a/caml/CMlexer.mll
+++ b/caml/CMlexer.mll
@@ -99,6 +99,7 @@ rule token = parse
   | "*" { STAR }
   | "*f"    { STARF }
   | "switch"    { SWITCH }
+  | "tailcall"  { TAILCALL }
   | "~"    { TILDE }
   | "var"    { VAR }
   | "void"    { VOID }
diff --git a/caml/CMparser.mly b/caml/CMparser.mly
index 0db0af2b5..fb095275a 100644
--- a/caml/CMparser.mly
+++ b/caml/CMparser.mly
@@ -10,22 +10,136 @@ open Integers
 open AST
 open Cminor
 
+(** Naming function calls in expressions *)
+
+type rexpr =
+  | Rvar of ident
+  | Rconst of constant
+  | Runop of unary_operation * rexpr
+  | Rbinop of binary_operation * rexpr * rexpr
+  | Rload of memory_chunk * rexpr
+  | Rcondition of rexpr * rexpr * rexpr
+  | Rcall of signature * rexpr * rexpr list
+  | Ralloc of rexpr
+
+let temp_counter = ref 0
+
+let temporaries = ref Coq_nil
+
+let mktemp () =
+  incr temp_counter;
+  let n = Printf.sprintf "__t%d" !temp_counter in
+  let id = intern_string n in
+  temporaries := Coq_cons(id, !temporaries);
+  id
+
+let convert_accu = ref []
+
+let rec convert_rexpr = function
+  | Rvar id -> Evar id
+  | Rconst c -> Econst c
+  | Runop(op, e1) -> Eunop(op, convert_rexpr e1)
+  | Rbinop(op, e1, e2) ->
+      let c1 = convert_rexpr e1 in
+      let c2 = convert_rexpr e2 in
+      Ebinop(op, c1, c2)
+  | Rload(chunk, e1) -> Eload(chunk, convert_rexpr e1)
+  | Rcondition(e1, e2, e3) ->
+      let c1 = convert_rexpr e1 in
+      let c2 = convert_rexpr e2 in
+      let c3 = convert_rexpr e3 in
+      Econdition(c1, c2, c3)
+  | Rcall(sg, e1, el) ->
+      let c1 = convert_rexpr e1 in
+      let cl = convert_rexpr_list el in
+      let t = mktemp() in
+      convert_accu := Scall(Some t, sg, c1, cl) :: !convert_accu;
+      Evar t
+  | Ralloc e1 ->
+      let c1 = convert_rexpr e1 in
+      let t = mktemp() in
+      convert_accu := Salloc(t, c1) :: !convert_accu;
+      Evar t
+
+and convert_rexpr_list = function
+  | Coq_nil -> Coq_nil
+  | Coq_cons(e1, el) ->
+      let c1 = convert_rexpr e1 in
+      let cl = convert_rexpr_list el in
+      Coq_cons(c1, cl)
+
+let rec prepend_seq stmts last =
+  match stmts with
+  | [] -> last
+  | s1 :: sl -> prepend_seq sl (Sseq(s1, last))
+
+let mkeval e =
+  convert_accu := [];
+  match e with
+  | Rcall(sg, e1, el) ->
+      let c1 = convert_rexpr e1 in
+      let cl = convert_rexpr_list el in
+      prepend_seq !convert_accu (Scall(None, sg, c1, cl))
+  | _ ->
+      ignore (convert_rexpr e);
+      prepend_seq !convert_accu Sskip
+
+let mkassign id e =
+  convert_accu := [];
+  match e with
+  | Rcall(sg, e1, el) ->
+      let c1 = convert_rexpr e1 in
+      let cl = convert_rexpr_list el in
+      prepend_seq !convert_accu (Scall(Some id, sg, c1, cl))
+  | Ralloc(e1) ->
+      let c1 = convert_rexpr e1 in
+      prepend_seq !convert_accu (Salloc(id, c1))
+  | _ ->
+      let c = convert_rexpr e in
+      prepend_seq !convert_accu (Sassign(id, c))
+
+let mkstore chunk e1 e2 =
+  convert_accu := [];
+  let c1 = convert_rexpr e1 in
+  let c2 = convert_rexpr e2 in
+  prepend_seq !convert_accu (Sstore(chunk, c1, c2))
+
+let mkifthenelse e s1 s2 =
+  convert_accu := [];
+  let c = convert_rexpr e in
+  prepend_seq !convert_accu (Sifthenelse(c, s1, s2))
+
+let mkreturn_some e =
+  convert_accu := [];
+  let c = convert_rexpr e in
+  prepend_seq !convert_accu (Sreturn (Some c))
+
+let mktailcall sg e1 el =
+  convert_accu := [];
+  let c1 = convert_rexpr e1 in
+  let cl = convert_rexpr_list el in
+  prepend_seq !convert_accu (Stailcall(sg, c1, cl))
+
+(** Other constructors *)
+
 let intconst n =
-  Econst(Ointconst(coqint_of_camlint n))
+  Rconst(Ointconst(coqint_of_camlint n))
 
 let andbool e1 e2 =
-  Econdition(e1, e2, intconst 0l)
+  Rcondition(e1, e2, intconst 0l)
 let orbool e1 e2 =
-  Econdition(e1, intconst 1l, e2)
+  Rcondition(e1, intconst 1l, e2)
 
 let exitnum n = nat_of_camlint(Int32.pred n)
 
 let mkswitch expr (cases, dfl) =
+  convert_accu := [];
+  let c = convert_rexpr expr in
   let rec mktable = function
   | [] -> Coq_nil
   | (key, exit) :: rem ->
       Coq_cons(Coq_pair(coqint_of_camlint key, exitnum exit), mktable rem) in
-  Sswitch(expr, mktable cases, exitnum dfl)
+  prepend_seq !convert_accu (Sswitch(c, mktable cases, exitnum dfl))
 
 (***
    match (a) { case 0: s0; case 1: s1; case 2: s2; }  --->
@@ -65,10 +179,14 @@ let mkmatch_aux expr cases =
   mkblocks (Sblock sw) (Int32.pred ncases) cases
 
 let mkmatch expr cases =
-  match cases with
-  | [] -> Sskip (* ??? *)
-  | [key, action] -> action
-  | _ -> mkmatch_aux expr cases
+  convert_accu := [];
+  let c = convert_rexpr expr in
+  let s =
+    match cases with
+    | [] -> Sskip (* ??? *)
+    | [key, action] -> action
+    | _ -> mkmatch_aux c cases in
+  prepend_seq !convert_accu s
 
 %}
 
@@ -158,6 +276,7 @@ let mkmatch expr cases =
 %token <AST.ident> STRINGLIT
 %token SWITCH
 %token TILDE
+%token TAILCALL
 %token VAR
 %token VOID
 
@@ -221,10 +340,13 @@ proc:
       var_declarations
       stmt_list
     RBRACE
-      { Coq_pair($1,
+      { let tmp = !temporaries in
+        temporaries := Coq_nil;
+        temp_counter := 0;
+        Coq_pair($1,
         Internal { fn_sig = $6;
                    fn_params = CList.rev $3;
-                   fn_vars = CList.rev $9;
+                   fn_vars = CList.rev (CList.app tmp $9);
                    fn_stackspace = $8;
                    fn_body = $10 }) }
   | EXTERN STRINGLIT COLON signature 
@@ -269,20 +391,24 @@ var_declaration:
 /* Statements */
 
 stmt:
-    expr SEMICOLON                              { Sexpr $1 }
-  | IDENT EQUAL expr SEMICOLON                  { Sassign($1, $3) }
-  | IF LPAREN expr RPAREN stmts ELSE stmts      { Sifthenelse($3, $5, $7) }
-  | IF LPAREN expr RPAREN stmts                 { Sifthenelse($3, $5, Sskip) }
+    expr SEMICOLON                              { mkeval $1 }
+  | IDENT EQUAL expr SEMICOLON                  { mkassign $1 $3 }
+  | memory_chunk LBRACKET expr RBRACKET EQUAL expr SEMICOLON
+                                                { mkstore $1 $3 $6 }
+  | IF LPAREN expr RPAREN stmts ELSE stmts      { mkifthenelse $3 $5 $7 }
+  | IF LPAREN expr RPAREN stmts                 { mkifthenelse $3 $5 Sskip }
   | LOOP stmts                                  { Sloop($2) }
   | LBRACELBRACE stmt_list RBRACERBRACE         { Sblock($2) }
   | EXIT SEMICOLON                              { Sexit O }
   | EXIT INTLIT SEMICOLON                       { Sexit (exitnum $2) }
   | RETURN SEMICOLON                            { Sreturn None }
-  | RETURN expr SEMICOLON                       { Sreturn (Some $2) }
+  | RETURN expr SEMICOLON                       { mkreturn_some $2 }
   | SWITCH LPAREN expr RPAREN LBRACE switch_cases RBRACE
                                                 { mkswitch $3 $6 }
   | MATCH LPAREN expr RPAREN LBRACE match_cases RBRACE
                                                 { mkmatch $3 $6 }
+  | TAILCALL expr LPAREN expr_list RPAREN COLON signature SEMICOLON
+                                                { mktailcall $7 $2 $4 }
 ;
 
 stmts:
@@ -311,80 +437,75 @@ match_cases:
 
 expr:
     LPAREN expr RPAREN                          { $2 }
-  | IDENT                                       { Evar $1 }
+  | IDENT                                       { Rvar $1 }
   | INTLIT                                      { intconst $1 }
-  | FLOATLIT                                    { Econst(Ofloatconst $1) }
-  | STRINGLIT                                   { Econst(Oaddrsymbol($1, Int.zero)) }
-  | AMPERSAND INTLIT                            { Econst(Oaddrstack(coqint_of_camlint $2)) }
-  | MINUS expr    %prec p_uminus                { Eunop(Onegint, $2) }
-  | MINUSF expr   %prec p_uminus                { Eunop(Onegf, $2) }
-  | ABSF expr                                   { Eunop(Oabsf, $2) }
-  | INTOFFLOAT expr                             { Eunop(Ointoffloat, $2) }
-  | FLOATOFINT expr                             { Eunop(Ofloatofint, $2) }
-  | FLOATOFINTU expr                            { Eunop(Ofloatofintu, $2) }
-  | TILDE expr                                  { Eunop(Onotint, $2) }
-  | BANG expr                                   { Eunop(Onotbool, $2) }
-  | INT8S expr                                  { Eunop(Ocast8signed, $2) }
-  | INT8U expr                                  { Eunop(Ocast8unsigned, $2) }
-  | INT16S expr                                 { Eunop(Ocast16signed, $2) }
-  | INT16U expr                                 { Eunop(Ocast16unsigned, $2) }
-  | FLOAT32 expr                                { Eunop(Osingleoffloat, $2) }
-  | ALLOC expr                                  { Ealloc $2 }
-  | expr PLUS expr                              { Ebinop(Oadd, $1, $3) }
-  | expr MINUS expr                             { Ebinop(Osub, $1, $3) }
-  | expr STAR expr                              { Ebinop(Omul, $1, $3) }
-  | expr SLASH expr                             { Ebinop(Odiv, $1, $3) }
-  | expr PERCENT expr                           { Ebinop(Omod, $1, $3) }
-  | expr SLASHU expr                            { Ebinop(Odivu, $1, $3) }
-  | expr PERCENTU expr                          { Ebinop(Omodu, $1, $3) }
-  | expr AMPERSAND expr                         { Ebinop(Oand, $1, $3) }
-  | expr BAR expr                               { Ebinop(Oor, $1, $3) }
-  | expr CARET expr                             { Ebinop(Oxor, $1, $3) }
-  | expr LESSLESS expr                          { Ebinop(Oshl, $1, $3) }
-  | expr GREATERGREATER expr                    { Ebinop(Oshr, $1, $3) }
-  | expr GREATERGREATERU expr                   { Ebinop(Oshru, $1, $3) }
-  | expr PLUSF expr                             { Ebinop(Oaddf, $1, $3) }
-  | expr MINUSF expr                            { Ebinop(Osubf, $1, $3) }
-  | expr STARF expr                             { Ebinop(Omulf, $1, $3) }
-  | expr SLASHF expr                            { Ebinop(Odivf, $1, $3) }
-  | expr EQUALEQUAL expr                        { Ebinop(Ocmp Ceq, $1, $3) }
-  | expr BANGEQUAL expr                         { Ebinop(Ocmp Cne, $1, $3) }
-  | expr LESS expr                              { Ebinop(Ocmp Clt, $1, $3) }
-  | expr LESSEQUAL expr                         { Ebinop(Ocmp Cle, $1, $3) }
-  | expr GREATER expr                           { Ebinop(Ocmp Cgt, $1, $3) }
-  | expr GREATEREQUAL expr                      { Ebinop(Ocmp Cge, $1, $3) }
-  | expr EQUALEQUALU expr                       { Ebinop(Ocmpu Ceq, $1, $3) }
-  | expr BANGEQUALU expr                        { Ebinop(Ocmpu Cne, $1, $3) }
-  | expr LESSU expr                             { Ebinop(Ocmpu Clt, $1, $3) }
-  | expr LESSEQUALU expr                        { Ebinop(Ocmpu Cle, $1, $3) }
-  | expr GREATERU expr                          { Ebinop(Ocmpu Cgt, $1, $3) }
-  | expr GREATEREQUALU expr                     { Ebinop(Ocmpu Cge, $1, $3) }
-  | expr EQUALEQUALF expr                       { Ebinop(Ocmpf Ceq, $1, $3) }
-  | expr BANGEQUALF expr                        { Ebinop(Ocmpf Cne, $1, $3) }
-  | expr LESSF expr                             { Ebinop(Ocmpf Clt, $1, $3) }
-  | expr LESSEQUALF expr                        { Ebinop(Ocmpf Cle, $1, $3) }
-  | expr GREATERF expr                          { Ebinop(Ocmpf Cgt, $1, $3) }
-  | expr GREATEREQUALF expr                     { Ebinop(Ocmpf Cge, $1, $3) }
-  | memory_chunk LBRACKET expr RBRACKET         { Eload($1, $3) }
-  | memory_chunk LBRACKET expr RBRACKET EQUAL expr
-                                                { Estore($1, $3, $6) }
-  | expr LPAREN expr_list RPAREN COLON signature
-                                                { Ecall($6, $1, $3) }
+  | FLOATLIT                                    { Rconst(Ofloatconst $1) }
+  | STRINGLIT                                   { Rconst(Oaddrsymbol($1, Int.zero)) }
+  | AMPERSAND INTLIT                            { Rconst(Oaddrstack(coqint_of_camlint $2)) }
+  | MINUS expr    %prec p_uminus                { Rbinop(Osub, intconst 0l, $2) } /***FIXME***/
+  | MINUSF expr   %prec p_uminus                { Runop(Onegf, $2) }
+  | ABSF expr                                   { Runop(Oabsf, $2) }
+  | INTOFFLOAT expr                             { Runop(Ointoffloat, $2) }
+  | FLOATOFINT expr                             { Runop(Ofloatofint, $2) }
+  | FLOATOFINTU expr                            { Runop(Ofloatofintu, $2) }
+  | TILDE expr                                  { Runop(Onotint, $2) }
+  | BANG expr                                   { Runop(Onotbool, $2) }
+  | INT8S expr                                  { Runop(Ocast8signed, $2) }
+  | INT8U expr                                  { Runop(Ocast8unsigned, $2) }
+  | INT16S expr                                 { Runop(Ocast16signed, $2) }
+  | INT16U expr                                 { Runop(Ocast16unsigned, $2) }
+  | FLOAT32 expr                                { Runop(Osingleoffloat, $2) }
+  | expr PLUS expr                              { Rbinop(Oadd, $1, $3) }
+  | expr MINUS expr                             { Rbinop(Osub, $1, $3) }
+  | expr STAR expr                              { Rbinop(Omul, $1, $3) }
+  | expr SLASH expr                             { Rbinop(Odiv, $1, $3) }
+  | expr PERCENT expr                           { Rbinop(Omod, $1, $3) }
+  | expr SLASHU expr                            { Rbinop(Odivu, $1, $3) }
+  | expr PERCENTU expr                          { Rbinop(Omodu, $1, $3) }
+  | expr AMPERSAND expr                         { Rbinop(Oand, $1, $3) }
+  | expr BAR expr                               { Rbinop(Oor, $1, $3) }
+  | expr CARET expr                             { Rbinop(Oxor, $1, $3) }
+  | expr LESSLESS expr                          { Rbinop(Oshl, $1, $3) }
+  | expr GREATERGREATER expr                    { Rbinop(Oshr, $1, $3) }
+  | expr GREATERGREATERU expr                   { Rbinop(Oshru, $1, $3) }
+  | expr PLUSF expr                             { Rbinop(Oaddf, $1, $3) }
+  | expr MINUSF expr                            { Rbinop(Osubf, $1, $3) }
+  | expr STARF expr                             { Rbinop(Omulf, $1, $3) }
+  | expr SLASHF expr                            { Rbinop(Odivf, $1, $3) }
+  | expr EQUALEQUAL expr                        { Rbinop(Ocmp Ceq, $1, $3) }
+  | expr BANGEQUAL expr                         { Rbinop(Ocmp Cne, $1, $3) }
+  | expr LESS expr                              { Rbinop(Ocmp Clt, $1, $3) }
+  | expr LESSEQUAL expr                         { Rbinop(Ocmp Cle, $1, $3) }
+  | expr GREATER expr                           { Rbinop(Ocmp Cgt, $1, $3) }
+  | expr GREATEREQUAL expr                      { Rbinop(Ocmp Cge, $1, $3) }
+  | expr EQUALEQUALU expr                       { Rbinop(Ocmpu Ceq, $1, $3) }
+  | expr BANGEQUALU expr                        { Rbinop(Ocmpu Cne, $1, $3) }
+  | expr LESSU expr                             { Rbinop(Ocmpu Clt, $1, $3) }
+  | expr LESSEQUALU expr                        { Rbinop(Ocmpu Cle, $1, $3) }
+  | expr GREATERU expr                          { Rbinop(Ocmpu Cgt, $1, $3) }
+  | expr GREATEREQUALU expr                     { Rbinop(Ocmpu Cge, $1, $3) }
+  | expr EQUALEQUALF expr                       { Rbinop(Ocmpf Ceq, $1, $3) }
+  | expr BANGEQUALF expr                        { Rbinop(Ocmpf Cne, $1, $3) }
+  | expr LESSF expr                             { Rbinop(Ocmpf Clt, $1, $3) }
+  | expr LESSEQUALF expr                        { Rbinop(Ocmpf Cle, $1, $3) }
+  | expr GREATERF expr                          { Rbinop(Ocmpf Cgt, $1, $3) }
+  | expr GREATEREQUALF expr                     { Rbinop(Ocmpf Cge, $1, $3) }
+  | memory_chunk LBRACKET expr RBRACKET         { Rload($1, $3) }
   | expr AMPERSANDAMPERSAND expr                { andbool $1 $3 }
   | expr BARBAR expr                            { orbool $1 $3 }
-  | expr QUESTION expr COLON expr               { Econdition($1, $3, $5) }
-  | LET expr IN expr %prec p_let                { Elet($2, $4) }
-  | DOLLAR INTLIT                               { Eletvar (nat_of_camlint $2) }
+  | expr QUESTION expr COLON expr               { Rcondition($1, $3, $5) }
+  | expr LPAREN expr_list RPAREN COLON signature{ Rcall($6, $1, $3) }
+  | ALLOC expr                                  { Ralloc $2 }
 ;
 
 expr_list:
-    /* empty */                                 { Enil }
+    /* empty */                                 { Coq_nil }
   | expr_list_1                                 { $1 }
 ;
 
 expr_list_1:
-    expr                     %prec COMMA        { Econs($1, Enil) }
-  | expr COMMA expr_list_1                      { Econs($1, $3) }
+    expr                     %prec COMMA        { Coq_cons($1, Coq_nil) }
+  | expr COMMA expr_list_1                      { Coq_cons($1, $3) }
 ;
 
 memory_chunk:
diff --git a/caml/CMtypecheck.ml b/caml/CMtypecheck.ml
index 495ded0cf..9277829c4 100644
--- a/caml/CMtypecheck.ml
+++ b/caml/CMtypecheck.ml
@@ -206,30 +206,6 @@ let rec type_expr env lenv e =
                               (name_of_chunk chunk) s))
       end;
       type_chunk chunk
-  | Estore(chunk, e1, e2) ->
-      let te1 = type_expr env lenv e1 in
-      let te2 = type_expr env lenv e2 in
-      begin try
-        unify tint te1;
-        unify (type_chunk chunk) te2
-      with Error s ->
-        raise (Error (sprintf "In store %s:\n%s"
-                              (name_of_chunk chunk) s))
-      end;
-      te1
-  | Ecall(sg, e1, el) ->
-      let te1 = type_expr env lenv e1 in
-      let tel = type_exprlist env lenv el in
-      begin try
-        unify tint te1;
-        unify_list (ty_of_sig_args sg.sig_args) tel
-      with Error s ->
-        raise (Error (sprintf "In call:\n%s" s))
-      end;
-      begin match sg.sig_res with
-      | None -> tint (*???*)
-      | Some t -> ty_of_typ t
-      end
   | Econdition(e1, e2, e3) ->
       type_condexpr env lenv e1;
       let te2 = type_expr env lenv e2 in
@@ -240,25 +216,19 @@ let rec type_expr env lenv e =
         raise (Error (sprintf "In conditional expression:\n%s" s))
       end;
       te2
+(*
   | Elet(e1, e2) ->
       let te1 = type_expr env lenv e1 in
       let te2 = type_expr env (te1 :: lenv) e2 in
       te2
   | Eletvar n ->
       type_letvar lenv n
-  | Ealloc e ->
-      let te = type_expr env lenv e in
-      begin try
-        unify tint te
-      with Error s ->
-        raise (Error (sprintf "In alloc:\n%s" s))
-      end;
-      tint
+*)
 
 and type_exprlist env lenv el =
   match el with
-  | Enil -> []
-  | Econs (e1, et) ->
+  | Coq_nil -> []
+  | Coq_cons (e1, et) ->
       let te1 = type_expr env lenv e1 in
       let tet = type_exprlist env lenv et in
       (te1 :: tet)
@@ -274,8 +244,6 @@ and type_condexpr env lenv e =
 let rec type_stmt env blk ret s =
   match s with
   | Sskip -> ()
-  | Sexpr e -> 
-      ignore (type_expr env [] e)
   | Sassign(id, e1) ->
       let tid = type_var env id in
       let te1 = type_expr env [] e1 in
@@ -284,6 +252,42 @@ let rec type_stmt env blk ret s =
       with Error s ->
         raise (Error (sprintf "In assignment to %s:\n%s" (extern_atom id) s))
       end
+  | Sstore(chunk, e1, e2) ->
+      let te1 = type_expr env [] e1 in
+      let te2 = type_expr env [] e2 in
+      begin try
+        unify tint te1;
+        unify (type_chunk chunk) te2
+      with Error s ->
+        raise (Error (sprintf "In store %s:\n%s"
+                              (name_of_chunk chunk) s))
+      end
+  | Scall(optid, sg, e1, el) ->
+      let te1 = type_expr env [] e1 in
+      let tel = type_exprlist env [] el in
+      begin try
+        unify tint te1;
+        unify_list (ty_of_sig_args sg.sig_args) tel;
+        let ty_res =
+          match sg.sig_res with
+          | None -> tint (*???*)
+          | Some t -> ty_of_typ t in
+        begin match optid with
+        | None -> ()
+        | Some id -> unify (type_var env id) ty_res
+        end
+      with Error s ->
+        raise (Error (sprintf "In call:\n%s" s))
+      end
+  | Salloc(id, e) ->
+      let tid = type_var env id in
+      let te = type_expr env [] e in
+      begin try
+        unify tint te;
+        unify tint tid
+      with Error s ->
+        raise (Error (sprintf "In alloc:\n%s" s))
+      end
   | Sseq(s1, s2) ->
       type_stmt env blk ret s1;
       type_stmt env blk ret s2
diff --git a/caml/Cil2Csyntax.ml b/caml/Cil2Csyntax.ml
index 553229c64..0e168414d 100644
--- a/caml/Cil2Csyntax.ml
+++ b/caml/Cil2Csyntax.ml
@@ -3,6 +3,7 @@ CIL -> CabsCoq translator
 **************************************************************************)
 
 open Cil
+open CList
 open Camlcoq
 open AST
 open Csyntax
@@ -192,6 +193,17 @@ let declare_stub_functions k =
   Hashtbl.fold (fun n i k -> CList.Coq_cons(declare_stub_function n i, k))
                stub_function_table k
 
+(** ** Generation of temporary variable names *)
+
+let current_function = ref (None: Cil.fundec option)
+
+let make_temp typ =
+  match !current_function with
+  | None -> assert false
+  | Some f ->
+      let v = Cil.makeTempVar f typ in 
+      intern_string v.vname
+
 (** ** Translation functions *)
 
 (** Convert a [Cil.ikind] into a pair [(intsize * signedness)] *)
@@ -310,13 +322,13 @@ and processCast t e =
 
 (** Convert a [Cil.exp list] into an [CamlCoq.exprlist] *)
 and processParamsE = function
-  | [] -> Enil
+  | [] -> Coq_nil
   | e :: l ->
       let (Expr (_, t)) as e' = convertExp e in
 	match t with
 	  | Tstruct _ | Tunion _ ->
               unsupported "function parameter of struct or union type"
-	  | _ -> Econs (e', processParamsE l)
+	  | _ -> Coq_cons (e', processParamsE l)
 
 
 (** Convert a [Cil.exp] into a [CabsCoq.expr] *)
@@ -489,8 +501,8 @@ let convertVarinfoParam v =
 
 (** Convert a [Cil.exp] which has a function type into a [CabsCoq.expr]
     (used only to translate function calls) *)
-let convertExpFuncall e tfun eList =
-  match tfun with
+let convertExpFuncall e eList =
+  match typeOf e with
   | TFun (res, argListOpt, vArg, _) ->
       begin match argListOpt, vArg with
       | Some argList, false ->
@@ -512,8 +524,8 @@ let convertExpFuncall e tfun eList =
             | _ ->
                 unsupported "call to variadic or non-prototyped function" in
           let rec typeOfExprList = function
-            | Enil -> Tnil
-            | Econs (Expr (_, ty), rem) -> Tcons (ty, typeOfExprList rem) in
+            | Coq_nil -> Tnil
+            | Coq_cons (Expr (_, ty), rem) -> Tcons (ty, typeOfExprList rem) in
           let targs = typeOfExprList params in
           let tres = convertTyp res in
           let (stub_fun_name, stub_fun_typ) =
@@ -523,6 +535,33 @@ let convertExpFuncall e tfun eList =
       end
   | _ -> internal_error "convertExpFuncall: not a function"
 
+(** Auxiliaries for function calls *)
+
+let makeFuncall1 tyfun (Expr(_, tlhs) as elhs) efun eargs =
+  match tyfun with
+  | TFun (t, _, _, _) ->
+      let tres = convertTyp t in
+      if tlhs = tres then
+        Scall(Datatypes.Some elhs, efun, eargs)
+      else begin
+        let tmp = make_temp t in
+        let elhs' = Expr(Evar tmp, tres) in
+        Ssequence(Scall(Datatypes.Some elhs', efun, eargs),
+                  Sassign(elhs, Expr(Ecast(tlhs, elhs'), tlhs)))
+      end
+  | _ -> internal_error "wrong type for function in call"
+
+let makeFuncall2 tyfun tylhs elhs efun eargs =
+  match elhs with
+  | Expr(Evar _, _) ->
+      makeFuncall1 tyfun elhs efun eargs
+  | Expr(_, tlhs) ->
+      let tmp = make_temp tylhs in
+      let elhs' = Expr(Evar tmp, tlhs) in
+      Ssequence(makeFuncall1 tyfun elhs' efun eargs,
+                Sassign(elhs, elhs'))
+                
+
 (** Convert a [Cil.instr list] into a [CabsCoq.statement] *)
 let rec processInstrList l =
   (* convert an instruction *)
@@ -533,33 +572,14 @@ let rec processInstrList l =
         | Tstruct _ | Tunion _ -> unsupported "struct or union assignment"
         | t -> Sassign (convertLval lv, convertExp e)
         end
-    | Call (lvOpt, e, eList, loc) ->
+    | Call (None, e, eList, loc) ->
 	updateLoc(loc);
-	begin match Cil.unrollType (Cil.typeOf e) with
-	  | TFun (t, _, _, _) as tfun ->
-	      let t' = convertTyp t in
-	      let (efun, params) = convertExpFuncall e tfun eList in
-	      let e' = Expr (Ecall (efun, params), t') in
-		begin match lvOpt with
-		  | None -> Sexpr e'
-		  | Some lv ->
-		      let (Expr (_, tlv)) as elv = convertLval lv in
-			begin match tlv with
-			  | Tstruct _ | Tunion _ ->
-                              unsupported "struct or union assignment"
-			  | _ ->
-			      if tlv = t' then
-				Sassign (elv, e')
-			      else
-				(* a cast must be inserted *)
-				if compatibleTypes tlv t' then
-				  Sassign (elv,
-				           Expr (Ecast (tlv, e'), tlv))
-				else internal_error "processCast: illegal cast"
-			end
-		end
-	  | _ -> internal_error "convertInstr: illegal call"
-	end
+        let (efun, params) = convertExpFuncall e eList in
+        Scall(Datatypes.None, efun, params)
+    | Call (Some lv, e, eList, loc) ->
+	updateLoc(loc);
+        let (efun, params) = convertExpFuncall e eList in
+        makeFuncall2 (Cil.typeOf e) (Cil.typeOfLval lv) (convertLval lv) efun params
     | Asm (_, _, _, _, _, loc) ->
 	updateLoc(loc);
         unsupported "inline assembly"
@@ -687,6 +707,7 @@ and convertStmt s =
 
 (** Convert a [Cil.GFun] into a pair [(ident * coq_fundecl)] *)
 let convertGFun fdec =
+  current_function := Some fdec;
   let v = fdec.svar in
   let ret = match v.vtype with
     | TFun (t, _, vArg, _) ->
@@ -698,15 +719,16 @@ let convertGFun fdec =
         end
     | _ -> internal_error "convertGFun: incorrect function type"
   in
+  let s = processStmtList fdec.sbody.bstmts in   (* function body -- do it first because of generated temps *)
   let args = map_coqlist convertVarinfoParam fdec.sformals in   (* parameters*)
   let varList = map_coqlist convertVarinfo fdec.slocals in   (* local vars *)
-  let s = processStmtList fdec.sbody.bstmts in   (* function body *)
   if v.vname = "main" then begin
     match ret with
     | Tint(_, _) -> ()
     | _ -> updateLoc v.vdecl;
            unsupported "the return type of main() must be an integer type"
   end;
+  current_function := None;
   Datatypes.Coq_pair
     (intern_string v.vname,
      Internal { fn_return=ret; fn_params=args; fn_vars=varList; fn_body=s })
diff --git a/caml/PrintCsyntax.ml b/caml/PrintCsyntax.ml
index f9abd9a2f..59c42d3bf 100644
--- a/caml/PrintCsyntax.ml
+++ b/caml/PrintCsyntax.ml
@@ -129,7 +129,6 @@ let parenthesis_level (Expr (e, ty)) =
       end
   | Ecast _ -> 30
   | Eindex(_, _) -> 20
-  | Ecall(_, _) -> 20
   | Eandbool(_, _) -> 80
   | Eorbool(_, _) -> 80
   | Esizeof _ -> 20
@@ -163,10 +162,6 @@ let rec print_expr p (Expr (eb, ty) as e) =
       fprintf p "@[<hov 2>%a@,[%a]@]"
                 print_expr_prec (level, e1)
                 print_expr_prec (level, e2)
-  | Ecall(e1, el) ->
-      fprintf p "@[<hov 2>%a@,(@[<hov 0>%a@])@]"
-                print_expr_prec (level, e1)
-                print_expr_list (true, el)
   | Eandbool(e1, e2) ->
       fprintf p "@[<hov 0>%a@ && %a@]"
                 print_expr_prec (level, e1)
@@ -186,10 +181,10 @@ and print_expr_prec p (context_prec, e) =
   then fprintf p "(%a)" print_expr e
   else print_expr p e
 
-and print_expr_list p (first, el) =
+let rec print_expr_list p (first, el) =
   match el with
-  | Enil -> ()
-  | Econs(e1, et) ->
+  | Coq_nil -> ()
+  | Coq_cons(e1, et) ->
       if not first then fprintf p ",@ ";
       print_expr p e1;
       print_expr_list p (false, et)
@@ -198,10 +193,17 @@ let rec print_stmt p s =
   match s with
   | Sskip ->
       fprintf p "/*skip*/;"
-  | Sexpr e ->
-      fprintf p "%a;" print_expr e
   | Sassign(e1, e2) ->
       fprintf p "@[<hv 2>%a =@ %a;@]" print_expr e1 print_expr e2
+  | Scall(None, e1, el) ->
+      fprintf p "@[<hv 2>%a@,(@[<hov 0>%a@]);@]"
+                print_expr e1
+                print_expr_list (true, el)
+  | Scall(Some lhs, e1, el) ->
+      fprintf p "@[<hv 2>%a =@ %a@,(@[<hov 0>%a@]);@]"
+                print_expr lhs
+                print_expr e1
+                print_expr_list (true, el)
   | Ssequence(s1, s2) ->
       fprintf p "%a@ %a" print_stmt s1 print_stmt s2
   | Sifthenelse(e, s1, Sskip) ->
@@ -260,12 +262,19 @@ and print_stmt_for p s =
   match s with
   | Sskip ->
       fprintf p "/*nothing*/"
-  | Sexpr e ->
-      fprintf p "%a" print_expr e
   | Sassign(e1, e2) ->
       fprintf p "%a = %a" print_expr e1 print_expr e2
   | Ssequence(s1, s2) ->
       fprintf p "%a, %a" print_stmt_for s1 print_stmt_for s2
+  | Scall(None, e1, el) ->
+      fprintf p "@[<hv 2>%a@,(@[<hov 0>%a@])@]"
+                print_expr e1
+                print_expr_list (true, el)
+  | Scall(Some lhs, e1, el) ->
+      fprintf p "@[<hv 2>%a =@ %a@,(@[<hov 0>%a@])@]"
+                print_expr lhs
+                print_expr e1
+                print_expr_list (true, el)
   | _ ->
       fprintf p "<impossible>"
 
@@ -395,20 +404,20 @@ let rec collect_expr (Expr(ed, ty)) =
   | Ebinop(op, e1, e2) -> collect_expr e1; collect_expr e2
   | Ecast(ty, e1) -> collect_type ty; collect_expr e1
   | Eindex(e1, e2) -> collect_expr e1; collect_expr e2
-  | Ecall(e1, el) -> collect_expr e1; collect_expr_list el
   | Eandbool(e1, e2) -> collect_expr e1; collect_expr e2
   | Eorbool(e1, e2) -> collect_expr e1; collect_expr e2
   | Esizeof ty -> collect_type ty
   | Efield(e1, id) -> collect_expr e1
 
-and collect_expr_list = function
-  | Enil -> ()
-  | Econs(hd, tl) -> collect_expr hd; collect_expr_list tl
+let rec collect_expr_list = function
+  | Coq_nil -> ()
+  | Coq_cons(hd, tl) -> collect_expr hd; collect_expr_list tl
 
 let rec collect_stmt = function
   | Sskip -> ()
-  | Sexpr e -> collect_expr e
   | Sassign(e1, e2) -> collect_expr e1; collect_expr e2
+  | Scall(None, e1, el) -> collect_expr e1; collect_expr_list el
+  | Scall(Some lhs, e1, el) -> collect_expr lhs; collect_expr e1; collect_expr_list el
   | Ssequence(s1, s2) -> collect_stmt s1; collect_stmt s2
   | Sifthenelse(e, s1, s2) -> collect_expr e; collect_stmt s1; collect_stmt s2
   | Swhile(e, s) -> collect_expr e; collect_stmt s
diff --git a/cfrontend/Cminorgen.v b/cfrontend/Cminorgen.v
index d021a63c6..8596ebfa8 100644
--- a/cfrontend/Cminorgen.v
+++ b/cfrontend/Cminorgen.v
@@ -79,7 +79,7 @@ Definition store_arg (chunk: memory_chunk) (e: expr) : expr :=
   end.
 
 Definition make_store (chunk: memory_chunk) (e1 e2: expr): stmt :=
-  Sexpr (Estore chunk e1 (store_arg chunk e2)).
+  Sstore chunk e1 (store_arg chunk e2).
 
 Definition make_stackaddr (ofs: Z): expr :=
   Econst (Oaddrstack (Int.repr ofs)).
@@ -160,35 +160,22 @@ Fixpoint transl_expr (cenv: compilenv) (e: Csharpminor.expr)
   | Csharpminor.Eload chunk e =>
       do te <- transl_expr cenv e;
       OK (Eload chunk te)
-  | Csharpminor.Ecall sig e el =>
-      do te <- transl_expr cenv e;
-      do tel <- transl_exprlist cenv el;
-      OK (Ecall sig te tel)
   | Csharpminor.Econdition e1 e2 e3 =>
       do te1 <- transl_expr cenv e1;
       do te2 <- transl_expr cenv e2;
       do te3 <- transl_expr cenv e3;
       OK (Econdition te1 te2 te3)
-  | Csharpminor.Elet e1 e2 =>
-      do te1 <- transl_expr cenv e1;
-      do te2 <- transl_expr cenv e2;
-      OK (Elet te1 te2)
-  | Csharpminor.Eletvar n =>
-      OK (Eletvar n)
-  | Csharpminor.Ealloc e =>
-      do te <- transl_expr cenv e;
-      OK (Ealloc te)
-  end
+  end.
 
-with transl_exprlist (cenv: compilenv) (el: Csharpminor.exprlist)
-                     {struct el}: res exprlist :=
+Fixpoint transl_exprlist (cenv: compilenv) (el: list Csharpminor.expr)
+                     {struct el}: res (list expr) :=
   match el with
-  | Csharpminor.Enil =>
-      OK Enil
-  | Csharpminor.Econs e1 e2 =>
+  | nil =>
+      OK nil
+  | e1 :: e2 =>
       do te1 <- transl_expr cenv e1;
       do te2 <- transl_exprlist cenv e2;
-      OK (Econs te1 te2)
+      OK (te1 :: te2)
   end.
 
 (** Translation of statements.  Entirely straightforward. *)
@@ -198,14 +185,21 @@ Fixpoint transl_stmt (cenv: compilenv) (s: Csharpminor.stmt)
   match s with
   | Csharpminor.Sskip =>
       OK Sskip
-  | Csharpminor.Sexpr e =>
-      do te <- transl_expr cenv e; OK(Sexpr te)
   | Csharpminor.Sassign id e =>
       do te <- transl_expr cenv e; var_set cenv id te
   | Csharpminor.Sstore chunk e1 e2 =>
       do te1 <- transl_expr cenv e1;
       do te2 <- transl_expr cenv e2;
       OK (make_store chunk te1 te2)
+  | Csharpminor.Scall None sig e el =>
+      do te <- transl_expr cenv e;
+      do tel <- transl_exprlist cenv el;
+      OK (Scall None sig te tel)
+  | Csharpminor.Scall (Some id) sig e el =>
+      do te <- transl_expr cenv e;
+      do tel <- transl_exprlist cenv el;
+      do s <- var_set cenv id (Evar id);
+      OK (Sseq (Scall (Some id) sig te tel) s)
   | Csharpminor.Sseq s1 s2 =>
       do ts1 <- transl_stmt cenv s1;
       do ts2 <- transl_stmt cenv s2;
@@ -245,31 +239,26 @@ Fixpoint addr_taken_expr (e: Csharpminor.expr): Identset.t :=
   | Csharpminor.Ebinop op e1 e2 =>
       Identset.union (addr_taken_expr e1) (addr_taken_expr e2)
   | Csharpminor.Eload chunk e => addr_taken_expr e
-  | Csharpminor.Ecall sig e el =>
-      Identset.union (addr_taken_expr e) (addr_taken_exprlist el)
   | Csharpminor.Econdition e1 e2 e3 =>
       Identset.union (addr_taken_expr e1) 
         (Identset.union (addr_taken_expr e2) (addr_taken_expr e3))
-  | Csharpminor.Elet e1 e2 =>
-      Identset.union (addr_taken_expr e1) (addr_taken_expr e2)
-  | Csharpminor.Eletvar n => Identset.empty
-  | Csharpminor.Ealloc e => addr_taken_expr e
-  end
+  end.
 
-with addr_taken_exprlist (e: Csharpminor.exprlist): Identset.t :=
+Fixpoint addr_taken_exprlist (e: list Csharpminor.expr): Identset.t :=
   match e with
-  | Csharpminor.Enil => Identset.empty
-  | Csharpminor.Econs e1 e2 =>
+  | nil => Identset.empty
+  | e1 :: e2 =>
       Identset.union (addr_taken_expr e1) (addr_taken_exprlist e2)
   end.
 
 Fixpoint addr_taken_stmt (s: Csharpminor.stmt): Identset.t :=
   match s with
   | Csharpminor.Sskip => Identset.empty
-  | Csharpminor.Sexpr e => addr_taken_expr e
   | Csharpminor.Sassign id e => addr_taken_expr e
   | Csharpminor.Sstore chunk e1 e2 =>
       Identset.union (addr_taken_expr e1) (addr_taken_expr e2)
+  | Csharpminor.Scall optid sig e el =>
+      Identset.union (addr_taken_expr e) (addr_taken_exprlist el)
   | Csharpminor.Sseq s1 s2 =>
       Identset.union (addr_taken_stmt s1) (addr_taken_stmt s2)
   | Csharpminor.Sifthenelse e s1 s2 =>
@@ -342,20 +331,13 @@ Definition build_global_compilenv (p: Csharpminor.program) : compilenv :=
 
 Fixpoint store_parameters
        (cenv: compilenv) (params: list (ident * memory_chunk))
-       {struct params} : stmt :=
+       {struct params} : res stmt :=
   match params with
-  | nil => Sskip
+  | nil => OK Sskip
   | (id, chunk) :: rem =>
-      match PMap.get id cenv with
-      | Var_local chunk =>
-          Sseq (Sassign id (make_cast chunk (Evar id)))
-               (store_parameters cenv rem)
-      | Var_stack_scalar chunk ofs =>
-          Sseq (make_store chunk (make_stackaddr ofs) (Evar id))
-               (store_parameters cenv rem)
-      | _ =>
-          Sskip (* should never happen *)
-      end
+      do s1 <- var_set cenv id (Evar id);
+      do s2 <- store_parameters cenv rem;
+      OK (Sseq s1 s2)
   end.
 
 (** Translation of a Csharpminor function.  We must check that the
@@ -368,12 +350,13 @@ Definition transl_function
   let (cenv, stacksize) := build_compilenv gce f in
   if zle stacksize Int.max_signed then
     do tbody <- transl_stmt cenv f.(Csharpminor.fn_body);
+    do sparams <- store_parameters cenv f.(Csharpminor.fn_params);
        OK (mkfunction
               (Csharpminor.fn_sig f)
               (Csharpminor.fn_params_names f)
               (Csharpminor.fn_vars_names f)
               stacksize
-              (Sseq (store_parameters cenv f.(Csharpminor.fn_params)) tbody))
+              (Sseq sparams tbody))
   else Error(msg "Cminorgen: too many local variables, stack size exceeded").
 
 Definition transl_fundef (gce: compilenv) (f: Csharpminor.fundef): res fundef :=
diff --git a/cfrontend/Cminorgenproof.v b/cfrontend/Cminorgenproof.v
index 5bcb88016..ff10bb3ee 100644
--- a/cfrontend/Cminorgenproof.v
+++ b/cfrontend/Cminorgenproof.v
@@ -12,6 +12,7 @@ Require Import Mem.
 Require Import Events.
 Require Import Globalenvs.
 Require Import Csharpminor.
+Require Import Op.
 Require Import Cminor.
 Require Import Cminorgen.
 
@@ -279,30 +280,6 @@ Qed.
   must be normalized with respect to the memory chunk of the variable,
   in the following sense. *)
 
-(*
-Definition val_normalized (chunk: memory_chunk) (v: val) : Prop :=
-  exists v0, v = Val.load_result chunk v0.
-
-Lemma load_result_idem:
-  forall chunk v,
-  Val.load_result chunk (Val.load_result chunk v) =
-  Val.load_result chunk v.
-Proof.
-  destruct chunk; destruct v; simpl; auto.
-  rewrite Int.cast8_signed_idem; auto.
-  rewrite Int.cast8_unsigned_idem; auto.
-  rewrite Int.cast16_signed_idem; auto.
-  rewrite Int.cast16_unsigned_idem; auto.
-  rewrite Float.singleoffloat_idem; auto.
-Qed.
-
-Lemma load_result_normalized:
-  forall chunk v,
-  val_normalized chunk v -> Val.load_result chunk v = v.
-Proof.
-  intros chunk v [v0 EQ]. rewrite EQ. apply load_result_idem. 
-Qed.
-*)
 Lemma match_env_store_local:
   forall f cenv e m1 m2 te sp lo hi id b chunk v tv,
   e!id = Some(b, Vscalar chunk) ->
@@ -796,21 +773,12 @@ Qed.
 
 (** * Correctness of Cminor construction functions *)
 
-Hint Resolve eval_Econst eval_Eunop eval_Ebinop eval_Eload: evalexpr.
-
 Remark val_inject_val_of_bool:
   forall f b, val_inject f (Val.of_bool b) (Val.of_bool b).
 Proof.
   intros; destruct b; unfold Val.of_bool, Vtrue, Vfalse; constructor.
 Qed.
 
-Remark val_inject_bool_of_val:
-  forall f v b tv,
-  val_inject f v tv -> Val.bool_of_val v b -> Val.bool_of_val tv b.
-Proof.
-  intros. inv H; inv H0; constructor; auto.
-Qed.
-
 Remark val_inject_eval_compare_null:
   forall f c i v,  
   eval_compare_null c i = Some v ->
@@ -822,6 +790,8 @@ Proof.
   discriminate.
 Qed.
 
+Hint Resolve eval_Econst eval_Eunop eval_Ebinop eval_Eload: evalexpr.
+
 Ltac TrivialOp :=
   match goal with
   | [ |- exists y, _ /\ val_inject _ (Vint ?x) _ ] =>
@@ -838,6 +808,17 @@ Ltac TrivialOp :=
   | _ => idtac
   end.
 
+Remark eval_compare_null_inv:
+  forall c i v,
+  eval_compare_null c i = Some v ->
+  i = Int.zero /\ (c = Ceq /\ v = Vfalse \/ c = Cne /\ v = Vtrue).
+Proof.
+  intros until v. unfold eval_compare_null.
+  predSpec Int.eq Int.eq_spec i Int.zero.
+  case c; intro EQ; simplify_eq EQ; intro; subst v; tauto.
+  congruence.
+Qed.
+
 (** Correctness of [transl_constant]. *)
 
 Lemma transl_constant_correct:
@@ -865,12 +846,12 @@ Proof.
   inv H; inv H0; simpl; TrivialOp.
   inv H; inv H0; simpl; TrivialOp.
   inv H; inv H0; simpl; TrivialOp.
-  inv H0; inv H. TrivialOp. 
+  inv H0; inv H. TrivialOp. unfold Vfalse; TrivialOp.
   inv H0; inv H. TrivialOp. unfold Vfalse; TrivialOp.
   inv H0; inv H; TrivialOp.
   inv H0; inv H; TrivialOp.
   inv H0; inv H; TrivialOp.
-  inv H; inv H0; simpl; TrivialOp.
+  inv H0; inv H; TrivialOp.
   inv H0; inv H; TrivialOp.
   inv H0; inv H; TrivialOp.
   inv H0; inv H; TrivialOp.
@@ -950,12 +931,11 @@ Qed.
   normalized according to the given memory chunk. *)
 
 Lemma make_cast_correct:
-  forall f sp le te tm1 a t tm2 v chunk tv,
-  eval_expr tge (Vptr sp Int.zero) le te tm1 a t tm2 tv ->
+  forall f sp te tm a v tv chunk,
+  eval_expr tge sp te tm a tv ->
   val_inject f v tv ->
   exists tv',
-  eval_expr tge (Vptr sp Int.zero) le
-            te tm1 (make_cast chunk a) t tm2 tv'
+     eval_expr tge sp te tm (make_cast chunk a) tv'
   /\ val_inject f (Val.load_result chunk v) tv'.
 Proof.
   intros. destruct chunk; simpl make_cast.
@@ -983,46 +963,44 @@ Proof.
 Qed.
 
 Lemma make_stackaddr_correct:
-  forall sp le te tm ofs,
-  eval_expr tge (Vptr sp Int.zero) le
-            te tm (make_stackaddr ofs)
-            E0 tm (Vptr sp (Int.repr ofs)).
+  forall sp te tm ofs,
+  eval_expr tge (Vptr sp Int.zero) te tm
+            (make_stackaddr ofs) (Vptr sp (Int.repr ofs)).
 Proof.
   intros; unfold make_stackaddr.
-  econstructor. simpl. decEq. decEq.
+  eapply eval_Econst. simpl. decEq. decEq.
   rewrite Int.add_commut. apply Int.add_zero.
 Qed.
 
 Lemma make_globaladdr_correct:
-  forall sp le te tm id b,
+  forall sp te tm id b,
   Genv.find_symbol tge id = Some b ->
-  eval_expr tge (Vptr sp Int.zero) le
-            te tm (make_globaladdr id)
-            E0 tm (Vptr b Int.zero).
+  eval_expr tge (Vptr sp Int.zero) te tm
+            (make_globaladdr id) (Vptr b Int.zero).
 Proof.
   intros; unfold make_globaladdr.
-  econstructor. simpl. rewrite H. auto.
+  eapply eval_Econst. simpl. rewrite H. auto.
 Qed.
 
 (** Correctness of [make_store]. *)
 
 Lemma store_arg_content_inject:
-  forall f sp le te tm1 a t tm2 v va chunk,
-  eval_expr tge (Vptr sp Int.zero) le te tm1 a t tm2 va ->
+  forall f sp te tm a v va chunk,
+  eval_expr tge sp te tm a va ->
   val_inject f v va ->
   exists vb,
-  eval_expr tge (Vptr sp Int.zero) le te tm1 (store_arg chunk a) t tm2 vb  
+     eval_expr tge sp te tm (store_arg chunk a) vb
   /\ val_content_inject f chunk v vb.
 Proof.
   intros. 
   assert (exists vb,
-    eval_expr tge (Vptr sp Int.zero) le te tm1 a t tm2 vb  
+       eval_expr tge sp te tm a vb  
     /\ val_content_inject f chunk v vb).
   exists va; split. assumption. constructor. assumption.
   destruct a; simpl store_arg; trivial;
   destruct u; trivial;
   destruct chunk; trivial;
-  inv H; simpl in H12; inv H12;
+  inv H; simpl in H6; inv H6;
   econstructor; (split; [eauto|idtac]);
   destruct v1; simpl in H0; inv H0; try (constructor; constructor).
   apply val_content_inject_8. auto. apply Int.cast8_unsigned_idem.
@@ -1033,47 +1011,43 @@ Proof.
 Qed.
 
 Lemma make_store_correct:
-  forall f sp te tm1 addr tm2 tvaddr rhs tm3 tvrhs
-         chunk vrhs m3 vaddr m4 t1 t2,
-  eval_expr tge (Vptr sp Int.zero) nil
-            te tm1 addr t1 tm2 tvaddr ->
-  eval_expr tge (Vptr sp Int.zero) nil
-            te tm2 rhs t2 tm3 tvrhs ->
-  Mem.storev chunk m3 vaddr vrhs = Some m4 ->
-  mem_inject f m3 tm3 ->
+  forall f sp te tm addr tvaddr rhs tvrhs chunk m vaddr vrhs m',
+  eval_expr tge sp te tm addr tvaddr ->
+  eval_expr tge sp te tm rhs tvrhs ->
+  Mem.storev chunk m vaddr vrhs = Some m' ->
+  mem_inject f m tm ->
   val_inject f vaddr tvaddr ->
   val_inject f vrhs tvrhs ->
-  exists tm4,
-  exec_stmt tge (Vptr sp Int.zero)
-            te tm1 (make_store chunk addr rhs)
-            (t1**t2) te tm4 Out_normal
-  /\ mem_inject f m4 tm4
-  /\ nextblock tm4 = nextblock tm3.
+  exists tm',
+  exec_stmt tge sp te tm (make_store chunk addr rhs)
+                E0 te tm' Out_normal
+  /\ mem_inject f m' tm'
+  /\ nextblock tm' = nextblock tm.
 Proof.
   intros. unfold make_store.
   exploit store_arg_content_inject. eexact H0. eauto. 
   intros [tv [EVAL VCINJ]].
   exploit storev_mapped_inject_1; eauto.
-  intros [tm4 [STORE MEMINJ]].
-  exists tm4. 
-  split. apply exec_Sexpr with tv. eapply eval_Estore; eauto. 
-  split. auto. 
+  intros [tm' [STORE MEMINJ]].
+  exists tm'.
+  split. eapply exec_Sstore; eauto. 
+  split. auto.
   unfold storev in STORE; destruct tvaddr; try discriminate.
   eapply nextblock_store; eauto.
 Qed.
 
-(** Correctness of the variable accessors [var_get], [var_set]
-  and [var_addr]. *)
+(** Correctness of the variable accessors [var_get], [var_addr],
+  and [var_set]. *)
 
 Lemma var_get_correct:
-  forall cenv id a f e te sp lo hi m cs tm b chunk v le,
+  forall cenv id a f e te sp lo hi m cs tm b chunk v,
   var_get cenv id = OK a ->
   match_callstack f (mkframe cenv e te sp lo hi :: cs) m.(nextblock) tm.(nextblock) m ->
   mem_inject f m tm ->
   eval_var_ref prog e id b chunk ->
   load chunk m b 0 = Some v ->
   exists tv,
-    eval_expr tge (Vptr sp Int.zero) le te tm a E0 tm tv /\
+    eval_expr tge (Vptr sp Int.zero) te tm a tv /\
     val_inject f v tv.
 Proof.
   unfold var_get; intros.
@@ -1093,7 +1067,7 @@ Proof.
     unfold loadv. eexact H3. 
   intros [tv [LOAD INJ]].
   exists tv; split. 
-  econstructor; eauto. eapply make_stackaddr_correct; eauto.
+  eapply eval_Eload; eauto. eapply make_stackaddr_correct; eauto.
   auto.
   (* var_global_scalar *)
   inversion H2; [congruence|subst]. 
@@ -1106,17 +1080,17 @@ Proof.
   generalize (loadv_inject _ _ _ _ _ _ _ H1 H12 H13).
   intros [tv [LOAD INJ]].
   exists tv; split. 
-  econstructor; eauto. eapply make_globaladdr_correct; eauto.
+  eapply eval_Eload; eauto. eapply make_globaladdr_correct; eauto.
   auto.
 Qed.
 
 Lemma var_addr_correct:
-  forall cenv id a f e te sp lo hi m cs tm b le,
+  forall cenv id a f e te sp lo hi m cs tm b,
   match_callstack f (mkframe cenv e te sp lo hi :: cs) m.(nextblock) tm.(nextblock) m ->
   var_addr cenv id = OK a ->
   eval_var_addr prog e id b ->
   exists tv,
-    eval_expr tge (Vptr sp Int.zero) le te tm a E0 tm tv /\
+    eval_expr tge (Vptr sp Int.zero) te tm a tv /\
     val_inject f (Vptr b Int.zero) tv.
 Proof.
   unfold var_addr; intros.
@@ -1150,62 +1124,169 @@ Proof.
 Qed.
 
 Lemma var_set_correct:
-  forall cenv id rhs a f e te sp lo hi m2 cs tm2 tm1 tv b chunk v m3 t,
+  forall cenv id rhs a f e te sp lo hi m cs tm tv v m',
   var_set cenv id rhs = OK a ->
-  match_callstack f (mkframe cenv e te sp lo hi :: cs) m2.(nextblock) tm2.(nextblock) m2 ->
-  eval_expr tge (Vptr sp Int.zero) nil te tm1 rhs t tm2 tv ->
+  match_callstack f (mkframe cenv e te sp lo hi :: cs) m.(nextblock) tm.(nextblock) m ->
+  eval_expr tge (Vptr sp Int.zero) te tm rhs tv ->
   val_inject f v tv ->
-  mem_inject f m2 tm2 ->
-  eval_var_ref prog e id b chunk ->
-  store chunk m2 b 0 v = Some m3 ->
-  exists te3, exists tm3,
-    exec_stmt tge (Vptr sp Int.zero) te tm1 a t te3 tm3 Out_normal /\
-    mem_inject f m3 tm3 /\
-    match_callstack f (mkframe cenv e te3 sp lo hi :: cs) m3.(nextblock) tm3.(nextblock) m3.
+  mem_inject f m tm ->
+  exec_assign prog e m id v m' ->
+  exists te', exists tm',
+    exec_stmt tge (Vptr sp Int.zero) te tm a E0 te' tm' Out_normal /\
+    mem_inject f m' tm' /\
+    match_callstack f (mkframe cenv e te' sp lo hi :: cs) m'.(nextblock) tm'.(nextblock) m' /\
+    (forall id', id' <> id -> te'!id' = te!id').
 Proof.
   unfold var_set; intros.
-  assert (NEXTBLOCK: nextblock m3 = nextblock m2).
+  inv H4. 
+  assert (NEXTBLOCK: nextblock m' = nextblock m).
     eapply nextblock_store; eauto.
-  inversion H0. subst.
-  assert (match_var f id e m2 te sp cenv!!id). inversion H19; auto.
-  inversion H6; subst; rewrite <- H7 in H; inversion H; subst; clear H.
+  inversion H0; subst.
+  assert (match_var f id e m te sp cenv!!id). inversion H19; auto.
+  inv H4; rewrite <- H7 in H; inv H.
   (* var_local *)
-  inversion H4; [subst|congruence]. 
-  assert (b0 = b). congruence. subst b0.
-  assert (chunk0 = chunk). congruence. subst chunk0.
+  inversion H5; [subst|congruence]. 
+  assert (b0 = b) by congruence. subst b0.
+  assert (chunk0 = chunk) by congruence. subst chunk0.
   exploit make_cast_correct; eauto.  
   intros [tv' [EVAL INJ]].
-  exists (PTree.set id tv' te); exists tm2.
+  exists (PTree.set id tv' te); exists tm.
   split. eapply exec_Sassign. eauto. 
   split. eapply store_unmapped_inject; eauto. 
-  rewrite NEXTBLOCK. eapply match_callstack_store_local; eauto.
+  split. rewrite NEXTBLOCK. eapply match_callstack_store_local; eauto.
+  intros. apply PTree.gso; auto.
   (* var_stack_scalar *)
+  inversion H5; [subst|congruence].
+  assert (b0 = b) by congruence. subst b0.
+  assert (chunk0 = chunk) by congruence. subst chunk0.
+  assert (storev chunk m (Vptr b Int.zero) v = Some m'). assumption.
+  exploit make_store_correct.
+    eapply make_stackaddr_correct.
+    eauto. eauto. eauto. eauto. eauto. 
+  intros [tm' [EVAL [MEMINJ TNEXTBLOCK]]].
+  exists te; exists tm'.
+  split. auto. split. auto.  
+  split. rewrite NEXTBLOCK; rewrite TNEXTBLOCK.
+  eapply match_callstack_mapped; eauto. 
+  inversion H9; congruence.
+  auto.
+  (* var_global_scalar *)
+  inversion H5; [congruence|subst]. 
+  assert (chunk0 = chunk) by congruence. subst chunk0.  
+  assert (storev chunk m (Vptr b Int.zero) v = Some m'). assumption.
+  assert (match_globalenvs f). eapply match_callstack_match_globalenvs; eauto.
+  inversion H12. destruct (mg_symbols0 _ _ H4) as [A B].
+  exploit make_store_correct.
+    eapply make_globaladdr_correct; eauto.
+    eauto. eauto. eauto. eauto. eauto. 
+  intros [tm' [EVAL [MEMINJ TNEXTBLOCK]]].
+  exists te; exists tm'.
+  split. auto. split. auto. 
+  split. rewrite NEXTBLOCK; rewrite TNEXTBLOCK.
+  eapply match_callstack_mapped; eauto. congruence.
+  auto.
+Qed.
+
+Lemma match_env_extensional':
+  forall f cenv e m te1 sp lo hi,
+  match_env f cenv e m te1 sp lo hi ->
+  forall te2,
+  (forall id, 
+     match cenv!!id with
+     | Var_local _ => te2!id = te1!id
+     | _ => True
+     end) ->
+  match_env f cenv e m te2 sp lo hi.
+Proof.
+  induction 1; intros; econstructor; eauto.
+  intros. generalize (me_vars0 id); intro. 
+  inversion H0; econstructor; eauto.
+  generalize (H id). rewrite <- H1. congruence. 
+Qed.
+
+
+Lemma match_callstack_extensional:
+  forall f cenv e te1 te2 sp lo hi cs bound tbound m,
+  (forall id, 
+     match cenv!!id with
+     | Var_local _ => te2!id = te1!id
+     | _ => True
+     end) ->
+  match_callstack f (mkframe cenv e te1 sp lo hi :: cs) bound tbound m ->
+  match_callstack f (mkframe cenv e te2 sp lo hi :: cs) bound tbound m.
+Proof.
+  intros. inv H0. constructor; auto. 
+  apply match_env_extensional' with te1; auto.
+Qed.
+
+Lemma var_set_self_correct:
+  forall cenv id a f e te sp lo hi m cs tm tv v m',
+  var_set cenv id (Evar id) = OK a ->
+  match_callstack f (mkframe cenv e te sp lo hi :: cs) m.(nextblock) tm.(nextblock) m ->
+  val_inject f v tv ->
+  mem_inject f m tm ->
+  exec_assign prog e m id v m' ->
+  exists te', exists tm',
+    exec_stmt tge (Vptr sp Int.zero) (PTree.set id tv te) tm a E0 te' tm' Out_normal /\
+    mem_inject f m' tm' /\
+    match_callstack f (mkframe cenv e te' sp lo hi :: cs) m'.(nextblock) tm'.(nextblock) m'.
+Proof.
+  unfold var_set; intros.
+  inv H3. 
+  assert (NEXTBLOCK: nextblock m' = nextblock m).
+    eapply nextblock_store; eauto.
+  inversion H0; subst.
+  assert (EVAR: eval_expr tge (Vptr sp Int.zero) (PTree.set id tv te) tm (Evar id) tv).
+    constructor. apply PTree.gss.
+  assert (match_var f id e m te sp cenv!!id). inversion H18; auto.
+  inv H3; rewrite <- H6 in H; inv H.
+  (* var_local *)
   inversion H4; [subst|congruence]. 
-  assert (b0 = b). congruence. subst b0.
-  assert (chunk0 = chunk). congruence. subst chunk0.  
-  assert (storev chunk m2 (Vptr b Int.zero) v = Some m3). assumption.
+  assert (b0 = b) by congruence. subst b0.
+  assert (chunk0 = chunk) by congruence. subst chunk0.
+  exploit make_cast_correct; eauto. 
+  intros [tv' [EVAL INJ]].
+  exists (PTree.set id tv' (PTree.set id tv te)); exists tm.
+  split. eapply exec_Sassign. eauto. 
+  split. eapply store_unmapped_inject; eauto. 
+  rewrite NEXTBLOCK.
+  apply match_callstack_extensional with (PTree.set id tv' te).
+  intros. destruct (cenv!!id0); auto. 
+  repeat rewrite PTree.gsspec. destruct (peq id0 id); auto. 
+  eapply match_callstack_store_local; eauto.
+  (* var_stack_scalar *)
+  inversion H4; [subst|congruence].
+  assert (b0 = b) by congruence. subst b0.
+  assert (chunk0 = chunk) by congruence. subst chunk0.
+  assert (storev chunk m (Vptr b Int.zero) v = Some m'). assumption.
   exploit make_store_correct.
     eapply make_stackaddr_correct.
     eauto. eauto. eauto. eauto. eauto. 
-  rewrite E0_left. intros [tm3 [EVAL [MEMINJ TNEXTBLOCK]]].
-  exists te; exists tm3.
+  intros [tm' [EVAL [MEMINJ TNEXTBLOCK]]].
+  exists (PTree.set id tv te); exists tm'.
   split. auto. split. auto.  
   rewrite NEXTBLOCK; rewrite TNEXTBLOCK.
+  apply match_callstack_extensional with te.
+  intros. caseEq (cenv!!id0); intros; auto.
+  rewrite PTree.gsspec. destruct (peq id0 id). congruence. auto.
   eapply match_callstack_mapped; eauto. 
-  inversion H9; congruence.
+  inversion H8; congruence.
   (* var_global_scalar *)
   inversion H4; [congruence|subst]. 
-  assert (chunk0 = chunk). congruence. subst chunk0.  
-  assert (storev chunk m2 (Vptr b Int.zero) v = Some m3). assumption.
+  assert (chunk0 = chunk) by congruence. subst chunk0.  
+  assert (storev chunk m (Vptr b Int.zero) v = Some m'). assumption.
   assert (match_globalenvs f). eapply match_callstack_match_globalenvs; eauto.
-  inversion H13. destruct (mg_symbols0 _ _ H10) as [A B].
+  inversion H11. destruct (mg_symbols0 _ _ H3) as [A B].
   exploit make_store_correct.
     eapply make_globaladdr_correct; eauto.
     eauto. eauto. eauto. eauto. eauto. 
-  rewrite E0_left. intros [tm3 [EVAL [MEMINJ TNEXTBLOCK]]].
-  exists te; exists tm3.
+  intros [tm' [EVAL [MEMINJ TNEXTBLOCK]]].
+  exists (PTree.set id tv te); exists tm'.
   split. auto. split. auto. 
   rewrite NEXTBLOCK; rewrite TNEXTBLOCK.
+  apply match_callstack_extensional with te.
+  intros. caseEq (cenv!!id0); intros; auto.
+  rewrite PTree.gsspec. destruct (peq id0 id). congruence. auto.
   eapply match_callstack_mapped; eauto. congruence.
 Qed.
 
@@ -1501,79 +1582,42 @@ Qed.
 Lemma store_parameters_correct:
   forall e m1 params vl m2,
   bind_parameters e m1 params vl m2 ->
-  forall f te1 cenv sp lo hi cs tm1,
+  forall s f te1 cenv sp lo hi cs tm1,
   vars_vals_match f params vl te1 ->
   list_norepet (List.map (@fst ident memory_chunk) params) ->
   mem_inject f m1 tm1 ->
   match_callstack f (mkframe cenv e te1 sp lo hi :: cs) m1.(nextblock) tm1.(nextblock) m1 ->
+  store_parameters cenv params = OK s ->
   exists te2, exists tm2,
      exec_stmt tge (Vptr sp Int.zero)
-                   te1 tm1 (store_parameters cenv params)
+                   te1 tm1 s
                 E0 te2 tm2 Out_normal
   /\ mem_inject f m2 tm2
   /\ match_callstack f (mkframe cenv e te2 sp lo hi :: cs) m2.(nextblock) tm2.(nextblock) m2.
 Proof.
   induction 1.
   (* base case *)
-  intros; simpl. exists te1; exists tm1. split. constructor. tauto.
+  intros; simpl. monadInv H3.
+  exists te1; exists tm1. split. constructor. tauto.
   (* inductive case *)
-  intros until tm1.  intros VVM NOREPET MINJ MATCH. simpl.
+  intros until tm1.  intros VVM NOREPET MINJ MATCH STOREP.
+  monadInv STOREP.
   inversion VVM. subst f0 id0 chunk0 vars v vals te.
-  inversion MATCH. subst f0 cenv0 e0 te sp0 lo0 hi0 cs0 bound tbound m0.
-  inversion H18.
   inversion NOREPET. subst hd tl.
-  assert (NEXT: nextblock m1 = nextblock m).
-    eapply nextblock_store; eauto.
-  generalize (me_vars0 id). intro. inversion H2; subst.
-  (* cenv!!id = Var_local chunk *)
-  assert (b0 = b). congruence. subst b0.
-  assert (chunk0 = chunk). congruence. subst chunk0.
-  assert (v' = tv). congruence. subst v'.
-  exploit make_cast_correct.
-    apply eval_Evar with (id := id). eauto.
-    eexact H10. 
-  intros [tv' [EVAL1 VINJ1]].
-  set (te2 := PTree.set id tv' te1).
-  assert (VVM2: vars_vals_match f params vl te2).
+  exploit var_set_correct; eauto.
+    constructor; auto.
+    econstructor; eauto.
+    econstructor; eauto.
+  intros [te2 [tm2 [EXEC1 [MINJ1 [MATCH1 UNCHANGED1]]]]].
+  assert (vars_vals_match f params vl te2).
     apply vars_vals_match_extensional with te1; auto.
-    intros. unfold te2; apply PTree.gso. red; intro; subst id0.
-    elim H4. change id with (fst (id, lv)). apply List.in_map; auto.
-  exploit store_unmapped_inject; eauto. intro MINJ2.
-  exploit match_callstack_store_local; eauto. 
-  fold te2; rewrite <- NEXT; intro MATCH2.
+    intros. apply UNCHANGED1. red; intro; subst id0.
+    elim H4. change id with (fst (id, lv)). apply List.in_map. auto.
   exploit IHbind_parameters; eauto.
-  intros [te3 [tm3 [EXEC3 [MINJ3 MATCH3]]]].
-  exists te3; exists tm3. 
-  (* execution *)
-  split. apply exec_Sseq_continue with E0 te2 tm1 E0. 
-  unfold te2. constructor. eassumption. assumption. traceEq.
-  (* meminj & match_callstack *)
-  tauto.
-
-  (* cenv!!id = Var_stack_scalar *)
-  assert (b0 = b). congruence. subst b0.
-  assert (chunk0 = chunk). congruence. subst chunk0.
-  exploit make_store_correct.
-    eapply make_stackaddr_correct.
-    apply eval_Evar with (id := id).
-    eauto. 2:eauto. 2:eauto. unfold storev; eexact H0. eauto.
-  intros [tm2 [EVAL3 [MINJ2 NEXT1]]].
-  exploit match_callstack_mapped.
-    eexact MATCH. 2:eauto. inversion H7. congruence. 
-  rewrite <- NEXT; rewrite <- NEXT1; intro MATCH2.
-  exploit IHbind_parameters; eauto.
-  intros  [te3 [tm3 [EVAL4 [MINJ3 MATCH3]]]].
+  intros [te3 [tm3 [EXEC2 [MINJ2 MATCH2]]]].
   exists te3; exists tm3.
-  (* execution *)
-  split. apply exec_Sseq_continue with (E0**E0) te1 tm2 E0. 
-  auto. assumption. traceEq.
-  (* meminj & match_callstack *)
-  tauto.
-
-  (* Impossible cases on cenv!!id *)
-  congruence. 
-  congruence.
-  congruence.
+  split. econstructor; eauto.
+  auto.
 Qed.
 
 Lemma vars_vals_match_holds_1:
@@ -1634,7 +1678,7 @@ Qed.
   and initialize the blocks corresponding to function parameters). *)
 
 Lemma function_entry_ok:
-  forall fn m e m1 lb vargs m2 f cs tm cenv sz tm1 sp tvargs,
+  forall fn m e m1 lb vargs m2 f cs tm cenv sz tm1 sp tvargs s,
   alloc_variables empty_env m (fn_variables fn) e m1 lb ->
   bind_parameters e m1 fn.(Csharpminor.fn_params) vargs m2 ->
   match_callstack f cs m.(nextblock) tm.(nextblock) m ->
@@ -1646,9 +1690,10 @@ Lemma function_entry_ok:
   val_list_inject f vargs tvargs ->
   mem_inject f m tm ->
   list_norepet (fn_params_names fn ++ fn_vars_names fn) ->
+  store_parameters cenv fn.(Csharpminor.fn_params) = OK s ->
   exists f2, exists te2, exists tm2,
      exec_stmt tge (Vptr sp Int.zero)
-               te tm1 (store_parameters cenv fn.(Csharpminor.fn_params))
+               te tm1 s
             E0 te2 tm2 Out_normal
   /\ mem_inject f2 m2 tm2
   /\ inject_incr f f2
@@ -1669,7 +1714,7 @@ Proof.
   exploit store_parameters_correct.
     eauto. eauto. 
     unfold fn_params_names in H7. eapply list_norepet_append_left; eauto.
-    eexact MINJ1. eauto. 
+    eexact MINJ1. eauto. eauto. 
   intros [te2 [tm2 [EXEC [MINJ2 MATCH2]]]].
   exists f1; exists te2; exists tm2.
   split; auto. split; auto. split; auto. split; auto.
@@ -1681,64 +1726,101 @@ Qed.
 (** The proof of semantic preservation uses simulation diagrams of the
   following form:
 <<
-     le, e, m1, a --------------- tle, sp, te1, tm1, ta
-          |                                |
+       e, m1, s ----------------- sp, te1, tm1, ts
           |                                |
+         t|                                |t
           v                                v
-     le, e, m2, v --------------- tle, sp, te2, tm2, tv
+       e, m2, out --------------- sp, te2, tm2, tout
 >>
-  where [ta] is the Cminor expression obtained by translating the
-  Csharpminor expression [a].  The left vertical arrow is an evaluation
-  of a Csharpminor expression.  The right vertical arrow is an evaluation
-  of a Cminor expression.  The precondition (top vertical bar)
+  where [ts] is the Cminor statement obtained by translating the
+  Csharpminor statement [s].  The left vertical arrow is an execution
+  of a Csharpminor statement.  The right vertical arrow is an execution
+  of a Cminor statement.  The precondition (top vertical bar)
   includes a [mem_inject] relation between the memory states [m1] and [tm1],
-  a [val_list_inject] relation between the let environments [le] and [tle],
   and a [match_callstack] relation for any callstack having
   [e], [te1], [sp] as top frame.  The postcondition (bottom vertical bar)
   is the existence of a memory injection [f2] that extends the injection
   [f1] we started with, preserves the [match_callstack] relation for
   the transformed callstack at the final state, and validates a
-  [val_inject] relation between the result values [v] and [tv].
+  [outcome_inject] relation between the outcomes [out] and [tout].
+*)
 
-  We capture these diagrams by the following predicates, parameterized
-  over the Csharpminor executions, which will serve as induction
-  hypotheses in the proof of simulation. *)
+(** ** Semantic preservation for expressions *)
 
-Definition eval_expr_prop
-    (le: Csharpminor.letenv) (e: Csharpminor.env) (m1: mem) (a: Csharpminor.expr) (t: trace) (m2: mem) (v: val) : Prop :=
-  forall cenv ta f1 tle te tm1 sp lo hi cs
-  (TR: transl_expr cenv a = OK ta)
-  (LINJ: val_list_inject f1 le tle)
-  (MINJ: mem_inject f1 m1 tm1)
-  (MATCH: match_callstack f1
-           (mkframe cenv e te sp lo hi :: cs)
-           m1.(nextblock) tm1.(nextblock) m1),
-  exists f2, exists tm2, exists tv,
-     eval_expr tge (Vptr sp Int.zero) tle te tm1 ta t tm2 tv
-  /\ val_inject f2 v tv
-  /\ mem_inject f2 m2 tm2
-  /\ inject_incr f1 f2
-  /\ match_callstack f2
-        (mkframe cenv e te sp lo hi :: cs)
-        m2.(nextblock) tm2.(nextblock) m2.
+Remark bool_of_val_inject:
+  forall f v tv b,
+  Val.bool_of_val v b -> val_inject f v tv -> Val.bool_of_val tv b.
+Proof.
+  intros. inv H0; inv H; constructor; auto.
+Qed.
 
-Definition eval_exprlist_prop
-    (le: Csharpminor.letenv) (e: Csharpminor.env) (m1: mem) (al: Csharpminor.exprlist) (t: trace) (m2: mem) (vl: list val) : Prop :=
-  forall cenv tal f1 tle te tm1 sp lo hi cs
-  (TR: transl_exprlist cenv al = OK tal)
-  (LINJ: val_list_inject f1 le tle)
-  (MINJ: mem_inject f1 m1 tm1)
-  (MATCH: match_callstack f1
-           (mkframe cenv e te sp lo hi :: cs)
-           m1.(nextblock) tm1.(nextblock) m1),
-  exists f2, exists tm2, exists tvl,
-     eval_exprlist tge (Vptr sp Int.zero) tle te tm1 tal t tm2 tvl
-  /\ val_list_inject f2 vl tvl
-  /\ mem_inject f2 m2 tm2
-  /\ inject_incr f1 f2
-  /\ match_callstack f2
-        (mkframe cenv e te sp lo hi :: cs)
-        m2.(nextblock) tm2.(nextblock) m2.
+Lemma transl_expr_correct:
+  forall f m tm cenv e te sp lo hi cs
+    (MINJ: mem_inject f m tm)
+    (MATCH: match_callstack f
+             (mkframe cenv e te sp lo hi :: cs)
+             m.(nextblock) tm.(nextblock) m),
+  forall a v,
+  Csharpminor.eval_expr prog e m a v ->
+  forall ta
+    (TR: transl_expr cenv a = OK ta),
+  exists tv,
+     eval_expr tge (Vptr sp Int.zero) te tm ta tv
+  /\ val_inject f v tv.
+Proof.
+  induction 3; intros; simpl in TR; try (monadInv TR).
+  (* Evar *)
+  eapply var_get_correct; eauto.
+  (* Eaddrof *)
+  eapply var_addr_correct; eauto.
+  (* Econst *)
+  exploit transl_constant_correct; eauto. intros [tv [A B]].
+  exists tv; split. constructor; eauto. eauto.
+  (* Eunop *)
+  exploit IHeval_expr; eauto. intros [tv1 [EVAL1 INJ1]].
+  exploit eval_unop_compat; eauto. intros [tv [EVAL INJ]].
+  exists tv; split. econstructor; eauto. auto.
+  (* Ebinop *)
+  exploit IHeval_expr1; eauto. intros [tv1 [EVAL1 INJ1]].
+  exploit IHeval_expr2; eauto. intros [tv2 [EVAL2 INJ2]].
+  exploit eval_binop_compat; eauto. intros [tv [EVAL INJ]].
+  exists tv; split. econstructor; eauto. auto.
+  (* Eload *)
+  exploit IHeval_expr; eauto. intros [tv1 [EVAL1 INJ1]].
+  exploit loadv_inject; eauto. intros [tv [LOAD INJ]].
+  exists tv; split. econstructor; eauto. auto.
+  (* Econdition *)
+  exploit IHeval_expr1; eauto. intros [tv1 [EVAL1 INJ1]].
+  assert (transl_expr cenv (if vb1 then b else c) =
+          OK (if vb1 then x0 else x1)).
+    destruct vb1; auto.
+  exploit IHeval_expr2; eauto. intros [tv2 [EVAL2 INJ2]].
+  exists tv2; split. eapply eval_Econdition; eauto.
+  eapply bool_of_val_inject; eauto. auto.
+Qed.
+
+Lemma transl_exprlist_correct:
+  forall f m tm cenv e te sp lo hi cs
+    (MINJ: mem_inject f m tm)
+    (MATCH: match_callstack f
+             (mkframe cenv e te sp lo hi :: cs)
+             m.(nextblock) tm.(nextblock) m),
+  forall a v,
+  Csharpminor.eval_exprlist prog e m a v ->
+  forall ta
+    (TR: transl_exprlist cenv a = OK ta),
+  exists tv,
+     eval_exprlist tge (Vptr sp Int.zero) te tm ta tv
+  /\ val_list_inject f v tv.
+Proof.
+  induction 3; intros; monadInv TR.
+  exists (@nil val); split. constructor. constructor.
+  exploit transl_expr_correct; eauto. intros [tv1 [EVAL1 VINJ1]].
+  exploit IHeval_exprlist; eauto. intros [tv2 [EVAL2 VINJ2]].
+  exists (tv1 :: tv2); split. constructor; auto. constructor; auto.
+Qed.
+
+(** ** Semantic preservation for statements and functions *)
 
 Definition eval_funcall_prop
     (m1: mem) (fn: Csharpminor.fundef) (args: list val) (t: trace) (m2: mem) (res: val) : Prop :=
@@ -1783,316 +1865,12 @@ Definition exec_stmt_prop
         (mkframe cenv e te2 sp lo hi :: cs)
         m2.(nextblock) tm2.(nextblock) m2.
 
+(* Check (Csharpminor.eval_funcall_ind2 prog eval_funcall_prop exec_stmt_prop). *)
+
 (** There are as many cases in the inductive proof as there are evaluation
   rules in the Csharpminor semantics.  We treat each case as a separate
   lemma. *)
 
-Lemma transl_expr_Evar_correct:
-   forall (le : Csharpminor.letenv)
-     (e : Csharpminor.env) (m : mem) (id : positive)
-     (b : block) (chunk : memory_chunk) (v : val),
-   eval_var_ref prog e id b chunk ->
-   load chunk m b 0 = Some v ->
-   eval_expr_prop le e m (Csharpminor.Evar id) E0 m v.
-Proof.
-  intros; red; intros. unfold transl_expr in TR.
-  exploit var_get_correct; eauto.
-  intros [tv [EVAL VINJ]].
-  exists f1; exists tm1; exists tv; intuition eauto.
-Qed.
-
-Lemma transl_expr_Eaddrof_correct:
-   forall (le : Csharpminor.letenv)
-     (e : Csharpminor.env) (m : mem) (id : positive)
-     (b : block),
-   eval_var_addr prog e id b ->
-   eval_expr_prop le e m (Eaddrof id) E0 m (Vptr b Int.zero).
-Proof.
-  intros; red; intros. simpl in TR. 
-  exploit var_addr_correct; eauto.
-  intros [tv [EVAL VINJ]].
-  exists f1; exists tm1; exists tv. intuition eauto.
-Qed.
-
-Lemma transl_expr_Econst_correct:
-  forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-         (cst : Csharpminor.constant) (v : val),
-  Csharpminor.eval_constant cst = Some v ->
-  eval_expr_prop le e m (Csharpminor.Econst cst) E0 m v.
-Proof.
-  intros; red; intros; monadInv TR.
-  exploit transl_constant_correct; eauto.
-  intros [tv [EVAL VINJ]].
-  exists f1; exists tm1; exists tv. intuition eauto. 
-  constructor; eauto.
-Qed.
-
-Lemma transl_expr_Eunop_correct:
-  forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-         (op : unary_operation) (a : Csharpminor.expr) (t : trace)
-         (m1 : mem) (v1 v : val),
-  Csharpminor.eval_expr prog le e m a t m1 v1 ->
-  eval_expr_prop le e m a t m1 v1 ->
-  Csharpminor.eval_unop op v1 = Some v ->
-  eval_expr_prop le e m (Csharpminor.Eunop op a) t m1 v.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tvl [EVAL1 [VINJ1 [MINJ1 [INCR1 MATCH1]]]]]]].
-  exploit eval_unop_compat; eauto. intros [tv [EVAL VINJ]].
-  exists f2; exists tm2; exists tv; intuition.
-  econstructor; eauto.
-Qed.
-
-Lemma transl_expr_Ebinop_correct:
-  forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-         (op : binary_operation) (a1 a2 : Csharpminor.expr) (t1 : trace)
-         (m1 : mem) (v1 : val) (t2 : trace) (m2 : mem) (v2 : val)
-         (t : trace) (v : val),
-  Csharpminor.eval_expr prog le e m a1 t1 m1 v1 ->
-  eval_expr_prop le e m a1 t1 m1 v1 ->
-  Csharpminor.eval_expr prog le e m1 a2 t2 m2 v2 ->
-  eval_expr_prop le e m1 a2 t2 m2 v2 ->
-  Csharpminor.eval_binop op v1 v2 m2 = Some v ->
-  t = t1 ** t2 ->
-  eval_expr_prop le e m (Csharpminor.Ebinop op a1 a2) t m2 v.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tvl [EVAL1 [VINJ1 [MINJ1 [INCR1 MATCH1]]]]]]].
-  exploit H2.
-    eauto. eapply val_list_inject_incr; eauto. eauto. eauto.  
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exploit eval_binop_compat.
-    eauto. eapply val_inject_incr; eauto. eauto. eauto. 
-  intros [tv [EVAL VINJ]].
-  exists f3; exists tm3; exists tv; intuition.
-  econstructor; eauto.
-  eapply inject_incr_trans; eauto.
-Qed.
-
-Lemma transl_expr_Eload_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-     (chunk : memory_chunk) (a : Csharpminor.expr) (t: trace) (m1 : mem)
-     (v1 v : val),
-   Csharpminor.eval_expr prog le e m a t m1 v1 ->
-   eval_expr_prop le e m a t m1 v1 ->
-   loadv chunk m1 v1 = Some v ->
-   eval_expr_prop le e m (Csharpminor.Eload chunk a) t m1 v.
-Proof.
-  intros; red; intros.
-  monadInv TR. 
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL [VINJ1 [MINJ2 [INCR MATCH2]]]]]]].
-  exploit loadv_inject; eauto. 
-  intros [tv [TLOAD VINJ]].
-  exists f2; exists tm2; exists tv.
-  intuition.
-  econstructor; eauto.
-Qed.
-
-Lemma transl_expr_Ecall_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-     (sig : signature) (a : Csharpminor.expr) (bl : Csharpminor.exprlist)
-     (t1: trace) (m1: mem) (t2: trace) (m2: mem) (t3: trace) (m3: mem) 
-     (vf : val) (vargs : list val) (vres : val)
-     (f : Csharpminor.fundef) (t: trace),
-   Csharpminor.eval_expr prog le e m a t1 m1 vf ->
-   eval_expr_prop le e m a t1 m1 vf ->
-   Csharpminor.eval_exprlist prog le e m1 bl t2 m2 vargs ->
-   eval_exprlist_prop le e m1 bl t2 m2 vargs ->
-   Genv.find_funct ge vf = Some f ->
-   Csharpminor.funsig f = sig ->
-   Csharpminor.eval_funcall prog m2 f vargs t3 m3 vres ->
-   eval_funcall_prop m2 f vargs t3 m3 vres ->
-   t = t1 ** t2 ** t3 ->
-   eval_expr_prop le e m (Csharpminor.Ecall sig a bl) t m3 vres.
-Proof.
-  intros;red;intros. monadInv TR. 
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ1 [INCR1 MATCH1]]]]]]].
-  exploit H2.
-    eauto. eapply val_list_inject_incr; eauto. eauto. eauto. 
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ2 [INCR2 MATCH2]]]]]]].
-  assert (tv1 = vf).
-    elim (Genv.find_funct_inv H3). intros bf VF. rewrite VF in H3.
-    rewrite Genv.find_funct_find_funct_ptr in H3. 
-    generalize (Genv.find_funct_ptr_negative H3). intro.
-    assert (match_globalenvs f2). eapply match_callstack_match_globalenvs; eauto.
-    generalize (mg_functions _ H7 _ H4). intro.
-    rewrite VF in VINJ1. inversion VINJ1. subst vf. 
-    decEq. congruence. 
-    subst ofs2. replace x1 with 0. reflexivity. congruence.
-  subst tv1. elim (functions_translated _ _ H3). intros tf [FIND TRF].
-  exploit H6; eauto.
-  intros [f4 [tm4 [tres [EVAL3 [VINJ3 [MINJ3 [INCR3 MATCH3]]]]]]].
-  exists f4; exists tm4; exists tres. intuition.
-  eapply eval_Ecall; eauto. 
-  apply sig_preserved; auto.
-  apply inject_incr_trans with f2; auto. 
-  apply inject_incr_trans with f3; auto.
-Qed.
-
-Lemma transl_expr_Econdition_true_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-     (a b c : Csharpminor.expr) (t1: trace) (m1 : mem) (v1 : val)
-     (t2: trace) (m2 : mem) (v2 : val) (t: trace),
-   Csharpminor.eval_expr prog le e m a t1 m1 v1 ->
-   eval_expr_prop le e m a t1 m1 v1 ->
-   Val.is_true v1 ->
-   Csharpminor.eval_expr prog le e m1 b t2 m2 v2 ->
-   eval_expr_prop le e m1 b t2 m2 v2 ->
-   t = t1 ** t2 ->
-   eval_expr_prop le e m (Csharpminor.Econdition a b c) t m2 v2.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ1 [INCR1 MATCH1]]]]]]].
-  exploit H3.
-    eauto. eapply val_list_inject_incr; eauto. eauto. eauto.
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exists f3; exists tm3; exists tv2.
-  intuition.
-  eapply eval_Econdition with (b1 := true); eauto. 
-    eapply val_inject_bool_of_val; eauto. apply Val.bool_of_true_val; eauto.
-  eapply inject_incr_trans; eauto.
-Qed.
-
-Lemma transl_expr_Econdition_false_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-     (a b c : Csharpminor.expr) (t1: trace) (m1 : mem) (v1 : val)
-     (t2: trace) (m2 : mem) (v2 : val) (t: trace),
-   Csharpminor.eval_expr prog le e m a t1 m1 v1 ->
-   eval_expr_prop le e m a t1 m1 v1 ->
-   Val.is_false v1 ->
-   Csharpminor.eval_expr prog le e m1 c t2 m2 v2 ->
-   eval_expr_prop le e m1 c t2 m2 v2 ->
-   t = t1 ** t2 ->
-   eval_expr_prop le e m (Csharpminor.Econdition a b c) t m2 v2.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ1 [INCR1 MATCH1]]]]]]].
-  exploit H3.
-    eauto. eapply val_list_inject_incr; eauto. eauto. eauto.
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exists f3; exists tm3; exists tv2.
-  intuition.
-  eapply eval_Econdition with (b1 := false); eauto. 
-    eapply val_inject_bool_of_val; eauto. apply Val.bool_of_false_val; eauto.
-  eapply inject_incr_trans; eauto.
-Qed.
-
-Lemma transl_expr_Elet_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-     (a b : Csharpminor.expr) (t1: trace) (m1 : mem) (v1 : val)
-     (t2: trace) (m2 : mem) (v2 : val) (t: trace),
-   Csharpminor.eval_expr prog le e m a t1 m1 v1 ->
-   eval_expr_prop le e m a t1 m1 v1 ->
-   Csharpminor.eval_expr prog (v1 :: le) e m1 b t2 m2 v2 ->
-   eval_expr_prop (v1 :: le) e m1 b t2 m2 v2 ->
-   t = t1 ** t2 ->
-   eval_expr_prop le e m (Csharpminor.Elet a b) t m2 v2.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ1 [INCR1 MATCH1]]]]]]].
-  exploit H2.
-    eauto. 
-    constructor. eauto. eapply val_list_inject_incr; eauto.
-    eauto. eauto.
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exists f3; exists tm3; exists tv2.
-  intuition.
-  eapply eval_Elet; eauto.
-  eapply inject_incr_trans; eauto.
-Qed.
-
-Remark val_list_inject_nth:
-  forall f l1 l2, val_list_inject f l1 l2 ->
-  forall n v1, nth_error l1 n = Some v1 ->
-  exists v2, nth_error l2 n = Some v2 /\ val_inject f v1 v2.
-Proof.
-  induction 1; destruct n; simpl; intros.
-  discriminate. discriminate.
-  injection H1; intros; subst v. exists v'; split; auto.
-  eauto.
-Qed.
-
-Lemma transl_expr_Eletvar_correct:
-   forall (le : list val) (e : Csharpminor.env) (m : mem) (n : nat)
-     (v : val),
-   nth_error le n = Some v ->
-   eval_expr_prop le e m (Csharpminor.Eletvar n) E0 m v.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit val_list_inject_nth; eauto. intros [tv [A B]].
-  exists f1; exists tm1; exists tv.
-  intuition.
-  eapply eval_Eletvar; auto.
-Qed.
-
-Lemma transl_expr_Ealloc_correct:
-  forall (le: list val) (e: Csharpminor.env) (m1: mem) (a: Csharpminor.expr)
-         (t: trace) (m2: mem) (n: int) (m3: mem) (b: block),
-  Csharpminor.eval_expr prog le e m1 a t m2 (Vint n) ->
-  eval_expr_prop le e m1 a t m2 (Vint n) ->
-  Mem.alloc m2 0 (Int.signed n) = (m3, b) ->
-  eval_expr_prop le e m1 (Csharpminor.Ealloc a) t m3 (Vptr b Int.zero).
-Proof.
-  intros; red; intros. monadInv TR. 
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ2 [INCR2 MATCH2]]]]]]].
-  inversion VINJ1. subst tv1 i. 
-  caseEq (alloc tm2 0 (Int.signed n)). intros tm3 tb TALLOC.
-  assert (LB: Int.min_signed <= 0). compute. congruence.
-  assert (HB: Int.signed n <= Int.max_signed). 
-    generalize (Int.signed_range n); omega.
-  exploit alloc_parallel_inject; eauto.
-  intros [MINJ3 INCR3].
-  exists (extend_inject b (Some (tb, 0)) f2); 
-  exists tm3; exists (Vptr tb Int.zero).
-  split. econstructor; eauto.
-  split. econstructor. unfold extend_inject, eq_block. rewrite zeq_true. reflexivity.
-  reflexivity.
-  split. assumption.
-  split. eapply inject_incr_trans; eauto. 
-  eapply match_callstack_alloc; eauto.
-Qed.
-
-Lemma transl_exprlist_Enil_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem),
-   eval_exprlist_prop le e m Csharpminor.Enil E0 m nil.
-Proof.
-  intros; red; intros. monadInv TR. 
-  exists f1; exists tm1; exists (@nil val).
-  intuition. constructor.
-Qed.
-
-Lemma transl_exprlist_Econs_correct:
-   forall (le : Csharpminor.letenv) (e : Csharpminor.env) (m : mem)
-     (a : Csharpminor.expr) (bl : Csharpminor.exprlist)
-     (t1: trace) (m1 : mem) (v : val) 
-     (t2: trace) (m2 : mem) (vl : list val) (t: trace),
-   Csharpminor.eval_expr prog le e m a t1 m1 v ->
-   eval_expr_prop le e m a t1 m1 v ->
-   Csharpminor.eval_exprlist prog le e m1 bl t2 m2 vl ->
-   eval_exprlist_prop le e m1 bl t2 m2 vl ->
-   t = t1 ** t2 ->
-   eval_exprlist_prop le e m (Csharpminor.Econs a bl) t m2 (v :: vl).
-Proof.
-  intros; red; intros. monadInv TR. 
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exploit H2.
-    eauto. eapply val_list_inject_incr; eauto. eauto. eauto.
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ3 [INCR3 MATCH3]]]]]]].
-  exists f3; exists tm3; exists (tv1 :: tv2).
-  intuition. econstructor; eauto.
-  constructor. eapply val_inject_incr; eauto. auto.
-  eapply inject_incr_trans; eauto.
-Qed.
-
 Lemma transl_funcall_internal_correct:
    forall (m : mem) (f : Csharpminor.function) (vargs : list val)
      (e : Csharpminor.env) (m1 : mem) (lb : list block) (m2: mem)
@@ -2176,77 +1954,104 @@ Proof.
   intuition. constructor. constructor.
 Qed.
 
-Lemma transl_stmt_Sexpr_correct:
-   forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
-          (t: trace) (m1 : mem) (v : val),
-   Csharpminor.eval_expr prog nil e m a t m1 v ->
-   eval_expr_prop nil e m a t m1 v ->
-   exec_stmt_prop e m (Csharpminor.Sexpr a) t m1 Csharpminor.Out_normal.
-Proof.
-  intros; red; intros. monadInv TR. 
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exists f2; exists te1; exists tm2; exists Out_normal.
-  intuition. econstructor; eauto.
-  constructor.
-Qed.
-
 Lemma transl_stmt_Sassign_correct:
-   forall (e : Csharpminor.env) (m : mem)
-     (id : ident) (a : Csharpminor.expr) (t: trace) (m1 : mem) (b : block)
-     (chunk : memory_chunk) (v : val) (m2 : mem),
-   Csharpminor.eval_expr prog nil e m a t m1 v ->
-   eval_expr_prop nil e m a t m1 v ->
-   eval_var_ref prog e id b chunk ->
-   store chunk m1 b 0 v = Some m2 ->
-   exec_stmt_prop e m (Csharpminor.Sassign id a) t m2 Csharpminor.Out_normal.
+  forall (e : Csharpminor.env) (m : mem) (id : ident)
+         (a : Csharpminor.expr) (v : val) (m' : mem),
+  Csharpminor.eval_expr prog e m a v ->
+  exec_assign prog e m id v m' ->
+  exec_stmt_prop e m (Csharpminor.Sassign id a) E0 m' Csharpminor.Out_normal.
 Proof.
   intros; red; intros. monadInv TR.
-  exploit H0; eauto. 
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ1 [INCR12 MATCH1]]]]]]].
-  exploit var_set_correct; eauto.
-  intros [te3 [tm3 [EVAL2 [MINJ2 MATCH2]]]].
-  exists f2; exists te3; exists tm3; exists Out_normal.
+  exploit transl_expr_correct; eauto. intros [tv1 [EVAL1 VINJ1]].
+  exploit var_set_correct; eauto. 
+  intros [te2 [tm2 [EVAL2 [MINJ2 MATCH2]]]].
+  exists f1; exists te2; exists tm2; exists Out_normal.
   intuition. constructor.
 Qed.
 
 Lemma transl_stmt_Sstore_correct:
-   forall (e : Csharpminor.env) (m : mem)
-     (chunk : memory_chunk) (a b : Csharpminor.expr) (t1: trace) (m1 : mem)
-     (v1 : val) (t2: trace) (m2 : mem) (v2 : val) 
-     (t3: trace) (m3 : mem),
-   Csharpminor.eval_expr prog nil e m a t1 m1 v1 ->
-   eval_expr_prop nil e m a t1 m1 v1 ->
-   Csharpminor.eval_expr prog nil e m1 b t2 m2 v2 ->
-   eval_expr_prop nil e m1 b t2 m2 v2 ->
-   storev chunk m2 v1 v2 = Some m3 ->
-   t3 = t1 ** t2 ->
-   exec_stmt_prop e m (Csharpminor.Sstore chunk a b) t3 m3 Csharpminor.Out_normal.
+  forall (e : Csharpminor.env) (m : mem) (chunk : memory_chunk)
+         (a b : Csharpminor.expr) (v1 v2 : val) (m' : mem),
+  Csharpminor.eval_expr prog e m a v1 ->
+  Csharpminor.eval_expr prog e m b v2 ->
+  storev chunk m v1 v2 = Some m' ->
+  exec_stmt_prop e m (Csharpminor.Sstore chunk a b) E0 m' Csharpminor.Out_normal.
 Proof.
   intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exploit H2.
-    eauto. 
-    eapply val_list_inject_incr; eauto.
-    eauto. eauto. 
-  intros [f3 [tm3 [tv2 [EVAL2 [VINJ2 [MINJ3 [INCR3 MATCH3]]]]]]].
+  exploit transl_expr_correct.
+    eauto. eauto. eexact H. eauto. 
+  intros [tv1 [EVAL1 INJ1]].
+  exploit transl_expr_correct.
+    eauto. eauto. eexact H0. eauto. 
+  intros [tv2 [EVAL2 INJ2]].
   exploit make_store_correct.
-    eexact EVAL1. eexact EVAL2. eauto. eauto. 
-    eapply val_inject_incr; eauto. eauto.
-  intros [tm4 [EVAL [MINJ4 NEXTBLOCK]]].
-  exists f3; exists te1; exists tm4; exists Out_normal.
+    eexact EVAL1. eexact EVAL2. eauto. eauto. eauto. eauto.
+  intros [tm2 [EXEC [MINJ2 NEXTBLOCK]]].
+  exists f1; exists te1; exists tm2; exists Out_normal.
   intuition. 
   constructor.
-  eapply inject_incr_trans; eauto.
-  assert (val_inject f3 v1 tv1). eapply val_inject_incr; eauto.
-  unfold storev in H3; destruct v1; try discriminate.
-  inversion H4. 
-  rewrite NEXTBLOCK. replace (nextblock m3) with (nextblock m2).
+  unfold storev in H1; destruct v1; try discriminate.
+  inv INJ1.
+  rewrite NEXTBLOCK. replace (nextblock m') with (nextblock m).
   eapply match_callstack_mapped; eauto. congruence.
   symmetry. eapply nextblock_store; eauto. 
 Qed.
 
+Lemma transl_stmt_Scall_correct:
+  forall (e : Csharpminor.env) (m : mem) (optid : option ident)
+         (sig : signature) (a : Csharpminor.expr)
+         (bl : list Csharpminor.expr) (vf : val) (vargs : list val)
+         (f : Csharpminor.fundef) (t : trace) (m1 : mem) (vres : val)
+         (m2 : mem),
+  Csharpminor.eval_expr prog e m a vf ->
+  Csharpminor.eval_exprlist prog e m bl vargs ->
+  Genv.find_funct (Genv.globalenv prog) vf = Some f ->
+  Csharpminor.funsig f = sig ->
+  Csharpminor.eval_funcall prog m f vargs t m1 vres ->
+  eval_funcall_prop m f vargs t m1 vres ->
+  exec_opt_assign prog e m1 optid vres m2 ->
+  exec_stmt_prop e m (Csharpminor.Scall optid sig a bl) t m2 Csharpminor.Out_normal.
+Proof.
+  intros;red;intros.
+  assert (forall tv, val_inject f1 vf tv -> tv = vf).
+    intros.
+    elim (Genv.find_funct_inv H1). intros bf VF. rewrite VF in H1.
+    rewrite Genv.find_funct_find_funct_ptr in H1. 
+    generalize (Genv.find_funct_ptr_negative H1). intro.
+    assert (match_globalenvs f1). eapply match_callstack_match_globalenvs; eauto.
+    generalize (mg_functions _ H8 _ H7). intro.
+    rewrite VF in H6. inv H6.  
+    decEq. congruence. 
+    replace x with 0. reflexivity. congruence.
+  inv H5; monadInv TR.
+  (* optid = None *)
+  exploit transl_expr_correct; eauto. intros [tv1 [EVAL1 VINJ1]].
+  exploit transl_exprlist_correct; eauto. intros [tv2 [EVAL2 VINJ2]].
+  rewrite <- (H6 _ VINJ1) in H1. 
+  elim (functions_translated _ _ H1). intros tf [FIND TRF].
+  exploit H4; eauto.
+  intros [f2 [tm2 [tres [EVAL3 [VINJ3 [MINJ3 [INCR3 MATCH3]]]]]]].
+  exists f2; exists te1; exists tm2; exists Out_normal.
+  intuition. eapply exec_Scall; eauto. 
+  apply sig_preserved; auto.
+  constructor.
+  (* optid = Some id *)
+  exploit transl_expr_correct; eauto. intros [tv1 [EVAL1 VINJ1]].
+  exploit transl_exprlist_correct; eauto. intros [tv2 [EVAL2 VINJ2]].
+  rewrite <- (H6 _ VINJ1) in H1. 
+  elim (functions_translated _ _ H1). intros tf [FIND TRF].
+  exploit H4; eauto.
+  intros [f2 [tm2 [tres [EVAL3 [VINJ3 [MINJ3 [INCR3 MATCH3]]]]]]].
+  exploit var_set_self_correct.
+    eauto. eexact MATCH3. eauto. eauto. eauto. 
+  intros [te3 [tm3 [EVAL4 [MINJ4 MATCH4]]]].  
+  exists f2; exists te3; exists tm3; exists Out_normal. intuition.
+  eapply exec_Sseq_continue. eapply exec_Scall; eauto. 
+  apply sig_preserved; auto.
+  simpl. eexact EVAL4. traceEq.
+  constructor.
+Qed.
+
 Lemma transl_stmt_Sseq_continue_correct:
   forall (e : Csharpminor.env) (m : mem) (s1 s2 : Csharpminor.stmt)
          (t1 t2: trace) (m1 m2 : mem) (t: trace) (out : Csharpminor.outcome),
@@ -2284,54 +2089,27 @@ Proof.
   inversion OINJ1; subst out tout1; congruence.
 Qed.
 
-Lemma transl_stmt_Sifthenelse_true_correct:
-   forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
-     (sl1 sl2 : Csharpminor.stmt) 
-     (t1: trace) (m1 : mem) (v1 : val) (t2: trace) (m2 : mem)
-     (out : Csharpminor.outcome) (t: trace),
-   Csharpminor.eval_expr prog nil e m a t1 m1 v1 ->
-   eval_expr_prop nil e m a t1 m1 v1 ->
-   Val.is_true v1 ->
-   Csharpminor.exec_stmt prog e m1 sl1 t2 m2 out ->
-   exec_stmt_prop e m1 sl1 t2 m2 out ->
-   t = t1 ** t2 ->
-   exec_stmt_prop e m (Csharpminor.Sifthenelse a sl1 sl2) t m2 out.
-Proof.
-  intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exploit H3; eauto.
-  intros [f3 [te3 [tm3 [tout [EVAL2 [OINJ [MINJ3 [INCR3 MATCH3]]]]]]]].
-  exists f3; exists te3; exists tm3; exists tout.
-  intuition. 
-  eapply exec_Sifthenelse with (b1 := true); eauto.
-  eapply val_inject_bool_of_val; eauto. apply Val.bool_of_true_val; auto.
-  eapply inject_incr_trans; eauto.
-Qed.
-
-Lemma transl_stmt_Sifthenelse_false_correct:
-   forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
-     (sl1 sl2 : Csharpminor.stmt) 
-     (t1: trace) (m1 : mem) (v1 : val) (t2: trace) (m2 : mem)
-     (out : Csharpminor.outcome) (t: trace),
-   Csharpminor.eval_expr prog nil e m a t1 m1 v1 ->
-   eval_expr_prop nil e m a t1 m1 v1 ->
-   Val.is_false v1 ->
-   Csharpminor.exec_stmt prog e m1 sl2 t2 m2 out ->
-   exec_stmt_prop e m1 sl2 t2 m2 out ->
-   t = t1 ** t2 ->
-   exec_stmt_prop e m (Csharpminor.Sifthenelse a sl1 sl2) t m2 out.
+Lemma transl_stmt_Sifthenelse_correct:
+  forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
+         (sl1 sl2 : Csharpminor.stmt) (v : val) (vb : bool) (t : trace)
+         (m' : mem) (out : Csharpminor.outcome),
+  Csharpminor.eval_expr prog e m a v ->
+  Val.bool_of_val v vb ->
+  Csharpminor.exec_stmt prog e m (if vb then sl1 else sl2) t m' out ->
+  exec_stmt_prop e m (if vb then sl1 else sl2) t m' out ->
+  exec_stmt_prop e m (Csharpminor.Sifthenelse a sl1 sl2) t m' out.
 Proof.
   intros; red; intros. monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL1 [VINJ1 [MINJ2 [INCR2 MATCH2]]]]]]].
-  exploit H3; eauto.
-  intros [f3 [te3 [tm3 [tout [EVAL2 [OINJ [MINJ3 [INCR3 MATCH3]]]]]]]].
-  exists f3; exists te3; exists tm3; exists tout.
+  exploit transl_expr_correct; eauto.
+  intros [tv1 [EVAL1 VINJ1]].
+  assert (transl_stmt cenv (if vb then sl1 else sl2) =
+          OK (if vb then x0 else x1)). destruct vb; auto.
+  exploit H2; eauto.
+  intros [f2 [te2 [tm2 [tout [EVAL2 [OINJ [MINJ2 [INCR2 MATCH2]]]]]]]].
+  exists f2; exists te2; exists tm2; exists tout.
   intuition. 
-  eapply exec_Sifthenelse with (b1 := false); eauto.
-  eapply val_inject_bool_of_val; eauto. apply Val.bool_of_false_val; auto.
-  eapply inject_incr_trans; eauto.
+  eapply exec_Sifthenelse; eauto.
+  eapply bool_of_val_inject; eauto.
 Qed.
 
 Lemma transl_stmt_Sloop_loop_correct:
@@ -2373,6 +2151,18 @@ Proof.
   inversion OINJ1; subst out tout1; congruence.
 Qed.
 
+Remark outcome_block_inject:
+  forall f out tout,
+  outcome_inject f out tout ->
+  outcome_inject f (Csharpminor.outcome_block out) (outcome_block tout).
+Proof.
+  induction 1; simpl.
+  constructor.
+  destruct n; constructor.
+  constructor.
+  constructor; auto.
+Qed.
+
 Lemma transl_stmt_Sblock_correct:
    forall (e : Csharpminor.env) (m : mem) (sl : Csharpminor.stmt)
      (t1: trace) (m1 : mem) (out : Csharpminor.outcome),
@@ -2386,11 +2176,7 @@ Proof.
   intros [f2 [te2 [tm2 [tout1 [EVAL1 [OINJ1 [MINJ2 [INCR2 MATCH2]]]]]]]].
   exists f2; exists te2; exists tm2; exists (outcome_block tout1).
   intuition. eapply exec_Sblock; eauto.
-  inversion OINJ1; subst out tout1; simpl.
-  constructor.
-  destruct n; constructor.
-  constructor.
-  constructor; auto.
+  apply outcome_block_inject; auto.
 Qed.
 
 Lemma transl_stmt_Sexit_correct:
@@ -2403,21 +2189,22 @@ Proof.
 Qed.
 
 Lemma transl_stmt_Sswitch_correct:
-  forall (e : Csharpminor.env) (m : mem)
-         (a : Csharpminor.expr) (cases : list (int * nat)) (default : nat)
-         (t1 : trace) (m1 : mem) (n : int),
-  Csharpminor.eval_expr prog nil e m a t1 m1 (Vint n) ->
-  eval_expr_prop nil e m a t1 m1 (Vint n) ->
-  exec_stmt_prop e m (Csharpminor.Sswitch a cases default) t1 m1
-       (Csharpminor.Out_exit (Csharpminor.switch_target n default cases)).
+  forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
+         (cases : list (int * nat)) (default : nat) (n : int),
+  Csharpminor.eval_expr prog e m a (Vint n) ->
+  exec_stmt_prop e m (Csharpminor.Sswitch a cases default) E0 m
+                     (Csharpminor.Out_exit (switch_target n default cases)).
 Proof.
   intros; red; intros. monadInv TR.
-  exploit H0; eauto. 
-  intros [f2 [tm2 [tv1 [EVAL [VINJ1 [MINJ2 [INCR MATCH2]]]]]]].
-  exists f2; exists te1; exists tm2; 
-  exists (Out_exit (switch_target n default cases)). intuition. 
-  constructor. inversion VINJ1. subst tv1. assumption.
-  constructor. 
+  exploit transl_expr_correct; eauto.
+  intros [tv1 [EVAL VINJ1]].
+  inv VINJ1.
+  exists f1; exists te1; exists tm1; exists (Out_exit (switch_target n default cases)).
+  split. constructor. auto.
+  split. constructor.
+  split. auto.
+  split. apply inject_incr_refl.
+  auto.
 Qed.
 
 Lemma transl_stmt_Sreturn_none_correct:
@@ -2431,17 +2218,16 @@ Proof.
 Qed.
 
 Lemma transl_stmt_Sreturn_some_correct:
-   forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
-     (t1: trace) (m1 : mem) (v : val),
-   Csharpminor.eval_expr prog nil e m a t1 m1 v ->
-   eval_expr_prop nil e m a t1 m1 v ->
-   exec_stmt_prop e m (Csharpminor.Sreturn (Some a)) t1 m1
-     (Csharpminor.Out_return (Some v)).
+  forall (e : Csharpminor.env) (m : mem) (a : Csharpminor.expr)
+         (v : val),
+  Csharpminor.eval_expr prog e m a v ->
+  exec_stmt_prop e m (Csharpminor.Sreturn (Some a)) E0 m
+                     (Csharpminor.Out_return (Some v)).
 Proof.
   intros; red; intros; monadInv TR.
-  exploit H0; eauto.
-  intros [f2 [tm2 [tv1 [EVAL [VINJ1 [MINJ2 [INCR MATCH2]]]]]]].
-  exists f2; exists te1; exists tm2; exists (Out_return (Some tv1)).
+  exploit transl_expr_correct; eauto.
+  intros [tv1 [EVAL VINJ1]].
+  exists f1; exists te1; exists tm1; exists (Out_return (Some tv1)).
   intuition. econstructor; eauto. constructor; auto.
 Qed.
 
@@ -2453,36 +2239,45 @@ Lemma transl_function_correct:
    Csharpminor.eval_funcall prog m1 f vargs t m2 vres ->
    eval_funcall_prop m1 f vargs t m2 vres.
 Proof
-  (Csharpminor.eval_funcall_ind4 prog
-     eval_expr_prop
-     eval_exprlist_prop
+  (Csharpminor.eval_funcall_ind2 prog
+     eval_funcall_prop
+     exec_stmt_prop
+
+     transl_funcall_internal_correct
+     transl_funcall_external_correct
+     transl_stmt_Sskip_correct
+     transl_stmt_Sassign_correct
+     transl_stmt_Sstore_correct
+     transl_stmt_Scall_correct
+     transl_stmt_Sseq_continue_correct
+     transl_stmt_Sseq_stop_correct
+     transl_stmt_Sifthenelse_correct
+     transl_stmt_Sloop_loop_correct
+     transl_stmt_Sloop_exit_correct
+     transl_stmt_Sblock_correct
+     transl_stmt_Sexit_correct
+     transl_stmt_Sswitch_correct
+     transl_stmt_Sreturn_none_correct
+     transl_stmt_Sreturn_some_correct).
+
+Lemma transl_stmt_correct:
+   forall e m1 s t m2 out,
+   Csharpminor.exec_stmt prog e m1 s t m2 out ->
+   exec_stmt_prop e m1 s t m2 out.
+Proof
+  (Csharpminor.exec_stmt_ind2 prog
      eval_funcall_prop
      exec_stmt_prop
 
-     transl_expr_Evar_correct
-     transl_expr_Eaddrof_correct
-     transl_expr_Econst_correct
-     transl_expr_Eunop_correct
-     transl_expr_Ebinop_correct
-     transl_expr_Eload_correct
-     transl_expr_Ecall_correct
-     transl_expr_Econdition_true_correct
-     transl_expr_Econdition_false_correct
-     transl_expr_Elet_correct
-     transl_expr_Eletvar_correct
-     transl_expr_Ealloc_correct
-     transl_exprlist_Enil_correct
-     transl_exprlist_Econs_correct
      transl_funcall_internal_correct
      transl_funcall_external_correct
      transl_stmt_Sskip_correct
-     transl_stmt_Sexpr_correct
      transl_stmt_Sassign_correct
      transl_stmt_Sstore_correct
+     transl_stmt_Scall_correct
      transl_stmt_Sseq_continue_correct
      transl_stmt_Sseq_stop_correct
-     transl_stmt_Sifthenelse_true_correct
-     transl_stmt_Sifthenelse_false_correct
+     transl_stmt_Sifthenelse_correct
      transl_stmt_Sloop_loop_correct
      transl_stmt_Sloop_exit_correct
      transl_stmt_Sblock_correct
@@ -2491,6 +2286,133 @@ Proof
      transl_stmt_Sreturn_none_correct
      transl_stmt_Sreturn_some_correct).
 
+(** ** Semantic preservation for divergence *)
+
+Definition evalinf_funcall_prop
+    (m1: mem) (fn: Csharpminor.fundef) (args: list val) (t: traceinf) : Prop :=
+  forall tfn f1 tm1 cs targs
+  (TR: transl_fundef gce fn = OK tfn)
+  (MINJ: mem_inject f1 m1 tm1)
+  (MATCH: match_callstack f1 cs m1.(nextblock) tm1.(nextblock) m1)
+  (ARGSINJ: val_list_inject f1 args targs),
+  evalinf_funcall tge tm1 tfn targs t.
+
+Definition execinf_stmt_prop
+    (e: Csharpminor.env) (m1: mem) (s: Csharpminor.stmt) (t: traceinf): Prop :=
+  forall cenv ts f1 te1 tm1 sp lo hi cs
+  (TR: transl_stmt cenv s = OK ts)
+  (MINJ: mem_inject f1 m1 tm1)
+  (MATCH: match_callstack f1
+           (mkframe cenv e te1 sp lo hi :: cs)
+           m1.(nextblock) tm1.(nextblock) m1),
+  execinf_stmt tge (Vptr sp Int.zero) te1 tm1 ts t.
+
+Theorem transl_function_divergence_correct:
+  forall m1 fn args t,
+  Csharpminor.evalinf_funcall prog m1 fn args t ->
+  evalinf_funcall_prop m1 fn args t.
+Proof.
+  unfold evalinf_funcall_prop; cofix FUNCALL.
+  assert (STMT: forall e m1 s t,
+          Csharpminor.execinf_stmt prog e m1 s t ->
+          execinf_stmt_prop e m1 s t).
+  unfold execinf_stmt_prop; cofix STMT.
+  intros. inv H; simpl in TR; try (monadInv TR).
+  (* Scall *)
+  assert (forall tv, val_inject f1 vf tv -> tv = vf).
+    intros.
+    elim (Genv.find_funct_inv H2). intros bf VF. rewrite VF in H2.
+    rewrite Genv.find_funct_find_funct_ptr in H2. 
+    generalize (Genv.find_funct_ptr_negative H2). intro.
+    assert (match_globalenvs f1). eapply match_callstack_match_globalenvs; eauto.
+    generalize (mg_functions _ H5 _ H3). intro.
+    rewrite VF in H. inv H.  
+    decEq. congruence. 
+    replace x with 0. reflexivity. congruence.
+  destruct optid; monadInv TR.
+  (* optid = Some i *)
+  destruct (transl_expr_correct _ _ _ _ _ _ _ _ _ _ MINJ MATCH _ _ H0 _ EQ)
+  as [tv1 [EVAL1 VINJ1]].
+  destruct (transl_exprlist_correct _ _ _ _ _ _ _ _ _ _ MINJ MATCH _ _ H1 _ EQ1)
+  as [tv2 [EVAL2 VINJ2]].
+  rewrite <- (H _ VINJ1) in H2. 
+  elim (functions_translated _ _ H2). intros tf [FIND TRF].
+  apply execinf_Sseq_1. eapply execinf_Scall.
+  eauto. eauto. eauto. apply sig_preserved; auto. 
+  eapply FUNCALL; eauto.
+  (* optid = None *)
+  destruct (transl_expr_correct _ _ _ _ _ _ _ _ _ _ MINJ MATCH _ _ H0 _ EQ)
+  as [tv1 [EVAL1 VINJ1]].
+  destruct (transl_exprlist_correct _ _ _ _ _ _ _ _ _ _ MINJ MATCH _ _ H1 _ EQ1)
+  as [tv2 [EVAL2 VINJ2]].
+  rewrite <- (H _ VINJ1) in H2. 
+  elim (functions_translated _ _ H2). intros tf [FIND TRF].
+  eapply execinf_Scall.
+  eauto. eauto. eauto. apply sig_preserved; auto. 
+  eapply FUNCALL; eauto.
+  (* Sseq, 1 *)
+  apply execinf_Sseq_1. eapply STMT; eauto. 
+  (* Sseq, 2 *)
+  destruct (transl_stmt_correct _ _ _ _ _ _ H0
+            _ _ _ _ _ _ _ _ _ EQ MINJ MATCH)
+  as [f2 [te2 [tm2 [tout [EXEC1 [OUT [MINJ2 [INCR12 MATCH2]]]]]]]].
+  inv OUT.
+  eapply execinf_Sseq_2. eexact EXEC1.
+  eapply STMT; eauto. 
+  auto.
+  (* Sifthenelse, true *)
+  destruct (transl_expr_correct _ _ _ _ _ _ _ _ _ _ MINJ MATCH _ _ H0 _ EQ)
+  as [tv1 [EVAL1 VINJ1]].
+  assert (transl_stmt cenv (if vb then sl1 else sl2) =
+          OK (if vb then x0 else x1)). destruct vb; auto.
+  eapply execinf_Sifthenelse. eexact EVAL1. 
+  eapply bool_of_val_inject; eauto.
+  eapply STMT; eauto.
+  (* Sloop, body *)
+  eapply execinf_Sloop_body. eapply STMT; eauto.
+  (* Sloop, loop *)
+  destruct (transl_stmt_correct _ _ _ _ _ _ H0
+            _ _ _ _ _ _ _ _ _ EQ MINJ MATCH)
+  as [f2 [te2 [tm2 [tout [EXEC1 [OUT [MINJ2 [INCR12 MATCH2]]]]]]]].
+  inv OUT.
+  eapply execinf_Sloop_loop. eexact EXEC1. 
+  eapply STMT; eauto. 
+  simpl. rewrite EQ. auto. auto.
+  (* Sblock *)
+  apply execinf_Sblock. eapply STMT; eauto.
+  (* stutter *)
+  generalize (execinf_stmt_N_inv _ _ _ _ _ _ H0); intro.
+  destruct s; try contradiction; monadInv TR.
+  apply execinf_Sseq_1. eapply STMT; eauto. 
+  apply execinf_Sblock. eapply STMT; eauto.
+  (* Sloop_block *)
+  destruct (transl_stmt_correct _ _ _ _ _ _ H0
+            _ _ _ _ _ _ _ _ _ EQ MINJ MATCH)
+  as [f2 [te2 [tm2 [tout [EXEC1 [OUT [MINJ2 [INCR12 MATCH2]]]]]]]].
+  inv OUT. 
+  eapply execinf_Sloop_loop. eexact EXEC1. 
+  eapply STMT with (s := Csharpminor.Sloop sl); eauto.
+  apply execinf_Sblock_inv; eauto.
+  simpl. rewrite EQ; auto. auto.   
+  (* Function *)
+  intros. inv H.
+  monadInv TR. generalize EQ.
+  unfold transl_function.
+  caseEq (build_compilenv gce f); intros cenv stacksize CENV.
+  destruct (zle stacksize Int.max_signed); try congruence.
+  intro TR. monadInv TR.
+  caseEq (alloc tm1 0 stacksize). intros tm2 sp ALLOC.
+  destruct (function_entry_ok _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+            H1 H2 MATCH CENV z ALLOC ARGSINJ MINJ H0 EQ2)
+  as [f2 [te2 [tm3 [STOREPARAM [MINJ2 [INCR12 [MATCH2 BLOCKS]]]]]]].
+  eapply evalinf_funcall_internal; simpl.
+  eauto. reflexivity. eapply execinf_Sseq_2. eexact STOREPARAM. 
+  unfold execinf_stmt_prop in STMT. eapply STMT; eauto.
+  traceEq.
+Qed.
+
+(** ** Semantic preservation for whole programs *)  
+
 (** The [match_globalenvs] relation holds for the global environments
   of the source program and the transformed program. *)
 
@@ -2513,12 +2435,11 @@ Qed.
   follows. *)
 
 Theorem transl_program_correct:
-  forall t n,
-  Csharpminor.exec_program prog t (Vint n) ->
-  exec_program tprog t (Vint n).
+  forall beh,
+  Csharpminor.exec_program prog beh ->
+  exec_program tprog beh.
 Proof.
-  intros t n [b [fn [m [FINDS [FINDF [SIG EVAL]]]]]].
-  elim (function_ptr_translated _ _ FINDF). intros tfn [TFIND TR].
+  intros.
   set (m0 := Genv.init_mem prog) in *.
   set (f := meminj_init m0).
   assert (MINJ0: mem_inject f m0 m0).
@@ -2526,17 +2447,31 @@ Proof.
     unfold m0; apply Genv.initmem_inject_neutral.
   assert (MATCH0: match_callstack f nil m0.(nextblock) m0.(nextblock) m0).
     constructor. unfold f; apply match_globalenvs_init.
-  fold ge in EVAL.
+  inv H.
+  (* Terminating case *)
+  subst ge0 m1. 
+  elim (function_ptr_translated _ _ H1). intros tfn [TFIND TR].
+  fold ge in H3.
   exploit transl_function_correct; eauto.
   intros [f1 [tm1 [tres [TEVAL [VINJ [MINJ1 [INCR MATCH1]]]]]]].
-  exists b; exists tfn; exists tm1.
-  split. fold tge. rewrite <- FINDS. 
-  replace (prog_main prog) with (AST.prog_main tprog). fold ge. apply symbols_preserved.
+  econstructor; eauto. 
+  fold tge. rewrite <- H0. fold ge. 
+  replace (prog_main prog) with (AST.prog_main tprog). apply symbols_preserved.
   apply transform_partial_program2_main with (transl_fundef gce) transl_globvar. assumption.
-  split. assumption.
-  split. rewrite <- SIG. apply sig_preserved; auto.
+  rewrite <- H2. apply sig_preserved; auto.
+  rewrite (Genv.init_mem_transf_partial2 (transl_fundef gce) transl_globvar _ TRANSL).
+  inv VINJ. fold tge; fold m0. eexact TEVAL.
+  (* Diverging case *)
+  subst ge0 m1. 
+  elim (function_ptr_translated _ _ H1). intros tfn [TFIND TR].
+  econstructor; eauto.
+  fold tge. rewrite <- H0. fold ge. 
+  replace (prog_main prog) with (AST.prog_main tprog). apply symbols_preserved.
+  apply transform_partial_program2_main with (transl_fundef gce) transl_globvar. assumption.
+  rewrite <- H2. apply sig_preserved; auto.
   rewrite (Genv.init_mem_transf_partial2 (transl_fundef gce) transl_globvar _ TRANSL).
-  inversion VINJ; subst tres. assumption. 
+  fold tge; fold m0.
+  eapply (transl_function_divergence_correct _ _ _ _ H3); eauto.
 Qed.
 
 End TRANSLATION.
diff --git a/cfrontend/Csem.v b/cfrontend/Csem.v
index 385f7c683..af601acae 100644
--- a/cfrontend/Csem.v
+++ b/cfrontend/Csem.v
@@ -11,6 +11,7 @@ Require Import Mem.
 Require Import Events.
 Require Import Globalenvs.
 Require Import Csyntax.
+Require Import Smallstep.
 
 (** * Semantics of type-dependent operations *)
 
@@ -509,129 +510,108 @@ Section RELSEM.
 
 Variable ge: genv.
 
-(** [eval_expr ge e m1 a t m2 v] defines the evaluation of expression [a]
-  in r-value position.  [v] is the value of the expression.
-  [m1] is the initial memory state, [m2] the final memory state.
-  [t] is the trace of input/output events performed during this
-  evaluation. *)
+Section EXPR.
+
+Variable e: env.
+Variable m: mem.
 
-Inductive eval_expr: env -> mem -> expr -> trace -> mem -> val -> Prop :=
-  | eval_Econst_int:   forall e m i ty,
-      eval_expr e m (Expr (Econst_int i) ty)
-               E0 m (Vint i)
-  | eval_Econst_float:   forall e m f ty,
-      eval_expr e m (Expr (Econst_float f) ty)
-               E0 m (Vfloat f)
-  | eval_Elvalue: forall e m a ty t m1 loc ofs v,
-      eval_lvalue e m (Expr a ty) t m1 loc ofs ->
-      load_value_of_type ty m1 loc ofs = Some v ->
-      eval_expr e m (Expr a ty) 
-                t m1 v
-  | eval_Eaddrof: forall e m a t m1 loc ofs ty,
-      eval_lvalue e m a t m1 loc ofs ->
-      eval_expr e m (Expr (Eaddrof a) ty)
-                t m1 (Vptr loc ofs)
-  | eval_Esizeof: forall e m ty' ty,
-      eval_expr e m (Expr (Esizeof ty') ty) 
-               E0 m (Vint (Int.repr (sizeof ty')))
-  | eval_Eunop:  forall e m op a ty t m1 v1 v,
-      eval_expr e m a t m1 v1 ->
+(** [eval_expr ge e m a v] defines the evaluation of expression [a]
+  in r-value position.  [v] is the value of the expression.
+  [e] is the current environment and [m] is the current memory state. *)
+
+Inductive eval_expr: expr -> val -> Prop :=
+  | eval_Econst_int:   forall i ty,
+      eval_expr (Expr (Econst_int i) ty) (Vint i)
+  | eval_Econst_float:   forall f ty,
+      eval_expr (Expr (Econst_float f) ty) (Vfloat f)
+  | eval_Elvalue: forall a ty loc ofs v,
+      eval_lvalue (Expr a ty) loc ofs ->
+      load_value_of_type ty m loc ofs = Some v ->
+      eval_expr (Expr a ty) v
+  | eval_Eaddrof: forall a ty loc ofs,
+      eval_lvalue a loc ofs ->
+      eval_expr (Expr (Eaddrof a) ty) (Vptr loc ofs)
+  | eval_Esizeof: forall ty' ty,
+      eval_expr (Expr (Esizeof ty') ty) (Vint (Int.repr (sizeof ty')))
+  | eval_Eunop:  forall op a ty v1 v,
+      eval_expr a v1 ->
       sem_unary_operation op v1 (typeof a) = Some v ->
-      eval_expr e m (Expr (Eunop op a) ty) 
-                t m1 v
-  | eval_Ebinop: forall e m op a1 a2 ty t1 m1 v1 t2 m2 v2 v,
-      eval_expr e m a1 t1 m1 v1 ->
-      eval_expr e m1 a2 t2 m2 v2 ->
-      sem_binary_operation op v1 (typeof a1) v2 (typeof a2) m2 = Some v ->
-      eval_expr e m (Expr (Ebinop op a1 a2) ty)
-                (t1 ** t2) m2 v
-  | eval_Eorbool_1: forall e m a1 a2 t m1 v1 ty,
-      eval_expr e m a1 t m1 v1 ->
+      eval_expr (Expr (Eunop op a) ty) v
+  | eval_Ebinop: forall op a1 a2 ty v1 v2 v,
+      eval_expr a1 v1 ->
+      eval_expr a2 v2 ->
+      sem_binary_operation op v1 (typeof a1) v2 (typeof a2) m = Some v ->
+      eval_expr (Expr (Ebinop op a1 a2) ty) v
+  | eval_Eorbool_1: forall a1 a2 ty v1,
+      eval_expr a1 v1 ->
       is_true v1 (typeof a1) ->
-      eval_expr e m (Expr (Eorbool a1 a2) ty)
-                  t m1 Vtrue
-  | eval_Eorbool_2: forall e m a1 a2 ty t1 m1 v1 t2 m2 v2 v,
-      eval_expr e m a1 t1 m1 v1 ->
+      eval_expr (Expr (Eorbool a1 a2) ty) Vtrue
+  | eval_Eorbool_2: forall a1 a2 ty v1 v2 v,
+      eval_expr a1 v1 ->
       is_false v1 (typeof a1) -> 
-      eval_expr e m1 a2 t2 m2 v2 ->
+      eval_expr a2 v2 ->
       bool_of_val v2 (typeof a2) v ->
-      eval_expr e m (Expr (Eorbool a1 a2) ty)
-                (t1 ** t2) m2 v
-  | eval_Eandbool_1: forall e m a1 a2 t m1 v1 ty,
-      eval_expr e m a1 t m1 v1 ->
+      eval_expr (Expr (Eorbool a1 a2) ty) v
+  | eval_Eandbool_1: forall a1 a2 ty v1,
+      eval_expr a1 v1 ->
       is_false v1 (typeof a1) ->
-      eval_expr e m (Expr (Eandbool a1 a2) ty)
-                  t m1 Vfalse
-  | eval_Eandbool_2: forall e m a1 a2 ty t1 m1 v1 t2 m2 v2 v,
-      eval_expr e m a1 t1 m1 v1 ->
+      eval_expr (Expr (Eandbool a1 a2) ty) Vfalse
+  | eval_Eandbool_2: forall a1 a2 ty v1 v2 v,
+      eval_expr a1 v1 ->
       is_true v1 (typeof a1) -> 
-      eval_expr e m1 a2 t2 m2 v2 ->
+      eval_expr a2 v2 ->
       bool_of_val v2 (typeof a2) v ->
-      eval_expr e m (Expr (Eandbool a1 a2) ty)
-                (t1 ** t2) m2 v
-  | eval_Ecast:   forall e m a ty t m1 v1 v,
-      eval_expr e m a t m1 v1 ->
+      eval_expr (Expr (Eandbool a1 a2) ty) v
+  | eval_Ecast:   forall a ty v1 v,
+      eval_expr a v1 ->
       cast v1 (typeof a) ty v ->
-      eval_expr e m (Expr (Ecast ty a) ty)
-                t m1 v
-  | eval_Ecall: forall e m a bl ty m3 vres t1 m1 vf t2 m2 vargs f t3,
-      eval_expr e m a t1 m1 vf ->
-      eval_exprlist e m1 bl t2 m2 vargs ->
-      Genv.find_funct ge vf = Some f ->
-      type_of_fundef f = typeof a ->
-      eval_funcall m2 f vargs t3 m3 vres ->
-      eval_expr e m (Expr (Ecall a bl) ty)
-                (t1 ** t2 ** t3) m3 vres 
-
-(** [eval_lvalue ge e m1 a t m2  b ofs] defines the evaluation of
-  expression [a] in r-value position.  The result of the evaluation
-  is the block reference [b] and the byte offset [ofs] of the
-  memory location where the value of [a] resides.
-  The other parameters are as in [eval_expr]. *)
-
-with eval_lvalue: env -> mem -> expr -> trace -> mem -> block -> int -> Prop :=
-  | eval_Evar_local:   forall e m id l ty,
+      eval_expr (Expr (Ecast ty a) ty) v
+
+(** [eval_lvalue ge e m a b ofs] defines the evaluation of expression [a]
+  in l-value position.  The result is the memory location [b, ofs]
+  that contains the value of the expression [a]. *)
+
+with eval_lvalue: expr -> block -> int -> Prop :=
+  | eval_Evar_local:   forall id l ty,
       e!id = Some l ->
-      eval_lvalue e m (Expr (Evar id) ty) 
-                 E0 m l Int.zero
-  | eval_Evar_global: forall e m id l ty,
+      eval_lvalue (Expr (Evar id) ty) l Int.zero
+  | eval_Evar_global: forall id l ty,
       e!id = None ->
       Genv.find_symbol ge id = Some l ->
-      eval_lvalue e m (Expr (Evar id) ty)
-                 E0 m l Int.zero
-  | eval_Ederef: forall e m m1 a t ofs ty l,
-      eval_expr e m a t m1 (Vptr l ofs) ->
-      eval_lvalue e m (Expr (Ederef a) ty)
-                  t m1 l ofs
-  | eval_Eindex: forall e m a1 t1 m1 v1 a2 t2 m2 v2 l ofs ty,
-      eval_expr e m a1 t1 m1 v1 ->
-      eval_expr e m1 a2 t2 m2 v2 ->
+      eval_lvalue (Expr (Evar id) ty) l Int.zero
+  | eval_Ederef: forall a ty l ofs,
+      eval_expr a (Vptr l ofs) ->
+      eval_lvalue (Expr (Ederef a) ty) l ofs
+  | eval_Eindex: forall a1 a2 ty v1 v2 l ofs,
+      eval_expr a1 v1 ->
+      eval_expr a2 v2 ->
       sem_add v1 (typeof a1) v2 (typeof a2) = Some (Vptr l ofs) ->
-      eval_lvalue e m (Expr (Eindex a1 a2) ty)
-                  (t1 ** t2) m2 l ofs
- | eval_Efield_struct:   forall e m a t m1 l ofs id fList i ty delta,
-      eval_lvalue e m a t m1 l ofs ->
+      eval_lvalue (Expr (Eindex a1 a2) ty) l ofs
+ | eval_Efield_struct:   forall a i ty l ofs id fList delta,
+      eval_lvalue a l ofs ->
       typeof a = Tstruct id fList ->
       field_offset i fList = OK delta ->
-      eval_lvalue e m (Expr (Efield a i) ty)
-                  t m1 l (Int.add ofs (Int.repr delta))
- | eval_Efield_union:   forall e m a t m1 l ofs id fList i ty,
-      eval_lvalue e m a t m1 l ofs ->
+      eval_lvalue (Expr (Efield a i) ty) l (Int.add ofs (Int.repr delta))
+ | eval_Efield_union:   forall a i ty l ofs id fList,
+      eval_lvalue a l ofs ->
       typeof a = Tunion id fList ->
-      eval_lvalue e m (Expr (Efield a i) ty) 
-                  t m1 l ofs
+      eval_lvalue (Expr (Efield a i) ty) l ofs.
+
+Scheme eval_expr_ind2 := Minimality for eval_expr Sort Prop
+  with eval_lvalue_ind2 := Minimality for eval_lvalue Sort Prop.
 
-(** [eval_exprlist ge e m1 al t m2 vl] evaluates a list of r-value
+(** [eval_exprlist ge e m al vl] evaluates a list of r-value
   expressions [al] to their values [vl]. *)
 
-with eval_exprlist: env -> mem -> exprlist -> trace -> mem -> list val -> Prop :=
-  | eval_Enil:   forall e m,
-      eval_exprlist e m Enil E0 m nil
-  | eval_Econs:   forall e m a bl t1 m1 v t2 m2 vl,
-      eval_expr e m a t1 m1 v ->
-      eval_exprlist e m1 bl t2 m2 vl ->
-      eval_exprlist e m (Econs a bl)
-                    (t1 ** t2) m2 (v :: vl)
+Inductive eval_exprlist: list expr -> list val -> Prop :=
+  | eval_Enil:
+      eval_exprlist nil nil
+  | eval_Econs:   forall a bl v vl,
+      eval_expr a v ->
+      eval_exprlist bl vl ->
+      eval_exprlist (a :: bl) (v :: vl).
+
+End EXPR.
 
 (** [exec_stmt ge e m1 s t m2 out] describes the execution of 
   the statement [s].  [out] is the outcome for this execution.
@@ -639,20 +619,34 @@ with eval_exprlist: env -> mem -> exprlist -> trace -> mem -> list val -> Prop :
   [t] is the trace of input/output events performed during this
   evaluation. *)
 
-with exec_stmt: env -> mem -> statement -> trace -> mem -> outcome -> Prop :=
+Inductive exec_stmt: env -> mem -> statement -> trace -> mem -> outcome -> Prop :=
   | exec_Sskip:   forall e m,
       exec_stmt e m Sskip
                E0 m Out_normal
-  | exec_Sexpr: forall e m a t m1 v,
-      eval_expr e m a t m1 v ->
-      exec_stmt e m (Sexpr a)
-                t m1 Out_normal 
-  | exec_Sassign:   forall e m a1 a2 t1 m1 loc ofs t2 m2 v2 m3,
-      eval_lvalue e m a1 t1 m1 loc ofs ->
-      eval_expr e m1 a2 t2 m2 v2 ->
-      store_value_of_type (typeof a1) m2 loc ofs v2 = Some m3 ->
+  | exec_Sassign:   forall e m a1 a2 loc ofs v2 m',
+      eval_lvalue e m a1 loc ofs ->
+      eval_expr e m a2 v2 ->
+      store_value_of_type (typeof a1) m loc ofs v2 = Some m' ->
       exec_stmt e m (Sassign a1 a2)
-                (t1 ** t2) m3 Out_normal
+               E0 m' Out_normal
+  | exec_Scall_none:   forall e m a al vf vargs f t m' vres,
+      eval_expr e m a vf ->
+      eval_exprlist e m al vargs ->
+      Genv.find_funct ge vf = Some f ->
+      type_of_fundef f = typeof a ->
+      eval_funcall m f vargs t m' vres ->
+      exec_stmt e m (Scall None a al)
+                t m' Out_normal
+  | exec_Scall_some:   forall e m lhs a al loc ofs vf vargs f t m' vres m'',
+      eval_lvalue e m lhs loc ofs ->
+      eval_expr e m a vf ->
+      eval_exprlist e m al vargs ->
+      Genv.find_funct ge vf = Some f ->
+      type_of_fundef f = typeof a ->
+      eval_funcall m f vargs t m' vres ->
+      store_value_of_type (typeof lhs) m' loc ofs vres = Some m'' ->
+      exec_stmt e m (Scall (Some lhs) a al)
+                t m'' Out_normal
   | exec_Sseq_1:   forall e m s1 s2 t1 m1 t2 m2 out,
       exec_stmt e m s1 t1 m1 Out_normal ->
       exec_stmt e m1 s2 t2 m2 out ->
@@ -663,102 +657,103 @@ with exec_stmt: env -> mem -> statement -> trace -> mem -> outcome -> Prop :=
       out <> Out_normal ->
       exec_stmt e m (Ssequence s1 s2)
                 t1 m1 out
-  | exec_Sifthenelse_true: forall e m a s1 s2 t1 m1 v1 t2 m2 out,
-      eval_expr e m a t1 m1 v1 ->
+  | exec_Sifthenelse_true: forall e m a s1 s2 v1 t m' out,
+      eval_expr e m a v1 ->
       is_true v1 (typeof a) ->
-      exec_stmt e m1 s1 t2 m2 out ->
+      exec_stmt e m s1 t m' out ->
       exec_stmt e m (Sifthenelse a s1 s2)
-                (t1 ** t2) m2 out
-  | exec_Sifthenelse_false: forall e m a s1 s2 t1 m1 v1 t2 m2 out,
-      eval_expr e m a t1 m1 v1 ->
+                t m' out
+  | exec_Sifthenelse_false: forall e m a s1 s2 v1 t m' out,
+      eval_expr e m a v1 ->
       is_false v1 (typeof a) ->
-      exec_stmt e m1 s2 t2 m2 out ->
+      exec_stmt e m s2 t m' out ->
       exec_stmt e m (Sifthenelse a s1 s2)
-                (t1 ** t2) m2 out
+                t m' out
   | exec_Sreturn_none:   forall e m,
       exec_stmt e m (Sreturn None)
                E0 m (Out_return None)
-  | exec_Sreturn_some: forall e m a t m1 v,
-      eval_expr e m a t m1 v ->
+  | exec_Sreturn_some: forall e m a v,
+      eval_expr e m a v ->
       exec_stmt e m (Sreturn (Some a))
-                t m1 (Out_return (Some v))
+               E0 m (Out_return (Some v))
   | exec_Sbreak:   forall e m,
       exec_stmt e m Sbreak
                E0 m Out_break
   | exec_Scontinue:   forall e m,
       exec_stmt e m Scontinue
                E0 m Out_continue
-  | exec_Swhile_false: forall e m s a t v m1,
-      eval_expr e m a t m1 v ->
+  | exec_Swhile_false: forall e m a s v,
+      eval_expr e m a v ->
       is_false v (typeof a) ->
       exec_stmt e m (Swhile a s)
-                t m1 Out_normal
-  | exec_Swhile_stop: forall e m a t1 m1 v s m2 t2 out2 out,
-      eval_expr e m a t1 m1 v ->
+               E0 m Out_normal
+  | exec_Swhile_stop: forall e m a v s t m' out' out,
+      eval_expr e m a v ->
       is_true v (typeof a) ->
-      exec_stmt e m1 s t2 m2 out2 ->
-      out_break_or_return out2 out ->
+      exec_stmt e m s t m' out' ->
+      out_break_or_return out' out ->
       exec_stmt e m (Swhile a s)
-                (t1 ** t2) m2 out
-  | exec_Swhile_loop: forall e m a t1 m1 v s out2 out t2 m2 t3 m3,
-      eval_expr e m a t1 m1 v ->
+                t m' out
+  | exec_Swhile_loop: forall e m a s v t1 m1 out1 t2 m2 out,
+      eval_expr e m a v ->
       is_true v (typeof a) ->
-      exec_stmt e m1 s t2 m2 out2 ->
-      out_normal_or_continue out2 ->
-      exec_stmt e m2 (Swhile a s) t3 m3 out ->
-      exec_stmt e m (Swhile a s)
-                (t1 ** t2 ** t3) m3 out
-  | exec_Sdowhile_false: forall e m s a t1 m1 out1 v t2 m2,
       exec_stmt e m s t1 m1 out1 ->
       out_normal_or_continue out1 ->
-      eval_expr e m1 a t2 m2 v ->
+      exec_stmt e m1 (Swhile a s) t2 m2 out ->
+      exec_stmt e m (Swhile a s)
+                (t1 ** t2) m2 out
+  | exec_Sdowhile_false: forall e m s a t m1 out1 v,
+      exec_stmt e m s t m1 out1 ->
+      out_normal_or_continue out1 ->
+      eval_expr e m1 a v ->
       is_false v (typeof a) ->
       exec_stmt e m (Sdowhile a s)
-                (t1 ** t2) m2 Out_normal
+                t m1 Out_normal
   | exec_Sdowhile_stop: forall e m s a t m1 out1 out,
       exec_stmt e m s t m1 out1 ->
       out_break_or_return out1 out ->
       exec_stmt e m (Sdowhile a s)
                 t m1 out
-  | exec_Sdowhile_loop: forall e m s a m1 m2 m3 t1 t2 t3 out out1 v,
+  | exec_Sdowhile_loop: forall e m s a m1 m2 t1 t2 out out1 v,
       exec_stmt e m s t1 m1 out1 ->
       out_normal_or_continue out1 ->
-      eval_expr e m1 a t2 m2 v ->
+      eval_expr e m1 a v ->
       is_true v (typeof a) ->
-      exec_stmt e m2 (Sdowhile a s) t3 m3 out ->
+      exec_stmt e m1 (Sdowhile a s) t2 m2 out ->
       exec_stmt e m (Sdowhile a s) 
-                (t1 ** t2 ** t3) m3 out
+                (t1 ** t2) m2 out
   | exec_Sfor_start: forall e m s a1 a2 a3 out m1 m2 t1 t2,
+      a1 <> Sskip ->
       exec_stmt e m a1 t1 m1 Out_normal ->
       exec_stmt e m1 (Sfor Sskip a2 a3 s) t2 m2 out ->
       exec_stmt e m (Sfor a1 a2 a3 s) 
                 (t1 ** t2) m2 out
-  | exec_Sfor_false: forall e m s a2 a3 t v m1,
-      eval_expr e m a2 t m1 v ->
+  | exec_Sfor_false: forall e m s a2 a3 v,
+      eval_expr e m a2 v ->
       is_false v (typeof a2) ->
       exec_stmt e m (Sfor Sskip a2 a3 s)
-                t m1 Out_normal
-  | exec_Sfor_stop: forall e m s a2 a3 v m1 m2 t1 t2 out2 out,
-      eval_expr e m a2 t1 m1 v ->
+               E0 m Out_normal
+  | exec_Sfor_stop: forall e m s a2 a3 v m1 t out1 out,
+      eval_expr e m a2 v ->
       is_true v (typeof a2) ->
-      exec_stmt e m1 s t2 m2 out2 ->
-      out_break_or_return out2 out ->
+      exec_stmt e m s t m1 out1 ->
+      out_break_or_return out1 out ->
       exec_stmt e m (Sfor Sskip a2 a3 s)
-                (t1 ** t2) m2 out
-  | exec_Sfor_loop: forall e m s a2 a3 v m1 m2 m3 m4 t1 t2 t3 t4 out2 out,
-      eval_expr e m a2 t1 m1 v ->
+                t m1 out
+  | exec_Sfor_loop: forall e m s a2 a3 v m1 m2 m3 t1 t2 t3 out1 out,
+      eval_expr e m a2 v ->
       is_true v (typeof a2) ->
-      exec_stmt e m1 s t2 m2 out2 ->
-      out_normal_or_continue out2 ->
-      exec_stmt e m2 a3 t3 m3 Out_normal ->
-      exec_stmt e m3 (Sfor Sskip a2 a3 s) t4 m4 out ->
+      exec_stmt e m s t1 m1 out1 ->
+      out_normal_or_continue out1 ->
+      exec_stmt e m1 a3 t2 m2 Out_normal ->
+      exec_stmt e m2 (Sfor Sskip a2 a3 s) t3 m3 out ->
       exec_stmt e m (Sfor Sskip a2 a3 s)
-                (t1 ** t2 ** t3 ** t4) m4 out
-  | exec_Sswitch:   forall e m a t1 m1 n sl t2 m2 out,
-      eval_expr e m a t1 m1 (Vint n) ->
-      exec_lblstmts e m1 (select_switch n sl) t2 m2 out ->
+                (t1 ** t2 ** t3) m3 out
+  | exec_Sswitch:   forall e m a t n sl m1 out,
+      eval_expr e m a (Vint n) ->
+      exec_lblstmts e m (select_switch n sl) t m1 out ->
       exec_stmt e m (Sswitch a sl)
-                (t1 ** t2) m2 (outcome_switch out)
+                t m1 (outcome_switch out)
 
 (** [exec_lblstmts ge e m1 ls t m2 out] is a variant of [exec_stmt]
   that executes in sequence all statements in the list of labeled
@@ -791,25 +786,137 @@ with eval_funcall: mem -> fundef -> list val -> trace -> mem -> val -> Prop :=
       event_match (external_function id targs tres) vargs t vres ->
       eval_funcall m (External id targs tres) vargs t m vres.
 
-Scheme eval_expr_ind6 := Minimality for eval_expr Sort Prop
-  with eval_lvalue_ind6 := Minimality for eval_lvalue Sort Prop
-  with eval_exprlist_ind6 := Minimality for eval_exprlist Sort Prop
-  with exec_stmt_ind6 := Minimality for exec_stmt Sort Prop
-  with exec_lblstmts_ind6 := Minimality for exec_lblstmts Sort Prop
-  with eval_funcall_ind6 := Minimality for eval_funcall Sort Prop.
+Scheme exec_stmt_ind3 := Minimality for exec_stmt Sort Prop
+  with exec_lblstmts_ind3 := Minimality for exec_lblstmts Sort Prop
+  with eval_funcall_ind3 := Minimality for eval_funcall Sort Prop.
+
+(** Coinductive semantics for divergence.
+  [execinf_stmt ge e m s t] holds if the execution of statement [s]
+  diverges, i.e. loops infinitely.  [t] is the possibly infinite
+  trace of observable events performed during the execution. *)
+
+CoInductive execinf_stmt: env -> mem -> statement -> traceinf -> Prop :=
+  | execinf_Scall:   forall e m lhs a al vf vargs f t,
+      eval_expr e m a vf ->
+      eval_exprlist e m al vargs ->
+      Genv.find_funct ge vf = Some f ->
+      type_of_fundef f = typeof a ->
+      evalinf_funcall m f vargs t ->
+      execinf_stmt e m (Scall lhs a al) t
+  | execinf_Sseq_1:   forall e m s1 s2 t,
+      execinf_stmt e m s1 t ->
+      execinf_stmt e m (Ssequence s1 s2) t
+  | execinf_Sseq_2:   forall e m s1 s2 t1 m1 t2,
+      exec_stmt e m s1 t1 m1 Out_normal ->
+      execinf_stmt e m1 s2 t2 ->
+      execinf_stmt e m (Ssequence s1 s2) (t1 *** t2)
+  | execinf_Sifthenelse_true: forall e m a s1 s2 v1 t,
+      eval_expr e m a v1 ->
+      is_true v1 (typeof a) ->
+      execinf_stmt e m s1 t ->
+      execinf_stmt e m (Sifthenelse a s1 s2) t
+  | execinf_Sifthenelse_false: forall e m a s1 s2 v1 t,
+      eval_expr e m a v1 ->
+      is_false v1 (typeof a) ->
+      execinf_stmt e m s2 t ->
+      execinf_stmt e m (Sifthenelse a s1 s2) t
+  | execinf_Swhile_body: forall e m a v s t,
+      eval_expr e m a v ->
+      is_true v (typeof a) ->
+      execinf_stmt e m s t ->
+      execinf_stmt e m (Swhile a s) t
+  | execinf_Swhile_loop: forall e m a s v t1 m1 out1 t2,
+      eval_expr e m a v ->
+      is_true v (typeof a) ->
+      exec_stmt e m s t1 m1 out1 ->
+      out_normal_or_continue out1 ->
+      execinf_stmt e m1 (Swhile a s) t2 ->
+      execinf_stmt e m (Swhile a s) (t1 *** t2)
+  | execinf_Sdowhile_body: forall e m s a t,
+      execinf_stmt e m s t ->
+      execinf_stmt e m (Sdowhile a s) t
+  | execinf_Sdowhile_loop: forall e m s a m1 t1 t2 out1 v,
+      exec_stmt e m s t1 m1 out1 ->
+      out_normal_or_continue out1 ->
+      eval_expr e m1 a v ->
+      is_true v (typeof a) ->
+      execinf_stmt e m1 (Sdowhile a s) t2 ->
+      execinf_stmt e m (Sdowhile a s) (t1 *** t2)
+  | execinf_Sfor_start_1: forall e m s a1 a2 a3 t,
+      execinf_stmt e m a1 t ->
+      execinf_stmt e m (Sfor a1 a2 a3 s) t
+  | execinf_Sfor_start_2: forall e m s a1 a2 a3 m1 t1 t2,
+      a1 <> Sskip ->
+      exec_stmt e m a1 t1 m1 Out_normal ->
+      execinf_stmt e m1 (Sfor Sskip a2 a3 s) t2 ->
+      execinf_stmt e m (Sfor a1 a2 a3 s) (t1 *** t2)
+  | execinf_Sfor_body: forall e m s a2 a3 v t,
+      eval_expr e m a2 v ->
+      is_true v (typeof a2) ->
+      execinf_stmt e m s t ->
+      execinf_stmt e m (Sfor Sskip a2 a3 s) t
+  | execinf_Sfor_next: forall e m s a2 a3 v m1 t1 t2 out1,
+      eval_expr e m a2 v ->
+      is_true v (typeof a2) ->
+      exec_stmt e m s t1 m1 out1 ->
+      out_normal_or_continue out1 ->
+      execinf_stmt e m1 a3 t2 ->
+      execinf_stmt e m (Sfor Sskip a2 a3 s) (t1 *** t2)
+  | execinf_Sfor_loop: forall e m s a2 a3 v m1 m2 t1 t2 t3 out1,
+      eval_expr e m a2 v ->
+      is_true v (typeof a2) ->
+      exec_stmt e m s t1 m1 out1 ->
+      out_normal_or_continue out1 ->
+      exec_stmt e m1 a3 t2 m2 Out_normal ->
+      execinf_stmt e m2 (Sfor Sskip a2 a3 s) t3 ->
+      execinf_stmt e m (Sfor Sskip a2 a3 s) (t1 *** t2 *** t3)
+  | execinf_Sswitch:   forall e m a t n sl,
+      eval_expr e m a (Vint n) ->
+      execinf_lblstmts e m (select_switch n sl) t ->
+      execinf_stmt e m (Sswitch a sl) t
+
+with execinf_lblstmts: env -> mem -> labeled_statements -> traceinf -> Prop :=
+  | execinf_LSdefault: forall e m s t,
+     execinf_stmt e m s t ->
+     execinf_lblstmts e m (LSdefault s) t
+  | execinf_LScase_body: forall e m n s ls t,
+     execinf_stmt e m s t ->
+     execinf_lblstmts e m (LScase n s ls) t
+  | execinf_LScase_fallthrough: forall e m n s ls t1 m1 t2,
+     exec_stmt e m s t1 m1 Out_normal ->
+     execinf_lblstmts e m1 ls t2 ->
+     execinf_lblstmts e m (LScase n s ls) (t1 *** t2)
+
+(** [evalinf_funcall ge m fd args t] holds if the invocation of function
+    [fd] on arguments [args] diverges, with observable trace [t]. *)
+
+with evalinf_funcall: mem -> fundef -> list val -> traceinf -> Prop :=
+  | evalinf_funcall_internal: forall m f vargs t e m1 lb m2,
+      alloc_variables empty_env m (f.(fn_params) ++ f.(fn_vars)) e m1 lb ->
+      bind_parameters e m1 f.(fn_params) vargs m2 ->
+      execinf_stmt e m2 f.(fn_body) t ->
+      evalinf_funcall m (Internal f) vargs t.
 
 End RELSEM.
 
-(** Execution of a whole program: [exec_program p t r]
-  holds if the application of [p]'s main function to no arguments
-  in the initial memory state for [p] performs the input/output
-  operations described in the trace [t], and eventually returns value [r].
-*)
-
-Definition exec_program (p: program) (t: trace) (r: val) : Prop :=
-  let ge := Genv.globalenv p in 
-  let m0 := Genv.init_mem p in
-  exists b, exists f, exists m1,
-  Genv.find_symbol ge p.(prog_main) = Some b /\
-  Genv.find_funct_ptr ge b = Some f /\
-  eval_funcall ge m0 f nil t m1 r.
+(** Execution of a whole program.  [exec_program p beh] holds
+  if the application of [p]'s main function to no arguments
+  in the initial memory state for [p] executes without errors and produces
+  the observable behaviour [beh]. *)
+
+Inductive exec_program (p: program): program_behavior -> Prop :=
+  | program_terminates: forall b f m1 t r,
+      let ge := Genv.globalenv p in 
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      eval_funcall ge m0 f nil t m1 (Vint r) ->
+      exec_program p (Terminates t r)
+  | program_diverges: forall b f t,
+      let ge := Genv.globalenv p in 
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      evalinf_funcall ge m0 f nil t ->
+      exec_program p (Diverges t).
+
diff --git a/cfrontend/Csharpminor.v b/cfrontend/Csharpminor.v
index 7d805c386..7afe27f2f 100644
--- a/cfrontend/Csharpminor.v
+++ b/cfrontend/Csharpminor.v
@@ -10,6 +10,7 @@ Require Import Mem.
 Require Import Events.
 Require Import Globalenvs.
 Require Cminor.
+Require Import Smallstep.
 
 (** Abstract syntax *)
 
@@ -17,10 +18,7 @@ Require Cminor.
   statements, functions and programs.  Expressions include
   reading global or local variables, reading store locations,
   arithmetic operations, function calls, and conditional expressions
-  (similar to [e1 ? e2 : e3] in C).  The [Elet] and [Eletvar] constructs
-  enable sharing the computations of subexpressions.  De Bruijn notation
-  is used: [Eletvar n] refers to the value bound by then [n+1]-th enclosing
-  [Elet] construct.
+  (similar to [e1 ? e2 : e3] in C). 
 
   Unlike in Cminor (the next intermediate language of the back-end),
   Csharpminor local variables reside in memory, and their addresses can
@@ -41,27 +39,19 @@ Inductive expr : Set :=
   | Eunop : unary_operation -> expr -> expr  (**r unary operation *)
   | Ebinop : binary_operation -> expr -> expr -> expr (**r binary operation *)
   | Eload : memory_chunk -> expr -> expr (**r memory read *)
-  | Ecall : signature -> expr -> exprlist -> expr (**r function call *)
-  | Econdition : expr -> expr -> expr -> expr (**r conditional expression *)
-  | Elet : expr -> expr -> expr         (**r let binding  *)
-  | Eletvar : nat -> expr               (**r reference to a let-bound variable *)
-  | Ealloc : expr -> expr               (**r memory allocation *)
-
-with exprlist : Set :=
-  | Enil: exprlist
-  | Econs: expr -> exprlist -> exprlist.
+  | Econdition : expr -> expr -> expr -> expr. (**r conditional expression *)
 
 (** Statements include expression evaluation, variable assignment,
-  memory stores, an if/then/else conditional,
+  memory stores, function calls, an if/then/else conditional,
   infinite loops, blocks and early block exits, and early function returns.
   [Sexit n] terminates prematurely the execution of the [n+1] enclosing
   [Sblock] statements. *)
 
 Inductive stmt : Set :=
   | Sskip: stmt
-  | Sexpr: expr -> stmt
   | Sassign : ident -> expr -> stmt
   | Sstore : memory_chunk -> expr -> expr -> stmt
+  | Scall : option ident -> signature -> expr -> list expr -> stmt
   | Sseq: stmt -> stmt -> stmt
   | Sifthenelse: expr -> stmt -> stmt -> stmt
   | Sloop: stmt -> stmt
@@ -136,19 +126,17 @@ Fixpoint switch_target (n: int) (dfl: nat) (cases: list (int * nat))
   | (n1, lbl1) :: rem => if Int.eq n n1 then lbl1 else switch_target n dfl rem
   end.
 
-(** Four kinds of evaluation environments are involved:
+(** Three kinds of evaluation environments are involved:
 - [genv]: global environments, define symbols and functions;
 - [gvarenv]: map global variables to variable informations (type [var_kind]);
 - [env]: local environments, map local variables 
-    to memory blocks and variable informations;
-- [lenv]: let environments, map de Bruijn indices to values.
+    to memory blocks and variable informations.
 *)
 
 Definition genv := Genv.t fundef.
 Definition gvarenv := PTree.t var_kind.
 Definition env := PTree.t (block * var_kind).
 Definition empty_env : env := PTree.empty (block * var_kind).
-Definition letenv := list val.
 
 Definition sizeof (lv: var_kind) : Z :=
   match lv with
@@ -252,111 +240,80 @@ Inductive eval_var_ref: env -> ident -> block -> memory_chunk -> Prop :=
       PTree.get id (global_var_env prg) = Some (Vscalar chunk) ->
       eval_var_ref e id b chunk.
 
-(** Evaluation of an expression: [eval_expr prg le e m a t m' v] states
-  that expression [a], in initial memory state [m], evaluates to value
-  [v].  [m'] is the final memory state, respectively, reflecting
-  memory stores possibly performed by [a].  [t] is the trace of input/output
-  events generated during the evaluation.
-  [e] and [le] are the local environment and let environment respectively. *)
-
-Inductive eval_expr:
-         letenv -> env ->
-         mem -> expr -> trace -> mem -> val -> Prop :=
-  | eval_Evar:
-      forall le e m id b chunk v,
+(** Evaluation of an expression: [eval_expr prg e m a v] states
+  that expression [a], in initial memory state [m] and local
+  environment [e], evaluates to value [v]. *)
+
+Section EVAL_EXPR.
+
+Variable e: env.
+Variable m: mem.
+
+Inductive eval_expr: expr -> val -> Prop :=
+  | eval_Evar: forall id b chunk v,
       eval_var_ref e id b chunk ->
       Mem.load chunk m b 0 = Some v ->
-      eval_expr le e m (Evar id) E0 m v
-  | eval_Eaddrof:
-      forall le e m id b,
+      eval_expr (Evar id) v
+  | eval_Eaddrof: forall id b,
       eval_var_addr e id b ->
-      eval_expr le e m (Eaddrof id) E0 m (Vptr b Int.zero)
-  | eval_Econst:
-      forall le e m cst v,
+      eval_expr (Eaddrof id) (Vptr b Int.zero)
+  | eval_Econst: forall cst v,
       eval_constant cst = Some v ->
-      eval_expr le e m (Econst cst) E0 m v
-  | eval_Eunop:
-      forall le e m op a t m1 v1 v,
-      eval_expr le e m a t m1 v1 ->
+      eval_expr (Econst cst) v
+  | eval_Eunop: forall op a1 v1 v,
+      eval_expr a1 v1 ->
       eval_unop op v1 = Some v ->
-      eval_expr le e m (Eunop op a) t m1 v
-  | eval_Ebinop:
-      forall le e m op a1 a2 t1 m1 v1 t2 m2 v2 t v,
-      eval_expr le e m a1 t1 m1 v1 ->
-      eval_expr le e m1 a2 t2 m2 v2 ->
-      eval_binop op v1 v2 m2 = Some v ->
-      t = t1 ** t2 ->
-      eval_expr le e m (Ebinop op a1 a2) t m2 v
-  | eval_Eload:
-      forall le e m chunk a t m1 v1 v,
-      eval_expr le e m a t m1 v1 ->
-      Mem.loadv chunk m1 v1 = Some v ->
-      eval_expr le e m (Eload chunk a) t m1 v
-  | eval_Ecall:
-      forall le e m sig a bl t1 m1 t2 m2 t3 m3 vf vargs vres f t,
-      eval_expr le e m a t1 m1 vf ->
-      eval_exprlist le e m1 bl t2 m2 vargs ->
-      Genv.find_funct ge vf = Some f ->
-      funsig f = sig ->
-      eval_funcall m2 f vargs t3 m3 vres ->
-      t = t1 ** t2 ** t3 ->
-      eval_expr le e m (Ecall sig a bl) t m3 vres
-  | eval_Econdition_true:
-      forall le e m a b c t1 m1 v1 t2 m2 v2 t,
-      eval_expr le e m a t1 m1 v1 ->
-      Val.is_true v1 ->
-      eval_expr le e m1 b t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr le e m (Econdition a b c) t m2 v2
-  | eval_Econdition_false:
-      forall le e m a b c t1 m1 v1 t2 m2 v2 t,
-      eval_expr le e m a t1 m1 v1 ->
-      Val.is_false v1 ->
-      eval_expr le e m1 c t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr le e m (Econdition a b c) t m2 v2
-  | eval_Elet:
-      forall le e m a b t1 m1 v1 t2 m2 v2 t,
-      eval_expr le e m a t1 m1 v1 ->
-      eval_expr (v1::le) e m1 b t2 m2 v2 ->
-      t = t1 ** t2 ->
-      eval_expr le e m (Elet a b) t m2 v2
-  | eval_Eletvar:
-      forall le e m n v,
-      nth_error le n = Some v ->
-      eval_expr le e m (Eletvar n) E0 m v
-  | eval_Ealloc:
-      forall le e m a t m1 n m2 b,
-      eval_expr le e m a t m1 (Vint n) ->
-      Mem.alloc m1 0 (Int.signed n) = (m2, b) ->
-      eval_expr le e m (Ealloc a) t m2 (Vptr b Int.zero)
+      eval_expr (Eunop op a1) v
+  | eval_Ebinop: forall op a1 a2 v1 v2 v,
+      eval_expr a1 v1 ->
+      eval_expr a2 v2 ->
+      eval_binop op v1 v2 m = Some v ->
+      eval_expr (Ebinop op a1 a2) v
+  | eval_Eload: forall chunk a v1 v,
+      eval_expr a v1 ->
+      Mem.loadv chunk m v1 = Some v ->
+      eval_expr (Eload chunk a) v
+  | eval_Econdition: forall a b c v1 vb1 v2,
+      eval_expr a v1 ->
+      Val.bool_of_val v1 vb1 ->
+      eval_expr (if vb1 then b else c) v2 ->
+      eval_expr (Econdition a b c) v2.
 
 (** Evaluation of a list of expressions:
-  [eval_exprlist prg le al m a t m' vl]
-  states that the list [al] of expressions evaluate 
-  to the list [vl] of values.
-  The other parameters are as in [eval_expr].
-*)
+  [eval_exprlist prg e m al vl] states that the list [al] of
+  expressions evaluate to the list [vl] of values.  The other
+  parameters are as in [eval_expr]. *)
 
-with eval_exprlist:
-         letenv -> env ->
-         mem -> exprlist -> trace ->
-         mem -> list val -> Prop :=
+Inductive eval_exprlist: list expr -> list val -> Prop :=
   | eval_Enil:
-      forall le e m,
-      eval_exprlist le e m Enil E0 m nil
-  | eval_Econs:
-      forall le e m a bl t1 m1 v t2 m2 vl t,
-      eval_expr le e m a t1 m1 v ->
-      eval_exprlist le e m1 bl t2 m2 vl ->
-      t = t1 ** t2 ->
-      eval_exprlist le e m (Econs a bl) t m2 (v :: vl)
+      eval_exprlist nil nil
+  | eval_Econs: forall a1 al v1 vl,
+      eval_expr a1 v1 -> eval_exprlist al vl ->
+      eval_exprlist (a1 :: al) (v1 :: vl).
+
+End EVAL_EXPR.
+
+(** Execution of an assignment to a variable. *)
+
+Inductive exec_assign: env -> mem -> ident -> val -> mem -> Prop :=
+  exec_assign_intro: forall e m id v b chunk m',
+    eval_var_ref e id b chunk ->
+    Mem.store chunk m b 0 v = Some m' ->
+    exec_assign e m id v m'.
+
+Inductive exec_opt_assign: env -> mem -> option ident -> val -> mem -> Prop :=
+  | exec_assign_none: forall e m v,
+      exec_opt_assign e m None v m
+  | exec_assign_some: forall e m id v m',
+      exec_assign e m id v m' ->
+      exec_opt_assign e m (Some id) v m'.
 
 (** Evaluation of a function invocation: [eval_funcall prg m f args t m' res]
   means that the function [f], applied to the arguments [args] in
   memory state [m], returns the value [res] in modified memory state [m'].
-*)
-with eval_funcall:
+  [t] is the trace of observable events performed during the call. *)
+
+Inductive eval_funcall:
         mem -> fundef -> list val -> trace ->
         mem -> val -> Prop :=
   | eval_funcall_internal:
@@ -374,6 +331,8 @@ with eval_funcall:
 
 (** Execution of a statement: [exec_stmt prg e m s t m' out]
   means that statement [s] executes with outcome [out].
+  [m] is the initial memory state, [m'] the final memory state,
+  and [t] the trace of events performed.
   The other parameters are as in [eval_expr]. *)
 
 with exec_stmt:
@@ -383,23 +342,26 @@ with exec_stmt:
   | exec_Sskip:
       forall e m,
       exec_stmt e m Sskip E0 m Out_normal
-  | exec_Sexpr:
-      forall e m a t m1 v,
-      eval_expr nil e m a t m1 v ->
-      exec_stmt e m (Sexpr a) t m1 Out_normal
-  | eval_Sassign:
-      forall e m id a t m1 b chunk v m2,
-      eval_expr nil e m a t m1 v ->
-      eval_var_ref e id b chunk ->
-      Mem.store chunk m1 b 0 v = Some m2 ->
-      exec_stmt e m (Sassign id a) t m2 Out_normal
-  | eval_Sstore:
-      forall e m chunk a b t1 m1 v1 t2 m2 v2 t3 m3,
-      eval_expr nil e m a t1 m1 v1 ->
-      eval_expr nil e m1 b t2 m2 v2 ->
-      Mem.storev chunk m2 v1 v2 = Some m3 ->
-      t3 = t1 ** t2 ->
-      exec_stmt e m (Sstore chunk a b) t3 m3 Out_normal
+  | exec_Sassign:
+      forall e m id a v m',
+      eval_expr e m a v ->
+      exec_assign e m id v m' ->
+      exec_stmt e m (Sassign id a) E0 m' Out_normal
+  | exec_Sstore:
+      forall e m chunk a b v1 v2 m',
+      eval_expr e m a v1 ->
+      eval_expr e m b v2 ->
+      Mem.storev chunk m v1 v2 = Some m' ->
+      exec_stmt e m (Sstore chunk a b) E0 m' Out_normal
+  | exec_Scall:
+      forall e m optid sig a bl vf vargs f t m1 vres m2,
+      eval_expr e m a vf ->
+      eval_exprlist e m bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      eval_funcall m f vargs t m1 vres ->
+      exec_opt_assign e m1 optid vres m2 ->
+      exec_stmt e m (Scall optid sig a bl) t m2 Out_normal
   | exec_Sseq_continue:
       forall e m s1 s2 t1 t2 m1 m2 t out,
       exec_stmt e m s1 t1 m1 Out_normal ->
@@ -411,20 +373,12 @@ with exec_stmt:
       exec_stmt e m s1 t1 m1 out ->
       out <> Out_normal ->
       exec_stmt e m (Sseq s1 s2) t1 m1 out
-  | exec_Sifthenelse_true:
-      forall e m a sl1 sl2 t1 m1 v1 t2 m2 out t,
-      eval_expr nil e m a t1 m1 v1 ->
-      Val.is_true v1 ->
-      exec_stmt e m1 sl1 t2 m2 out ->
-      t = t1 ** t2 ->
-      exec_stmt e m (Sifthenelse a sl1 sl2) t m2 out
-  | exec_Sifthenelse_false:
-      forall e m a sl1 sl2 t1 m1 v1 t2 m2 out t,
-      eval_expr nil e m a t1 m1 v1 ->
-      Val.is_false v1 ->
-      exec_stmt e m1 sl2 t2 m2 out ->
-      t = t1 ** t2 ->
-      exec_stmt e m (Sifthenelse a sl1 sl2) t m2 out
+  | exec_Sifthenelse:
+      forall e m a sl1 sl2 v vb t m' out,
+      eval_expr e m a v ->
+      Val.bool_of_val v vb ->
+      exec_stmt e m (if vb then sl1 else sl2) t m' out ->
+      exec_stmt e m (Sifthenelse a sl1 sl2) t m' out
   | exec_Sloop_loop:
       forall e m sl t1 m1 t2 m2 out t,
       exec_stmt e m sl t1 m1 Out_normal ->
@@ -444,35 +398,166 @@ with exec_stmt:
       forall e m n,
       exec_stmt e m (Sexit n) E0 m (Out_exit n)
   | exec_Sswitch:
-      forall e m a cases default t1 m1 n,
-      eval_expr nil e m a t1 m1 (Vint n) ->
+      forall e m a cases default n,
+      eval_expr e m a (Vint n) ->
       exec_stmt e m (Sswitch a cases default)
-               t1 m1 (Out_exit (switch_target n default cases))
+               E0 m (Out_exit (switch_target n default cases))
   | exec_Sreturn_none:
       forall e m,
       exec_stmt e m (Sreturn None) E0 m (Out_return None)
   | exec_Sreturn_some:
-      forall e m a t1 m1 v,
-      eval_expr nil e m a t1 m1 v ->
-      exec_stmt e m (Sreturn (Some a)) t1 m1 (Out_return (Some v)).
-
-Scheme eval_expr_ind4 := Minimality for eval_expr Sort Prop
-  with eval_exprlist_ind4 := Minimality for eval_exprlist Sort Prop
-  with eval_funcall_ind4 := Minimality for eval_funcall Sort Prop
-  with exec_stmt_ind4 := Minimality for exec_stmt Sort Prop.
+      forall e m a v,
+      eval_expr e m a v ->
+      exec_stmt e m (Sreturn (Some a)) E0 m (Out_return (Some v)).
+
+Scheme eval_funcall_ind2 := Minimality for eval_funcall Sort Prop
+  with exec_stmt_ind2 := Minimality for exec_stmt Sort Prop.
+
+(** Coinductive semantics for divergence. *)
+
+Inductive block_seq_context: (stmt -> stmt) -> Prop :=
+  | block_seq_context_base_1:
+      block_seq_context (fun x => Sblock x)
+  | block_seq_context_base_2: forall s,
+      block_seq_context (fun x => Sseq x s)
+  | block_seq_context_ctx_1: forall ctx,
+      block_seq_context ctx ->
+      block_seq_context (fun x => Sblock (ctx x))
+  | block_seq_context_ctx_2: forall s ctx,
+      block_seq_context ctx ->
+      block_seq_context (fun x => Sseq (ctx x) s).
+
+CoInductive evalinf_funcall:
+        mem -> fundef -> list val -> traceinf -> Prop :=
+  | evalinf_funcall_internal:
+      forall m f vargs e m1 lb m2 t,
+      list_norepet (fn_params_names f ++ fn_vars_names f) ->
+      alloc_variables empty_env m (fn_variables f) e m1 lb ->
+      bind_parameters e m1 f.(fn_params) vargs m2 ->
+      execinf_stmt e m2 f.(fn_body) t ->
+      evalinf_funcall m (Internal f) vargs t
+
+with execinf_stmt:
+         env -> mem -> stmt -> traceinf -> Prop :=
+  | execinf_Scall:
+      forall e m optid sig a bl vf vargs f t,
+      eval_expr e m a vf ->
+      eval_exprlist e m bl vargs ->
+      Genv.find_funct ge vf = Some f ->
+      funsig f = sig ->
+      evalinf_funcall m f vargs t ->
+      execinf_stmt e m (Scall optid sig a bl) t
+  | execinf_Sseq_1:
+      forall e m s1 s2 t,
+      execinf_stmt e m s1 t ->
+      execinf_stmt e m (Sseq s1 s2) t
+  | execinf_Sseq_2:
+      forall e m s1 s2 t1 t2 m1 t,
+      exec_stmt e m s1 t1 m1 Out_normal ->
+      execinf_stmt e m1 s2 t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt e m (Sseq s1 s2) t
+  | execinf_Sifthenelse:
+      forall e m a sl1 sl2 v vb t,
+      eval_expr e m a v ->
+      Val.bool_of_val v vb ->
+      execinf_stmt e m (if vb then sl1 else sl2) t ->
+      execinf_stmt e m (Sifthenelse a sl1 sl2) t
+  | execinf_Sloop_body:
+      forall e m sl t,
+      execinf_stmt e m sl t ->
+      execinf_stmt e m (Sloop sl) t
+  | execinf_Sloop_loop:
+      forall e m sl t1 m1 t2 t,
+      exec_stmt e m sl t1 m1 Out_normal ->
+      execinf_stmt e m1 (Sloop sl) t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt e m (Sloop sl) t
+  | execinf_Sblock:
+      forall e m sl t,
+      execinf_stmt e m sl t ->
+      execinf_stmt e m (Sblock sl) t
+  | execinf_stutter:
+      forall n e m s t,
+      execinf_stmt_N n e m s t ->
+      execinf_stmt e m s t
+  | execinf_Sloop_block:
+      forall e m sl t1 m1 t2 t,
+      exec_stmt e m sl t1 m1 Out_normal ->
+      execinf_stmt e m1 (Sblock (Sloop sl)) t2 ->
+      t = t1 *** t2 ->
+      execinf_stmt e m (Sloop sl) t
+
+with execinf_stmt_N:
+         nat -> env -> mem -> stmt -> traceinf -> Prop :=
+  | execinf_context: forall n e m s t ctx,
+      execinf_stmt e m s t -> block_seq_context ctx ->
+      execinf_stmt_N n e m (ctx s) t
+  | execinf_sleep: forall n e m s t,
+      execinf_stmt_N n e m s t ->
+      execinf_stmt_N (S n) e m s t.
+
+Lemma execinf_stmt_N_inv:
+  forall n e m s t,
+  execinf_stmt_N n e m s t ->
+  match s with
+  | Sblock s1 => execinf_stmt e m s1 t
+  | Sseq s1 s2 => execinf_stmt e m s1 t
+  | _ => False
+  end.
+Proof.
+  assert (BASECASE: forall e m s t ctx,
+          execinf_stmt e m s t -> block_seq_context ctx ->
+          match ctx s with
+          | Sblock s1 => execinf_stmt e m s1 t
+          | Sseq s1 s2 => execinf_stmt e m s1 t
+          | _ => False
+          end).
+  intros. inv H0.
+  auto.
+  auto.
+  apply execinf_stutter with O. apply execinf_context; eauto. 
+  apply execinf_stutter with O. apply execinf_context; eauto.
+
+  induction n; intros; inv H.
+  apply BASECASE; auto.
+  apply BASECASE; auto.
+  eapply IHn; eauto.
+Qed.
+
+Lemma execinf_Sblock_inv:
+  forall e m s t,
+  execinf_stmt e m (Sblock s) t ->
+  execinf_stmt e m s t.
+Proof.
+  intros. inv H.
+  auto.
+  exact (execinf_stmt_N_inv _ _ _ _ _ H0). 
+Qed.
 
 End RELSEM.
 
-(** Execution of a whole program: [exec_program p t r]
+(** Execution of a whole program: [exec_program p beh]
   holds if the application of [p]'s main function to no arguments
-  in the initial memory state for [p] performs the events described
-  in trace [t] and eventually returns value [r]. *)
-
-Definition exec_program (p: program) (t: trace) (r: val) : Prop :=
-  let ge := Genv.globalenv p in
-  let m0 := Genv.init_mem p in
-  exists b, exists f, exists m,
-  Genv.find_symbol ge p.(prog_main) = Some b /\
-  Genv.find_funct_ptr ge b = Some f /\
-  funsig f = mksignature nil (Some Tint) /\
-  eval_funcall p m0 f nil t m r.
+  in the initial memory state for [p] has [beh] as observable
+  behavior. *)
+
+Inductive exec_program (p: program): program_behavior -> Prop :=
+  | program_terminates:
+      forall b f t m r,
+      let ge := Genv.globalenv p in
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      funsig f = mksignature nil (Some Tint) ->
+      eval_funcall p m0 f nil t m (Vint r) ->
+      exec_program p (Terminates t r)
+  | program_diverges:
+      forall b f t,
+      let ge := Genv.globalenv p in
+      let m0 := Genv.init_mem p in
+      Genv.find_symbol ge p.(prog_main) = Some b ->
+      Genv.find_funct_ptr ge b = Some f ->
+      funsig f = mksignature nil (Some Tint) ->
+      evalinf_funcall p m0 f nil t ->
+      exec_program p (Diverges t).
diff --git a/cfrontend/Cshmgen.v b/cfrontend/Cshmgen.v
index 937ea78a8..6ec3757b3 100644
--- a/cfrontend/Cshmgen.v
+++ b/cfrontend/Cshmgen.v
@@ -253,6 +253,14 @@ Definition make_store (addr: expr) (ty: type) (rhs: expr) :=
 
 (** * Reading and writing variables *)
 
+(** Determine if a C expression is a variable *)
+
+Definition is_variable (e: Csyntax.expr) : option ident :=
+  match e with
+  | Expr (Csyntax.Evar id) _ => Some id
+  | _ => None
+  end.
+
 (** [var_get id ty] returns Csharpminor code that evaluates to the
    value of C variable [id] with type [ty].  Note that 
    C variables of array or function type evaluate to the address
@@ -277,7 +285,19 @@ Definition var_set (id: ident) (ty: type) (rhs: expr) :=
   | _ => Error (MSG "Cshmgen.var_set " :: CTX id :: nil)
   end.
 
-(** * Translation of operators *)
+(** Auxiliary for translating call statements *)
+
+Definition transl_lhs_call (opta: option Csyntax.expr) : res (option ident) :=
+  match opta with
+  | None => OK None
+  | Some a =>
+      match is_variable a with
+      | None => Error (msg "LHS of function call is not a variable")
+      | Some id => OK (Some id)
+      end
+  end.
+
+(** ** Translation of operators *)
 
 Definition transl_unop (op: Csyntax.unary_operation) (a: expr) (ta: type) : res expr :=
   match op with
@@ -350,15 +370,6 @@ Fixpoint transl_expr (a: Csyntax.expr) {struct a} : res expr :=
       do tc <- transl_expr c;
       do ts <- make_add tb (typeof b) tc (typeof c);
       make_load ts ty
-  | Expr (Csyntax.Ecall b cl) _ =>
-      match (classify_fun (typeof b)) with
-      | fun_case_f args res =>
-          do tb <- transl_expr b;
-          do tcl <- transl_exprlist cl;
-          OK(Ecall (signature_of_type args res) tb tcl)
-      | _ =>
-          Error(msg "Cshmgen.transl_expr(call)")
-      end 
   | Expr (Csyntax.Eandbool b c) _ =>
       do tb <- transl_expr b;
       do tc <- transl_expr c;
@@ -413,31 +424,23 @@ with transl_lvalue (a: Csyntax.expr) {struct a} : res expr :=
       end
   | _ => 
       Error(msg "Cshmgen.transl_lvalue")
-  end
+  end.
 
 (** [transl_exprlist al] returns a list of Csharpminor expressions
    that compute the values of the list [al] of Csyntax expressions.
    Used for function applications. *)
 
-with transl_exprlist (al: Csyntax.exprlist): res exprlist :=
+Fixpoint transl_exprlist (al: list Csyntax.expr): res (list expr) :=
   match al with
-  | Csyntax.Enil => OK Enil
-  | Csyntax.Econs a1 a2 =>
+  | nil => OK nil
+  | a1 :: a2 =>
       do ta1 <- transl_expr a1;
       do ta2 <- transl_exprlist a2;
-      OK (Econs ta1 ta2)
+      OK (ta1 :: ta2)
   end.
 
 (** * Translation of statements *)
 
-(** Determine if a C expression is a variable *)
-
-Definition is_variable (e: Csyntax.expr) : option ident :=
-  match e with
-  | Expr (Csyntax.Evar id) _ => Some id
-  | _ => None
-  end.
-
 (** [exit_if_false e] return the statement that tests the boolean
    value of the Clight expression [e].  If [e] evaluates to false,
    an [exit 0] is performed.  If [e] evaluates to true, the generated
@@ -512,15 +515,18 @@ Fixpoint switch_table (sl: labeled_statements) (k: nat) {struct sl} : list (int
   | LScase ni _ rem => (ni, k) :: switch_table rem (k+1)
   end.
 
+Definition is_Sskip:
+  forall (s: Csyntax.statement), {s = Csyntax.Sskip} + {s <> Csyntax.Sskip}.
+Proof.
+  destruct s; ((left; reflexivity) || (right; congruence)).
+Qed.
+
 Fixpoint transl_statement (nbrk ncnt: nat) (s: Csyntax.statement) {struct s} : res stmt :=
   match s with
   | Csyntax.Sskip =>
       OK Sskip
-  | Csyntax.Sexpr e =>
-      do te <- transl_expr e;
-      OK (Sexpr te)
   | Csyntax.Sassign b c =>
-      match (is_variable b) with
+      match is_variable b with
       | Some id =>
           do tc <- transl_expr c;
           var_set id (typeof b) tc
@@ -529,6 +535,15 @@ Fixpoint transl_statement (nbrk ncnt: nat) (s: Csyntax.statement) {struct s} : r
           do tc <- transl_expr c;
           make_store tb (typeof b) tc
       end 
+  | Csyntax.Scall opta b cl =>
+      match classify_fun (typeof b) with
+      | fun_case_f args res =>
+          do optid <- transl_lhs_call opta;
+          do tb <- transl_expr b;
+          do tcl <- transl_exprlist cl;
+          OK(Scall optid (signature_of_type args res) tb tcl)
+      | _ => Error(msg "Cshmgen.transl_stmt(call)")
+      end
   | Csyntax.Ssequence s1 s2 =>
       do ts1 <- transl_statement nbrk ncnt s1;
       do ts2 <- transl_statement nbrk ncnt s2;
@@ -547,11 +562,17 @@ Fixpoint transl_statement (nbrk ncnt: nat) (s: Csyntax.statement) {struct s} : r
       do ts1 <- transl_statement 1%nat 0%nat s1;
       OK (Sblock (Sloop (Sseq (Sblock ts1) te)))
   | Csyntax.Sfor e1 e2 e3 s1 =>
-      do te1 <- transl_statement nbrk ncnt e1;
-      do te2 <- exit_if_false e2;
-      do te3 <- transl_statement nbrk ncnt e3;
-      do ts1 <- transl_statement 1%nat 0%nat s1;
-      OK (Sseq te1 (Sblock (Sloop (Sseq te2 (Sseq (Sblock ts1) te3)))))
+      if is_Sskip e1 then
+       (do te2 <- exit_if_false e2;
+        do te3 <- transl_statement nbrk ncnt e3;
+        do ts1 <- transl_statement 1%nat 0%nat s1;
+        OK (Sblock (Sloop (Sseq te2 (Sseq (Sblock ts1) te3)))))
+      else
+       (do te1 <- transl_statement nbrk ncnt e1;
+        do te2 <- exit_if_false e2;
+        do te3 <- transl_statement nbrk ncnt e3;
+        do ts1 <- transl_statement 1%nat 0%nat s1;
+        OK (Sseq te1 (Sblock (Sloop (Sseq te2 (Sseq (Sblock ts1) te3))))))
   | Csyntax.Sbreak =>
       OK (Sexit nbrk)
   | Csyntax.Scontinue =>
@@ -579,7 +600,7 @@ with transl_lblstmts (nbrk ncnt: nat) (sl: labeled_statements) (body: stmt)
       transl_lblstmts (pred nbrk) (pred ncnt) rem (Sblock (Sseq body ts))
   end.
 
-(** * Translation of functions and programs *)
+(*** Translation of functions *)
 
 Definition prefix_var_name (id: ident) : errmsg :=
   MSG "In local variable " :: CTX id :: MSG ":\n" :: nil.
@@ -603,6 +624,8 @@ Definition transl_fundef (f: Csyntax.fundef) : res fundef :=
       OK(AST.External (external_function id args res))
   end.
 
+(** ** Translation of programs *)
+
 Definition transl_globvar (ty: type) := var_kind_of_type ty.
 
 Definition transl_program (p: Csyntax.program) : res program :=
diff --git a/cfrontend/Cshmgenproof1.v b/cfrontend/Cshmgenproof1.v
index b86b09bfb..9930ef808 100644
--- a/cfrontend/Cshmgenproof1.v
+++ b/cfrontend/Cshmgenproof1.v
@@ -175,8 +175,8 @@ Proof.
 Qed.
 
 Lemma transl_expr_lvalue:
-  forall ge e m1 a ty t m2 loc ofs ta,
-  Csem.eval_lvalue ge e m1 (Expr a ty) t m2 loc ofs ->
+  forall ge e m a ty loc ofs ta,
+  Csem.eval_lvalue ge e m (Expr a ty) loc ofs ->
   transl_expr (Expr a ty) = OK ta ->
   (exists id, a = Csyntax.Evar id /\ var_get id ty = OK ta) \/
   (exists tb, transl_lvalue (Expr a ty) = OK tb /\
@@ -188,28 +188,44 @@ Proof.
   monadInv H0. right. exists x; split; auto. 
   simpl. monadInv H0. right. exists x1; split; auto. 
   simpl. rewrite EQ; rewrite EQ1. simpl. auto.
-  rewrite H6 in H0. monadInv H0. right.  
+  rewrite H4 in H0. monadInv H0. right.  
   exists (Ebinop Oadd x (make_intconst (Int.repr x0))). split; auto.
-  simpl. rewrite H6. rewrite EQ. rewrite EQ1. auto.
-  rewrite H10 in H0. monadInv H0. right.
+  simpl. rewrite H4. rewrite EQ. rewrite EQ1. auto.
+  rewrite H6 in H0. monadInv H0. right.
   exists x; split; auto. 
-  simpl. rewrite H10. auto.
+  simpl. rewrite H6. auto.
 Qed.
 
 Lemma transl_stmt_Sfor_start:
   forall nbrk ncnt s1 e2 s3 s4 ts,
   transl_statement nbrk ncnt (Sfor s1 e2 s3 s4) = OK ts ->
+  s1 <> Csyntax.Sskip ->
   exists ts1, exists ts2,
     ts = Sseq ts1 ts2
   /\ transl_statement nbrk ncnt s1 = OK ts1
-  /\ transl_statement nbrk ncnt (Sfor Csyntax.Sskip e2 s3 s4) = OK (Sseq Sskip ts2).
+  /\ transl_statement nbrk ncnt (Sfor Csyntax.Sskip e2 s3 s4) = OK ts2.
 Proof.
-  intros. monadInv H. econstructor; econstructor.
+  intros. simpl in H. destruct (is_Sskip s1). contradiction.
+  monadInv H. econstructor; econstructor.
   split. reflexivity. split. auto. simpl.
+  destruct (is_Sskip Csyntax.Sskip). 2: tauto. 
   rewrite EQ1; rewrite EQ0; rewrite EQ2; auto.
 Qed.
 
-(** Properties related to [switch] constructs. *)
+Open Local Scope error_monad_scope.
+
+Lemma transl_stmt_Sfor_not_start:
+  forall nbrk ncnt e2 e3 s1,
+  transl_statement nbrk ncnt (Sfor Csyntax.Sskip e2 e3 s1) =
+    (do te2 <- exit_if_false e2;
+     do te3 <- transl_statement nbrk ncnt e3;
+     do ts1 <- transl_statement 1%nat 0%nat s1;
+     OK (Sblock (Sloop (Sseq te2 (Sseq (Sblock ts1) te3))))).
+Proof.
+  intros. simpl. destruct (is_Sskip Csyntax.Sskip). auto. congruence.
+Qed.
+
+(** Properties related to switch constructs *)
 
 Fixpoint lblstmts_length (sl: labeled_statements) : nat :=
   match sl with
@@ -233,4 +249,33 @@ Proof.
   induction sl; intro; simpl. auto. decEq; auto. 
 Qed.
 
+Lemma block_seq_context_compose:
+  forall ctx2 ctx1,
+  block_seq_context ctx1 ->
+  block_seq_context ctx2 ->
+  block_seq_context (fun x => ctx1 (ctx2 x)).
+Proof.
+  induction 1; intros; constructor; auto.
+Qed.
+
+Lemma transl_lblstmts_context:
+  forall sl nbrk ncnt body s,
+  transl_lblstmts nbrk ncnt sl body = OK s ->
+  exists ctx, block_seq_context ctx /\ s = ctx body.
+Proof.
+  induction sl; simpl; intros.
+  monadInv H. exists (fun y => Sblock (Sseq y x)); split.
+  apply block_seq_context_ctx_1. apply block_seq_context_base_2.
+  auto.
+  monadInv H. exploit IHsl; eauto. intros [ctx [A B]].
+  exists (fun y => ctx (Sblock (Sseq y x))); split.
+  apply block_seq_context_compose with
+    (ctx1 := ctx)
+    (ctx2 := fun y => Sblock (Sseq y x)).
+  auto. apply block_seq_context_ctx_1. apply block_seq_context_base_2. 
+  auto.
+Qed.
+
+
+
 
diff --git a/cfrontend/Cshmgenproof2.v b/cfrontend/Cshmgenproof2.v
index a75621cae..aa4e391a9 100644
--- a/cfrontend/Cshmgenproof2.v
+++ b/cfrontend/Cshmgenproof2.v
@@ -60,17 +60,17 @@ Qed.
 (** * Correctness of Csharpminor construction functions *)
 
 Lemma make_intconst_correct:
-  forall n le e m1,
-  Csharpminor.eval_expr tprog le e m1 (make_intconst n) E0 m1 (Vint n).
+  forall n e m,
+  eval_expr tprog e m (make_intconst n) (Vint n).
 Proof.
-  intros. unfold make_intconst. econstructor. constructor.  
+  intros. unfold make_intconst. econstructor. reflexivity. 
 Qed.
 
 Lemma make_floatconst_correct:
-  forall n le e m1,
-  Csharpminor.eval_expr tprog le e m1 (make_floatconst n) E0 m1 (Vfloat n).
+  forall n e m,
+  eval_expr tprog e m (make_floatconst n) (Vfloat n).
 Proof.
-  intros. unfold make_floatconst. econstructor. constructor.  
+  intros. unfold make_floatconst. econstructor. reflexivity. 
 Qed.
 
 Hint Resolve make_intconst_correct make_floatconst_correct
@@ -88,18 +88,18 @@ Proof.
 Qed.
 
 Lemma make_boolean_correct_true:
- forall le e m1 a t m2 v ty,
-  Csharpminor.eval_expr tprog le e m1 a t m2 v ->
+ forall e m a v ty,
+  eval_expr tprog e m a v ->
   is_true v ty ->
   exists vb,
-    Csharpminor.eval_expr tprog le e m1 (make_boolean a ty) t m2 vb
+    eval_expr tprog e m (make_boolean a ty) vb
     /\ Val.is_true vb.
 Proof.
   intros until ty; intros EXEC VTRUE.
   destruct ty; simpl;
   try (exists v; intuition; inversion VTRUE; simpl; auto; fail).
   exists Vtrue; split.
-  econstructor; eauto with cshm. 
+  eapply eval_Ebinop; eauto with cshm. 
   inversion VTRUE; simpl. 
   replace (Float.cmp Cne f0 Float.zero) with (negb (Float.cmp Ceq f0 Float.zero)).
   rewrite Float.eq_zero_false. reflexivity. auto.
@@ -108,18 +108,18 @@ Proof.
 Qed.
 
 Lemma make_boolean_correct_false:
- forall le e m1 a t m2 v ty,
-  Csharpminor.eval_expr tprog le e m1 a t m2 v ->
+ forall e m a v ty,
+  eval_expr tprog e m a v ->
   is_false v ty ->
   exists vb,
-    Csharpminor.eval_expr tprog le e m1 (make_boolean a ty) t m2 vb
+    eval_expr tprog e m (make_boolean a ty) vb
     /\ Val.is_false vb.
 Proof.
   intros until ty; intros EXEC VFALSE.
   destruct ty; simpl;
   try (exists v; intuition; inversion VFALSE; simpl; auto; fail).
   exists Vfalse; split.
-  econstructor; eauto with cshm. 
+  eapply eval_Ebinop; eauto with cshm. 
   inversion VFALSE; simpl. 
   replace (Float.cmp Cne Float.zero Float.zero) with (negb (Float.cmp Ceq Float.zero Float.zero)).
   rewrite Float.eq_zero_true. reflexivity. 
@@ -128,38 +128,38 @@ Proof.
 Qed.
 
 Lemma make_neg_correct:
-  forall a tya c ta va v le e m1 m2,
+  forall a tya c va v e m,
   sem_neg va tya = Some v ->
   make_neg a tya = OK c ->  
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m1 c ta m2 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m c v.
 Proof.
-  intros until m2; intro SEM. unfold make_neg. 
+  intros until m; intro SEM. unfold make_neg. 
   functional inversion SEM; intros.
-  inversion H4. econstructor; eauto with cshm.
+  inversion H4. eapply eval_Eunop; eauto with cshm.
   inversion H4. eauto with cshm.
 Qed.
 
 Lemma make_notbool_correct:
-  forall a tya c ta va v le e m1 m2,
+  forall a tya c va v e m,
   sem_notbool va tya = Some v ->
   make_notbool a tya = c ->  
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m1 c ta m2 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m c v.
 Proof.
-  intros until m2; intro SEM. unfold make_notbool. 
+  intros until m; intro SEM. unfold make_notbool. 
   functional inversion SEM; intros; inversion H4; simpl;
   eauto with cshm.
 Qed.
 
 Lemma make_notint_correct:
-  forall a tya c ta va v le e m1 m2,
+  forall a tya c va v e m,
   sem_notint va = Some v ->
   make_notint a tya = c ->  
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m1 c ta m2 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m c v.
 Proof.
-  intros until m2; intro SEM. unfold make_notint. 
+  intros until m; intro SEM. unfold make_notint. 
   functional inversion SEM; intros. 
   inversion H2; eauto with cshm.
 Qed.
@@ -167,143 +167,141 @@ Qed.
 Definition binary_constructor_correct
     (make: expr -> type -> expr -> type -> res expr)
     (sem: val -> type -> val -> type -> option val): Prop :=
-  forall a tya b tyb c ta va tb vb v le e m1 m2 m3,
+  forall a tya b tyb c va vb v e m,
   sem va tya vb tyb = Some v ->
   make a tya b tyb = OK c ->  
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m2 b tb m3 vb ->
-  eval_expr tprog le e m1 c (ta ** tb) m3 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m b vb ->
+  eval_expr tprog e m c v.
 
 Definition binary_constructor_correct'
     (make: expr -> type -> expr -> type -> res expr)
     (sem: val -> val -> option val): Prop :=
-  forall a tya b tyb c ta va tb vb v le e m1 m2 m3,
+  forall a tya b tyb c va vb v e m,
   sem va vb = Some v ->
   make a tya b tyb = OK c ->  
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m2 b tb m3 vb ->
-  eval_expr tprog le e m1 c (ta ** tb) m3 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m b vb ->
+  eval_expr tprog e m c v.
 
 Lemma make_add_correct: binary_constructor_correct make_add sem_add.
 Proof.
-  red; intros until m3. intro SEM. unfold make_add. 
+  red; intros until m. intro SEM. unfold make_add. 
   functional inversion SEM; rewrite H0; intros.
   inversion H7. eauto with cshm. 
   inversion H7. eauto with cshm.
   inversion H7. 
-  econstructor. eauto. 
-  econstructor. eauto with cshm. eauto.
+  eapply eval_Ebinop. eauto. 
+  eapply eval_Ebinop. eauto with cshm. eauto.
   simpl. reflexivity. reflexivity. 
-  simpl. reflexivity. traceEq.
 Qed.
 
 Lemma make_sub_correct: binary_constructor_correct make_sub sem_sub.
 Proof.
-  red; intros until m3. intro SEM. unfold make_sub. 
+  red; intros until m. intro SEM. unfold make_sub. 
   functional inversion SEM; rewrite H0; intros;
   inversion H7; eauto with cshm. 
-  econstructor. eauto. 
-  econstructor. eauto with cshm. eauto.
+  eapply eval_Ebinop. eauto. 
+  eapply eval_Ebinop. eauto with cshm. eauto.
   simpl. reflexivity. reflexivity. 
-  simpl. reflexivity. traceEq.
-  inversion H9. econstructor. 
-  econstructor; eauto. 
+  inversion H9. eapply eval_Ebinop. 
+  eapply eval_Ebinop; eauto. 
   simpl. unfold eq_block; rewrite H3. reflexivity.
-  eauto with cshm. simpl. rewrite H8. reflexivity. traceEq.
+  eauto with cshm. simpl. rewrite H8. reflexivity.
 Qed.
 
 Lemma make_mul_correct: binary_constructor_correct make_mul sem_mul.
 Proof.
-  red; intros until m3. intro SEM. unfold make_mul. 
+  red; intros until m. intro SEM. unfold make_mul. 
   functional inversion SEM; rewrite H0; intros;
   inversion H7; eauto with cshm. 
 Qed.
 
 Lemma make_div_correct: binary_constructor_correct make_div sem_div.
 Proof.
-  red; intros until m3. intro SEM. unfold make_div. 
+  red; intros until m. intro SEM. unfold make_div. 
   functional inversion SEM; rewrite H0; intros.
-  inversion H8. econstructor; eauto with cshm. 
+  inversion H8. eapply eval_Ebinop; eauto with cshm. 
   simpl. rewrite H7; auto.
-  inversion H8. econstructor; eauto with cshm. 
+  inversion H8. eapply eval_Ebinop; eauto with cshm. 
   simpl. rewrite H7; auto.
   inversion H7; eauto with cshm. 
 Qed.
 
 Lemma make_mod_correct: binary_constructor_correct make_mod sem_mod.
-  red; intros until m3. intro SEM. unfold make_mod. 
+  red; intros until m. intro SEM. unfold make_mod. 
   functional inversion SEM; rewrite H0; intros.
-  inversion H8. econstructor; eauto with cshm. 
+  inversion H8. eapply eval_Ebinop; eauto with cshm. 
   simpl. rewrite H7; auto.
-  inversion H8. econstructor; eauto with cshm. 
+  inversion H8. eapply eval_Ebinop; eauto with cshm. 
   simpl. rewrite H7; auto.
 Qed.
 
 Lemma make_and_correct: binary_constructor_correct' make_and sem_and.
 Proof.
-  red; intros until m3. intro SEM. unfold make_and. 
+  red; intros until m. intro SEM. unfold make_and. 
   functional inversion SEM. intros. inversion H4. 
   eauto with cshm. 
 Qed.
 
 Lemma make_or_correct: binary_constructor_correct' make_or sem_or.
 Proof.
-  red; intros until m3. intro SEM. unfold make_or. 
+  red; intros until m. intro SEM. unfold make_or. 
   functional inversion SEM. intros. inversion H4. 
   eauto with cshm. 
 Qed.
 
 Lemma make_xor_correct: binary_constructor_correct' make_xor sem_xor.
 Proof.
-  red; intros until m3. intro SEM. unfold make_xor. 
+  red; intros until m. intro SEM. unfold make_xor. 
   functional inversion SEM. intros. inversion H4. 
   eauto with cshm. 
 Qed.
 
 Lemma make_shl_correct: binary_constructor_correct' make_shl sem_shl.
 Proof.
-  red; intros until m3. intro SEM. unfold make_shl. 
+  red; intros until m. intro SEM. unfold make_shl. 
   functional inversion SEM. intros. inversion H5. 
-  econstructor; eauto with cshm. 
+  eapply eval_Ebinop; eauto with cshm. 
   simpl. rewrite H4. auto.
 Qed.
 
 Lemma make_shr_correct: binary_constructor_correct make_shr sem_shr.
 Proof.
-  red; intros until m3. intro SEM. unfold make_shr. 
+  red; intros until m. intro SEM. unfold make_shr. 
   functional inversion SEM; intros; rewrite H0 in H8; inversion H8.
-  econstructor; eauto with cshm.
+  eapply eval_Ebinop; eauto with cshm.
   simpl; rewrite H7; auto.
-  econstructor; eauto with cshm.
+  eapply eval_Ebinop; eauto with cshm.
   simpl; rewrite H7; auto.
 Qed.
 
 Lemma make_cmp_correct:
-  forall cmp a tya b tyb c ta va tb vb v le e m1 m2 m3,
-  sem_cmp cmp va tya vb tyb m3 = Some v ->
+  forall cmp a tya b tyb c va vb v e m,
+  sem_cmp cmp va tya vb tyb m = Some v ->
   make_cmp cmp a tya b tyb = OK c ->  
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m2 b tb m3 vb ->
-  eval_expr tprog le e m1 c (ta ** tb) m3 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m b vb ->
+  eval_expr tprog e m c v.
 Proof.
-  intros until m3. intro SEM. unfold make_cmp.
+  intros until m. intro SEM. unfold make_cmp.
   functional inversion SEM; rewrite H0; intros. 
   inversion H8. eauto with cshm.
   inversion H8. eauto with cshm.
   inversion H8. eauto with cshm.
-  inversion H9. econstructor; eauto with cshm.
+  inversion H9. eapply eval_Ebinop; eauto with cshm.
   simpl. functional inversion H; subst; unfold eval_compare_null;
   rewrite H8; auto.
-  inversion H10. econstructor; eauto with cshm.
+  inversion H10. eapply eval_Ebinop; eauto with cshm.
   simpl. rewrite H3. unfold eq_block; rewrite H9. auto.
 Qed.
 
 Lemma transl_unop_correct:
-  forall op a tya c ta va v le e m1 m2, 
+  forall op a tya c va v e m, 
   transl_unop op a tya = OK c ->
   sem_unary_operation op va tya = Some v ->
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m1 c ta m2 v.
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m c v.
 Proof.
   intros. destruct op; simpl in *.
   eapply make_notbool_correct; eauto. congruence.
@@ -312,12 +310,12 @@ Proof.
 Qed.
 
 Lemma transl_binop_correct:
-forall op a tya b tyb c ta va tb vb v le e m1 m2 m3,
+  forall op a tya b tyb c va vb v e m,
   transl_binop op a tya b tyb = OK c ->  
-  sem_binary_operation op va tya vb tyb m3 = Some v ->
-  eval_expr tprog le e m1 a ta m2 va ->
-  eval_expr tprog le e m2 b tb m3 vb ->
-  eval_expr tprog le e m1 c (ta ** tb) m3 v.
+  sem_binary_operation op va tya vb tyb m = Some v ->
+  eval_expr tprog e m a va ->
+  eval_expr tprog e m b vb ->
+  eval_expr tprog e m c v.
 Proof.
   intros. destruct op; simpl in *.
   eapply make_add_correct; eauto.
@@ -339,10 +337,10 @@ Proof.
 Qed. 
 
 Lemma make_cast_correct:
-  forall le e m1 a t m2 v ty1 ty2 v',
-   eval_expr tprog le e m1 a t m2 v ->
+  forall e m a v ty1 ty2 v',
+   eval_expr tprog e m a v ->
    cast v ty1 ty2 v' ->
-   eval_expr tprog le e m1 (make_cast ty1 ty2 a) t m2 v'.
+   eval_expr tprog e m (make_cast ty1 ty2 a) v'.
 Proof.
   unfold make_cast, make_cast1, make_cast2.
   intros until v'; intros EVAL CAST.
@@ -362,14 +360,14 @@ Proof.
 Qed.
 
 Lemma make_load_correct:
-  forall addr ty code b ofs v le e m1 t m2,
+  forall addr ty code b ofs v e m,
   make_load addr ty = OK code ->
-  eval_expr tprog le e m1 addr t m2 (Vptr b ofs) ->
-  load_value_of_type ty m2 b ofs = Some v ->
-  eval_expr tprog le e m1 code t m2 v.
+  eval_expr tprog e m addr (Vptr b ofs) ->
+  load_value_of_type ty m b ofs = Some v ->
+  eval_expr tprog e m code v.
 Proof.
   unfold make_load, load_value_of_type.
-  intros until m2; intros MKLOAD EVEXP LDVAL.
+  intros until m; intros MKLOAD EVEXP LDVAL.
   destruct (access_mode ty); inversion MKLOAD.
   (* access_mode ty = By_value m *)
   apply eval_Eload with (Vptr b ofs); auto.
@@ -378,18 +376,18 @@ Proof.
 Qed.
 
 Lemma make_store_correct:
-  forall addr ty rhs code e m1 t1 m2 b ofs t2 m3 v m4,
+  forall addr ty rhs code e m b ofs v m',
   make_store addr ty rhs = OK code ->
-  eval_expr tprog nil e m1 addr t1 m2 (Vptr b ofs) ->
-  eval_expr tprog nil e m2 rhs t2 m3 v ->
-  store_value_of_type ty m3 b ofs v = Some m4 ->
-  exec_stmt tprog e m1 code (t1 ** t2) m4 Out_normal.
+  eval_expr tprog e m addr (Vptr b ofs) ->
+  eval_expr tprog e m rhs v ->
+  store_value_of_type ty m b ofs v = Some m' ->
+  exec_stmt tprog e m code E0 m' Out_normal.
 Proof.
   unfold make_store, store_value_of_type.
-  intros until m4; intros MKSTORE EV1 EV2 STVAL.
+  intros until m'; intros MKSTORE EV1 EV2 STVAL.
   destruct (access_mode ty); inversion MKSTORE.
   (* access_mode ty = By_value m *)
-  eapply eval_Sstore; eauto. 
+  eapply exec_Sstore; eauto. 
 Qed.
 
 End CONSTRUCTORS.
diff --git a/cfrontend/Cshmgenproof3.v b/cfrontend/Cshmgenproof3.v
index 10f48f612..54f9b7727 100644
--- a/cfrontend/Cshmgenproof3.v
+++ b/cfrontend/Cshmgenproof3.v
@@ -10,6 +10,7 @@ Require Import Values.
 Require Import Events.
 Require Import Mem.
 Require Import Globalenvs.
+Require Import Smallstep.
 Require Import Csyntax.
 Require Import Csem.
 Require Import Ctyping.
@@ -307,13 +308,13 @@ Qed.
 (** Correctness of the code generated by [var_get]. *)
 
 Lemma var_get_correct:
-  forall e m id ty loc ofs v tyenv code te le,
-  Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) E0 m loc ofs ->
+  forall e m id ty loc ofs v tyenv code te,
+  Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) loc ofs ->
   load_value_of_type ty m loc ofs = Some v ->
   wt_expr tyenv (Expr (Csyntax.Evar id) ty) ->
   var_get id ty = OK code ->
   match_env tyenv e te ->
-  eval_expr tprog le te m code E0 m v.
+  eval_expr tprog te m code v.
 Proof.
   intros. inversion H1; subst; clear H1. 
   unfold load_value_of_type in H0.
@@ -356,14 +357,14 @@ Qed.
 (** Correctness of the code generated by [var_set]. *)
 
 Lemma var_set_correct:
-  forall e m id ty m1 loc ofs t1 m2 v t2 m3 tyenv code te rhs, 
-  Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) t1 m1 loc ofs ->
-  store_value_of_type ty m2 loc ofs v = Some m3 ->
+  forall e m id ty loc ofs v m' tyenv code te rhs, 
+  Csem.eval_lvalue ge e m (Expr (Csyntax.Evar id) ty) loc ofs ->
+  store_value_of_type ty m loc ofs v = Some m' ->
   wt_expr tyenv (Expr (Csyntax.Evar id) ty) ->
   var_set id ty rhs = OK code ->
   match_env tyenv e te ->
-  eval_expr tprog nil te m1 rhs t2 m2 v ->
-  exec_stmt tprog te m code (t1 ** t2) m3 Out_normal.
+  eval_expr tprog te m rhs v ->
+  exec_stmt tprog te m code E0 m' Out_normal.
 Proof.
   intros. inversion H1; subst; clear H1. 
   unfold store_value_of_type in H0.
@@ -372,16 +373,16 @@ Proof.
   (* access mode By_value *)
   intros chunk ACC. rewrite ACC in H0. rewrite ACC in H2. 
   inversion H2; clear H2; subst.
-  inversion H; subst; clear H; rewrite E0_left.
+  inversion H; subst; clear H. 
     (* local variable *)
     exploit me_local; eauto. intros [vk [A B]].
     red in A; rewrite ACC in A; subst vk.
-    eapply eval_Sassign. eauto. 
-    eapply eval_var_ref_local. eauto. assumption. 
+    eapply exec_Sassign. eauto.
+    econstructor. eapply eval_var_ref_local. eauto. assumption. 
     (* global variable *)
     exploit me_global; eauto. intros [A B].
-    eapply eval_Sassign. eauto.
-    eapply eval_var_ref_global. auto. 
+    eapply exec_Sassign. eauto.
+    econstructor. eapply eval_var_ref_global. auto. 
     fold tge. rewrite symbols_preserved. eauto.
     eauto. assumption. 
   (* access mode By_reference *)
@@ -390,158 +391,145 @@ Proof.
   intros. rewrite H1 in H0; discriminate.
 Qed.
 
-(** * Proof of semantic simulation *)
+Lemma call_dest_set_correct:
+  forall e m0 lhs loc ofs m1 v m2 tyenv optid te,
+  Csem.eval_lvalue ge e m0 lhs loc ofs ->
+  store_value_of_type (typeof lhs) m1 loc ofs v = Some m2 ->
+  wt_expr tyenv lhs ->
+  transl_lhs_call (Some lhs) = OK optid ->
+  match_env tyenv e te ->
+  exec_opt_assign tprog te m1 optid v m2.
+Proof.
+  intros. generalize H2. simpl. caseEq (is_variable lhs). 2: congruence. 
+  intros. inv H5. 
+  exploit is_variable_correct; eauto. intro.
+  rewrite H5 in H. rewrite H5 in H1. inversion H1. subst i ty.
+  constructor.  
+  generalize H0. unfold store_value_of_type. 
+  caseEq (access_mode (typeof lhs)); intros; try discriminate.
+  (* access mode By_value *)
+  inversion H. 
+  (* local variable *)
+  subst id0 ty l ofs. exploit me_local; eauto. 
+  intros [vk [A B]]. red in A. rewrite H6 in A. subst vk.
+  econstructor. eapply eval_var_ref_local; eauto. assumption.
+  (* global variable *)
+  subst id0 ty l ofs. exploit me_global; eauto. 
+  intros [A B]. 
+  econstructor. eapply eval_var_ref_global; eauto. 
+  rewrite symbols_preserved. eauto. assumption. 
+Qed.
+
+(** * Proof of semantic preservation *)
+
+(** ** Semantic preservation for expressions *)
 
-(** The proof of semantic preservation for this compiler pass relies
-  on simulation diagrams of the following form:
+(** The proof of semantic preservation for the translation of expressions
+  relies on simulation diagrams of the following form:
 <<
-         e, m1, a ------------------- te, m1, ta
+         e, m, a ------------------- te, m, ta
             |                           |
            t|                           |t
             |                           |
             v                           v
-         e, m2, v ------------------- te, m2, v
+         e, m, v ------------------- te, m, v
 >>
-  Left: evaluation of expression [a] in Clight.
+  Left: evaluation of r-value expression [a] in Clight.
   Right: evaluation of its translation [ta] in Csharpminor.
   Top (precondition): matching between environments [e], [te], 
     plus well-typedness of expression [a].
-  Bottom (postcondition): the result values [v] and final memory states [m2]
+  Bottom (postcondition): the result values [v] 
     are identical in both evaluations.
 
   We state these diagrams as the following properties, parameterized
   by the Clight evaluation. *)
 
-Definition eval_expr_prop 
-    (e: Csem.env) (m1: mem) (a: Csyntax.expr) (t: trace) (m2: mem) (v: val) : Prop :=
-  forall tyenv ta te tle
+Section EXPR.
+
+Variable e: Csem.env.
+Variable m: mem.
+Variable te: Csharpminor.env.
+Variable tyenv: typenv.
+Hypothesis MENV: match_env tyenv e te.
+
+Definition eval_expr_prop (a: Csyntax.expr) (v: val) : Prop :=
+  forall ta
     (WT: wt_expr tyenv a)
-    (TR: transl_expr a = OK ta)
-    (MENV: match_env tyenv e te),
-  Csharpminor.eval_expr tprog tle te m1 ta t m2 v.
+    (TR: transl_expr a = OK ta),
+  Csharpminor.eval_expr tprog te m ta v.
 
-Definition eval_lvalue_prop
-    (e: Csem.env) (m1: mem) (a: Csyntax.expr) (t: trace)
-    (m2: mem) (b: block) (ofs: int) : Prop :=
-  forall tyenv ta te tle
+Definition eval_lvalue_prop (a: Csyntax.expr) (b: block) (ofs: int) : Prop :=
+  forall ta
     (WT: wt_expr tyenv a)
-    (TR: transl_lvalue a = OK ta)
-    (MENV: match_env tyenv e te),
-  Csharpminor.eval_expr tprog tle te m1 ta t m2 (Vptr b ofs).
+    (TR: transl_lvalue a = OK ta),
+  Csharpminor.eval_expr tprog te m ta (Vptr b ofs).
 
-Definition eval_exprlist_prop
-    (e: Csem.env) (m1: mem) (al: Csyntax.exprlist) (t: trace)
-    (m2: mem) (vl: list val) : Prop :=
-  forall tyenv tal te tle
+Definition eval_exprlist_prop (al: list Csyntax.expr) (vl: list val) : Prop :=
+  forall tal
     (WT: wt_exprlist tyenv al)
-    (TR: transl_exprlist al = OK tal)
-    (MENV: match_env tyenv e te),
-  Csharpminor.eval_exprlist tprog tle te m1 tal t m2 vl.
-
-Definition transl_outcome (nbrk ncnt: nat) (out: Csem.outcome): Csharpminor.outcome :=
-  match out with
-  | Csem.Out_normal => Csharpminor.Out_normal
-  | Csem.Out_break  => Csharpminor.Out_exit nbrk
-  | Csem.Out_continue => Csharpminor.Out_exit ncnt
-  | Csem.Out_return vopt => Csharpminor.Out_return vopt
-  end.
-
-Definition exec_stmt_prop
-    (e: Csem.env) (m1: mem) (s: Csyntax.statement) (t: trace)
-    (m2: mem) (out: Csem.outcome) : Prop :=
-  forall tyenv nbrk ncnt ts te
-    (WT: wt_stmt tyenv s)
-    (TR: transl_statement nbrk ncnt s = OK ts)   
-    (MENV: match_env tyenv e te),
-  Csharpminor.exec_stmt tprog te m1 ts t m2 (transl_outcome nbrk ncnt out).
-
-Definition exec_lblstmts_prop
-    (e: Csem.env) (m1: mem) (s: Csyntax.labeled_statements)
-    (t: trace) (m2: mem) (out: Csem.outcome) : Prop :=
-  forall tyenv nbrk ncnt body ts te m0 t0
-    (WT: wt_lblstmts tyenv s)
-    (TR: transl_lblstmts (lblstmts_length s)
-                         (1 + lblstmts_length s + ncnt)
-                         s body = OK ts)   
-    (MENV: match_env tyenv e te)
-    (BODY: Csharpminor.exec_stmt tprog te m0 body t0 m1 Out_normal),
-  Csharpminor.exec_stmt tprog te m0 ts (t0 ** t) m2 
-       (transl_outcome nbrk ncnt (outcome_switch out)).
-
-Definition eval_funcall_prop
-    (m1: mem) (f: Csyntax.fundef) (params: list val)
-    (t: trace) (m2: mem) (res: val) : Prop :=
-  forall tf
-    (WT: wt_fundef (global_typenv prog) f)
-    (TR: transl_fundef f = OK tf),
-   Csharpminor.eval_funcall tprog m1 tf params t m2 res.
+    (TR: transl_exprlist al = OK tal),
+  Csharpminor.eval_exprlist tprog te m tal vl.
 
-(** The proof of semantic preservation is by induction on the Clight
-  evaluation derivation.  Since this proof is large, we break it
-  into one lemma for each Clight evaluation rule. *)
+(* Check (eval_expr_ind2 ge e m eval_expr_prop eval_lvalue_prop).*)
 
 Lemma transl_Econst_int_correct:
-       (forall (e : Csem.env) (m : mem) (i : int) (ty : type),
-        eval_expr_prop e m (Expr (Econst_int i) ty) E0 m (Vint i)).
+  forall (i : int) (ty : type),
+  eval_expr_prop (Expr (Econst_int i) ty) (Vint i).
 Proof.
   intros; red; intros.
   monadInv TR. apply make_intconst_correct.
 Qed.
 
 Lemma transl_Econst_float_correct:
-       (forall (e : Csem.env) (m : mem) (f0 : float) (ty : type),
-        eval_expr_prop e m (Expr (Econst_float f0) ty) E0 m (Vfloat f0)).
+  forall (f0 : float) (ty : type),
+  eval_expr_prop (Expr (Econst_float f0) ty) (Vfloat f0).
 Proof.
   intros; red; intros.
   monadInv TR. apply make_floatconst_correct.
 Qed.
 
 Lemma transl_Elvalue_correct:
-       (forall (e : Csem.env) (m : mem) (a : expr_descr) (ty : type)
-          (t : trace) (m1 : mem) (loc : block) (ofs : int) (v : val),
-        eval_lvalue ge e m (Expr a ty) t m1 loc ofs ->
-        eval_lvalue_prop e m (Expr a ty) t m1 loc ofs ->
-        load_value_of_type ty m1 loc ofs = Some v ->
-        eval_expr_prop e m (Expr a ty) t m1 v).
+  forall (a : expr_descr) (ty : type) (loc : block) (ofs : int)
+         (v : val),
+  eval_lvalue ge e m (Expr a ty) loc ofs ->
+  eval_lvalue_prop (Expr a ty) loc ofs ->
+  load_value_of_type ty m loc ofs = Some v ->
+  eval_expr_prop (Expr a ty) v.
 Proof.
   intros; red; intros.
   exploit transl_expr_lvalue; eauto. 
   intros [[id [EQ VARGET]] | [tb [TRLVAL MKLOAD]]].
   (* Case a is a variable *)
-  subst a. 
-  assert (t = E0 /\ m1 = m). inversion H; auto. 
-  destruct H2; subst t m1.
-  eapply var_get_correct; eauto.
+  subst a. eapply var_get_correct; eauto.
   (* Case a is another lvalue *)
   eapply make_load_correct; eauto. 
 Qed.
 
 Lemma transl_Eaddrof_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace)
-          (m1 : mem) (loc : block) (ofs : int) (ty : type),
-        eval_lvalue ge e m a t m1 loc ofs ->
-        eval_lvalue_prop e m a t m1 loc ofs ->
-        eval_expr_prop e m (Expr (Csyntax.Eaddrof a) ty) t m1 (Vptr loc ofs)).
+  forall (a : Csyntax.expr) (ty : type) (loc : block) (ofs : int),
+  eval_lvalue ge e m a loc ofs ->
+  eval_lvalue_prop a loc ofs ->
+  eval_expr_prop (Expr (Csyntax.Eaddrof a) ty) (Vptr loc ofs).
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. simpl in TR. 
   eauto.
 Qed.
 
 Lemma transl_Esizeof_correct:
-       (forall (e : Csem.env) (m : mem) (ty' ty : type),
-        eval_expr_prop e m (Expr (Esizeof ty') ty) E0 m
-          (Vint (Int.repr (Csyntax.sizeof ty')))).
+  forall ty' ty : type,
+  eval_expr_prop (Expr (Esizeof ty') ty)
+                 (Vint (Int.repr (Csyntax.sizeof ty'))).
 Proof.
   intros; red; intros. monadInv TR. apply make_intconst_correct. 
 Qed.
 
 Lemma transl_Eunop_correct:
-       (forall (e : Csem.env) (m : mem) (op : Csyntax.unary_operation)
-          (a : Csyntax.expr) (ty : type) (t : trace) (m1 : mem) (v1 v : val),
-        Csem.eval_expr ge e m a t m1 v1 ->
-        eval_expr_prop e m a t m1 v1 ->
-        sem_unary_operation op v1 (typeof a) = Some v ->
-        eval_expr_prop e m (Expr (Csyntax.Eunop op a) ty) t m1 v).
+  forall (op : Csyntax.unary_operation) (a : Csyntax.expr) (ty : type)
+         (v1 v : val),
+  Csem.eval_expr ge e m a v1 ->
+  eval_expr_prop a v1 ->
+  sem_unary_operation op v1 (typeof a) = Some v ->
+  eval_expr_prop (Expr (Csyntax.Eunop op a) ty) v.
 Proof.
   intros; red; intros.
   inversion WT; clear WT; subst.
@@ -550,15 +538,14 @@ Proof.
 Qed.
 
 Lemma transl_Ebinop_correct:
-       (forall (e : Csem.env) (m : mem) (op : Csyntax.binary_operation)
-          (a1 a2 : Csyntax.expr) (ty : type) (t1 : trace) (m1 : mem)
-          (v1 : val) (t2 : trace) (m2 : mem) (v2 v : val),
-        Csem.eval_expr ge e m a1 t1 m1 v1 ->
-        eval_expr_prop e m a1 t1 m1 v1 ->
-        Csem.eval_expr ge e m1 a2 t2 m2 v2 ->
-        eval_expr_prop e m1 a2 t2 m2 v2 ->
-        sem_binary_operation op v1 (typeof a1) v2 (typeof a2) m2 = Some v ->
-        eval_expr_prop e m (Expr (Csyntax.Ebinop op a1 a2) ty) (t1 ** t2) m2 v).
+  forall (op : Csyntax.binary_operation) (a1 a2 : Csyntax.expr)
+         (ty : type) (v1 v2 v : val),
+  Csem.eval_expr ge e m a1 v1 ->
+  eval_expr_prop a1 v1 ->
+  Csem.eval_expr ge e m a2 v2 ->
+  eval_expr_prop a2 v2 ->
+  sem_binary_operation op v1 (typeof a1) v2 (typeof a2) m = Some v ->
+  eval_expr_prop (Expr (Csyntax.Ebinop op a1 a2) ty) v.
 Proof.
   intros; red; intros.
   inversion WT; clear WT; subst.
@@ -567,137 +554,93 @@ Proof.
 Qed.
 
 Lemma transl_Eorbool_1_correct:
-       (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (t : trace)
-          (m1 : mem) (v1 : val) (ty : type),
-        Csem.eval_expr ge e m a1 t m1 v1 ->
-        eval_expr_prop e m a1 t m1 v1 ->
-        is_true v1 (typeof a1) ->
-        eval_expr_prop e m (Expr (Eorbool a1 a2) ty) t m1 Vtrue).
+  forall (a1 a2 : Csyntax.expr) (ty : type) (v1 : val),
+  Csem.eval_expr ge e m a1 v1 ->
+  eval_expr_prop a1 v1 ->
+  is_true v1 (typeof a1) ->
+  eval_expr_prop (Expr (Eorbool a1 a2) ty) Vtrue.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR.
   unfold make_orbool.
   exploit make_boolean_correct_true; eauto. intros [vb [EVAL ISTRUE]].
-  eapply eval_Econdition_true; eauto.
-  unfold Vtrue; apply make_intconst_correct. traceEq.
+  eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto.
+  simpl. unfold Vtrue; apply make_intconst_correct. 
 Qed.
 
 Lemma transl_Eorbool_2_correct:
-       (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (ty : type)
-          (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace) (m2 : mem)
-          (v2 v : val),
-        Csem.eval_expr ge e m a1 t1 m1 v1 ->
-        eval_expr_prop e m a1 t1 m1 v1 ->
-        is_false v1 (typeof a1) ->
-        Csem.eval_expr ge e m1 a2 t2 m2 v2 ->
-        eval_expr_prop e m1 a2 t2 m2 v2 ->
-        bool_of_val v2 (typeof a2) v ->
-        eval_expr_prop e m (Expr (Eorbool a1 a2) ty) (t1 ** t2) m2 v).
+  forall (a1 a2 : Csyntax.expr) (ty : type) (v1 v2 v : val),
+  Csem.eval_expr ge e m a1 v1 ->
+  eval_expr_prop a1 v1 ->
+  is_false v1 (typeof a1) ->
+  Csem.eval_expr ge e m a2 v2 ->
+  eval_expr_prop a2 v2 ->
+  bool_of_val v2 (typeof a2) v ->
+  eval_expr_prop (Expr (Eorbool a1 a2) ty) v.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR.
   unfold make_orbool.
   exploit make_boolean_correct_false. eapply H0; eauto. eauto. intros [vb [EVAL ISFALSE]].
-  eapply eval_Econdition_false; eauto.
-  inversion H4; subst.
+  eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto.
+  simpl. inversion H4; subst.
   exploit make_boolean_correct_true. eapply H3; eauto. eauto. intros [vc [EVAL' ISTRUE']].
-  eapply eval_Econdition_true; eauto. 
-  unfold Vtrue; apply make_intconst_correct. traceEq.
+  eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto. 
+  unfold Vtrue; apply make_intconst_correct.
   exploit make_boolean_correct_false. eapply H3; eauto. eauto. intros [vc [EVAL' ISFALSE']].
-  eapply eval_Econdition_false; eauto.
-  unfold Vfalse; apply make_intconst_correct. traceEq.
+  eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto. 
+  unfold Vfalse; apply make_intconst_correct. 
 Qed.
 
 Lemma transl_Eandbool_1_correct:
-       (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (t : trace)
-          (m1 : mem) (v1 : val) (ty : type),
-        Csem.eval_expr ge e m a1 t m1 v1 ->
-        eval_expr_prop e m a1 t m1 v1 ->
-        is_false v1 (typeof a1) ->
-        eval_expr_prop e m (Expr (Eandbool a1 a2) ty) t m1 Vfalse).
+  forall (a1 a2 : Csyntax.expr) (ty : type) (v1 : val),
+  Csem.eval_expr ge e m a1 v1 ->
+  eval_expr_prop a1 v1 ->
+  is_false v1 (typeof a1) ->
+  eval_expr_prop (Expr (Eandbool a1 a2) ty) Vfalse.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR.
   unfold make_andbool.
   exploit make_boolean_correct_false; eauto. intros [vb [EVAL ISFALSE]].
-  eapply eval_Econdition_false; eauto.
-  unfold Vfalse; apply make_intconst_correct. traceEq.
+  eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto. 
+  unfold Vfalse; apply make_intconst_correct. 
 Qed.
 
 Lemma transl_Eandbool_2_correct:
-       (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (ty : type)
-          (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace) (m2 : mem)
-          (v2 v : val),
-        Csem.eval_expr ge e m a1 t1 m1 v1 ->
-        eval_expr_prop e m a1 t1 m1 v1 ->
-        is_true v1 (typeof a1) ->
-        Csem.eval_expr ge e m1 a2 t2 m2 v2 ->
-        eval_expr_prop e m1 a2 t2 m2 v2 ->
-        bool_of_val v2 (typeof a2) v ->
-        eval_expr_prop e m (Expr (Eandbool a1 a2) ty) (t1 ** t2) m2 v).
+  forall (a1 a2 : Csyntax.expr) (ty : type) (v1 v2 v : val),
+  Csem.eval_expr ge e m a1 v1 ->
+  eval_expr_prop a1 v1 ->
+  is_true v1 (typeof a1) ->
+  Csem.eval_expr ge e m a2 v2 ->
+  eval_expr_prop a2 v2 ->
+  bool_of_val v2 (typeof a2) v ->
+  eval_expr_prop (Expr (Eandbool a1 a2) ty) v.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR.
   unfold make_andbool.
   exploit make_boolean_correct_true. eapply H0; eauto. eauto. intros [vb [EVAL ISTRUE]].
-  eapply eval_Econdition_true; eauto.
-  inversion H4; subst.
+  eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto. 
+  simpl. inversion H4; subst.
   exploit make_boolean_correct_true. eapply H3; eauto. eauto. intros [vc [EVAL' ISTRUE']].
-  eapply eval_Econdition_true; eauto. 
-  unfold Vtrue; apply make_intconst_correct. traceEq.
+  eapply eval_Econdition; eauto. apply Val.bool_of_true_val; eauto.
+  unfold Vtrue; apply make_intconst_correct.
   exploit make_boolean_correct_false. eapply H3; eauto. eauto. intros [vc [EVAL' ISFALSE']].
-  eapply eval_Econdition_false; eauto.
-  unfold Vfalse; apply make_intconst_correct. traceEq.
+  eapply eval_Econdition; eauto. apply Val.bool_of_false_val; eauto.
+  unfold Vfalse; apply make_intconst_correct.
 Qed.
 
 Lemma transl_Ecast_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (ty : type)
-          (t : trace) (m1 : mem) (v1 v : val),
-        Csem.eval_expr ge e m a t m1 v1 ->
-        eval_expr_prop e m a t m1 v1 ->
-        cast v1 (typeof a) ty v ->
-        eval_expr_prop e m (Expr (Ecast ty a) ty) t m1 v).
+  forall (a : Csyntax.expr) (ty : type) (v1 v : val),
+  Csem.eval_expr ge e m a v1 ->
+  eval_expr_prop a v1 ->
+  cast v1 (typeof a) ty v -> eval_expr_prop (Expr (Ecast ty a) ty) v.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR.
   eapply make_cast_correct; eauto.
 Qed.
 
-Lemma transl_Ecall_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr)
-          (bl : Csyntax.exprlist) (ty : type) (m3 : mem) (vres : val)
-          (t1 : trace) (m1 : mem) (vf : val) (t2 : trace) (m2 : mem)
-          (vargs : list val) (f : Csyntax.fundef) (t3 : trace),
-        Csem.eval_expr ge e m a t1 m1 vf ->
-        eval_expr_prop e m a t1 m1 vf ->
-        Csem.eval_exprlist ge e m1 bl t2 m2 vargs ->
-        eval_exprlist_prop e m1 bl t2 m2 vargs ->
-        Genv.find_funct ge vf = Some f ->
-        type_of_fundef f = typeof a ->
-        Csem.eval_funcall ge m2 f vargs t3 m3 vres ->
-        eval_funcall_prop m2 f vargs t3 m3 vres ->
-        eval_expr_prop e m (Expr (Csyntax.Ecall a bl) ty) (t1 ** t2 ** t3) m3
-          vres).
-Proof.
-  intros; red; intros.
-  inversion WT; clear WT; subst.
-  simpl in TR. 
-  caseEq (classify_fun (typeof a)).
-  2: intros; rewrite H7 in TR; discriminate.
-  intros targs tres EQ. rewrite EQ in TR. 
-  monadInv TR. 
-  rewrite <- H4 in EQ.
-  exploit functions_translated; eauto. intros [tf [FIND TRL]].
-  econstructor.
-  eapply H0; eauto.
-  eapply H2; eauto.
-  eexact FIND. 
-  eapply transl_fundef_sig1; eauto. 
-  eapply H6; eauto. 
-  eapply functions_well_typed; eauto.
-  auto.
-Qed.
-
 Lemma transl_Evar_local_correct:
-       (forall (e : Csem.env) (m : mem) (id : positive) (l : block)
-          (ty : type),
-        e ! id = Some l ->
-        eval_lvalue_prop e m (Expr (Csyntax.Evar id) ty) E0 m l Int.zero).
+  forall (id : ident) (l : block) (ty : type),
+  e ! id = Some l ->
+  eval_lvalue_prop (Expr (Csyntax.Evar id) ty) l Int.zero.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR.
   exploit (me_local _ _ _ MENV); eauto. intros [vk [A B]].
@@ -705,11 +648,10 @@ Proof.
 Qed.
 
 Lemma transl_Evar_global_correct:
-       (forall (e : PTree.t block) (m : mem) (id : positive) (l : block)
-          (ty : type),
-        e ! id = None ->
-        Genv.find_symbol ge id = Some l ->
-        eval_lvalue_prop e m (Expr (Csyntax.Evar id) ty) E0 m l Int.zero).
+  forall (id : ident) (l : block) (ty : type),
+  e ! id = None ->
+  Genv.find_symbol ge id = Some l ->
+  eval_lvalue_prop (Expr (Csyntax.Evar id) ty) l Int.zero.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. monadInv TR. 
   exploit (me_global _ _ _ MENV); eauto. intros [A B].
@@ -718,83 +660,183 @@ Proof.
 Qed.
 
 Lemma transl_Ederef_correct:
-       (forall (e : Csem.env) (m m1 : mem) (a : Csyntax.expr) (t : trace)
-          (ofs : int) (ty : type) (l : block),
-        Csem.eval_expr ge e m a t m1 (Vptr l ofs) ->
-        eval_expr_prop e m a t m1 (Vptr l ofs) ->
-        eval_lvalue_prop e m (Expr (Ederef a) ty) t m1 l ofs).
+  forall (a : Csyntax.expr) (ty : type) (l : block) (ofs : int),
+  Csem.eval_expr ge e m a (Vptr l ofs) ->
+  eval_expr_prop a (Vptr l ofs) ->
+  eval_lvalue_prop (Expr (Ederef a) ty) l ofs.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. simpl in TR. 
   eauto.
 Qed.
 
 Lemma transl_Eindex_correct:
-       (forall (e : Csem.env) (m : mem) (a1 : Csyntax.expr) (t1 : trace)
-          (m1 : mem) (v1 : val) (a2 : Csyntax.expr) (t2 : trace) (m2 : mem)
-          (v2 : val) (l : block) (ofs : int) (ty : type),
-        Csem.eval_expr ge e m a1 t1 m1 v1 ->
-        eval_expr_prop e m a1 t1 m1 v1 ->
-        Csem.eval_expr ge e m1 a2 t2 m2 v2 ->
-        eval_expr_prop e m1 a2 t2 m2 v2 ->
-        sem_add v1 (typeof a1) v2 (typeof a2) = Some (Vptr l ofs) ->
-        eval_lvalue_prop e m (Expr (Eindex a1 a2) ty) (t1 ** t2) m2 l ofs).
+  forall (a1 a2 : Csyntax.expr) (ty : type) (v1 v2 : val) (l : block)
+         (ofs : int),
+  Csem.eval_expr ge e m a1 v1 ->
+  eval_expr_prop a1 v1 ->
+  Csem.eval_expr ge e m a2 v2 ->
+  eval_expr_prop a2 v2 ->
+  sem_add v1 (typeof a1) v2 (typeof a2) = Some (Vptr l ofs) ->
+  eval_lvalue_prop (Expr (Eindex a1 a2) ty) l ofs.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. simpl in TR. monadInv TR.
   eapply (make_add_correct tprog); eauto. 
 Qed.
 
 Lemma transl_Efield_struct_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace)
-          (m1 : mem) (l : block) (ofs : int) (id: ident) (fList : fieldlist) (i : ident)
-          (ty : type) (delta : Z),
-        eval_lvalue ge e m a t m1 l ofs ->
-        eval_lvalue_prop e m a t m1 l ofs ->
-        typeof a = Tstruct id fList ->
-        field_offset i fList = OK delta ->
-        eval_lvalue_prop e m (Expr (Efield a i) ty) t m1 l
-          (Int.add ofs (Int.repr delta))).
+  forall (a : Csyntax.expr) (i : ident) (ty : type) (l : block)
+         (ofs : int) (id : ident) (fList : fieldlist) (delta : Z),
+  eval_lvalue ge e m a l ofs ->
+  eval_lvalue_prop a l ofs ->
+  typeof a = Tstruct id fList ->
+  field_offset i fList = OK delta ->
+  eval_lvalue_prop (Expr (Efield a i) ty) l (Int.add ofs (Int.repr delta)).
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. 
   simpl in TR. rewrite H1 in TR. monadInv TR.
-  econstructor; eauto.
+  eapply eval_Ebinop; eauto.
   apply make_intconst_correct. 
-  simpl. congruence. traceEq.
+  simpl. congruence.
 Qed.
 
 Lemma transl_Efield_union_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace)
-          (m1 : mem) (l : block) (ofs : int) (id: ident) (fList : fieldlist) (i : ident)
-          (ty : type),
-        eval_lvalue ge e m a t m1 l ofs ->
-        eval_lvalue_prop e m a t m1 l ofs ->
-        typeof a = Tunion id fList ->
-        eval_lvalue_prop e m (Expr (Efield a i) ty) t m1 l ofs).
+  forall (a : Csyntax.expr) (i : ident) (ty : type) (l : block)
+         (ofs : int) (id : ident) (fList : fieldlist),
+  eval_lvalue ge e m a l ofs ->
+  eval_lvalue_prop a l ofs ->
+  typeof a = Tunion id fList ->
+  eval_lvalue_prop (Expr (Efield a i) ty) l ofs.
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. 
   simpl in TR. rewrite H1 in TR. eauto.
 Qed.
 
-Lemma transl_Enil_correct:
-       (forall (e : Csem.env) (m : mem),
-        eval_exprlist_prop e m Csyntax.Enil E0 m nil).
-Proof.
-  intros; red; intros. monadInv TR. constructor.
-Qed.
+Lemma transl_expr_correct:
+  forall a v,
+  Csem.eval_expr ge e m a v ->
+  eval_expr_prop a v.
+Proof
+  (eval_expr_ind2 ge e m eval_expr_prop eval_lvalue_prop
+         transl_Econst_int_correct
+         transl_Econst_float_correct
+         transl_Elvalue_correct
+         transl_Eaddrof_correct
+         transl_Esizeof_correct
+         transl_Eunop_correct
+         transl_Ebinop_correct
+         transl_Eorbool_1_correct
+         transl_Eorbool_2_correct
+         transl_Eandbool_1_correct
+         transl_Eandbool_2_correct
+         transl_Ecast_correct
+         transl_Evar_local_correct
+         transl_Evar_global_correct
+         transl_Ederef_correct
+         transl_Eindex_correct
+         transl_Efield_struct_correct
+         transl_Efield_union_correct).
 
-Lemma transl_Econs_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr)
-          (bl : Csyntax.exprlist) (t1 : trace) (m1 : mem) (v : val)
-          (t2 : trace) (m2 : mem) (vl : list val),
-        Csem.eval_expr ge e m a t1 m1 v ->
-        eval_expr_prop e m a t1 m1 v ->
-        Csem.eval_exprlist ge e m1 bl t2 m2 vl ->
-        eval_exprlist_prop e m1 bl t2 m2 vl ->
-        eval_exprlist_prop e m (Csyntax.Econs a bl) (t1 ** t2) m2 (v :: vl)).
+Lemma transl_lvalue_correct:
+  forall a blk ofs,
+  Csem.eval_lvalue ge e m a blk ofs ->
+  eval_lvalue_prop a blk ofs.
+Proof
+  (eval_lvalue_ind2 ge e m eval_expr_prop eval_lvalue_prop
+         transl_Econst_int_correct
+         transl_Econst_float_correct
+         transl_Elvalue_correct
+         transl_Eaddrof_correct
+         transl_Esizeof_correct
+         transl_Eunop_correct
+         transl_Ebinop_correct
+         transl_Eorbool_1_correct
+         transl_Eorbool_2_correct
+         transl_Eandbool_1_correct
+         transl_Eandbool_2_correct
+         transl_Ecast_correct
+         transl_Evar_local_correct
+         transl_Evar_global_correct
+         transl_Ederef_correct
+         transl_Eindex_correct
+         transl_Efield_struct_correct
+         transl_Efield_union_correct).
+
+Lemma transl_exprlist_correct:
+  forall al vl,
+  Csem.eval_exprlist ge e m al vl ->
+  eval_exprlist_prop al vl.
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR. 
-  econstructor; eauto. 
+  induction 1; red; intros; monadInv TR; inv WT.
+  constructor.
+  constructor. eapply (transl_expr_correct _ _ H); eauto. eauto.
 Qed.
 
+End EXPR.
+
+(** ** Semantic preservation for statements *)
+
+(** The simulation diagrams for terminating statements and function
+  calls are of the following form:
+  relies on simulation diagrams of the following form:
+<<
+         e, m1, s ------------------- te, m1, ts
+            |                           |
+           t|                           |t
+            |                           |
+            v                           v
+         e, m2, out ----------------- te, m2, tout
+>>
+  Left: execution of statement [s] in Clight.
+  Right: execution of its translation [ts] in Csharpminor.
+  Top (precondition): matching between environments [e], [te], 
+    plus well-typedness of statement [s].
+  Bottom (postcondition): the outcomes [out] and [tout] are
+    related per the following function [transl_outcome].
+*)
+
+Definition transl_outcome (nbrk ncnt: nat) (out: Csem.outcome): Csharpminor.outcome :=
+  match out with
+  | Csem.Out_normal => Csharpminor.Out_normal
+  | Csem.Out_break  => Csharpminor.Out_exit nbrk
+  | Csem.Out_continue => Csharpminor.Out_exit ncnt
+  | Csem.Out_return vopt => Csharpminor.Out_return vopt
+  end.
+
+Definition exec_stmt_prop
+    (e: Csem.env) (m1: mem) (s: Csyntax.statement) (t: trace)
+    (m2: mem) (out: Csem.outcome) : Prop :=
+  forall tyenv nbrk ncnt ts te
+    (WT: wt_stmt tyenv s)
+    (TR: transl_statement nbrk ncnt s = OK ts)   
+    (MENV: match_env tyenv e te),
+  Csharpminor.exec_stmt tprog te m1 ts t m2 (transl_outcome nbrk ncnt out).
+
+Definition exec_lblstmts_prop
+    (e: Csem.env) (m1: mem) (s: Csyntax.labeled_statements)
+    (t: trace) (m2: mem) (out: Csem.outcome) : Prop :=
+  forall tyenv nbrk ncnt body ts te m0 t0
+    (WT: wt_lblstmts tyenv s)
+    (TR: transl_lblstmts (lblstmts_length s)
+                         (1 + lblstmts_length s + ncnt)
+                         s body = OK ts)   
+    (MENV: match_env tyenv e te)
+    (BODY: Csharpminor.exec_stmt tprog te m0 body t0 m1 Out_normal),
+  Csharpminor.exec_stmt tprog te m0 ts (t0 ** t) m2 
+       (transl_outcome nbrk ncnt (outcome_switch out)).
+
+Definition eval_funcall_prop
+    (m1: mem) (f: Csyntax.fundef) (params: list val)
+    (t: trace) (m2: mem) (res: val) : Prop :=
+  forall tf
+    (WT: wt_fundef (global_typenv prog) f)
+    (TR: transl_fundef f = OK tf),
+   Csharpminor.eval_funcall tprog m1 tf params t m2 res.
+
+(*
+Set Printing Depth 100.
+Check (Csem.eval_funcall_ind3 ge exec_stmt_prop exec_lblstmts_prop eval_funcall_prop).
+*)
+
 Lemma transl_Sskip_correct:
        (forall (e : Csem.env) (m : mem),
         exec_stmt_prop e m Csyntax.Sskip E0 m Csem.Out_normal).
@@ -802,28 +844,13 @@ Proof.
   intros; red; intros. monadInv TR. simpl. constructor.
 Qed.
 
-Lemma transl_Sexpr_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace)
-          (m1 : mem) (v : val),
-        Csem.eval_expr ge e m a t m1 v ->
-        eval_expr_prop e m a t m1 v ->
-        exec_stmt_prop e m (Csyntax.Sexpr a) t m1 Csem.Out_normal).
-Proof.
-  intros; red; intros; simpl. inversion WT; clear WT; subst. 
-  monadInv TR. econstructor; eauto.
-Qed.
-
 Lemma transl_Sassign_correct:
-       (forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (t1 : trace)
-          (m1 : mem) (loc : block) (ofs : int) (t2 : trace) (m2 : mem)
-          (v2 : val) (m3 : mem),
-        eval_lvalue ge e m a1 t1 m1 loc ofs ->
-        eval_lvalue_prop e m a1 t1 m1 loc ofs ->
-        Csem.eval_expr ge e m1 a2 t2 m2 v2 ->
-        eval_expr_prop e m1 a2 t2 m2 v2 ->
-        store_value_of_type (typeof a1) m2 loc ofs v2 = Some m3 ->
-        exec_stmt_prop e m (Csyntax.Sassign a1 a2) (t1 ** t2) m3
-          Csem.Out_normal).
+  forall (e : Csem.env) (m : mem) (a1 a2 : Csyntax.expr) (loc : block)
+         (ofs : int) (v2 : val) (m' : mem),
+  eval_lvalue ge e m a1 loc ofs ->
+  Csem.eval_expr ge e m a2 v2 ->
+  store_value_of_type (typeof a1) m loc ofs v2 = Some m' ->
+  exec_stmt_prop e m (Csyntax.Sassign a1 a2) E0 m' Csem.Out_normal.
 Proof.
   intros; red; intros.
   inversion WT; subst; clear WT.
@@ -832,12 +859,70 @@ Proof.
   (* a = variable id *)
   intros id ISVAR. rewrite ISVAR in TR. 
   generalize (is_variable_correct _ _ ISVAR). intro EQ. 
-  rewrite EQ in H; rewrite EQ in H0; rewrite EQ in H6.
+  rewrite EQ in H; rewrite EQ in H4.
   monadInv TR.
-  eapply var_set_correct; eauto. 
+  eapply var_set_correct; eauto.
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.  
   (* a is not a variable *)
   intro ISVAR; rewrite ISVAR in TR. monadInv TR.
   eapply make_store_correct; eauto.
+  eapply (transl_lvalue_correct _ _ _ _ MENV _ _ _ H); eauto.
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.  
+Qed.
+
+Lemma transl_Scall_None_correct:
+  forall (e : Csem.env) (m : mem) (a : Csyntax.expr)
+         (al : list Csyntax.expr) (vf : val) (vargs : list val)
+         (f : Csyntax.fundef) (t : trace) (m' : mem) (vres : val),
+  Csem.eval_expr ge e m a vf ->
+  Csem.eval_exprlist ge e m al vargs ->
+  Genv.find_funct ge vf = Some f ->
+  type_of_fundef f = typeof a ->
+  Csem.eval_funcall ge m f vargs t m' vres ->
+  eval_funcall_prop m f vargs t m' vres ->
+  exec_stmt_prop e m (Csyntax.Scall None a al) t m' Csem.Out_normal.
+Proof.
+  intros; red; intros; simpl.
+  inv WT. simpl in TR. 
+  caseEq (classify_fun (typeof a)); intros; rewrite H5 in TR; monadInv TR.
+  exploit functions_translated; eauto. intros [tf [TFIND TFD]].
+  econstructor. 
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto.
+  eapply (transl_exprlist_correct _ _ _ _ MENV _ _ H0); eauto.
+  eauto. 
+  eapply transl_fundef_sig1; eauto. rewrite H2; auto. 
+  eapply H4; eauto. 
+  eapply functions_well_typed; eauto.
+  constructor. 
+Qed.
+
+Lemma transl_Scall_Some_correct:
+  forall (e : Csem.env) (m : mem) (lhs a : Csyntax.expr)
+         (al : list Csyntax.expr) (loc : block) (ofs : int) (vf : val)
+         (vargs : list val) (f : Csyntax.fundef) (t : trace) (m' : mem)
+         (vres : val) (m'' : mem),
+  eval_lvalue ge e m lhs loc ofs ->
+  Csem.eval_expr ge e m a vf ->
+  Csem.eval_exprlist ge e m al vargs ->
+  Genv.find_funct ge vf = Some f ->
+  type_of_fundef f = typeof a ->
+  Csem.eval_funcall ge m f vargs t m' vres ->
+  eval_funcall_prop m f vargs t m' vres ->
+  store_value_of_type (typeof lhs) m' loc ofs vres = Some m'' ->
+  exec_stmt_prop e m (Csyntax.Scall (Some lhs) a al) t m'' Csem.Out_normal.
+Proof.
+  intros; red; intros; simpl.
+  inv WT. inv H10. unfold transl_statement in TR.
+  caseEq (classify_fun (typeof a)); intros; rewrite H7 in TR; monadInv TR.
+  exploit functions_translated; eauto. intros [tf [TFIND TFD]].
+  econstructor. 
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.
+  eapply (transl_exprlist_correct _ _ _ _ MENV _ _ H1); eauto.
+  eauto. 
+  eapply transl_fundef_sig1; eauto. rewrite H3; auto. 
+  eapply H5; eauto. 
+  eapply functions_well_typed; eauto.
+  eapply call_dest_set_correct; eauto. 
 Qed.
 
 Lemma transl_Ssequence_1_correct:
@@ -867,35 +952,39 @@ Proof.
 Qed.
 
 Lemma transl_Sifthenelse_true_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr)
-          (s1 s2 : statement) (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace)
-          (m2 : mem) (out : Csem.outcome),
-        Csem.eval_expr ge e m a t1 m1 v1 ->
-        eval_expr_prop e m a t1 m1 v1 ->
+        (forall (e : Csem.env) (m : mem) (a : Csyntax.expr)
+          (s1 s2 : statement) (v1 : val) (t : trace) (m' : mem)
+          (out : Csem.outcome),
+        Csem.eval_expr ge e m a v1 ->
         is_true v1 (typeof a) ->
-        Csem.exec_stmt ge e m1 s1 t2 m2 out ->
-        exec_stmt_prop e m1 s1 t2 m2 out ->
-        exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) (t1 ** t2) m2 out).
+        Csem.exec_stmt ge e m s1 t m' out ->
+        exec_stmt_prop e m s1 t m' out ->
+        exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) t m' out).
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  exploit make_boolean_correct_true. eapply H0; eauto. eauto. intros [vb [EVAL ISTRUE]].
-  eapply exec_Sifthenelse_true; eauto. 
+  exploit make_boolean_correct_true.
+    eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto.
+    eauto.
+  intros [vb [EVAL ISTRUE]].
+  eapply exec_Sifthenelse; eauto. apply Val.bool_of_true_val; eauto. simpl; eauto. 
 Qed.
 
 Lemma transl_Sifthenelse_false_correct:
        (forall (e : Csem.env) (m : mem) (a : Csyntax.expr)
-          (s1 s2 : statement) (t1 : trace) (m1 : mem) (v1 : val) (t2 : trace)
-          (m2 : mem) (out : Csem.outcome),
-        Csem.eval_expr ge e m a t1 m1 v1 ->
-        eval_expr_prop e m a t1 m1 v1 ->
+          (s1 s2 : statement) (v1 : val) (t : trace) (m' : mem)
+          (out : Csem.outcome),
+        Csem.eval_expr ge e m a v1 ->
         is_false v1 (typeof a) ->
-        Csem.exec_stmt ge e m1 s2 t2 m2 out ->
-        exec_stmt_prop e m1 s2 t2 m2 out ->
-        exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) (t1 ** t2) m2 out).
+        Csem.exec_stmt ge e m s2 t m' out ->
+        exec_stmt_prop e m s2 t m' out ->
+        exec_stmt_prop e m (Csyntax.Sifthenelse a s1 s2) t m' out).
 Proof.
   intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  exploit make_boolean_correct_false. eapply H0; eauto. eauto. intros [vb [EVAL ISFALSE]].
-  eapply exec_Sifthenelse_false; eauto. 
+  exploit make_boolean_correct_false.
+    eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto.
+    eauto.
+  intros [vb [EVAL ISFALSE]].
+  eapply exec_Sifthenelse; eauto. apply Val.bool_of_false_val; eauto. simpl; eauto. 
 Qed.
 
 Lemma transl_Sreturn_none_correct:
@@ -907,15 +996,13 @@ Proof.
 Qed.
 
 Lemma transl_Sreturn_some_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace)
-          (m1 : mem) (v : val),
-        Csem.eval_expr ge e m a t m1 v ->
-        eval_expr_prop e m a t m1 v ->
-        exec_stmt_prop e m (Csyntax.Sreturn (Some a)) t m1
-          (Csem.Out_return (Some v))).
+       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (v : val),
+        Csem.eval_expr ge e m a v ->
+        exec_stmt_prop e m (Csyntax.Sreturn (Some a)) E0 m (Csem.Out_return (Some v))).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  simpl. eapply exec_Sreturn_some; eauto. 
+  intros; red; intros. inv WT. inv H1. monadInv TR.
+  simpl. eapply exec_Sreturn_some; eauto.
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto.
 Qed.
 
 Lemma transl_Sbreak_correct:
@@ -935,47 +1022,51 @@ Proof.
 Qed.
 
 Lemma exit_if_false_true:
-  forall a ts e m1 t m2 v tyenv te,
+  forall a ts e m v tyenv te,
   exit_if_false a = OK ts ->
-  eval_expr_prop e m1 a t m2 v ->
+  Csem.eval_expr ge e m a v ->
+  is_true v (typeof a) ->
   match_env tyenv e te ->
   wt_expr tyenv a ->
-  is_true v (typeof a) ->
-  exec_stmt tprog te m1 ts t m2 Out_normal.
+  exec_stmt tprog te m ts E0 m Out_normal.
 Proof.
-  intros. monadInv H. 
-  exploit make_boolean_correct_true. eapply H0; eauto. eauto.
+  intros. monadInv H.
+  exploit make_boolean_correct_true.
+    eapply (transl_expr_correct _ _ _ _ H2 _ _ H0); eauto.
+    eauto.
   intros [vb [EVAL ISTRUE]].
-  eapply exec_Sifthenelse_true with (v1 := vb); eauto. 
-  constructor. traceEq.
+  eapply exec_Sifthenelse with (v := vb); eauto.
+  apply Val.bool_of_true_val; eauto.  
+  constructor.
 Qed.
  
 Lemma exit_if_false_false:
-  forall a ts e m1 t m2 v tyenv te,
+  forall a ts e m v tyenv te,
   exit_if_false a = OK ts ->
-  eval_expr_prop e m1 a t m2 v ->
+  Csem.eval_expr ge e m a v ->
+  is_false v (typeof a) ->
   match_env tyenv e te ->
   wt_expr tyenv a ->
-  is_false v (typeof a) ->
-  exec_stmt tprog te m1 ts t m2 (Out_exit 0).
+  exec_stmt tprog te m ts E0 m (Out_exit 0).
 Proof.
-  intros. monadInv H. 
-  exploit make_boolean_correct_false. eapply H0; eauto. eauto.
+  intros. monadInv H.
+  exploit make_boolean_correct_false.
+    eapply (transl_expr_correct _ _ _ _ H2 _ _ H0); eauto.
+    eauto.
   intros [vb [EVAL ISFALSE]].
-  eapply exec_Sifthenelse_false with (v1 := vb); eauto. 
-  constructor. traceEq.
+  eapply exec_Sifthenelse with (v := vb); eauto.
+  apply Val.bool_of_false_val; eauto. 
+  simpl. constructor.
 Qed.
 
 Lemma transl_Swhile_false_correct:
-       (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr)
-          (t : trace) (v : val) (m1 : mem),
-        Csem.eval_expr ge e m a t m1 v ->
-        eval_expr_prop e m a t m1 v ->
+       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (s : statement)
+          (v : val),
+        Csem.eval_expr ge e m a v ->
         is_false v (typeof a) ->
-        exec_stmt_prop e m (Swhile a s) t m1 Csem.Out_normal).
+        exec_stmt_prop e m (Swhile a s) E0 m Csem.Out_normal).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  simpl.
+  intros; red; intros; simpl. inv WT. monadInv TR.
   change Out_normal with (outcome_block (Out_exit 0)).
   apply exec_Sblock. apply exec_Sloop_stop. apply exec_Sseq_stop.
   eapply exit_if_false_false; eauto. congruence. congruence.
@@ -999,48 +1090,45 @@ Proof.
 Qed.
 
 Lemma transl_Swhile_stop_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t1 : trace)
-          (m1 : mem) (v : val) (s : statement) (m2 : mem) (t2 : trace)
-          (out2 out : Csem.outcome),
-        Csem.eval_expr ge e m a t1 m1 v ->
-        eval_expr_prop e m a t1 m1 v ->
+       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (v : val)
+          (s : statement) (t : trace) (m' : mem) (out' out : Csem.outcome),
+        Csem.eval_expr ge e m a v ->
         is_true v (typeof a) ->
-        Csem.exec_stmt ge e m1 s t2 m2 out2 ->
-        exec_stmt_prop e m1 s t2 m2 out2 ->
-        out_break_or_return out2 out ->
-        exec_stmt_prop e m (Swhile a s) (t1 ** t2) m2 out).
+        Csem.exec_stmt ge e m s t m' out' ->
+        exec_stmt_prop e m s t m' out' ->
+        out_break_or_return out' out ->
+        exec_stmt_prop e m (Swhile a s) t m' out).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  rewrite (transl_out_break_or_return _ _ nbrk ncnt H4).
+  intros; red; intros. inv WT. monadInv TR.
+  rewrite (transl_out_break_or_return _ _ nbrk ncnt H3).
   apply exec_Sblock. apply exec_Sloop_stop. 
   eapply exec_Sseq_continue. 
   eapply exit_if_false_true; eauto. 
-  apply exec_Sblock. eauto.
-  auto. inversion H4; simpl; congruence.
+  apply exec_Sblock. eauto. traceEq.
+  inversion H3; simpl; congruence.
 Qed.
 
 Lemma transl_Swhile_loop_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t1 : trace)
-          (m1 : mem) (v : val) (s : statement) (out2 out : Csem.outcome)
-          (t2 : trace) (m2 : mem) (t3 : trace) (m3 : mem),
-        Csem.eval_expr ge e m a t1 m1 v ->
-        eval_expr_prop e m a t1 m1 v ->
+       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (s : statement)
+          (v : val) (t1 : trace) (m1 : mem) (out1 : Csem.outcome)
+          (t2 : trace) (m2 : mem) (out : Csem.outcome),
+        Csem.eval_expr ge e m a v ->
         is_true v (typeof a) ->
-        Csem.exec_stmt ge e m1 s t2 m2 out2 ->
-        exec_stmt_prop e m1 s t2 m2 out2 ->
-        out_normal_or_continue out2 ->
-        Csem.exec_stmt ge e m2 (Swhile a s) t3 m3 out ->
-        exec_stmt_prop e m2 (Swhile a s) t3 m3 out ->
-        exec_stmt_prop e m (Swhile a s) (t1 ** t2 ** t3) m3 out).
+        Csem.exec_stmt ge e m s t1 m1 out1 ->
+        exec_stmt_prop e m s t1 m1 out1 ->
+        out_normal_or_continue out1 ->
+        Csem.exec_stmt ge e m1 (Swhile a s) t2 m2 out ->
+        exec_stmt_prop e m1 (Swhile a s) t2 m2 out ->
+        exec_stmt_prop e m (Swhile a s) (t1 ** t2) m2 out).
 Proof.
   intros; red; intros. 
-  exploit H6; eauto. intro NEXTITER.
-  inversion WT; clear WT; subst. simpl in TR; monadInv TR.
+  exploit H5; eauto. intro NEXTITER.
+  inv WT. monadInv TR. 
   inversion NEXTITER; subst.
   apply exec_Sblock. 
   eapply exec_Sloop_loop. eapply exec_Sseq_continue.
   eapply exit_if_false_true; eauto. 
-  rewrite (transl_out_normal_or_continue _ H4).
+  rewrite (transl_out_normal_or_continue _ H3).
   apply exec_Sblock. eauto. 
   reflexivity. eassumption.
   traceEq.
@@ -1048,23 +1136,21 @@ Qed.
 
 Lemma transl_Sdowhile_false_correct:
        (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr)
-          (t1 : trace) (m1 : mem) (out1 : Csem.outcome) (v : val)
-          (t2 : trace) (m2 : mem),
-        Csem.exec_stmt ge e m s t1 m1 out1 ->
-        exec_stmt_prop e m s t1 m1 out1 ->
+          (t : trace) (m1 : mem) (out1 : Csem.outcome) (v : val),
+        Csem.exec_stmt ge e m s t m1 out1 ->
+        exec_stmt_prop e m s t m1 out1 ->
         out_normal_or_continue out1 ->
-        Csem.eval_expr ge e m1 a t2 m2 v ->
-        eval_expr_prop e m1 a t2 m2 v ->
+        Csem.eval_expr ge e m1 a v ->
         is_false v (typeof a) ->
-        exec_stmt_prop e m (Sdowhile a s) (t1 ** t2) m2 Csem.Out_normal).
+        exec_stmt_prop e m (Sdowhile a s) t m1 Csem.Out_normal).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
+  intros; red; intros. inv WT. monadInv TR.
   simpl.
   change Out_normal with (outcome_block (Out_exit 0)).
   apply exec_Sblock. apply exec_Sloop_stop. eapply exec_Sseq_continue.
   rewrite (transl_out_normal_or_continue out1 H1).
   apply exec_Sblock. eauto. 
-  eapply exit_if_false_false; eauto. auto. congruence. 
+  eapply exit_if_false_false; eauto. traceEq. congruence. 
 Qed.
 
 Lemma transl_Sdowhile_stop_correct:
@@ -1075,7 +1161,7 @@ Lemma transl_Sdowhile_stop_correct:
         out_break_or_return out1 out ->
         exec_stmt_prop e m (Sdowhile a s) t m1 out).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
+  intros; red; intros. inv WT. monadInv TR.
   simpl.
   assert (outcome_block (transl_outcome 1 0 out1) <> Out_normal).
     inversion H1; simpl; congruence.
@@ -1087,22 +1173,19 @@ Qed.
 
 Lemma transl_Sdowhile_loop_correct:
        (forall (e : Csem.env) (m : mem) (s : statement) (a : Csyntax.expr)
-          (m1 m2 m3 : mem) (t1 t2 t3 : trace) (out out1 : Csem.outcome)
-          (v : val),
+          (m1 m2 : mem) (t1 t2 : trace) (out out1 : Csem.outcome) (v : val),
         Csem.exec_stmt ge e m s t1 m1 out1 ->
         exec_stmt_prop e m s t1 m1 out1 ->
         out_normal_or_continue out1 ->
-        Csem.eval_expr ge e m1 a t2 m2 v ->
-        eval_expr_prop e m1 a t2 m2 v ->
+        Csem.eval_expr ge e m1 a v ->
         is_true v (typeof a) ->
-        Csem.exec_stmt ge e m2 (Sdowhile a s) t3 m3 out ->
-        exec_stmt_prop e m2 (Sdowhile a s) t3 m3 out ->
-        exec_stmt_prop e m (Sdowhile a s) (t1 ** t2 ** t3) m3 out).
+        Csem.exec_stmt ge e m1 (Sdowhile a s) t2 m2 out ->
+        exec_stmt_prop e m1 (Sdowhile a s) t2 m2 out ->
+        exec_stmt_prop e m (Sdowhile a s) (t1 ** t2) m2 out).
 Proof.
   intros; red; intros. 
-  exploit H6; eauto. intro NEXTITER.
-  inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  inversion NEXTITER; subst.
+  exploit H5; eauto. intro NEXTITER.
+  inv WT. monadInv TR. inversion NEXTITER; subst.
   apply exec_Sblock. 
   eapply exec_Sloop_loop. eapply exec_Sseq_continue.
   rewrite (transl_out_normal_or_continue _ H1).
@@ -1115,6 +1198,7 @@ Lemma transl_Sfor_start_correct:
        (forall (e : Csem.env) (m : mem) (s a1 : statement)
           (a2 : Csyntax.expr) (a3 : statement) (out : Csem.outcome)
           (m1 m2 : mem) (t1 t2 : trace),
+        a1 <> Csyntax.Sskip ->
         Csem.exec_stmt ge e m a1 t1 m1 Csem.Out_normal ->
         exec_stmt_prop e m a1 t1 m1 Csem.Out_normal ->
         Csem.exec_stmt ge e m1 (Sfor Csyntax.Sskip a2 a3 s) t2 m2 out ->
@@ -1122,101 +1206,88 @@ Lemma transl_Sfor_start_correct:
         exec_stmt_prop e m (Sfor a1 a2 a3 s) (t1 ** t2) m2 out).
 Proof.
   intros; red; intros.
-  exploit transl_stmt_Sfor_start; eauto. 
-  intros [ts1 [ts2 [A [B C]]]].
-  clear TR; subst ts. 
-  inversion WT; subst.
+  destruct (transl_stmt_Sfor_start _ _ _ _ _ _ _ TR H) as [ts1 [ts2 [EQ [TR1 TR2]]]].
+  subst ts.
+  inv WT.
   assert (WT': wt_stmt tyenv (Sfor Csyntax.Sskip a2 a3 s)).
     constructor; auto. constructor.
-  exploit H0; eauto. simpl. intro EXEC1.
-  exploit H2; eauto. intro EXEC2. 
-  assert (EXEC3: exec_stmt tprog te m1 ts2 t2 m2 (transl_outcome nbrk ncnt out)).
-    inversion EXEC2; subst.
-    inversion H5; subst. rewrite E0_left; auto.
-    inversion H11; subst. congruence.
-  eapply exec_Sseq_continue; eauto. 
+  exploit H1; eauto. simpl. intro EXEC1.
+  exploit H3; eauto. intro EXEC2.
+  eapply exec_Sseq_continue; eauto.  
 Qed.
 
 Lemma transl_Sfor_false_correct:
        (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr)
-          (a3 : statement) (t : trace) (v : val) (m1 : mem),
-        Csem.eval_expr ge e m a2 t m1 v ->
-        eval_expr_prop e m a2 t m1 v ->
+          (a3 : statement) (v : val),
+        Csem.eval_expr ge e m a2 v ->
         is_false v (typeof a2) ->
-        exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) t m1 Csem.Out_normal).
+        exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) E0 m Csem.Out_normal).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
+  intros; red; intros. inv WT.
+  rewrite transl_stmt_Sfor_not_start in TR; monadInv TR.
   simpl.
-  eapply exec_Sseq_continue. apply exec_Sskip.
   change Out_normal with (outcome_block (Out_exit 0)).
   apply exec_Sblock. apply exec_Sloop_stop. 
   apply exec_Sseq_stop. eapply exit_if_false_false; eauto. 
-  congruence. congruence. traceEq. 
+  congruence. congruence.  
 Qed.
 
 Lemma transl_Sfor_stop_correct:
        (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr)
-          (a3 : statement) (v : val) (m1 m2 : mem) (t1 t2 : trace)
-          (out2 out : Csem.outcome),
-        Csem.eval_expr ge e m a2 t1 m1 v ->
-        eval_expr_prop e m a2 t1 m1 v ->
+          (a3 : statement) (v : val) (m1 : mem) (t : trace)
+          (out1 out : Csem.outcome),
+        Csem.eval_expr ge e m a2 v ->
         is_true v (typeof a2) ->
-        Csem.exec_stmt ge e m1 s t2 m2 out2 ->
-        exec_stmt_prop e m1 s t2 m2 out2 ->
-        out_break_or_return out2 out ->
-        exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) (t1 ** t2) m2 out).
+        Csem.exec_stmt ge e m s t m1 out1 ->
+        exec_stmt_prop e m s t m1 out1 ->
+        out_break_or_return out1 out ->
+        exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) t m1 out).
 Proof.
-  intros; red; intros. inversion WT; clear WT; subst. simpl in TR; monadInv TR.
-  simpl.
-  assert (outcome_block (transl_outcome 1 0 out2) <> Out_normal).
-    inversion H4; simpl; congruence.
-  rewrite (transl_out_break_or_return _ _ nbrk ncnt H4). 
-  eapply exec_Sseq_continue. apply exec_Sskip.
+  intros; red; intros. inv WT.
+  rewrite transl_stmt_Sfor_not_start in TR; monadInv TR.
+  assert (outcome_block (transl_outcome 1 0 out1) <> Out_normal).
+    inversion H3; simpl; congruence.
+  rewrite (transl_out_break_or_return _ _ nbrk ncnt H3). 
   apply exec_Sblock. apply exec_Sloop_stop. 
   eapply exec_Sseq_continue. eapply exit_if_false_true; eauto.
   apply exec_Sseq_stop. apply exec_Sblock. eauto. 
-  auto. reflexivity. auto. traceEq. 
+  auto. reflexivity. auto. 
 Qed.
 
 Lemma transl_Sfor_loop_correct:
        (forall (e : Csem.env) (m : mem) (s : statement) (a2 : Csyntax.expr)
-          (a3 : statement) (v : val) (m1 m2 m3 m4 : mem)
-          (t1 t2 t3 t4 : trace) (out2 out : Csem.outcome),
-        Csem.eval_expr ge e m a2 t1 m1 v ->
-        eval_expr_prop e m a2 t1 m1 v ->
+          (a3 : statement) (v : val) (m1 m2 m3 : mem) (t1 t2 t3 : trace)
+          (out1 out : Csem.outcome),
+        Csem.eval_expr ge e m a2 v ->
         is_true v (typeof a2) ->
-        Csem.exec_stmt ge e m1 s t2 m2 out2 ->
-        exec_stmt_prop e m1 s t2 m2 out2 ->
-        out_normal_or_continue out2 ->
-        Csem.exec_stmt ge e m2 a3 t3 m3 Csem.Out_normal ->
-        exec_stmt_prop e m2 a3 t3 m3 Csem.Out_normal ->
-        Csem.exec_stmt ge e m3 (Sfor Csyntax.Sskip a2 a3 s) t4 m4 out ->
-        exec_stmt_prop e m3 (Sfor Csyntax.Sskip a2 a3 s) t4 m4 out ->
-        exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s)
-          (t1 ** t2 ** t3 ** t4) m4 out).
+        Csem.exec_stmt ge e m s t1 m1 out1 ->
+        exec_stmt_prop e m s t1 m1 out1 ->
+        out_normal_or_continue out1 ->
+        Csem.exec_stmt ge e m1 a3 t2 m2 Csem.Out_normal ->
+        exec_stmt_prop e m1 a3 t2 m2 Csem.Out_normal ->
+        Csem.exec_stmt ge e m2 (Sfor Csyntax.Sskip a2 a3 s) t3 m3 out ->
+        exec_stmt_prop e m2 (Sfor Csyntax.Sskip a2 a3 s) t3 m3 out ->
+        exec_stmt_prop e m (Sfor Csyntax.Sskip a2 a3 s) (t1 ** t2 ** t3) m3 out).
 Proof.
   intros; red; intros. 
-  exploit H8; eauto. intro NEXTITER.
-  inversion WT; clear WT; subst. simpl in TR; monadInv TR.
+  exploit H7; eauto. intro NEXTITER.
+  inv WT.
+  rewrite transl_stmt_Sfor_not_start in TR; monadInv TR.
   inversion NEXTITER; subst.
-  inversion H11; subst.
-  inversion H18; subst.   
-  eapply exec_Sseq_continue. apply exec_Sskip.
   apply exec_Sblock. 
   eapply exec_Sloop_loop. eapply exec_Sseq_continue.
   eapply exit_if_false_true; eauto.
   eapply exec_Sseq_continue.
-  rewrite (transl_out_normal_or_continue _ H4).
+  rewrite (transl_out_normal_or_continue _ H3).
   apply exec_Sblock. eauto. 
-  red in H6; simpl in H6; eauto.
+  red in H5; simpl in H5; eauto.
   reflexivity. reflexivity. eassumption. 
-  reflexivity. traceEq. 
-  inversion H17. congruence.
+  traceEq. 
 Qed.
 
 Lemma transl_lblstmts_switch:
-  forall e m0 t1 m1 n nbrk ncnt tyenv te t2 m2 out sl body ts,
-  exec_stmt tprog te m0 body t1 m1 
+  forall e m0 m1 n nbrk ncnt tyenv te t0 t m2 out sl body ts,
+  exec_stmt tprog te m0 body t0 m1 
     (Out_exit (switch_target n (lblstmts_length sl) (switch_table sl 0))) ->
   transl_lblstmts 
     (lblstmts_length sl)
@@ -1224,8 +1295,8 @@ Lemma transl_lblstmts_switch:
     sl (Sblock body) = OK ts ->
   wt_lblstmts tyenv sl ->
   match_env tyenv e te ->
-  exec_lblstmts_prop e m1 (select_switch n sl) t2 m2 out ->
-  Csharpminor.exec_stmt tprog te m0 ts (t1 ** t2) m2 
+  exec_lblstmts_prop e m1 (select_switch n sl) t m2 out ->
+  Csharpminor.exec_stmt tprog te m0 ts (t0 ** t) m2 
     (transl_outcome nbrk ncnt (outcome_switch out)).
 Proof.
   induction sl; intros.
@@ -1251,24 +1322,20 @@ Proof.
 Qed.
 
 Lemma transl_Sswitch_correct:
-       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t1 : trace)
-          (m1 : mem) (n : int) (sl : labeled_statements) (t2 : trace)
-          (m2 : mem) (out : Csem.outcome),
-        Csem.eval_expr ge e m a t1 m1 (Vint n) ->
-        eval_expr_prop e m a t1 m1 (Vint n) ->
-        exec_lblstmts ge e m1 (select_switch n sl) t2 m2 out ->
-        exec_lblstmts_prop e m1 (select_switch n sl) t2 m2 out ->
-        exec_stmt_prop e m (Csyntax.Sswitch a sl) (t1 ** t2) m2
-          (outcome_switch out)).
+       (forall (e : Csem.env) (m : mem) (a : Csyntax.expr) (t : trace)
+          (n : int) (sl : labeled_statements) (m1 : mem) (out : Csem.outcome),
+        Csem.eval_expr ge e m a (Vint n) ->
+        exec_lblstmts ge e m (select_switch n sl) t m1 out ->
+        exec_lblstmts_prop e m (select_switch n sl) t m1 out ->
+        exec_stmt_prop e m (Csyntax.Sswitch a sl) t m1 (outcome_switch out)).
 Proof.
   intros; red; intros.
-  inversion WT; clear WT; subst.
-  simpl in TR. monadInv TR. 
+  inv WT. monadInv TR.
   rewrite length_switch_table in EQ0. 
   replace (ncnt + lblstmts_length sl + 1)%nat
      with (S (lblstmts_length sl + ncnt))%nat in EQ0 by omega.
-  eapply transl_lblstmts_switch; eauto. 
-  constructor. eapply H0; eauto. 
+  change t with (E0 ** t). eapply transl_lblstmts_switch; eauto. 
+  constructor. eapply (transl_expr_correct _ _ _ _ MENV _ _ H); eauto. 
 Qed.
 
 Lemma transl_LSdefault_correct:
@@ -1278,9 +1345,7 @@ Lemma transl_LSdefault_correct:
         exec_stmt_prop e m s t m1 out ->
         exec_lblstmts_prop e m (LSdefault s) t m1 out).
 Proof.
-  intros; red; intros.
-  inversion WT; subst.
-  simpl in TR. monadInv TR.
+  intros; red; intros. inv WT. monadInv TR.
   replace (transl_outcome nbrk ncnt (outcome_switch out))
      with (outcome_block (transl_outcome 0 (S ncnt) out)).
   constructor. 
@@ -1299,11 +1364,9 @@ Lemma transl_LScase_fallthrough_correct:
         exec_lblstmts_prop e m1 ls t2 m2 out ->
         exec_lblstmts_prop e m (LScase n s ls) (t1 ** t2) m2 out).
 Proof.
-  intros; red; intros.
-  inversion WT; subst.
-  monadInv TR.
+  intros; red; intros. inv WT. monadInv TR. 
   assert (exec_stmt tprog te m0 (Sblock (Sseq body x)) 
-                  (t0 ** t1) m1 Out_normal).
+                          (t0 ** t1) m1 Out_normal).
   change Out_normal with
     (outcome_block (transl_outcome (S (lblstmts_length ls))
                                    (S (S (lblstmts_length ls + ncnt)))
@@ -1316,7 +1379,7 @@ Proof.
 Qed.
 
 Lemma transl_LScase_stop_correct:
-       (forall (e : Csem.env) (m : mem) (n : int) (s : statement)
+      (forall (e : Csem.env) (m : mem) (n : int) (s : statement)
           (ls : labeled_statements) (t : trace) (m1 : mem)
           (out : Csem.outcome),
         Csem.exec_stmt ge e m s t m1 out ->
@@ -1324,9 +1387,7 @@ Lemma transl_LScase_stop_correct:
         out <> Csem.Out_normal ->
         exec_lblstmts_prop e m (LScase n s ls) t m1 out).
 Proof.
-  intros; red; intros.
-  inversion WT; subst.
-  monadInv TR.
+  intros; red; intros. inv WT. monadInv TR.
   exploit H0; eauto. intro EXEC.
   destruct out; simpl; simpl in EXEC.
   (* out = Out_break *)
@@ -1378,8 +1439,7 @@ Lemma transl_funcall_internal_correct:
 Proof.
   intros; red; intros.
   (* Exploitation of typing hypothesis *)
-  inversion WT; clear WT; subst. 
-  inversion H6; clear H6; subst.
+  inv WT. inv H6.
   (* Exploitation of translation hypothesis *)
   monadInv TR. 
   monadInv EQ.
@@ -1419,38 +1479,55 @@ Theorem transl_funcall_correct:
   Csem.eval_funcall ge m f l t m0 v ->
   eval_funcall_prop m f l t m0 v.
 Proof
-  (Csem.eval_funcall_ind6 ge
-         eval_expr_prop
-         eval_lvalue_prop
-         eval_exprlist_prop
+  (Csem.eval_funcall_ind3 ge
+         exec_stmt_prop
+         exec_lblstmts_prop
+         eval_funcall_prop
+
+         transl_Sskip_correct
+         transl_Sassign_correct
+         transl_Scall_None_correct
+         transl_Scall_Some_correct
+         transl_Ssequence_1_correct
+         transl_Ssequence_2_correct
+         transl_Sifthenelse_true_correct
+         transl_Sifthenelse_false_correct
+         transl_Sreturn_none_correct
+         transl_Sreturn_some_correct
+         transl_Sbreak_correct
+         transl_Scontinue_correct
+         transl_Swhile_false_correct
+         transl_Swhile_stop_correct
+         transl_Swhile_loop_correct
+         transl_Sdowhile_false_correct
+         transl_Sdowhile_stop_correct
+         transl_Sdowhile_loop_correct
+         transl_Sfor_start_correct
+         transl_Sfor_false_correct
+         transl_Sfor_stop_correct
+         transl_Sfor_loop_correct
+         transl_Sswitch_correct
+         transl_LSdefault_correct
+         transl_LScase_fallthrough_correct
+         transl_LScase_stop_correct
+         transl_funcall_internal_correct
+         transl_funcall_external_correct).
+
+Theorem transl_stmt_correct:
+  forall (e: Csem.env) (m1: mem) (s: Csyntax.statement) (t: trace)
+         (m2: mem) (out: Csem.outcome),
+  Csem.exec_stmt ge e m1 s t m2 out ->
+  exec_stmt_prop e m1 s t m2 out.
+Proof
+  (Csem.exec_stmt_ind3 ge
          exec_stmt_prop
          exec_lblstmts_prop
          eval_funcall_prop
 
-         transl_Econst_int_correct
-         transl_Econst_float_correct
-         transl_Elvalue_correct
-         transl_Eaddrof_correct
-         transl_Esizeof_correct
-         transl_Eunop_correct
-         transl_Ebinop_correct
-         transl_Eorbool_1_correct
-         transl_Eorbool_2_correct
-         transl_Eandbool_1_correct
-         transl_Eandbool_2_correct
-         transl_Ecast_correct
-         transl_Ecall_correct
-         transl_Evar_local_correct
-         transl_Evar_global_correct
-         transl_Ederef_correct
-         transl_Eindex_correct
-         transl_Efield_struct_correct
-         transl_Efield_union_correct
-         transl_Enil_correct
-         transl_Econs_correct
          transl_Sskip_correct
-         transl_Sexpr_correct
          transl_Sassign_correct
+         transl_Scall_None_correct
+         transl_Scall_Some_correct
          transl_Ssequence_1_correct
          transl_Ssequence_2_correct
          transl_Sifthenelse_true_correct
@@ -1476,41 +1553,287 @@ Proof
          transl_funcall_internal_correct
          transl_funcall_external_correct).
 
+(** ** Semantic preservation for divergence *)
+
+Lemma transl_funcall_divergence_correct:
+  forall m1 f params t tf,
+  Csem.evalinf_funcall ge m1 f params t ->
+  wt_fundef (global_typenv prog) f ->
+  transl_fundef f = OK tf ->
+  Csharpminor.evalinf_funcall tprog m1 tf params t.
+Proof.
+  cofix FUNCALL.
+  assert (STMT: 
+    forall e m1 s t,
+    Csem.execinf_stmt ge e m1 s t ->
+    forall tyenv nbrk ncnt ts te
+      (WT: wt_stmt tyenv s)
+      (TR: transl_statement nbrk ncnt s = OK ts)   
+      (MENV: match_env tyenv e te),
+    Csharpminor.execinf_stmt tprog te m1 ts t).
+  cofix STMT.
+  assert(LBLSTMT:
+  forall s ncnt body ts tyenv e te m0 t0 m1 t1 n,
+  transl_lblstmts (lblstmts_length s)
+                  (S (lblstmts_length s + ncnt))
+                  s body = OK ts ->
+  wt_lblstmts tyenv s ->
+  match_env tyenv e te ->
+      (exec_stmt tprog te m0 body t0 m1
+        (outcome_block (Out_exit
+           (switch_target n (lblstmts_length s) (switch_table s 0))))
+       /\ execinf_lblstmts ge e m1 (select_switch n s) t1)
+   \/ (exec_stmt tprog te m0 body t0 m1 Out_normal
+       /\ execinf_lblstmts ge e m1 s t1) ->
+  execinf_stmt_N tprog (lblstmts_length s) te m0 ts (t0 *** t1)).
+
+  cofix LBLSTMT; intros.
+  destruct s; simpl in *; monadInv H; inv H0.
+  (* 1. LSdefault *)
+  assert (exec_stmt tprog te m0 body t0 m1 Out_normal) by tauto.
+  assert (execinf_lblstmts ge e m1 (LSdefault s) t1) by tauto.
+  clear H2. inv H0.  
+  change (Sblock (Sseq body x))
+    with ((fun z => Sblock z) (Sseq body x)).
+  apply execinf_context. 
+  eapply execinf_Sseq_2. eauto. eapply STMT; eauto. auto.
+  constructor.
+  (* 2. LScase *)
+  elim H2; clear H2.
+  (* 2.1 searching for the case *)
+  rewrite (Int.eq_sym i n). 
+  destruct (Int.eq n i).
+  (* 2.1.1 found it! *)
+  intros [A B]. inv B.
+  (* 2.1.1.1 we diverge because of this case *)
+  destruct (transl_lblstmts_context _ _ _ _ _ EQ0) as [ctx [CTX EQ1]].
+  rewrite EQ1. apply execinf_context; auto. 
+  apply execinf_Sblock. eapply execinf_Sseq_2. eauto. 
+  eapply STMT; eauto. auto.
+  (* 2.1.1.2 we diverge later, after falling through *)
+  simpl. apply execinf_sleep.
+  replace (t0 *** t2 *** t3) with ((t0 ** t2) *** t3). 
+  eapply LBLSTMT with (n := n); eauto. right. split.
+  change Out_normal with (outcome_block Out_normal). 
+  apply exec_Sblock.
+  eapply exec_Sseq_continue. eauto. 
+  change Out_normal with (transl_outcome (S (lblstmts_length s0)) (S (S (lblstmts_length s0 + ncnt))) Csem.Out_normal).
+  eapply (transl_stmt_correct _ _ _ _ _ _ H8); eauto.
+  auto. auto. traceEq.
+  (* 2.1.2 still searching *)
+  rewrite switch_target_table_shift. intros [A B].
+  apply execinf_sleep.
+  eapply LBLSTMT with (n := n); eauto. left. split.
+  fold (outcome_block (Out_exit (switch_target n (lblstmts_length s0) (switch_table s0 0)))).
+  apply exec_Sblock. apply exec_Sseq_stop. eauto. congruence.
+  auto.
+  (* 2.2 found the case already, falling through next cases *)
+  intros [A B]. inv B.
+  (* 2.2.1 we diverge because of this case *)
+  destruct (transl_lblstmts_context _ _ _ _ _ EQ0) as [ctx [CTX EQ1]].
+  rewrite EQ1. apply execinf_context; auto. 
+  apply execinf_Sblock. eapply execinf_Sseq_2. eauto. 
+  eapply STMT; eauto. auto.
+  (* 2.2.2 we diverge later *)
+  simpl. apply execinf_sleep.
+  replace (t0 *** t2 *** t3) with ((t0 ** t2) *** t3). 
+  eapply LBLSTMT with (n := n); eauto. right. split.
+  change Out_normal with (outcome_block Out_normal). 
+  apply exec_Sblock.
+  eapply exec_Sseq_continue. eauto. 
+  change Out_normal with (transl_outcome (S (lblstmts_length s0)) (S (S (lblstmts_length s0 + ncnt))) Csem.Out_normal).
+  eapply (transl_stmt_correct _ _ _ _ _ _ H8); eauto.
+  auto. auto. traceEq.
+
+
+  intros. inv H; inv WT; try (generalize TR; intro TR'; monadInv TR').
+  (* Scall *)
+  simpl in TR.
+  caseEq (classify_fun (typeof a)); intros; rewrite H in TR; monadInv TR.
+  destruct (functions_translated _ _ H2) as [tf [TFIND TFD]].
+  eapply execinf_Scall. 
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.
+  eapply (transl_exprlist_correct _ _ _ _ MENV _ _ H1); eauto.
+  eauto. 
+  eapply transl_fundef_sig1; eauto. rewrite H3; auto. 
+  eapply FUNCALL; eauto.
+  eapply functions_well_typed; eauto.
+  (* Sseq 1 *)
+  apply execinf_Sseq_1. eapply STMT; eauto. 
+  (* Sseq 2 *)
+  eapply execinf_Sseq_2. 
+  change Out_normal with (transl_outcome nbrk ncnt Csem.Out_normal).
+  eapply (transl_stmt_correct _ _ _ _ _ _ H0); eauto.
+  eapply STMT; eauto. auto.
+  (* Sifthenelse, true *)
+  assert (eval_expr tprog te m1 x v1).
+    eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.
+  destruct (make_boolean_correct_true _ _ _ _ _ _ H H1) as [vb [A B]].
+  eapply execinf_Sifthenelse. eauto. apply Val.bool_of_true_val; eauto.
+  auto. eapply STMT; eauto.
+  (* Sifthenelse, false *)
+  assert (eval_expr tprog te m1 x v1).
+    eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.
+  destruct (make_boolean_correct_false _ _ _ _ _ _ H H1) as [vb [A B]].
+  eapply execinf_Sifthenelse. eauto. apply Val.bool_of_false_val; eauto.
+  auto. eapply STMT; eauto.
+  (* Swhile, body *)
+  apply execinf_Sblock. apply execinf_Sloop_body.  
+  eapply execinf_Sseq_2. eapply exit_if_false_true; eauto. 
+  apply execinf_Sblock. eapply STMT; eauto. traceEq.
+  (* Swhile, loop *)
+  apply execinf_Sblock. eapply execinf_Sloop_block.
+  eapply exec_Sseq_continue. eapply exit_if_false_true; eauto.
+  rewrite (transl_out_normal_or_continue out1 H3). 
+  apply exec_Sblock. 
+  eapply (transl_stmt_correct _ _ _ _ _ _ H2); eauto. reflexivity.
+  eapply STMT with (nbrk := 1%nat) (ncnt := 0%nat); eauto.
+  constructor; eauto.
+  traceEq.
+  (* Sdowhile, body *)
+  apply execinf_Sblock. apply execinf_Sloop_body.  
+  apply execinf_Sseq_1. apply execinf_Sblock.
+  eapply STMT; eauto.
+  (* Sdowhile, loop *)
+  apply execinf_Sblock. eapply execinf_Sloop_block.
+  eapply exec_Sseq_continue.
+  rewrite (transl_out_normal_or_continue out1 H1). 
+  apply exec_Sblock. 
+  eapply (transl_stmt_correct _ _ _ _ _ _ H0); eauto. 
+  eapply exit_if_false_true; eauto. reflexivity.
+  eapply STMT with (nbrk := 1%nat) (ncnt := 0%nat); eauto.
+  constructor; auto.
+  traceEq.
+  (* Sfor start 1 *)
+  simpl in TR. destruct (is_Sskip a1). 
+  subst a1. inv H0.
+  monadInv TR. 
+  apply execinf_Sseq_1. eapply STMT; eauto.
+  (* Sfor start 2 *)
+  destruct (transl_stmt_Sfor_start _ _ _ _ _ _ _ TR H0) as [ts1 [ts2 [EQ [TR1 TR2]]]].
+  subst ts. 
+  eapply execinf_Sseq_2. 
+  change Out_normal with (transl_outcome nbrk ncnt Csem.Out_normal).
+  eapply (transl_stmt_correct _ _ _ _ _ _ H1); eauto.
+  eapply STMT; eauto. 
+    constructor; auto. constructor.
+  auto.
+  (* Sfor_body *)
+  rewrite transl_stmt_Sfor_not_start in TR; monadInv TR.
+  apply execinf_Sblock. apply execinf_Sloop_body.
+  eapply execinf_Sseq_2. 
+  eapply exit_if_false_true; eauto.
+  apply execinf_Sseq_1. apply execinf_Sblock. 
+  eapply STMT; eauto.
+  traceEq.
+  (* Sfor next *)
+  rewrite transl_stmt_Sfor_not_start in TR; monadInv TR.
+  apply execinf_Sblock. apply execinf_Sloop_body.
+  eapply execinf_Sseq_2. 
+  eapply exit_if_false_true; eauto.
+  eapply execinf_Sseq_2.
+  rewrite (transl_out_normal_or_continue out1 H3). 
+  apply exec_Sblock. 
+  eapply (transl_stmt_correct _ _ _ _ _ _ H2); eauto.
+  eapply STMT; eauto.
+  reflexivity. traceEq. 
+  (* Sfor loop *)
+  generalize TR. rewrite transl_stmt_Sfor_not_start; intro TR'; monadInv TR'.
+  apply execinf_Sblock. eapply execinf_Sloop_block.
+  eapply exec_Sseq_continue.
+  eapply exit_if_false_true; eauto.
+  eapply exec_Sseq_continue.
+  rewrite (transl_out_normal_or_continue out1 H3). 
+  apply exec_Sblock. 
+  eapply (transl_stmt_correct _ _ _ _ _ _ H2); eauto.
+  change Out_normal with (transl_outcome nbrk ncnt Csem.Out_normal).
+  eapply (transl_stmt_correct _ _ _ _ _ _ H4); eauto.
+  reflexivity. reflexivity. 
+  eapply STMT; eauto. 
+    constructor; auto.
+  traceEq.
+  (* Sswitch *)
+  apply execinf_stutter with (lblstmts_length sl).
+  rewrite length_switch_table in EQ0.
+  replace (ncnt + lblstmts_length sl + 1)%nat
+     with (S (lblstmts_length sl + ncnt))%nat in EQ0 by omega.
+  change t with (E0 *** t).
+  eapply LBLSTMT; eauto.
+  left. split. apply exec_Sblock. constructor. 
+  eapply (transl_expr_correct _ _ _ _ MENV _ _ H0); eauto.
+  auto. 
+
+  (* Functions *)
+  intros. inv H. 
+  (* Exploitation of typing hypothesis *)
+  inv H0. inv H6. 
+  (* Exploitation of translation hypothesis *)
+  monadInv H1. monadInv EQ.
+  (* Allocation of variables *)
+  assert (match_env (global_typenv prog) Csem.empty_env Csharpminor.empty_env).
+    apply match_globalenv_match_env_empty. apply match_global_typenv. 
+  generalize (transl_fn_variables _ _ (signature_of_function f0) _ _ x2 EQ0 EQ).
+  intro. 
+  destruct (match_env_alloc_variables _ _ _ _ _ _ H2 _ _ _ H1 H5)
+  as [te [ALLOCVARS MATCHENV]].
+  (* Execution *)
+  econstructor; simpl.
+  eapply transl_names_norepet; eauto. 
+  eexact ALLOCVARS.
+  eapply bind_parameters_match; eauto.
+  eapply STMT; eauto. 
+Qed.
+
 End CORRECTNESS.
 
 (** Semantic preservation for whole programs. *)
 
 Theorem transl_program_correct:
-  forall prog tprog t r,
+  forall prog tprog beh,
   transl_program prog = OK tprog ->
   Ctyping.wt_program prog ->
-  Csem.exec_program prog t r ->
-  Csharpminor.exec_program tprog t r.
+  Csem.exec_program prog beh ->
+  Csharpminor.exec_program tprog beh.
 Proof.
-  intros until r. intros TRANSL WT [b [f [m1 [FINDS [FINDF EVAL]]]]].
-  inversion WT; subst.
-
+  intros. inversion H0; subst. inv H1.
+  (* Termination *)
   assert (exists targs, type_of_fundef f = Tfunction targs (Tint I32 Signed)).
     apply wt_program_main.
     eapply Genv.find_funct_ptr_symbol_inversion; eauto. 
-  elim H; clear H; intros targs TYP.
+  elim H1; clear H1; intros targs TYP.
   assert (targs = Tnil).
-    inversion EVAL; subst; simpl in TYP.
-    inversion H0; subst. injection TYP. rewrite <- H6. simpl; auto.
-    inversion TYP; subst targs0 tres. inversion H. simpl in H0. 
-    inversion H0. destruct targs; simpl in H8; congruence.
+    inv H4; simpl in TYP.
+    inv H5. injection TYP. rewrite <- H10. simpl. auto.
+    inv TYP. inv H1. 
+    destruct targs; simpl in H4. auto. inv H4. 
   subst targs.
   exploit function_ptr_translated; eauto. intros [tf [TFINDF TRANSLFD]].
-  exists b; exists tf; exists m1.
-  split. 
-    rewrite (symbols_preserved _ _ TRANSL).
-    rewrite (transform_partial_program2_main transl_fundef transl_globvar prog TRANSL). auto.
-  split. auto.
-  split. 
-    generalize (transl_fundef_sig2 _ _ _ _ TRANSLFD TYP). simpl; auto.
-  rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog TRANSL).
-  generalize (transl_funcall_correct _ _ WT TRANSL _ _ _ _ _ _ EVAL).
-  intro. eapply H. 
+  apply program_terminates with b tf m1.
+  rewrite (symbols_preserved _ _ H).
+  rewrite (transform_partial_program2_main transl_fundef transl_globvar prog H). auto.
+  auto.
+  generalize (transl_fundef_sig2 _ _ _ _ TRANSLFD TYP). simpl; auto.
+  rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog H).
+  generalize (transl_funcall_correct _ _ H0 H _ _ _ _ _ _ H4).
+  intro. eapply H1. 
   eapply function_ptr_well_typed; eauto.
   auto.
+  (* Divergence *)
+  assert (exists targs, type_of_fundef f = Tfunction targs (Tint I32 Signed)).
+    apply wt_program_main.
+    eapply Genv.find_funct_ptr_symbol_inversion; eauto. 
+  elim H1; clear H1; intros targs TYP.
+  assert (targs = Tnil).
+    inv H4; simpl in TYP.
+    inv H5. injection TYP. rewrite <- H9. simpl. auto.
+  subst targs.
+  exploit function_ptr_translated; eauto. intros [tf [TFINDF TRANSLFD]].
+  apply program_diverges with b tf.
+  rewrite (symbols_preserved _ _ H).
+  rewrite (transform_partial_program2_main transl_fundef transl_globvar prog H). auto.
+  auto.
+  generalize (transl_fundef_sig2 _ _ _ _ TRANSLFD TYP). simpl; auto.
+  rewrite (@Genv.init_mem_transf_partial2 _ _ _ _ transl_fundef transl_globvar prog tprog H).
+  eapply transl_funcall_divergence_correct; eauto. 
+  eapply function_ptr_well_typed; eauto.
 Qed.
diff --git a/cfrontend/Csyntax.v b/cfrontend/Csyntax.v
index 3866669a4..31d1d873e 100644
--- a/cfrontend/Csyntax.v
+++ b/cfrontend/Csyntax.v
@@ -136,15 +136,10 @@ with expr_descr : Set :=
   | Ebinop: binary_operation -> expr -> expr -> expr_descr (**r binary operation *)
   | Ecast: type -> expr -> expr_descr   (**r type cast ([(ty) e]) *)
   | Eindex: expr -> expr -> expr_descr  (**r array indexing ([e1[e2]]) *)
-  | Ecall: expr -> exprlist -> expr_descr  (**r function call *)
   | Eandbool: expr -> expr -> expr_descr (**r sequential and ([&&]) *)
   | Eorbool: expr -> expr -> expr_descr (**r sequential or ([||]) *)
   | Esizeof: type -> expr_descr         (**r size of a type *)
-  | Efield: expr -> ident -> expr_descr (**r access to a member of a struct or union *)
-
-with exprlist : Set :=
-  | Enil: exprlist
-  | Econs: expr -> exprlist -> exprlist.
+  | Efield: expr -> ident -> expr_descr. (**r access to a member of a struct or union *)
 
 (** Extract the type part of a type-annotated Clight expression. *)
 
@@ -160,8 +155,8 @@ Definition typeof (e: expr) : type :=
 
 Inductive statement : Set :=
   | Sskip : statement                   (**r do nothing *)
-  | Sexpr : expr -> statement           (**r evaluate expression for its side-effects *)
   | Sassign : expr -> expr -> statement (**r assignment [lvalue = rvalue] *)
+  | Scall: option expr -> expr -> list expr -> statement (**r function call *)
   | Ssequence : statement -> statement -> statement  (**r sequence *)
   | Sifthenelse : expr  -> statement -> statement -> statement (**r conditional *)
   | Swhile : expr -> statement -> statement   (**r [while] loop *)
diff --git a/cfrontend/Ctyping.v b/cfrontend/Ctyping.v
index cb572c09e..72c4edf2b 100644
--- a/cfrontend/Ctyping.v
+++ b/cfrontend/Ctyping.v
@@ -47,10 +47,6 @@ Inductive wt_expr: expr -> Prop :=
   | wt_Eindex: forall e1 e2 ty,
      wt_expr e1 -> wt_expr e2 ->
      wt_expr (Expr (Eindex e1 e2) ty)
-  | wt_Ecall: forall e1 el ty,
-     wt_expr e1 ->
-     wt_exprlist el ->
-     wt_expr (Expr (Ecall e1 el) ty)
   | wt_Eandbool: forall e1 e2 ty,
      wt_expr e1 -> wt_expr e2 ->
      wt_expr (Expr (Eandbool e1 e2) ty)
@@ -61,23 +57,32 @@ Inductive wt_expr: expr -> Prop :=
      wt_expr (Expr (Esizeof ty') ty)
   | wt_Efield: forall e id ty,
      wt_expr e ->
-     wt_expr (Expr (Efield e id) ty)
+     wt_expr (Expr (Efield e id) ty).
+
+Inductive wt_optexpr: option expr -> Prop :=
+  | wt_Enone:
+      wt_optexpr None
+  | wt_Esome: forall e,
+      wt_expr e ->
+      wt_optexpr (Some e).
 
-with wt_exprlist: exprlist -> Prop :=
+Inductive wt_exprlist: list expr -> Prop :=
   | wt_Enil:
-     wt_exprlist Enil
+     wt_exprlist nil
   | wt_Econs: forall e el,
-     wt_expr e -> wt_exprlist el -> wt_exprlist (Econs e el).
+     wt_expr e -> wt_exprlist el -> wt_exprlist (e :: el).
 
 Inductive wt_stmt: statement -> Prop :=
   | wt_Sskip:
      wt_stmt Sskip
-  | wt_Sexpr: forall e,
-     wt_expr e ->
-     wt_stmt (Sexpr e)
   | wt_Sassign: forall e1 e2,
      wt_expr e1 -> wt_expr e2 ->
      wt_stmt (Sassign e1 e2)
+  | wt_Scall: forall lhs e1 el,
+     wt_optexpr lhs ->
+     wt_expr e1 ->
+     wt_exprlist el ->
+     wt_stmt (Scall lhs e1 el)
   | wt_Ssequence: forall s1 s2,
      wt_stmt s1 -> wt_stmt s2 ->
      wt_stmt (Ssequence s1 s2)
@@ -97,11 +102,9 @@ Inductive wt_stmt: statement -> Prop :=
      wt_stmt Sbreak
   | wt_Scontinue:
      wt_stmt Scontinue
-  | wt_Sreturn_some: forall e,
-     wt_expr e ->
-     wt_stmt (Sreturn (Some e))
-  | wt_Sreturn_none:
-     wt_stmt (Sreturn None)
+  | wt_Sreturn: forall opte,
+     wt_optexpr opte ->
+     wt_stmt (Sreturn opte)
   | wt_Sswitch: forall e sl,
      wt_expr e -> wt_lblstmts sl ->
      wt_stmt (Sswitch e sl)
@@ -282,49 +285,35 @@ with typecheck_exprdescr (a: Csyntax.expr_descr) (ty: type) {struct a} : bool :=
   | Csyntax.Ebinop op b c => typecheck_expr b && typecheck_expr c
   | Csyntax.Ecast ty b => typecheck_expr b
   | Csyntax.Eindex b c => typecheck_expr b && typecheck_expr c
-  | Csyntax.Ecall b cl => typecheck_expr b && typecheck_exprlist cl
   | Csyntax.Eandbool b c => typecheck_expr b && typecheck_expr c
   | Csyntax.Eorbool b c => typecheck_expr b && typecheck_expr c
   | Csyntax.Esizeof ty => true
   | Csyntax.Efield b i => typecheck_expr b
-  end
+  end.
 
-with typecheck_exprlist (al: Csyntax.exprlist): bool :=
+Fixpoint typecheck_exprlist (al: list Csyntax.expr): bool :=
   match al with
-  | Csyntax.Enil => true
-  | Csyntax.Econs a1 a2 => typecheck_expr a1 && typecheck_exprlist a2
+  | nil => true
+  | a1 :: a2 => typecheck_expr a1 && typecheck_exprlist a2
+  end.
+
+Definition typecheck_optexpr (opta: option Csyntax.expr): bool :=
+  match opta with
+  | None => true
+  | Some a => typecheck_expr a
   end.
 
-Scheme expr_ind_3 := Induction for expr Sort Prop
-  with expr_descr_ind_3 := Induction for expr_descr Sort Prop
-  with exprlist_ind_3 := Induction for exprlist Sort Prop.
+Scheme expr_ind_2 := Induction for expr Sort Prop
+  with expr_descr_ind_2 := Induction for expr_descr Sort Prop.
 
 Lemma typecheck_expr_correct:
   forall a, typecheck_expr a = true -> wt_expr env a.
 Proof.
-  apply (expr_ind_3 (fun a => typecheck_expr a = true -> wt_expr env a)
-                    (fun a => forall ty, typecheck_exprdescr a ty = true -> wt_expr env (Expr a ty))
-                    (fun a => typecheck_exprlist a = true -> wt_exprlist env a));
-  simpl; intros; TrueInv.
-  auto.
-  constructor.
-  constructor.
-  constructor. destruct (env!i). decEq; symmetry; apply eq_type_correct; auto.
+  apply (expr_ind_2 (fun a => typecheck_expr a = true -> wt_expr env a)
+                    (fun a => forall ty, typecheck_exprdescr a ty = true -> wt_expr env (Expr a ty)));
+  simpl; intros; TrueInv; try constructor; auto.
+  destruct (env!i). decEq; symmetry; apply eq_type_correct; auto.
   discriminate.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  constructor; auto.
-  auto.
-  constructor; auto.
-  constructor; auto.
-  constructor.
-  constructor; auto.
 Qed.
 
 Lemma typecheck_exprlist_correct:
@@ -335,11 +324,19 @@ Proof.
   TrueInv. constructor; auto. apply typecheck_expr_correct; auto.
 Qed.
 
+Lemma typecheck_optexpr_correct:
+  forall a, typecheck_optexpr a = true -> wt_optexpr env a.
+Proof.
+  destruct a; simpl; intros.
+  constructor. apply typecheck_expr_correct; auto.
+  constructor.
+Qed.
+
 Fixpoint typecheck_stmt (s: Csyntax.statement) {struct s} : bool :=
   match s with
   | Csyntax.Sskip => true
-  | Csyntax.Sexpr e => typecheck_expr e
   | Csyntax.Sassign b c => typecheck_expr b && typecheck_expr c
+  | Csyntax.Scall a b cl => typecheck_optexpr a && typecheck_expr b && typecheck_exprlist cl
   | Csyntax.Ssequence s1 s2 => typecheck_stmt s1 && typecheck_stmt s2
   | Csyntax.Sifthenelse e s1 s2 =>
       typecheck_expr e && typecheck_stmt s1 && typecheck_stmt s2
@@ -368,10 +365,11 @@ Lemma typecheck_stmt_correct:
   forall s, typecheck_stmt s = true -> wt_stmt env s.
 Proof.
   generalize typecheck_expr_correct; intro.
+  generalize typecheck_exprlist_correct; intro.
+  generalize typecheck_optexpr_correct; intro.
   apply (stmt_ind_2 (fun s => typecheck_stmt s = true -> wt_stmt env s)
                     (fun s => typecheck_lblstmts s = true -> wt_lblstmts env s));
-  simpl; intros; TrueInv; try constructor; auto.
-  destruct o; constructor; auto.
+  simpl; intros; TrueInv; constructor; auto.
 Qed.
 
 End TYPECHECKING.
diff --git a/common/Complements.v b/common/Complements.v
index 5280947ba..2263f4ece 100644
--- a/common/Complements.v
+++ b/common/Complements.v
@@ -8,8 +8,11 @@ Require Import Values.
 Require Import Events.
 Require Import Globalenvs.
 Require Import Smallstep.
+Require Import Csyntax.
+Require Import Csem.
 Require Import PPC.
 Require Import Main.
+Require Import Errors.
 
 (** * Determinism of PPC semantics *)
 
@@ -555,22 +558,29 @@ Proof.
   auto. apply traceinf_sim_sym; auto. apply traceinf_sim_refl.
 Qed.
 
-(** * Strong semantic preservation property *)
+(** * Additional semantic preservation property *)
 
-Require Import Errors.
+(** Combining the semantic preservation theorem from module [Main]
+  with the determinism of PPC executions, we easily obtain
+  additional, stronger semantic preservation properties.
+  The first property states that, when compiling a Clight
+  program that has well-defined semantics, all possible executions
+  of the resulting PPC code correspond to an execution of
+  the source Clight program, in the sense of the [matching_behaviors]
+  predicate. *)
 
-Theorem transf_rtl_program_correct_strong:
+Theorem transf_c_program_correct_strong:
   forall p tp b w,
-  transf_rtl_program p = OK tp ->
-  RTL.exec_program p b ->
+  transf_c_program p = OK tp ->
+  Csem.exec_program p b ->
   possible_behavior w b ->
   (exists b', exec_program' tp w b')
 /\(forall b', exec_program' tp w b' ->
-   exists b0, RTL.exec_program p b0 /\ matching_behaviors b0 b').
+   exists b0, Csem.exec_program p b0 /\ matching_behaviors b0 b').
 Proof.
   intros.
   assert (PPC.exec_program tp b).
-    eapply transf_rtl_program_correct; eauto.
+    eapply transf_c_program_correct; eauto.
   exploit exec_program_program'; eauto. 
   intros [b' [A B]].
   split. exists b'; auto.
@@ -578,3 +588,52 @@ Proof.
   apply matching_behaviors_same with b'. auto.
   eapply exec_program'_deterministic; eauto.
 Qed.
+
+Section SPECS_PRESERVED.
+
+(** The second additional results shows that if one execution
+  of the source Clight program satisfies a given specification
+  (a predicate on the observable behavior of the program),
+  then all executions of the produced PPC program satisfy
+  this specification as well.  *) 
+
+Variable spec: program_behavior -> Prop.
+
+(* Since the execution trace for a diverging Clight program
+   is not uniquely defined (the trace can contain events that
+   the program will never perform because it loops earlier),
+   this result holds only if the specification is closed under
+   prefixes in the case of diverging executions.  This is the
+   case for all safety properties (some undesirable event never
+   occurs), but not for liveness properties (some desirable event
+   always occurs). *)
+
+Hypothesis spec_safety:
+  forall T T', traceinf_prefix T T' -> spec (Diverges T') -> spec (Diverges T).
+
+Theorem transf_c_program_preserves_spec:
+  forall p tp b w,
+  transf_c_program p = OK tp ->
+  Csem.exec_program p b ->
+  possible_behavior w b ->
+  spec b ->
+  (exists b', exec_program' tp w b')
+/\(forall b', exec_program' tp w b' -> spec b').
+Proof.
+  intros.
+  assert (PPC.exec_program tp b).
+    eapply transf_c_program_correct; eauto.
+  exploit exec_program_program'; eauto. 
+  intros [b' [A B]].
+  split. exists b'; auto.
+  intros b'' EX.
+  assert (same_behaviors b' b''). eapply exec_program'_deterministic; eauto.
+  inv B; inv H4. 
+  auto.
+  apply spec_safety with T1. 
+  eapply traceinf_prefix_compat with T2 T1. 
+  auto. apply traceinf_sim_sym; auto. apply traceinf_sim_refl.
+  auto.
+Qed.
+
+End SPECS_PRESERVED.
diff --git a/common/Events.v b/common/Events.v
index 83a7a19bb..e9070e169 100644
--- a/common/Events.v
+++ b/common/Events.v
@@ -66,14 +66,18 @@ Proof. intros. unfold E0, Eapp. rewrite <- app_nil_end. auto. Qed.
 Lemma Eapp_assoc: forall t1 t2 t3, (t1 ** t2) ** t3 = t1 ** (t2 ** t3).
 Proof. intros. unfold Eapp, trace. apply app_ass. Qed.
 
+Lemma E0_left_inf: forall T, E0 *** T = T.
+Proof. auto. Qed.
+
 Lemma Eappinf_assoc: forall t1 t2 T, (t1 ** t2) *** T = t1 *** (t2 *** T).
 Proof.
   induction t1; intros; simpl. auto. decEq; auto.
 Qed.
 
-Hint Rewrite E0_left E0_right Eapp_assoc: trace_rewrite.
+Hint Rewrite E0_left E0_right Eapp_assoc
+             E0_left_inf Eappinf_assoc: trace_rewrite.
 
-Opaque trace E0 Eextcall Eapp.
+Opaque trace E0 Eextcall Eapp Eappinf.
 
 (** The following [traceEq] tactic proves equalities between traces
   or infinite traces. *)
@@ -251,7 +255,7 @@ Proof.
   inv H; inv H0; inv H1; constructor; eapply COINDHYP; eauto.
 Qed.
 
-Transparent trace E0 Eapp.
+Transparent trace E0 Eapp Eappinf.
 
 Lemma traceinf_prefix_app:
   forall T1 T2 t,
diff --git a/common/Main.v b/common/Main.v
index 33bc7830d..db159298e 100644
--- a/common/Main.v
+++ b/common/Main.v
@@ -258,10 +258,10 @@ Proof.
 Qed.
 
 Theorem transf_cminor_program_correct:
-  forall p tp t n,
+  forall p tp beh,
   transf_cminor_program p = OK tp ->
-  Cminor.exec_program p t (Vint n) ->
-  PPC.exec_program tp (Terminates t n).
+  Cminor.exec_program p beh ->
+  PPC.exec_program tp beh.
 Proof.
   intros. unfold transf_cminor_program, transf_cminor_fundef in H.
   destruct (transform_partial_program_compose _ _ _ _ _ _ _ _ H) as [p3 [H3 P3]].
@@ -276,12 +276,12 @@ Proof.
 Qed.
 
 Theorem transf_c_program_correct:
-  forall p tp t n,
+  forall p tp beh,
   transf_c_program p = OK tp ->
-  Csem.exec_program p t (Vint n) ->
-  PPC.exec_program tp (Terminates t n).
+  Csem.exec_program p beh ->
+  PPC.exec_program tp beh.
 Proof.
-  intros until n; unfold transf_c_program; simpl.
+  intros until beh; unfold transf_c_program; simpl.
   caseEq (Ctyping.typecheck_program p); try congruence; intro.
   caseEq (Cshmgen.transl_program p); simpl; try congruence; intros p1 EQ1.
   caseEq (Cminorgen.transl_program p1); simpl; try congruence; intros p2 EQ2. 
diff --git a/common/Smallstep.v b/common/Smallstep.v
index f60746d3f..8039ba43a 100644
--- a/common/Smallstep.v
+++ b/common/Smallstep.v
@@ -172,12 +172,17 @@ Qed.
     for coinductive reasoning. *)
 
 CoInductive forever_N (ge: genv): nat -> state -> traceinf -> Prop :=
-  | forever_N_star: forall s1 t s2 p q T,
-      star ge s1 t s2 -> (p < q)%nat -> forever_N ge p s2 T ->
-      forever_N ge q s1 (t *** T)
-  | forever_N_plus: forall s1 t s2 p q T,
-      plus ge s1 t s2 -> forever_N ge p s2 T ->
-      forever_N ge q s1 (t *** T).
+  | forever_N_star: forall s1 t s2 p q T1 T2,
+      star ge s1 t s2 -> 
+      (p < q)%nat ->
+      forever_N ge p s2 T2 ->
+      T1 = t *** T2 ->
+      forever_N ge q s1 T1
+  | forever_N_plus: forall s1 t s2 p q T1 T2,
+      plus ge s1 t s2 ->
+      forever_N ge p s2 T2 ->
+      T1 = t *** T2 ->
+      forever_N ge q s1 T1.
 
 Remark Peano_induction:
   forall (P: nat -> Prop),
@@ -202,14 +207,14 @@ Proof.
   (* star case *)
   inv H1.
   (* no transition *)
-  change (E0 *** T0) with T0. apply H with p1. auto. auto. 
+  change (E0 *** T2) with T2. apply H with p1. auto. auto. 
   (* at least one transition *)
-  exists t1; exists s0; exists p0; exists (t2 *** T0).
+  exists t1; exists s0; exists p0; exists (t2 *** T2).
   split. auto. split. eapply forever_N_star; eauto.
   apply Eappinf_assoc.
   (* plus case *)
   inv H1.
-  exists t1; exists s0; exists (S p1); exists (t2 *** T0).
+  exists t1; exists s0; exists (S p1); exists (t2 *** T2).
   split. auto. split. eapply forever_N_star; eauto. 
   apply Eappinf_assoc.
 Qed.
@@ -348,12 +353,12 @@ Proof.
     forever_N step2 ge2 (measure st1) st2 T).
   cofix COINDHYP; intros.
   inversion H; subst. elim (simulation H1 H0).
-  intros [st2' [A B]]. apply forever_N_plus with st2' (measure s2).
-  auto. apply COINDHYP. assumption. assumption.
+  intros [st2' [A B]]. apply forever_N_plus with t st2' (measure s2) T0.
+  auto. apply COINDHYP. assumption. assumption. auto.
   intros [A [B C]].
-  apply forever_N_star with st2 (measure s2).
+  apply forever_N_star with t st2 (measure s2) T0.
   rewrite B. apply star_refl. auto.
-  apply COINDHYP. assumption. auto.
+  apply COINDHYP. assumption. auto. auto.
   intros. eapply forever_N_forever; eauto.
 Qed.
 
diff --git a/doc/index.html b/doc/index.html
index e75e7b17b..4390c8765 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -25,7 +25,7 @@ a:active {color : Red; text-decoration : underline; }
 
 <H1 align="center">The Compcert certified compiler</H1>
 <H2 align="center">Commented Coq development</H2>
-<H3 align="center">Version 1.0, 2007-08-03</H3>
+<H3 align="center">Version 1.0, 2007-08-28</H3>
 
 <H2>Introduction</H2>
 
@@ -274,6 +274,7 @@ Proofs that compiler passes are type-preserving:
 <UL>
 <LI> <A HREF="html/Main.html">Main</A>: composing the passes together; the
 final semantic preservation theorems.
+<LI> <A HREF="html/Complements.html">Complements</A>: interesting consequences of the semantic preservation theorems.
 </UL>
 
 <HR>
diff --git a/doc/removeproofs b/doc/removeproofs
index 82809ba68..5ae9a2354 100755
--- a/doc/removeproofs
+++ b/doc/removeproofs
@@ -2,7 +2,9 @@
 
 for i in $*; do
   mv $i $i.bak
-  sed -e '/<code class="keyword">Proof<\/code> *\./,/<code class="keyword">\(Qed\|Defined\)<\/code> *\./d' $i.bak > $i
+  sed -e '/<span class="keyword">Proof<\/span> *\./,/<span class="keyword">\(Qed\|Defined\)<\/span> *\./d' \
+      -e "s/\"'do' X <- A ; B\" error_monad_scope/doXAB error_monad_scope/g" \
+      $i.bak > $i
   rm $i.bak
 done
 
diff --git a/extraction/.depend b/extraction/.depend
index afffe8169..6a10752b5 100644
--- a/extraction/.depend
+++ b/extraction/.depend
@@ -4,14 +4,6 @@
 ../caml/Coloringaux.cmi: Registers.cmi RTLtyping.cmi RTL.cmi Locations.cmi \
     InterfGraph.cmi 
 ../caml/PrintPPC.cmi: PPC.cmi 
-../caml/Camlcoq.cmo: Integers.cmi Datatypes.cmi CString.cmi CList.cmi \
-    BinPos.cmi BinInt.cmi Ascii.cmi 
-../caml/Camlcoq.cmx: Integers.cmx Datatypes.cmx CString.cmx CList.cmx \
-    BinPos.cmx BinInt.cmx Ascii.cmx 
-../caml/Cil2Csyntax.cmo: Datatypes.cmi Csyntax.cmi ../caml/Camlcoq.cmo \
-    CList.cmi AST.cmi 
-../caml/Cil2Csyntax.cmx: Datatypes.cmx Csyntax.cmx ../caml/Camlcoq.cmx \
-    CList.cmx AST.cmx 
 ../caml/CMlexer.cmo: ../caml/Camlcoq.cmo ../caml/CMparser.cmi \
     ../caml/CMlexer.cmi 
 ../caml/CMlexer.cmx: ../caml/Camlcoq.cmx ../caml/CMparser.cmx \
@@ -26,6 +18,14 @@
     ../caml/Camlcoq.cmo CList.cmi AST.cmi ../caml/CMtypecheck.cmi 
 ../caml/CMtypecheck.cmx: Integers.cmx Datatypes.cmx Cminor.cmx \
     ../caml/Camlcoq.cmx CList.cmx AST.cmx ../caml/CMtypecheck.cmi 
+../caml/Camlcoq.cmo: Integers.cmi Datatypes.cmi CString.cmi CList.cmi \
+    BinPos.cmi BinInt.cmi Ascii.cmi 
+../caml/Camlcoq.cmx: Integers.cmx Datatypes.cmx CString.cmx CList.cmx \
+    BinPos.cmx BinInt.cmx Ascii.cmx 
+../caml/Cil2Csyntax.cmo: Datatypes.cmi Csyntax.cmi ../caml/Camlcoq.cmo \
+    CList.cmi AST.cmi 
+../caml/Cil2Csyntax.cmx: Datatypes.cmx Csyntax.cmx ../caml/Camlcoq.cmx \
+    CList.cmx AST.cmx 
 ../caml/Coloringaux.cmo: Registers.cmi RTLtyping.cmi RTL.cmi Maps.cmi \
     Locations.cmi InterfGraph.cmi Datatypes.cmi Conventions.cmi \
     ../caml/Camlcoq.cmo BinPos.cmi BinInt.cmi AST.cmi ../caml/Coloringaux.cmi 
@@ -42,12 +42,6 @@
     ../caml/CMlexer.cmx 
 ../caml/Floataux.cmo: Integers.cmi ../caml/Camlcoq.cmo 
 ../caml/Floataux.cmx: Integers.cmx ../caml/Camlcoq.cmx 
-../caml/Main2.cmo: ../caml/PrintPPC.cmi ../caml/PrintCsyntax.cmo Main.cmi \
-    Errors.cmi Csyntax.cmi ../caml/Cil2Csyntax.cmo ../caml/CMtypecheck.cmi \
-    ../caml/CMparser.cmi ../caml/CMlexer.cmi 
-../caml/Main2.cmx: ../caml/PrintPPC.cmx ../caml/PrintCsyntax.cmx Main.cmx \
-    Errors.cmx Csyntax.cmx ../caml/Cil2Csyntax.cmx ../caml/CMtypecheck.cmx \
-    ../caml/CMparser.cmx ../caml/CMlexer.cmx 
 ../caml/PrintCshm.cmo: Integers.cmi Datatypes.cmi Csharpminor.cmi \
     ../caml/Camlcoq.cmo CList.cmi AST.cmi 
 ../caml/PrintCshm.cmx: Integers.cmx Datatypes.cmx Csharpminor.cmx \
@@ -68,12 +62,12 @@
     ../caml/Camlcoq.cmo CList.cmi AST.cmi 
 ../caml/RTLtypingaux.cmx: Registers.cmx RTL.cmx Op.cmx Maps.cmx Datatypes.cmx \
     ../caml/Camlcoq.cmx CList.cmx AST.cmx 
+AST.cmi: Specif.cmi Integers.cmi Floats.cmi Errors.cmi Datatypes.cmi \
+    Coqlib.cmi CString.cmi CList.cmi BinPos.cmi BinInt.cmi Ascii.cmi 
 Allocation.cmi: Specif.cmi Registers.cmi RTLtyping.cmi RTL.cmi Op.cmi \
     Maps.cmi Locations.cmi LTL.cmi Errors.cmi Datatypes.cmi Coloring.cmi \
     CString.cmi CList.cmi BinPos.cmi Ascii.cmi AST.cmi 
 Ascii.cmi: Specif.cmi Peano.cmi Datatypes.cmi Bool.cmi BinPos.cmi 
-AST.cmi: Specif.cmi Integers.cmi Floats.cmi Errors.cmi Datatypes.cmi \
-    Coqlib.cmi CString.cmi CList.cmi BinPos.cmi BinInt.cmi Ascii.cmi 
 BinInt.cmi: Datatypes.cmi BinPos.cmi BinNat.cmi 
 BinNat.cmi: Specif.cmi Datatypes.cmi BinPos.cmi 
 BinPos.cmi: Peano.cmi Datatypes.cmi 
@@ -82,15 +76,18 @@ Bounds.cmi: Zmax.cmi Locations.cmi Linear.cmi Conventions.cmi CList.cmi \
     BinPos.cmi BinInt.cmi AST.cmi 
 CInt.cmi: Zmax.cmi ZArith_dec.cmi Specif.cmi BinPos.cmi BinInt.cmi 
 CList.cmi: Specif.cmi Datatypes.cmi 
+CSE.cmi: Specif.cmi Registers.cmi RTL.cmi Op.cmi Maps.cmi Integers.cmi \
+    Floats.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi AST.cmi 
+CString.cmi: Specif.cmi Datatypes.cmi Ascii.cmi 
+Cminor.cmi: Values.cmi Specif.cmi Mem.cmi Maps.cmi Integers.cmi \
+    Globalenvs.cmi Floats.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi \
+    AST.cmi 
+CminorSel.cmi: Values.cmi Op.cmi Integers.cmi Globalenvs.cmi Datatypes.cmi \
+    CList.cmi BinInt.cmi AST.cmi 
 Cminorgen.cmi: Zmax.cmi Specif.cmi OrderedType.cmi Ordered.cmi Mem.cmi \
     Maps.cmi Integers.cmi Errors.cmi Datatypes.cmi Csharpminor.cmi Coqlib.cmi \
     Cminor.cmi CString.cmi CList.cmi CInt.cmi BinPos.cmi BinInt.cmi Ascii.cmi \
     AST.cmi 
-Cminor.cmi: Values.cmi Specif.cmi Mem.cmi Maps.cmi Integers.cmi \
-    Globalenvs.cmi Floats.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi \
-    AST.cmi 
-CminorSel.cmi: Op.cmi Integers.cmi Globalenvs.cmi Datatypes.cmi CList.cmi \
-    BinInt.cmi AST.cmi 
 Coloring.cmi: Specif.cmi Registers.cmi RTLtyping.cmi RTL.cmi Op.cmi Maps.cmi \
     Locations.cmi InterfGraph.cmi Datatypes.cmi Coqlib.cmi Conventions.cmi \
     CList.cmi BinInt.cmi AST.cmi 
@@ -101,15 +98,12 @@ Conventions.cmi: Locations.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi \
     BinInt.cmi AST.cmi 
 Coqlib.cmi: Zdiv.cmi ZArith_dec.cmi Wf.cmi Specif.cmi Datatypes.cmi CList.cmi \
     BinPos.cmi BinInt.cmi 
-CSE.cmi: Specif.cmi Registers.cmi RTL.cmi Op.cmi Maps.cmi Integers.cmi \
-    Floats.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi AST.cmi 
 Csharpminor.cmi: Zmax.cmi Values.cmi Mem.cmi Maps.cmi Integers.cmi \
     Globalenvs.cmi Floats.cmi Datatypes.cmi Cminor.cmi CList.cmi BinInt.cmi \
     AST.cmi 
-Cshmgen.cmi: Peano.cmi Integers.cmi Floats.cmi Errors.cmi Datatypes.cmi \
-    Csyntax.cmi Csharpminor.cmi Cminor.cmi CString.cmi CList.cmi Ascii.cmi \
-    AST.cmi 
-CString.cmi: Specif.cmi Datatypes.cmi Ascii.cmi 
+Cshmgen.cmi: Specif.cmi Peano.cmi Integers.cmi Floats.cmi Errors.cmi \
+    Datatypes.cmi Csyntax.cmi Csharpminor.cmi Cminor.cmi CString.cmi \
+    CList.cmi Ascii.cmi AST.cmi 
 Csyntax.cmi: Zmax.cmi Specif.cmi Integers.cmi Floats.cmi Errors.cmi \
     Datatypes.cmi Coqlib.cmi CString.cmi CList.cmi BinPos.cmi BinInt.cmi \
     Ascii.cmi AST.cmi 
@@ -117,12 +111,12 @@ Ctyping.cmi: Specif.cmi Maps.cmi Datatypes.cmi Csyntax.cmi Coqlib.cmi \
     CList.cmi AST.cmi 
 EqNat.cmi: Specif.cmi Datatypes.cmi 
 Errors.cmi: Datatypes.cmi CString.cmi CList.cmi BinPos.cmi 
-Floats.cmi: Specif.cmi Integers.cmi Datatypes.cmi 
 FSetAVL.cmi: Wf.cmi Specif.cmi Peano.cmi OrderedType.cmi Datatypes.cmi \
     CList.cmi CInt.cmi BinPos.cmi BinInt.cmi 
 FSetFacts.cmi: Specif.cmi Setoid.cmi FSetInterface.cmi Datatypes.cmi 
 FSetInterface.cmi: Specif.cmi OrderedType.cmi Datatypes.cmi CList.cmi 
 FSetList.cmi: Specif.cmi OrderedType.cmi Datatypes.cmi CList.cmi 
+Floats.cmi: Specif.cmi Integers.cmi Datatypes.cmi 
 Globalenvs.cmi: Values.cmi Mem.cmi Maps.cmi Integers.cmi Datatypes.cmi \
     CList.cmi BinPos.cmi BinInt.cmi AST.cmi 
 Integers.cmi: Zpower.cmi Zdiv.cmi Specif.cmi Datatypes.cmi Coqlib.cmi \
@@ -133,21 +127,21 @@ Iteration.cmi: Wf.cmi Specif.cmi Datatypes.cmi Coqlib.cmi BinPos.cmi
 Kildall.cmi: Specif.cmi Setoid.cmi OrderedType.cmi Ordered.cmi Maps.cmi \
     Lattice.cmi Iteration.cmi Datatypes.cmi Coqlib.cmi CList.cmi CInt.cmi \
     BinPos.cmi BinInt.cmi 
+LTL.cmi: Values.cmi Specif.cmi Op.cmi Mem.cmi Maps.cmi Locations.cmi \
+    Integers.cmi Globalenvs.cmi Datatypes.cmi Conventions.cmi CList.cmi \
+    BinPos.cmi BinInt.cmi AST.cmi 
+LTLin.cmi: Values.cmi Specif.cmi Op.cmi Mem.cmi Locations.cmi Integers.cmi \
+    Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
+    AST.cmi 
 Lattice.cmi: Specif.cmi Maps.cmi FSetInterface.cmi Datatypes.cmi Bool.cmi \
     BinPos.cmi 
-Linearize.cmi: Specif.cmi Op.cmi Maps.cmi Lattice.cmi LTLin.cmi LTL.cmi \
-    Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi AST.cmi 
 Linear.cmi: Values.cmi Specif.cmi Op.cmi Mem.cmi Locations.cmi Integers.cmi \
     Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
     AST.cmi 
+Linearize.cmi: Specif.cmi Op.cmi Maps.cmi Lattice.cmi LTLin.cmi LTL.cmi \
+    Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi AST.cmi 
 Locations.cmi: Values.cmi Specif.cmi Datatypes.cmi Coqlib.cmi BinPos.cmi \
     BinInt.cmi AST.cmi 
-LTLin.cmi: Values.cmi Specif.cmi Op.cmi Mem.cmi Locations.cmi Integers.cmi \
-    Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
-    AST.cmi 
-LTL.cmi: Values.cmi Specif.cmi Op.cmi Mem.cmi Maps.cmi Locations.cmi \
-    Integers.cmi Globalenvs.cmi Datatypes.cmi Conventions.cmi CList.cmi \
-    BinPos.cmi BinInt.cmi AST.cmi 
 Mach.cmi: Zmax.cmi Zdiv.cmi Values.cmi Specif.cmi Op.cmi Locations.cmi \
     Integers.cmi Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi \
     BinInt.cmi AST.cmi 
@@ -164,26 +158,26 @@ Op.cmi: Values.cmi Specif.cmi Mem.cmi Integers.cmi Globalenvs.cmi Floats.cmi \
 Ordered.cmi: Specif.cmi OrderedType.cmi Maps.cmi Datatypes.cmi Coqlib.cmi \
     BinPos.cmi 
 OrderedType.cmi: Specif.cmi Datatypes.cmi 
-Parallelmove.cmi: Parmov.cmi Locations.cmi Datatypes.cmi CList.cmi AST.cmi 
-Parmov.cmi: Specif.cmi Peano.cmi Datatypes.cmi CList.cmi 
-Peano.cmi: Datatypes.cmi 
+PPC.cmi: Values.cmi Specif.cmi Mem.cmi Integers.cmi Globalenvs.cmi Floats.cmi \
+    Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi 
 PPCgen.cmi: Specif.cmi PPC.cmi Op.cmi Mach.cmi Locations.cmi Integers.cmi \
     Errors.cmi Datatypes.cmi Coqlib.cmi CString.cmi CList.cmi Bool.cmi \
     BinPos.cmi BinInt.cmi Ascii.cmi AST.cmi 
-PPC.cmi: Values.cmi Specif.cmi Mem.cmi Integers.cmi Globalenvs.cmi Floats.cmi \
-    Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi 
-Registers.cmi: Specif.cmi OrderedType.cmi Ordered.cmi Maps.cmi Datatypes.cmi \
-    Coqlib.cmi CList.cmi CInt.cmi BinPos.cmi BinInt.cmi AST.cmi 
-Reload.cmi: Specif.cmi Parallelmove.cmi Op.cmi Locations.cmi Linear.cmi \
-    LTLin.cmi Datatypes.cmi Conventions.cmi CList.cmi AST.cmi 
+Parallelmove.cmi: Parmov.cmi Locations.cmi Datatypes.cmi CList.cmi AST.cmi 
+Parmov.cmi: Specif.cmi Peano.cmi Datatypes.cmi CList.cmi 
+Peano.cmi: Datatypes.cmi 
+RTL.cmi: Values.cmi Registers.cmi Op.cmi Mem.cmi Maps.cmi Integers.cmi \
+    Globalenvs.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi 
 RTLgen.cmi: Switch.cmi Specif.cmi Registers.cmi RTL.cmi Op.cmi Maps.cmi \
     Integers.cmi Errors.cmi Datatypes.cmi Coqlib.cmi CminorSel.cmi \
     CString.cmi CList.cmi BinPos.cmi Ascii.cmi AST.cmi 
-RTL.cmi: Values.cmi Registers.cmi Op.cmi Mem.cmi Maps.cmi Integers.cmi \
-    Globalenvs.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi 
 RTLtyping.cmi: Specif.cmi Registers.cmi RTL.cmi Op.cmi Maps.cmi Errors.cmi \
     Datatypes.cmi Coqlib.cmi Conventions.cmi CString.cmi CList.cmi BinPos.cmi \
     BinInt.cmi Ascii.cmi AST.cmi 
+Registers.cmi: Specif.cmi OrderedType.cmi Ordered.cmi Maps.cmi Datatypes.cmi \
+    Coqlib.cmi CList.cmi CInt.cmi BinPos.cmi BinInt.cmi AST.cmi 
+Reload.cmi: Specif.cmi Parallelmove.cmi Op.cmi Locations.cmi Linear.cmi \
+    LTLin.cmi Datatypes.cmi Conventions.cmi CList.cmi AST.cmi 
 Selection.cmi: Specif.cmi Op.cmi Integers.cmi Datatypes.cmi Compare_dec.cmi \
     CminorSel.cmi Cminor.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi 
 Setoid.cmi: Datatypes.cmi 
@@ -205,6 +199,10 @@ Zeven.cmi: Specif.cmi Datatypes.cmi BinPos.cmi BinInt.cmi
 Zmax.cmi: Datatypes.cmi BinInt.cmi 
 Zmisc.cmi: Datatypes.cmi BinPos.cmi BinInt.cmi 
 Zpower.cmi: Zmisc.cmi Datatypes.cmi BinPos.cmi BinInt.cmi 
+AST.cmo: Specif.cmi Integers.cmi Floats.cmi Errors.cmi Datatypes.cmi \
+    Coqlib.cmi CString.cmi CList.cmi BinPos.cmi BinInt.cmi Ascii.cmi AST.cmi 
+AST.cmx: Specif.cmx Integers.cmx Floats.cmx Errors.cmx Datatypes.cmx \
+    Coqlib.cmx CString.cmx CList.cmx BinPos.cmx BinInt.cmx Ascii.cmx AST.cmi 
 Allocation.cmo: Specif.cmi Registers.cmi RTLtyping.cmi RTL.cmi Op.cmi \
     Maps.cmi Locations.cmi Lattice.cmi LTL.cmi Kildall.cmi Errors.cmi \
     Datatypes.cmi Coloring.cmi CString.cmi CList.cmi BinPos.cmi Ascii.cmi \
@@ -215,10 +213,6 @@ Allocation.cmx: Specif.cmx Registers.cmx RTLtyping.cmx RTL.cmx Op.cmx \
     AST.cmx Allocation.cmi 
 Ascii.cmo: Specif.cmi Peano.cmi Datatypes.cmi Bool.cmi BinPos.cmi Ascii.cmi 
 Ascii.cmx: Specif.cmx Peano.cmx Datatypes.cmx Bool.cmx BinPos.cmx Ascii.cmi 
-AST.cmo: Specif.cmi Integers.cmi Floats.cmi Errors.cmi Datatypes.cmi \
-    Coqlib.cmi CString.cmi CList.cmi BinPos.cmi BinInt.cmi Ascii.cmi AST.cmi 
-AST.cmx: Specif.cmx Integers.cmx Floats.cmx Errors.cmx Datatypes.cmx \
-    Coqlib.cmx CString.cmx CList.cmx BinPos.cmx BinInt.cmx Ascii.cmx AST.cmi 
 BinInt.cmo: Datatypes.cmi BinPos.cmi BinNat.cmi BinInt.cmi 
 BinInt.cmx: Datatypes.cmx BinPos.cmx BinNat.cmx BinInt.cmi 
 BinNat.cmo: Specif.cmi Datatypes.cmi BinPos.cmi BinNat.cmi 
@@ -235,6 +229,24 @@ CInt.cmo: Zmax.cmi ZArith_dec.cmi Specif.cmi BinPos.cmi BinInt.cmi CInt.cmi
 CInt.cmx: Zmax.cmx ZArith_dec.cmx Specif.cmx BinPos.cmx BinInt.cmx CInt.cmi 
 CList.cmo: Specif.cmi Datatypes.cmi CList.cmi 
 CList.cmx: Specif.cmx Datatypes.cmx CList.cmi 
+CSE.cmo: Specif.cmi Registers.cmi RTL.cmi Op.cmi Maps.cmi Kildall.cmi \
+    Integers.cmi Floats.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi \
+    AST.cmi CSE.cmi 
+CSE.cmx: Specif.cmx Registers.cmx RTL.cmx Op.cmx Maps.cmx Kildall.cmx \
+    Integers.cmx Floats.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx \
+    AST.cmx CSE.cmi 
+CString.cmo: Specif.cmi Datatypes.cmi Ascii.cmi CString.cmi 
+CString.cmx: Specif.cmx Datatypes.cmx Ascii.cmx CString.cmi 
+Cminor.cmo: Values.cmi Specif.cmi Mem.cmi Maps.cmi Integers.cmi \
+    Globalenvs.cmi Floats.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi \
+    AST.cmi Cminor.cmi 
+Cminor.cmx: Values.cmx Specif.cmx Mem.cmx Maps.cmx Integers.cmx \
+    Globalenvs.cmx Floats.cmx Datatypes.cmx CList.cmx BinPos.cmx BinInt.cmx \
+    AST.cmx Cminor.cmi 
+CminorSel.cmo: Values.cmi Op.cmi Integers.cmi Globalenvs.cmi Datatypes.cmi \
+    CList.cmi BinInt.cmi AST.cmi CminorSel.cmi 
+CminorSel.cmx: Values.cmx Op.cmx Integers.cmx Globalenvs.cmx Datatypes.cmx \
+    CList.cmx BinInt.cmx AST.cmx CminorSel.cmi 
 Cminorgen.cmo: Zmax.cmi Specif.cmi OrderedType.cmi Ordered.cmi Mem.cmi \
     Maps.cmi Integers.cmi FSetAVL.cmi Errors.cmi Datatypes.cmi \
     Csharpminor.cmi Coqlib.cmi Cminor.cmi CString.cmi CList.cmi BinPos.cmi \
@@ -243,16 +255,6 @@ Cminorgen.cmx: Zmax.cmx Specif.cmx OrderedType.cmx Ordered.cmx Mem.cmx \
     Maps.cmx Integers.cmx FSetAVL.cmx Errors.cmx Datatypes.cmx \
     Csharpminor.cmx Coqlib.cmx Cminor.cmx CString.cmx CList.cmx BinPos.cmx \
     BinInt.cmx Ascii.cmx AST.cmx Cminorgen.cmi 
-Cminor.cmo: Values.cmi Specif.cmi Mem.cmi Maps.cmi Integers.cmi \
-    Globalenvs.cmi Floats.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi \
-    AST.cmi Cminor.cmi 
-Cminor.cmx: Values.cmx Specif.cmx Mem.cmx Maps.cmx Integers.cmx \
-    Globalenvs.cmx Floats.cmx Datatypes.cmx CList.cmx BinPos.cmx BinInt.cmx \
-    AST.cmx Cminor.cmi 
-CminorSel.cmo: Op.cmi Integers.cmi Globalenvs.cmi Datatypes.cmi CList.cmi \
-    BinInt.cmi AST.cmi CminorSel.cmi 
-CminorSel.cmx: Op.cmx Integers.cmx Globalenvs.cmx Datatypes.cmx CList.cmx \
-    BinInt.cmx AST.cmx CminorSel.cmi 
 Coloring.cmo: Specif.cmi Registers.cmi RTLtyping.cmi RTL.cmi Op.cmi Maps.cmi \
     Locations.cmi InterfGraph.cmi Datatypes.cmi Coqlib.cmi Conventions.cmi \
     ../caml/Coloringaux.cmi CList.cmi BinInt.cmi AST.cmi Coloring.cmi 
@@ -275,26 +277,18 @@ Coqlib.cmo: Zdiv.cmi ZArith_dec.cmi Wf.cmi Specif.cmi Datatypes.cmi CList.cmi \
     BinPos.cmi BinInt.cmi Coqlib.cmi 
 Coqlib.cmx: Zdiv.cmx ZArith_dec.cmx Wf.cmx Specif.cmx Datatypes.cmx CList.cmx \
     BinPos.cmx BinInt.cmx Coqlib.cmi 
-CSE.cmo: Specif.cmi Registers.cmi RTL.cmi Op.cmi Maps.cmi Kildall.cmi \
-    Integers.cmi Floats.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi \
-    AST.cmi CSE.cmi 
-CSE.cmx: Specif.cmx Registers.cmx RTL.cmx Op.cmx Maps.cmx Kildall.cmx \
-    Integers.cmx Floats.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx \
-    AST.cmx CSE.cmi 
 Csharpminor.cmo: Zmax.cmi Values.cmi Mem.cmi Maps.cmi Integers.cmi \
     Globalenvs.cmi Floats.cmi Datatypes.cmi Cminor.cmi CList.cmi BinInt.cmi \
     AST.cmi Csharpminor.cmi 
 Csharpminor.cmx: Zmax.cmx Values.cmx Mem.cmx Maps.cmx Integers.cmx \
     Globalenvs.cmx Floats.cmx Datatypes.cmx Cminor.cmx CList.cmx BinInt.cmx \
     AST.cmx Csharpminor.cmi 
-Cshmgen.cmo: Peano.cmi Integers.cmi Floats.cmi Errors.cmi Datatypes.cmi \
-    Csyntax.cmi Csharpminor.cmi Cminor.cmi CString.cmi CList.cmi Ascii.cmi \
-    AST.cmi Cshmgen.cmi 
-Cshmgen.cmx: Peano.cmx Integers.cmx Floats.cmx Errors.cmx Datatypes.cmx \
-    Csyntax.cmx Csharpminor.cmx Cminor.cmx CString.cmx CList.cmx Ascii.cmx \
-    AST.cmx Cshmgen.cmi 
-CString.cmo: Specif.cmi Datatypes.cmi Ascii.cmi CString.cmi 
-CString.cmx: Specif.cmx Datatypes.cmx Ascii.cmx CString.cmi 
+Cshmgen.cmo: Specif.cmi Peano.cmi Integers.cmi Floats.cmi Errors.cmi \
+    Datatypes.cmi Csyntax.cmi Csharpminor.cmi Cminor.cmi CString.cmi \
+    CList.cmi Ascii.cmi AST.cmi Cshmgen.cmi 
+Cshmgen.cmx: Specif.cmx Peano.cmx Integers.cmx Floats.cmx Errors.cmx \
+    Datatypes.cmx Csyntax.cmx Csharpminor.cmx Cminor.cmx CString.cmx \
+    CList.cmx Ascii.cmx AST.cmx Cshmgen.cmi 
 Csyntax.cmo: Zmax.cmi Specif.cmi Integers.cmi Floats.cmi Errors.cmi \
     Datatypes.cmi Coqlib.cmi CString.cmi CList.cmi BinPos.cmi BinInt.cmi \
     Ascii.cmi AST.cmi Csyntax.cmi 
@@ -311,10 +305,6 @@ EqNat.cmo: Specif.cmi Datatypes.cmi EqNat.cmi
 EqNat.cmx: Specif.cmx Datatypes.cmx EqNat.cmi 
 Errors.cmo: Datatypes.cmi CString.cmi CList.cmi BinPos.cmi Errors.cmi 
 Errors.cmx: Datatypes.cmx CString.cmx CList.cmx BinPos.cmx Errors.cmi 
-Floats.cmo: Specif.cmi Integers.cmi ../caml/Floataux.cmo Datatypes.cmi \
-    Floats.cmi 
-Floats.cmx: Specif.cmx Integers.cmx ../caml/Floataux.cmx Datatypes.cmx \
-    Floats.cmi 
 FSetAVL.cmo: Wf.cmi Specif.cmi Peano.cmi OrderedType.cmi FSetList.cmi \
     Datatypes.cmi CList.cmi CInt.cmi BinPos.cmi BinInt.cmi FSetAVL.cmi 
 FSetAVL.cmx: Wf.cmx Specif.cmx Peano.cmx OrderedType.cmx FSetList.cmx \
@@ -329,6 +319,10 @@ FSetInterface.cmx: Specif.cmx OrderedType.cmx Datatypes.cmx CList.cmx \
     FSetInterface.cmi 
 FSetList.cmo: Specif.cmi OrderedType.cmi Datatypes.cmi CList.cmi FSetList.cmi 
 FSetList.cmx: Specif.cmx OrderedType.cmx Datatypes.cmx CList.cmx FSetList.cmi 
+Floats.cmo: Specif.cmi Integers.cmi ../caml/Floataux.cmo Datatypes.cmi \
+    Floats.cmi 
+Floats.cmx: Specif.cmx Integers.cmx ../caml/Floataux.cmx Datatypes.cmx \
+    Floats.cmi 
 Globalenvs.cmo: Values.cmi Mem.cmi Maps.cmi Integers.cmi Datatypes.cmi \
     CList.cmi BinPos.cmi BinInt.cmi AST.cmi Globalenvs.cmi 
 Globalenvs.cmx: Values.cmx Mem.cmx Maps.cmx Integers.cmx Datatypes.cmx \
@@ -353,40 +347,40 @@ Kildall.cmo: Specif.cmi Setoid.cmi OrderedType.cmi Ordered.cmi Maps.cmi \
 Kildall.cmx: Specif.cmx Setoid.cmx OrderedType.cmx Ordered.cmx Maps.cmx \
     Lattice.cmx Iteration.cmx FSetFacts.cmx FSetAVL.cmx Datatypes.cmx \
     Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx Kildall.cmi 
+LTL.cmo: Values.cmi Specif.cmi Op.cmi Mem.cmi Maps.cmi Locations.cmi \
+    Integers.cmi Globalenvs.cmi Datatypes.cmi Conventions.cmi CList.cmi \
+    BinPos.cmi BinInt.cmi AST.cmi LTL.cmi 
+LTL.cmx: Values.cmx Specif.cmx Op.cmx Mem.cmx Maps.cmx Locations.cmx \
+    Integers.cmx Globalenvs.cmx Datatypes.cmx Conventions.cmx CList.cmx \
+    BinPos.cmx BinInt.cmx AST.cmx LTL.cmi 
+LTLin.cmo: Values.cmi Specif.cmi Op.cmi Mem.cmi Locations.cmi Integers.cmi \
+    Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
+    AST.cmi LTLin.cmi 
+LTLin.cmx: Values.cmx Specif.cmx Op.cmx Mem.cmx Locations.cmx Integers.cmx \
+    Globalenvs.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx \
+    AST.cmx LTLin.cmi 
 Lattice.cmo: Specif.cmi Maps.cmi FSetInterface.cmi Datatypes.cmi Bool.cmi \
     BinPos.cmi Lattice.cmi 
 Lattice.cmx: Specif.cmx Maps.cmx FSetInterface.cmx Datatypes.cmx Bool.cmx \
     BinPos.cmx Lattice.cmi 
-Linearize.cmo: Specif.cmi Op.cmi Maps.cmi Lattice.cmi LTLin.cmi LTL.cmi \
-    Kildall.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi AST.cmi \
-    Linearize.cmi 
-Linearize.cmx: Specif.cmx Op.cmx Maps.cmx Lattice.cmx LTLin.cmx LTL.cmx \
-    Kildall.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx AST.cmx \
-    Linearize.cmi 
 Linear.cmo: Values.cmi Specif.cmi Op.cmi Mem.cmi Locations.cmi Integers.cmi \
     Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
     AST.cmi Linear.cmi 
 Linear.cmx: Values.cmx Specif.cmx Op.cmx Mem.cmx Locations.cmx Integers.cmx \
     Globalenvs.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx \
     AST.cmx Linear.cmi 
+Linearize.cmo: Specif.cmi Op.cmi Maps.cmi Lattice.cmi LTLin.cmi LTL.cmi \
+    Kildall.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi AST.cmi \
+    Linearize.cmi 
+Linearize.cmx: Specif.cmx Op.cmx Maps.cmx Lattice.cmx LTLin.cmx LTL.cmx \
+    Kildall.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx AST.cmx \
+    Linearize.cmi 
 Locations.cmo: Values.cmi Specif.cmi Datatypes.cmi Coqlib.cmi BinPos.cmi \
     BinInt.cmi AST.cmi Locations.cmi 
 Locations.cmx: Values.cmx Specif.cmx Datatypes.cmx Coqlib.cmx BinPos.cmx \
     BinInt.cmx AST.cmx Locations.cmi 
 Logic.cmo: Logic.cmi 
 Logic.cmx: Logic.cmi 
-LTLin.cmo: Values.cmi Specif.cmi Op.cmi Mem.cmi Locations.cmi Integers.cmi \
-    Globalenvs.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
-    AST.cmi LTLin.cmi 
-LTLin.cmx: Values.cmx Specif.cmx Op.cmx Mem.cmx Locations.cmx Integers.cmx \
-    Globalenvs.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx \
-    AST.cmx LTLin.cmi 
-LTL.cmo: Values.cmi Specif.cmi Op.cmi Mem.cmi Maps.cmi Locations.cmi \
-    Integers.cmi Globalenvs.cmi Datatypes.cmi Conventions.cmi CList.cmi \
-    BinPos.cmi BinInt.cmi AST.cmi LTL.cmi 
-LTL.cmx: Values.cmx Specif.cmx Op.cmx Mem.cmx Maps.cmx Locations.cmx \
-    Integers.cmx Globalenvs.cmx Datatypes.cmx Conventions.cmx CList.cmx \
-    BinPos.cmx BinInt.cmx AST.cmx LTL.cmi 
 Mach.cmo: Zmax.cmi Zdiv.cmi Values.cmi Specif.cmi Op.cmi Maps.cmi \
     Locations.cmi Integers.cmi Globalenvs.cmi Datatypes.cmi Coqlib.cmi \
     CList.cmi BinPos.cmi BinInt.cmi AST.cmi Mach.cmi 
@@ -419,6 +413,18 @@ Ordered.cmx: Specif.cmx OrderedType.cmx Maps.cmx Datatypes.cmx Coqlib.cmx \
     BinPos.cmx Ordered.cmi 
 OrderedType.cmo: Specif.cmi Datatypes.cmi OrderedType.cmi 
 OrderedType.cmx: Specif.cmx Datatypes.cmx OrderedType.cmi 
+PPC.cmo: Values.cmi Specif.cmi Mem.cmi Maps.cmi Integers.cmi Globalenvs.cmi \
+    Floats.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
+    AST.cmi PPC.cmi 
+PPC.cmx: Values.cmx Specif.cmx Mem.cmx Maps.cmx Integers.cmx Globalenvs.cmx \
+    Floats.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx \
+    AST.cmx PPC.cmi 
+PPCgen.cmo: Specif.cmi PPC.cmi Op.cmi Mach.cmi Locations.cmi Integers.cmi \
+    Errors.cmi Datatypes.cmi Coqlib.cmi CString.cmi CList.cmi Bool.cmi \
+    BinPos.cmi BinInt.cmi Ascii.cmi AST.cmi PPCgen.cmi 
+PPCgen.cmx: Specif.cmx PPC.cmx Op.cmx Mach.cmx Locations.cmx Integers.cmx \
+    Errors.cmx Datatypes.cmx Coqlib.cmx CString.cmx CList.cmx Bool.cmx \
+    BinPos.cmx BinInt.cmx Ascii.cmx AST.cmx PPCgen.cmi 
 Parallelmove.cmo: Parmov.cmi Locations.cmi Datatypes.cmi CList.cmi AST.cmi \
     Parallelmove.cmi 
 Parallelmove.cmx: Parmov.cmx Locations.cmx Datatypes.cmx CList.cmx AST.cmx \
@@ -427,28 +433,12 @@ Parmov.cmo: Specif.cmi Peano.cmi Datatypes.cmi CList.cmi Parmov.cmi
 Parmov.cmx: Specif.cmx Peano.cmx Datatypes.cmx CList.cmx Parmov.cmi 
 Peano.cmo: Datatypes.cmi Peano.cmi 
 Peano.cmx: Datatypes.cmx Peano.cmi 
-PPCgen.cmo: Specif.cmi PPC.cmi Op.cmi Mach.cmi Locations.cmi Integers.cmi \
-    Errors.cmi Datatypes.cmi Coqlib.cmi CString.cmi CList.cmi Bool.cmi \
-    BinPos.cmi BinInt.cmi Ascii.cmi AST.cmi PPCgen.cmi 
-PPCgen.cmx: Specif.cmx PPC.cmx Op.cmx Mach.cmx Locations.cmx Integers.cmx \
-    Errors.cmx Datatypes.cmx Coqlib.cmx CString.cmx CList.cmx Bool.cmx \
-    BinPos.cmx BinInt.cmx Ascii.cmx AST.cmx PPCgen.cmi 
-PPC.cmo: Values.cmi Specif.cmi Mem.cmi Maps.cmi Integers.cmi Globalenvs.cmi \
-    Floats.cmi Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi \
-    AST.cmi PPC.cmi 
-PPC.cmx: Values.cmx Specif.cmx Mem.cmx Maps.cmx Integers.cmx Globalenvs.cmx \
-    Floats.cmx Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx \
-    AST.cmx PPC.cmi 
-Registers.cmo: Specif.cmi OrderedType.cmi Ordered.cmi Maps.cmi FSetAVL.cmi \
-    Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi \
-    Registers.cmi 
-Registers.cmx: Specif.cmx OrderedType.cmx Ordered.cmx Maps.cmx FSetAVL.cmx \
-    Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx AST.cmx \
-    Registers.cmi 
-Reload.cmo: Specif.cmi Parallelmove.cmi Op.cmi Locations.cmi Linear.cmi \
-    LTLin.cmi Datatypes.cmi Conventions.cmi CList.cmi AST.cmi Reload.cmi 
-Reload.cmx: Specif.cmx Parallelmove.cmx Op.cmx Locations.cmx Linear.cmx \
-    LTLin.cmx Datatypes.cmx Conventions.cmx CList.cmx AST.cmx Reload.cmi 
+RTL.cmo: Values.cmi Registers.cmi Op.cmi Mem.cmi Maps.cmi Integers.cmi \
+    Globalenvs.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi \
+    RTL.cmi 
+RTL.cmx: Values.cmx Registers.cmx Op.cmx Mem.cmx Maps.cmx Integers.cmx \
+    Globalenvs.cmx Datatypes.cmx CList.cmx BinPos.cmx BinInt.cmx AST.cmx \
+    RTL.cmi 
 RTLgen.cmo: Switch.cmi Specif.cmi Registers.cmi ../caml/RTLgenaux.cmo RTL.cmi \
     Op.cmi Maps.cmi Integers.cmi Errors.cmi Datatypes.cmi Coqlib.cmi \
     CminorSel.cmi CString.cmi CList.cmi BinPos.cmi Ascii.cmi AST.cmi \
@@ -457,12 +447,6 @@ RTLgen.cmx: Switch.cmx Specif.cmx Registers.cmx ../caml/RTLgenaux.cmx RTL.cmx \
     Op.cmx Maps.cmx Integers.cmx Errors.cmx Datatypes.cmx Coqlib.cmx \
     CminorSel.cmx CString.cmx CList.cmx BinPos.cmx Ascii.cmx AST.cmx \
     RTLgen.cmi 
-RTL.cmo: Values.cmi Registers.cmi Op.cmi Mem.cmi Maps.cmi Integers.cmi \
-    Globalenvs.cmi Datatypes.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi \
-    RTL.cmi 
-RTL.cmx: Values.cmx Registers.cmx Op.cmx Mem.cmx Maps.cmx Integers.cmx \
-    Globalenvs.cmx Datatypes.cmx CList.cmx BinPos.cmx BinInt.cmx AST.cmx \
-    RTL.cmi 
 RTLtyping.cmo: Specif.cmi Registers.cmi ../caml/RTLtypingaux.cmo RTL.cmi \
     Op.cmi Maps.cmi Errors.cmi Datatypes.cmi Coqlib.cmi Conventions.cmi \
     CString.cmi CList.cmi BinPos.cmi BinInt.cmi Ascii.cmi AST.cmi \
@@ -471,6 +455,16 @@ RTLtyping.cmx: Specif.cmx Registers.cmx ../caml/RTLtypingaux.cmx RTL.cmx \
     Op.cmx Maps.cmx Errors.cmx Datatypes.cmx Coqlib.cmx Conventions.cmx \
     CString.cmx CList.cmx BinPos.cmx BinInt.cmx Ascii.cmx AST.cmx \
     RTLtyping.cmi 
+Registers.cmo: Specif.cmi OrderedType.cmi Ordered.cmi Maps.cmi FSetAVL.cmi \
+    Datatypes.cmi Coqlib.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi \
+    Registers.cmi 
+Registers.cmx: Specif.cmx OrderedType.cmx Ordered.cmx Maps.cmx FSetAVL.cmx \
+    Datatypes.cmx Coqlib.cmx CList.cmx BinPos.cmx BinInt.cmx AST.cmx \
+    Registers.cmi 
+Reload.cmo: Specif.cmi Parallelmove.cmi Op.cmi Locations.cmi Linear.cmi \
+    LTLin.cmi Datatypes.cmi Conventions.cmi CList.cmi AST.cmi Reload.cmi 
+Reload.cmx: Specif.cmx Parallelmove.cmx Op.cmx Locations.cmx Linear.cmx \
+    LTLin.cmx Datatypes.cmx Conventions.cmx CList.cmx AST.cmx Reload.cmi 
 Selection.cmo: Specif.cmi Op.cmi Integers.cmi Datatypes.cmi Compare_dec.cmi \
     CminorSel.cmi Cminor.cmi CList.cmi BinPos.cmi BinInt.cmi AST.cmi \
     Selection.cmi 
diff --git a/extraction/Makefile b/extraction/Makefile
index dd70d8803..4274e8e1b 100644
--- a/extraction/Makefile
+++ b/extraction/Makefile
@@ -28,9 +28,9 @@ FILES=\
   Mach.ml Bounds.ml Stacking.ml \
   PPC.ml PPCgen.ml \
   Main.ml \
-  ../caml/Cil2Csyntax.ml \
+  ../caml/PrintCsyntax.ml ../caml/Cil2Csyntax.ml \
   ../caml/CMparser.ml ../caml/CMlexer.ml ../caml/CMtypecheck.ml \
-  ../caml/PrintCsyntax.ml ../caml/PrintPPC.ml \
+  ../caml/PrintPPC.ml \
   ../caml/Configuration.ml ../caml/Driver.ml
 
 EXTRACTEDFILES:=$(filter-out ../caml/%, $(FILES))
diff --git a/test/c/Results/lists b/test/c/Results/lists
index d86bac9de..2c94e4837 100644
--- a/test/c/Results/lists
+++ b/test/c/Results/lists
@@ -1 +1,2 @@
 OK
+OK
diff --git a/test/cminor/sha1.cmp b/test/cminor/sha1.cmp
index 31c4b1786..9d7744c5c 100644
--- a/test/cminor/sha1.cmp
+++ b/test/cminor/sha1.cmp
@@ -125,11 +125,13 @@ extern "memset" : int -> int -> int -> void
 
 "SHA1_add_data"(ctx, data, len) : int -> int -> int -> void
 {
-  var t;
+  var t, t2;
 
   /* Update length */
   t = context_length_lo(ctx);
-  if ((context_length_lo(ctx) = t + (len << 3)) <u t)
+  t2 = t + (len << 3);
+  context_length_lo(ctx) = t2;
+  if (t2 <u t)
     context_length_hi(ctx) = context_length_hi(ctx) + 1;
   context_length_hi(ctx) = context_length_hi(ctx) + (len >>u 29);
 
-- 
GitLab