]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[PATCH 4/7] Regcache: Refactor dup/cpy/save/restore
authorAlan Hayward <alan.hayward@arm.com>
Tue, 15 Aug 2017 15:39:47 +0000 (16:39 +0100)
committerAlan Hayward <alan.hayward@arm.com>
Tue, 15 Aug 2017 15:39:47 +0000 (16:39 +0100)
gdb/frame.c
gdb/infcmd.c
gdb/infrun.c
gdb/linux-fork.c
gdb/ppc-linux-tdep.c
gdb/regcache.c
gdb/regcache.h
gdb/spu-tdep.c

index 7fd4b07a2e95f28b2eb6a18dea4d2071f0ece4e2..30cd8532e6dcb91510c527f0c3c524558a7a6058 100644 (file)
@@ -1024,7 +1024,7 @@ frame_save_as_regcache (struct frame_info *this_frame)
   regcache *backup = new regcache (get_frame_arch (this_frame), aspace);
   struct cleanup *cleanups = make_cleanup_regcache_delete (backup);
 
-  regcache_save (backup, do_frame_register_read, this_frame);
+  backup->save (do_frame_register_read, this_frame);
   discard_cleanups (cleanups);
   return backup;
 }
@@ -1072,9 +1072,8 @@ frame_pop (struct frame_info *this_frame)
      Unfortunately, they don't implement it.  Their lack of a formal
      definition can lead to targets writing back bogus values
      (arguably a bug in the target code mind).  */
-  /* Now copy those saved registers into the current regcache.
-     Here, regcache_cpy() calls regcache_restore().  */
-  regcache_cpy (get_current_regcache (), scratch);
+  /* Now copy those saved registers into the current regcache.  */
+  scratch->restore_to (get_current_regcache ());
   do_cleanups (cleanups);
 
   /* We've made right mess of GDB's local state, just discard
index defa7b0c48cd3a1a90786ba3d883a986247a3b5d..52da4ba0e68417b7b515d1382f3f107e9d262130 100644 (file)
@@ -1602,8 +1602,8 @@ advance_command (char *arg, int from_tty)
 struct value *
 get_return_value (struct value *function, struct type *value_type)
 {
-  regcache stop_regs (regcache::readonly, *get_current_regcache ());
-  struct gdbarch *gdbarch = stop_regs.arch ();
+  regcache *stop_regs = get_current_regcache ()->dup ();
+  struct gdbarch *gdbarch = stop_regs->arch ();
   struct value *value;
 
   value_type = check_typedef (value_type);
@@ -1623,7 +1623,7 @@ get_return_value (struct value *function, struct type *value_type)
     case RETURN_VALUE_ABI_RETURNS_ADDRESS:
     case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
       value = allocate_value (value_type);
-      gdbarch_return_value (gdbarch, function, value_type, &stop_regs,
+      gdbarch_return_value (gdbarch, function, value_type, stop_regs,
                            value_contents_raw (value), NULL);
       break;
     case RETURN_VALUE_STRUCT_CONVENTION:
@@ -1633,6 +1633,7 @@ get_return_value (struct value *function, struct type *value_type)
       internal_error (__FILE__, __LINE__, _("bad switch"));
     }
 
+  delete stop_regs;
   return value;
 }
 
index 6510aec548f6495ca64f5b566ff3628734698113..485cdccf133a055382b569c9d20a6f2f76c4c0ba 100644 (file)
@@ -8911,7 +8911,7 @@ save_infcall_suspend_state (void)
 
   inf_state->stop_pc = stop_pc;
 
-  inf_state->registers = regcache_dup (regcache);
+  inf_state->registers = regcache->dup ();
 
   return inf_state;
 }
@@ -8922,7 +8922,7 @@ void
 restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
-  struct regcache *regcache = get_current_regcache ();
+  target_regcache *regcache = get_current_regcache ();
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
   tp->suspend = inf_state->thread_suspend;
@@ -8942,7 +8942,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
      (and perhaps other times).  */
   if (target_has_execution)
     /* NB: The register write goes through to the target.  */
-    regcache_cpy (regcache, inf_state->registers);
+    inf_state->registers->restore_to (regcache);
 
   discard_infcall_suspend_state (inf_state);
 }
index 032ff62807b728be336bf0e5daf59e47615d4799..d307aa7162cdd2b8ac1536e4eb1a1936ed6766f5 100644 (file)
@@ -264,7 +264,7 @@ fork_load_infrun_state (struct fork_info *fp)
   linux_nat_switch_fork (fp->ptid);
 
   if (fp->savedregs && fp->clobber_regs)
-    regcache_cpy (get_current_regcache (), fp->savedregs);
+     fp->savedregs->restore_to (get_current_regcache ());
 
   registers_changed ();
   reinit_frame_cache ();
@@ -297,7 +297,7 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
   if (fp->savedregs)
     delete fp->savedregs;
 
