public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA 3/3] Use gdb::function_view in pv_area
  2017-10-08 17:08 [RFA 0/3] C++-ify pv_area Tom Tromey
@ 2017-10-08 17:07 ` Tom Tromey
  2017-10-09  4:06   ` Simon Marchi
  2017-10-08 17:08 ` [RFA 1/3] C++-ify prologue-value's pv_area Tom Tromey
  2017-10-08 17:08 ` [RFA 2/3] Use bool in pv_area Tom Tromey
  2 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2017-10-08 17:07 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes pv_area::scan to use gdb::function_view and updates all
the callers.  The primary gain from this change is type-safety in the
calling code.

gdb/ChangeLog
2017-10-07  Tom Tromey  <tom@tromey.com>

	* rl78-tdep.c (rl78_analyze_prologue): Update.
	(check_for_saved): Change type of "result".
	* msp430-tdep.c (check_for_saved): Change type of "result".
	(msp430_analyze_prologue): Update.
	* rx-tdep.c (rx_analyze_prologue): Update.
	(check_for_saved): Change type of "result".
	* mn10300-tdep.c (mn10300_analyze_prologue): Update.
	(check_for_saved): Change type of "result".
	* m32c-tdep.c (m32c_analyze_prologue): Update.
	(check_for_saved): Change type of "prologue".
	* s390-linux-tdep.c (s390_check_for_saved): Change type of
	"data".
	(s390_analyze_prologue): Update.
	* mep-tdep.c (check_for_saved): Change type of "result".
	(mep_analyze_prologue): Update.
	* prologue-value.h (pv_area::scan): Use gdb::function_view.
---
 gdb/ChangeLog         | 19 +++++++++++++++++++
 gdb/m32c-tdep.c       |  8 +++++---
 gdb/mep-tdep.c        |  9 +++++----
 gdb/mn10300-tdep.c    |  9 +++++----
 gdb/msp430-tdep.c     |  9 +++++----
 gdb/prologue-value.c  | 10 ++++------
 gdb/prologue-value.h  | 14 +++++++-------
 gdb/rl78-tdep.c       |  8 ++++----
 gdb/rx-tdep.c         |  9 +++++----
 gdb/s390-linux-tdep.c |  7 ++++---
 10 files changed, 63 insertions(+), 39 deletions(-)

diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index 39f9ec0e5a..62d575b3ef 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -36,6 +36,7 @@
 #include "prologue-value.h"
 #include "target.h"
 #include "objfiles.h"
+#include <functional>
 
 \f
 /* The m32c tdep structure.  */
@@ -1499,9 +1500,9 @@ m32c_pushm_is_reg_save (struct m32c_pv_state *st, int src)
    offset from the frame base, and SIZE indicates that the whole
    register was saved, record its offset in RESULT_UNTYPED.  */
 static void
