This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Don't use lib2funcs.asm on PA


>  It is very likely that what you are seeing is related to some problems we
>  also "experimented". In the current state of things, we have added an
>  eh_return pattern to the machine description and a "for_eh_return" argument
>  to hppa_expand_epilogue. 

Thanks for the input.  The stack adjust was one thing that was missing.
Last night, I arrived at a set of modifications that allow the "stdexceptions"
test in libstdc++ to PASS when linked statically.  It still doesn't work
when linked with a shared libstdc++.  There were also more issues with the
frame note code and saving and restoring the eh data registers.

I believe that we need an eh_return pattern and use an interspace jump
to return from shared code.  I also need to figure out if an eh_return
can return a value.  If it can then the data registers need to be revised.
Now on the PA, external calls usually go via a stub.  One of the functions
of the stub is to message the outgoing arguments and the return value
so that the caller and callee agree on their location.  There could be
a problem with return values because I suspect we bypass the stub on
an eh_return.

I enclosed my latest work.  Comments appreciated.  I am going to try
to looked at the shared return today.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

Index: config/pa/pa-linux.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa-linux.h,v
retrieving revision 1.12
diff -u -3 -p -r1.12 pa-linux.h
--- config/pa/pa-linux.h	15 Feb 2002 19:11:01 -0000	1.12
+++ config/pa/pa-linux.h	18 Feb 2002 04:32:28 -0000
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA.  */
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 #define DWARF2_ASM_LINE_DEBUG_INFO 1
 #define DWARF2_UNWIND_INFO 1
+#define ARG_POINTER_CFA_OFFSET(FNDECL) 0
 
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES "-D__ELF__ -Dunix -D__hppa__ -Dlinux -Asystem=unix -Asystem=posix -Acpu=hppa -Amachine=hppa -Amachine=bigendian"
Index: config/pa/pa.md
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa.md,v
retrieving revision 1.101
diff -u -3 -p -r1.101 pa.md
--- config/pa/pa.md	4 Feb 2002 21:05:25 -0000	1.101
+++ config/pa/pa.md	18 Feb 2002 04:32:29 -0000
@@ -7216,14 +7216,12 @@
 ;; restore the PIC register.
 (define_expand "exception_receiver"
   [(const_int 4)]
-  "!TARGET_PORTABLE_RUNTIME && flag_pic"
+  "flag_pic"
   "
 {
-  /* Load the PIC register from the stack slot (in our caller's
-     frame).  */
-  emit_move_insn (pic_offset_table_rtx,
-		  gen_rtx_MEM (SImode,
-			       plus_constant (stack_pointer_rtx, -32)));
+  /* Restore the PIC register using hppa_pic_save_rtx ().  The
+     PIC register is not saved in the frame in 64-bit ABI.  */
+  emit_move_insn (pic_offset_table_rtx, hppa_pic_save_rtx ());
   emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
   emit_insn (gen_blockage ());
   DONE;
Index: config/pa/pa.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.148
diff -u -3 -p -r1.148 pa.c
--- config/pa/pa.c	12 Feb 2002 15:21:04 -0000	1.148
+++ config/pa/pa.c	18 Feb 2002 04:32:30 -0000
@@ -55,18 +55,6 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif
 
-#if DO_FRAME_NOTES
-#define FRP(INSN) \
-  do					\
-    {					\
-      rtx insn = INSN;			\
-      RTX_FRAME_RELATED_P (insn) = 1;	\
-    }					\
-  while (0)
-#else
-#define FRP(INSN) INSN
-#endif
-
 #ifndef FUNC_BEGIN_PROLOG_LABEL
 #define FUNC_BEGIN_PROLOG_LABEL        "LFBP"
 #endif
@@ -83,6 +71,7 @@ static int compute_movstrsi_length PARAM
 static bool pa_assemble_integer PARAMS ((rtx, unsigned int, int));
 static void remove_useless_addtr_insns PARAMS ((rtx, int));
 static void store_reg PARAMS ((int, int, int));
+static void store_reg_modify PARAMS ((int, int, int));
 static void load_reg PARAMS ((int, int, int));
 static void set_reg_plus_d PARAMS ((int, int, int));
 static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
@@ -2662,7 +2651,7 @@ output_ascii (file, p, size)
 	  fputs ("\"\n\t.STRING \"", file);
 	  chars_output = 0;
 	}
-      fwrite (partial_output, 1, co, file);
+      fwrite (partial_output, 1, (size_t) co, file);
       chars_output += co;
       co = 0;
     }
