let get_read_addr with_direct p =
  let do_var acc v = match Fol.lvar_of_variable v with
    | Some lv when lv.lv_origin <> None -> 
        if with_direct then 
          (Wp_parameters.debug ~level:3 
             "get_read_addr : in '%s' base" lv.lv_name;
          (M.mk_lvar_addr lv)::acc)
        else 
          (Wp_parameters.debug ~level:3 
             "get_read_addr : ignore direct access to @@%s" lv.lv_name; 
           acc)
    | Some lv ->
        Wp_parameters.debug ~level:3
             "get_read_addr : ignore logic variable %s" lv.lv_name;
        acc 
    | None ->
        Wp_parameters.debug ~level:3
             "get_read_addr : ignore named variable %s" (Fol.var_name v);
        acc 
  in
  let rec do_data acc d = match d with
    | E1addr _v -> acc
    | E1proj (s, WpFol.Pfield f) -> 
        let add acc ps = 
          let pf = E1depl (ps, WpFol.Pfield f) in
            (Fol.Tdata pf)::acc 
        in List.fold_left add acc (do_exp true [] s)
    | E1proj (t, WpFol.Pidx i) -> 
        (match do_exp false [] i with
          | [] ->
              let add acc ps = 
                let pi = E1depl (ps, WpFol.Pidx i) in
                  (Fol.Tdata pi)::acc 
              in List.fold_left add acc (do_exp true [] t)
          | _ -> raise (UnknownGuard (Fol.Tdata d, "index with data"))
        )
    | E1depl (ps, WpFol.Pfield _) -> do_exp true acc ps
    | E1depl (pt, WpFol.Pidx _) -> do_exp true acc pt
    | E1indir p  -> let acc = match do_exp true [] p with
        | [] -> acc (* no modifiable var in p *)
                    (* TODO : check indir cannot be lowered *)
        | accp -> p::(accp @ acc)
      in acc
    | E1shift (p, _)  -> do_exp true acc p
    | E1mu (s, WpFol.Pfield _f, x)  -> 
        let acc = do_exp false acc x in
          do_exp true acc s (* TODO what about f ? *)
    | E1mu (t, WpFol.Pidx i, x)  -> 
        let acc = do_exp false acc x in
        let acc = do_exp false acc i in
          do_exp true acc t (* TODO what about idx ? *)
    | E1muI (_p, _x)  -> raise (UnknownGuard (Fol.Tdata d, "indirect mu"))
  and do_exp in_data (acc : M.t_exp list) e : M.t_exp list = match e with
    | Fol.Tdata d -> do_data acc d
    | Fol.Tvar v -> do_var acc v
    | _ when in_data -> raise (UnknownGuard (e, "exp in data"))
    | _ ->  Fol.fold_data_in_exp do_var do_data acc e
  in
    Fol.fold_exp_in_pred (do_exp false) [] p