Separate compilation proof for the MC generation *
Require Import Coqlib Integers Values Maps AST.
Require Import Asm FlatAsmProgram MC MCgen MCgenproof.
Require Import Segment.
Require Import Linking Errors FlatAsmSep.
Require Import Num.
Definition de_transl_instr (
i:
MC.instr_with_info) :
FlatAsm.instr_with_info :=
let '(
i',
sb,
id) :=
i in
let i'' :=
match i'
with
|
MCjmp_l l ofs =>
Pjmp_l l
|
MCjcc c l ofs =>
Pjcc c l
|
MCjcc2 c1 c2 l ofs =>
Pjcc2 c1 c2 l
|
MCjmptbl r tbl ol =>
Pjmptbl r tbl
|
MCAsminstr i =>
i
end in
(
i'',
sb,
id).
Definition de_transl_fun (
f : @
function MC.instruction) : @
function Asm.instruction :=
let code' :=
List.map de_transl_instr (
fn_code f)
in
FlatAsmProgram.mkfunction (
fn_sig f)
code' (
fn_range f) (
fn_stacksize f) (
fn_pubrange f).
Definition de_transl_globdef (
def:
ident *
option FlatAsmProgram.gdef *
segblock) :=
let '(
id,
def,
sb) :=
def in
match def with
|
None => (
id,
None,
sb)
|
Some (
Gfun (
Internal f)) => (
id,
Some (
Gfun (
Internal (
de_transl_fun f))),
sb)
|
Some (
Gfun (
External f)) => (
id,
Some (
Gfun (
External f)),
sb)
|
Some (
Gvar v) => (
id,
Some (
Gvar v),
sb)
end.
Definition mc_to_flatasm (
p:
FlatAsmProgram.program) :
FlatAsm.program :=
let prog_defs :=
List.map de_transl_globdef (
prog_defs p)
in
let prog_public := (
prog_public p)
in
let prog_main := (
prog_main p)
in
Build_program prog_defs prog_public prog_main
(
data_seg p) (
code_seg p) (
glob_map p) (
lbl_map p) (
prog_senv p).
Definition link_mcprog (
p1 p2:
MC.program) :
option MC.program :=
match link (
mc_to_flatasm p1) (
mc_to_flatasm p2)
with
|
None =>
None
|
Some p =>
match (
transf_program p)
with
|
OK p' =>
Some p'
|
Error _ =>
None
end
end.
Instance Linker_mcprog :
Linker MC.program := {
link :=
link_mcprog;
linkorder :=
fun p1 p2 =>
True
}.
Proof.
- auto.
- auto.
- auto.
Defined.
Lemma transl_instr_from_flat_asm_succeeds:
forall o i s0 i1 l i1',
is_valid_label l i1' ->
FlatAsmgen.transl_instr o i s0 i1 =
OK i1' ->
exists ins,
transl_instr l i i1' =
OK ins.
Proof.
unfold FlatAsmgen.transl_instr.
intros o i s0 i1 l i1'
H0 H1.
repeat destr_in H1;
simpl in *;
eauto.
-
unfold get_lbl_offset.
destr.
simpl.
eauto.
-
unfold get_lbl_offset.
destr.
simpl.
eauto.
-
unfold get_lbl_offset.
destr.
simpl.
eauto.
-
assert (
forall s,
exists o,
get_lbl_list_offset l i tbl s =
OK o).
{
revert H0.
induction 1;
simpl;
intros;
eauto.
unfold get_lbl_offset.
destr.
simpl.
edestruct IHForall as (
oo &
EQ);
eauto.
rewrite EQ.
simpl;
eauto.
}
edestruct H as (
oo &
EQ).
erewrite EQ.
simpl.
eauto.
Qed.
Lemma transl_instrs_from_flat_asm_succeeds:
forall i s0 c i0 x0 x1 l,
Forall (
is_valid_label l)
x1 ->
FlatAsmgen.transl_instrs i s0 i0 c =
OK (
x0,
x1) ->
exists ins,
transl_instrs l i x1 =
OK ins.
Proof.
induction c;
simpl;
intros;
eauto.
inv H0;
simpl;
eauto.
monadInv H0.
simpl.
inv H.
edestruct transl_instr_from_flat_asm_succeeds as (
ins &
TI);
eauto.
rewrite TI.
simpl.
edestruct IHc as (
inss &
TIS);
eauto.
rewrite TIS.
simpl;
eauto.
Qed.
Lemma transl_globdef_from_flat_asm_succeeds:
forall g l i d1 d2,
(
forall f,
snd (
fst d2) =
Some (
Gfun (
Internal f)) ->
Forall (
is_valid_label l) (
fn_code f)) ->
FlatAsmgen.transl_globdef g i d1 =
OK d2 ->
exists d3,
transl_globdef l d2 =
OK d3.
Proof.
Lemma
transl_globdefs_from_flat_asm_succeeds:
forall g l d1 d2,
Forall (
fun '(
_,
d,
_) =>
forall f,
d =
Some (
Gfun (
Internal f)) ->
Forall (
is_valid_label l) (
fn_code f))
d2 ->
FlatAsmgen.transl_globdefs g d1 =
OK d2 ->
exists d3,
transl_globdefs l d2 =
OK d3.
Proof.
induction d1;
simpl;
intros;
eauto.
inv H0;
simpl;
eauto.
destr_in H0.
monadInv H0.
simpl.
edestruct transl_globdef_from_flat_asm_succeeds as (
oo &
EQQ);
eauto.
inv H.
repeat destr_in H2.
simpl;
intros;
subst.
simpl.
eauto.
inv H.
edestruct IHd1 as (
ins &
TG);
eauto.
rewrite TG.
rewrite EQQ.
simpl;
eauto.
Qed.
Lemma transl_globdefs_back:
forall defs g tdefs x,
FlatAsmgen.transl_globdefs g defs =
OK tdefs ->
In x tdefs ->
exists i y,
In (
i,
y)
defs /\
FlatAsmgen.transl_globdef g i y =
OK x.
Proof.
induction defs; simpl; intros; eauto. inv H; easy.
destr_in H. monadInv H. simpl in H0. destruct H0.
- subst. do 2 eexists; split. left; eauto. auto.
- edestruct IHdefs as (ii & y & IN & TG); eauto.
Qed.
Lemma update_maps_labels:
forall defs g l c d g'
l'
c'
d',
list_norepet (
map fst defs) ->
(
forall i,
In i (
map fst defs) ->
forall lab,
l i lab =
None) ->
FlatAsmgen.update_maps g l c d defs = (
g',
l',
c',
d') ->
forall i lab,
l'
i lab <>
None <-> (
l i lab <>
None \/
exists f,
In (
i,
Some (
Gfun (
Internal f)))
defs /\
In lab (
FlatAsmgen.labels (
Asm.fn_code f))).
Proof.
induction defs;
simpl;
intros g l c d g'
l'
c'
d'
LNR NOLAB UM i lab.
-
inv UM.
split.
tauto.
intros [
A|(? & [] & ?)];
auto.
-
destruct a.
rewrite FlatAsmgenproof.update_maps_cons in UM.
repeat destr_in UM.
erewrite IHdefs. 4:
eauto.
split.
+
intros [
A | (
f &
IN1 &
IN2)];
eauto.
*
erewrite FlatAsmgenproof.update_lmap in A. 2:
eauto.
repeat destr_in A.
subst.
right.
eexists;
split.
left.
eauto.
simpl in LNR.
inv LNR.
simpl in *.
destr_in Heqp.
simpl in *.
inv Heqp.
destruct (
in_dec peq lab (
FlatAsmgen.labels (
Asm.fn_code f0))).
auto.
eapply FlatAsmgenproof.update_instrs_other_label in Heqp0;
eauto.
rewrite Heqp0 in A.
destruct A.
apply NOLAB.
auto.
+
intros [
A | (
f &
IN1 &
IN2)];
eauto.
*
erewrite FlatAsmgenproof.update_lmap. 2:
eauto.
repeat destr.
subst.
simpl in *.
destr_in Heqp.
simpl in *.
inv Heqp.
rewrite NOLAB in A.
congruence.
auto.
*
destruct IN1 as [
A|
IN1];
eauto.
inv A.
simpl in *.
repeat destr_in Heqp.
edestruct FlatAsmgenproof.update_instrs_in_lbl as (
sid &
ofs &
EQ);
eauto.
rewrite EQ.
left;
congruence.
+
inv LNR;
auto.
+
intros.
erewrite FlatAsmgenproof.update_lmap. 2:
eauto.
simpl in LNR.
inv LNR.
erewrite <- (
NOLAB i1)
with (
lab :=
lab0);
auto.
repeat destr.
Qed.
Lemma make_maps_labels:
forall p g l c d,
list_norepet (
map fst (
AST.prog_defs p)) ->
FlatAsmgen.make_maps p = (
g,
l,
c,
d) ->
forall i lab,
l i lab <>
None <->
exists f,
In (
i,
Some (
Gfun (
Internal f))) (
AST.prog_defs p) /\
In lab (
FlatAsmgen.labels (
Asm.fn_code f)).
Proof.
Lemma transl_instrs_valid_label:
forall labs i l c s0 i0 x x0,
Forall
(
fun i1 :
Asm.instruction =>
forall lab :
label,
FlatAsmgen.has_label i1 lab ->
In lab labs)
c ->
(
forall lab :
label,
In lab labs ->
l i lab <>
None) ->
FlatAsmgen.transl_instrs i s0 i0 c =
OK (
x,
x0) ->
Forall (
is_valid_label l)
x0.
Proof.
induction c;
simpl;
intros s0 i0 x x0 H H0 H1;
eauto.
inv H1.
constructor.
monadInv H1.
inv H.
constructor;
eauto.
-
destruct a;
simpl in EQ;
inv EQ;
simpl in *;
auto.
rewrite Forall_forall;
intros;
apply H0.
auto.
Qed.
Lemma transl_fun_valid_label:
forall g i f tf l,
FlatAsmgen.transl_fun g i f =
OK tf ->
Forall (
fun i =>
forall lab,
FlatAsmgen.has_label i lab ->
In lab (
FlatAsmgen.labels (
Asm.fn_code f)))
(
Asm.fn_code f) ->
(
forall lab,
In lab (
FlatAsmgen.labels (
Asm.fn_code f)) ->
l i lab <>
None) ->
Forall (
is_valid_label l) (
fn_code tf).
Proof.
Lemma transf_prog_combine :
forall (
p1 p2:
FlatAsm.program) (
tp1 tp2:
MC.program)
p
(
LK:
link p1 p2 =
Some p)
(
TF1:
transf_program p1 =
OK tp1)
(
TF2:
transf_program p2 =
OK tp2),
exists tp,
transf_program p =
OK tp.
Proof.
Lemma transl_instr_inv :
forall l fid i i',
transl_instr l fid i =
OK i' ->
de_transl_instr i' =
i.
Proof.
intros. destruct i. destruct p. destruct i0; simpl in H; monadInv H; auto.
monadInv EQ. auto.
monadInv EQ. auto.
monadInv EQ. auto.
monadInv EQ. auto.
Qed.
Lemma transl_instrs_inv :
forall l fid code code',
transl_instrs l fid code =
OK code' ->
map de_transl_instr code' =
code.
Proof.
induction code;
simpl;
intros.
-
inv H.
auto.
-
monadInv H.
simpl.
erewrite transl_instr_inv;
eauto.
erewrite IHcode;
eauto.
Qed.
Lemma transl_fun_inv:
forall g i f f',
transl_fun g i f =
OK f' ->
de_transl_fun f' =
f.
Proof.
Lemma transl_globdef_inv:
forall l def def',
transl_globdef l def =
OK def' ->
de_transl_globdef def' =
def.
Proof.
intros.
destruct def.
destruct p.
destruct o.
destruct g.
destruct f.
-
monadInv H.
simpl.
erewrite transl_fun_inv;
eauto.
-
monadInv H.
simpl.
auto.
-
monadInv H.
simpl.
auto.
-
monadInv H.
simpl.
auto.
Qed.
Lemma transl_globdefs_inv:
forall g defs defs',
transl_globdefs g defs =
OK defs' ->
map de_transl_globdef defs' =
defs.
Proof.
induction defs;
simpl;
intros.
-
inv H.
auto.
-
destruct a.
monadInv H.
simpl.
erewrite transl_globdef_inv;
eauto.
erewrite IHdefs;
eauto.
Qed.
Lemma transf_prog_inv :
forall p tp,
transf_program p =
OK tp ->
mc_to_flatasm tp =
p.
Proof.
Instance TransfMCLink :
TransfLink match_prog.
Proof.
red.
unfold match_prog.
simpl link.
intros p1 p2 tp1 tp2 p LK MC1 MC2.
exploit transf_prog_combine;
eauto.
intros H.
destruct H as [
p'
TF].
exists p'.
split.
unfold link_mcprog.
repeat (
erewrite transf_prog_inv;
eauto).
simpl link.
rewrite LK.
rewrite TF.
auto.
auto.
Defined.