let pp_sl_mark p fmt m =
  let pp = match m.SlicingInternals.m1, m.SlicingInternals.m2 with
    | SlicingInternals.Spare, _ -> None
    | _, SlicingInternals.Spare -> None
    | SlicingInternals.Cav mark1, SlicingInternals.Cav mark2 ->
        if (PdgTypes.Dpd.is_bottom mark2) then
          (* use [!Db.Slicing.Mark.make] contructor *)
          Some (fun fmt ->
                  Format.fprintf fmt "@[<hv 2>!Db.Slicing.Mark.make@;~addr:%b@;~data:%b@;~ctrl:%b@]"
                    (PdgTypes.Dpd.is_addr mark1)
                    (PdgTypes.Dpd.is_data mark1)
                    (PdgTypes.Dpd.is_ctrl mark1))
        else
          None
  in
  let pp = match pp with
    | Some pp -> pp
    | None ->
        let pp fmt sub_m = match sub_m with
            (* use internals constructors *)
          | SlicingInternals.Spare -> Format.fprintf fmt "SlicingInternals.Spare"
          | SlicingInternals.Cav pdg_m -> Format.fprintf fmt
              "@[<hv 2>(SlicingInternals.Cav@;@[<hv 2>(PdgTypes.Dpd.make@;~a:%b@;~d:%b@;~c:%b@;())@])@]"
                (PdgTypes.Dpd.is_addr pdg_m)
                (PdgTypes.Dpd.is_data pdg_m)
                (PdgTypes.Dpd.is_ctrl pdg_m)
        in
        fun fmt ->
          Format.fprintf fmt "@[<hv 2>SlicingInternals.create_sl_mark@;~m1:%a@;~m2:%a@]"
            pp m.SlicingInternals.m1 pp m.SlicingInternals.m2
  in Type.par p Type.Call fmt pp