Ltac DestructM :=
  match goal with
    [ H: exists p, _ /\ _ |- _ ] =>
      let p := fresh "p" in let M := fresh "M" in let MM := fresh "MM" in
      destruct H as (p & M & MM); clear H
  end.

(* Specifications: *)
Theorem c_semantic_preservation: forall p tp, match_prog p tp -> backward_simulation (Csem.semantics p) (Asm.semantics tp).
Theorem transf_c_program_correct: forall p tp, transf_c_program p = OK tp -> backward_simulation (Csem.semantics p) (Asm.semantics tp).
Theorem separate_transf_c_program_correct: forall c_units asm_units c_program, nlist_forall2 (fun cu tcu => transf_c_program cu = OK tcu) c_units asm_units -> link_list c_units = Some c_program -> exists asm_program, link_list asm_units = Some asm_program /\ backward_simulation (Csem.semantics c_program) (Asm.semantics asm_program).