[RFA,3/3] Use gdb::function_view in pv_area

Message ID 20171008170741.23151-4-tom@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey Oct. 8, 2017, 5:07 p.m. UTC
  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(-)
  

Comments

Simon Marchi Oct. 9, 2017, 4:06 a.m. UTC | #1
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>
>  
>  
>  /* 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
  
Tom Tromey Oct. 9, 2017, 3:10 p.m. UTC | #2
>>>>> "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
  
Tom Tromey Oct. 12, 2017, 9:35 p.m. UTC | #3
>>>>> "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
  

Patch

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>
 
 
 /* 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;
 }