Allow struct 'return' on 32-bit sparc.
authorDavid S. Miller <davem@redhat.com>
Wed, 6 Feb 2013 19:40:04 +0000 (19:40 +0000)
committerDavid S. Miller <davem@redhat.com>
Wed, 6 Feb 2013 19:40:04 +0000 (19:40 +0000)
gdb/

* sparc-tdep.c (sparc32_return_value): Handle writing return value when
using RETURN_VALUE_ABI_PRESERVES_ADDRESS.
* value.c (struct_return_convention): New function.
(using_struct_return): Implement in terms of struct_return_convention.
* value.h (struct_return_convention): Declare.
* stack.c (return_command): Allow successful overriding of the return
value when RETURN_VALUE_ABI_PRESERVES_ADDRESS.

gdb/ChangeLog
gdb/sparc-tdep.c
gdb/stack.c
gdb/value.c
gdb/value.h

index 3c49f96139599da9f888aa109e69b895ec60c016..32f0c49293f2ba32a750f67c47e80f0ea17dedf2 100644 (file)
@@ -1,3 +1,13 @@
+2013-02-06  David S. Miller  <davem@davemloft.net>
+
+       * sparc-tdep.c (sparc32_return_value): Handle writing return value when
+       using RETURN_VALUE_ABI_PRESERVES_ADDRESS.
+       * value.c (struct_return_convention): New function.
+       (using_struct_return): Implement in terms of struct_return_convention.
+       * value.h (struct_return_convention): Declare.
+       * stack.c (return_command): Allow successful overriding of the return
+       value when RETURN_VALUE_ABI_PRESERVES_ADDRESS.
+
 2013-02-06  Tom Tromey  <tromey@redhat.com>
 
        * python/py-type.c (typy_strip_typedefs): Don't call check_typedef
index 3ae73950b09ef87bd1bbc5db99d5d8c1ac5f99aa..2b38521a85f6600fde32afc6127d534bb6ba144a 100644 (file)
@@ -1370,15 +1370,21 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
   if (sparc_structure_or_union_p (type)
       || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
     {
+      ULONGEST sp;
+      CORE_ADDR addr;
+
       if (readbuf)
        {
-         ULONGEST sp;
-         CORE_ADDR addr;
-
          regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
          addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
          read_memory (addr, readbuf, TYPE_LENGTH (type));
        }
+      if (writebuf)
+       {
+         regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+         addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
+         write_memory (addr, writebuf, TYPE_LENGTH (type));
+       }
 
       return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
     }
index bfec1b853b3ebd6c49060d04dc9326e9a47622e9..9f4aafc812d117cc32129d63996e5942f58e51e8 100644 (file)
@@ -2278,6 +2278,7 @@ down_command (char *count_exp, int from_tty)
 void
 return_command (char *retval_exp, int from_tty)
 {
+  enum return_value_convention rv_conv;
   struct frame_info *thisframe;
   struct gdbarch *gdbarch;
   struct symbol *thisfun;
@@ -2331,6 +2332,7 @@ return_command (char *retval_exp, int from_tty)
       if (thisfun != NULL)
        function = read_var_value (thisfun, thisframe);
 
+      rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
       if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
        /* If the return-type is "void", don't try to find the
            return-value's location.  However, do still evaluate the
@@ -2338,14 +2340,18 @@ return_command (char *retval_exp, int from_tty)
            is discarded, side effects such as "return i++" still
            occur.  */
        return_value = NULL;
-      else if (thisfun != NULL
-              && using_struct_return (gdbarch, function, return_type))
+      else if (thisfun != NULL)
        {
-         query_prefix = "The location at which to store the "
-           "function's return value is unknown.\n"
-           "If you continue, the return value "
-           "that you specified will be ignored.\n";
-         return_value = NULL;
+         rv_conv = struct_return_convention (gdbarch, function, return_type);
+         if (rv_conv == RETURN_VALUE_STRUCT_CONVENTION
+             || rv_conv == RETURN_VALUE_ABI_RETURNS_ADDRESS)
+           {
+             query_prefix = "The location at which to store the "
+               "function's return value is unknown.\n"
+               "If you continue, the return value "
+               "that you specified will be ignored.\n";
+             return_value = NULL;
+           }
        }
     }
 
@@ -2375,9 +2381,8 @@ return_command (char *retval_exp, int from_tty)
       struct type *return_type = value_type (return_value);
       struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
 
-      gdb_assert (gdbarch_return_value (gdbarch, function, return_type, NULL,
-                                       NULL, NULL)
-                 == RETURN_VALUE_REGISTER_CONVENTION);
+      gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION
+                 && rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS);
       gdbarch_return_value (gdbarch, function, return_type,
                            get_current_regcache (), NULL /*read*/,
                            value_contents (return_value) /*write*/);
index dbf1c376bed69565b7e6f6eb722058f9c751d9a0..4b70eceed9abd78e1eedc506a5f94ff10fd1e73d 100644 (file)
@@ -3323,6 +3323,23 @@ coerce_array (struct value *arg)
 }
 \f
 
+/* Return the return value convention that will be used for the
+   specified type.  */
+
+enum return_value_convention
+struct_return_convention (struct gdbarch *gdbarch,
+                         struct value *function, struct type *value_type)
+{
+  enum type_code code = TYPE_CODE (value_type);
+
+  if (code == TYPE_CODE_ERROR)
+    error (_("Function return type unknown."));
+
+  /* Probe the architecture for the return-value convention.  */
+  return gdbarch_return_value (gdbarch, function, value_type,
+                              NULL, NULL, NULL);
+}
+
 /* Return true if the function returning the specified type is using
    the convention of returning structures in memory (passing in the
    address as a hidden first parameter).  */
@@ -3331,19 +3348,12 @@ int
 using_struct_return (struct gdbarch *gdbarch,
                     struct value *function, struct type *value_type)
 {
-  enum type_code code = TYPE_CODE (value_type);
-
-  if (code == TYPE_CODE_ERROR)
-    error (_("Function return type unknown."));
-
-  if (code == TYPE_CODE_VOID)
+  if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
     /* A void return value is never in memory.  See also corresponding
        code in "print_return_value".  */
     return 0;
 
-  /* Probe the architecture for the return-value convention.  */
-  return (gdbarch_return_value (gdbarch, function, value_type,
-                               NULL, NULL, NULL)
+  return (struct_return_convention (gdbarch, function, value_type)
          != RETURN_VALUE_REGISTER_CONVENTION);
 }
 
index b9013fdf1e87079174053858684b3729788b4ccf..c10c3ecf163ab8f36b5f1a72c5e26b4fae3767d7 100644 (file)
@@ -696,6 +696,10 @@ extern int value_in (struct value *element, struct value *set);
 extern int value_bit_index (struct type *type, const gdb_byte *addr,
                            int index);
 
+extern enum return_value_convention
+struct_return_convention (struct gdbarch *gdbarch, struct value *function,
+                         struct type *value_type);
+
 extern int using_struct_return (struct gdbarch *gdbarch,
                                struct value *function,
                                struct type *value_type);