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]

IA-64 function epilogue unwind support


This adds unwind support for function epilogues.  This is needed by the
linux kernel stack frame unwinder.  This requires the gas change I made
earlier today.

2000-06-08  James E. Wilson  <wilson@bletchleypark.cygnus.com>

	* config/ia64/ia64-protos.h (ia64_output_end_prologue): Add.
	(output_function_prologue): Fix mispelling.
	(output_function_prologue, output_function_epilogue): Reorder to
	match ia64.c definition order.
	* config/ia64/ia64.c (ia64_expand_prologue): Add comment.
	(ia64_expand_epilogue): Set RTX_FRAME_RELATED_P on stack restore insns.
	Use r3 instead of r2 for large stack restores.
	(ia64_output_end_prologue): New function.
	(process_set): Emit ".restore sp" for epilogue stack restores.
	* config/ia64/ia64.h (FUNCTION_END_PROLOGUE): Define.
	
Index: ia64-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64-protos.h,v
retrieving revision 1.7
diff -p -r1.7 ia64-protos.h
*** ia64-protos.h	2000/06/01 00:10:35	1.7
--- ia64-protos.h	2000/06/08 17:11:49
*************** extern void ia64_encode_section_info PAR
*** 92,102 ****
  extern int ia64_epilogue_uses PARAMS((int));
  extern void ia64_expand_prologue PARAMS((void));
  extern void ia64_expand_epilogue PARAMS((void));
  extern int ia64_direct_return PARAMS((void));
  extern int ia64_rap_fp_offset PARAMS((void));
  extern void ia64_init_builtins PARAMS((void));
  extern void ia64_override_options PARAMS((void));
  extern unsigned int ia64_compute_frame_size PARAMS((int));
  extern void save_restore_insns PARAMS((int));
- extern void ia64_function_prologue PARAMS((FILE *, int));
- extern void ia64_funtion_epilogue PARAMS((FILE *, int));
--- 92,103 ----
  extern int ia64_epilogue_uses PARAMS((int));
  extern void ia64_expand_prologue PARAMS((void));
  extern void ia64_expand_epilogue PARAMS((void));
+ extern void ia64_function_prologue PARAMS((FILE *, int));
+ extern void ia64_output_end_prologue PARAMS((FILE *));
+ extern void ia64_function_epilogue PARAMS((FILE *, int));
  extern int ia64_direct_return PARAMS((void));
  extern int ia64_rap_fp_offset PARAMS((void));
  extern void ia64_init_builtins PARAMS((void));
  extern void ia64_override_options PARAMS((void));
  extern unsigned int ia64_compute_frame_size PARAMS((int));
  extern void save_restore_insns PARAMS((int));
Index: ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.21
diff -p -r1.21 ia64.c
*** ia64.c	2000/06/07 02:27:51	1.21
--- ia64.c	2000/06/08 17:11:50
*************** ia64_expand_prologue ()
*** 1001,1006 ****
--- 1001,1008 ----
  	offset = GEN_INT (-frame_size);
        else
  	{
+ 	  /* ??? We use r2 to tell process_set that this is a stack pointer
+ 	     decrement.  See also ia64_expand_epilogue.  */
  	  offset = gen_rtx_REG (DImode, GR_REG (2));
  	  insn = emit_insn (gen_movdi (offset, GEN_INT (-frame_size)));
  	  RTX_FRAME_RELATED_P (insn) = 1;
*************** ia64_expand_prologue ()
*** 1033,1038 ****
--- 1035,1042 ----
  void
  ia64_expand_epilogue ()
  {
+   rtx insn;
+ 
    /* Restore registers from frame.  */
    save_restore_insns (0);
  
*************** ia64_expand_epilogue ()
*** 1053,1060 ****
  	/* If there is a frame pointer, then we need to make the stack pointer
  	   restore depend on the frame pointer, so that the stack pointer
  	   restore won't be moved up past fp-relative loads from the frame.  */
! 	emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
! 						  hard_frame_pointer_rtx));
        }
      else
        {
--- 1057,1066 ----
  	/* If there is a frame pointer, then we need to make the stack pointer
  	   restore depend on the frame pointer, so that the stack pointer
  	   restore won't be moved up past fp-relative loads from the frame.  */
! 	insn
! 	  = emit_insn (gen_epilogue_deallocate_stack (stack_pointer_rtx,
! 						      hard_frame_pointer_rtx));
! 	RTX_FRAME_RELATED_P (insn) = 1;
        }
      else
        {
*************** ia64_expand_epilogue ()
*** 1067,1077 ****
  	      offset = GEN_INT (frame_size);
  	    else
  	      {
! 		offset = gen_rtx_REG (DImode, GR_REG (2));
  		emit_insn (gen_movdi (offset, GEN_INT (frame_size)));
  	      }
! 	    emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
! 				   offset));
  	  }
        }
      }