-check_for_saved (void *prologue_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+check_for_saved (struct m32c_prologue *prologue, pv_t addr, CORE_ADDR size,
+		 pv_t value)
 {
-  struct m32c_prologue *prologue = (struct m32c_prologue *) prologue_untyped;
   struct gdbarch *arch = prologue->arch;
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
 
@@ -1811,7 +1812,8 @@ m32c_analyze_prologue (struct gdbarch *arch,
     prologue->kind = prologue_first_frame;
 
   /* Record where all the registers were saved.  */
-  st.stack->scan (check_for_saved, (void *) prologue);
+  using namespace std::placeholders;
+  stack.scan (std::bind (check_for_saved, prologue, _1, _2, _3));
 
   prologue->prologue_end = after_last_frame_related_insn;
 }
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index bf08ca14d2..1589764a5d 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -45,6 +45,7 @@
 #include "prologue-value.h"
 #include "cgen/bitset.h"
 #include "infcall.h"
+#include <functional>
 
 /* Get the user's customized MeP coprocessor register names from
    libopcodes.  */
@@ -1651,10 +1652,9 @@ is_arg_spill (struct gdbarch *gdbarch, pv_t value, pv_t addr,
    offset from the frame base, and SIZE indicates that the whole
    register was saved, record its offset in RESULT_UNTYPED.  */
 static void
-check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+check_for_saved (struct mep_prologue *result, pv_t addr, CORE_ADDR size,
+		 pv_t value)
 {
-  struct mep_prologue *result = (struct mep_prologue *) result_untyped;
-
   if (value.kind == pvk_register
       && value.k == 0
       && pv_is_register (addr, MEP_SP_REGNUM)
@@ -1884,7 +1884,8 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  stack.scan (check_for_saved, (void *) result);
+  using namespace std::placeholders;
+  stack.scan (std::bind (check_for_saved, result, _1, _2, _3));
 
   result->prologue_end = after_last_frame_setup_insn;
 }
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
index eadbbb367e..ebd35cf9d3 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -33,6 +33,7 @@
 #include "infcall.h"
 #include "prologue-value.h"
 #include "target.h"
+#include <functional>
 
 #include "mn10300-tdep.h"
 
@@ -362,10 +363,9 @@ translate_rreg (int rreg)
    offset from the frame base, and SIZE indicates that the whole
    register was saved, record its offset in RESULT_UNTYPED.  */
 static void
-check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+check_for_saved (struct mn10300_prologue *result, pv_t addr, CORE_ADDR size,
+		 pv_t value)
 {
-  struct mn10300_prologue *result = (struct mn10300_prologue *) result_untyped;
-
   if (value.kind == pvk_register
       && value.k == 0
       && pv_is_register (addr, E_SP_REGNUM)
@@ -1034,7 +1034,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  stack.scan (check_for_saved, (void *) result);
+  using namespace std::placeholders;
+  stack.scan (std::bind (check_for_saved, result, _1, _2, _3));
 
   result->prologue_end = after_last_frame_setup_insn;
 }
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index 771ac9cd04..15ae2cff1e 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -34,6 +34,7 @@
 #include "gdbcore.h"
 #include "dwarf2-frame.h"
 #include "reggroups.h"
+#include <functional>
 
 #include "elf/msp430.h"
 #include "opcode/msp430-decode.h"
@@ -318,10 +319,9 @@ msp430_get_opcode_byte (void *handle)
    register was saved, record its offset.  */
 
 static void
-check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+check_for_saved (struct msp430_prologue *result, pv_t addr, CORE_ADDR size,
+		 pv_t value)
 {
-  struct msp430_prologue *result = (struct msp430_prologue *) result_untyped;
-
   if (value.kind == pvk_register
       && value.k == 0
       && pv_is_register (addr, MSP430_SP_REGNUM)
@@ -425,7 +425,8 @@ msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
     result->frame_size = reg[MSP430_SP_REGNUM].k;
 
   /* Record where all the registers were saved.  */
-  stack.scan (check_for_saved, result);
+  using namespace std::placeholders;
+  stack.scan (std::bind (check_for_saved, result, _1, _2, _3));
 
   result->prologue_end = after_last_frame_setup_insn;
 }
diff --git a/gdb/prologue-value.c b/gdb/prologue-value.c
index 2b2e5a8b65..b9b6667580 100644
--- a/gdb/prologue-value.c
+++ b/gdb/prologue-value.c
@@ -505,11 +505,9 @@ pv_area::find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p)
 
 
 void
-pv_area::scan (void (*func) (void *closure,
-			     pv_t addr,
-			     CORE_ADDR size,
-			     pv_t value),
-	       void *closure)
+pv_area::scan (gdb::function_view<void (pv_t addr,
+					CORE_ADDR size,
+					pv_t value)> func)
 {
   struct area_entry *e = m_entry;
   pv_t addr;
@@ -521,7 +519,7 @@ pv_area::scan (void (*func) (void *closure,
     do
       {
         addr.k = e->offset;
-        func (closure, addr, e->size, e->value);
+        func (addr, e->size, e->value);
         e = e->next;
       }
     while (e != m_entry);
diff --git a/gdb/prologue-value.h b/gdb/prologue-value.h
index c6fd34bdab..b70521b877 100644
--- a/gdb/prologue-value.h
+++ b/gdb/prologue-value.h
@@ -19,6 +19,8 @@
 #ifndef PROLOGUE_VALUE_H
 #define PROLOGUE_VALUE_H
 
+#include "common/function-view.h"
+
 /* What sort of value is this?  This determines the interpretation
    of subsequent fields.  */
 enum prologue_value_kind
@@ -283,13 +285,11 @@ public:
   bool find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p);
 
 
-  /* For every part of AREA whose value we know, apply FUNC to CLOSURE,
-     the value's address, its size, and the value itself.  */
-  void scan (void (*func) (void *closure,
-			   pv_t addr,
-			   CORE_ADDR size,
-			   pv_t value),
-	     void *closure);
+  /* For every part of AREA whose value we know, apply FUNC to the
+     value's address, its size, and the value itself.  */
+  void scan (gdb::function_view<void (pv_t addr,
+				      CORE_ADDR size,
+				      pv_t value)>);
 
 private:
 
diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
index 19f8098b7b..b3a2f8d513 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -34,6 +34,7 @@
 #include "gdbcore.h"
 #include "dwarf2-frame.h"
 #include "reggroups.h"
+#include <functional>
 
 #include "elf/rl78.h"
 #include "elf-bfd.h"
@@ -890,11 +891,9 @@ rl78_get_opcode_byte (void *handle)
    register was saved, record its offset.  */
 
 static void
-check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size,
+check_for_saved (struct rl78_prologue *result, pv_t addr, CORE_ADDR size,
                  pv_t value)
 {
-  struct rl78_prologue *result = (struct rl78_prologue *) result_untyped;
-
   if (value.kind == pvk_register
       && value.k == 0
       && pv_is_register (addr, RL78_SP_REGNUM)
@@ -1013,7 +1012,8 @@ rl78_analyze_prologue (CORE_ADDR start_pc,
     result->frame_size = reg[RL78_SP_REGNUM].k;
 
   /* Record where all the registers were saved.  */
-  stack.scan (check_for_saved, (void *) result);
+  using namespace std::placeholders;
+  stack.scan (std::bind (check_for_saved, result, _1, _2, _3));
 
   result->prologue_end = after_last_frame_setup_insn;
 }
diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
index 7d0436c33f..7ef18f4b0a 100644
--- a/gdb/rx-tdep.c
+++ b/gdb/rx-tdep.c
@@ -37,6 +37,7 @@
 #include "elf/rx.h"
 #include "elf-bfd.h"
 #include <algorithm>
+#include <functional>
 
 /* Certain important register numbers.  */
 enum
@@ -236,10 +237,9 @@ rx_register_type (struct gdbarch *gdbarch, int reg_nr)
    offset from the frame base, and SIZE indicates that the whole
    register was saved, record its offset.  */
 static void
-check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+check_for_saved (struct rx_prologue *result, pv_t addr, CORE_ADDR size,
+		 pv_t value)
 {
-  struct rx_prologue *result = (struct rx_prologue *) result_untyped;
-
   if (value.kind == pvk_register
       && value.k == 0
       && pv_is_register (addr, RX_SP_REGNUM)
@@ -453,7 +453,8 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
     }
 
   /* Record where all the registers were saved.  */
-  stack.scan (check_for_saved, (void *) result);
+  using namespace std::placeholders;
+  stack.scan (std::bind (check_for_saved, result, _1, _2, _3));
 
   result->prologue_end = after_last_frame_setup_insn;
 }
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index d48364b93f..e56cbf3f0e 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -58,6 +58,7 @@
 #include "elf/s390.h"
 #include "elf-bfd.h"
 #include <algorithm>
+#include <functional>
 
 #include "features/s390-linux32.c"
 #include "features/s390-linux32v1.c"
@@ -1424,10 +1425,9 @@ s390_load (struct s390_prologue_data *data,
    register was saved, record its offset in the reg_offset table in
    PROLOGUE_UNTYPED.  */
 static void
-s390_check_for_saved (void *data_untyped, pv_t addr,
+s390_check_for_saved (struct s390_prologue_data *data, pv_t addr,
 		      CORE_ADDR size, pv_t value)
 {
-  struct s390_prologue_data *data = (struct s390_prologue_data *) data_untyped;
   int i, offset;
 
   if (!pv_is_register (addr, S390_SP_REGNUM))
@@ -1731,7 +1731,8 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  data->stack->scan (s390_check_for_saved, data);
+  using namespace std::placeholders;
+  data->stack->scan (std::bind (s390_check_for_saved, data, _1, _2, _3));
 
   return result;
 }
-- 
2.13.6

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFA 1/3] C++-ify prologue-value's pv_area
  2017-10-08 17:08 [RFA 0/3] C++-ify pv_area Tom Tromey
  2017-10-08 17:07 ` [RFA 3/3] Use gdb::function_view in pv_area Tom Tromey
@ 2017-10-08 17:08 ` Tom Tromey
  2017-10-09  3:04   ` Simon Marchi
  2017-10-08 17:08 ` [RFA 2/3] Use bool in pv_area Tom Tromey
  2 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2017-10-08 17:08 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch is an initial C++-ification of pv_area, from
prologue-value.  It turns pv_area into a class with a constructor and
destructor; renames the data members; and changes various functions to
be member functions.  This allows the removal of
make_cleanup_free_pv_area.

gdb/ChangeLog
2017-10-07  Tom Tromey  <tom@tromey.com>

	* s390-linux-tdep.c (s390_store, s390_load)
	(s390_check_for_saved, s390_analyze_prologue): Update.
	* rx-tdep.c (check_for_saved, rx_analyze_prologue): Update.
	* rl78-tdep.c (rl78_analyze_prologue, check_for_saved): Update.
	* prologue-value.h (class pv_area): Move from prologue-value.c.
	Change names of members.  Add constructor, destructor, member
	functions.
	(make_pv_area, free_pv_area, make_cleanup_free_pv_area)
	(pv_area_store, pv_area_fetch, pv_area_store_would_trash)
	(pv_area_fetch, pv_area_scan): Don't declare.
	* prologue-value.c (struct pv_area::area_entry): Now member of
	pv_area.
	(struct pv_area): Move to prologue-value.h.
	(pv_area::pv_area): Rename from make_pv_area.
	(pv_area::~pv_area): Rename from free_pv_area.
	(do_free_pv_area_cleanup, make_cleanup_free_pv_area): Remove.
	(clear_entries, find_entry, overlaps, store_would_trash, store)
	(fetch, find_reg, scan): Now member of pv_area.
	Remove "area" argument.  Update.
	* msp430-tdep.c (check_for_saved, msp430_analyze_prologue):
	Update.
	* mn10300-tdep.c (push_reg, check_for_saved)
	(mn10300_analyze_prologue): Update.
	* mep-tdep.c (is_arg_spill, check_for_saved)
	(mep_analyze_prologue): Update.
	* m32c-tdep.c (m32c_pv_push, m32c_srcdest_fetch)
	(m32c_srcdest_store, m32c_pv_enter, m32c_is_arg_spill)
	(m32c_is_struct_return, m32c_analyze_prologue): Update.
	* arm-tdep.c (thumb_analyze_prologue, arm_analyze_prologue):
	Update.
	* arc-tdep.c (arc_is_in_prologue, arc_analyze_prologue): Update.
	* aarch64-tdep.c (aarch64_analyze_prologue): Update.
---
 gdb/ChangeLog         |  35 ++++++++++
 gdb/aarch64-tdep.c    |  41 +++++------
 gdb/arc-tdep.c        |  32 ++++-----
 gdb/arm-tdep.c        |  73 +++++++++-----------
 gdb/m32c-tdep.c       |  27 ++++----
 gdb/mep-tdep.c        |  33 ++++-----
 gdb/mn10300-tdep.c    | 128 ++++++++++++++++-------------------
 gdb/msp430-tdep.c     |  17 ++---
 gdb/prologue-value.c  | 168 +++++++++++++++------------------------------
 gdb/prologue-value.h  | 183 +++++++++++++++++++++++++++++---------------------
 gdb/rl78-tdep.c       |  19 ++----
 gdb/rx-tdep.c         |  19 ++----
 gdb/s390-linux-tdep.c |  18 +++--
 13 files changed, 367 insertions(+), 426 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index e74b7cd370..a40dc69b92 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -234,13 +234,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
   int i;
   /* Track X registers and D registers in prologue.  */
   pv_t regs[AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT];
-  struct pv_area *stack;
-  struct cleanup *back_to;
 
   for (i = 0; i < AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT; i++)
     regs[i] = pv_register (i, 0);
-  stack = make_pv_area (AARCH64_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (AARCH64_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
   for (; start < limit; start += 4)
     {
@@ -345,9 +342,9 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 	  gdb_assert (inst.operands[1].type == AARCH64_OPND_ADDR_SIMM9);
 	  gdb_assert (!inst.operands[1].addr.offset.is_reg);
 
-	  pv_area_store (stack, pv_add_constant (regs[rn],
-						 inst.operands[1].addr.offset.imm),
-			 is64 ? 8 : 4, regs[rt]);
+	  stack.store (pv_add_constant (regs[rn],
+					inst.operands[1].addr.offset.imm),
+		       is64 ? 8 : 4, regs[rt]);
 	}
       else if ((inst.opcode->iclass == ldstpair_off
 		|| (inst.opcode->iclass == ldstpair_indexed
@@ -370,12 +367,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 	  /* If recording this store would invalidate the store area
 	     (perhaps because rn is not known) then we should abandon
 	     further prologue analysis.  */
-	  if (pv_area_store_would_trash (stack,
-					 pv_add_constant (regs[rn], imm)))
+	  if (stack.store_would_trash (pv_add_constant (regs[rn], imm)))
 	    break;
 
-	  if (pv_area_store_would_trash (stack,
-					 pv_add_constant (regs[rn], imm + 8)))
+	  if (stack.store_would_trash (pv_add_constant (regs[rn], imm + 8)))
 	    break;
 
 	  rt1 = inst.operands[0].reg.regno;
@@ -389,10 +384,10 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 	      rt2 += AARCH64_X_REGISTER_COUNT;
 	    }
 
-	  pv_area_store (stack, pv_add_constant (regs[rn], imm), 8,
-			 regs[rt1]);
-	  pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8,
-			 regs[rt2]);
+	  stack.store (pv_add_constant (regs[rn], imm), 8,
+		       regs[rt1]);
+	  stack.store (pv_add_constant (regs[rn], imm + 8), 8,
+		       regs[rt2]);
 
 	  if (inst.operands[2].addr.writeback)
 	    regs[rn] = pv_add_constant (regs[rn], imm);
@@ -422,8 +417,8 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 	      rt += AARCH64_X_REGISTER_COUNT;
 	    }
 
-	  pv_area_store (stack, pv_add_constant (regs[rn], imm),
-			 is64 ? 8 : 4, regs[rt]);
+	  stack.store (pv_add_constant (regs[rn], imm),
+		       is64 ? 8 : 4, regs[rt]);
 	  if (inst.operands[1].addr.writeback)
 	    regs[rn] = pv_add_constant (regs[rn], imm);
 	}
@@ -445,10 +440,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   if (cache == NULL)
-    {
-      do_cleanups (back_to);
-      return start;
-    }
+    return start;
 
   if (pv_is_register (regs[AARCH64_FP_REGNUM], AARCH64_SP_REGNUM))
     {
@@ -473,7 +465,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
     {
       CORE_ADDR offset;
 
-      if (pv_area_find_reg (stack, gdbarch, i, &offset))
+      if (stack.find_reg (gdbarch, i, &offset))
 	cache->saved_regs[i].addr = offset;
     }
 
@@ -482,12 +474,11 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
       int regnum = gdbarch_num_regs (gdbarch);
       CORE_ADDR offset;
 
-      if (pv_area_find_reg (stack, gdbarch, i + AARCH64_X_REGISTER_COUNT,
-			    &offset))
+      if (stack.find_reg (gdbarch, i + AARCH64_X_REGISTER_COUNT,
+			  &offset))
 	cache->saved_regs[i + regnum + AARCH64_D0_REGNUM].addr = offset;
     }
 
-  do_cleanups (back_to);
   return start;
 }
 
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 1d05c5a20f..252bb54a48 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1014,7 +1014,7 @@ arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
 	addr = pv_add_constant (regs[base_reg],
 				arc_insn_get_memory_offset (insn));
 
-      if (pv_area_store_would_trash (stack, addr))
+      if (stack->store_would_trash (addr))
 	return false;
 
       if (insn.data_size_mode != ARC_SCALING_D)
@@ -1031,7 +1031,7 @@ arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
 	  else
 	    size = ARC_REGISTER_SIZE;
 
-	  pv_area_store (stack, addr, size, store_value);
+	  stack->store (addr, size, store_value);
 	}
       else
 	{
@@ -1040,16 +1040,15 @@ arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
 	      /* If this is a double store, than write N+1 register as well.  */
 	      pv_t store_value1 = regs[insn.operands[0].value];
 	      pv_t store_value2 = regs[insn.operands[0].value + 1];
-	      pv_area_store (stack, addr, ARC_REGISTER_SIZE, store_value1);
-	      pv_area_store (stack,
-			     pv_add_constant (addr, ARC_REGISTER_SIZE),
-			     ARC_REGISTER_SIZE, store_value2);
+	      stack->store (addr, ARC_REGISTER_SIZE, store_value1);
+	      stack->store (pv_add_constant (addr, ARC_REGISTER_SIZE),
+			    ARC_REGISTER_SIZE, store_value2);
 	    }
 	  else
 	    {
 	      pv_t store_value
 		= pv_constant (arc_insn_get_operand_value (insn, 0));
-	      pv_area_store (stack, addr, ARC_REGISTER_SIZE * 2, store_value);
+	      stack->store (addr, ARC_REGISTER_SIZE * 2, store_value);
 	    }
 	}
 
@@ -1136,7 +1135,7 @@ arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
 
       /* Assume that if the last register (closest to new SP) can be written,
 	 then it is possible to write all of them.  */
-      if (pv_area_store_would_trash (stack, new_sp))
+      if (stack->store_would_trash (new_sp))
 	return false;
 
       /* Current store address.  */
@@ -1145,21 +1144,21 @@ arc_is_in_prologue (struct gdbarch *gdbarch, const struct arc_instruction &insn,
       if (is_fp_saved)
 	{
 	  addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
-	  pv_area_store (stack, addr, ARC_REGISTER_SIZE, regs[ARC_FP_REGNUM]);
+	  stack->store (addr, ARC_REGISTER_SIZE, regs[ARC_FP_REGNUM]);
 	}
 
       /* Registers are stored in backward order: from GP (R26) to R13.  */
       for (int i = ARC_R13_REGNUM + regs_saved - 1; i >= ARC_R13_REGNUM; i--)
 	{
 	  addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
-	  pv_area_store (stack, addr, ARC_REGISTER_SIZE, regs[i]);
+	  stack->store (addr, ARC_REGISTER_SIZE, regs[i]);
 	}
 
       if (is_blink_saved)
 	{
 	  addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
-	  pv_area_store (stack, addr, ARC_REGISTER_SIZE,
-			 regs[ARC_BLINK_REGNUM]);
+	  stack->store (addr, ARC_REGISTER_SIZE,
+			regs[ARC_BLINK_REGNUM]);
 	}
 
       gdb_assert (pv_is_identical (addr, new_sp));
@@ -1271,9 +1270,7 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
   pv_t regs[ARC_LAST_CORE_REGNUM + 1];
   for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
     regs[i] = pv_register (i, 0);
-  struct pv_area *stack = make_pv_area (ARC_SP_REGNUM,
-					gdbarch_addr_bit (gdbarch));
-  struct cleanup *back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (ARC_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
   CORE_ADDR current_prologue_end = entrypoint;
 
@@ -1290,7 +1287,7 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
 
       /* If this instruction is in the prologue, fields in the cache will be
 	 updated, and the saved registers mask may be updated.  */
-      if (!arc_is_in_prologue (gdbarch, insn, regs, stack))
+      if (!arc_is_in_prologue (gdbarch, insn, regs, &stack))
 	{
 	  /* Found an instruction that is not in the prologue.  */
 	  if (arc_debug)
@@ -1320,12 +1317,11 @@ arc_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR entrypoint,
       for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
 	{
 	  CORE_ADDR offset;
-	  if (pv_area_find_reg (stack, gdbarch, i, &offset))
+	  if (stack.find_reg (gdbarch, i, &offset))
 	    cache->saved_regs[i].addr = offset;
 	}
     }
 
-  do_cleanups (back_to);
   return current_prologue_end;
 }
 
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index d8569e051a..d417beddb4 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -647,15 +647,12 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   int i;
   pv_t regs[16];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR offset;
   CORE_ADDR unrecognized_pc = 0;
 
   for (i = 0; i < 16; i++)
     regs[i] = pv_register (i, 0);
-  stack = make_pv_area (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
   while (start < limit)
     {
@@ -668,7 +665,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	  int regno;
 	  int mask;
 
-	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
 	    break;
 
 	  /* Bits 0-7 contain a mask for registers R0-R7.  Bit 8 says
@@ -681,7 +678,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	      {
 		regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
 						       -4);
-		pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
+		stack.store (regs[ARM_SP_REGNUM], 4, regs[regno]);
 	      }
 	}
       else if ((insn & 0xff80) == 0xb080)	/* sub sp, #imm */
@@ -735,10 +732,10 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	  offset = (insn & 0xff) << 2;
 	  addr = pv_add_constant (regs[ARM_SP_REGNUM], offset);
 
-	  if (pv_area_store_would_trash (stack, addr))
+	  if (stack.store_would_trash (addr))
 	    break;
 
-	  pv_area_store (stack, addr, 4, regs[regno]);
+	  stack.store (addr, 4, regs[regno]);
 	}
       else if ((insn & 0xf800) == 0x6000)	/* str rd, [rn, #off] */
 	{
@@ -749,10 +746,10 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	  offset = bits (insn, 6, 10) << 2;
 	  addr = pv_add_constant (regs[rn], offset);
 
-	  if (pv_area_store_would_trash (stack, addr))
+	  if (stack.store_would_trash (addr))
 	    break;
 
-	  pv_area_store (stack, addr, 4, regs[rd]);
+	  stack.store (addr, 4, regs[rd]);
 	}
       else if (((insn & 0xf800) == 0x7000	/* strb Rd, [Rn, #off] */
 		|| (insn & 0xf800) == 0x8000)	/* strh Rd, [Rn, #off] */
@@ -828,7 +825,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	      pv_t addr = regs[bits (insn, 0, 3)];
 	      int regno;
 
-	      if (pv_area_store_would_trash (stack, addr))
+	      if (stack.store_would_trash (addr))
 		break;
 
 	      /* Calculate offsets of saved registers.  */
@@ -836,7 +833,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 		if (inst2 & (1 << regno))
 		  {
 		    addr = pv_add_constant (addr, -4);
-		    pv_area_store (stack, addr, 4, regs[regno]);
+		    stack.store (addr, 4, regs[regno]);
 		  }
 
 	      if (insn & 0x0020)
@@ -857,12 +854,12 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	      else
 		addr = pv_add_constant (addr, -offset);
 
-	      if (pv_area_store_would_trash (stack, addr))
+	      if (stack.store_would_trash (addr))
 		break;
 
-	      pv_area_store (stack, addr, 4, regs[regno1]);
-	      pv_area_store (stack, pv_add_constant (addr, 4),
-			     4, regs[regno2]);
+	      stack.store (addr, 4, regs[regno1]);
+	      stack.store (pv_add_constant (addr, 4),
+			   4, regs[regno2]);
 
 	      if (insn & 0x0020)
 		regs[bits (insn, 0, 3)] = addr;
@@ -881,10 +878,10 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	      else
 		addr = pv_add_constant (addr, -offset);
 
-	      if (pv_area_store_would_trash (stack, addr))
+	      if (stack.store_would_trash (addr))
 		break;
 
-	      pv_area_store (stack, addr, 4, regs[regno]);
+	      stack.store (addr, 4, regs[regno]);
 
 	      if (inst2 & 0x0100)
 		regs[bits (insn, 0, 3)] = addr;
@@ -899,10 +896,10 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 	      offset = inst2 & 0xfff;
 	      addr = pv_add_constant (regs[bits (insn, 0, 3)], offset);
 
-	      if (pv_area_store_would_trash (stack, addr))
+	      if (stack.store_would_trash (addr))
 		break;
 
-	      pv_area_store (stack, addr, 4, regs[regno]);
+	      stack.store (addr, 4, regs[regno]);
 	    }
 
 	  else if ((insn & 0xffd0) == 0xf880	/* str{bh}.w Rt,[Rn,#imm] */
@@ -1085,10 +1082,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
     unrecognized_pc = start;
 
   if (cache == NULL)
-    {
-      do_cleanups (back_to);
-      return unrecognized_pc;
-    }
+    return unrecognized_pc;
 
   if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
     {
@@ -1110,10 +1104,9 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   for (i = 0; i < 16; i++)
-    if (pv_area_find_reg (stack, gdbarch, i, &offset))
+    if (stack.find_reg (gdbarch, i, &offset))
       cache->saved_regs[i].addr = offset;
 
-  do_cleanups (back_to);
   return unrecognized_pc;
 }
 
@@ -1489,8 +1482,6 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
   int regno;
   CORE_ADDR offset, current_pc;
   pv_t regs[ARM_FPS_REGNUM];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR unrecognized_pc = 0;
 
   /* Search the prologue looking for instructions that set up the
@@ -1505,8 +1496,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
 
   for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
     regs[regno] = pv_register (regno, 0);
-  stack = make_pv_area (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
   for (current_pc = prologue_start;
        current_pc < prologue_end;
@@ -1543,11 +1533,11 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
       else if ((insn & 0xffff0fff) == 0xe52d0004)	/* str Rd,
 							   [sp, #-4]! */
 	{
-	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
 	    break;
 	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -4);
-	  pv_area_store (stack, regs[ARM_SP_REGNUM], 4,
-			 regs[bits (insn, 12, 15)]);
+	  stack.store (regs[ARM_SP_REGNUM], 4,
+		       regs[bits (insn, 12, 15)]);
 	  continue;
 	}
       else if ((insn & 0xffff0000) == 0xe92d0000)
@@ -1557,7 +1547,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
 	{
 	  int mask = insn & 0xffff;
 
-	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
 	    break;
 
 	  /* Calculate offsets of saved registers.  */
@@ -1566,7 +1556,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
 	      {
 		regs[ARM_SP_REGNUM]
 		  = pv_add_constant (regs[ARM_SP_REGNUM], -4);
-		pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
+		stack.store (regs[ARM_SP_REGNUM], 4, regs[regno]);
 	      }
 	}
       else if ((insn & 0xffff0000) == 0xe54b0000	/* strb rx,[r11,#-n] */
@@ -1608,12 +1598,12 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
 							   [sp, -#c]! */
 	       && gdbarch_tdep (gdbarch)->have_fpa_registers)
 	{
-	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
 	    break;
 
 	  regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
 	  regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
-	  pv_area_store (stack, regs[ARM_SP_REGNUM], 12, regs[regno]);
+	  stack.store (regs[ARM_SP_REGNUM], 12, regs[regno]);
 	}
       else if ((insn & 0xffbf0fff) == 0xec2d0200	/* sfmfd f0, 4,
 							   [sp!] */
@@ -1622,7 +1612,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
 	  int n_saved_fp_regs;
 	  unsigned int fp_start_reg, fp_bound_reg;
 
-	  if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+	  if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
 	    break;
 
 	  if ((insn & 0x800) == 0x800)		/* N0 is set */
@@ -1645,8 +1635,8 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
 	  for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
 	    {
 	      regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
-	      pv_area_store (stack, regs[ARM_SP_REGNUM], 12,
-			     regs[fp_start_reg++]);
+	      stack.store (regs[ARM_SP_REGNUM], 12,
+			   regs[fp_start_reg++]);
 	    }
 	}
       else if ((insn & 0xff000000) == 0xeb000000 && cache == NULL) /* bl */
@@ -1726,7 +1716,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
       cache->framesize = framesize;
 
       for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
-	if (pv_area_find_reg (stack, gdbarch, regno, &offset))
+	if (stack.find_reg (gdbarch, regno, &offset))
 	  cache->saved_regs[regno].addr = offset;
     }
 
@@ -1734,7 +1724,6 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
     fprintf_unfiltered (gdb_stdlog, "Prologue scan stopped at %s\n",
 			paddress (gdbarch, unrecognized_pc));
 
-  do_cleanups (back_to);
   return unrecognized_pc;
 }
 
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index 3a4dbda52b..39f9ec0e5a 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -1079,11 +1079,11 @@ struct m32c_pv_state
 static int
 m32c_pv_push (struct m32c_pv_state *state, pv_t value, int size)
 {
-  if (pv_area_store_would_trash (state->stack, state->sp))
+  if (state->stack->store_would_trash (state->sp))
     return 1;
 
   state->sp = pv_add_constant (state->sp, -size);
-  pv_area_store (state->stack, state->sp, size, value);
+  state->stack->store (state->sp, size, value);
 
   return 0;
 }
@@ -1114,7 +1114,7 @@ static pv_t
 m32c_srcdest_fetch (struct m32c_pv_state *state, struct srcdest loc, int size)
 {
   if (loc.kind == srcdest_mem)
-    return pv_area_fetch (state->stack, loc.addr, size);
+    return state->stack->fetch (loc.addr, size);
   else if (loc.kind == srcdest_partial_reg)
     return pv_unknown ();
   else
@@ -1131,9 +1131,9 @@ m32c_srcdest_store (struct m32c_pv_state *state, struct srcdest loc,
 {
   if (loc.kind == srcdest_mem)
     {
-      if (pv_area_store_would_trash (state->stack, loc.addr))
+      if (state->stack->store_would_trash (loc.addr))
 	return 1;
-      pv_area_store (state->stack, loc.addr, size, value);
+      state->stack->store (loc.addr, size, value);
     }
   else if (loc.kind == srcdest_partial_reg)
     *loc.reg = pv_unknown ();
@@ -1350,7 +1350,7 @@ m32c_pv_enter (struct m32c_pv_state *state, int size)
   /* If simulating this store would require us to forget
      everything we know about the stack frame in the name of
      accuracy, it would be better to just quit now.  */
-  if (pv_area_store_would_trash (state->stack, state->sp))
+  if (state->stack->store_would_trash (state->sp))
     return 1;
 
   if (m32c_pv_push (state, state->fb, tdep->push_addr_bytes))
@@ -1441,7 +1441,7 @@ m32c_is_arg_spill (struct m32c_pv_state *st,
   return (m32c_is_arg_reg (st, value)
 	  && loc.kind == srcdest_mem
           && pv_is_register (loc.addr, tdep->sp->num)
-          && ! pv_area_find_reg (st->stack, st->arch, value.reg, 0));
+          && ! st->stack->find_reg (st->arch, value.reg, 0));
 }
 
 /* Return non-zero if a store of VALUE to LOC is probably 
@@ -1462,7 +1462,7 @@ m32c_is_struct_return (struct m32c_pv_state *st,
   struct gdbarch_tdep *tdep = gdbarch_tdep (st->arch);
 
   return (m32c_is_1st_arg_reg (st, value)
-	  && !pv_area_find_reg (st->stack, st->arch, value.reg, 0)
+	  && !st->stack->find_reg (st->arch, value.reg, 0)
 	  && loc.kind == srcdest_reg
 	  && (pv_is_register (*loc.reg, tdep->a0->num)
 	      || pv_is_register (*loc.reg, tdep->a1->num)));
@@ -1493,7 +1493,7 @@ m32c_pushm_is_reg_save (struct m32c_pv_state *st, int src)
 
 
 /* Function for finding saved registers in a 'struct pv_area'; we pass
-   this to pv_area_scan.
+   this to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -1546,7 +1546,6 @@ m32c_analyze_prologue (struct gdbarch *arch,
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
   unsigned long mach = gdbarch_bfd_arch_info (arch)->mach;
   CORE_ADDR after_last_frame_related_insn;
-  struct cleanup *back_to;
   struct m32c_pv_state st;
 
   st.arch = arch;
@@ -1560,8 +1559,8 @@ m32c_analyze_prologue (struct gdbarch *arch,
   st.fb = pv_register (tdep->fb->num, 0);
   st.sp = pv_register (tdep->sp->num, 0);
   st.pc = pv_register (tdep->pc->num, 0);
-  st.stack = make_pv_area (tdep->sp->num, gdbarch_addr_bit (arch));
-  back_to = make_cleanup_free_pv_area (st.stack);
+  pv_area stack (tdep->sp->num, gdbarch_addr_bit (arch));
+  st.stack = &stack;
 
   /* Record that the call instruction has saved the return address on
      the stack.  */
@@ -1812,11 +1811,9 @@ m32c_analyze_prologue (struct gdbarch *arch,
     prologue->kind = prologue_first_frame;
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (st.stack, check_for_saved, (void *) prologue);
+  st.stack->scan (check_for_saved, (void *) prologue);
 
   prologue->prologue_end = after_last_frame_related_insn;
-
-  do_cleanups (back_to);
 }
 
 
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index 623ab7f42f..bf08ca14d2 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -1640,12 +1640,12 @@ is_arg_spill (struct gdbarch *gdbarch, pv_t value, pv_t addr,
 {
   return (is_arg_reg (value)
           && pv_is_register (addr, MEP_SP_REGNUM)
-          && ! pv_area_find_reg (stack, gdbarch, value.reg, 0));
+          && ! stack->find_reg (gdbarch, value.reg, 0));
 }
 
 
 /* Function for finding saved registers in a 'struct pv_area'; we pass
-   this to pv_area_scan.
+   this to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -1675,8 +1675,6 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
   int rn;
   int found_lp = 0;
   pv_t reg[MEP_NUM_REGS];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR after_last_frame_setup_insn = start_pc;
 
   memset (result, 0, sizeof (*result));
@@ -1688,8 +1686,7 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
       result->reg_offset[rn] = 1;
     }
 
-  stack = make_pv_area (MEP_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (MEP_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
   pc = start_pc;
   while (pc < limit_pc)
@@ -1741,13 +1738,13 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
           /* If simulating this store would require us to forget
              everything we know about the stack frame in the name of
              accuracy, it would be better to just quit now.  */
-          if (pv_area_store_would_trash (stack, reg[rm]))
+          if (stack.store_would_trash (reg[rm]))
             break;
           
-          if (is_arg_spill (gdbarch, reg[rn], reg[rm], stack))
+          if (is_arg_spill (gdbarch, reg[rn], reg[rm], &stack))
             after_last_frame_setup_insn = next_pc;
 
-          pv_area_store (stack, reg[rm], 4, reg[rn]);
+          stack.store (reg[rm], 4, reg[rn]);
         }
       else if (IS_SW_IMMD (insn))
         {
@@ -1758,13 +1755,13 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
           /* If simulating this store would require us to forget
              everything we know about the stack frame in the name of
              accuracy, it would be better to just quit now.  */
-          if (pv_area_store_would_trash (stack, addr))
+          if (stack.store_would_trash (addr))
             break;
 
-          if (is_arg_spill (gdbarch, reg[rn], addr, stack))
+          if (is_arg_spill (gdbarch, reg[rn], addr, &stack))
             after_last_frame_setup_insn = next_pc;
 
-          pv_area_store (stack, addr, 4, reg[rn]);
+          stack.store (addr, 4, reg[rn]);
         }
       else if (IS_MOV (insn))
 	{
@@ -1786,13 +1783,13 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
                       : (gdb_assert (IS_SW (insn)), 4));
           pv_t addr = pv_add_constant (reg[rm], disp);
 
-          if (pv_area_store_would_trash (stack, addr))
+          if (stack.store_would_trash (addr))
             break;
 
-          if (is_arg_spill (gdbarch, reg[rn], addr, stack))
+          if (is_arg_spill (gdbarch, reg[rn], addr, &stack))
             after_last_frame_setup_insn = next_pc;
 
-          pv_area_store (stack, addr, size, reg[rn]);
+          stack.store (addr, size, reg[rn]);
 	}
       else if (IS_LDC (insn))
 	{
@@ -1808,7 +1805,7 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
           int offset = LW_OFFSET (insn);
           pv_t addr = pv_add_constant (reg[rm], offset);
 
-          reg[rn] = pv_area_fetch (stack, addr, 4);
+          reg[rn] = stack.fetch (addr, 4);
         }
       else if (IS_BRA (insn) && BRA_DISP (insn) > 0)
 	{
@@ -1887,11 +1884,9 @@ mep_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (stack, check_for_saved, (void *) result);
+  stack.scan (check_for_saved, (void *) result);
 
   result->prologue_end = after_last_frame_setup_insn;
-
-  do_cleanups (back_to);
 }
 
 
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
index 7b21e4f6dc..eadbbb367e 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -337,7 +337,7 @@ static void
 push_reg (pv_t *regs, struct pv_area *stack, int regnum)
 {
   regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4);
-  pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[regnum]);
+  stack->store (regs[E_SP_REGNUM], 4, regs[regnum]);
 }
 
 /* Translate an "r" register number extracted from an instruction encoding
@@ -356,7 +356,7 @@ translate_rreg (int rreg)
     return E_E0_REGNUM + rreg;
 }
 
-/* Find saved registers in a 'struct pv_area'; we pass this to pv_area_scan.
+/* Find saved registers in a 'struct pv_area'; we pass this to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -386,8 +386,6 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
   CORE_ADDR pc;
   int rn;
   pv_t regs[MN10300_MAX_NUM_REGS];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR after_last_frame_setup_insn = start_pc;
   int am33_mode = AM33_MODE (gdbarch);
 
@@ -399,16 +397,15 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
       regs[rn] = pv_register (rn, 0);
       result->reg_offset[rn] = 1;
     }
-  stack = make_pv_area (E_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (E_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
- /* The typical call instruction will have saved the return address on the
-    stack.  Space for the return address has already been preallocated in
-    the caller's frame.  It's possible, such as when using -mrelax with gcc
-    that other registers were saved as well.  If this happens, we really
-    have no chance of deciphering the frame.  DWARF info can save the day
-    when this happens.  */
-  pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);
+  /* The typical call instruction will have saved the return address on the
+     stack.  Space for the return address has already been preallocated in
+     the caller's frame.  It's possible, such as when using -mrelax with gcc
+     that other registers were saved as well.  If this happens, we really
+     have no chance of deciphering the frame.  DWARF info can save the day
+     when this happens.  */
+  stack.store (regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);
 
   pc = start_pc;
   while (pc < limit_pc)
@@ -432,42 +429,42 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 
 	  if ((save_mask & movm_exreg0_bit) && am33_mode)
 	    {
-	      push_reg (regs, stack, E_E2_REGNUM);
-	      push_reg (regs, stack, E_E3_REGNUM);
+	      push_reg (regs, &stack, E_E2_REGNUM);
+	      push_reg (regs, &stack, E_E3_REGNUM);
 	    }
 	  if ((save_mask & movm_exreg1_bit) && am33_mode)
 	    {
-	      push_reg (regs, stack, E_E4_REGNUM);
-	      push_reg (regs, stack, E_E5_REGNUM);
-	      push_reg (regs, stack, E_E6_REGNUM);
-	      push_reg (regs, stack, E_E7_REGNUM);
+	      push_reg (regs, &stack, E_E4_REGNUM);
+	      push_reg (regs, &stack, E_E5_REGNUM);
+	      push_reg (regs, &stack, E_E6_REGNUM);
+	      push_reg (regs, &stack, E_E7_REGNUM);
 	    }
 	  if ((save_mask & movm_exother_bit) && am33_mode)
 	    {
-	      push_reg (regs, stack, E_E0_REGNUM);
-	      push_reg (regs, stack, E_E1_REGNUM);
-	      push_reg (regs, stack, E_MDRQ_REGNUM);
-	      push_reg (regs, stack, E_MCRH_REGNUM);
-	      push_reg (regs, stack, E_MCRL_REGNUM);
-	      push_reg (regs, stack, E_MCVF_REGNUM);
+	      push_reg (regs, &stack, E_E0_REGNUM);
+	      push_reg (regs, &stack, E_E1_REGNUM);
+	      push_reg (regs, &stack, E_MDRQ_REGNUM);
+	      push_reg (regs, &stack, E_MCRH_REGNUM);
+	      push_reg (regs, &stack, E_MCRL_REGNUM);
+	      push_reg (regs, &stack, E_MCVF_REGNUM);
 	    }
 	  if (save_mask & movm_d2_bit)
-	    push_reg (regs, stack, E_D2_REGNUM);
+	    push_reg (regs, &stack, E_D2_REGNUM);
 	  if (save_mask & movm_d3_bit)
-	    push_reg (regs, stack, E_D3_REGNUM);
+	    push_reg (regs, &stack, E_D3_REGNUM);
 	  if (save_mask & movm_a2_bit)
-	    push_reg (regs, stack, E_A2_REGNUM);
+	    push_reg (regs, &stack, E_A2_REGNUM);
 	  if (save_mask & movm_a3_bit)
-	    push_reg (regs, stack, E_A3_REGNUM);
+	    push_reg (regs, &stack, E_A3_REGNUM);
 	  if (save_mask & movm_other_bit)
 	    {
-	      push_reg (regs, stack, E_D0_REGNUM);
-	      push_reg (regs, stack, E_D1_REGNUM);
-	      push_reg (regs, stack, E_A0_REGNUM);
-	      push_reg (regs, stack, E_A1_REGNUM);
-	      push_reg (regs, stack, E_MDR_REGNUM);
-	      push_reg (regs, stack, E_LIR_REGNUM);
-	      push_reg (regs, stack, E_LAR_REGNUM);
+	      push_reg (regs, &stack, E_D0_REGNUM);
+	      push_reg (regs, &stack, E_D1_REGNUM);
+	      push_reg (regs, &stack, E_A0_REGNUM);
+	      push_reg (regs, &stack, E_A1_REGNUM);
+	      push_reg (regs, &stack, E_MDR_REGNUM);
+	      push_reg (regs, &stack, E_LIR_REGNUM);
+	      push_reg (regs, &stack, E_LAR_REGNUM);
 	      /* The `other' bit leaves a blank area of four bytes at
 		 the beginning of its block of saved registers, making
 		 it 32 bytes long in total.  */
@@ -653,8 +650,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  rN = buf[0] & 0x0f;
 	  fsM = (Y << 4) | sM;
 
-	  pv_area_store (stack, regs[translate_rreg (rN)], 4,
-	                 regs[E_FS0_REGNUM + fsM]);
+	  stack.store (regs[translate_rreg (rN)], 4,
+		       regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 3;
 	}
@@ -673,8 +670,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  sM = (buf[0] & 0xf0) >> 4;
 	  fsM = (Y << 4) | sM;
 
-	  pv_area_store (stack, regs[E_SP_REGNUM], 4,
-	                 regs[E_FS0_REGNUM + fsM]);
+	  stack.store (regs[E_SP_REGNUM], 4,
+		       regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 3;
 	}
@@ -695,10 +692,9 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  Z = (buf[1] & 0x02) >> 1;
 	  fsM = (Z << 4) | sM;
 
-	  pv_area_store (stack,
-	                 pv_add (regs[translate_rreg (rN)],
-			         regs[translate_rreg (rI)]),
-			 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add (regs[translate_rreg (rN)],
+			       regs[translate_rreg (rI)]),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 4;
 	}
@@ -720,9 +716,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  fsM = (Y << 4) | sM;
 	  d8 = extract_signed_integer (&buf[1], 1, byte_order);
 
-	  pv_area_store (stack,
-	                 pv_add_constant (regs[translate_rreg (rN)], d8),
-	                 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add_constant (regs[translate_rreg (rN)], d8),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 4;
 	}
@@ -744,9 +739,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  fsM = (Y << 4) | sM;
 	  d24 = extract_signed_integer (&buf[1], 3, byte_order);
 
-	  pv_area_store (stack,
-	                 pv_add_constant (regs[translate_rreg (rN)], d24),
-	                 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add_constant (regs[translate_rreg (rN)], d24),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 6;
 	}
@@ -768,9 +762,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  fsM = (Y << 4) | sM;
 	  d32 = extract_signed_integer (&buf[1], 4, byte_order);
 
-	  pv_area_store (stack,
-	                 pv_add_constant (regs[translate_rreg (rN)], d32),
-	                 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add_constant (regs[translate_rreg (rN)], d32),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 7;
 	}
@@ -791,9 +784,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  fsM = (Y << 4) | sM;
 	  d8 = extract_signed_integer (&buf[1], 1, byte_order);
 
-	  pv_area_store (stack,
-	                 pv_add_constant (regs[E_SP_REGNUM], d8),
-	                 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add_constant (regs[E_SP_REGNUM], d8),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 4;
 	}
@@ -814,9 +806,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  fsM = (Y << 4) | sM;
 	  d24 = extract_signed_integer (&buf[1], 3, byte_order);
 
-	  pv_area_store (stack,
-	                 pv_add_constant (regs[E_SP_REGNUM], d24),
-	                 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add_constant (regs[E_SP_REGNUM], d24),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 6;
 	}
@@ -837,9 +828,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 	  fsM = (Y << 4) | sM;
 	  d32 = extract_signed_integer (&buf[1], 4, byte_order);
 
-	  pv_area_store (stack,
-	                 pv_add_constant (regs[E_SP_REGNUM], d32),
-	                 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (pv_add_constant (regs[E_SP_REGNUM], d32),
+		       4, regs[E_FS0_REGNUM + fsM]);
 
 	  pc += 7;
 	}
@@ -861,8 +851,8 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 
 	  rN_regnum = translate_rreg (rN);
 
-	  pv_area_store (stack, regs[rN_regnum], 4,
-	                 regs[E_FS0_REGNUM + fsM]);
+	  stack.store (regs[rN_regnum], 4,
+		       regs[E_FS0_REGNUM + fsM]);
 	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], 4);
 
 	  pc += 3;
@@ -887,7 +877,7 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 
 	  rN_regnum = translate_rreg (rN);
 
-	  pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
 	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm8);
 
 	  pc += 4;
@@ -912,7 +902,7 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 
 	  rN_regnum = translate_rreg (rN);
 
-	  pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
 	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm24);
 
 	  pc += 6;
@@ -937,7 +927,7 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
 
 	  rN_regnum = translate_rreg (rN);
 
-	  pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+	  stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
 	  regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm32);
 
 	  pc += 7;
@@ -1044,11 +1034,9 @@ mn10300_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (stack, check_for_saved, (void *) result);
+  stack.scan (check_for_saved, (void *) result);
 
   result->prologue_end = after_last_frame_setup_insn;
-
-  do_cleanups (back_to);
 }
 
 /* Function: skip_prologue
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index d74be1dcdf..771ac9cd04 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -311,7 +311,7 @@ msp430_get_opcode_byte (void *handle)
 }
 
 /* Function for finding saved registers in a 'struct pv_area'; this
-   function is passed to pv_area_scan.
+   function is passed to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -339,8 +339,6 @@ msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
   CORE_ADDR pc, next_pc;
   int rn;
   pv_t reg[MSP430_NUM_TOTAL_REGS];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR after_last_frame_setup_insn = start_pc;
   int code_model = gdbarch_tdep (gdbarch)->code_model;
   int sz;
@@ -353,13 +351,12 @@ msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
       result->reg_offset[rn] = 1;
     }
 
-  stack = make_pv_area (MSP430_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (MSP430_SP_REGNUM, gdbarch_addr_bit (gdbarch));
 
   /* The call instruction has saved the return address on the stack.  */
   sz = code_model == MSP_LARGE_CODE_MODEL ? 4 : 2;
   reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -sz);
