Gible Seq Generation

Definition check_valid_node (tc: code) (e: node) :=
  match tc ! e with
  | Some _ => true
  | _ => false
  end.

Fixpoint check_code (c: RTL.code) (tc: code) (pc: node) (b: SeqBB.t) :=
  match c ! pc, b with
  | Some (RTL.Inop pc'), RBnop :: (_ :: _ :: _) as b' =>
      check_code c tc pc' b'
  | Some (RTL.Iop op' args' dst' pc'), RBop None op args dst :: (_ :: _ :: _) as b' =>
      ceq operation_eq op op'
      && ceq list_pos_eq args args'
      && ceq peq dst dst'
      && check_code c tc pc' b'
  | Some (RTL.Iload chunk' addr' args' dst' pc'),
    RBload None chunk addr args dst :: (_ :: _ :: _) as b' =>
      ceq memory_chunk_eq chunk chunk'
      && ceq addressing_eq addr addr'
      && ceq list_pos_eq args args'
      && ceq peq dst dst'
      && check_code c tc pc' b'
  | Some (RTL.Istore chunk' addr' args' src' pc'),
    RBstore None chunk addr args src :: (_ :: _ :: _) as b' =>
      ceq memory_chunk_eq chunk chunk'
      && ceq addressing_eq addr addr'
      && ceq list_pos_eq args args'
      && ceq peq src src'
      && check_code c tc pc' b'
  | Some (RTL.Inop pc''), RBnop :: RBexit None (RBgoto pc') :: nil =>
      check_valid_node tc pc'
      && ceq peq pc' pc''
  | Some (RTL.Iop op' args' dst' pc''), RBop None op args dst :: RBexit None (RBgoto pc') :: nil =>
      check_valid_node tc pc'
      && ceq peq pc' pc''
      && ceq operation_eq op op'
      && ceq list_pos_eq args args'
      && ceq peq dst dst'
  | Some (RTL.Iload chunk' addr' args' dst' pc''),
    RBload None chunk addr args dst :: RBexit None (RBgoto pc') :: nil =>
      check_valid_node tc pc'
      && ceq peq pc' pc''
      && ceq memory_chunk_eq chunk chunk'
      && ceq addressing_eq addr addr'
      && ceq list_pos_eq args args'
      && ceq peq dst dst'
  | Some (RTL.Istore chunk' addr' args' src' pc''),
    RBstore None chunk addr args src :: RBexit None (RBgoto pc') :: nil =>
      check_valid_node tc pc'
      && ceq peq pc' pc''
      && ceq memory_chunk_eq chunk chunk'
      && ceq addressing_eq addr addr'
      && ceq list_pos_eq args args'
      && ceq peq src src'
  | Some (RTL.Icall sig' (inl r') args' dst' pc''),
    RBnop :: RBexit None (RBcall sig (inl r) args dst pc') :: nil =>
      check_valid_node tc pc'
      && ceq peq pc' pc''
      && ceq signature_eq sig sig'
      && ceq peq r r'
      && ceq list_pos_eq args args'
      && ceq peq dst dst'
  | Some (RTL.Icall sig' (inr i') args' dst' pc''),
    RBnop :: RBexit None (RBcall sig (inr i) args dst pc') :: nil =>
      check_valid_node tc pc'
      && ceq peq pc' pc''
      && ceq signature_eq sig sig'
      && ceq peq i i'
      && ceq list_pos_eq args args'
      && ceq peq dst dst'
  | Some (RTL.Itailcall sig (inl r) args),
    RBnop :: RBexit None (RBtailcall sig' (inl r') args') :: nil =>
      ceq signature_eq sig sig'
      && ceq peq r r'
      && ceq list_pos_eq args args'
  | Some (RTL.Itailcall sig (inr r) args),
    RBnop :: RBexit None (RBtailcall sig' (inr r') args') :: nil =>
      ceq signature_eq sig sig'
      && ceq peq r r'
      && ceq list_pos_eq args args'
  | Some (RTL.Icond cond args n1 n2), RBnop :: RBexit None (RBcond cond' args' n1' n2') :: nil =>
      check_valid_node tc n1
      && check_valid_node tc n2
      && ceq condition_eq cond cond'
      && ceq list_pos_eq args args'
      && ceq peq n1 n1'
      && ceq peq n2 n2'
  | Some (RTL.Ijumptable r ns), RBnop :: RBexit None (RBjumptable r' ns') :: nil =>
      ceq peq r r'
      && ceq list_pos_eq ns ns'
      && forallb (check_valid_node tc) ns
  | Some (RTL.Ireturn (Some r)), RBnop :: RBexit None (RBreturn (Some r')) :: nil =>
      ceq peq r r'
  | Some (RTL.Ireturn None), RBnop :: RBexit None (RBreturn None) :: nil => true
  | _, _ => false
  end.

Parameter partition : RTL.function -> Errors.res function.

Definition transl_function (f: RTL.function) :=
  match partition f with
  | Errors.OK f' =>
      if check_valid_node f'.(fn_code) f.(RTL.fn_entrypoint) then
        if forall_ptree (check_code f.(RTL.fn_code) f'.(fn_code)) f'.(fn_code) then
          Errors.OK
            (mkfunction f.(RTL.fn_sig) f.(RTL.fn_params) f.(RTL.fn_stacksize) f'.(fn_code) f.(RTL.fn_entrypoint))
        else Errors.Error (Errors.msg "check_present_blocks failed")
      else Errors.Error (Errors.msg "entrypoint does not exists")
  | Errors.Error msg => Errors.Error msg
  end.

Definition transl_fundef := transf_partial_fundef transl_function.

Definition transl_program : RTL.program -> Errors.res program :=
  transform_partial_program transl_fundef.