frame.h (ia64_frame_state): Add my_psp.
authorRichard Henderson <rth@cygnus.com>
Tue, 8 Aug 2000 09:08:55 +0000 (02:08 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 8 Aug 2000 09:08:55 +0000 (02:08 -0700)
        * frame.h (ia64_frame_state): Add my_psp.
        * libgcc2.c (ia64_throw_helper): Add throw_sp argument.
        (__throw): Pass it in.  Don't clobber r7.
        * config/ia64/frame-ia64.c (init_ia64_reg_loc): Mark inline.
        (execute_one_ia64_descriptor) [mem_stack_v]: Sets psp.when
        and nothing to do with sp.
        (normalize_reg_loc): Use frame->my_psp.
        (frame_translate): Handle frame-pointer-less functions.  Set
        spill_base correctly, in absence of being told.
        (__build_ia64_frame_state): New sp argument.  Fill in frame->my_sp.
        (__ia64_backtrace_helper): New sp argument.  Use
        builtin_return_address instead of label addresses.
        (print_record) [mem_stack_v]: No size member.

From-SVN: r35565

gcc/ChangeLog
gcc/config/ia64/frame-ia64.c
gcc/frame.h
gcc/libgcc2.c

index 8b6db106efd815b97a2ba07bb064a3a84f2a1dd8..52dbb268080163cf7696ba896410865e3bb7c48b 100644 (file)
@@ -1,3 +1,23 @@
+2000-08-08  Richard Henderson  <rth@cygnus.com>
+
+       * frame.h (ia64_frame_state): Add my_psp.
+       * libgcc2.c (ia64_throw_helper): Add throw_sp argument.
+       (__throw): Pass it in.  Don't clobber r7.
+       * config/ia64/frame-ia64.c (init_ia64_reg_loc): Mark inline.
+       (execute_one_ia64_descriptor) [mem_stack_v]: Sets psp.when
+       and nothing to do with sp.
+       (normalize_reg_loc): Use frame->my_psp.
+       (frame_translate): Handle frame-pointer-less functions.  Set
+       spill_base correctly, in absence of being told.
+       (__build_ia64_frame_state): New sp argument.  Fill in frame->my_sp.
+       (__ia64_backtrace_helper): New sp argument.  Use
+       builtin_return_address instead of label addresses.
+       (print_record) [mem_stack_v]: No size member.
+
+2000-08-08  Richard Henderson  <rth@cygnus.com>
+
+       * regclass.c (choose_hard_reg_mode): Iterate over all CC modes.
+
 2000-08-08  Richard Henderson  <rth@cygnus.com>
 
        * tm.texi (LOCAL_REGNO): Document.
index 4ff78dd4a4dcdd0ac84138bea0274be165c8a27a..efddd9f08bb7957706e87b33af867c1622b635c8 100644 (file)
@@ -678,7 +678,7 @@ read_P_record (data, val, ptr, header)
 /* Frame processing routines.  */
 
 /* Initialize a single register structure.  */
-static void 
+static inline void 
 init_ia64_reg_loc (reg, size)
      ia64_reg_loc *reg;
      short size;
@@ -692,7 +692,7 @@ init_ia64_reg_loc (reg, size)
 /* Iniitialize an entire frame to the default of nothing.  */
 static void
 init_ia64_unwind_frame (frame) 
-     ia64_frame_state *frame ;
+     ia64_frame_state *frame;
 {
   int x;
   
@@ -741,7 +741,7 @@ execute_one_ia64_descriptor (addr, frame, len)
   *len = -1;
   addr = get_unwind_record (&region_header, &r, addr);
 
-  /* process it in 2 phases, the first phase will either do the work,
+  /* Process it in 2 phases, the first phase will either do the work,
      or set up a pointer to the records we care about 
      (ie a special purpose ar perhaps, and the second will actually 
      fill in the record.  */
@@ -787,10 +787,12 @@ execute_one_ia64_descriptor (addr, frame, len)
          break;
        }
       case mem_stack_f:
-      case mem_stack_v:
-        frame->sp.when = r.record.p.t; 
        frame->sp.l.offset = r.record.p.size;
        frame->sp.loc_type = IA64_UNW_LOC_TYPE_OFFSET;
+        frame->sp.when = r.record.p.t; 
+       break;
+      case mem_stack_v:
+       frame->psp.when = r.record.p.t;
        break;
       case psp_gr:
       case psp_sprel:
@@ -1091,7 +1093,7 @@ normalize_reg_loc (frame, reg)
       case IA64_UNW_LOC_TYPE_BR:
         break;
       case IA64_UNW_LOC_TYPE_SPOFF:
-        /* offset from the stack pointer, calculate the memory address
+        /* Offset from the stack pointer, calculate the memory address
           now.  */
        tmp = (unsigned char *)frame->my_sp + reg->l.offset * 4;
        reg->l.mem = tmp;
@@ -1100,7 +1102,7 @@ normalize_reg_loc (frame, reg)
       case IA64_UNW_LOC_TYPE_PSPOFF:
         /* Actualy go get the value of the PSP add the offset, and thats 
           the mem location we can find this value at. */
-       tmp = (*(unsigned char **)(frame->psp.l.mem)) + 16 - reg->l.offset * 4;
+       tmp = (unsigned char *)frame->my_psp + 16 - reg->l.offset * 4;
        reg->l.mem = tmp;
        reg->loc_type = IA64_UNW_LOC_TYPE_MEM;
         break;
@@ -1114,7 +1116,8 @@ normalize_reg_loc (frame, reg)
     }
 
 }
