Section SEPARATE_COMPILATION.
(** The source: a list of C compilation units *)
Variable c_units: nlist Csyntax.program.
(** The compiled code: a list of Asm compilation units, obtained by separate compilation *)
Variable asm_units: nlist Asm.program.
Hypothesis separate_compilation_succeeds:
nlist_forall2 (fun cu tcu => transf_c_program cu = OK tcu) c_units asm_units.
(** We assume that the source C compilation units can be linked together to obtain a monolithic C program [c_program]. *)
Variable c_program: Csyntax.program.
Hypothesis source_linking: link_list c_units = Some c_program.
(** Let asm_program be the result of linking the Asm units. *)
Let asm_program: Asm.program := proj1_sig compiled_linking_succeeds.
Let compiled_linking: link_list asm_units = Some asm_program := proj2_sig compiled_linking_succeeds.
(** Then, [asm_program] preserves the semantics and the specifications of [c_program], in the following sense. First, every behavior of [asm_program] improves upon one of the possible behaviors of [c_program]. *)
(** As a corollary, if [c_program] is free of undefined behaviors, the behavior of [asm_program] is one of the possible behaviors of [c_program]. *)
(** We now show that if all executions of [c_program] satisfy a specification, then all executions of [asm_program] also satisfy the specification, provided the specification is of the safety-enforcing kind. *)
(** As another corollary of [separate_transf_c_program_preservation], if all executions of [c_program] have a trace [t] as initial trace, so do all executions of [asm_program]. *)

Theorem separate_transf_c_program_preserves_initial_trace:
forall t,
c_program_has_initial_trace c_program t ->
asm_program_has_initial_trace asm_program t.