(** * Commutation between linking and program transformations *)
Section LINK_MATCH_PROGRAM.
Context {C F1 V1 F2 V2: Type} {LC: Linker C} {LF1: Linker F1} {LF2: Linker F2} {LV1: Linker V1} {LV2: Linker V2}.
Variable match_fundef: C -> F1 -> F2 -> Prop.
Variable match_varinfo: V1 -> V2 -> Prop.
Local Transparent Linker_vardef Linker_def Linker_prog.
Hypothesis link_match_fundef:
forall ctx1 ctx2 f1 tf1 f2 tf2 f,
link f1 f2 = Some f ->
match_fundef ctx1 f1 tf1 -> match_fundef ctx2 f2 tf2 ->
exists tf, link tf1 tf2 = Some tf /\ (match_fundef ctx1 f tf \/ match_fundef ctx2 f tf).
Hypothesis link_match_varinfo:
forall v1 tv1 v2 tv2 v,
link v1 v2 = Some v ->
match_varinfo v1 tv1 -> match_varinfo v2 tv2 ->
exists tv, link tv1 tv2 = Some tv /\ match_varinfo v tv.

(* Specifications: *)
Lemma link_match_globvar:
forall v1 tv1 v2 tv2 v,
link v1 v2 = Some v ->
match_globvar match_varinfo v1 tv1 -> match_globvar match_varinfo v2 tv2 ->
exists tv, link tv1 tv2 = Some tv /\ match_globvar match_varinfo v tv.
Lemma link_match_globdef:
forall ctx1 ctx2 ctx g1 tg1 g2 tg2 g,
linkorder ctx1 ctx -> linkorder ctx2 ctx ->
link g1 g2 = Some g ->
match_globdef match_fundef match_varinfo ctx1 g1 tg1 ->
match_globdef match_fundef match_varinfo ctx2 g2 tg2 ->
exists tg, link tg1 tg2 = Some tg /\ match_globdef match_fundef match_varinfo ctx g tg.
Lemma match_globdef_linkorder:
forall ctx ctx' g tg,
match_globdef match_fundef match_varinfo ctx g tg ->
linkorder ctx ctx' ->
match_globdef match_fundef match_varinfo ctx' g tg.
Theorem link_match_program:
forall ctx1 ctx2 ctx p1 p2 tp1 tp2 p,
link p1 p2 = Some p ->
match_program_gen match_fundef match_varinfo ctx1 p1 tp1 ->
match_program_gen match_fundef match_varinfo ctx2 p2 tp2 ->
linkorder ctx1 ctx -> linkorder ctx2 ctx ->
exists tp, link tp1 tp2 = Some tp /\ match_program_gen match_fundef match_varinfo ctx p tp.
Lemma link_match_globvar:
forall v1 tv1 v2 tv2 v,
link v1 v2 = Some v ->
match_globvar match_varinfo v1 tv1 -> match_globvar match_varinfo v2 tv2 ->
exists tv, link tv1 tv2 = Some tv /\ match_globvar match_varinfo v tv.
Lemma link_match_globdef:
forall ctx1 ctx2 ctx g1 tg1 g2 tg2 g,
linkorder ctx1 ctx -> linkorder ctx2 ctx ->
link g1 g2 = Some g ->
match_globdef match_fundef match_varinfo ctx1 g1 tg1 ->
match_globdef match_fundef match_varinfo ctx2 g2 tg2 ->
exists tg, link tg1 tg2 = Some tg /\ match_globdef match_fundef match_varinfo ctx g tg.
Lemma match_globdef_linkorder:
forall ctx ctx' g tg,
match_globdef match_fundef match_varinfo ctx g tg ->
linkorder ctx ctx' ->
match_globdef match_fundef match_varinfo ctx' g tg.
Theorem link_match_program:
forall ctx1 ctx2 ctx p1 p2 tp1 tp2 p,
link p1 p2 = Some p ->
match_program_gen match_fundef match_varinfo ctx1 p1 tp1 ->
match_program_gen match_fundef match_varinfo ctx2 p2 tp2 ->
linkorder ctx1 ctx -> linkorder ctx2 ctx ->
exists tp, link tp1 tp2 = Some tp /\ match_program_gen match_fundef match_varinfo ctx p tp.