@@ -2933,6 +2922,50 @@ store_reg (reg, disp, base)
     RTX_FRAME_RELATED_P (insn) = 1;
 }
 
+/* Emit RTL to store REG at the memory location specified by BASE and then
+   add MOD to BASE.  MOD must be <= 8k.  */
+
+static void
+store_reg_modify (base, reg, mod)
+     int base, reg, mod;
+{
+  rtx insn, basereg, srcreg, delta;
+
+  if (! VAL_14_BITS_P (mod))
+    abort ();
+
+  basereg = gen_rtx_REG (Pmode, base);
+  srcreg = gen_rtx_REG (word_mode, reg);
+  delta = GEN_INT (mod);
+
+  insn = emit_insn (gen_post_store (basereg, srcreg, delta));
+  if (DO_FRAME_NOTES)
+    {
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      /* RTX_FRAME_RELATED_P must be set on each frame related set
+	 in a parallel with more than one element.  Don't set
+	 RTX_FRAME_RELATED_P in the first set if reg is temporary
+	 register 1. The effect of this operation is recorded in
+	 the initial copy.  */
+      if (reg != 1)
+	{
+	  RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 0)) = 1;
+	  RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
+	}
+      else
+	{
+	  /* The first element of a PARALLEL is always processed if it is
+	     a SET.  Thus, we need an expression list for this case.  */
+	  REG_NOTES (insn)
+	    = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+		gen_rtx_SET (VOIDmode, basereg,
+			     gen_rtx_PLUS (word_mode, basereg, delta)),
+                REG_NOTES (insn));
+	}
+    }
+}
+
 /* Emit RTL to set REG to the value specified by BASE+DISP.
    Handle case where DISP > 8k by using the add_high_const patterns.
 
@@ -2981,6 +3014,18 @@ compute_frame_size (size, fregs_live)
      of them at the same time.  */
   fsize = size + (size || frame_pointer_needed ? STARTING_FRAME_OFFSET : 0);
 
+  /* If the current function calls __builtin_eh_return, then we need
+     to allocate stack space for registers that will hold data for
+     the exception handler.  */
+  if (DO_FRAME_NOTES && current_function_calls_eh_return)
+    {
+      unsigned int i;
+
+      for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
+	continue;
+      fsize += i * UNITS_PER_WORD;
+    }
+
   /* Account for space used by the callee general register saves.  */
   for (i = 18; i >= 3; i--)
     if (regs_ever_live[i])
@@ -3108,7 +3153,7 @@ hppa_expand_prologue ()
   int size = get_frame_size ();
   int merge_sp_adjust_with_store = 0;
   int i, offset;
-  rtx tmpreg, size_rtx;
+  rtx insn, tmpreg;
 
   gr_saved = 0;
   fr_saved = 0;
@@ -3126,7 +3171,6 @@ hppa_expand_prologue ()
 
   /* Compute a few things we will use often.  */
   tmpreg = gen_rtx_REG (word_mode, 1);
-  size_rtx = GEN_INT (actual_fsize);
 
   /* Save RP first.  The calling conventions manual states RP will
      always be stored into the caller's frame at sp - 20 or sp - 16
@@ -3141,36 +3185,30 @@ hppa_expand_prologue ()
 	{
 	  /* Copy the old frame pointer temporarily into %r1.  Set up the
 	     new stack pointer, then store away the saved old frame pointer
-	     into the stack at sp+actual_fsize and at the same time update
-	     the stack pointer by actual_fsize bytes.  Two versions, first
+	     into the stack at sp and at the same time update the stack
+	     pointer by actual_fsize bytes.  Two versions, first
 	     handles small (<8k) frames.  The second handles large (>=8k)
 	     frames.  */
