2008-03-25 Pedro Alves <pedro@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / valops.c
index 6b2b3cea16ac1518e68290a70fe19f21eac23dc7..80bee1e8968dfbdf359ea34ecd414e92b159f6d3 100644 (file)
@@ -1,8 +1,8 @@
 /* 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.
 
@@ -36,6 +36,7 @@
 #include "infcall.h"
 #include "dictionary.h"
 #include "cp-support.h"
+#include "dfp.h"
 
 #include <errno.h>
 #include "gdb_string.h"
@@ -338,7 +339,8 @@ value_cast (struct type *type, struct value *arg2)
     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
@@ -357,6 +359,22 @@ value_cast (struct type *type, struct value *arg2)
     }
   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
@@ -453,6 +471,40 @@ value_zero (struct type *type, enum lval_type lv)
   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;
@@ -548,9 +600,18 @@ value_assign (struct value *toval, struct value *fromval)
 
   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
@@ -800,6 +861,50 @@ value_of_variable (struct symbol *var, struct block *b)
   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.
@@ -829,6 +934,11 @@ value_coerce_array (struct value *arg1)
 {
   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."));
 
@@ -874,6 +984,10 @@ value_addr (struct value *arg1)
   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."));
 
@@ -964,7 +1078,7 @@ value_ind (struct value *arg1)
   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.
 
@@ -1022,24 +1136,15 @@ value_array (int lowbound, int highbound, struct value **elemvec)
       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
@@ -1346,100 +1451,6 @@ search_struct_field (char *name, struct value *arg1, int offset,
   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
@@ -1516,47 +1527,30 @@ search_struct_method (char *name, struct value **arg1p,
 
       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
        {
@@ -1756,29 +1750,12 @@ find_method_list (struct value **argp, char *method,
       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.  */
@@ -2853,7 +2830,7 @@ value_slice (struct value *array, int lowbound, int length)
          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);
            }
This page took 0.030546 seconds and 4 git commands to generate.