(** Accessing locations *)

Definition do_deref_loc (w: world) (ty: type) (m: mem) (b: block) (ofs: ptrofs) : option (world * trace * val) :=
  match access_mode ty with
  | By_value chunk =>
      match type_is_volatile ty with
      | false => do v <- Mem.loadv chunk m (Vptr b ofs); Some(w, E0, v)
      | true => do_volatile_load w chunk m b ofs
      end
  | By_reference => Some(w, E0, Vptr b ofs)
  | By_copy => Some(w, E0, Vptr b ofs)
  | _ => None
  end.Remark check_assign_copy:
  forall (ty: type) (b: block) (ofs: ptrofs) (b': block) (ofs': ptrofs),
  { assign_copy_ok ty b ofs b' ofs' } + {~ assign_copy_ok ty b ofs b' ofs' }.Definition do_assign_loc (w: world) (ty: type) (m: mem) (b: block) (ofs: ptrofs) (v: val): option (world * trace * mem) :=
  match access_mode ty with
  | By_value chunk =>
      match type_is_volatile ty with
      | false => do m' <- Mem.storev chunk m (Vptr b ofs) v; Some(w, E0, m')
      | true => do_volatile_store w chunk m b ofs v
      end
  | By_copy =>
      match v with
      | Vptr b' ofs' =>
          if check_assign_copy ty b ofs b' ofs' then
            do bytes <- Mem.loadbytes m b' (Ptrofs.unsigned ofs') (sizeof ge ty);
            do m' <- Mem.storebytes m b (Ptrofs.unsigned ofs) bytes;
            Some(w, E0, m')
          else None
      | _ => None
      end
  | _ => None
  end.

Lemma do_assign_loc_complete: forall w ty m b ofs v w' t m', assign_loc ge ty m b ofs v t m' -> possible_trace w t w' -> do_assign_loc w ty m b ofs v = Some(w', t, m').