--- 1073,1086 ----
  	      offset = GEN_INT (frame_size);
  	    else
  	      {
! 		/* ??? We use r3 to tell process_set that this is a stack
! 		   pointer increment.  See also ia64_expand_prologue.  */
! 		offset = gen_rtx_REG (DImode, GR_REG (3));
  		emit_insn (gen_movdi (offset, GEN_INT (frame_size)));
  	      }
! 	    insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
! 					  offset));
! 	    RTX_FRAME_RELATED_P (insn) = 1;
  	  }
        }
      }
*************** ia64_function_prologue (file, size)
*** 1136,1141 ****
--- 1145,1162 ----
      fprintf (file, "\t.prologue\n");
  }
  
+ /* Emit the .body directive at the scheduled end of the prologue.  */
+ 
+ void
+ ia64_output_end_prologue (file)
+      FILE *file;
+ {
+   if (!flag_unwind_tables && (!flag_exceptions || exceptions_via_longjmp))
+     return;
+ 
+   fputs ("\t.body\n", file);
+ }
+ 
  /* Emit the function epilogue.  */
  
  void
*************** process_set (asm_out_file, pat)
*** 3021,3039 ****
  	  rtx op1 = XEXP (src, 1);
  	  if (op0 == dest && GET_CODE (op1) == CONST_INT)
  	    {
! 	      fputs ("\t.fframe ", asm_out_file);
! 	      fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (op1));
! 	      fputc ('\n', asm_out_file);
! 	      frame_size = INTVAL (op1);
! 	      return 1;
  	    }
  	  else if (op0 == dest && GET_CODE (op1) == REG)
  	    {
! 	      fprintf (asm_out_file, "\t.vframe r%d\n", REGNO (op1));
! 	      frame_size = 0;
! 	      return 1;
  	    }
  	}
      }
    /* Look for a frame offset.  */
    if (GET_CODE (dest) == REG)
--- 3042,3081 ----
  	  rtx op1 = XEXP (src, 1);
  	  if (op0 == dest && GET_CODE (op1) == CONST_INT)
  	    {
! 	      if (INTVAL (op1) < 0)
! 		{
! 		  fputs ("\t.fframe ", asm_out_file);
! 		  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
! 			   -INTVAL (op1));
! 		  fputc ('\n', asm_out_file);
! 		  frame_size = INTVAL (op1);
! 		}
! 	      else
! 		fprintf (asm_out_file, "\t.restore sp\n");
  	    }
  	  else if (op0 == dest && GET_CODE (op1) == REG)
  	    {
! 	      /* ia64_expand_prologue uses r2 for stack pointer decrements,
! 		 ia64_expand_epilogue uses r3 for stack pointer increments.  */
! 	      if (REGNO (op1) == GR_REG (2))
! 		{
! 		  fprintf (asm_out_file, "\t.vframe r%d\n", REGNO (op1));
! 		  frame_size = 0;
! 		}
! 	      else if (REGNO (op1) == GR_REG (3))
! 		fprintf (asm_out_file, "\t.restore sp\n");
! 	      else
! 		abort ();
  	    }
+ 	  else
+ 	    abort ();
  	}
+       else if (GET_CODE (src) == REG && REGNO (src) == FRAME_POINTER_REGNUM)
+ 	fprintf (asm_out_file, "\t.restore sp\n");
+       else
+ 	abort ();
+ 
+       return 1;
      }
    /* Look for a frame offset.  */
    if (GET_CODE (dest) == REG)
Index: ia64.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.h,v
retrieving revision 1.16
diff -p -r1.16 ia64.h
*** ia64.h	2000/06/01 00:10:35	1.16
--- ia64.h	2000/06/08 17:11:50
*************** do {									\
*** 1464,1469 ****
--- 1464,1473 ----
  #define FUNCTION_PROLOGUE(FILE, SIZE) \
    ia64_function_prologue (FILE, SIZE)
  
+ /* This macro notes the end of the prologue.  */
+ 
+ #define FUNCTION_END_PROLOGUE(FILE)  ia64_output_end_prologue (FILE)
+ 
  /* Define this macro as a C expression that is nonzero if the return
     instruction or the function epilogue ignores the value of the stack pointer;
     in other words, if it is safe to delete an instruction to adjust the stack

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