Notation val_inject:= Val.inject.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** * Structured Injections *)

Record SM_Injection :=
  { (** The blocks allocated by *this* module in the source language. *)
    locBlocksSrc : block -> bool

    (** The blocks allocated by *this* module in the target language. *)
  ; locBlocksTgt : block -> bool

    (** The subset of local source blocks that have been made public. Must be mapped. *)
  ; pubBlocksSrc : block -> bool

    (** The subset of local target blocks that have been made public. Contains the image
        of the public source blocks. *)
  ; pubBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by *this* module. *)
  ; local_of: meminj

    (** The blocks allocated by *other* modules at the source level. *)
  ; extBlocksSrc: block -> bool

    (** The blocks allocated by *other* modules at the target level. *)
  ; extBlocksTgt: block -> bool

    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksSrc : block -> bool


    (** The subset of extern source blocks that have been made public. Must be mapped. *)
  ; frgnBlocksTgt : block -> bool

    (** Memory injection on blocks allocated by OTHER modules; the injection is
        not modified by coresteps, and is partitioned by frgnBlocksSrc/Tgt into
        foreign (leaked to this module) and unknown (non-leaked) components,
        where the former blocks are accessible by *this* module. This module
        behaves uniformly over block mentioned by frgnInj, and assumes that
        blocks in frgnInj remain mapped. Compilation of *this* module neither
        merges nor unmaps blocks from here, nor does it spill into them. *)
  ; extern_of: meminj }.(** The four projections: *)

Definition unknown_of (mu: SM_Injection) : meminj :=
  match mu with
    Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
    fun b => if locBSrc b then None else if fSrc b then None else extern b
  end.Definition foreign_of (mu: SM_Injection) : meminj :=
  match mu with
    Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
    fun b => if fSrc b then extern b else None
  end.Definition pub_of (mu: SM_Injection) : meminj :=
  match mu with
    Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
    fun b => if pSrc b then local b else None
  end.Definition priv_of (mu: SM_Injection) : meminj :=
  match mu with
    Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
    fun b => if pSrc b then None else local b
  end.

Lemma inject_incr_coincide: forall f g (INC: inject_incr f g) b p (G:g b = Some p) q (F:f b = Some q),p=q.