From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mark Kettenis To: ac131313@cygnus.com, gdb-patches@sources.redhat.com Subject: [RFC] Restructure doublest.c a bit Date: Sun, 28 Oct 2001 04:39:00 -0000 Message-id: <200110281239.f9SCdOk08291@delius.kettenis.local> X-SW-Source: 2001-10/msg00343.html Here's a patch that restructures doublest.c a bit. It moves the logic to determine the floating-point format from the length of a floating-point variable into a special function. It also turns the error that would occur when the floating-point format could not be guessed into a warning, and tries to return a NaN in that case. Andrew, what do you think? I'd like to check this in such that I can make changes that will change the type of the i387 floating-point registers to i386_ext. Mark Index: ChangeLog from Mark Kettenis * doublest.c: Improve comments a bit. (floatformat_from_length): New function. (NAN): Define to 0.0 if not already defined. (extract_floating): Rewrite to use floatformat_from_length. Warn instead of error if LEN doesn't match a known floating-point type, and return NaN (or 0.0 if NaN isn't available) in that case. (store_floating): Likewise, but zero out the target byte-stream if LEN doesn't match a known floating-point type. (extract_typed_floating): Reformat a bit. (store_typed_floating): Reformat a bit. Add comment about zeroing out padding in the target buffer. * doublest.h (extract_floating, store_floating): Fix comment about deprecation of these functions. Add parameter names to prototypes. Index: doublest.c =================================================================== RCS file: /cvs/src/src/gdb/doublest.c,v retrieving revision 1.4 diff -u -p -r1.4 doublest.c --- doublest.c 2001/09/24 17:16:53 1.4 +++ doublest.c 2001/10/28 12:33:26 @@ -532,7 +532,6 @@ floatformat_mantissa (const struct float return res; } - /* Convert TO/FROM target to the hosts DOUBLEST floating-point format. @@ -607,84 +606,108 @@ floatformat_from_doublest (const struct } -/* Extract/store a target floating-point number from byte-stream at - ADDR to/from a DOUBLEST. The LEN is used to select between the - pre-defined target type FLOAT, DOUBLE or LONG_DOUBLE. These - functions are used when extract/store typed floating() find that - the ``struct type'' did not include a FLOATFORMAT (e.g. some symbol - table readers and XXX-language support modules). */ +/* Return a floating-point format for a floating-point variable of + length LEN. Return NULL, if no suitable floating-point format + could be found. + + We need this functionality since information about the + floating-point format of a type is not always available to GDB; the + debug information typically only tells us the size of a + floating-point type. + + FIXME: kettenis/2001-10-28: In many places, particularly in + target-dependent code, the format of floating-point types is known, + but not passed on by GDB. This should be fixed. */ -DOUBLEST -extract_floating (const void *addr, int len) +static const struct floatformat * +floatformat_from_length (int len) { - DOUBLEST dretval; if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT) - { - floatformat_to_doublest (TARGET_FLOAT_FORMAT, addr, &dretval); - } + return TARGET_FLOAT_FORMAT; else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT) - { - floatformat_to_doublest (TARGET_DOUBLE_FORMAT, addr, &dretval); - } + return TARGET_DOUBLE_FORMAT; else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT) - { - floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, &dretval); - } - else + return TARGET_LONG_DOUBLE_FORMAT; + + return NULL; +} + +/* If the host doesn't define NAN, use zero instead. */ +#ifndef NAN +#define NAN 0.0 +#endif + +/* Extract a floating-point number of length LEN from a target-order + byte-stream at ADDR. Returns the value as type DOUBLEST. */ + +DOUBLEST +extract_floating (const void *addr, int len) +{ + const struct floatformat *fmt = floatformat_from_length (len); + DOUBLEST val; + + if (fmt == NULL) { - error ("Can't deal with a floating point number of %d bytes.", len); + warning ("Can't store a floating-point number of %d bytes.", len); + return NAN; } - return dretval; + + floatformat_to_doublest (fmt, addr, &val); + return val; } +/* Store VAL as a floating-point number of length LEN to a + target-order byte-stream at ADDR. */ + void store_floating (void *addr, int len, DOUBLEST val) { - if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT) - { - floatformat_from_doublest (TARGET_FLOAT_FORMAT, &val, addr); - } - else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT) - { - floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr); - } - else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT) - { - floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr); - } - else + const struct floatformat *fmt = floatformat_from_length (len); + + if (fmt == NULL) { - error ("Can't deal with a floating point number of %d bytes.", len); + warning ("Can't store a floating-point number of %d bytes.", len); + memset (addr, 0, len); } + + floatformat_from_doublest (fmt, &val, addr); } -/* Extract/store a floating-point number of format TYPE from a - target-ordered byte-stream at ADDR to/from an internal DOUBLEST - accroding to its TYPE_FORMAT(). When GDB reads in debug - information, it is sometimes only provided with the type name, its - length and the fact that it is a float (TYPE_FORMAT() is not set). - For such types, the old extract/store floating() functions are - used. */ +/* Extract a floating-point number of type TYPE from a target-order + byte-stream at ADDR. Returns the value as type DOUBLEST. */ DOUBLEST extract_typed_floating (const void *addr, const struct type *type) { DOUBLEST retval; + gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); + if (TYPE_FLOATFORMAT (type) == NULL) - retval = extract_floating (addr, TYPE_LENGTH (type)); - else - floatformat_to_doublest (TYPE_FLOATFORMAT (type), addr, &retval); + return extract_floating (addr, TYPE_LENGTH (type)); + + floatformat_to_doublest (TYPE_FLOATFORMAT (type), addr, &retval); return retval; } +/* Store VAL as a floating-point number of type TYPE to a target-order + byte-stream at ADDR. */ + void store_typed_floating (void *addr, const struct type *type, DOUBLEST val) { gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); + + /* FIXME: kettenis/2001-10-06: It is debatable whether we should + zero out any remaining bytes in the target buffer when TYPE is + longer than the actual underlying floating-point format. Perhaps + we should store a fixed bitpattern in those remaining bytes, + instead of zero, or perhaps we shouldn't touch those remaining + bytes at all. */ memset (addr, 0, TYPE_LENGTH (type)); + if (TYPE_FLOATFORMAT (type) == NULL) - store_floating (addr, TYPE_LENGTH (type), val); - else - floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr); + return store_floating (addr, TYPE_LENGTH (type), val); + + floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr); } Index: doublest.h =================================================================== RCS file: /cvs/src/src/gdb/doublest.h,v retrieving revision 1.5 diff -u -p -r1.5 doublest.h --- doublest.h 2001/09/24 17:16:53 1.5 +++ doublest.h 2001/10/28 12:33:26 @@ -61,9 +61,12 @@ extern int floatformat_is_negative (cons extern int floatformat_is_nan (const struct floatformat *, char *); extern char *floatformat_mantissa (const struct floatformat *, char *); -/* Use extract_typed_float() and store_typed_float(). */ -extern DOUBLEST extract_floating (const void *in, int); /* DEPRECATED */ -extern void store_floating (void *, int, DOUBLEST); /* DEPRECATED */ +/* These two functions are deprecated in favour of + extract_typed_floating and store_typed_floating. See comments in + 'doublest.c' for details. */ + +extern DOUBLEST extract_floating (const void *addr, int len); +extern void store_floating (void *addr, int len, DOUBLEST val); extern DOUBLEST extract_typed_floating (const void *addr, const struct type *type);