-  pv_area_store (stack, reg[MSP430_SP_REGNUM], sz, reg[MSP430_PC_REGNUM]);
+  stack.store (reg[MSP430_SP_REGNUM], sz, reg[MSP430_PC_REGNUM]);
 
   pc = start_pc;
   while (pc < limit_pc)
@@ -378,7 +375,7 @@ msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
 	  int rsrc = opc.op[0].reg;
 
 	  reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -2);
-	  pv_area_store (stack, reg[MSP430_SP_REGNUM], 2, reg[rsrc]);
+	  stack.store (reg[MSP430_SP_REGNUM], 2, reg[rsrc]);
 	  after_last_frame_setup_insn = next_pc;
 	}
       else if (opc.id == MSO_push	/* PUSHM  */
@@ -393,7 +390,7 @@ msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
 	    {
 	      reg[MSP430_SP_REGNUM]
 		= pv_add_constant (reg[MSP430_SP_REGNUM], -size);
-	      pv_area_store (stack, reg[MSP430_SP_REGNUM], size, reg[rsrc]);
+	      stack.store (reg[MSP430_SP_REGNUM], size, reg[rsrc]);
 	      rsrc--;
 	      count--;
 	    }
@@ -428,11 +425,9 @@ msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
     result->frame_size = reg[MSP430_SP_REGNUM].k;
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (stack, check_for_saved, result);
+  stack.scan (check_for_saved, result);
 
   result->prologue_end = after_last_frame_setup_insn;
-
-  do_cleanups (back_to);
 }
 
 /* Implement the "skip_prologue" gdbarch method.  */