-/* this function looks at a reg_loc and determines if its going
+
+/* This function looks at a reg_loc and determines if its going
    to be an executed record or not between time start and end.  
    It is executed if it is exectued at START time. It is NOT
    executed if it happens at END time. */
@@ -1173,7 +1176,7 @@ copy_reg_value (src, dest)
   else
     {
       void **d;
-      if (src->reg_size> 16)
+      if (src->reg_size > 16)
         abort ();
       if (dest->loc_type != IA64_UNW_LOC_TYPE_MEM)
         abort ();
@@ -1218,7 +1221,9 @@ process_state_between (frame, start, end)
   /* PSP, RP, SP, and PFS are handled seperately from here. */
 
   /* GR's, FR's and BR's are saved at an arbitrary point, so we
-      should handle them at teh very beginning.  */
+     should handle them at the very beginning.  */
+  /* ??? Err, no they aren't.  There's the spill_mask record that
+     tells us when each is processed.  */
   if (start == 0)
     {
       for (x = 0; x < 4 ; x++)
@@ -1252,25 +1257,52 @@ frame_translate (frame, unwind_time)
      ia64_frame_state *frame;
      long unwind_time;
 {
-  /* First, establish values of PFS and PSP and RP, if needed.  */
-
-  normalize_reg_loc (frame, &frame->pfs);
-  normalize_reg_loc (frame, &frame->psp);
-  normalize_reg_loc (frame, &frame->rp);
+  /* ??? Is this supposed to mark the end of the stack?  */
   if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE)
     return;
 
-  /* The stack pointer at the function start is the PSP value
-     saved away.  */
-  frame->my_sp = __get_real_reg_value (&frame->psp);
+  /* At function entry, SP == PSP.  */
+  frame->my_psp = frame->my_sp;
+  if (frame->psp.loc_type != IA64_UNW_LOC_TYPE_NONE)
+    {
+      /* We've saved a frame pointer somewhere.  This will be the
+        canonical PSP for the function.  */
+      normalize_reg_loc (frame, &frame->psp);
+      if (frame->psp.when < unwind_time)
+       frame->my_psp = __get_real_reg_value (&frame->psp);
+    }
+  else if (frame->sp.loc_type == IA64_UNW_LOC_TYPE_OFFSET)
+    {
+      /* We've a fixed sized stack frame.  The PSP is at a known offset.  */
+       
+      if (frame->sp.when < unwind_time)
+        frame->my_psp = frame->my_sp + frame->sp.l.offset;
+    }
+  /* Otherwise the stack frame size was zero and no adjustment needed.  */
 
-  if (frame->psp.loc_type != IA64_UNW_LOC_TYPE_MEM)
-    abort ();
+  /* Find PFS, RP and the spill base.  All of which might have
+     addresses based off the PSP computed above.  */
+  normalize_reg_loc (frame, &frame->pfs);
+  normalize_reg_loc (frame, &frame->rp);
 
-  /* spill base is set up off the PSP register, which should now 
-     have its value. */
-  normalize_reg_loc (frame, &frame->spill_base);
+  if (frame->spill_base.loc_type != IA64_UNW_LOC_TYPE_NONE)
+    normalize_reg_loc (frame, &frame->spill_base);
+  else
+    {
+      /* Otherwise we're supposed to infer it from the size of the
+        saved GR/BR/FR registers, putting the top at psp+16.  */
+      long size = 0, i;
+      for (i = 0; i < 4; ++i)
+       if (frame->gr[i].when >= 0)
+         size += 8;
+      for (i = 0; i < 5; ++i)
+       if (frame->br[i].when >= 0)
+         size += 8;
+      for (i = 0; i < 20; ++i)
+       if (frame->fr[i].when >= 0)
+         size += 16;
+      frame->spill_base.l.mem = frame->my_psp + 16 - size;
+    }
 
   /* If the SP is adjusted, process records up to where it
      is adjusted, then adjust it, then process the rest.  */
@@ -1279,24 +1311,23 @@ frame_translate (frame, unwind_time)
       process_state_between (frame, 0, frame->sp.when);
       if (frame->sp.loc_type != IA64_UNW_LOC_TYPE_OFFSET)
        abort ();
-      frame->my_sp = 
-             (unsigned char *)frame->my_sp - frame->sp.l.offset;
+      frame->my_sp = frame->my_psp - frame->sp.l.offset;
       process_state_between (frame, frame->sp.when, unwind_time);
     }
   else
     process_state_between (frame, 0, unwind_time);
 }
 
