2003-04-09 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / valops.c
index d1a18774f964eeefd80097d376041bc468880a54..a2a2e978bd39425343d106b2b2f9fad4540f94ed 100644 (file)
@@ -33,6 +33,7 @@
 #include "gdbcmd.h"
 #include "regcache.h"
 #include "cp-abi.h"
+#include "block.h"
 
 #include <errno.h>
 #include "gdb_string.h"
@@ -515,6 +516,7 @@ value_assign (struct value *toval, struct value *fromval)
   struct value *val;
   char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE);
   int use_buffer = 0;
+  struct frame_id old_frame;
 
   if (!toval->modifiable)
     error ("Left operand of assignment is not a modifiable lvalue.");
@@ -544,6 +546,11 @@ value_assign (struct value *toval, struct value *fromval)
        }
     }
 
+  /* Since modifying a register can trash the frame chain, and modifying memory
+     can trash the frame cache, we save the old frame and then restore the new
+     frame afterwards.  */
+  old_frame = get_frame_id (deprecated_selected_frame);
+
   switch (VALUE_LVAL (toval))
     {
     case lval_internalvar:
@@ -612,7 +619,6 @@ value_assign (struct value *toval, struct value *fromval)
     case lval_reg_frame_relative:
     case lval_register:
       {
-       struct frame_id old_frame;
        /* value is stored in a series of registers in the frame
           specified by the structure.  Copy that value out, modify
           it, and copy it back in.  */
@@ -625,11 +631,6 @@ value_assign (struct value *toval, struct value *fromval)
        int regno;
        struct frame_info *frame;
 
-       /* Since modifying a register can trash the frame chain, we
-           save the old frame and then restore the new frame
-           afterwards.  */
-       old_frame = get_frame_id (deprecated_selected_frame);
-
        /* Figure out which frame this is in currently.  */
        if (VALUE_LVAL (toval) == lval_register)
          {
@@ -731,26 +732,6 @@ value_assign (struct value *toval, struct value *fromval)
          register_changed_hook (-1);
        target_changed_event ();
 
-       /* Assigning to the stack pointer, frame pointer, and other
-          (architecture and calling convention specific) registers
-          may cause the frame cache to be out of date.  We just do
-          this on all assignments to registers for simplicity; I
-          doubt the slowdown matters.  */
-       reinit_frame_cache ();
-
-       /* Having destoroyed the frame cache, restore the selected
-           frame.  */
-       /* FIXME: cagney/2002-11-02: There has to be a better way of
-           doing this.  Instead of constantly saving/restoring the
-           frame.  Why not create a get_selected_frame() function
-           that, having saved the selected frame's ID can
-           automatically re-find the previously selected frame
-           automatically.  */
-       {
-         struct frame_info *fi = frame_find_by_id (old_frame);
-         if (fi != NULL)
-           select_frame (fi);
-       }
       }
       break;
       
@@ -759,6 +740,38 @@ value_assign (struct value *toval, struct value *fromval)
       error ("Left operand of assignment is not an lvalue.");
     }
 
+  /* Assigning to the stack pointer, frame pointer, and other
+     (architecture and calling convention specific) registers may
+     cause the frame cache to be out of date.  Assigning to memory
+     also can.  We just do this on all assignments to registers or
+     memory, for simplicity's sake; I doubt the slowdown matters.  */
+  switch (VALUE_LVAL (toval))
+    {
+    case lval_memory:
+    case lval_register:
+    case lval_reg_frame_relative:
+
+      reinit_frame_cache ();
+
+      /* Having destoroyed the frame cache, restore the selected frame.  */
+
+      /* FIXME: cagney/2002-11-02: There has to be a better way of
+        doing this.  Instead of constantly saving/restoring the
+        frame.  Why not create a get_selected_frame() function that,
+        having saved the selected frame's ID can automatically
+        re-find the previously selected frame automatically.  */
+
+      {
+       struct frame_info *fi = frame_find_by_id (old_frame);
+       if (fi != NULL)
+         select_frame (fi);
+      }
+
+      break;
+    default:
+      break;
+    }
+  
   /* If the field does not entirely fill a LONGEST, then zero the sign bits.
      If the field is signed, and is negative, then sign extend. */
   if ((VALUE_BITSIZE (toval) > 0)
@@ -822,9 +835,9 @@ value_of_variable (struct symbol *var, struct block *b)
       if (!frame)
        {
          if (BLOCK_FUNCTION (b)
-             && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)))
+             && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)))
            error ("No frame is currently executing in block %s.",
-                  SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)));
+                  SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)));
          else
            error ("No frame is currently executing in specified block");
        }
@@ -832,7 +845,7 @@ value_of_variable (struct symbol *var, struct block *b)
 
   val = read_var_value (var, frame);
   if (!val)
