/* Perform non-arithmetic operations on values, for GDB.
- Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
This file is part of GDB.
#include "infcall.h"
#include "dictionary.h"
#include "cp-support.h"
+#include "dfp.h"
#include <errno.h>
#include "gdb_string.h"
code2 = TYPE_CODE_INT;
scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
- || code2 == TYPE_CODE_ENUM || code2 == TYPE_CODE_RANGE);
+ || code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM
+ || code2 == TYPE_CODE_RANGE);
if (code1 == TYPE_CODE_STRUCT
&& code2 == TYPE_CODE_STRUCT
}
if (code1 == TYPE_CODE_FLT && scalar)
return value_from_double (type, value_as_double (arg2));
+ else if (code1 == TYPE_CODE_DECFLOAT && scalar)
+ {
+ int dec_len = TYPE_LENGTH (type);
+ gdb_byte dec[16];
+
+ if (code2 == TYPE_CODE_FLT)
+ decimal_from_floating (arg2, dec, dec_len);
+ else if (code2 == TYPE_CODE_DECFLOAT)
+ decimal_convert (value_contents (arg2), TYPE_LENGTH (type2),
+ dec, dec_len);
+ else
+ /* The only option left is an integral type. */
+ decimal_from_integral (arg2, dec, dec_len);
+
+ return value_from_decfloat (type, dec);
+ }
else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
|| code1 == TYPE_CODE_RANGE)
&& (scalar || code2 == TYPE_CODE_PTR
return val;
}
+/* Create a value of numeric type TYPE that is one, and return it. */
+
+struct value *
+value_one (struct type *type, enum lval_type lv)
+{
+ struct type *type1 = check_typedef (type);
+ struct value *val = NULL; /* avoid -Wall warning */
+
+ if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
+ {
+ struct value *int_one = value_from_longest (builtin_type_int, 1);
+ struct value *val;
+ gdb_byte v[16];
+
+ decimal_from_integral (int_one, v, TYPE_LENGTH (builtin_type_int));
+ val = value_from_decfloat (type, v);
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_FLT)
+ {
+ val = value_from_double (type, (DOUBLEST) 1);
+ }
+ else if (is_integral_type (type1))
+ {
+ val = value_from_longest (type, (LONGEST) 1);
+ }
+ else
+ {
+ error (_("Not a numeric type."));
+ }
+
+ VALUE_LVAL (val) = lv;
+ return val;
+}
+
/* Return a value with type TYPE located at ADDR.
Call value_at only if the data needs to be fetched immediately;
type = value_type (toval);
if (VALUE_LVAL (toval) != lval_internalvar)
- fromval = value_cast (type, fromval);
+ {
+ toval = value_coerce_to_target (toval);
+ fromval = value_cast (type, fromval);
+ }
else
- fromval = coerce_array (fromval);
+ {
+ /* Coerce arrays and functions to pointers, except for arrays
+ which only live in GDB's storage. */
+ if (!value_must_coerce_to_target (fromval))
+ fromval = coerce_array (fromval);
+ }
+
CHECK_TYPEDEF (type);
/* Since modifying a register can trash the frame chain, and
return val;
}
+/* Return one if VAL does not live in target memory, but should in order
+ to operate on it. Otherwise return zero. */
+
+int
+value_must_coerce_to_target (struct value *val)
+{
+ struct type *valtype;
+
+ /* The only lval kinds which do not live in target memory. */
+ if (VALUE_LVAL (val) != not_lval
+ && VALUE_LVAL (val) != lval_internalvar)
+ return 0;
+
+ valtype = check_typedef (value_type (val));
+
+ switch (TYPE_CODE (valtype))
+ {
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRING:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Make sure that VAL lives in target memory if it's supposed to. For instance,
+ strings are constructed as character arrays in GDB's storage, and this
+ function copies them to the target. */
+
+struct value *
+value_coerce_to_target (struct value *val)
+{
+ LONGEST length;
+ CORE_ADDR addr;
+
+ if (!value_must_coerce_to_target (val))
+ return val;
+
+ length = TYPE_LENGTH (check_typedef (value_type (val)));
+ addr = allocate_space_in_inferior (length);
+ write_memory (addr, value_contents (val), length);
+ return value_at_lazy (value_type (val), addr);
+}
+
/* Given a value which is an array, return a value which is a pointer
to its first element, regardless of whether or not the array has a
nonzero lower bound.
{
struct type *type = check_typedef (value_type (arg1));
+ /* If the user tries to do something requiring a pointer with an
+ array that has not yet been pushed to the target, then this would
+ be a good time to do so. */
+ arg1 = value_coerce_to_target (arg1);
+
if (VALUE_LVAL (arg1) != lval_memory)
error (_("Attempt to take address of value not located in memory."));
if (TYPE_CODE (type) == TYPE_CODE_FUNC)
return value_coerce_function (arg1);
+ /* If this is an array that has not yet been pushed to the target,
+ then this would be a good time to force it to memory. */
+ arg1 = value_coerce_to_target (arg1);
+
if (VALUE_LVAL (arg1) != lval_memory)
error (_("Attempt to take address of value not located in memory."));
return 0; /* For lint -- never reached. */
}
\f
-/* Create a value for an array by allocating space in the inferior,
+/* Create a value for an array by allocating space in GDB, copying
copying the data into that space, and then setting up an array
value.
return val;
}
- /* Allocate space to store the array in the inferior, and then
- initialize it by copying in each element. FIXME: Is it worth it
- to create a local buffer in which to collect each value and then
- write all the bytes in one operation? */
+ /* Allocate space to store the array, and then initialize it by
+ copying in each element. */
- addr = allocate_space_in_inferior (nelem * typelength);
+ val = allocate_value (arraytype);
for (idx = 0; idx < nelem; idx++)
- {
- write_memory (addr + (idx * typelength),
- value_contents_all (elemvec[idx]),
- typelength);
- }
-
- /* Create the array type and set up an array value to be evaluated
- lazily. */
-
- val = value_at_lazy (arraytype, addr);
- return (val);
+ memcpy (value_contents_writeable (val) + (idx * typelength),
+ value_contents_all (elemvec[idx]),
+ typelength);
+ return val;
}
/* Create a value for a string constant by allocating space in the
return NULL;
}
-
-/* Return the offset (in bytes) of the virtual base of type BASETYPE
- * in an object pointed to by VALADDR (on the host), assumed to be of
- * type TYPE. OFFSET is number of bytes beyond start of ARG to start
- * looking (in case VALADDR is the contents of an enclosing object).
- *
- * This routine recurses on the primary base of the derived class
- * because the virtual base entries of the primary base appear before
- * the other virtual base entries.
- *
- * If the virtual base is not found, a negative integer is returned.
- * The magnitude of the negative integer is the number of entries in
- * the virtual table to skip over (entries corresponding to various
- * ancestral classes in the chain of primary bases).
- *
- * Important: This assumes the HP / Taligent C++ runtime conventions.
- * Use baseclass_offset() instead to deal with g++ conventions. */
-
-void
-find_rt_vbase_offset (struct type *type, struct type *basetype,
- const gdb_byte *valaddr, int offset,
- int *boffset_p, int *skip_p)
-{
- int boffset; /* Offset of virtual base. */
- int index; /* Displacement to use in virtual
- table. */
- int skip;
-
- struct value *vp;
- CORE_ADDR vtbl; /* The virtual table pointer. */
- struct type *pbc; /* The primary base class. */
-
- /* Look for the virtual base recursively in the primary base, first.
- * This is because the derived class object and its primary base
- * subobject share the primary virtual table. */
-
- boffset = 0;
- pbc = TYPE_PRIMARY_BASE (type);
- if (pbc)
- {
- find_rt_vbase_offset (pbc, basetype, valaddr,
- offset, &boffset, &skip);
- if (skip < 0)
- {
- *boffset_p = boffset;
- *skip_p = -1;
- return;
- }
- }
- else
- skip = 0;
-
-
- /* Find the index of the virtual base according to HP/Taligent
- runtime spec. (Depth-first, left-to-right.) */
- index = virtual_base_index_skip_primaries (basetype, type);
-
- if (index < 0)
- {
- *skip_p = skip + virtual_base_list_length_skip_primaries (type);
- *boffset_p = 0;
- return;
- }
-
- /* pai: FIXME -- 32x64 possible problem. */
- /* First word (4 bytes) in object layout is the vtable pointer. */
- vtbl = *(CORE_ADDR *) (valaddr + offset);
-
- /* Before the constructor is invoked, things are usually zero'd
- out. */
- if (vtbl == 0)
- error (_("Couldn't find virtual table -- object may not be constructed yet."));
-
-
- /* Find virtual base's offset -- jump over entries for primary base
- * ancestors, then use the index computed above. But also adjust by
- * HP_ACC_VBASE_START for the vtable slots before the start of the
- * virtual base entries. Offset is negative -- virtual base entries
- * appear _before_ the address point of the virtual table. */
-
- /* pai: FIXME -- 32x64 problem, if word = 8 bytes, change multiplier
- & use long type */
-
- /* epstein : FIXME -- added param for overlay section. May not be
- correct. */
- vp = value_at (builtin_type_int,
- vtbl + 4 * (-skip - index - HP_ACC_VBASE_START));
- boffset = value_as_long (vp);
- *skip_p = -1;
- *boffset_p = boffset;
- return;
-}
-
-
/* Helper function used by value_struct_elt to recurse through
baseclasses. Look for a field NAME in ARG1. Adjust the address of
ARG1 by OFFSET bytes, and search in it assuming it has (class) type
if (BASETYPE_VIA_VIRTUAL (type, i))
{
- if (TYPE_HAS_VTABLE (type))
- {
- /* HP aCC compiled type, search for virtual base offset
- according to HP/Taligent runtime spec. */
- int skip;
- find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
- value_contents_all (*arg1p),
- offset + value_embedded_offset (*arg1p),
- &base_offset, &skip);
- if (skip >= 0)
- error (_("Virtual base class offset not found in vtable"));
- }
- else
- {
- struct type *baseclass =
- check_typedef (TYPE_BASECLASS (type, i));
- const gdb_byte *base_valaddr;
+ struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
+ const gdb_byte *base_valaddr;
- /* The virtual base class pointer might have been
- clobbered by the user program. Make sure that it
- still points to a valid memory location. */
+ /* The virtual base class pointer might have been
+ clobbered by the user program. Make sure that it
+ still points to a valid memory location. */
- 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,
- tmp, TYPE_LENGTH (baseclass)) != 0)
- error (_("virtual baseclass botch"));
- base_valaddr = tmp;
- }
- else
- base_valaddr = value_contents (*arg1p) + offset;
-
- base_offset =
- baseclass_offset (type, i, base_valaddr,
- VALUE_ADDRESS (*arg1p)
- + value_offset (*arg1p) + offset);
- if (base_offset == -1)
+ 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,
+ tmp, TYPE_LENGTH (baseclass)) != 0)
error (_("virtual baseclass botch"));
+ base_valaddr = tmp;
}
+ else
+ base_valaddr = value_contents (*arg1p) + offset;
+
+ base_offset = baseclass_offset (type, i, base_valaddr,
+ VALUE_ADDRESS (*arg1p)
+ + value_offset (*arg1p) + offset);
+ if (base_offset == -1)
+ error (_("virtual baseclass botch"));
}
else
{
int base_offset;
if (BASETYPE_VIA_VIRTUAL (type, i))
{
- if (TYPE_HAS_VTABLE (type))
- {
- /* HP aCC compiled type, search for virtual base offset
- * according to HP/Taligent runtime spec. */
- int skip;
- find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
- value_contents_all (*argp),
- offset + value_embedded_offset (*argp),
- &base_offset, &skip);
- if (skip >= 0)
- error (_("Virtual base class offset not found in vtable"));
- }
- else
- {
- /* probably g++ runtime model */
- base_offset = value_offset (*argp) + offset;
- base_offset =
- baseclass_offset (type, i,
- value_contents (*argp) + base_offset,
- VALUE_ADDRESS (*argp) + base_offset);
- if (base_offset == -1)
- error (_("virtual baseclass botch"));
- }
+ base_offset = value_offset (*argp) + offset;
+ base_offset = baseclass_offset (type, i,
+ value_contents (*argp) + base_offset,
+ VALUE_ADDRESS (*argp) + base_offset);
+ if (base_offset == -1)
+ error (_("virtual baseclass botch"));
}
else /* Non-virtual base, simply use bit position from debug
info. */
else if (element > 0)
{
int j = i % TARGET_CHAR_BIT;
- if (BITS_BIG_ENDIAN)
+ if (gdbarch_bits_big_endian (current_gdbarch))
j = TARGET_CHAR_BIT - 1 - j;
value_contents_raw (slice)[i / TARGET_CHAR_BIT] |= (1 << j);
}