-/* this function will set a frame_state with all the required fields
+/* This function will set a frame_state with all the required fields
    from a functions unwind descriptors.
    pc is the location we need info up until (ie, the unwind point)
    frame is the frame_state structure to be set up.
    Returns a pointer to the unwind info pointer for the frame.  */
 unwind_info_ptr *
-__build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
+__build_ia64_frame_state (pc, frame, bsp, sp, pc_base_ptr)
      unsigned char *pc;
      ia64_frame_state *frame;
-     void *bsp;
+     void *bsp, *sp;
      void **pc_base_ptr;
 {
   long len;
@@ -1321,8 +1352,9 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
 
   init_ia64_unwind_frame (frame);
   frame->my_bsp = bsp;
+  frame->my_sp = sp;
 
-  /* stop when we get to the end of the descriptor list, or if we
+  /* Stop when we get to the end of the descriptor list, or if we
      encounter a region whose initial offset is already past the
      PC we are unwinding too.  */
 
@@ -1336,6 +1368,7 @@ __build_ia64_frame_state (pc, frame, bsp, pc_base_ptr)
          last_region_size = len;
        }
     }
+
   /* Now we go get the actual values.  */
   frame_translate (frame, pc_offset);
   if (pc_base_ptr)
@@ -1385,10 +1418,10 @@ __calc_caller_bsp (pfs, bsp)
 }
 
 static int 