-  fp->savedregs = regcache_dup (get_current_regcache ());
+  fp->savedregs = get_current_regcache ()->dup ();
   fp->clobber_regs = clobber_regs;
 
   if (clobber_regs)
index 42aff2cd1bf3834268b0b58dcf00dac1c52add96..285ab74cbf656f501805663b4e1063f28d5269d0 100644 (file)
@@ -1366,7 +1366,7 @@ ppu2spu_sniffer (const struct frame_unwind *self,
          struct address_space *aspace = get_frame_address_space (this_frame);
          regcache *backup = new regcache (data.gdbarch, aspace);
          struct cleanup *cleanups = make_cleanup_regcache_delete (backup);
-         regcache_save (backup, ppu2spu_unwind_register, &data);
+         backup->save (ppu2spu_unwind_register, &data);
          discard_cleanups (cleanups);
 
          cache->frame_id = frame_id_build (base, func);
index e7da5a622e861e1e6a1938f91a0dd9a39942a050..5405dba7a706910f0b6d20c77eef657e38695b34 100644 (file)
@@ -226,13 +226,6 @@ do_cooked_read (void *src, int regnum, gdb_byte *buf)
   return regcache_cooked_read (regcache, regnum, buf);
 }
 
-regcache::regcache (readonly_t, const regcache &src)
-  : regcache (src.arch (), src.aspace (), true)
-{
-  gdb_assert (!src.m_readonly_p);
-  save (do_cooked_read, (void *) &src);
-}
-
 gdbarch *
 regcache::arch () const
 {
@@ -312,23 +305,11 @@ regcache::register_buffer (int regnum) const
 }
 
 void
