--- gdb/value.c (/patches/gdb/value_primitive_field/gdb_mainline) (revision 3210) +++ gdb/value.c (/patches/gdb/lazy_bitfields/gdb_mainline) (revision 3210) @@ -63,6 +63,10 @@ struct value struct internalvar *internalvar; } location; + /* For bitfields, this gives the index of + the field inside parent. */ + int fieldno; + /* Describes offset of a value within lval of a structure in bytes. If lval == lval_memory, this is an offset to the address. If lval == lval_register, this is a further offset from @@ -129,6 +133,18 @@ struct value int embedded_offset; int pointed_to_offset; + /* Pointer to parent variable. This pointer is + set only when a value needs access to the value of the + parent, for example for bitfields. */ + struct value *parent; + + /* The number of references for this value. This counts + all references via the 'parent' pointer, and either + 0 or 1 depending on whether there's reference to this + value from other gdb code. References from that 'other code' + are managed using explicit calls to value_free and release_value. */ + int reference_count; + /* Values are stored in a chain, so that they can be deleted easily over calls to the inferior. Values assigned to internal variables or put into the value history are taken off this @@ -233,6 +249,8 @@ allocate_value (struct type *type) val->embedded_offset = 0; val->pointed_to_offset = 0; val->modifiable = 1; + val->parent = NULL; + val->reference_count = 1; return val; } @@ -432,6 +450,16 @@ deprecated_value_internalvar_hack (struc return &value->location.internalvar; } +extern struct value *value_parent (struct value *value) +{ + return value->parent; +} + +extern int value_fieldno (struct value *value) +{ + return value->fieldno; +} + struct frame_id * deprecated_value_frame_id_hack (struct value *value) { @@ -540,6 +568,17 @@ value_release_to_mark (struct value *mar return val; } +extern void value_free (struct value *value) +{ + /* If there's a parent, drop parents's reference count + and free it if necessary. */ + if (value->parent) + value_free (value->parent); + + if (--value->reference_count == 0) + xfree (value); +} + /* Return a copy of the value ARG. It contains the same contents, for same memory address, but it's a different block of storage. */ @@ -562,6 +601,11 @@ value_copy (struct value *arg) val->embedded_offset = value_embedded_offset (arg); val->pointed_to_offset = arg->pointed_to_offset; val->modifiable = arg->modifiable; + val->fieldno = arg->fieldno; + val->parent = arg->parent; + if (val->parent) + ++val->parent->reference_count; + val->reference_count = 1; if (!value_lazy (val)) { memcpy (value_contents_all_raw (val), value_contents_all_raw (arg), @@ -1300,15 +1344,23 @@ value_primitive_field (struct value *arg if (TYPE_FIELD_BITSIZE (arg_type, fieldno)) { - v = value_from_longest (type, - unpack_field_as_long (arg_type, - value_contents (arg1) - + offset, - fieldno)); + LONGEST num; + int len; + + + v = allocate_value (type); v->bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8; v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno); v->offset = value_offset (arg1) + offset + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; + v->parent = arg1; + v->lval = lval_bitfield; + v->fieldno = fieldno; + + if (!value_lazy (arg1)) + value_fetch_lazy (v); + else + set_value_lazy (v, 1); } else if (fieldno < TYPE_N_BASECLASSES (arg_type)) { @@ -1340,7 +1392,9 @@ value_primitive_field (struct value *arg v->offset = (value_offset (arg1) + offset + value_embedded_offset (arg1)); } - VALUE_LVAL (v) = VALUE_LVAL (arg1); + + if (v->lval == not_lval) + VALUE_LVAL (v) = VALUE_LVAL (arg1); if (VALUE_LVAL (arg1) == lval_internalvar) VALUE_LVAL (v) = lval_internalvar_component; v->location = arg1->location; --- gdb/value.h (/patches/gdb/value_primitive_field/gdb_mainline) (revision 3210) +++ gdb/value.h (/patches/gdb/lazy_bitfields/gdb_mainline) (revision 3210) @@ -211,6 +211,10 @@ extern CORE_ADDR *deprecated_value_addre extern struct internalvar **deprecated_value_internalvar_hack (struct value *); #define VALUE_INTERNALVAR(val) (*deprecated_value_internalvar_hack (val)) +extern struct value *value_parent (struct value *v); + +extern int value_fieldno (struct value *v); + /* Frame register value is relative to. This will be described in the lval enum above as "lval_register". */ extern struct frame_id *deprecated_value_frame_id_hack (struct value *); @@ -458,7 +462,7 @@ extern int unop_user_defined_p (enum exp extern int destructor_name_p (const char *name, const struct type *type); -#define value_free(val) xfree (val) +extern void value_free (struct value *value); extern void free_all_values (void); --- gdb/valops.c (/patches/gdb/value_primitive_field/gdb_mainline) (revision 3210) +++ gdb/valops.c (/patches/gdb/lazy_bitfields/gdb_mainline) (revision 3210) @@ -541,13 +541,30 @@ value_at_lazy (struct type *type, CORE_A int value_fetch_lazy (struct value *val) { - CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (val); - int length = TYPE_LENGTH (value_enclosing_type (val)); - struct type *type = value_type (val); - if (length) - read_memory (addr, value_contents_all_raw (val), length); + if (VALUE_LVAL (val) == lval_bitfield) + { + LONGEST num; + int len; + num = unpack_field_as_long (value_type (value_parent (val)), + value_contents (value_parent (val)), + value_fieldno (val)); + + type = check_typedef (type); + len = TYPE_LENGTH (type); + + store_signed_integer (value_contents_raw (val), len, num); + } + else + { + CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (val); + int length = TYPE_LENGTH (value_enclosing_type (val)); + + if (length) + read_memory (addr, value_contents_all_raw (val), length); + } + set_value_lazy (val, 0); return 0; } @@ -600,37 +617,15 @@ value_assign (struct value *toval, struc case lval_memory: { + int changed_len; const gdb_byte *dest_buffer; CORE_ADDR changed_addr; - int changed_len; gdb_byte buffer[sizeof (LONGEST)]; - 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 (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); - - read_memory (VALUE_ADDRESS (toval) + value_offset (toval), - buffer, changed_len); - modify_field (buffer, value_as_long (fromval), - value_bitpos (toval), value_bitsize (toval)); - changed_addr = VALUE_ADDRESS (toval) + value_offset (toval); - dest_buffer = buffer; - } - else - { - changed_addr = VALUE_ADDRESS (toval) + value_offset (toval); - changed_len = TYPE_LENGTH (type); - dest_buffer = value_contents (fromval); - } + gdb_assert (!value_bitsize (toval)); + changed_addr = VALUE_ADDRESS (toval) + value_offset (toval); + changed_len = TYPE_LENGTH (type); + dest_buffer = value_contents (fromval); write_memory (changed_addr, dest_buffer, changed_len); if (deprecated_memory_changed_hook) @@ -659,38 +654,11 @@ value_assign (struct value *toval, struc } else { - if (value_bitsize (toval)) - { - int changed_len; - gdb_byte buffer[sizeof (LONGEST)]; - - changed_len = (value_bitpos (toval) - + value_bitsize (toval) - + HOST_CHAR_BIT - 1) - / HOST_CHAR_BIT; - - 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); - - get_frame_register_bytes (frame, value_reg, - value_offset (toval), - changed_len, buffer); - - modify_field (buffer, value_as_long (fromval), - value_bitpos (toval), value_bitsize (toval)); - - put_frame_register_bytes (frame, value_reg, - value_offset (toval), - changed_len, buffer); - } - else - { - put_frame_register_bytes (frame, value_reg, - value_offset (toval), - TYPE_LENGTH (type), - value_contents (fromval)); - } + gdb_assert (!value_bitsize (toval)); + put_frame_register_bytes (frame, value_reg, + value_offset (toval), + TYPE_LENGTH (type), + value_contents (fromval)); } if (deprecated_register_changed_hook) @@ -698,6 +666,43 @@ value_assign (struct value *toval, struc observer_notify_target_changed (¤t_target); break; } + + case lval_bitfield: + { + int changed_len; + gdb_byte *content; + + /* 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 (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); + + content = value_contents_writeable (value_parent (toval)) + + value_offset (toval); + modify_field (content, value_as_long (fromval), + value_bitpos (toval), value_bitsize (toval)); + + if (VALUE_LVAL (value_parent (toval)) == lval_register) + { + struct frame_info *frame = + frame_find_by_id (VALUE_FRAME_ID (toval)); + put_frame_register_bytes (frame, VALUE_REGNUM (toval), + value_offset (toval), + changed_len, content); + } + else + write_memory (VALUE_ADDRESS (value_parent (toval)) + + value_offset (toval), + content, changed_len); + + break; + } default: error (_("Left operand of assignment is not an lvalue.")); --- gdb/defs.h (/patches/gdb/value_primitive_field/gdb_mainline) (revision 3210) +++ gdb/defs.h (/patches/gdb/lazy_bitfields/gdb_mainline) (revision 3210) @@ -671,7 +671,9 @@ enum lval_type /* In a gdb internal variable. */ lval_internalvar, /* Part of a gdb internal variable (structure field). */ - lval_internalvar_component + lval_internalvar_component, + /* Bitfield of a structure. */ + lval_bitfield }; /* Control types for commands */ Property changes on: ___________________________________________________________________ Name: csl:base +/all/patches/gdb/value_primitive_field/gdb_mainline Name: svk:merge +d48a11ec-ee1c-0410-b3f5-c20844f99675:/work/gdb/gdb_mainline:2531 +e7755896-6108-0410-9592-8049d3e74e28:/mirrors/gdb/trunk:160955