diff --git a/gdb/prologue-value.c b/gdb/prologue-value.c
index 5263f131ad..b830b8f50d 100644
--- a/gdb/prologue-value.c
+++ b/gdb/prologue-value.c
@@ -278,7 +278,7 @@ pv_is_array_ref (pv_t addr, CORE_ADDR size,
    The entry with the lowest offset simply follows the entry with the
    highest offset.  Entries may abut, but never overlap.  The area's
    'entry' pointer points to an arbitrary node in the ring.  */
-struct area_entry
+struct pv_area::area_entry
 {
   /* Links in the doubly-linked ring.  */
   struct area_entry *prev, *next;
@@ -296,44 +296,19 @@ struct area_entry
 };
 
 
-struct pv_area
+pv_area::pv_area (int base_reg, int addr_bit)
+  : m_base_reg (base_reg),
+    /* Remember that shift amounts equal to the type's width are
+       undefined.  */
+    m_addr_mask (((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1),
+    m_entry (nullptr)
 {
-  /* This area's base register.  */
-  int base_reg;
-
-  /* The mask to apply to addresses, to make the wrap-around happen at
-     the right place.  */
-  CORE_ADDR addr_mask;
-
-  /* An element of the doubly-linked ring of entries, or zero if we
-     have none.  */
-  struct area_entry *entry;
-};
-
-
-struct pv_area *
-make_pv_area (int base_reg, int addr_bit)
-{
-  struct pv_area *a = XNEW (struct pv_area);
-
-  memset (a, 0, sizeof (*a));
-
-  a->base_reg = base_reg;
-  a->entry = 0;
-
-  /* Remember that shift amounts equal to the type's width are
-     undefined.  */
-  a->addr_mask = ((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1;
-
-  return a;
 }
 
-
-/* Delete all entries from AREA.  */
-static void
-clear_entries (struct pv_area *area)
+void
+pv_area::clear_entries ()
 {
-  struct area_entry *e = area->entry;
+  struct area_entry *e = m_entry;
 
   if (e)
     {
@@ -347,37 +322,21 @@ clear_entries (struct pv_area *area)
           xfree (e);
           e = next;
         }
-      while (e != area->entry);
+      while (e != m_entry);
 
-      area->entry = 0;
+      m_entry = 0;
     }
 }
 
 
-void
-free_pv_area (struct pv_area *area)
+pv_area::~pv_area ()
 {
-  clear_entries (area);
-  xfree (area);
-}
-
-
-static void
-do_free_pv_area_cleanup (void *arg)
-{
-  free_pv_area ((struct pv_area *) arg);
-}
-
-
-struct cleanup *
-make_cleanup_free_pv_area (struct pv_area *area)
-{
-  return make_cleanup (do_free_pv_area_cleanup, (void *) area);
+  clear_entries ();
 }
 
 
 int
-pv_area_store_would_trash (struct pv_area *area, pv_t addr)
+pv_area::store_would_trash (pv_t addr)
 {
   /* It may seem odd that pvk_constant appears here --- after all,
      that's the case where we know the most about the address!  But
@@ -386,23 +345,14 @@ pv_area_store_would_trash (struct pv_area *area, pv_t addr)
      constants.  */
   return (addr.kind == pvk_unknown
           || addr.kind == pvk_constant
-          || (addr.kind == pvk_register && addr.reg != area->base_reg));
+          || (addr.kind == pvk_register && addr.reg != m_base_reg));
 }
 
 
-/* Return a pointer to the first entry we hit in AREA starting at
-   OFFSET and going forward.
-
-   This may return zero, if AREA has no entries.
-
-   And since the entries are a ring, this may return an entry that
-   entirely precedes OFFSET.  This is the correct behavior: depending
-   on the sizes involved, we could still overlap such an area, with
-   wrap-around.  */
-static struct area_entry *
-find_entry (struct pv_area *area, CORE_ADDR offset)
+struct pv_area::area_entry *
+pv_area::find_entry (CORE_ADDR offset)
 {
-  struct area_entry *e = area->entry;
+  struct area_entry *e = m_entry;
 
   if (! e)
     return 0;
@@ -416,19 +366,19 @@ find_entry (struct pv_area *area, CORE_ADDR offset)
      with wrap-around.  We have to subtract offset from both sides to
      make sure both things we're comparing are on the same side of the
      discontinuity.  */
-  while (((e->next->offset - offset) & area->addr_mask)
-         < ((e->offset - offset) & area->addr_mask))
+  while (((e->next->offset - offset) & m_addr_mask)
+         < ((e->offset - offset) & m_addr_mask))
     e = e->next;
 
   /* If the previous entry would be better than the current one, then
      scan backwards.  */
-  while (((e->prev->offset - offset) & area->addr_mask)
-         < ((e->offset - offset) & area->addr_mask))
+  while (((e->prev->offset - offset) & m_addr_mask)
+         < ((e->offset - offset) & m_addr_mask))
     e = e->prev;
 
   /* In case there's some locality to the searches, set the area's
      pointer to the entry we've found.  */
-  area->entry = e;
+  m_entry = e;
 
   return e;
 }
@@ -436,34 +386,28 @@ find_entry (struct pv_area *area, CORE_ADDR offset)
 
 /* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY;
    return zero otherwise.  AREA is the area to which ENTRY belongs.  */
-static int
-overlaps (struct pv_area *area,
-          struct area_entry *entry,
-          CORE_ADDR offset,
-          CORE_ADDR size)
+int
+pv_area::overlaps (struct area_entry *entry, CORE_ADDR offset, CORE_ADDR size)
 {
   /* Think carefully about wrap-around before simplifying this.  */
-  return (((entry->offset - offset) & area->addr_mask) < size
-          || ((offset - entry->offset) & area->addr_mask) < entry->size);
+  return (((entry->offset - offset) & m_addr_mask) < size
+          || ((offset - entry->offset) & m_addr_mask) < entry->size);
 }
 
 
 void
-pv_area_store (struct pv_area *area,
-               pv_t addr,
-               CORE_ADDR size,
-               pv_t value)
+pv_area::store (pv_t addr, CORE_ADDR size, pv_t value)
 {
   /* Remove any (potentially) overlapping entries.  */
-  if (pv_area_store_would_trash (area, addr))
-    clear_entries (area);
+  if (store_would_trash (addr))
+    clear_entries ();
   else
     {
       CORE_ADDR offset = addr.k;
-      struct area_entry *e = find_entry (area, offset);
+      struct area_entry *e = find_entry (offset);
 
       /* Delete all entries that we would overlap.  */
-      while (e && overlaps (area, e, offset, size))
+      while (e && overlaps (e, offset, size))
         {
           struct area_entry *next = (e->next == e) ? 0 : e->next;
 
@@ -476,10 +420,10 @@ pv_area_store (struct pv_area *area,
 
       /* Move the area's pointer to the next remaining entry.  This
          will also zero the pointer if we've deleted all the entries.  */
-      area->entry = e;
+      m_entry = e;
     }
 
-  /* Now, there are no entries overlapping us, and area->entry is
+  /* Now, there are no entries overlapping us, and m_entry is
      either zero or pointing at the closest entry after us.  We can
      just insert ourselves before that.
 
@@ -496,33 +440,33 @@ pv_area_store (struct pv_area *area,
       e->size = size;
       e->value = value;
 
-      if (area->entry)
+      if (m_entry)
         {
-          e->prev = area->entry->prev;
-          e->next = area->entry;
+          e->prev = m_entry->prev;
+          e->next = m_entry;
           e->prev->next = e->next->prev = e;
         }
       else
         {
           e->prev = e->next = e;
-          area->entry = e;
+          m_entry = e;
         }
     }
 }
 
 
 pv_t
-pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size)
+pv_area::fetch (pv_t addr, CORE_ADDR size)
 {
   /* If we have no entries, or we can't decide how ADDR relates to the
      entries we do have, then the value is unknown.  */
-  if (! area->entry
-      || pv_area_store_would_trash (area, addr))
+  if (! m_entry
+      || store_would_trash (addr))
     return pv_unknown ();
   else
     {
       CORE_ADDR offset = addr.k;
-      struct area_entry *e = find_entry (area, offset);
+      struct area_entry *e = find_entry (offset);
 
       /* If this entry exactly matches what we're looking for, then
          we're set.  Otherwise, say it's unknown.  */
@@ -535,12 +479,9 @@ pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size)
 
 
 int
-pv_area_find_reg (struct pv_area *area,
-                  struct gdbarch *gdbarch,
-                  int reg,
-                  CORE_ADDR *offset_p)
+pv_area::find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p)
 {
-  struct area_entry *e = area->entry;
+  struct area_entry *e = m_entry;
 
   if (e)
     do
@@ -557,25 +498,24 @@ pv_area_find_reg (struct pv_area *area,
 
         e = e->next;
       }
-    while (e != area->entry);
+    while (e != m_entry);
 
   return 0;
 }
 
 
 void
-pv_area_scan (struct pv_area *area,
-              void (*func) (void *closure,
-                            pv_t addr,
-                            CORE_ADDR size,
-                            pv_t value),
-              void *closure)
+pv_area::scan (void (*func) (void *closure,
+			     pv_t addr,
+			     CORE_ADDR size,
+			     pv_t value),
+	       void *closure)
 {
-  struct area_entry *e = area->entry;
+  struct area_entry *e = m_entry;
   pv_t addr;
 
   addr.kind = pvk_register;
-  addr.reg = area->base_reg;
+  addr.reg = m_base_reg;
 
   if (e)
     do
@@ -584,5 +524,5 @@ pv_area_scan (struct pv_area *area,
         func (closure, addr, e->size, e->value);
         e = e->next;
       }
-    while (e != area->entry);
+    while (e != m_entry);
 }
diff --git a/gdb/prologue-value.h b/gdb/prologue-value.h
index e09c886a2c..e3004aa6ad 100644
--- a/gdb/prologue-value.h
+++ b/gdb/prologue-value.h
@@ -221,83 +221,110 @@ enum pv_boolean pv_is_array_ref (pv_t addr, CORE_ADDR size,
                                  int *i);
 
 
-/* A 'struct pv_area' keeps track of values stored in a particular
-   region of memory.  */
-struct pv_area;
-
-/* Create a new area, tracking stores relative to the original value
-   of BASE_REG.  If BASE_REG is SP, then this effectively records the
-   contents of the stack frame: the original value of the SP is the
-   frame's CFA, or some constant offset from it.
-
-   Stores to constant addresses, unknown addresses, or to addresses
-   relative to registers other than BASE_REG will trash this area; see
-   pv_area_store_would_trash.
-
-   To check whether a pointer refers to this area, only the low
-   ADDR_BIT bits will be compared.  */
-struct pv_area *make_pv_area (int base_reg, int addr_bit);
-
-/* Free AREA.  */
-void free_pv_area (struct pv_area *area);
-
-
-/* Register a cleanup to free AREA.  */
-struct cleanup *make_cleanup_free_pv_area (struct pv_area *area);
-
-
-/* Store the SIZE-byte value VALUE at ADDR in AREA.
-
-   If ADDR is not relative to the same base register we used in
-   creating AREA, then we can't tell which values here the stored
-   value might overlap, and we'll have to mark everything as
-   unknown.  */
-void pv_area_store (struct pv_area *area,
-                    pv_t addr,
-                    CORE_ADDR size,
-                    pv_t value);
-
-/* Return the SIZE-byte value at ADDR in AREA.  This may return
-   pv_unknown ().  */
-pv_t pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size);
-
-/* Return true if storing to address ADDR in AREA would force us to
-   mark the contents of the entire area as unknown.  This could happen
-   if, say, ADDR is unknown, since we could be storing anywhere.  Or,
-   it could happen if ADDR is relative to a different register than
-   the other stores base register, since we don't know the relative
-   values of the two registers.
-
-   If you've reached such a store, it may be better to simply stop the
-   prologue analysis, and return the information you've gathered,
-   instead of losing all that information, most of which is probably
-   okay.  */
-int pv_area_store_would_trash (struct pv_area *area, pv_t addr);
-
-
-/* Search AREA for the original value of REGISTER.  If we can't find
-   it, return zero; if we can find it, return a non-zero value, and if
-   OFFSET_P is non-zero, set *OFFSET_P to the register's offset within
-   AREA.  GDBARCH is the architecture of which REGISTER is a member.
-
-   In the worst case, this takes time proportional to the number of
-   items stored in AREA.  If you plan to gather a lot of information
-   about registers saved in AREA, consider calling pv_area_scan
-   instead, and collecting all your information in one pass.  */
-int pv_area_find_reg (struct pv_area *area,
-                      struct gdbarch *gdbarch,
-                      int reg,
-                      CORE_ADDR *offset_p);
-
-
-/* For every part of AREA whose value we know, apply FUNC to CLOSURE,
-   the value's address, its size, and the value itself.  */
-void pv_area_scan (struct pv_area *area,
-                   void (*func) (void *closure,
-                                 pv_t addr,
-                                 CORE_ADDR size,
-                                 pv_t value),
-                   void *closure);
-
+/* A 'pv_area' keeps track of values stored in a particular region of
+   memory.  */
+class pv_area
+{
+public:
+
+  /* Create a new area, tracking stores relative to the original value
+     of BASE_REG.  If BASE_REG is SP, then this effectively records the
+     contents of the stack frame: the original value of the SP is the
+     frame's CFA, or some constant offset from it.
+
+     Stores to constant addresses, unknown addresses, or to addresses
+     relative to registers other than BASE_REG will trash this area; see
+     pv_area::store_would_trash.
+
+     To check whether a pointer refers to this area, only the low
+     ADDR_BIT bits will be compared.  */
+  pv_area (int base_reg, int addr_bit);
+
+  ~pv_area ();
+
+  DISABLE_COPY_AND_ASSIGN (pv_area);
+
+  /* Store the SIZE-byte value VALUE at ADDR in AREA.
+
+     If ADDR is not relative to the same base register we used in
+     creating AREA, then we can't tell which values here the stored
+     value might overlap, and we'll have to mark everything as
+     unknown.  */
+  void store (pv_t addr,
+	      CORE_ADDR size,
+	      pv_t value);
+
+  /* Return the SIZE-byte value at ADDR in AREA.  This may return
+     pv_unknown ().  */
+  pv_t fetch (pv_t addr, CORE_ADDR size);
+
+  /* Return true if storing to address ADDR in AREA would force us to
+     mark the contents of the entire area as unknown.  This could happen
+     if, say, ADDR is unknown, since we could be storing anywhere.  Or,
+     it could happen if ADDR is relative to a different register than
+     the other stores base register, since we don't know the relative
+     values of the two registers.
+
+     If you've reached such a store, it may be better to simply stop the
+     prologue analysis, and return the information you've gathered,
+     instead of losing all that information, most of which is probably
+     okay.  */
+  int store_would_trash (pv_t addr);
+
+  /* Search AREA for the original value of REGISTER.  If we can't find
+     it, return zero; if we can find it, return a non-zero value, and if
+     OFFSET_P is non-zero, set *OFFSET_P to the register's offset within
+     AREA.  GDBARCH is the architecture of which REGISTER is a member.
+
+     In the worst case, this takes time proportional to the number of
+     items stored in AREA.  If you plan to gather a lot of information
+     about registers saved in AREA, consider calling pv_area::scan
+     instead, and collecting all your information in one pass.  */
+  int find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p);
+
+
+  /* For every part of AREA whose value we know, apply FUNC to CLOSURE,
+     the value's address, its size, and the value itself.  */
+  void scan (void (*func) (void *closure,
+			   pv_t addr,
+			   CORE_ADDR size,
+			   pv_t value),
+	     void *closure);
+
+private:
+
+  struct area_entry;
+
+  /* Delete all entries from AREA.  */
+  void clear_entries ();
+
+  /* Return a pointer to the first entry we hit in AREA starting at
+     OFFSET and going forward.
+
+     This may return zero, if AREA has no entries.
+
+     And since the entries are a ring, this may return an entry that
+     entirely precedes OFFSET.  This is the correct behavior: depending
+     on the sizes involved, we could still overlap such an area, with
+     wrap-around.  */
+  struct area_entry *find_entry (CORE_ADDR offset);
+
+  /* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY;
+     return zero otherwise.  AREA is the area to which ENTRY belongs.  */
+  int overlaps (struct area_entry *entry,
+		CORE_ADDR offset,
+		CORE_ADDR size);
+
+  /* This area's base register.  */
+  int m_base_reg;
+
+  /* The mask to apply to addresses, to make the wrap-around happen at
+     the right place.  */
+  CORE_ADDR m_addr_mask;
+
+  /* An element of the doubly-linked ring of entries, or zero if we
+     have none.  */
+  struct area_entry *m_entry;
+};
 
 #endif /* PROLOGUE_VALUE_H */
diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
index c3d5352eac..19f8098b7b 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -883,7 +883,7 @@ rl78_get_opcode_byte (void *handle)
 }
 
 /* Function for finding saved registers in a 'struct pv_area'; this
-   function is passed to pv_area_scan.
+   function is passed to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -912,8 +912,6 @@ rl78_analyze_prologue (CORE_ADDR start_pc,
   CORE_ADDR pc, next_pc;
   int rn;
   pv_t reg[RL78_NUM_TOTAL_REGS];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR after_last_frame_setup_insn = start_pc;
   int bank = 0;
 
@@ -925,12 +923,11 @@ rl78_analyze_prologue (CORE_ADDR start_pc,
       result->reg_offset[rn] = 1;
     }
 
-  stack = make_pv_area (RL78_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (RL78_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
 
   /* The call instruction has saved the return address on the stack.  */
   reg[RL78_SP_REGNUM] = pv_add_constant (reg[RL78_SP_REGNUM], -4);
-  pv_area_store (stack, reg[RL78_SP_REGNUM], 4, reg[RL78_PC_REGNUM]);
+  stack.store (reg[RL78_SP_REGNUM], 4, reg[RL78_PC_REGNUM]);
 
   pc = start_pc;
   while (pc < limit_pc)
@@ -954,12 +951,12 @@ rl78_analyze_prologue (CORE_ADDR start_pc,
 	       && opc.op[1].type == RL78_Operand_Register)
 	{
 	  int rsrc = (bank * RL78_REGS_PER_BANK) 
-	           + 2 * (opc.op[1].reg - RL78_Reg_AX);
+	    + 2 * (opc.op[1].reg - RL78_Reg_AX);
 
 	  reg[RL78_SP_REGNUM] = pv_add_constant (reg[RL78_SP_REGNUM], -1);
-	  pv_area_store (stack, reg[RL78_SP_REGNUM], 1, reg[rsrc]);
+	  stack.store (reg[RL78_SP_REGNUM], 1, reg[rsrc]);
 	  reg[RL78_SP_REGNUM] = pv_add_constant (reg[RL78_SP_REGNUM], -1);
-	  pv_area_store (stack, reg[RL78_SP_REGNUM], 1, reg[rsrc + 1]);
+	  stack.store (reg[RL78_SP_REGNUM], 1, reg[rsrc + 1]);
 	  after_last_frame_setup_insn = next_pc;
 	}
       else if (opc.id == RLO_sub
@@ -1016,11 +1013,9 @@ rl78_analyze_prologue (CORE_ADDR start_pc,
     result->frame_size = reg[RL78_SP_REGNUM].k;
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (stack, check_for_saved, (void *) result);
+  stack.scan (check_for_saved, (void *) result);
 
   result->prologue_end = after_last_frame_setup_insn;
-
-  do_cleanups (back_to);
 }
 
 /* Implement the "addr_bits_remove" gdbarch method.  */
diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
index ac2b68f33f..7d0436c33f 100644
--- a/gdb/rx-tdep.c
+++ b/gdb/rx-tdep.c
@@ -230,7 +230,7 @@ rx_register_type (struct gdbarch *gdbarch, int reg_nr)
 
 
 /* Function for finding saved registers in a 'struct pv_area'; this
-   function is passed to pv_area_scan.
+   function is passed to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -287,8 +287,6 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   CORE_ADDR pc, next_pc;
   int rn;
   pv_t reg[RX_NUM_REGS];
-  struct pv_area *stack;
-  struct cleanup *back_to;
   CORE_ADDR after_last_frame_setup_insn = start_pc;
 
   memset (result, 0, sizeof (*result));
@@ -301,8 +299,7 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
       result->reg_offset[rn] = 1;
     }
 
-  stack = make_pv_area (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
-  back_to = make_cleanup_free_pv_area (stack);
+  pv_area stack (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
 
   if (frame_type == RX_FRAME_TYPE_FAST_INTERRUPT)
     {
@@ -318,13 +315,13 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
       if (frame_type == RX_FRAME_TYPE_EXCEPTION)
 	{
 	  reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
-	  pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PSW_REGNUM]);
+	  stack.store (reg[RX_SP_REGNUM], 4, reg[RX_PSW_REGNUM]);
 	}
 
       /* The call instruction (or an exception/interrupt) has saved the return
           address on the stack.  */
       reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
-      pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]);
+      stack.store (reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]);
 
     }
 
