* [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).