-    error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
+    error ("Address of symbol \"%s\" is unknown.", SYMBOL_PRINT_NAME (var));
 
   return val;
 }
@@ -1066,8 +1079,8 @@ value_push (register CORE_ADDR sp, struct value *arg)
 }
 
 CORE_ADDR
-default_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
-                       int struct_return, CORE_ADDR struct_addr)
+legacy_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+                      int struct_return, CORE_ADDR struct_addr)
 {
   /* ASSERT ( !struct_return); */
   int i;
@@ -1227,8 +1240,8 @@ find_function_addr (struct value *function, struct type **retval_type)
 
    ARGS is modified to contain coerced values. */
 
-static struct value *
-hand_function_call (struct value *function, int nargs, struct value **args)
+struct value *
+call_function_by_hand (struct value *function, int nargs, struct value **args)
 {
   register CORE_ADDR sp;
   register int i;
@@ -1251,6 +1264,7 @@ hand_function_call (struct value *function, int nargs, struct value **args)
   static ULONGEST *dummy;
   int sizeof_dummy1;
   char *dummy1;
+  CORE_ADDR dummy_addr;
   CORE_ADDR old_sp;
   struct type *value_type;
   unsigned char struct_return;
@@ -1287,10 +1301,34 @@ hand_function_call (struct value *function, int nargs, struct value **args)
   inf_status = save_inferior_status (1);
   inf_status_cleanup = make_cleanup_restore_inferior_status (inf_status);
 
-  /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
-     (and POP_FRAME for restoring them).  (At least on most machines)
-     they are saved on the stack in the inferior.  */
-  PUSH_DUMMY_FRAME;
+  if (DEPRECATED_PUSH_DUMMY_FRAME_P ())
+    {
+      /* DEPRECATED_PUSH_DUMMY_FRAME is responsible for saving the
+        inferior registers (and frame_pop() for restoring them).  (At
+        least on most machines) they are saved on the stack in the
+        inferior.  */
+      DEPRECATED_PUSH_DUMMY_FRAME;
+    }
+  else
+    {
+      /* FIXME: cagney/2003-02-26: Step zero of this little tinker is
+      to extract the generic dummy frame code from the architecture
+      vector.  Hence this direct call.
+
+      A follow-on change is to modify this interface so that it takes
+      thread OR frame OR tpid as a parameter, and returns a dummy
+      frame handle.  The handle can then be used further down as a
+      parameter SAVE_DUMMY_FRAME_TOS.  Hmm, thinking about it, since
+      everything is ment to be using generic dummy frames, why not
+      even use some of the dummy frame code to here - do a regcache
+      dup and then pass the duped regcache, along with all the other
+      stuff, at one single point.
+
+      In fact, you can even save the structure's return address in the
+      dummy frame and fix one of those nasty lost struct return edge
+      conditions.  */
+      generic_push_dummy_frame ();
+    }
 
   old_sp = read_sp ();
 
@@ -1337,9 +1375,9 @@ hand_function_call (struct value *function, int nargs, struct value **args)
        be able to correctly perform back traces.  If a target is
        having trouble with backtraces, first thing to do is add
        FRAME_ALIGN() to its architecture vector.  After that, try
-       adding SAVE_DUMMY_FRAME_TOS() and modifying FRAME_CHAIN so that
-       when the next outer frame is a generic dummy, it returns the
-       current frame's base.  */
+       adding SAVE_DUMMY_FRAME_TOS() and modifying
+       DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
+       generic dummy, it returns the current frame's base.  */
     sp = old_sp;
 
   if (INNER_THAN (1, 2))
@@ -1386,57 +1424,34 @@ hand_function_call (struct value *function, int nargs, struct value **args)
   real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
                            value_type, using_gcc);
 #else
-  FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
-                 value_type, using_gcc);
+  if (FIX_CALL_DUMMY_P ())
+    {
+      /* gdb_assert (CALL_DUMMY_LOCATION == ON_STACK) true?  */
+      FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, value_type,
+                     using_gcc);
+    }
   real_pc = start_sp;
 #endif
 