@@ -353,7 +350,7 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 	  for (r = r2; r >= r1; r--)
 	    {
 	      reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
-	      pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[r]);
+	      stack.store (reg[RX_SP_REGNUM], 4, reg[r]);
 	    }
 	  after_last_frame_setup_insn = next_pc;
 	}
@@ -380,7 +377,7 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 
 	  rsrc = opc.op[1].reg;
 	  reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
-	  pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[rsrc]);
+	  stack.store (reg[RX_SP_REGNUM], 4, reg[rsrc]);
 	  after_last_frame_setup_insn = next_pc;
 	}
       else if (opc.id == RXO_add	/* add #const, rsrc, rdst */
@@ -456,11 +453,9 @@ rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
     }
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (stack, check_for_saved, (void *) result);
+  stack.scan (check_for_saved, (void *) result);
 
   result->prologue_end = after_last_frame_setup_insn;
-
-  do_cleanups (back_to);
 }
 
 
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index dfc7404f4b..d48364b93f 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -1375,8 +1375,8 @@ s390_store (struct s390_prologue_data *data,
 
 
   /* Check whether we are storing a register into the stack.  */
-  if (!pv_area_store_would_trash (data->stack, addr))
-    pv_area_store (data->stack, addr, size, value);
+  if (!data->stack->store_would_trash (addr))
+    data->stack->store (addr, size, value);
 
 
   /* Note: If this is some store we cannot identify, you might think we
@@ -1413,11 +1413,11 @@ s390_load (struct s390_prologue_data *data,
     }
 
   /* Check whether we are accessing one of our save slots.  */
-  return pv_area_fetch (data->stack, addr, size);
+  return data->stack->fetch (addr, size);
 }
 
 /* Function for finding saved registers in a 'struct pv_area'; we pass
-   this to pv_area_scan.
+   this to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -1486,12 +1486,13 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
   /* The address of the next instruction after that.  */
   CORE_ADDR next_pc;
 