-regcache_save (struct regcache *regcache,
-              regcache_cooked_read_ftype *cooked_read, void *src)
-{
-  regcache->save (cooked_read, src);
-}
-
-void
-regcache::save (regcache_cooked_read_ftype *cooked_read,
-               void *src)
+regcache::save (regcache_cooked_read_ftype *cooked_read, void *src)
 {
   struct gdbarch *gdbarch = m_descr->gdbarch;
   int regnum;
 
-  /* The DST should be `read-only', if it wasn't then the save would
-     end up trying to write the register values back out to the
-     target.  */
-  gdb_assert (m_readonly_p);
   /* Clear the dest.  */
   memset (m_registers, 0, m_descr->sizeof_cooked_registers);
   memset (m_register_status, 0, m_descr->sizeof_cooked_register_status);
@@ -354,15 +335,14 @@ regcache::save (regcache_cooked_read_ftype *cooked_read,
 }
 
 void
-regcache::restore (struct regcache *src)
+regcache::restore_to (target_regcache *dst)
 {
   struct gdbarch *gdbarch = m_descr->gdbarch;
   int regnum;
+  gdb_assert (dst != NULL);
+  gdb_assert (dst->m_descr->gdbarch == m_descr->gdbarch);
+  gdb_assert (dst != this);
 
-  /* The dst had better not be read-only.  If it is, the `restore'
-     doesn't make much sense.  */
-  gdb_assert (!m_readonly_p);
-  gdb_assert (src->m_readonly_p);
   /* Copy over any registers, being careful to only restore those that
      were both saved and need to be restored.  The full [0 .. gdbarch_num_regs
      + gdbarch_num_pseudo_regs) range is checked since some architectures need
@@ -371,27 +351,33 @@ regcache::restore (struct regcache *src)
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
        {
-         if (src->m_register_status[regnum] == REG_VALID)
-           cooked_write (regnum, src->register_buffer (regnum));
+         if (m_register_status[regnum] == REG_VALID)
+           dst->cooked_write (regnum, register_buffer (regnum));
        }
     }
 }
 
-void
-regcache_cpy (struct regcache *dst, struct regcache *src)
+/* Duplicate detached regcache to a detached regcache.  */
+regcache*
+regcache::dup ()
 {
-  gdb_assert (src != NULL && dst != NULL);
-  gdb_assert (src->m_descr->gdbarch == dst->m_descr->gdbarch);
-  gdb_assert (src != dst);
-  gdb_assert (src->m_readonly_p && !dst->m_readonly_p);
+  regcache *new_regcache = new regcache (arch (), aspace ());
+
+  memcpy (new_regcache->m_registers, m_registers,
+         m_descr->sizeof_cooked_registers);
+  memcpy (new_regcache->m_register_status, m_register_status,
+         m_descr->sizeof_cooked_register_status);
 
-  dst->restore (src);
+  return new_regcache;
 }
 
-struct regcache *
-regcache_dup (struct regcache *src)
+/* Duplicate a target_regcache to a detached regcache.  */
+regcache*
+target_regcache::dup ()
 {
-  return new regcache (regcache::readonly, *src);
+  regcache *new_regcache = new regcache (arch (), aspace ());
+  new_regcache->save (do_cooked_read, (void *) this);
+  return new_regcache;
 }
 
 enum register_status
index 00b87db7d145205b74859c08ca5a9d852441a4aa..1437dac220e0364557e3c568f1c5223cec598dfd 100644 (file)
@@ -209,20 +209,10 @@ extern struct type *register_type (struct gdbarch *gdbarch, int regnum);
    
 extern int register_size (struct gdbarch *gdbarch, int regnum);
 
-
-/* Save/restore a register cache.  The set of registers saved /
-   restored into the DST regcache determined by the save_reggroup /
-   restore_reggroup respectively.  COOKED_READ returns zero iff the
-   register's value can't be returned.  */
-
 typedef enum register_status (regcache_cooked_read_ftype) (void *src,
                                                           int regnum,
                                                           gdb_byte *buf);
 
-extern void regcache_save (struct regcache *dst,
-                          regcache_cooked_read_ftype *cooked_read,
-                          void *cooked_read_context);
-
 enum regcache_dump_what
 {
   regcache_dump_none, regcache_dump_raw,
@@ -249,12 +239,6 @@ public:
     : regcache (gdbarch, aspace_, true)
   {}
 
-  struct readonly_t {};
-  static constexpr readonly_t readonly {};
-
-  /* Create a readonly regcache from a non-readonly regcache.  */
-  regcache (readonly_t, const regcache &src);
-
   regcache (const regcache &) = delete;
   void operator= (const regcache &) = delete;
 
@@ -271,8 +255,17 @@ public:
     return m_aspace;
   }
 
+  /* Duplicate self into a new regcache.  */
+  virtual regcache* dup ();
+
+  /* Copy the register contents from a target_regcache to self.
+     All cooked registers are read and cached.  */
   void save (regcache_cooked_read_ftype *cooked_read, void *src);
 
+  /* Copy register contents to a target_regcache. All cached cooked registers
+     are also restored.  */
+  void restore_to (target_regcache *dst);
+
   enum register_status cooked_read (int regnum, gdb_byte *buf);
   void cooked_write (int regnum, const gdb_byte *buf);
 
@@ -348,8 +341,6 @@ protected:
 
   gdb_byte *register_buffer (int regnum) const;
 
-  void restore (struct regcache *src);
-
   struct regcache_descr *m_descr;
 
   /* The address space of this register cache (for registers where it
@@ -363,12 +354,10 @@ protected:
 
   /* Register cache status.  */
   signed char *m_register_status;
-  /* Is this a read-only cache?  A read-only cache is used for saving
-     the target's register state (e.g, across an inferior function
-     call or just before forcing a function return).  A read-only
-     cache can only be updated via the methods regcache_dup() and
-     regcache_cpy().  The actual contents are determined by the
-     reggroup_save and reggroup_restore methods.  */
+
+  /* A read-only cache can not change it's register contents, except from
+     an target_regcache via the save () method.
+     A target_regcache cache can never be read-only.  */
   bool m_readonly_p;
 
 private:
@@ -385,8 +374,6 @@ private:
 
 private:
 
-  friend void
-  regcache_cpy (struct regcache *dst, struct regcache *src);
 };
 
 
@@ -397,6 +384,16 @@ class target_regcache : public regcache
 {
 public:
 
+  target_regcache (const target_regcache &) = delete;
+  void operator= (const target_regcache &) = delete;
+
+  /* Cannot be called on a target_regcache.  */
+  void save (regcache_cooked_read_ftype *cooked_read, void *src) = delete;
+  void restore_to (target_regcache *dst) = delete;
+
+  /* Duplicate self into a new regcache.  Result is not a target_regcache.  */
+  regcache* dup ();
+
   /* Overridden regcache methods.  These versions will pass the read/write
      through to the target.  */
   enum register_status raw_read (int regnum, gdb_byte *buf);
@@ -434,14 +431,6 @@ private:
   friend void registers_changed_ptid (ptid_t ptid);
 };
 
-/* Duplicate the contents of a register cache to a read-only register
-   cache.  The operation is pass-through.  */
-extern struct regcache *regcache_dup (struct regcache *regcache);
-
-/* Writes to DEST will go through to the target.  SRC is a read-only
-   register cache.  */
-extern void regcache_cpy (struct regcache *dest, struct regcache *src);
-
 extern void registers_changed (void);
 extern void registers_changed_ptid (ptid_t);
 
index 1ac763da7ede9d4b9f4bff1e8d71551b0c776fa1..59ed3851a62df324a61ca3c604f22548a1630f7d 100644 (file)
@@ -1275,7 +1275,7 @@ spu2ppu_sniffer (const struct frame_unwind *self,
        {
          struct regcache *regcache;
          regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
-         cache->regcache = regcache_dup (regcache);
+         cache->regcache = regcache->dup ();
          *this_prologue_cache = cache;
          return 1;
        }