-  if (CALL_DUMMY_LOCATION == ON_STACK)
+  switch (CALL_DUMMY_LOCATION)
     {
+    case ON_STACK:
+      dummy_addr = start_sp;
       write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
       if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
        generic_save_call_dummy_addr (start_sp, start_sp + sizeof_dummy1);
-    }
-
-  if (CALL_DUMMY_LOCATION == BEFORE_TEXT_END)
-    {
-      /* Convex Unix prohibits executing in the stack segment. */
-      /* Hope there is empty room at the top of the text segment. */
-      extern CORE_ADDR text_end;
-      static int checked = 0;
-      if (!checked)
-       for (start_sp = text_end - sizeof_dummy1; start_sp < text_end; ++start_sp)
-         if (read_memory_integer (start_sp, 1) != 0)
-           error ("text segment full -- no place to put call");
-      checked = 1;
-      sp = old_sp;
-      real_pc = text_end - sizeof_dummy1;
-      write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
-      if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
-       generic_save_call_dummy_addr (real_pc, real_pc + sizeof_dummy1);
-    }
-
-  if (CALL_DUMMY_LOCATION == AFTER_TEXT_END)
-    {
-      extern CORE_ADDR text_end;
-      int errcode;
-      sp = old_sp;
-      real_pc = text_end;
-      errcode = target_write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
-      if (errcode != 0)
-       error ("Cannot write text segment -- call_function failed");
-      if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
-       generic_save_call_dummy_addr (real_pc, real_pc + sizeof_dummy1);
-    }
-
-  if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
-    {
+      break;
+    case AT_ENTRY_POINT:
       real_pc = funaddr;
+      dummy_addr = CALL_DUMMY_ADDRESS ();
       if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
        /* NOTE: cagney/2002-04-13: The entry point is going to be
            modified with a single breakpoint.  */
        generic_save_call_dummy_addr (CALL_DUMMY_ADDRESS (),
                                      CALL_DUMMY_ADDRESS () + 1);
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, "bad switch");
     }
 
 #ifdef lint