-	  emit_move_insn (tmpreg, frame_pointer_rtx);
-	  FRP (emit_move_insn (frame_pointer_rtx, stack_pointer_rtx));
-	  if (VAL_14_BITS_P (actual_fsize))
+	  insn = emit_move_insn (tmpreg, frame_pointer_rtx);
+	  if (DO_FRAME_NOTES)
 	    {
-	      rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
-						    size_rtx));
-	      if (DO_FRAME_NOTES)
-		{
-		  rtvec vec;
-		  RTX_FRAME_RELATED_P (insn) = 1;
-		  vec = gen_rtvec (2,
-				   gen_rtx_SET (VOIDmode,
-						gen_rtx_MEM (word_mode,
-							     stack_pointer_rtx),
-						frame_pointer_rtx),
-				   gen_rtx_SET (VOIDmode,
-						stack_pointer_rtx,
-						gen_rtx_PLUS (word_mode,
-							      stack_pointer_rtx,
-							      size_rtx)));
-		  REG_NOTES (insn)
-		    = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-					 gen_rtx_SEQUENCE (VOIDmode, vec),
-					 REG_NOTES (insn));
-		}
-	    }
+	      /* We need to record the frame pointer save here since the
+	         new frame pointer is set in the following insn.  */
+	      RTX_FRAME_RELATED_P (insn) = 1;
+	      REG_NOTES (insn)
+		= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+		    gen_rtx_SET (VOIDmode,
+				 gen_rtx_MEM (word_mode, stack_pointer_rtx),
+			         frame_pointer_rtx),
+		    REG_NOTES (insn));
+	    }
+
+	  insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+	  if (DO_FRAME_NOTES)
+	    RTX_FRAME_RELATED_P (insn) = 1;
+
+	  if (VAL_14_BITS_P (actual_fsize))
+	    store_reg_modify (STACK_POINTER_REGNUM, 1, actual_fsize);
 	  else
 	    {
 	      /* It is incorrect to store the saved frame pointer at *sp,
@@ -3181,32 +3219,12 @@ hppa_expand_prologue ()
 		 finish allocating the new frame.  */
 	      int adjust1 = 8192 - 64;
 	      int adjust2 = actual_fsize - adjust1;
-	      rtx delta = GEN_INT (adjust1);
-	      rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
-						    delta));
-	      if (DO_FRAME_NOTES)
-		{
-		  rtvec vec;
-		  RTX_FRAME_RELATED_P (insn) = 1;
-		  vec = gen_rtvec (2,
-				   gen_rtx_SET (VOIDmode,
-						gen_rtx_MEM (word_mode,
-							     stack_pointer_rtx),
-						frame_pointer_rtx),
-				   gen_rtx_SET (VOIDmode,
-						stack_pointer_rtx,
-						gen_rtx_PLUS (word_mode,
-							      stack_pointer_rtx,
-							      delta)));
-		  REG_NOTES (insn)
-		    = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-					 gen_rtx_SEQUENCE (VOIDmode, vec),
-					 REG_NOTES (insn));
-		}
 
+	      store_reg_modify (STACK_POINTER_REGNUM, 1, adjust1);
 	      set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
 			      adjust2);
 	    }