-ia64_backtrace_helper (void **array, void *throw_pc, 
-                      ia64_frame_state *throw_frame,
-                      ia64_frame_state *frame, void *bsp, int size)
+ia64_backtrace_helper (void **array, ia64_frame_state *throw_frame,
+                      ia64_frame_state *frame, void *bsp, void *sp, int size)
 {
+  void *throw_pc = __builtin_return_address (0);
   void *pc = NULL;
   int frame_count = 0;
   unwind_info_ptr *info;
@@ -1396,7 +1429,7 @@ ia64_backtrace_helper (void **array, void *throw_pc,
   __builtin_ia64_flushrs ();      /*  Make the local register stacks available.  */
 
   /* Start at our stack frame, get our state.  */
-  info = __build_ia64_frame_state (throw_pc, throw_frame, bsp, NULL);
+  info = __build_ia64_frame_state (throw_pc, throw_frame, bsp, sp, NULL);
 
   *frame = *throw_frame;
 
@@ -1406,7 +1439,7 @@ ia64_backtrace_helper (void **array, void *throw_pc,
       --pc;
       bsp = __calc_caller_bsp 
        ((long)__get_real_reg_value (&frame->pfs), frame->my_bsp);
-      info = __build_ia64_frame_state (pc, frame, bsp, NULL);
+      info = __build_ia64_frame_state (pc, frame, bsp, frame->my_psp, NULL);
       if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE) /* We've finished. */
        break;
     }
@@ -1419,6 +1452,7 @@ ia64_backtrace_helper (void **array, void *throw_pc,
 int
 __ia64_backtrace (void **array, int size)
 {
+  register void *stack_pointer __asm__("r12");
   ia64_frame_state my_frame;
   ia64_frame_state originator; /* For the context handler is in.  */
   void *bsp;
@@ -1428,11 +1462,10 @@ __ia64_backtrace (void **array, int size)
      registers. */
   __builtin_unwind_init ();
 
-label_ia64:
   bsp = __builtin_ia64_bsp ();
   
-  return ia64_backtrace_helper (array, &&label_ia64, &my_frame, 
-                               &originator, bsp, size);
+  return ia64_backtrace_helper (array, &my_frame, &originator, bsp,
+                               stack_pointer, size);
 }
 
 \f
@@ -1482,10 +1515,12 @@ print_record (f, ptr)
                                                 ptr->record.r.grsave);
        break;
       case mem_stack_f:
-      case mem_stack_v:
        fprintf (f, "(P7) t = %d, size = %d", ptr->record.p.t, 
                                         ptr->record.p.size);
        break;
+      case mem_stack_v:
+       fprintf (f, "(P7) t = %d", ptr->record.p.t);
+       break;
       case psp_gr:
       case rp_gr:
       case pfs_gr:
index dc445612d93d4d15785ced6491f599b63bb579de..472d358327c6baf465b92f3207b2a72dccfb1342 100644 (file)
@@ -248,6 +248,7 @@ typedef struct ia64_frame_state
   ia64_reg_loc sp;
   ia64_reg_loc psp;
   ia64_reg_loc spill_base;
+  void *my_psp;
   void *my_sp;
   void *my_bsp;
 } ia64_frame_state;
@@ -267,7 +268,8 @@ typedef struct unwind_info_ptr
 #define IA64_UNW_HDR_VERSION(x)        (((x) >> 48) & 0xffffUL)
 
 extern unwind_info_ptr *__build_ia64_frame_state (unsigned char *, 
-                                                 ia64_frame_state *, void *,
+                                                 ia64_frame_state *,
+                                                 void *, void *,
                                                  void **);
 extern void *__get_real_reg_value (ia64_reg_loc *);
 extern void *__get_personality (unwind_info_ptr *);
index 6403676adb4544700a18b9f9eb8a98920c0d508c..616338613811190095d86a5aaceec022f000dd1c 100644 (file)
@@ -4046,10 +4046,8 @@ __ia64_personality_v1 (void *pc, old_exception_table *table)
 }
 
 static void