@@ -1563,9 +1578,8 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
     {
       int len = TYPE_LENGTH (value_type);
       if (STACK_ALIGN_P ())
-       /* MVS 11/22/96: I think at least some of this stack_align
-          code is really broken.  Better to let PUSH_ARGUMENTS adjust
-          the stack in a target-defined manner.  */
+       /* NOTE: cagney/2003-03-22: Should rely on frame align, rather
+           than stack align to force the alignment of the stack.  */
        len = STACK_ALIGN (len);
       if (INNER_THAN (1, 2))
        {
@@ -1593,10 +1607,13 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
      on other architectures. This is because all the alignment is
      taken care of in the above code (ifdef REG_STRUCT_HAS_ADDR) and
      in hppa_push_arguments */
-  if (EXTRA_STACK_ALIGNMENT_NEEDED)
+  /* NOTE: cagney/2003-03-24: The below code is very broken.  Given an
+     odd sized parameter the below will mis-align the stack.  As was
+     suggested back in '96, better to let PUSH_ARGUMENTS handle it.  */
+  if (DEPRECATED_EXTRA_STACK_ALIGNMENT_NEEDED)
     {
       /* MVS 11/22/96: I think at least some of this stack_align code
-        is really broken.  Better to let PUSH_ARGUMENTS adjust the
+        is really broken.  Better to let push_dummy_call() adjust the
         stack in a target-defined manner.  */
       if (STACK_ALIGN_P () && INNER_THAN (1, 2))
        {
@@ -1605,15 +1622,30 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
 
          for (i = nargs - 1; i >= 0; i--)
            len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
-         if (CALL_DUMMY_STACK_ADJUST_P)
-           len += CALL_DUMMY_STACK_ADJUST;
+         if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+           len += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
          sp -= STACK_ALIGN (len) - len;
        }
     }
 
-  sp = PUSH_ARGUMENTS (nargs, args, sp, struct_return, struct_addr);
+  /* Create the dummy stack frame.  Pass in the call dummy address as,
+     presumably, the ABI code knows where, in the call dummy, the
+     return address should be pointed.  */
+  if (gdbarch_push_dummy_call_p (current_gdbarch))
+    /* When there is no push_dummy_call method, should this code
+       simply error out.  That would the implementation of this method
+       for all ABIs (which is probably a good thing).  */
+    sp = gdbarch_push_dummy_call (current_gdbarch, current_regcache,
+                                 dummy_addr, nargs, args, sp, struct_return,
+                                 struct_addr);
+  else  if (DEPRECATED_PUSH_ARGUMENTS_P ())
+    /* Keep old targets working.  */
+    sp = DEPRECATED_PUSH_ARGUMENTS (nargs, args, sp, struct_return,
+                                   struct_addr);
+  else
+    sp = legacy_push_arguments (nargs, args, sp, struct_return, struct_addr);
 
-  if (PUSH_RETURN_ADDRESS_P ())
+  if (DEPRECATED_PUSH_RETURN_ADDRESS_P ())
     /* for targets that use no CALL_DUMMY */
     /* There are a number of targets now which actually don't write
        any CALL_DUMMY instructions into the target, but instead just
@@ -1624,14 +1656,19 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
        return-address register as appropriate.  Formerly this has been
        done in PUSH_ARGUMENTS, but that's overloading its
        functionality a bit, so I'm making it explicit to do it here.  */
-    sp = PUSH_RETURN_ADDRESS (real_pc, sp);
+    sp = DEPRECATED_PUSH_RETURN_ADDRESS (real_pc, sp);
 
-  if (STACK_ALIGN_P () && !INNER_THAN (1, 2))
+  /* NOTE: cagney/2003-03-23: Diable this code when there is a
+     push_dummy_call() method.  Since that method will have already
+     handled any alignment issues, the code below is entirely
+     redundant.  */
+  if (!gdbarch_push_dummy_call_p (current_gdbarch)
+      && STACK_ALIGN_P () && !INNER_THAN (1, 2))
     {
       /* If stack grows up, we must leave a hole at the bottom, note
          that sp already has been advanced for the arguments!  */
-      if (CALL_DUMMY_STACK_ADJUST_P)
-       sp += CALL_DUMMY_STACK_ADJUST;
+      if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
+       sp += DEPRECATED_CALL_DUMMY_STACK_ADJUST;
       sp = STACK_ALIGN (sp);
     }
 
@@ -1640,30 +1677,31 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
   /* MVS 11/22/96: I think at least some of this stack_align code is
      really broken.  Better to let PUSH_ARGUMENTS adjust the stack in
      a target-defined manner.  */
-  if (CALL_DUMMY_STACK_ADJUST_P)
+  if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
     if (INNER_THAN (1, 2))
       {
        /* stack grows downward */
-       sp -= CALL_DUMMY_STACK_ADJUST;
+       sp -= DEPRECATED_CALL_DUMMY_STACK_ADJUST;
       }
 
   /* Store the address at which the structure is supposed to be
-     written.  Note that this (and the code which reserved the space
-     above) assumes that gcc was used to compile this function.  Since
-     it doesn't cost us anything but space and if the function is pcc
-     it will ignore this value, we will make that assumption.
-
-     Also note that on some machines (like the sparc) pcc uses a
-     convention like gcc's.  */
-
-  if (struct_return)
-    STORE_STRUCT_RETURN (struct_addr, sp);
+     written.  */
+  /* NOTE: 2003-03-24: Since PUSH_ARGUMENTS can (and typically does)
+     store the struct return address, this call is entirely redundant.  */
+  if (struct_return && DEPRECATED_STORE_STRUCT_RETURN_P ())
+    DEPRECATED_STORE_STRUCT_RETURN (struct_addr, sp);
 
   /* Write the stack pointer.  This is here because the statements above
      might fool with it.  On SPARC, this write also stores the register
      window into the right place in the new stack frame, which otherwise
      wouldn't happen.  (See store_inferior_registers in sparc-nat.c.)  */
-  write_sp (sp);
+  /* NOTE: cagney/2003-03-23: Disable this code when there is a
+     push_dummy_call() method.  Since that method will have already
+     stored the stack pointer (as part of creating the fake call
+     frame), and none of the code following that code adjusts the
+     stack-pointer value, the below call is entirely redundant.  */
+  if (DEPRECATED_DUMMY_WRITE_SP_P ())
+    DEPRECATED_DUMMY_WRITE_SP (sp);
 
   if (SAVE_DUMMY_FRAME_TOS_P ())
     SAVE_DUMMY_FRAME_TOS (sp);
@@ -1676,7 +1714,7 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
     symbol = find_pc_function (funaddr);
     if (symbol)
       {
-       name = SYMBOL_SOURCE_NAME (symbol);
+       name = SYMBOL_PRINT_NAME (symbol);
       }
     else
       {
@@ -1685,7 +1723,7 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
 
        if (msymbol)
          {
-           name = SYMBOL_SOURCE_NAME (msymbol);
+           name = SYMBOL_PRINT_NAME (msymbol);
          }
       }
     if (name == NULL)
@@ -1819,21 +1857,6 @@ the function call).", name);
   }
 }
 
-struct value *
-call_function_by_hand (struct value *function, int nargs, struct value **args)
-{
-  if (CALL_DUMMY_P)
-    {
-      return hand_function_call (function, nargs, args);
-    }
-  else
-    {
-      error ("Cannot invoke functions on this machine.");
-    }
-}
-\f
-
-
 /* Create a value for an array by allocating space in the inferior, copying
    the data into that space, and then setting up an array value.
 
@@ -2753,7 +2776,7 @@ find_overload_match (struct type **arg_types, int nargs, char *name, int method,
   else
     {
       int i = -1;
-      func_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_NO_OPTS);
+      func_name = cplus_demangle (DEPRECATED_SYMBOL_NAME (fsym), DMGL_NO_OPTS);
 
       /* If the name is NULL this must be a C-style function.
          Just return the same symbol. */
This page took 0.029689 seconds and 4 git commands to generate.