* [RFC] LONGEST and ULONGEST function template instantiation
@ 2017-06-13 11:29 Yao Qi
2017-06-13 11:33 ` Yao Qi
2017-06-14 16:12 ` Pedro Alves
0 siblings, 2 replies; 7+ messages in thread
From: Yao Qi @ 2017-06-13 11:29 UTC (permalink / raw)
To: gdb-patches
This patch converts functions extract_{unsigned,signed}_integer
to a function template extract_integer, which has two instantiations. It
also does the similar changes to store__{unsigned,signed}_integer,
regcache::raw_read_{unsigned,signed}, regcache::raw_write_{unsigned,signed},
regcache::cooked_read_{unsigned,signed},
regcache::cooked_write_{unsigned,signed}. It is an RFC, because I
am not sure people like it or hate it :)
This patch was posted here
https://sourceware.org/ml/gdb-patches/2017-05/msg00492.html but the
problem was fixed in a different way. However, I think the patch is still
useful to shorten the code.
The patch increase the binary code size (measured on x86_64-linux), from
$ size ./gdb
text data bss dec hex filename
23856767 2395936 364616 26617319 19625e7 ./gdb
to
$ size ./gdb
text data bss dec hex filename
23858667 2395936 364616 26619219 1962d53 ./gdb
The patch is tested on x86_64-linux.
gdb:
2017-06-13 Alan Hayward <alan.hayward@arm.com>
Yao Qi <yao.qi@linaro.org>
* defs.h (LongType): New alias.
(extract_signed_integer): Remove declaration.
(extract_unsigned_integer): Likewise.
(extract_integer): New function template.
(extract_unsigned_integer): New macro.
(extract_signed_integer): New macro.
(store_integer): New function template.
(store_signed_integer): New macro.
(store_unsigned_integer): New macro.
* findvar.c (extract_signed_integer): Remove.
(extract_unsigned_integer): Remove.
(store_signed_integer): Remove.
(store_unsigned_integer): Remove.
* regcache.c (regcache_raw_read_signed): Update.
(regcache::raw_read_signed): Remove.
(regcache::raw_read): New function.
(regcache::raw_read_unsigned): Remove.
(regcache_raw_read_unsigned): Update.
(regcache_raw_write_unsigned): Update.
(regcache::raw_write_signed): Remove.
(regcache::raw_write): New function.
(regcache_cooked_read_signed): Update.
(regcache::raw_write_unsigned): Remove.
(regcache::cooked_read_signed): Remove.
(regcache_cooked_read_unsigned): Update.
(regcache::cooked_read_unsigned): Remove.
(regcache_cooked_write_signed): Update.
(regcache_cooked_write_unsigned): Update.
* regcache.h (regcache) <raw_read_signed>: Remove.
<raw_write_signed, raw_read_unsigned, raw_write_unsigned>: Remove.
<raw_read, raw_write>: New.
<cooked_read_signed, cooked_write_signed>: Remove.
<cooked_write_unsigned, cooked_read_unsigned>: Remove.
<cooked_read, cooked_write>: New.
* sh64-tdep.c (sh64_pseudo_register_read): Update.
(sh64_pseudo_register_write): Update.
---
gdb/defs.h | 108 +++++++++++++++++++++++++++++++++++++++++++----
gdb/findvar.c | 127 +-------------------------------------------------------
gdb/regcache.c | 124 +++++++++++++++++-------------------------------------
gdb/regcache.h | 36 +++++++++-------
gdb/sh64-tdep.c | 12 +++---
5 files changed, 166 insertions(+), 241 deletions(-)
diff --git a/gdb/defs.h b/gdb/defs.h
index a1a97bb..5ef94f5 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -627,6 +627,11 @@ enum symbol_needs_kind
SYMBOL_NEEDS_FRAME
};
+template<typename T>
+using LongType = typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ T>::type;
+
/* Dynamic target-system-dependent parameters for GDB. */
#include "gdbarch.h"
@@ -637,11 +642,61 @@ enum { MAX_REGISTER_SIZE = 64 };
/* In findvar.c. */
-extern LONGEST extract_signed_integer (const gdb_byte *, int,
- enum bfd_endian);
+/* All 'extract' functions return a host-format integer from a target-format
+ integer at ADDR which is LEN bytes long. */
-extern ULONGEST extract_unsigned_integer (const gdb_byte *, int,
- enum bfd_endian);
+template<typename T>
+LongType<T>
+extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order)
+{
+ T retval = 0;
+ const unsigned char *p;
+ const unsigned char *startaddr = addr;
+ const unsigned char *endaddr = startaddr + len;
+
+ if (len > (int) sizeof (T))
+ error (_("\
+That operation is not available on integers of more than %d bytes."),
+ (int) sizeof (T));
+
+ /* Start at the most significant end of the integer, and work towards
+ the least significant. */
+ if (byte_order == BFD_ENDIAN_BIG)
+ {
+ p = startaddr;
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) * p ^ 0x80) - 0x80;
+ ++p;
+ }
+ for (; p < endaddr; ++p)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ p = endaddr - 1;
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) * p ^ 0x80) - 0x80;
+ --p;
+ }
+ for (; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+template ULONGEST extract_integer<ULONGEST>
+ (const gdb_byte *addr, int len, enum bfd_endian byte_order);
+
+template LONGEST extract_integer<LONGEST>
+ (const gdb_byte *addr, int len, enum bfd_endian byte_order);
+
+#define extract_unsigned_integer extract_integer<ULONGEST>
+
+#define extract_signed_integer extract_integer<LONGEST>
extern int extract_long_unsigned_integer (const gdb_byte *, int,
enum bfd_endian, LONGEST *);
@@ -649,11 +704,48 @@ extern int extract_long_unsigned_integer (const gdb_byte *, int,
extern CORE_ADDR extract_typed_address (const gdb_byte *buf,
struct type *type);
-extern void store_signed_integer (gdb_byte *, int,
- enum bfd_endian, LONGEST);
+/* All 'store' functions accept a host-format integer and store a
+ target-format integer at ADDR which is LEN bytes long. */
-extern void store_unsigned_integer (gdb_byte *, int,
- enum bfd_endian, ULONGEST);
+template<typename T>
+typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ void>::type
+store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+ T val)
+{
+ gdb_byte *p;
+ gdb_byte *startaddr = addr;
+ gdb_byte *endaddr = startaddr + len;
+
+ /* Start at the least significant end of the integer, and work towards
+ the most significant. */
+ if (byte_order == BFD_ENDIAN_BIG)
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+}
+
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order, ULONGEST val);
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order, LONGEST val);
+
+#define store_signed_integer store_integer<LONGEST>
+
+#define store_unsigned_integer store_integer<ULONGEST>
extern void store_typed_address (gdb_byte *buf, struct type *type,
CORE_ADDR addr);
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 6c18e25..4caf125 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -35,9 +35,7 @@
#include "dwarf2loc.h"
#include "selftest.h"
-/* Basic byte-swapping routines. All 'extract' functions return a
- host-format integer from a target-format integer at ADDR which is
- LEN bytes long. */
+/* Basic byte-swapping routines. */
#if TARGET_CHAR_BIT != 8 || HOST_CHAR_BIT != 8
/* 8 bit characters are a pretty safe assumption these days, so we
@@ -47,70 +45,6 @@
you lose
#endif
-LONGEST
-extract_signed_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
-{
- LONGEST retval;
- const unsigned char *p;
- const unsigned char *startaddr = addr;
- const unsigned char *endaddr = startaddr + len;
-
- if (len > (int) sizeof (LONGEST))
- error (_("\
-That operation is not available on integers of more than %d bytes."),
- (int) sizeof (LONGEST));
-
- /* Start at the most significant end of the integer, and work towards
- the least significant. */
- if (byte_order == BFD_ENDIAN_BIG)
- {
- p = startaddr;
- /* Do the sign extension once at the start. */
- retval = ((LONGEST) * p ^ 0x80) - 0x80;
- for (++p; p < endaddr; ++p)
- retval = (retval << 8) | *p;
- }
- else
- {
- p = endaddr - 1;
- /* Do the sign extension once at the start. */
- retval = ((LONGEST) * p ^ 0x80) - 0x80;
- for (--p; p >= startaddr; --p)
- retval = (retval << 8) | *p;
- }
- return retval;
-}
-
-ULONGEST
-extract_unsigned_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
-{
- ULONGEST retval;
- const unsigned char *p;
- const unsigned char *startaddr = addr;
- const unsigned char *endaddr = startaddr + len;
-
- if (len > (int) sizeof (ULONGEST))
- error (_("\
-That operation is not available on integers of more than %d bytes."),
- (int) sizeof (ULONGEST));
-
- /* Start at the most significant end of the integer, and work towards
- the least significant. */
- retval = 0;
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = startaddr; p < endaddr; ++p)
- retval = (retval << 8) | *p;
- }
- else
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- retval = (retval << 8) | *p;
- }
- return retval;
-}
/* Sometimes a long long unsigned integer can be extracted as a
LONGEST value. This is done so that we can print these values
@@ -178,65 +112,6 @@ extract_typed_address (const gdb_byte *buf, struct type *type)
return gdbarch_pointer_to_address (get_type_arch (type), type, buf);
}
-/* All 'store' functions accept a host-format integer and store a
- target-format integer at ADDR which is LEN bytes long. */
-
-void
-store_signed_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, LONGEST val)
-{
- gdb_byte *p;
- gdb_byte *startaddr = addr;
- gdb_byte *endaddr = startaddr + len;
-
- /* Start at the least significant end of the integer, and work towards
- the most significant. */
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
- else
- {
- for (p = startaddr; p < endaddr; ++p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
-}
-
-void
-store_unsigned_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, ULONGEST val)
-{
- unsigned char *p;
- unsigned char *startaddr = (unsigned char *) addr;
- unsigned char *endaddr = startaddr + len;
-
- /* Start at the least significant end of the integer, and work towards
- the most significant. */
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
- else
- {
- for (p = startaddr; p < endaddr; ++p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
-}
-
/* Store the address ADDR as a pointer of type TYPE at BUF, in target
form. */
void
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 43ea430..4ec33d4 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -662,11 +662,14 @@ enum register_status
regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->raw_read_signed (regnum, val);
+ return regcache->raw_read (regnum, val);
}
-enum register_status
-regcache::raw_read_signed (int regnum, LONGEST *val)
+template<typename T>
+typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ enum register_status>::type
+regcache::raw_read (int regnum, T *val)
{
gdb_byte *buf;
enum register_status status;
@@ -675,9 +678,9 @@ regcache::raw_read_signed (int regnum, LONGEST *val)
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = raw_read (regnum, buf);
if (status == REG_VALID)
- *val = extract_signed_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
+ *val = extract_integer<T> (buf,
+ m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch));
else
*val = 0;
return status;
@@ -688,44 +691,28 @@ regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
ULONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->raw_read_unsigned (regnum, val);
-}
-
-
-enum register_status
-regcache::raw_read_unsigned (int regnum, ULONGEST *val)
-{
- gdb_byte *buf;
- enum register_status status;
-
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- status = raw_read (regnum, buf);
- if (status == REG_VALID)
- *val = extract_unsigned_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
- else
- *val = 0;
- return status;
+ return regcache->raw_read (regnum, val);
}
void
regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->raw_write_signed (regnum, val);
+ regcache->raw_write (regnum, val);
}
-void
-regcache::raw_write_signed (int regnum, LONGEST val)
+template<typename T>
+typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ void>::type
+regcache::raw_write (int regnum, T val)
{
gdb_byte *buf;
gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_signed_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
+ store_integer (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch), val);
raw_write (regnum, buf);
}
@@ -734,19 +721,7 @@ regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
ULONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->raw_write_unsigned (regnum, val);
-}
-
-void
-regcache::raw_write_unsigned (int regnum, ULONGEST val)
-{
- gdb_byte *buf;
-
- gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_unsigned_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
- raw_write (regnum, buf);
+ regcache->raw_write (regnum, val);
}
LONGEST
@@ -857,11 +832,14 @@ regcache_cooked_read_signed (struct regcache *regcache, int regnum,
LONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->cooked_read_signed (regnum, val);
+ return regcache->cooked_read (regnum, val);
}
-enum register_status
-regcache::cooked_read_signed (int regnum, LONGEST *val)
+template<typename T>
+typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ enum register_status>::type
+regcache::cooked_read (int regnum, T *val)
{
enum register_status status;
gdb_byte *buf;
@@ -870,9 +848,8 @@ regcache::cooked_read_signed (int regnum, LONGEST *val)
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = cooked_read (regnum, buf);
if (status == REG_VALID)
- *val = extract_signed_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
+ *val = extract_integer<T>(buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch));
else
*val = 0;
return status;
@@ -883,25 +860,7 @@ regcache_cooked_read_unsigned (struct regcache *regcache, int regnum,
ULONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->cooked_read_unsigned (regnum, val);
-}
-
-enum register_status
-regcache::cooked_read_unsigned (int regnum, ULONGEST *val)
-{
- enum register_status status;
- gdb_byte *buf;
-
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- status = cooked_read (regnum, buf);
- if (status == REG_VALID)
- *val = extract_unsigned_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
- else
- *val = 0;
- return status;
+ return regcache->cooked_read (regnum, val);
}
void
@@ -909,18 +868,21 @@ regcache_cooked_write_signed (struct regcache *regcache, int regnum,
LONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->cooked_write_signed (regnum, val);
+ regcache->cooked_write (regnum, val);
}
-void
-regcache::cooked_write_signed (int regnum, LONGEST val)
+template<typename T>
+typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ void>::type
+regcache::cooked_write (int regnum, T val)
{
gdb_byte *buf;
gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_signed_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
+ store_integer (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch), val);
cooked_write (regnum, buf);
}
@@ -929,19 +891,7 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
ULONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->cooked_write_unsigned (regnum, val);
-}
-
-void
-regcache::cooked_write_unsigned (int regnum, ULONGEST val)
-{
- gdb_byte *buf;
-
- gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_unsigned_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
- cooked_write (regnum, buf);
+ regcache->cooked_write (regnum, val);
}
/* See regcache.h. */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 4cf27a0..9ba3cf8 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -282,23 +282,31 @@ public:
#endif
void raw_write (int regnum, const gdb_byte *buf);
- enum register_status raw_read_signed (int regnum, LONGEST *val);
-
- void raw_write_signed (int regnum, LONGEST val);
-
- enum register_status raw_read_unsigned (int regnum, ULONGEST *val);
-
- void raw_write_unsigned (int regnum, ULONGEST val);
+ template<typename T>
+ typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ enum register_status>::type
+ raw_read (int regnum, T *val);
+
+ template<typename T>
+ typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ void>::type
+ raw_write (int regnum, T val);
struct value *cooked_read_value (int regnum);
- enum register_status cooked_read_signed (int regnum, LONGEST *val);
-
- void cooked_write_signed (int regnum, LONGEST val);
-
- enum register_status cooked_read_unsigned (int regnum, ULONGEST *val);
-
- void cooked_write_unsigned (int regnum, ULONGEST val);
+ template<typename T>
+ typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ enum register_status>::type
+ cooked_read (int regnum, T *val);
+
+ template<typename T>
+ typename std::enable_if<(std::is_same<T, LONGEST>::value
+ || std::is_same<T, ULONGEST>::value),
+ void>::type
+ cooked_write (int regnum, T val);
void raw_update (int regnum);
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index dd18e9f..5aeb235 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -1665,11 +1665,11 @@ sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
*/
/* *INDENT-ON* */
/* Get FPSCR as an int. */
- status = regcache->raw_read_unsigned (fpscr_base_regnum, &fpscr_value);
+ status = regcache->raw_read (fpscr_base_regnum, &fpscr_value);
if (status != REG_VALID)
return status;
/* Get SR as an int. */
- status = regcache->raw_read_unsigned (sr_base_regnum, &sr_value);
+ status = regcache->raw_read (sr_base_regnum, &sr_value);
if (status != REG_VALID)
return status;
/* Build the new value. */
@@ -1847,15 +1847,15 @@ sh64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
fpscr_value = fpscr_c_value & fpscr_mask;
sr_value = (fpscr_value & sr_mask) >> 6;
- regcache->raw_read_unsigned (fpscr_base_regnum, &old_fpscr_value);
+ regcache->raw_read (fpscr_base_regnum, &old_fpscr_value);
old_fpscr_value &= 0xfffc0002;
fpscr_value |= old_fpscr_value;
- regcache->raw_write_unsigned (fpscr_base_regnum, fpscr_value);
+ regcache->raw_write (fpscr_base_regnum, fpscr_value);
- regcache->raw_read_unsigned (sr_base_regnum, &old_sr_value);
+ regcache->raw_read (sr_base_regnum, &old_sr_value);
old_sr_value &= 0xffff8fff;
sr_value |= old_sr_value;
- regcache->raw_write_unsigned (sr_base_regnum, sr_value);
+ regcache->raw_write (sr_base_regnum, sr_value);
}
else if (reg_nr == FPUL_C_REGNUM)
--
1.9.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] LONGEST and ULONGEST function template instantiation
2017-06-13 11:29 [RFC] LONGEST and ULONGEST function template instantiation Yao Qi
@ 2017-06-13 11:33 ` Yao Qi
2017-06-14 13:54 ` Alan Hayward
2017-06-14 16:12 ` Pedro Alves
1 sibling, 1 reply; 7+ messages in thread
From: Yao Qi @ 2017-06-13 11:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Alan Hayward
On Tue, Jun 13, 2017 at 12:29 PM, Yao Qi <qiyaoltc@gmail.com> wrote:
>
> This patch was posted here
> https://sourceware.org/ml/gdb-patches/2017-05/msg00492.html but the
> problem was fixed in a different way. However, I think the patch is still
> useful to shorten the code.
Add Alan to CC.
--
Yao (齐尧)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] LONGEST and ULONGEST function template instantiation
2017-06-13 11:33 ` Yao Qi
@ 2017-06-14 13:54 ` Alan Hayward
0 siblings, 0 replies; 7+ messages in thread
From: Alan Hayward @ 2017-06-14 13:54 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches, nd
> On 13 Jun 2017, at 12:33, Yao Qi <qiyaoltc@gmail.com> wrote:
>
> On Tue, Jun 13, 2017 at 12:29 PM, Yao Qi <qiyaoltc@gmail.com> wrote:
>
>>
>> This patch was posted here
>> https://sourceware.org/ml/gdb-patches/2017-05/msg00492.html but the
>> problem was fixed in a different way. However, I think the patch is still
>> useful to shorten the code.
>
> Add Alan to CC.
>
> It is an RFC, because I am not sure people like it or hate it :)
My only objection to this would be that “enable_if” is fairly confusing.
However, having said that, I think the end result is quite nice, and
calling the functions is very simple, so I withdraw my objection.
It would be nice if the header files could use “LongType” instead of
the longer “enable_if” block, however I remember when I tried this
myself and couldn’t find a way around it.
Alan.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] LONGEST and ULONGEST function template instantiation
2017-06-13 11:29 [RFC] LONGEST and ULONGEST function template instantiation Yao Qi
2017-06-13 11:33 ` Yao Qi
@ 2017-06-14 16:12 ` Pedro Alves
2017-06-15 11:59 ` Yao Qi
1 sibling, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2017-06-14 16:12 UTC (permalink / raw)
To: Yao Qi, Alan Hayward; +Cc: gdb-patches
On 06/13/2017 12:29 PM, Yao Qi wrote:
> This patch converts functions extract_{unsigned,signed}_integer
> to a function template extract_integer, which has two instantiations. It
> also does the similar changes to store__{unsigned,signed}_integer,
> regcache::raw_read_{unsigned,signed}, regcache::raw_write_{unsigned,signed},
> regcache::cooked_read_{unsigned,signed},
> regcache::cooked_write_{unsigned,signed}. It is an RFC, because I
> am not sure people like it or hate it :)
I like it, but I'd like it more with a few tweaks to the
implementation. :-) See patch below.
>
> This patch was posted here
> https://sourceware.org/ml/gdb-patches/2017-05/msg00492.html but the
> problem was fixed in a different way. However, I think the patch is still
> useful to shorten the code.
>
> The patch increase the binary code size (measured on x86_64-linux), from
>
> $ size ./gdb
> text data bss dec hex filename
> 23856767 2395936 364616 26617319 19625e7 ./gdb
>
> to
>
> $ size ./gdb
> text data bss dec hex filename
> 23858667 2395936 364616 26619219 1962d53 ./gdb
The version below has no impact on code size:
$ size gdb.before gdb.after
text data bss dec hex filename
7535236 125008 181184 7841428 77a694 gdb.before
7535236 125008 181184 7841428 77a694 gdb.after
Since the templates will ever only be instantiated with T=LONGEST
and T=ULONGEST, then there's no actual need to move the
templates' definitions to the header file.
Even if we wanted to move the functions to the header so that
their bodies can be inlined for performance (no idea whether it
really helps anything), I'd still think this is a useful
intermediate step, since it avoids both changing and moving the
function bodies at the same time.
> +
> +#define extract_unsigned_integer extract_integer<ULONGEST>
> +
> +#define extract_signed_integer extract_integer<LONGEST>
These can be static inline functions, instead of macros.
On 06/14/2017 02:54 PM, Alan Hayward wrote:
> My only objection to this would be that “enable_if” is fairly confusing.
> However, having said that, I think the end result is quite nice, and
> calling the functions is very simple, so I withdraw my objection.
>
> It would be nice if the header files could use “LongType” instead of
> the longer “enable_if” block, however I remember when I tried this
> myself and couldnÂ’t find a way around it.
>
In C++11 we have default template params, so we can use those for the
SFINAE magic instead of having to use a function's parameter of the
function's return type. Also, I think that using the "gdb::Requires"
helper makes the parameter's intention clearer.
From bce7ebe33950b5a2cd5343d9a678ad23f02ec625 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 14 Jun 2017 16:24:07 +0100
Subject: [PATCH] extract/store integer templates
---
gdb/defs.h | 47 +++++++++++++++++++-----
gdb/findvar.c | 105 ++++++++++++++++++------------------------------------
gdb/regcache.c | 108 +++++++++++++-------------------------------------------
gdb/regcache.h | 20 +++++------
gdb/sh64-tdep.c | 12 +++----
5 files changed, 113 insertions(+), 179 deletions(-)
diff --git a/gdb/defs.h b/gdb/defs.h
index a1a97bb..55d16d1 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -82,6 +82,11 @@ enum compile_i_scope_types
COMPILE_I_PRINT_VALUE_SCOPE,
};
+
+template<typename T>
+using RequireLongest = gdb::Requires<gdb::Or<std::is_same<T, LONGEST>,
+ std::is_same<T, ULONGEST>>>;
+
/* Just in case they're not defined in stdio.h. */
#ifndef SEEK_SET
@@ -637,11 +642,22 @@ enum { MAX_REGISTER_SIZE = 64 };
/* In findvar.c. */
-extern LONGEST extract_signed_integer (const gdb_byte *, int,
- enum bfd_endian);
+template<typename T, typename = RequireLongest<T>>
+T extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order);
-extern ULONGEST extract_unsigned_integer (const gdb_byte *, int,
- enum bfd_endian);
+static inline LONGEST
+extract_signed_integer (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order)
+{
+ return extract_integer<LONGEST> (addr, len, byte_order);
+}
+
+static inline ULONGEST
+extract_unsigned_integer (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order)
+{
+ return extract_integer<ULONGEST> (addr, len, byte_order);
+}
extern int extract_long_unsigned_integer (const gdb_byte *, int,
enum bfd_endian, LONGEST *);
@@ -649,11 +665,26 @@ extern int extract_long_unsigned_integer (const gdb_byte *, int,
extern CORE_ADDR extract_typed_address (const gdb_byte *buf,
struct type *type);
-extern void store_signed_integer (gdb_byte *, int,
- enum bfd_endian, LONGEST);
+/* All 'store' functions accept a host-format integer and store a
+ target-format integer at ADDR which is LEN bytes long. */
-extern void store_unsigned_integer (gdb_byte *, int,
- enum bfd_endian, ULONGEST);
+template<typename T, typename = RequireLongest<T>>
+extern void store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+ T val);
+
+static inline void
+store_signed_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order, LONGEST val)
+{
+ return store_integer (addr, len, byte_order, val);
+}
+
+static inline void
+store_unsigned_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order, ULONGEST val)
+{
+ return store_integer (addr, len, byte_order, val);
+}
extern void store_typed_address (gdb_byte *buf, struct type *type,
CORE_ADDR addr);
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 6c18e25..beb127e 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -47,70 +47,54 @@
you lose
#endif
-LONGEST
-extract_signed_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
+template<typename T, typename>
+T
+extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order)
{
- LONGEST retval;
+ T retval = 0;
const unsigned char *p;
const unsigned char *startaddr = addr;
const unsigned char *endaddr = startaddr + len;
- if (len > (int) sizeof (LONGEST))
+ if (len > (int) sizeof (T))
error (_("\
That operation is not available on integers of more than %d bytes."),
- (int) sizeof (LONGEST));
+ (int) sizeof (T));
/* Start at the most significant end of the integer, and work towards
the least significant. */
if (byte_order == BFD_ENDIAN_BIG)
{
p = startaddr;
- /* Do the sign extension once at the start. */
- retval = ((LONGEST) * p ^ 0x80) - 0x80;
- for (++p; p < endaddr; ++p)
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) * p ^ 0x80) - 0x80;
+ ++p;
+ }
+ for (; p < endaddr; ++p)
retval = (retval << 8) | *p;
}
else
{
p = endaddr - 1;
- /* Do the sign extension once at the start. */
- retval = ((LONGEST) * p ^ 0x80) - 0x80;
- for (--p; p >= startaddr; --p)
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) * p ^ 0x80) - 0x80;
+ --p;
+ }
+ for (; p >= startaddr; --p)
retval = (retval << 8) | *p;
}
return retval;
}
-ULONGEST
-extract_unsigned_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
-{
- ULONGEST retval;
- const unsigned char *p;
- const unsigned char *startaddr = addr;
- const unsigned char *endaddr = startaddr + len;
-
- if (len > (int) sizeof (ULONGEST))
- error (_("\
-That operation is not available on integers of more than %d bytes."),
- (int) sizeof (ULONGEST));
-
- /* Start at the most significant end of the integer, and work towards
- the least significant. */
- retval = 0;
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = startaddr; p < endaddr; ++p)
- retval = (retval << 8) | *p;
- }
- else
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- retval = (retval << 8) | *p;
- }
- return retval;
-}
+/* Explicit instantiations. */
+template LONGEST extract_integer<LONGEST> (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order);
+template ULONGEST extract_integer<ULONGEST> (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order);
/* Sometimes a long long unsigned integer can be extracted as a
LONGEST value. This is done so that we can print these values
@@ -180,10 +164,10 @@ extract_typed_address (const gdb_byte *buf, struct type *type)
/* All 'store' functions accept a host-format integer and store a
target-format integer at ADDR which is LEN bytes long. */
-
+template<typename T, typename>
void
-store_signed_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, LONGEST val)
+store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+ T val)
{
gdb_byte *p;
gdb_byte *startaddr = addr;
@@ -209,33 +193,14 @@ store_signed_integer (gdb_byte *addr, int len,
}
}
-void
-store_unsigned_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, ULONGEST val)
-{
- unsigned char *p;
- unsigned char *startaddr = (unsigned char *) addr;
- unsigned char *endaddr = startaddr + len;
+/* Explicit instantiations. */
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order,
+ LONGEST val);
- /* Start at the least significant end of the integer, and work towards
- the most significant. */
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
- else
- {
- for (p = startaddr; p < endaddr; ++p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
-}
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order,
+ ULONGEST val);
/* Store the address ADDR as a pointer of type TYPE at BUF, in target
form. */
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 46f4641..608717f 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -662,11 +662,12 @@ enum register_status
regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->raw_read_signed (regnum, val);
+ return regcache->raw_read (regnum, val);
}
+template<typename T, typename>
enum register_status
-regcache::raw_read_signed (int regnum, LONGEST *val)
+regcache::raw_read (int regnum, T *val)
{
gdb_byte *buf;
enum register_status status;
@@ -675,9 +676,9 @@ regcache::raw_read_signed (int regnum, LONGEST *val)
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = raw_read (regnum, buf);
if (status == REG_VALID)
- *val = extract_signed_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
+ *val = extract_integer<T> (buf,
+ m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch));
else
*val = 0;
return status;
@@ -688,44 +689,26 @@ regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
ULONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->raw_read_unsigned (regnum, val);
-}
-
-
-enum register_status
-regcache::raw_read_unsigned (int regnum, ULONGEST *val)
-{
- gdb_byte *buf;
- enum register_status status;
-
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- status = raw_read (regnum, buf);
- if (status == REG_VALID)
- *val = extract_unsigned_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
- else
- *val = 0;
- return status;
+ return regcache->raw_read (regnum, val);
}
void
regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->raw_write_signed (regnum, val);
+ regcache->raw_write (regnum, val);
}
+template<typename T, typename>
void
-regcache::raw_write_signed (int regnum, LONGEST val)
+regcache::raw_write (int regnum, T val)
{
gdb_byte *buf;
gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_signed_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
+ store_integer (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch), val);
raw_write (regnum, buf);
}
@@ -734,19 +717,7 @@ regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
ULONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->raw_write_unsigned (regnum, val);
-}
-
-void
-regcache::raw_write_unsigned (int regnum, ULONGEST val)
-{
- gdb_byte *buf;
-
- gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_unsigned_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
- raw_write (regnum, buf);
+ regcache->raw_write (regnum, val);
}
LONGEST
@@ -857,11 +828,12 @@ regcache_cooked_read_signed (struct regcache *regcache, int regnum,
LONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->cooked_read_signed (regnum, val);
+ return regcache->cooked_read (regnum, val);
}
+template<typename T, typename>
enum register_status
-regcache::cooked_read_signed (int regnum, LONGEST *val)
+regcache::cooked_read (int regnum, T *val)
{
enum register_status status;
gdb_byte *buf;
@@ -870,9 +842,8 @@ regcache::cooked_read_signed (int regnum, LONGEST *val)
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = cooked_read (regnum, buf);
if (status == REG_VALID)
- *val = extract_signed_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
+ *val = extract_integer<T> (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch));
else
*val = 0;
return status;
@@ -883,25 +854,7 @@ regcache_cooked_read_unsigned (struct regcache *regcache, int regnum,
ULONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->cooked_read_unsigned (regnum, val);
-}
-
-enum register_status
-regcache::cooked_read_unsigned (int regnum, ULONGEST *val)
-{
- enum register_status status;
- gdb_byte *buf;
-
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- status = cooked_read (regnum, buf);
- if (status == REG_VALID)
- *val = extract_unsigned_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
- else
- *val = 0;
- return status;
+ return regcache->cooked_read (regnum, val);
}
void
@@ -909,18 +862,19 @@ regcache_cooked_write_signed (struct regcache *regcache, int regnum,
LONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->cooked_write_signed (regnum, val);
+ regcache->cooked_write (regnum, val);
}
+template<typename T, typename>
void
-regcache::cooked_write_signed (int regnum, LONGEST val)
+regcache::cooked_write (int regnum, T val)
{
gdb_byte *buf;
gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_signed_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
+ store_integer (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch), val);
cooked_write (regnum, buf);
}
@@ -929,19 +883,7 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
ULONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->cooked_write_unsigned (regnum, val);
-}
-
-void
-regcache::cooked_write_unsigned (int regnum, ULONGEST val)
-{
- gdb_byte *buf;
-
- gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_unsigned_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
- cooked_write (regnum, buf);
+ regcache->cooked_write (regnum, val);
}
/* See regcache.h. */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 4cf27a0..3f3f823 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -282,23 +282,19 @@ public:
#endif
void raw_write (int regnum, const gdb_byte *buf);
- enum register_status raw_read_signed (int regnum, LONGEST *val);
+ template<typename T, typename = RequireLongest<T>>
+ enum register_status raw_read (int regnum, T *val);
- void raw_write_signed (int regnum, LONGEST val);
-
- enum register_status raw_read_unsigned (int regnum, ULONGEST *val);
-
- void raw_write_unsigned (int regnum, ULONGEST val);
+ template<typename T, typename = RequireLongest<T>>
+ void raw_write (int regnum, T val);
struct value *cooked_read_value (int regnum);
- enum register_status cooked_read_signed (int regnum, LONGEST *val);
-
- void cooked_write_signed (int regnum, LONGEST val);
-
- enum register_status cooked_read_unsigned (int regnum, ULONGEST *val);
+ template<typename T, typename = RequireLongest<T>>
+ enum register_status cooked_read (int regnum, T *val);
- void cooked_write_unsigned (int regnum, ULONGEST val);
+ template<typename T, typename = RequireLongest<T>>
+ void cooked_write (int regnum, T val);
void raw_update (int regnum);
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index 4eb8947..3273197 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -1665,11 +1665,11 @@ sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
*/
/* *INDENT-ON* */
/* Get FPSCR as an int. */
- status = regcache->raw_read_unsigned (fpscr_base_regnum, &fpscr_value);
+ status = regcache->raw_read (fpscr_base_regnum, &fpscr_value);
if (status != REG_VALID)
return status;
/* Get SR as an int. */
- status = regcache->raw_read_unsigned (sr_base_regnum, &sr_value);
+ status = regcache->raw_read (sr_base_regnum, &sr_value);
if (status != REG_VALID)
return status;
/* Build the new value. */
@@ -1847,15 +1847,15 @@ sh64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
fpscr_value = fpscr_c_value & fpscr_mask;
sr_value = (fpscr_value & sr_mask) >> 6;
- regcache->raw_read_unsigned (fpscr_base_regnum, &old_fpscr_value);
+ regcache->raw_read (fpscr_base_regnum, &old_fpscr_value);
old_fpscr_value &= 0xfffc0002;
fpscr_value |= old_fpscr_value;
- regcache->raw_write_unsigned (fpscr_base_regnum, fpscr_value);
+ regcache->raw_write (fpscr_base_regnum, fpscr_value);
- regcache->raw_read_unsigned (sr_base_regnum, &old_sr_value);
+ regcache->raw_read (sr_base_regnum, &old_sr_value);
old_sr_value &= 0xffff8fff;
sr_value |= old_sr_value;
- regcache->raw_write_unsigned (sr_base_regnum, sr_value);
+ regcache->raw_write (sr_base_regnum, sr_value);
}
else if (reg_nr == FPUL_C_REGNUM)
--
2.5.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] LONGEST and ULONGEST function template instantiation
2017-06-14 16:12 ` Pedro Alves
@ 2017-06-15 11:59 ` Yao Qi
2017-06-15 16:19 ` Pedro Alves
0 siblings, 1 reply; 7+ messages in thread
From: Yao Qi @ 2017-06-15 11:59 UTC (permalink / raw)
To: Pedro Alves; +Cc: Alan Hayward, gdb-patches
Pedro Alves <palves@redhat.com> writes:
Hi Pedro,
I pick up your patch, and update the ChangeLog entry.
> The version below has no impact on code size:
>
> $ size gdb.before gdb.after
> text data bss dec hex filename
> 7535236 125008 181184 7841428 77a694 gdb.before
> 7535236 125008 181184 7841428 77a694 gdb.after
I can't reproduce your result with gcc 5.4.0 on Ubuntu 16.04. The
patched GDB size increased by 112, but it doesn't matter.
before:
$ size ./gdb
text data bss dec hex filename
7733505 144208 180768 8058481 7af671 ./gdb
after:
$ size ./gdb
text data bss dec hex filename
7733617 144208 180768 8058593 7af6e1 ./gdb
--
Yao (齐尧)
From cb61b39bb2a35e6ac81dce31019e3dabbc111292 Mon Sep 17 00:00:00 2001
From: Yao Qi <yao.qi@linaro.org>
Date: Thu, 15 Jun 2017 11:06:58 +0100
Subject: [PATCH] extract/store integer function template
This patch converts functions extract_{unsigned,signed}_integer
to a function template extract_integer, which has two instantiations. It
also does the similar changes to store__{unsigned,signed}_integer,
regcache::raw_read_{unsigned,signed}, regcache::raw_write_{unsigned,signed},
regcache::cooked_read_{unsigned,signed},
regcache::cooked_write_{unsigned,signed}.
This patch was posted here
https://sourceware.org/ml/gdb-patches/2017-05/msg00492.html but the
problem was fixed in a different way. However, I think the patch is still
useful to shorten the code.
gdb:
2017-06-15 Alan Hayward <alan.hayward@arm.com>
Pedro Alves <palves@redhat.com>
Yao Qi <yao.qi@linaro.org>
* defs.h (RequireLongest): New.
(extract_integer): Declare function template.
(extract_signed_integer): Remove the declaration, but define it
static inline.
(extract_unsigned_integer): Likewise.
(store_integer): Declare function template.
(store_signed_integer): Remove the declaration, but define it
static inline.
(store_unsigned_integer): Likewise.
* findvar.c (extract_integer): New function template.
(extract_signed_integer): Remove.
(extract_unsigned_integer): Remove.
(extract_integer<LONGEST>, extract_integer<ULONGEST>): Explicit
instantiations.
(store_integer): New function template.
(store_signed_integer): Remove.
(store_unsigned_integer): Remove.
(store_integer): Explicit instantiations.
* regcache.c (regcache_raw_read_signed): Update.
(regcache::raw_read): New function.
(regcache::raw_read_signed): Remove.
(regcache::raw_read_unsigned): Remove.
(regcache_raw_read_unsigned): Update.
(regcache_raw_write_unsigned): Update.
(regcache::raw_write_signed): Remove.
(regcache::raw_write): New function.
(regcache_cooked_read_signed): Update.
(regcache::raw_write_unsigned): Remove.
(regcache::cooked_read_signed): Remove.
(regcache_cooked_read_unsigned): Update.
(regcache::cooked_read_unsigned): Remove.
(regcache_cooked_write_signed): Update.
(regcache_cooked_write_unsigned): Update.
* regcache.h (regcache) <raw_read_signed>: Remove.
<raw_write_signed, raw_read_unsigned, raw_write_unsigned>: Remove.
<raw_read, raw_write>: New.
<cooked_read_signed, cooked_write_signed>: Remove.
<cooked_write_unsigned, cooked_read_unsigned>: Remove.
<cooked_read, cooked_write>: New.
* sh64-tdep.c (sh64_pseudo_register_read): Update.
(sh64_pseudo_register_write): Update.
diff --git a/gdb/defs.h b/gdb/defs.h
index a1a97bb..55d16d1 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -82,6 +82,11 @@ enum compile_i_scope_types
COMPILE_I_PRINT_VALUE_SCOPE,
};
+
+template<typename T>
+using RequireLongest = gdb::Requires<gdb::Or<std::is_same<T, LONGEST>,
+ std::is_same<T, ULONGEST>>>;
+
/* Just in case they're not defined in stdio.h. */
#ifndef SEEK_SET
@@ -637,11 +642,22 @@ enum { MAX_REGISTER_SIZE = 64 };
/* In findvar.c. */
-extern LONGEST extract_signed_integer (const gdb_byte *, int,
- enum bfd_endian);
+template<typename T, typename = RequireLongest<T>>
+T extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order);
-extern ULONGEST extract_unsigned_integer (const gdb_byte *, int,
- enum bfd_endian);
+static inline LONGEST
+extract_signed_integer (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order)
+{
+ return extract_integer<LONGEST> (addr, len, byte_order);
+}
+
+static inline ULONGEST
+extract_unsigned_integer (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order)
+{
+ return extract_integer<ULONGEST> (addr, len, byte_order);
+}
extern int extract_long_unsigned_integer (const gdb_byte *, int,
enum bfd_endian, LONGEST *);
@@ -649,11 +665,26 @@ extern int extract_long_unsigned_integer (const gdb_byte *, int,
extern CORE_ADDR extract_typed_address (const gdb_byte *buf,
struct type *type);
-extern void store_signed_integer (gdb_byte *, int,
- enum bfd_endian, LONGEST);
+/* All 'store' functions accept a host-format integer and store a
+ target-format integer at ADDR which is LEN bytes long. */
-extern void store_unsigned_integer (gdb_byte *, int,
- enum bfd_endian, ULONGEST);
+template<typename T, typename = RequireLongest<T>>
+extern void store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+ T val);
+
+static inline void
+store_signed_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order, LONGEST val)
+{
+ return store_integer (addr, len, byte_order, val);
+}
+
+static inline void
+store_unsigned_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order, ULONGEST val)
+{
+ return store_integer (addr, len, byte_order, val);
+}
extern void store_typed_address (gdb_byte *buf, struct type *type,
CORE_ADDR addr);
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 6c18e25..beb127e 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -47,70 +47,54 @@
you lose
#endif
-LONGEST
-extract_signed_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
+template<typename T, typename>
+T
+extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order)
{
- LONGEST retval;
+ T retval = 0;
const unsigned char *p;
const unsigned char *startaddr = addr;
const unsigned char *endaddr = startaddr + len;
- if (len > (int) sizeof (LONGEST))
+ if (len > (int) sizeof (T))
error (_("\
That operation is not available on integers of more than %d bytes."),
- (int) sizeof (LONGEST));
+ (int) sizeof (T));
/* Start at the most significant end of the integer, and work towards
the least significant. */
if (byte_order == BFD_ENDIAN_BIG)
{
p = startaddr;
- /* Do the sign extension once at the start. */
- retval = ((LONGEST) * p ^ 0x80) - 0x80;
- for (++p; p < endaddr; ++p)
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) * p ^ 0x80) - 0x80;
+ ++p;
+ }
+ for (; p < endaddr; ++p)
retval = (retval << 8) | *p;
}
else
{
p = endaddr - 1;
- /* Do the sign extension once at the start. */
- retval = ((LONGEST) * p ^ 0x80) - 0x80;
- for (--p; p >= startaddr; --p)
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) * p ^ 0x80) - 0x80;
+ --p;
+ }
+ for (; p >= startaddr; --p)
retval = (retval << 8) | *p;
}
return retval;
}
-ULONGEST
-extract_unsigned_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
-{
- ULONGEST retval;
- const unsigned char *p;
- const unsigned char *startaddr = addr;
- const unsigned char *endaddr = startaddr + len;
-
- if (len > (int) sizeof (ULONGEST))
- error (_("\
-That operation is not available on integers of more than %d bytes."),
- (int) sizeof (ULONGEST));
-
- /* Start at the most significant end of the integer, and work towards
- the least significant. */
- retval = 0;
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = startaddr; p < endaddr; ++p)
- retval = (retval << 8) | *p;
- }
- else
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- retval = (retval << 8) | *p;
- }
- return retval;
-}
+/* Explicit instantiations. */
+template LONGEST extract_integer<LONGEST> (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order);
+template ULONGEST extract_integer<ULONGEST> (const gdb_byte *addr, int len,
+ enum bfd_endian byte_order);
/* Sometimes a long long unsigned integer can be extracted as a
LONGEST value. This is done so that we can print these values
@@ -180,10 +164,10 @@ extract_typed_address (const gdb_byte *buf, struct type *type)
/* All 'store' functions accept a host-format integer and store a
target-format integer at ADDR which is LEN bytes long. */
-
+template<typename T, typename>
void
-store_signed_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, LONGEST val)
+store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+ T val)
{
gdb_byte *p;
gdb_byte *startaddr = addr;
@@ -209,33 +193,14 @@ store_signed_integer (gdb_byte *addr, int len,
}
}
-void
-store_unsigned_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, ULONGEST val)
-{
- unsigned char *p;
- unsigned char *startaddr = (unsigned char *) addr;
- unsigned char *endaddr = startaddr + len;
+/* Explicit instantiations. */
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order,
+ LONGEST val);
- /* Start at the least significant end of the integer, and work towards
- the most significant. */
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
- else
- {
- for (p = startaddr; p < endaddr; ++p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
-}
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order,
+ ULONGEST val);
/* Store the address ADDR as a pointer of type TYPE at BUF, in target
form. */
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 43ea430..7eeb737 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -662,11 +662,12 @@ enum register_status
regcache_raw_read_signed (struct regcache *regcache, int regnum, LONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->raw_read_signed (regnum, val);
+ return regcache->raw_read (regnum, val);
}
+template<typename T, typename>
enum register_status
-regcache::raw_read_signed (int regnum, LONGEST *val)
+regcache::raw_read (int regnum, T *val)
{
gdb_byte *buf;
enum register_status status;
@@ -675,9 +676,9 @@ regcache::raw_read_signed (int regnum, LONGEST *val)
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = raw_read (regnum, buf);
if (status == REG_VALID)
- *val = extract_signed_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
+ *val = extract_integer<T> (buf,
+ m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch));
else
*val = 0;
return status;
@@ -688,44 +689,26 @@ regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
ULONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->raw_read_unsigned (regnum, val);
-}
-
-
-enum register_status
-regcache::raw_read_unsigned (int regnum, ULONGEST *val)
-{
- gdb_byte *buf;
- enum register_status status;
-
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- status = raw_read (regnum, buf);
- if (status == REG_VALID)
- *val = extract_unsigned_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
- else
- *val = 0;
- return status;
+ return regcache->raw_read (regnum, val);
}
void
regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->raw_write_signed (regnum, val);
+ regcache->raw_write (regnum, val);
}
+template<typename T, typename>
void
-regcache::raw_write_signed (int regnum, LONGEST val)
+regcache::raw_write (int regnum, T val)
{
gdb_byte *buf;
gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_signed_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
+ store_integer (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch), val);
raw_write (regnum, buf);
}
@@ -734,19 +717,7 @@ regcache_raw_write_unsigned (struct regcache *regcache, int regnum,
ULONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->raw_write_unsigned (regnum, val);
-}
-
-void
-regcache::raw_write_unsigned (int regnum, ULONGEST val)
-{
- gdb_byte *buf;
-
- gdb_assert (regnum >=0 && regnum < m_descr->nr_raw_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_unsigned_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
- raw_write (regnum, buf);
+ regcache->raw_write (regnum, val);
}
LONGEST
@@ -857,11 +828,12 @@ regcache_cooked_read_signed (struct regcache *regcache, int regnum,
LONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->cooked_read_signed (regnum, val);
+ return regcache->cooked_read (regnum, val);
}
+template<typename T, typename>
enum register_status
-regcache::cooked_read_signed (int regnum, LONGEST *val)
+regcache::cooked_read (int regnum, T *val)
{
enum register_status status;
gdb_byte *buf;
@@ -870,9 +842,8 @@ regcache::cooked_read_signed (int regnum, LONGEST *val)
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
status = cooked_read (regnum, buf);
if (status == REG_VALID)
- *val = extract_signed_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
+ *val = extract_integer<T> (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch));
else
*val = 0;
return status;
@@ -883,25 +854,7 @@ regcache_cooked_read_unsigned (struct regcache *regcache, int regnum,
ULONGEST *val)
{
gdb_assert (regcache != NULL);
- return regcache->cooked_read_unsigned (regnum, val);
-}
-
-enum register_status
-regcache::cooked_read_unsigned (int regnum, ULONGEST *val)
-{
- enum register_status status;
- gdb_byte *buf;
-
- gdb_assert (regnum >= 0 && regnum < m_descr->nr_cooked_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- status = cooked_read (regnum, buf);
- if (status == REG_VALID)
- *val = extract_unsigned_integer
- (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch));
- else
- *val = 0;
- return status;
+ return regcache->cooked_read (regnum, val);
}
void
@@ -909,18 +862,19 @@ regcache_cooked_write_signed (struct regcache *regcache, int regnum,
LONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->cooked_write_signed (regnum, val);
+ regcache->cooked_write (regnum, val);
}
+template<typename T, typename>
void
-regcache::cooked_write_signed (int regnum, LONGEST val)
+regcache::cooked_write (int regnum, T val)
{
gdb_byte *buf;
gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers);
buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_signed_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
+ store_integer (buf, m_descr->sizeof_register[regnum],
+ gdbarch_byte_order (m_descr->gdbarch), val);
cooked_write (regnum, buf);
}
@@ -929,19 +883,7 @@ regcache_cooked_write_unsigned (struct regcache *regcache, int regnum,
ULONGEST val)
{
gdb_assert (regcache != NULL);
- regcache->cooked_write_unsigned (regnum, val);
-}
-
-void
-regcache::cooked_write_unsigned (int regnum, ULONGEST val)
-{
- gdb_byte *buf;
-
- gdb_assert (regnum >=0 && regnum < m_descr->nr_cooked_registers);
- buf = (gdb_byte *) alloca (m_descr->sizeof_register[regnum]);
- store_unsigned_integer (buf, m_descr->sizeof_register[regnum],
- gdbarch_byte_order (m_descr->gdbarch), val);
- cooked_write (regnum, buf);
+ regcache->cooked_write (regnum, val);
}
/* See regcache.h. */
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 4cf27a0..3f3f823 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -282,23 +282,19 @@ public:
#endif
void raw_write (int regnum, const gdb_byte *buf);
- enum register_status raw_read_signed (int regnum, LONGEST *val);
+ template<typename T, typename = RequireLongest<T>>
+ enum register_status raw_read (int regnum, T *val);
- void raw_write_signed (int regnum, LONGEST val);
-
- enum register_status raw_read_unsigned (int regnum, ULONGEST *val);
-
- void raw_write_unsigned (int regnum, ULONGEST val);
+ template<typename T, typename = RequireLongest<T>>
+ void raw_write (int regnum, T val);
struct value *cooked_read_value (int regnum);
- enum register_status cooked_read_signed (int regnum, LONGEST *val);
-
- void cooked_write_signed (int regnum, LONGEST val);
-
- enum register_status cooked_read_unsigned (int regnum, ULONGEST *val);
+ template<typename T, typename = RequireLongest<T>>
+ enum register_status cooked_read (int regnum, T *val);
- void cooked_write_unsigned (int regnum, ULONGEST val);
+ template<typename T, typename = RequireLongest<T>>
+ void cooked_write (int regnum, T val);
void raw_update (int regnum);
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index dd18e9f..5aeb235 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -1665,11 +1665,11 @@ sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
*/
/* *INDENT-ON* */
/* Get FPSCR as an int. */
- status = regcache->raw_read_unsigned (fpscr_base_regnum, &fpscr_value);
+ status = regcache->raw_read (fpscr_base_regnum, &fpscr_value);
if (status != REG_VALID)
return status;
/* Get SR as an int. */
- status = regcache->raw_read_unsigned (sr_base_regnum, &sr_value);
+ status = regcache->raw_read (sr_base_regnum, &sr_value);
if (status != REG_VALID)
return status;
/* Build the new value. */
@@ -1847,15 +1847,15 @@ sh64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
fpscr_value = fpscr_c_value & fpscr_mask;
sr_value = (fpscr_value & sr_mask) >> 6;
- regcache->raw_read_unsigned (fpscr_base_regnum, &old_fpscr_value);
+ regcache->raw_read (fpscr_base_regnum, &old_fpscr_value);
old_fpscr_value &= 0xfffc0002;
fpscr_value |= old_fpscr_value;
- regcache->raw_write_unsigned (fpscr_base_regnum, fpscr_value);
+ regcache->raw_write (fpscr_base_regnum, fpscr_value);
- regcache->raw_read_unsigned (sr_base_regnum, &old_sr_value);
+ regcache->raw_read (sr_base_regnum, &old_sr_value);
old_sr_value &= 0xffff8fff;
sr_value |= old_sr_value;
- regcache->raw_write_unsigned (sr_base_regnum, sr_value);
+ regcache->raw_write (sr_base_regnum, sr_value);
}
else if (reg_nr == FPUL_C_REGNUM)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] LONGEST and ULONGEST function template instantiation
2017-06-15 11:59 ` Yao Qi
@ 2017-06-15 16:19 ` Pedro Alves
2017-06-16 14:46 ` Yao Qi
0 siblings, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2017-06-15 16:19 UTC (permalink / raw)
To: Yao Qi; +Cc: Alan Hayward, gdb-patches
On 06/15/2017 12:59 PM, Yao Qi wrote:
> Pedro Alves <palves@redhat.com> writes:
>
> Hi Pedro,
> I pick up your patch, and update the ChangeLog entry.
Thanks. FAOD, fine with me to push it in.
>> The version below has no impact on code size:
>>
>> $ size gdb.before gdb.after
>> text data bss dec hex filename
>> 7535236 125008 181184 7841428 77a694 gdb.before
>> 7535236 125008 181184 7841428 77a694 gdb.after
>
> I can't reproduce your result with gcc 5.4.0 on Ubuntu 16.04. The
> patched GDB size increased by 112, but it doesn't matter.
>
> before:
> $ size ./gdb
> text data bss dec hex filename
> 7733505 144208 180768 8058481 7af671 ./gdb
>
> after:
> $ size ./gdb
> text data bss dec hex filename
> 7733617 144208 180768 8058593 7af6e1 ./gdb
Curious, I see the same too now. Dunno what I did
before.
Diffing "size -A" (and stripping addr column) shows:
-gdb.before.stripped :
+gdb.after.stripped :
.rela.plt 16344
.init 26
.plt 10912
-.text 4239945
+.text 4239705
.fini 9
-.rodata 2280312
+.rodata 2280728
.stapsdt.base 1
-.eh_frame_hdr 126004
-.eh_frame 745124
+.eh_frame_hdr 125996
+.eh_frame 745084
So it results in less code after all. The increase is
in .rodata. Maybe the result of longer mangled names or
longer strings for __FUNCTION__.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] LONGEST and ULONGEST function template instantiation
2017-06-15 16:19 ` Pedro Alves
@ 2017-06-16 14:46 ` Yao Qi
0 siblings, 0 replies; 7+ messages in thread
From: Yao Qi @ 2017-06-16 14:46 UTC (permalink / raw)
To: Pedro Alves; +Cc: Alan Hayward, gdb-patches
On Thu, Jun 15, 2017 at 5:19 PM, Pedro Alves <palves@redhat.com> wrote:
> On 06/15/2017 12:59 PM, Yao Qi wrote:
>> Pedro Alves <palves@redhat.com> writes:
>>
>> Hi Pedro,
>> I pick up your patch, and update the ChangeLog entry.
>
> Thanks. FAOD, fine with me to push it in.
>
Patch is pushed in.
--
Yao (齐尧)
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-06-16 14:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-13 11:29 [RFC] LONGEST and ULONGEST function template instantiation Yao Qi
2017-06-13 11:33 ` Yao Qi
2017-06-14 13:54 ` Alan Hayward
2017-06-14 16:12 ` Pedro Alves
2017-06-15 11:59 ` Yao Qi
2017-06-15 16:19 ` Pedro Alves
2017-06-16 14:46 ` Yao Qi
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).