+
 	  /* Prevent register spills from being scheduled before the
 	     stack pointer is raised.  Necessary as we will be storing
 	     registers using the frame pointer as a base register, and
@@ -3236,7 +3254,27 @@ hppa_expand_prologue ()
      was done earlier.  */
   if (frame_pointer_needed)
     {
-      for (i = 18, offset = local_fsize; i >= 4; i--)
+      offset = local_fsize;
+
+      /* Saving the EH return data registers in the frame is the simplest
+         way to get the frame unwind information emitted.  We put them
+	 just before the general registers.  */
+      if (DO_FRAME_NOTES && current_function_calls_eh_return)
+	{
+	  unsigned int i, regno;
+
+	  for (i = 0; ; ++i)
+	    {
+	      regno = EH_RETURN_DATA_REGNO (i);
+	      if (regno == INVALID_REGNUM)
+		break;
+
+	      store_reg (regno, offset, FRAME_POINTER_REGNUM);
+	      offset += UNITS_PER_WORD;
+	    }
+	}
+
+      for (i = 18; i >= 4; i--)
 	if (regs_ever_live[i] && ! call_used_regs[i])
 	  {
 	    store_reg (i, offset, FRAME_POINTER_REGNUM);
@@ -3249,18 +3287,42 @@ hppa_expand_prologue ()
   /* No frame pointer needed.  */
   else
     {
-      for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
+      offset = local_fsize - actual_fsize;
+
+      /* Saving the EH return data registers in the frame is the simplest
+         way to get the frame unwind information emitted.  */
+      if (DO_FRAME_NOTES && current_function_calls_eh_return)
+	{
+	  unsigned int i, regno;
+
+	  for (i = 0; ; ++i)
+	    {
+	      regno = EH_RETURN_DATA_REGNO (i);
+	      if (regno == INVALID_REGNUM)
+		break;
+
+	      /* If merge_sp_adjust_with_store is nonzero, then we can
+		 optimize the first save.  */
+	      if (merge_sp_adjust_with_store)
+		{
+		  store_reg_modify (STACK_POINTER_REGNUM, regno, -offset);
+		  merge_sp_adjust_with_store = 0;
+		}
+	      else
+		store_reg (regno, offset, STACK_POINTER_REGNUM);
+	      offset += UNITS_PER_WORD;
+	    }
+	}
+
+      for (i = 18; i >= 3; i--)
       	if (regs_ever_live[i] && ! call_used_regs[i])
 	  {
 	    /* If merge_sp_adjust_with_store is nonzero, then we can
 	       optimize the first GR save.  */
 	    if (merge_sp_adjust_with_store)
 	      {
-		rtx delta = GEN_INT (-offset);
+		store_reg_modify (STACK_POINTER_REGNUM, i, -offset);
 		merge_sp_adjust_with_store = 0;
-	        FRP (emit_insn (gen_post_store (stack_pointer_rtx,
-						gen_rtx_REG (word_mode, i),
-						delta)));
 	      }
 	    else
 	      store_reg (i, offset, STACK_POINTER_REGNUM);
@@ -3290,12 +3352,20 @@ hppa_expand_prologue ()
   /* Floating point register store.  */
   if (save_fregs)
     {
+      rtx base;
+
       /* First get the frame or stack pointer to the start of the FP register
 	 save area.  */
       if (frame_pointer_needed)
-	set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
+	{
+	  set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
+	  base = frame_pointer_rtx;
+	}
       else
-	set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
+	{
+	  set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
+	  base = stack_pointer_rtx;
+	}
 
       /* Now actually save the FP registers.  */
       for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
@@ -3313,9 +3383,7 @@ hppa_expand_prologue ()
 		  REG_NOTES (insn)
 		    = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
 			gen_rtx_SET (VOIDmode,
-			  gen_rtx_MEM (DFmode,
-				       plus_constant (stack_pointer_rtx,
-						      offset)),
+			  gen_rtx_MEM (DFmode, plus_constant (base, offset)),
 			  reg),
 			REG_NOTES (insn));
 		}
@@ -3429,7 +3497,26 @@ hppa_expand_epilogue ()
   /* General register restores.  */
   if (frame_pointer_needed)
     {
-      for (i = 18, offset = local_fsize; i >= 4; i--)
+      offset = local_fsize;
+
+      /* If the current function calls __builtin_eh_return, then we need
+         to restore the saved EH data registers.  */
+      if (DO_FRAME_NOTES && current_function_calls_eh_return)
+	{
+	  unsigned int i, regno;
+
+	  for (i = 0; ; ++i)
+	    {
+	      regno = EH_RETURN_DATA_REGNO (i);
+	      if (regno == INVALID_REGNUM)
+		break;
+
+	      load_reg (regno, offset, FRAME_POINTER_REGNUM);
+	      offset += UNITS_PER_WORD;
+	    }
+	}
+
+      for (i = 18; i >= 4; i--)
 	if (regs_ever_live[i] && ! call_used_regs[i])
 	  {
 	    load_reg (i, offset, FRAME_POINTER_REGNUM);
@@ -3438,6 +3525,33 @@ hppa_expand_epilogue ()
     }
   else
     {
+      offset = local_fsize - actual_fsize;
+
+      /* If the current function calls __builtin_eh_return, then we need
+         to restore the saved EH data registers.  */
+      if (DO_FRAME_NOTES && current_function_calls_eh_return)
+	{
+	  unsigned int i, regno;
+
+	  for (i = 0; ; ++i)
+	    {
+	      regno = EH_RETURN_DATA_REGNO (i);
+	      if (regno == INVALID_REGNUM)
+		break;
+
+	      /* Only for the first load.
+	         merge_sp_adjust_with_load holds the register load
+	         with which we will merge the sp adjustment.  */
+	      if (merge_sp_adjust_with_load == 0
+		  && local_fsize == 0
+		  && VAL_14_BITS_P (-actual_fsize))
+	        merge_sp_adjust_with_load = regno;
+	      else
+		load_reg (regno, offset, STACK_POINTER_REGNUM);
+	      offset += UNITS_PER_WORD;
+	    }
+	}
+
       for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
 	{
 	  if (regs_ever_live[i] && ! call_used_regs[i])
@@ -3525,6 +3639,14 @@ hppa_expand_epilogue ()
     }
   else if (actual_fsize != 0)
     set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, - actual_fsize);
+
+  if (DO_FRAME_NOTES && current_function_calls_eh_return)
+    {
+      rtx sa = EH_RETURN_STACKADJ_RTX;
+      emit_insn (Pmode == SImode
+		 ? gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, sa)
+		 : gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, sa));
+    }
 
   /* If we haven't restored %r2 yet (no frame pointer, and a stack
      frame greater than 8k), do so now.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]