X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvalops.c;h=012ea6a4297541bd73cd8451af39c33b5c464ad7;hb=33b9c32b2647f4f59e7f0edb94572991aa8fef73;hp=1c724d3a56c0d42915b37c3afaefde2f2adf74b7;hpb=61212c0fb13d0a54f12748dcc56a41c15a91d12a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/valops.c b/gdb/valops.c index 1c724d3a56..012ea6a429 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -254,10 +254,8 @@ value_cast_structs (struct type *type, struct value *v2) if (v) { /* Downcasting is possible (t1 is superclass of v2). */ - CORE_ADDR addr2 = VALUE_ADDRESS (v2); - addr2 -= (VALUE_ADDRESS (v) - + value_offset (v) - + value_embedded_offset (v)); + CORE_ADDR addr2 = value_address (v2); + addr2 -= value_address (v) + value_embedded_offset (v); return value_at (type, addr2); } } @@ -424,17 +422,18 @@ value_cast (struct type *type, struct value *arg2) return value_from_double (type, value_as_double (arg2)); else if (code1 == TYPE_CODE_DECFLOAT && scalar) { + enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); int dec_len = TYPE_LENGTH (type); gdb_byte dec[16]; if (code2 == TYPE_CODE_FLT) - decimal_from_floating (arg2, dec, dec_len); + decimal_from_floating (arg2, dec, dec_len, byte_order); else if (code2 == TYPE_CODE_DECFLOAT) decimal_convert (value_contents (arg2), TYPE_LENGTH (type2), - dec, dec_len); + byte_order, dec, dec_len, byte_order); else /* The only option left is an integral type. */ - decimal_from_integral (arg2, dec, dec_len); + decimal_from_integral (arg2, dec, dec_len, byte_order); return value_from_decfloat (type, dec); } @@ -452,8 +451,9 @@ value_cast (struct type *type, struct value *arg2) sees a cast as a simple reinterpretation of the pointer's bits. */ if (code2 == TYPE_CODE_PTR) - longest = extract_unsigned_integer (value_contents (arg2), - TYPE_LENGTH (type2)); + longest = extract_unsigned_integer + (value_contents (arg2), TYPE_LENGTH (type2), + gdbarch_byte_order (get_type_arch (type2))); else longest = value_as_long (arg2); return value_from_longest (type, convert_to_boolean ? @@ -473,7 +473,7 @@ value_cast (struct type *type, struct value *arg2) otherwise occur when dealing with a target having two byte pointers and four byte addresses. */ - int addr_bit = gdbarch_addr_bit (current_gdbarch); + int addr_bit = gdbarch_addr_bit (get_type_arch (type2)); LONGEST longest = value_as_long (arg2); if (addr_bit < sizeof (LONGEST) * HOST_CHAR_BIT) @@ -510,11 +510,10 @@ value_cast (struct type *type, struct value *arg2) return arg2; } else if (VALUE_LVAL (arg2) == lval_memory) - return value_at_lazy (type, - VALUE_ADDRESS (arg2) + value_offset (arg2)); + return value_at_lazy (type, value_address (arg2)); else if (code1 == TYPE_CODE_VOID) { - return value_zero (builtin_type_void, not_lval); + return value_zero (type, not_lval); } else { @@ -540,15 +539,13 @@ struct value * value_one (struct type *type, enum lval_type lv) { struct type *type1 = check_typedef (type); - struct value *val = NULL; /* avoid -Wall warning */ + struct value *val; if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT) { - struct value *int_one = value_from_longest (builtin_type_int32, 1); - struct value *val; + enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); gdb_byte v[16]; - - decimal_from_integral (int_one, v, TYPE_LENGTH (builtin_type_int32)); + decimal_from_string (v, TYPE_LENGTH (type), byte_order, "1"); val = value_from_decfloat (type, v); } else if (TYPE_CODE (type1) == TYPE_CODE_FLT) @@ -568,6 +565,32 @@ value_one (struct type *type, enum lval_type lv) return val; } +/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack. */ + +static struct value * +get_value_at (struct type *type, CORE_ADDR addr, int lazy) +{ + struct value *val; + + if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) + error (_("Attempt to dereference a generic pointer.")); + + if (lazy) + { + val = allocate_value_lazy (type); + } + else + { + val = allocate_value (type); + read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type)); + } + + VALUE_LVAL (val) = lval_memory; + set_value_address (val, addr); + + return val; +} + /* Return a value with type TYPE located at ADDR. Call value_at only if the data needs to be fetched immediately; @@ -583,19 +606,7 @@ value_one (struct type *type, enum lval_type lv) struct value * value_at (struct type *type, CORE_ADDR addr) { - struct value *val; - - if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) - error (_("Attempt to dereference a generic pointer.")); - - val = allocate_value (type); - - read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type)); - - VALUE_LVAL (val) = lval_memory; - VALUE_ADDRESS (val) = addr; - - return val; + return get_value_at (type, addr, 0); } /* Return a lazy value with type TYPE located at ADDR (cf. value_at). */ @@ -603,17 +614,7 @@ value_at (struct type *type, CORE_ADDR addr) struct value * value_at_lazy (struct type *type, CORE_ADDR addr) { - struct value *val; - - if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID) - error (_("Attempt to dereference a generic pointer.")); - - val = allocate_value_lazy (type); - - VALUE_LVAL (val) = lval_memory; - VALUE_ADDRESS (val) = addr; - - return val; + return get_value_at (type, addr, 1); } /* Called only from the value_contents and value_contents_all() @@ -635,13 +636,36 @@ 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)) { - CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (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))); if (length) - read_memory (addr, value_contents_all_raw (val), length); + { + if (value_stack (val)) + read_stack (addr, value_contents_all_raw (val), length); + else + read_memory (addr, value_contents_all_raw (val), length); + } } else if (VALUE_LVAL (val) == lval_register) { @@ -708,8 +732,9 @@ value_fetch_lazy (struct value *val) fprintf_unfiltered (gdb_stdlog, " register=%d", VALUE_REGNUM (new_val)); else if (VALUE_LVAL (new_val) == lval_memory) - fprintf_unfiltered (gdb_stdlog, " address=0x%s", - paddr_nz (VALUE_ADDRESS (new_val))); + fprintf_unfiltered (gdb_stdlog, " address=%s", + paddress (gdbarch, + value_address (new_val))); else fprintf_unfiltered (gdb_stdlog, " computed"); @@ -727,6 +752,8 @@ value_fetch_lazy (struct value *val) watchpoints from trying to watch the saved frame pointer. */ value_free_to_mark (mark); } + else if (VALUE_LVAL (val) == lval_computed) + value_computed_funcs (val)->read (val); else internal_error (__FILE__, __LINE__, "Unexpected lazy value type."); @@ -775,7 +802,7 @@ value_assign (struct value *toval, struct value *fromval) { case lval_internalvar: set_internalvar (VALUE_INTERNALVAR (toval), fromval); - val = value_copy (VALUE_INTERNALVAR (toval)->value); + val = value_copy (fromval); val = value_change_enclosing_type (val, value_enclosing_type (fromval)); set_value_embedded_offset (val, value_embedded_offset (fromval)); @@ -800,27 +827,35 @@ 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? */ + struct value *parent = value_parent (toval); + changed_addr = value_address (parent) + value_offset (toval); + 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) changed_addr % 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); - read_memory (VALUE_ADDRESS (toval) + value_offset (toval), - buffer, changed_len); - modify_field (buffer, value_as_long (fromval), + read_memory (changed_addr, buffer, changed_len); + modify_field (type, 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_addr = value_address (toval); changed_len = TYPE_LENGTH (type); dest_buffer = value_contents (fromval); } @@ -834,6 +869,7 @@ value_assign (struct value *toval, struct value *fromval) case lval_register: { struct frame_info *frame; + struct gdbarch *gdbarch; int value_reg; /* Figure out which frame this is in currently. */ @@ -842,14 +878,14 @@ value_assign (struct value *toval, struct value *fromval) if (!frame) error (_("Value being assigned to is no longer active.")); - - if (gdbarch_convert_register_p - (current_gdbarch, VALUE_REGNUM (toval), type)) + + gdbarch = get_frame_arch (frame); + if (gdbarch_convert_register_p (gdbarch, VALUE_REGNUM (toval), type)) { /* If TOVAL is a special machine register requiring conversion of program values to a special raw format. */ - gdbarch_value_to_register (current_gdbarch, frame, + gdbarch_value_to_register (gdbarch, frame, VALUE_REGNUM (toval), type, value_contents (fromval)); } @@ -857,6 +893,8 @@ value_assign (struct value *toval, struct value *fromval) { if (value_bitsize (toval)) { + struct value *parent = value_parent (toval); + int offset = value_offset (parent) + value_offset (toval); int changed_len; gdb_byte buffer[sizeof (LONGEST)]; @@ -869,16 +907,13 @@ value_assign (struct value *toval, struct value *fromval) 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), + get_frame_register_bytes (frame, value_reg, offset, changed_len, buffer); - modify_field (buffer, value_as_long (fromval), - value_bitpos (toval), - value_bitsize (toval)); + modify_field (type, buffer, value_as_long (fromval), + value_bitpos (toval), value_bitsize (toval)); - put_frame_register_bytes (frame, value_reg, - value_offset (toval), + put_frame_register_bytes (frame, value_reg, offset, changed_len, buffer); } else @@ -895,7 +930,15 @@ value_assign (struct value *toval, struct value *fromval) observer_notify_target_changed (¤t_target); break; } - + + case lval_computed: + { + struct lval_funcs *funcs = value_computed_funcs (toval); + + funcs->write (toval, fromval); + } + break; + default: error (_("Left operand of assignment is not an lvalue.")); } @@ -975,11 +1018,11 @@ value_repeat (struct value *arg1, int count) val = allocate_repeat_value (value_enclosing_type (arg1), count); - read_memory (VALUE_ADDRESS (arg1) + value_offset (arg1), + read_memory (value_address (arg1), value_contents_all_raw (val), TYPE_LENGTH (value_enclosing_type (val))); VALUE_LVAL (val) = lval_memory; - VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + value_offset (arg1); + set_value_address (val, value_address (arg1)); return val; } @@ -999,7 +1042,7 @@ value_of_variable (struct symbol *var, struct block *b) frame = block_innermost_frame (b); if (!frame) { - if (BLOCK_FUNCTION (b) + if (BLOCK_FUNCTION (b) && !block_inlined_p (b) && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))) error (_("No frame is currently executing in block %s."), SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))); @@ -1029,7 +1072,7 @@ address_of_variable (struct symbol *var, struct block *b) if ((VALUE_LVAL (val) == lval_memory && value_lazy (val)) || TYPE_CODE (type) == TYPE_CODE_FUNC) { - CORE_ADDR addr = VALUE_ADDRESS (val); + CORE_ADDR addr = value_address (val); return value_from_pointer (lookup_pointer_type (type), addr); } @@ -1145,7 +1188,7 @@ value_coerce_array (struct value *arg1) error (_("Attempt to take address of value not located in memory.")); return value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), - (VALUE_ADDRESS (arg1) + value_offset (arg1))); + value_address (arg1)); } /* Given a value which is a function, return a value which is a pointer @@ -1160,7 +1203,7 @@ value_coerce_function (struct value *arg1) error (_("Attempt to take address of value not located in memory.")); retval = value_from_pointer (lookup_pointer_type (value_type (arg1)), - (VALUE_ADDRESS (arg1) + value_offset (arg1))); + value_address (arg1)); return retval; } @@ -1195,8 +1238,7 @@ value_addr (struct value *arg1) /* Get target memory address */ arg2 = value_from_pointer (lookup_pointer_type (value_type (arg1)), - (VALUE_ADDRESS (arg1) - + value_offset (arg1) + (value_address (arg1) + value_embedded_offset (arg1))); /* This may be a pointer to a base subobject; so remember the @@ -1291,7 +1333,6 @@ value_array (int lowbound, int highbound, struct value **elemvec) int idx; unsigned int typelength; struct value *val; - struct type *rangetype; struct type *arraytype; CORE_ADDR addr; @@ -1312,12 +1353,8 @@ value_array (int lowbound, int highbound, struct value **elemvec) } } - rangetype = create_range_type ((struct type *) NULL, - builtin_type_int32, - lowbound, highbound); - arraytype = create_array_type ((struct type *) NULL, - value_enclosing_type (elemvec[0]), - rangetype); + arraytype = lookup_array_range_type (value_enclosing_type (elemvec[0]), + lowbound, highbound); if (!current_language->c_style_arrays) { @@ -1342,6 +1379,20 @@ value_array (int lowbound, int highbound, struct value **elemvec) return val; } +struct value * +value_cstring (char *ptr, int len, struct type *char_type) +{ + struct value *val; + int lowbound = current_language->string_lower_bound; + int highbound = len / TYPE_LENGTH (char_type); + struct type *stringtype + = lookup_array_range_type (char_type, lowbound, highbound + lowbound - 1); + + val = allocate_value (stringtype); + memcpy (value_contents_raw (val), ptr, len); + return val; +} + /* Create a value for a string constant by allocating space in the inferior, copying the data into that space, and returning the address with type TYPE_CODE_STRING. PTR points to the string @@ -1352,45 +1403,26 @@ value_array (int lowbound, int highbound, struct value **elemvec) string may contain embedded null bytes. */ struct value * -value_string (char *ptr, int len) +value_string (char *ptr, int len, struct type *char_type) { struct value *val; int lowbound = current_language->string_lower_bound; - struct type *rangetype = create_range_type ((struct type *) NULL, - builtin_type_int32, - lowbound, - len + lowbound - 1); + int highbound = len / TYPE_LENGTH (char_type); struct type *stringtype - = create_string_type ((struct type *) NULL, rangetype); - CORE_ADDR addr; - - if (current_language->c_style_arrays == 0) - { - val = allocate_value (stringtype); - memcpy (value_contents_raw (val), ptr, len); - return val; - } - - - /* Allocate space to store the string in the inferior, and then copy - LEN bytes from PTR in gdb to that address in the inferior. */ - - addr = allocate_space_in_inferior (len); - write_memory (addr, (gdb_byte *) ptr, len); + = lookup_string_range_type (char_type, lowbound, highbound + lowbound - 1); - val = value_at_lazy (stringtype, addr); - return (val); + val = allocate_value (stringtype); + memcpy (value_contents_raw (val), ptr, len); + return val; } struct value * -value_bitstring (char *ptr, int len) +value_bitstring (char *ptr, int len, struct type *index_type) { struct value *val; - struct type *domain_type = create_range_type (NULL, - builtin_type_int32, - 0, len - 1); - struct type *type = create_set_type ((struct type *) NULL, - domain_type); + struct type *domain_type + = create_range_type (NULL, index_type, 0, len - 1); + struct type *type = create_set_type (NULL, domain_type); TYPE_CODE (type) = TYPE_CODE_BITSTRING; val = allocate_value (type); memcpy (value_contents_raw (val), ptr, TYPE_LENGTH (type)); @@ -1590,8 +1622,7 @@ search_struct_field (char *name, struct value *arg1, int offset, boffset = baseclass_offset (type, i, value_contents (arg1) + offset, - VALUE_ADDRESS (arg1) - + value_offset (arg1) + offset); + value_address (arg1) + offset); if (boffset == -1) error (_("virtual baseclass botch")); @@ -1605,14 +1636,13 @@ search_struct_field (char *name, struct value *arg1, int offset, CORE_ADDR base_addr; v2 = allocate_value (basetype); - base_addr = - VALUE_ADDRESS (arg1) + value_offset (arg1) + boffset; + base_addr = value_address (arg1) + boffset; if (target_read_memory (base_addr, value_contents_raw (v2), TYPE_LENGTH (basetype)) != 0) error (_("virtual baseclass botch")); VALUE_LVAL (v2) = lval_memory; - VALUE_ADDRESS (v2) = base_addr; + set_value_address (v2, base_addr); } else { @@ -1735,8 +1765,7 @@ search_struct_method (char *name, struct value **arg1p, if (offset < 0 || offset >= TYPE_LENGTH (type)) { gdb_byte *tmp = alloca (TYPE_LENGTH (baseclass)); - if (target_read_memory (VALUE_ADDRESS (*arg1p) - + value_offset (*arg1p) + offset, + if (target_read_memory (value_address (*arg1p) + offset, tmp, TYPE_LENGTH (baseclass)) != 0) error (_("virtual baseclass botch")); base_valaddr = tmp; @@ -1745,8 +1774,7 @@ search_struct_method (char *name, struct value **arg1p, base_valaddr = value_contents (*arg1p) + offset; base_offset = baseclass_offset (type, i, base_valaddr, - VALUE_ADDRESS (*arg1p) - + value_offset (*arg1p) + offset); + value_address (*arg1p) + offset); if (base_offset == -1) error (_("virtual baseclass botch")); } @@ -1830,10 +1858,6 @@ value_struct_elt (struct value **argp, struct value **args, /* C++: If it was not found as a data field, then try to return it as a pointer to a method. */ - - if (destructor_name_p (name, t)) - error (_("Cannot get value of destructor")); - v = search_struct_method (name, argp, args, 0, static_memfuncp, t); @@ -1849,32 +1873,6 @@ value_struct_elt (struct value **argp, struct value **args, return v; } - if (destructor_name_p (name, t)) - { - if (!args[1]) - { - /* Destructors are a special case. */ - int m_index, f_index; - - v = NULL; - if (get_destructor_fn_field (t, &m_index, &f_index)) - { - v = value_fn_field (NULL, - TYPE_FN_FIELDLIST1 (t, m_index), - f_index, NULL, 0); - } - if (v == NULL) - error (_("could not find destructor function named %s."), - name); - else - return v; - } - else - { - error (_("destructor should not have any argument")); - } - } - else v = search_struct_method (name, argp, args, 0, static_memfuncp, t); @@ -1955,7 +1953,7 @@ find_method_list (struct value **argp, char *method, base_offset = value_offset (*argp) + offset; base_offset = baseclass_offset (type, i, value_contents (*argp) + base_offset, - VALUE_ADDRESS (*argp) + base_offset); + value_address (*argp) + base_offset); if (base_offset == -1) error (_("virtual baseclass botch")); } @@ -2173,9 +2171,11 @@ find_overload_match (struct type **arg_types, int nargs, if (objp) { - if (TYPE_CODE (value_type (temp)) != TYPE_CODE_PTR - && (TYPE_CODE (value_type (*objp)) == TYPE_CODE_PTR - || TYPE_CODE (value_type (*objp)) == TYPE_CODE_REF)) + struct type *temp_type = check_typedef (value_type (temp)); + struct type *obj_type = check_typedef (value_type (*objp)); + if (TYPE_CODE (temp_type) != TYPE_CODE_PTR + && (TYPE_CODE (obj_type) == TYPE_CODE_PTR + || TYPE_CODE (obj_type) == TYPE_CODE_REF)) { temp = value_addr (temp); } @@ -2478,8 +2478,6 @@ classify_oload_match (struct badness_vector *oload_champ_bv, int destructor_name_p (const char *name, const struct type *type) { - /* Destructors are a special case. */ - if (name[0] == '~') { char *dname = type_name_no_tag (type); @@ -2518,14 +2516,6 @@ check_field (struct type *type, const char *name) /* C++: If it was not found as a data field, then try to return it as a pointer to a method. */ - /* Destructors are a special case. */ - if (destructor_name_p (name, type)) - { - int m_index, f_index; - - return get_destructor_fn_field (type, &m_index, &f_index); - } - for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i) { if (strcmp_iw (TYPE_FN_FIELDLIST_NAME (type, i), name) == 0) @@ -2621,12 +2611,6 @@ value_struct_elt_for_reference (struct type *domain, int offset, /* C++: If it was not found as a data field, then try to return it as a pointer to a method. */ - /* Destructors are a special case. */ - if (destructor_name_p (name, t)) - { - error (_("member pointers to destructors not implemented yet")); - } - /* Perform all necessary dereferencing. */ while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR) intype = TYPE_TARGET_TYPE (intype); @@ -2713,7 +2697,7 @@ value_struct_elt_for_reference (struct type *domain, int offset, result = allocate_value (lookup_methodptr_type (TYPE_FN_FIELD_TYPE (f, j))); cplus_make_method_ptr (value_type (result), value_contents_writeable (result), - VALUE_ADDRESS (v), 0); + value_address (v), 0); } } return result; @@ -2872,7 +2856,7 @@ value_full_object (struct value *argp, /* Go back by the computed top_offset from the beginning of the object, adjusting for the embedded offset of argp if that's what value_rtti_type used for its computation. */ - new_val = value_at_lazy (real_type, VALUE_ADDRESS (argp) - top + + new_val = value_at_lazy (real_type, value_address (argp) - top + (using_enc ? 0 : value_embedded_offset (argp))); deprecated_set_value_type (new_val, value_type (argp)); set_value_embedded_offset (new_val, (using_enc @@ -3002,7 +2986,7 @@ value_slice (struct value *array, int lowbound, int length) else if (element > 0) { int j = i % TARGET_CHAR_BIT; - if (gdbarch_bits_big_endian (current_gdbarch)) + if (gdbarch_bits_big_endian (get_type_arch (array_type))) j = TARGET_CHAR_BIT - 1 - j; value_contents_raw (slice)[i / TARGET_CHAR_BIT] |= (1 << j); }