+  pv_area stack (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch));
+  scoped_restore restore_stack = make_scoped_restore (&data->stack, &stack);
+
   /* Set up everything's initial value.  */
   {
     int i;
 
-    data->stack = make_pv_area (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-
     /* For the purpose of prologue tracking, we consider the GPR size to
        be equal to the ABI word size, even if it is actually larger
        (i.e. when running a 32-bit binary under a 64-bit kernel).  */
@@ -1730,10 +1731,7 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (data->stack, s390_check_for_saved, data);
-
-  free_pv_area (data->stack);
-  data->stack = NULL;
+  data->stack->scan (s390_check_for_saved, data);
 
   return result;
 }
-- 
2.13.6

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFA 2/3] Use bool in pv_area
  2017-10-08 17:08 [RFA 0/3] C++-ify pv_area Tom Tromey
  2017-10-08 17:07 ` [RFA 3/3] Use gdb::function_view in pv_area Tom Tromey
  2017-10-08 17:08 ` [RFA 1/3] C++-ify prologue-value's pv_area Tom Tromey
@ 2017-10-08 17:08 ` Tom Tromey
  2017-10-09  3:12   ` Simon Marchi
  2 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2017-10-08 17:08 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This updates a couple of member functions in pv_area to return bool.

gdb/ChangeLog
2017-10-07  Tom Tromey  <tom@tromey.com>

	* prologue-value.h (pv_area::store_would_trash): Return bool.
	(pv_area::find_reg): Likewise.
	* prologue-value.c (pv_area::store_would_trash): Return bool.
	(pv_area::find_reg): Likewise.
