(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Xavier Leroy, INRIA Paris-Rocquencourt                     *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)
(** Corollaries of the main semantic preservation theorem. *)
(** * Preservation of whole-program behaviors *)
(** From the simulation diagrams proved in file [Compiler]. it follows that whole-program observable behaviors are preserved in the following sense. First, every behavior of the generated assembly code is matched by a behavior of the source C code.  The behavior [beh] of the assembly code is either identical to the behavior [beh'] of the source C code or ``improves upon'' [beh']  by replacing a ``going wrong'' behavior with a more defined behavior. *)
(** As a corollary, if the source C code cannot go wrong, i.e. is free of undefined behaviors, the behavior of the generated assembly code is one of the possible behaviors of the source C code. *)
(** If we consider the C evaluation strategy implemented by the compiler, we get stronger preservation results. *)
(** We can also use the alternate big-step semantics for [Cstrategy] to establish behaviors of the generated assembly code. *)
(** * Satisfaction of specifications *)
(** The second additional results shows that if all executions of the source C program satisfies a given specification, then all executions of the produced Asm program satisfy this specification as well.  *)
(** The specifications we consider here are sets of observable behaviors, representing the good behaviors a program is expected to have.  A specification can be as simple as ``the program does not go wrong'' or as precise as ``the program prints a prime number then terminates with code 0''. As usual in Coq, sets of behaviors are represented as predicates [program_behavior -> Prop]. *)
Definition specification := program_behavior -> Prop.
(** A program satisfies a specification if all its observable behaviors are in the specification. *)
Definition c_program_satisfies_spec (p: Csyntax.program) (spec: specification): Prop :=
forall beh,  program_behaves (Csem.semantics p) beh -> spec beh.
Definition asm_program_satisfies_spec (p: Asm.program) (spec: specification): Prop :=
forall beh,  program_behaves (Asm.semantics p) beh -> spec beh.
(** It is not always the case that if the source program satisfies a specification, then the generated assembly code satisfies it as well.  For example, if the specification is ``the program goes wrong on an undefined behavior'', a C source that goes wrong satisfies this specification but can be compiled into Asm code that does not go wrong and therefore does not satisfy the specification.  For this reason, we restrict ourselves to safety-enforcing specifications: specifications that exclude ``going wrong'' behaviors and are satisfied only by programs that execute safely. *)
Definition safety_enforcing_specification (spec: specification): Prop :=
forall beh, spec beh -> not_wrong beh.
(** As the main result of this section, we show that CompCert compilation preserves safety-enforcing specifications: any such specification that is satisfied by the source C program is always satisfied by the generated assembly code. *)
(** Safety-enforcing specifications are not the only good properties of source programs that are preserved by compilation.  Another example of a property that is preserved is the ``initial trace'' property: all executions of the program start by producing an expected trace of I/O actions, representing the good behavior expected from the program. After that, the program may terminate, or continue running, or go wrong on an undefined behavior.  What matters is that the program produced the expected trace at the beginning of its execution.  This is a typical liveness property, and it is preserved by compilation. *)
Definition c_program_has_initial_trace (p: Csyntax.program) (t: trace): Prop :=
forall beh, program_behaves (Csem.semantics p) beh -> behavior_prefix t beh.
Definition asm_program_has_initial_trace (p: Asm.program) (t: trace): Prop :=
forall beh, program_behaves (Asm.semantics p) beh -> behavior_prefix t beh.

Theorem transf_c_program_preserves_initial_trace:
forall p tp t,
transf_c_program p = OK tp ->
c_program_has_initial_trace p t ->
asm_program_has_initial_trace tp t.