* valops.c (value_fetch_lazy): Handle bitfields explicitly.
	(value_assign): Remove unnecessary FIXME.  Honor the container
	type of bitfields if possible.
	* value.c (struct value): Add parent field.
	(value_parent): New function.
	(value_free): Free the parent also.
	(value_copy): Copy the parent also.
	(value_primitive_field): Do not read the contents of a lazy
	value to create a child bitfield value.  Set bitpos and offset
	according to the container type if possible.
	(unpack_bits_as_long): Rename from unpack_field_as_long.  Take
	field_type, bitpos, and bitsize instead of type and fieldno.
	(unpack_field_as_long): Use unpack_bits_as_long.
	* value.h (value_parent, unpack_bits_as_long): New prototypes.
This commit is contained in:
Daniel Jacobowitz
2009-07-21 18:15:32 +00:00
parent 828d3400fb
commit 4ea48cc1cd
4 changed files with 114 additions and 20 deletions

View File

@@ -632,7 +632,25 @@ value_fetch_lazy (struct value *val)
{
gdb_assert (value_lazy (val));
allocate_value_contents (val);
if (VALUE_LVAL (val) == lval_memory)
if (value_bitsize (val))
{
/* To read a lazy bitfield, read the entire enclosing value. This
prevents reading the same block of (possibly volatile) memory once
per bitfield. It would be even better to read only the containing
word, but we have no way to record that just specific bits of a
value have been fetched. */
struct type *type = check_typedef (value_type (val));
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
struct value *parent = value_parent (val);
LONGEST offset = value_offset (val);
LONGEST num = unpack_bits_as_long (value_type (val),
value_contents (parent) + offset,
value_bitpos (val),
value_bitsize (val));
int length = TYPE_LENGTH (type);
store_signed_integer (value_contents_raw (val), length, byte_order, num);
}
else if (VALUE_LVAL (val) == lval_memory)
{
CORE_ADDR addr = value_address (val);
int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val)));
@@ -800,13 +818,20 @@ value_assign (struct value *toval, struct value *fromval)
if (value_bitsize (toval))
{
/* We assume that the argument to read_memory is in units
of host chars. FIXME: Is that correct? */
changed_len = (value_bitpos (toval)
+ value_bitsize (toval)
+ HOST_CHAR_BIT - 1)
/ HOST_CHAR_BIT;
/* If we can read-modify-write exactly the size of the
containing type (e.g. short or int) then do so. This
is safer for volatile bitfields mapped to hardware
registers. */
if (changed_len < TYPE_LENGTH (type)
&& TYPE_LENGTH (type) <= (int) sizeof (LONGEST)
&& ((LONGEST) value_address (toval) % TYPE_LENGTH (type)) == 0)
changed_len = TYPE_LENGTH (type);
if (changed_len > (int) sizeof (LONGEST))
error (_("Can't handle bitfields which don't fit in a %d bit word."),
(int) sizeof (LONGEST) * HOST_CHAR_BIT);