---
 gdb/ChangeLog        | 7 +++++++
 gdb/prologue-value.c | 8 ++++----
 gdb/prologue-value.h | 4 ++--
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/gdb/prologue-value.c b/gdb/prologue-value.c
index b830b8f50d..2b2e5a8b65 100644
--- a/gdb/prologue-value.c
+++ b/gdb/prologue-value.c
@@ -335,7 +335,7 @@ pv_area::~pv_area ()
 }
 
 
-int
+bool
 pv_area::store_would_trash (pv_t addr)
 {
   /* It may seem odd that pvk_constant appears here --- after all,
@@ -478,7 +478,7 @@ pv_area::fetch (pv_t addr, CORE_ADDR size)
 }
 
 
-int
+bool
 pv_area::find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p)
 {
   struct area_entry *e = m_entry;
@@ -493,14 +493,14 @@ pv_area::find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p)
           {
             if (offset_p)
               *offset_p = e->offset;
-            return 1;
+            return true;
           }
 
         e = e->next;
       }
     while (e != m_entry);
 
-  return 0;
+  return false;
 }
 
 
diff --git a/gdb/prologue-value.h b/gdb/prologue-value.h
index e3004aa6ad..c6fd34bdab 100644
--- a/gdb/prologue-value.h
+++ b/gdb/prologue-value.h
@@ -269,7 +269,7 @@ public:
      prologue analysis, and return the information you've gathered,
      instead of losing all that information, most of which is probably
      okay.  */
-  int store_would_trash (pv_t addr);
+  bool store_would_trash (pv_t addr);
 
   /* Search AREA for the original value of REGISTER.  If we can't find
      it, return zero; if we can find it, return a non-zero value, and if
@@ -280,7 +280,7 @@ public:
      items stored in AREA.  If you plan to gather a lot of information
      about registers saved in AREA, consider calling pv_area::scan
      instead, and collecting all your information in one pass.  */
-  int find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p);
+  bool find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p);
 
 
   /* For every part of AREA whose value we know, apply FUNC to CLOSURE,
-- 
2.13.6

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFA 0/3] C++-ify pv_area
@ 2017-10-08 17:08 Tom Tromey
  2017-10-08 17:07 ` [RFA 3/3] Use gdb::function_view in pv_area Tom Tromey
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Tom Tromey @ 2017-10-08 17:08 UTC (permalink / raw)
  To: gdb-patches

This series C++-ifies pv_area, allowing the removal of some cleanups.

The first patch is the main change, with the follow-up patches being
additional C++-ifications I noticed while working on that.

Regression tested by the buildbot; but since the users are all in "non
primary" targets, I think careful review should be done.  That said,
the changes to the users of this API are, generally, straightforward,
and I did most of them with a regexp replace.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFA 1/3] C++-ify prologue-value's pv_area
  2017-10-08 17:08 ` [RFA 1/3] C++-ify prologue-value's pv_area Tom Tromey
@ 2017-10-09  3:04   ` Simon Marchi
  2017-10-12 21:33     ` Tom Tromey
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Marchi @ 2017-10-09  3:04 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 2017-10-08 01:07 PM, Tom Tromey wrote:
> diff --git a/gdb/prologue-value.c b/gdb/prologue-value.c
> index 5263f131ad..b830b8f50d 100644
> --- a/gdb/prologue-value.c
> +++ b/gdb/prologue-value.c
> @@ -278,7 +278,7 @@ pv_is_array_ref (pv_t addr, CORE_ADDR size,
>     The entry with the lowest offset simply follows the entry with the
>     highest offset.  Entries may abut, but never overlap.  The area's
>     'entry' pointer points to an arbitrary node in the ring.  */
> -struct area_entry
> +struct pv_area::area_entry
>  {
>    /* Links in the doubly-linked ring.  */
>    struct area_entry *prev, *next;
> @@ -296,44 +296,19 @@ struct area_entry
>  };
>  
>  
> -struct pv_area
> +pv_area::pv_area (int base_reg, int addr_bit)
> +  : m_base_reg (base_reg),
> +    /* Remember that shift amounts equal to the type's width are
> +       undefined.  */
> +    m_addr_mask (((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1),
> +    m_entry (nullptr)
>  {
> -  /* This area's base register.  */
> -  int base_reg;
> -
> -  /* The mask to apply to addresses, to make the wrap-around happen at
> -     the right place.  */
> -  CORE_ADDR addr_mask;
> -
> -  /* An element of the doubly-linked ring of entries, or zero if we
> -     have none.  */
> -  struct area_entry *entry;
> -};
> -
> -
> -struct pv_area *
> -make_pv_area (int base_reg, int addr_bit)
> -{
> -  struct pv_area *a = XNEW (struct pv_area);
> -
> -  memset (a, 0, sizeof (*a));
> -
> -  a->base_reg = base_reg;
> -  a->entry = 0;
> -
> -  /* Remember that shift amounts equal to the type's width are
> -     undefined.  */
> -  a->addr_mask = ((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1;
> -
> -  return a;
>  }
>  
> -
> -/* Delete all entries from AREA.  */
> -static void
> -clear_entries (struct pv_area *area)
> +void
> +pv_area::clear_entries ()
>  {
> -  struct area_entry *e = area->entry;
> +  struct area_entry *e = m_entry;
>  
>    if (e)
>      {
> @@ -347,37 +322,21 @@ clear_entries (struct pv_area *area)
>            xfree (e);
>            e = next;
>          }
> -      while (e != area->entry);
> +      while (e != m_entry);
>  
> -      area->entry = 0;
> +      m_entry = 0;
>      }
>  }
>  
>  
> -void
> -free_pv_area (struct pv_area *area)
> +pv_area::~pv_area ()
>  {
> -  clear_entries (area);
> -  xfree (area);
> -}
> -
> -
> -static void
> -do_free_pv_area_cleanup (void *arg)
> -{
> -  free_pv_area ((struct pv_area *) arg);
> -}
> -
> -
> -struct cleanup *
> -make_cleanup_free_pv_area (struct pv_area *area)
> -{
> -  return make_cleanup (do_free_pv_area_cleanup, (void *) area);
> +  clear_entries ();
>  }
>  
>  
>  int
> -pv_area_store_would_trash (struct pv_area *area, pv_t addr)
> +pv_area::store_would_trash (pv_t addr)
>  {

On top of methods, I think there should be

  /* See prologue-value.h.  */

like for regular functions.

Otherwise, LGTM.

Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFA 2/3] Use bool in pv_area
  2017-10-08 17:08 ` [RFA 2/3] Use bool in pv_area Tom Tromey
@ 2017-10-09  3:12   ` Simon Marchi
  0 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2017-10-09  3:12 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 2017-10-08 01:07 PM, Tom Tromey wrote:
> This updates a couple of member functions in pv_area to return bool.

LGTM.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFA 3/3] Use gdb::function_view in pv_area
  2017-10-08 17:07 ` [RFA 3/3] Use gdb::function_view in pv_area Tom Tromey
@ 2017-10-09  4:06   ` Simon Marchi
  2017-10-09 15:10     ` Tom Tromey
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Marchi @ 2017-10-09  4:06 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 2017-10-08 01:07 PM, Tom Tromey wrote:
> This changes pv_area::scan to use gdb::function_view and updates all
> the callers.  The primary gain from this change is type-safety in the
> calling code.
> 
> gdb/ChangeLog
> 2017-10-07  Tom Tromey  <tom@tromey.com>
> 
> 	* rl78-tdep.c (rl78_analyze_prologue): Update.
> 	(check_for_saved): Change type of "result".
> 	* msp430-tdep.c (check_for_saved): Change type of "result".
> 	(msp430_analyze_prologue): Update.
> 	* rx-tdep.c (rx_analyze_prologue): Update.
> 	(check_for_saved): Change type of "result".
> 	* mn10300-tdep.c (mn10300_analyze_prologue): Update.
> 	(check_for_saved): Change type of "result".
> 	* m32c-tdep.c (m32c_analyze_prologue): Update.
> 	(check_for_saved): Change type of "prologue".
> 	* s390-linux-tdep.c (s390_check_for_saved): Change type of
> 	"data".
> 	(s390_analyze_prologue): Update.
> 	* mep-tdep.c (check_for_saved): Change type of "result".
> 	(mep_analyze_prologue): Update.
> 	* prologue-value.h (pv_area::scan): Use gdb::function_view.
> ---
>  gdb/ChangeLog         | 19 +++++++++++++++++++
>  gdb/m32c-tdep.c       |  8 +++++---
>  gdb/mep-tdep.c        |  9 +++++----
>  gdb/mn10300-tdep.c    |  9 +++++----
>  gdb/msp430-tdep.c     |  9 +++++----
>  gdb/prologue-value.c  | 10 ++++------
>  gdb/prologue-value.h  | 14 +++++++-------
>  gdb/rl78-tdep.c       |  8 ++++----
>  gdb/rx-tdep.c         |  9 +++++----
>  gdb/s390-linux-tdep.c |  7 ++++---
>  10 files changed, 63 insertions(+), 39 deletions(-)
> 
> diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
> index 39f9ec0e5a..62d575b3ef 100644
> --- a/gdb/m32c-tdep.c
> +++ b/gdb/m32c-tdep.c
> @@ -36,6 +36,7 @@
>  #include "prologue-value.h"
>  #include "target.h"
>  #include "objfiles.h"
> +#include <functional>
>  
>  \f
>  /* The m32c tdep structure.  */
> @@ -1499,9 +1500,9 @@ m32c_pushm_is_reg_save (struct m32c_pv_state *st, int src)
>     offset from the frame base, and SIZE indicates that the whole
>     register was saved, record its offset in RESULT_UNTYPED.  */
>  static void
> -check_for_saved (void *prologue_untyped, pv_t addr, CORE_ADDR size, pv_t value)
> +check_for_saved (struct m32c_prologue *prologue, pv_t addr, CORE_ADDR size,
> +		 pv_t value)
>  {
> -  struct m32c_prologue *prologue = (struct m32c_prologue *) prologue_untyped;
>    struct gdbarch *arch = prologue->arch;
>    struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
>  
> @@ -1811,7 +1812,8 @@ m32c_analyze_prologue (struct gdbarch *arch,
>      prologue->kind = prologue_first_frame;
>  
>    /* Record where all the registers were saved.  */
> -  st.stack->scan (check_for_saved, (void *) prologue);
> +  using namespace std::placeholders;
> +  stack.scan (std::bind (check_for_saved, prologue, _1, _2, _3));

For readability, I would be inclined to use lambdas for these.  For performance,
I have read that lambdas were preferable to std::bind, in that they were always
at least as efficient, often more.  But I don't know about that specific case,
since we go through a function_view.  If we put the scan method in the header,
then we could use a template parameter for the callback type instead of
gdb::function_vew.  I think that would be the most efficient, since it would
allow the compiler to optimize through the callback, as the whole call chain
would be known at compile-time.

It would be interesting if somebody with more C++-fu looked at it.

Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFA 3/3] Use gdb::function_view in pv_area
  2017-10-09  4:06   ` Simon Marchi
@ 2017-10-09 15:10     ` Tom Tromey
  2017-10-12 21:35       ` Tom Tromey
  0 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2017-10-09 15:10 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

>> +  stack.scan (std::bind (check_for_saved, prologue, _1, _2, _3));

Simon> For readability, I would be inclined to use lambdas for these.

FWIW I tried that first, and I thought it was uglier:

    stack.scan ([=] (pv_t addr, CORE_ADDR size, pv_t value)
                {
                  check_for_saved (prologue, addr, size, value);
                });

I can do it if you want though.

Simon> For performance, I have read that lambdas were preferable to
Simon> std::bind, in that they were always at least as efficient, often
Simon> more.

Does that matter here?

Simon> If we put the scan method in the header,
Simon> then we could use a template parameter for the callback type instead of
Simon> gdb::function_vew.  I think that would be the most efficient, since it would
Simon> allow the compiler to optimize through the callback, as the whole call chain
Simon> would be known at compile-time.

Then we'd be back to passing through the user-data.  I suppose it's ok though.
Just let me know which one you want.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFA 1/3] C++-ify prologue-value's pv_area
  2017-10-09  3:04   ` Simon Marchi
@ 2017-10-12 21:33     ` Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2017-10-12 21:33 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

Simon> On top of methods, I think there should be
Simon>   /* See prologue-value.h.  */
Simon> like for regular functions.

I made this change.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFA 3/3] Use gdb::function_view in pv_area
  2017-10-09 15:10     ` Tom Tromey
@ 2017-10-12 21:35       ` Tom Tromey
  0 siblings, 0 replies; 10+ messages in thread
From: Tom Tromey @ 2017-10-12 21:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Simon Marchi, gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> Just let me know which one you want.

I'm going to push patches 1 and 2 now; patch 3 is independent anyway.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-10-12 21:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-08 17:08 [RFA 0/3] C++-ify pv_area Tom Tromey
2017-10-08 17:07 ` [RFA 3/3] Use gdb::function_view in pv_area Tom Tromey
2017-10-09  4:06   ` Simon Marchi
2017-10-09 15:10     ` Tom Tromey
2017-10-12 21:35       ` Tom Tromey
2017-10-08 17:08 ` [RFA 1/3] C++-ify prologue-value's pv_area Tom Tromey
2017-10-09  3:04   ` Simon Marchi
2017-10-12 21:33     ` Tom Tromey
2017-10-08 17:08 ` [RFA 2/3] Use bool in pv_area Tom Tromey
2017-10-09  3:12   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).