-ia64_throw_helper (throw_frame, caller, throw_bsp)
-     ia64_frame_state *throw_frame;
-     ia64_frame_state *caller;
-     void *throw_bsp;
+ia64_throw_helper (ia64_frame_state *throw_frame, ia64_frame_state *caller,
+                  void *throw_bsp, void *throw_sp)
 {
   void *throw_pc = __builtin_return_address (0);
   unwind_info_ptr *info;
@@ -4061,7 +4059,8 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
   __builtin_ia64_flushrs ();      /*  Make the local register stacks available.  */
 
   /* Start at our stack frame, get our state.  */
-  __build_ia64_frame_state (throw_pc, throw_frame, throw_bsp, &pc_base);
+  __build_ia64_frame_state (throw_pc, throw_frame, throw_bsp, throw_sp,
+                           &pc_base);
 
   /* Now we have to find the proper frame for pc, and see if there
      is a handler for it. if not, we keep going back frames until
@@ -4078,8 +4077,10 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
       /* We only care about the RP right now, so we dont need to keep
          any other information about a call frame right now.  */
       pc = __get_real_reg_value (&caller->rp) - 1;
-      bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs), caller->my_bsp);
-      info = __build_ia64_frame_state (pc, caller, bsp, &pc_base);
+      bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs),
+                              caller->my_bsp);
+      info = __build_ia64_frame_state (pc, caller, bsp, caller->my_psp,
+                                      &pc_base);
 
       /* If we couldn't find the next frame, we lose.  */
       if (! info)
@@ -4099,7 +4100,7 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
     }
   
   if (!handler)
-   __terminate ();
+    __terminate ();
 
   /* Handler is a segment relative address, so we must adjust it here.  */
   handler += (long) pc_base;
@@ -4116,8 +4117,9 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
   for ( ; frame_count > 0; frame_count--)
     {
       pc = __get_real_reg_value (&caller->rp) - 1;
-      bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs), caller->my_bsp);
-      __build_ia64_frame_state (pc, caller, bsp, &pc_base);
+      bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs),
+                              caller->my_bsp);
+      __build_ia64_frame_state (pc, caller, bsp, caller->my_psp, &pc_base);
       /* Any regs that were saved can be put in the throw frame now.  */
       /* We don't want to copy any saved register from the 
          target destination, but we do want to load up it's frame.  */
@@ -4130,12 +4132,13 @@ ia64_throw_helper (throw_frame, caller, throw_bsp)
 
   /* TODO, do we need to do anything to make the values we wrote 'stick'? */
   /* DO we need to go through the whole loadrs seqeunce?  */
-
 }
 
+
 void
 __throw ()
 {
+  register void *stack_pointer __asm__("r12");
   struct eh_context *eh = (*get_eh_context) ();
   ia64_frame_state my_frame;
   ia64_frame_state originator; /* For the context handler is in.  */
@@ -4149,6 +4152,7 @@ __throw ()
     __terminate ();
 
   __builtin_unwind_init ();
+
   /* We have to call another routine to actually process the frame 
      information, which will force all of __throw's local registers into
      backing store.  */
@@ -4156,7 +4160,7 @@ __throw ()
   /* Get the value of ar.bsp while we're here.  */
 
   bsp = __builtin_ia64_bsp ();
-  ia64_throw_helper (&my_frame, &originator, bsp);
+  ia64_throw_helper (&my_frame, &originator, bsp, stack_pointer);
 
   /* Now we have to fudge the bsp by the amount in our (__throw)
      frame marker, since the return is going to adjust it by that much. */
@@ -4166,11 +4170,6 @@ __throw ()
   offset = (char *)my_frame.my_bsp - (char *)tmp_bsp;
   tmp_bsp = (char *)originator.my_bsp + offset;
 
-  /* A throw handler is trated like a  non-local goto, which is architeched
-     to set the FP (or PSP) in r7 before branching.  gr[0-3] map to 
-     r4-r7, so we want gr[3].  */
-  __set_real_reg_value (&my_frame.gr[3], __get_real_reg_value (&originator.psp));
-
   __builtin_eh_return (tmp_bsp, offset, originator.my_sp);
 
   /* The return address was already set by throw_helper.  */