Notation CoreSem Sem :=(semantics.csem(event_semantics.msem (semSem Sem))).Inductive match_thread_source:
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | SThread_Running: forall j code1 m1 code2 m2,
      source_match j code1 m1 code2 m2 ->
      match_thread_source
        j (Krun (SState _ _ code1)) m1
        (Krun (SState _ _ code2)) m2
  | SThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      source_match j code1 m1 code2 m2 ->
      match_thread_source  j (Kblocked (SState _ _ code1)) m1
                          (Kblocked (SState _ _ code2)) m2
  | SThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
    semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
    semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
    Val.inject_list j ls1 ls2 ->
    semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
    semantics.after_external (CoreSem Sems) genvS None code2 = Some code2' ->
    source_match j code1' m2 code2' m2 ->
    match_thread_source j (Kresume (SState _ _ code1) v) m1
                        (Kresume (SState _ _ code2) v') m2
| SThread_Init: forall j m1 m2 v1 v1' v2 v2',
    Val.inject j v1 v2 ->
    Val.inject j v1' v2' ->
    match_thread_source j (Kinit v1 v1') m1
                        (Kinit v2 v2') m2.Inductive match_thread_source:
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | SThread_Running: forall j code1 m1 code2 m2,
      source_match j code1 m1 code2 m2 ->
      match_thread_source
        j (Krun (SState _ _ code1)) m1
        (Krun (SState _ _ code2)) m2
  | SThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      source_match j code1 m1 code2 m2 ->
      match_thread_source  j (Kblocked (SState _ _ code1)) m1
                          (Kblocked (SState _ _ code2)) m2
  | SThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
    semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
    semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
    Val.inject_list j ls1 ls2 ->
    semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
    semantics.after_external (CoreSem Sems) genvS None code2 = Some code2' ->
    source_match j code1' m2 code2' m2 ->
    match_thread_source j (Kresume (SState _ _ code1) v) m1
                        (Kresume (SState _ _ code2) v') m2
| SThread_Init: forall j m1 m2 v1 v1' v2 v2',
    Val.inject j v1 v2 ->
    Val.inject j v1' v2' ->
    match_thread_source j (Kinit v1 v1') m1
                        (Kinit v2 v2') m2.Inductive match_thread_source:
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | SThread_Running: forall j code1 m1 code2 m2,
      source_match j code1 m1 code2 m2 ->
      match_thread_source
        j (Krun (SState _ _ code1)) m1
        (Krun (SState _ _ code2)) m2
  | SThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      source_match j code1 m1 code2 m2 ->
      match_thread_source  j (Kblocked (SState _ _ code1)) m1
                          (Kblocked (SState _ _ code2)) m2
  | SThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
    semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
    semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
    Val.inject_list j ls1 ls2 ->
    semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
    semantics.after_external (CoreSem Sems) genvS None code2 = Some code2' ->
    source_match j code1' m2 code2' m2 ->
    match_thread_source j (Kresume (SState _ _ code1) v) m1
                        (Kresume (SState _ _ code2) v') m2
| SThread_Init: forall j m1 m2 v1 v1' v2 v2',
    Val.inject j v1 v2 ->
    Val.inject j v1' v2' ->
    match_thread_source j (Kinit v1 v1') m1
                        (Kinit v2 v2') m2.Inductive match_thread_source:
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | SThread_Running: forall j code1 m1 code2 m2,
      source_match j code1 m1 code2 m2 ->
      match_thread_source
        j (Krun (SState _ _ code1)) m1
        (Krun (SState _ _ code2)) m2
  | SThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      source_match j code1 m1 code2 m2 ->
      match_thread_source  j (Kblocked (SState _ _ code1)) m1
                          (Kblocked (SState _ _ code2)) m2
  | SThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
    semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
    semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
    Val.inject_list j ls1 ls2 ->
    semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
    semantics.after_external (CoreSem Sems) genvS None code2 = Some code2' ->
    source_match j code1' m2 code2' m2 ->
    match_thread_source j (Kresume (SState _ _ code1) v) m1
                        (Kresume (SState _ _ code2) v') m2
| SThread_Init: forall j m1 m2 v1 v1' v2 v2',
    Val.inject j v1 v2 ->
    Val.inject j v1' v2' ->
    match_thread_source j (Kinit v1 v1') m1
                        (Kinit v2 v2') m2.Inductive match_thread_source:
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | SThread_Running: forall j code1 m1 code2 m2,
      source_match j code1 m1 code2 m2 ->
      match_thread_source
        j (Krun (SState _ _ code1)) m1
        (Krun (SState _ _ code2)) m2
  | SThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      source_match j code1 m1 code2 m2 ->
      match_thread_source  j (Kblocked (SState _ _ code1)) m1
                          (Kblocked (SState _ _ code2)) m2
  | SThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
    semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
    semantics.at_external (CoreSem Sems) genvS code2 m2 = Some (f',ls2) ->
    Val.inject_list j ls1 ls2 ->
    semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
    semantics.after_external (CoreSem Sems) genvS None code2 = Some code2' ->
    source_match j code1' m2 code2' m2 ->
    match_thread_source j (Kresume (SState _ _ code1) v) m1
                        (Kresume (SState _ _ code2) v') m2
| SThread_Init: forall j m1 m2 v1 v1' v2 v2',
    Val.inject j v1 v2 ->
    Val.inject j v1' v2' ->
    match_thread_source j (Kinit v1 v1') m1
                        (Kinit v2 v2') m2.Inductive match_thread_target :
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | TThread_Running: forall j code1 m1 code2 m2,
      target_match j code1 m1 code2 m2 ->
      match_thread_target  j (Krun (TState _ _ code1)) m1
                          (Krun (TState _ _ code2)) m2
  | TThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      target_match j code1 m1 code2 m2 ->
      match_thread_target j (Kblocked (TState _ _ code1)) m1
                          (Kblocked (TState _ _ code2)) m2
  | TThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Semt) genvT None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      target_match j code1' m2 code2' m2 ->
      match_thread_target j (Kresume (TState _ _ code1) v) m1
                          (Kresume (TState _ _ code2) v') m2
  | TThread_Init: forall j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_target j (Kinit v1 v1') m1
                          (Kinit v2 v2') m2.Inductive match_thread_target :
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | TThread_Running: forall j code1 m1 code2 m2,
      target_match j code1 m1 code2 m2 ->
      match_thread_target  j (Krun (TState _ _ code1)) m1
                          (Krun (TState _ _ code2)) m2
  | TThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      target_match j code1 m1 code2 m2 ->
      match_thread_target j (Kblocked (TState _ _ code1)) m1
                          (Kblocked (TState _ _ code2)) m2
  | TThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Semt) genvT None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      target_match j code1' m2 code2' m2 ->
      match_thread_target j (Kresume (TState _ _ code1) v) m1
                          (Kresume (TState _ _ code2) v') m2
  | TThread_Init: forall j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_target j (Kinit v1 v1') m1
                          (Kinit v2 v2') m2.Inductive match_thread_target :
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | TThread_Running: forall j code1 m1 code2 m2,
      target_match j code1 m1 code2 m2 ->
      match_thread_target  j (Krun (TState _ _ code1)) m1
                          (Krun (TState _ _ code2)) m2
  | TThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      target_match j code1 m1 code2 m2 ->
      match_thread_target j (Kblocked (TState _ _ code1)) m1
                          (Kblocked (TState _ _ code2)) m2
  | TThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Semt) genvT None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      target_match j code1' m2 code2' m2 ->
      match_thread_target j (Kresume (TState _ _ code1) v) m1
                          (Kresume (TState _ _ code2) v') m2
  | TThread_Init: forall j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_target j (Kinit v1 v1') m1
                          (Kinit v2 v2') m2.Inductive match_thread_target :
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | TThread_Running: forall j code1 m1 code2 m2,
      target_match j code1 m1 code2 m2 ->
      match_thread_target  j (Krun (TState _ _ code1)) m1
                          (Krun (TState _ _ code2)) m2
  | TThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      target_match j code1 m1 code2 m2 ->
      match_thread_target j (Kblocked (TState _ _ code1)) m1
                          (Kblocked (TState _ _ code2)) m2
  | TThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Semt) genvT None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      target_match j code1' m2 code2' m2 ->
      match_thread_target j (Kresume (TState _ _ code1) v) m1
                          (Kresume (TState _ _ code2) v') m2
  | TThread_Init: forall j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_target j (Kinit v1 v1') m1
                          (Kinit v2 v2') m2.Inductive match_thread_target :
    meminj -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | TThread_Running: forall j code1 m1 code2 m2,
      target_match j code1 m1 code2 m2 ->
      match_thread_target  j (Krun (TState _ _ code1)) m1
                          (Krun (TState _ _ code2)) m2
  | TThread_Blocked: forall j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      target_match j code1 m1 code2 m2 ->
      match_thread_target j (Kblocked (TState _ _ code1)) m1
                          (Kblocked (TState _ _ code2)) m2
  | TThread_Resume: forall j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Semt) genvT code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Semt) genvT None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      target_match j code1' m2 code2' m2 ->
      match_thread_target j (Kresume (TState _ _ code1) v) m1
                          (Kresume (TState _ _ code2) v') m2
  | TThread_Init: forall j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_target j (Kinit v1 v1') m1
                          (Kinit v2 v2') m2.(* match_compiled_states *)
  
  Inductive match_thread_compiled:
    compiler_index -> meminj ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | CThread_Running: forall cd j code1 m1 code2 m2,
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled cd j (Krun (SState _ _ code1)) m1
                            (Krun (TState _ _ code2)) m2
  | CThread_Blocked: forall cd j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1  = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled  cd j (Kblocked (SState _ _ code1)) m1
                            (Kblocked (TState _ _ code2)) m2
  | CThread_Resume: forall cd j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      match_compiled_states cd j code1' m1 code2' m2 ->
      match_thread_compiled cd j (Kresume (SState _ _ code1) v) m1
                            (Kresume (TState _ _ code2) v') m2
  | CThread_Init: forall cd j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_compiled cd j (Kinit v1 v1') m1
                            (Kinit v2 v2') m2.(* match_compiled_states *)
  
  Inductive match_thread_compiled:
    compiler_index -> meminj ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | CThread_Running: forall cd j code1 m1 code2 m2,
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled cd j (Krun (SState _ _ code1)) m1
                            (Krun (TState _ _ code2)) m2
  | CThread_Blocked: forall cd j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1  = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled  cd j (Kblocked (SState _ _ code1)) m1
                            (Kblocked (TState _ _ code2)) m2
  | CThread_Resume: forall cd j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      match_compiled_states cd j code1' m1 code2' m2 ->
      match_thread_compiled cd j (Kresume (SState _ _ code1) v) m1
                            (Kresume (TState _ _ code2) v') m2
  | CThread_Init: forall cd j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_compiled cd j (Kinit v1 v1') m1
                            (Kinit v2 v2') m2.(* match_compiled_states *)
  
  Inductive match_thread_compiled:
    compiler_index -> meminj ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | CThread_Running: forall cd j code1 m1 code2 m2,
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled cd j (Krun (SState _ _ code1)) m1
                            (Krun (TState _ _ code2)) m2
  | CThread_Blocked: forall cd j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1  = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled  cd j (Kblocked (SState _ _ code1)) m1
                            (Kblocked (TState _ _ code2)) m2
  | CThread_Resume: forall cd j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      match_compiled_states cd j code1' m1 code2' m2 ->
      match_thread_compiled cd j (Kresume (SState _ _ code1) v) m1
                            (Kresume (TState _ _ code2) v') m2
  | CThread_Init: forall cd j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_compiled cd j (Kinit v1 v1') m1
                            (Kinit v2 v2') m2.(* match_compiled_states *)
  
  Inductive match_thread_compiled:
    compiler_index -> meminj ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | CThread_Running: forall cd j code1 m1 code2 m2,
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled cd j (Krun (SState _ _ code1)) m1
                            (Krun (TState _ _ code2)) m2
  | CThread_Blocked: forall cd j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1  = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled  cd j (Kblocked (SState _ _ code1)) m1
                            (Kblocked (TState _ _ code2)) m2
  | CThread_Resume: forall cd j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      match_compiled_states cd j code1' m1 code2' m2 ->
      match_thread_compiled cd j (Kresume (SState _ _ code1) v) m1
                            (Kresume (TState _ _ code2) v') m2
  | CThread_Init: forall cd j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_compiled cd j (Kinit v1 v1') m1
                            (Kinit v2 v2') m2.(* match_compiled_states *)
  
  Inductive match_thread_compiled:
    compiler_index -> meminj ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem ->
    @ctl (state_sum (semC Sems) (semC Semt)) -> mem -> Prop  :=
  | CThread_Running: forall cd j code1 m1 code2 m2,
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled cd j (Krun (SState _ _ code1)) m1
                            (Krun (TState _ _ code2)) m2
  | CThread_Blocked: forall cd j code1 m1 code2 m2 ls1 ls2 f f',
      semantics.at_external (CoreSem Sems) genvS code1 m1  = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      match_compiled_states cd j code1 m1 code2 m2 ->
      match_thread_compiled  cd j (Kblocked (SState _ _ code1)) m1
                            (Kblocked (TState _ _ code2)) m2
  | CThread_Resume: forall cd j code1 m1 code2 m2 ls1 ls2 f f' v v' code1' code2',
      (*Do I need to keep this two? Probanly not*)
      semantics.at_external (CoreSem Sems) genvS code1 m1 = Some (f,ls1) ->
      semantics.at_external (CoreSem Semt) genvT code2 m2 = Some (f',ls2) ->
      Val.inject_list j ls1 ls2 ->
      semantics.after_external (CoreSem Sems) genvS None code1 = Some code1' ->
      semantics.after_external (CoreSem Semt) genvT None code2 = Some code2' ->
      match_compiled_states cd j code1' m1 code2' m2 ->
      match_thread_compiled cd j (Kresume (SState _ _ code1) v) m1
                            (Kresume (TState _ _ code2) v') m2
  | CThread_Init: forall cd j m1 m2 v1 v1' v2 v2',
      Val.inject j v1 v2 ->
      Val.inject j v1' v2' ->
      match_thread_compiled cd j (Kinit v1 v1') m1
                            (Kinit v2 v2') m2.Definition FST {A B} (HH : A /\ B):=
    fst (ssrfun.pair_of_and HH).Definition SND {A B} (HH : A /\ B):=
    snd (ssrfun.pair_of_and HH).(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.(*
  Definition FST {A B} (HH : A /\ B) : A:=
    match HH with
    | conj H _ => H
    end. *)

  

  Record concur_match (ocd: option compiler_index)
       (j:meminj) (cstate1: C1) (m1: mem) (cstate2: C2) (m2: mem):=
  { same_length: num_threads cstate1 = num_threads cstate2
    ; memcompat1: HybridMachine.mem_compatible _ _ _ cstate1 m1
    ; memcompat2: HybridMachine.mem_compatible _ _ _ cstate2 m2
    ; mtch_source:
        forall (i:nat),
          (i > hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_source  j
                              (getThreadC cnti1)
                              (restrPermMap (FST (memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST (memcompat2 i cnti2)))
    ; mtch_target:
        forall (i:nat),
          (i < hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
          match_thread_target  j
                              (getThreadC cnti1)
                              (restrPermMap (FST(memcompat1 i cnti1)))
                              (getThreadC cnti2)
                              (restrPermMap (FST(memcompat2 i cnti2)))
    ; mtch_compiled:
        forall (i:nat),
          (i = hb')%nat ->
          forall (cnti1: containsThread cstate1 i)
            (cnti2: containsThread cstate2 i),
            exists cd, ocd = Some cd /\
          match_thread_compiled cd j
                                (getThreadC cnti1)
                                (restrPermMap (FST(memcompat1 i cnti1)))
                                (getThreadC cnti2)
                                (restrPermMap (FST(memcompat2 i cnti2))) }.

(* Specifications: *)
Lemma contains12: forall {data j cstate1 m1 cstate2 m2}, concur_match data j cstate1 m1 cstate2 m2 -> forall {i:nat} (cnti1: containsThread cstate1 i), containsThread cstate2 i.
Lemma contains21: forall {data j cstate1 m1 cstate2 m2}, concur_match data j cstate1 m1 cstate2 m2 -> forall {i:nat} (cnti1: containsThread cstate2 i), containsThread cstate1 i.