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]

almost all of DWARF EH for ppc



This is everything needed for DWARF exception-handling on ppc,
except for

+#define INCOMING_RETURN_ADDR_RTX   gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)

in rs6000.h to turn the thing on, and support for cross-object throws
under AIX, which I'm still thinking about.  I'll commit the above line
when the patch to the toplevel for negative offsets is approved.

The eh_epilogue pattern is particularly interesting.  Not only does it
avoid the previous problem where eh_regs was picking the wrong
registers, but it has this cute feature where it delays calling
rs6000_emit_epilogue until after reload in the TARGET_SCHED_PROLOG
case (and of course delays it until final if we're not generating the
prolog or epilogue as RTL).  It's interesting to compare this pattern
with, say, the one for Alpha, which doesn't do any real work at all.

-- 
- Geoffrey Keating <geoffk@cygnus.com>

===File ~geoffkc/patches/rs6000-dwarfeh-1-misc.patch========
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/Attic/ChangeLog,v
retrieving revision 1.1.2.29
diff -p -u -u -p -r1.1.2.29 ChangeLog
--- ChangeLog	2000/02/04 07:17:12	1.1.2.29
+++ ChangeLog	2000/02/05 23:22:57
@@ -1,3 +1,33 @@
+2000-02-04  Geoff Keating  <geoffk@cygnus.com>
+
+	* rs6000.md (eh_epilogue): New expander.
+	(eh_reg_restore): New expand/split/insn combination.
+	(return_eh_si): New insn.
+	(return_eh_di): New insn.
+
+	* eabi-ci.asm: Put a label at the start of the .eh_frame section.
+	* eabi-cn.asm: Put a zero at the end of the .eh_frame section.
+	* eabi-ctors.c (__do_global_ctors): Register this object's
+	frame.  Clean up.  Call atexit() after the constructors.
+	(__do_global_dtors): Deregister this object's frame.  Clean up.
+	Allow for recursive calls to exit().
+	* rs6000.c (fixuplabelno): New variable.
+	* sysv4.h (ASM_OUTPUT_INT): Don't do .fixup if not
+	TARGET_RELOCATABLE, it slows down exec() under linux.
+	(ASM_OUTPUT_DWARF_ADDR): Do .fixup if TARGET_RELOCATABLE.
+
+	* aix.h (ASM_OUTPUT_DWARF_ADDR_VAR): New macro.
+	(ASM_OUTPUT_DWARF_DELTA_VAR): New macro.
+	(ASM_OUTPUT_DWARF_DELTA2): New macro.
+	(ASM_OUTPUT_DWARF_DELTA4): New macro.
+	(ASM_OUTPUT_DWARF_ADDR_DELTA): New macro.
+	(ASM_OUTPUT_DWARF_ADDR): New macro.
+	(ASM_OUTPUT_DWARF_DATA4): New macro.
+	(ASM_OUTPUT_DWARF_DATA2): New macro.
+	(ASM_OUTPUT_DWARF_OFFSET4): New macro.
+	(ASM_OUTPUT_DWARF_OFFSET): New macro.
+	(UNALIGNED_INT_ASM_OP): New macro, fake definition.
+
 2000-02-03  Geoff Keating  <geoffk@cygnus.com>
 
 	* rs6000.c (rs6000_sr_alias_set): New variable.
Index: aix.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/Attic/aix.h,v
retrieving revision 1.1.2.6
diff -p -u -u -p -r1.1.2.6 aix.h
--- aix.h	2000/01/27 23:42:36	1.1.2.6
+++ aix.h	2000/02/05 23:22:57
@@ -425,3 +425,49 @@ toc_section ()						\
 	 fprintf( (FILE), ",%d\n", (SIZE));		\
   } while (0)
 
+/* These are various definitions for DWARF output.  They could just
+   use '.long' or '.word', but that aligns to a 4-byte boundary which
+   is not what is required.  So we define a million macros...  */
+
+#define ASM_OUTPUT_DWARF_ADDR_VAR(FILE, LABEL, LENGTH)	\
+ do {   fprintf ((FILE), "\t.vbyte\t%d,", LENGTH);	\
+        assemble_name (FILE, LABEL);			\
+  } while (0)
+
+#define ASM_OUTPUT_DWARF_DELTA_VAR(FILE, LABEL1, LABEL2, LENGTH)	\
+ do {   fprintf ((FILE), "\t.vbyte\t%d,", LENGTH);			\
+        assemble_name (FILE, LABEL1);					\
+        fprintf (FILE, "-");						\
+        assemble_name (FILE, LABEL2);					\
+  } while (0)
+
+#define ASM_OUTPUT_DWARF_DELTA2(FILE, LABEL1, LABEL2)	\
+ ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, 2)
+
+#define ASM_OUTPUT_DWARF_DELTA4(FILE, LABEL1, LABEL2)	\
+ ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, 4)
+
+#define ASM_OUTPUT_DWARF_DELTA(FILE, LABEL1, LABEL2)			\
+ ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, DWARF_OFFSET_SIZE)
+
+#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE, LABEL1, LABEL2)	\
+ ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2,		\
+			     POINTER_SIZE / BITS_PER_UNIT)
+
+#define ASM_OUTPUT_DWARF_ADDR(FILE, LABEL)				\
+ ASM_OUTPUT_DWARF_ADDR_VAR (FILE, LABEL, POINTER_SIZE / BITS_PER_UNIT)
+
+#define ASM_OUTPUT_DWARF_DATA4(FILE, VALUE)			\
+  fprintf ((FILE), "\t.vbyte\t4,0x%x", (unsigned) (VALUE))
+
+#define ASM_OUTPUT_DWARF_DATA2(FILE, VALUE)			\
+  fprintf ((FILE), "\t.vbyte\t2,0x%x", (unsigned) (VALUE))
+
+#define ASM_OUTPUT_DWARF_OFFSET4(FILE, LABEL)	\
+ ASM_OUTPUT_DWARF_ADDR_VAR (FILE, LABEL, 4)
+
+#define ASM_OUTPUT_DWARF_OFFSET(FILE, LABEL)			\
+ ASM_OUTPUT_DWARF_ADDR_VAR (FILE, LABEL, DWARF_OFFSET_SIZE)
+
+/* dwarf2out keys off this, but we don't have to have a real definition.  */
+#define UNALIGNED_INT_ASM_OP bite_me
Index: eabi-ci.asm
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/eabi-ci.asm,v
retrieving revision 1.2
diff -p -u -u -p -r1.2 eabi-ci.asm
--- eabi-ci.asm	1998/12/16 21:11:50	1.2
+++ eabi-ci.asm	2000/02/05 23:22:57
@@ -1,6 +1,6 @@
 # crti.s for eabi
 
-#   Copyright (C) 1996 Free Software Foundation, Inc.
+#   Copyright (C) 1996, 2000 Free Software Foundation, Inc.
 #   Written By Michael Meissner
 # 
 # This file is free software; you can redistribute it and/or modify it
@@ -101,6 +101,11 @@ __SBSS2_START__:
 	.globl	__EXCEPT_START__
 	.type	__EXCEPT_START__,@object
 __EXCEPT_START__:
+
+	.section ".eh_frame","aw"
+	.globl	__EH_FRAME_BEGIN__
+	.type	__EH_FRAME_BEGIN__,@object
+__EH_FRAME_BEGIN__:
 
 # Head of __init function used for static constructors in Solaris
 	.section ".init","ax"
Index: eabi-cn.asm
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/eabi-cn.asm,v
retrieving revision 1.2
diff -p -u -u -p -r1.2 eabi-cn.asm
--- eabi-cn.asm	1998/12/16 21:11:51	1.2
+++ eabi-cn.asm	2000/02/05 23:22:58
@@ -1,6 +1,6 @@
 # crtn.s for eabi
 
-#   Copyright (C) 1996 Free Software Foundation, Inc.
+#   Copyright (C) 1996, 2000 Free Software Foundation, Inc.
 #   Written By Michael Meissner
 # 
 # This file is free software; you can redistribute it and/or modify it
@@ -93,6 +93,12 @@ __SBSS2_END__:
 	.globl	__EXCEPT_END__
 	.type	__EXCEPT_END__,@object
 __EXCEPT_END__:
+
+	.section ".eh_frame","aw"
+	.globl	__EH_FRAME_END__
+	.type	__EH_FRAME_END__,@object
+__EH_FRAME_END__:
+        .long   0
 
 # Tail of __init used for static constructors in Solaris
 	.section ".init","ax"
Index: eabi-ctors.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/eabi-ctors.c,v
retrieving revision 1.3
diff -p -u -u -p -r1.3 eabi-ctors.c
--- eabi-ctors.c	1999/10/12 16:47:08	1.3
+++ eabi-ctors.c	2000/02/05 23:22:58
@@ -1,7 +1,7 @@
 /* Stripped down support to run global constructors and destructors on
    embedded PowerPC systems.
 
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2000 Free Software Foundation, Inc.
    Contributed by Michael Meissner  (meissner@cygnus.com).
 
 This file is part of GNU CC.
@@ -28,11 +28,15 @@ Boston, MA 02111-1307, USA.  */
    This exception does not however invalidate any other reasons why
    the executable file might be covered by the GNU General Public License.  */
 
+#include "tm.h"
+#include "defaults.h"
+#include <stddef.h>
+#include "frame.h"
+#include "gbl-ctors.h"
 
-/*  Declare a pointer to void function type.  */
+/* FIXME: This file should share code with all the other
+   constructor/destructor implementations in crtstuff.c and libgcc2.c.  */
 
-typedef void (*func_ptr) (void);
-
 /* Declare the set of symbols use as begin and end markers for the lists
    of global object constructors and global object destructors.  */
 
@@ -40,53 +44,61 @@ extern func_ptr __CTOR_LIST__[];
 extern func_ptr __CTOR_END__ [];
 extern func_ptr __DTOR_LIST__[];
 extern func_ptr __DTOR_END__ [];
+extern unsigned char __EH_FRAME_BEGIN__[];
 
 extern void __do_global_ctors (void);
-extern void __do_global_dtors (void);
 
 extern void __init (), __fini ();
 
-/* The Solaris linker seems to incorrectly relocate PC relative relocations
-   to a different section (ie, calls to __init, __fini), so avoid it by
-   using a function pointer.  */
-static void (*init_ptr) (void) = __init;
-static void (*fini_ptr) (void) = __fini;
-
 void (*__atexit)(func_ptr);
 
 /* Call all global constructors */
 void
 __do_global_ctors (void)
 {
-  func_ptr *ptr   = &__CTOR_END__[0] - 1;
-  func_ptr *start = &__CTOR_LIST__[0];
+  func_ptr *p = __CTOR_END__ - 1;
 
-  if (__atexit)
-    __atexit (__do_global_dtors);
+#ifdef EH_FRAME_SECTION
+  {
+    static struct object object;
+    __register_frame_info (__EH_FRAME_BEGIN__, &object);
+  }
+#endif
 
   /* Call the constructors collected in the .ctors section.  */
-  for ( ; ptr >= start; ptr--)
-    if (*ptr)
-      (*ptr)();
+  for ( ; p >= __CTOR_LIST__; p--)
+    if (*p)
+      (*p)();
+  
+  if (__atexit)
+    __atexit (__do_global_dtors);
 
   /* Call the initialization function in the .init section.  */
-  (*init_ptr) ();
+  __init ();
 }
 
 /* Call all global destructors */
 void
 __do_global_dtors (void)
 {
-  func_ptr *ptr   = &__DTOR_LIST__[0];
-  func_ptr *end   = &__DTOR_END__[0];
+  static func_ptr *p = __DTOR_LIST__ + 1;
+  static int completed = 0;
 
+  if (completed)
+    return;
+
   /* Call the termination function in the .fini section.  */
-  (*fini_ptr) ();
+  __fini ();
 
-  /* Call the  destructors collected in the .dtors section.  Run
-     the destructors in reverse order.  */
-  for ( ; ptr < end; ptr++)
-    if (*ptr)
-      (*ptr)();
+  while (p < __DTOR_END__)
+    {
+      p++;
+      (*(p-1)) ();
+    }
+
+#ifdef EH_FRAME_SECTION_ASM_OP
+  if (__deregister_frame_info)
+    __deregister_frame_info (__EH_FRAME_BEGIN__);
+#endif
+  completed = 1;
 }
-
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.108.2.13
diff -p -u -u -p -r1.108.2.13 rs6000.c
--- rs6000.c	2000/02/04 07:17:12	1.108.2.13
+++ rs6000.c	2000/02/05 23:22:58
@@ -92,6 +92,9 @@ enum rs6000_sdata_type rs6000_sdata = SD
 
 /* Which small data model to use */
 const char *rs6000_sdata_name = (char *)0;
+
+/* Counter for labels which are to be placed in .fixup.  */
+int fixuplabelno = 0;
 #endif
 
 /* Whether a System V.4 varargs area was created.  */
Index: rs6000.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.79.2.14
diff -p -u -u -p -r1.79.2.14 rs6000.md
--- rs6000.md	2000/02/04 07:17:12	1.79.2.14
+++ rs6000.md	2000/02/05 23:22:58
@@ -30,6 +30,7 @@
 ;; 6		address of a word pointing to the TOC
 ;; 7		address of the TOC (more-or-less)
 ;; 8		movsi_got
+;; 9/v		eh_reg_restore
 ;; 10		fctiwz
 ;; 19		movesi_from_cr
 ;; 20		movesi_to_cr
@@ -11166,3 +11167,118 @@
 			(match_operand:DF 4 "memory_operand" "m"))])]
  "TARGET_64BIT"
  "b %z2")
+
+; This is used in compiling the routines __throw and __rethrow.
+; It's a little different to the usual definition...
+
+(define_expand "eh_epilogue"
+  [(use (match_operand 0 "general_operand" "r"))
+   (use (match_operand 1 "general_operand" "r"))
+   (use (match_operand 2 "general_operand" "c"))]
+  ""
+  "
+{
+  rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+  rtx insn;
+
+  /* This is required for binary compatibility.  If it's wrong,
+     it probably means that eh_regs() in except.c is broken.  */
+  if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 3)
+    abort();
+
+  /* These can be anything that doesn't interfere with the epilogue.  */
+  if (GET_CODE (operands[1]) != REG || REGNO (operands[1]) != 4)
+    {
+      rtx r = gen_rtx_REG (Pmode, 4);
+      emit_move_insn (r, operands[1]);
+      operands[1] = r;
+    }
+
+  if (GET_CODE (operands[2]) != REG 
+	|| REGNO (operands[2]) != COUNT_REGISTER_REGNUM)
+    {
+      rtx r = gen_rtx_REG (Pmode, COUNT_REGISTER_REGNUM);
+      emit_move_insn (r, operands[2]);
+      operands[2] = r;
+    }
+
+  emit_insn (gen_eh_reg_restore ());
+
+  if (Pmode == SImode)
+    emit_insn (gen_addsi3 (stack_reg, stack_reg, operands[1]));
+  else
+    emit_insn (gen_adddi3 (stack_reg, stack_reg, operands[1]));
+  
+  if (Pmode == SImode)
+    insn = emit_jump_insn (gen_return_eh_si (operands[2]));
+  else
+    insn = emit_jump_insn (gen_return_eh_di (operands[2]));
+  emit_barrier_after (insn);
+
+  DONE;
+}")
+
+; We can't expand this before we know which registers are restored,
+; but we do want to expand it before flow2 because that way flow2 can
+; remove the redundant loads of the link register.
+(define_expand "eh_reg_restore"
+  [(unspec_volatile [(const_int 0)] 9)]
+  ""
+  "")
+
+(define_split
+  [(unspec_volatile [(const_int 0)] 9)]
+  "reload_completed && TARGET_SCHED_PROLOG"
+  [(unspec_volatile [(const_int 0)] 9)]
+  "
+{
+  rs6000_emit_epilogue (TRUE);
+  DONE;
+}")
+
+(define_insn ""
+  [(unspec_volatile [(const_int 0)] 9)]
+  ""
+  "*
+{
+  if (TARGET_SCHED_PROLOG)
+    return \"#\";
+
+  /* This is slightly ugly, but at least we don't have multiple
+     copies of the epilogue-emitting code.  */
+  start_sequence ();
+
+  /* A NOTE_INSN_DELETED is supposed to be at the start
+     and end of the \"toplevel\" insn chain.  */
+  emit_note (0, NOTE_INSN_DELETED);
+  rs6000_emit_epilogue (TRUE);
+  emit_note (0, NOTE_INSN_DELETED);
+
+  if (TARGET_DEBUG_STACK)
+    debug_rtx_list (get_insns(), 100);
+  final (get_insns(), asm_out_file, FALSE, FALSE);
+  end_sequence ();
+  return \"\";
+}")
+
+
+(define_insn "return_eh_si"
+  [(use (match_operand:SI 0 "register_operand" "l,c"))
+   (return)
+   (use (reg:SI 3))]
+  "TARGET_32BIT"
+  "@
+   {br|blr}
+   bctr"
+  [(set_attr "type" "jmpreg")])
+
+(define_insn "return_eh_di"
+  [(use (match_operand:DI 0 "register_operand" "l,c"))
+   (return)
+   (use (reg:DI 3))]
+  "TARGET_64BIT"
+  "@
+   {br|blr}
+   bctr"
+  [(set_attr "type" "jmpreg")])
+
Index: sysv4.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/sysv4.h,v
retrieving revision 1.23.4.8
diff -p -u -u -p -r1.23.4.8 sysv4.h
--- sysv4.h	2000/02/04 07:01:31	1.23.4.8
+++ sysv4.h	2000/02/05 23:22:58
@@ -735,6 +735,8 @@ do {									\
 } while (0)
 
 
+extern int fixuplabelno;
+
 /* This is how to output an assembler line defining an `int' constant.
    For -mrelocatable, we mark all addresses that need to be fixed up
    in the .fixup section.  */
@@ -742,7 +744,7 @@ do {									\
 #define ASM_OUTPUT_INT(FILE,VALUE)					\
 do {									\
   static int recurse = 0;						\
-  if ((TARGET_RELOCATABLE || flag_pic)					\
+  if (TARGET_RELOCATABLE						\
       && in_section != in_toc						\
       && in_section != in_text						\
       && in_section != in_ctors						\
@@ -752,18 +754,18 @@ do {									\
       && GET_CODE (VALUE) != CONST_DOUBLE				\
       && CONSTANT_P (VALUE))						\
     {									\
-      static int labelno = 0;						\
       char buf[256];							\
       const char *p;							\
 									\
       recurse = 1;							\
-      ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++);		\
+      ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", fixuplabelno);		\
+      fixuplabelno++;							\
       STRIP_NAME_ENCODING (p, buf);					\
       fprintf (FILE, "%s:\n", p);					\
       fprintf (FILE, "\t.long (");					\
       output_addr_const (FILE, (VALUE));				\
       fprintf (FILE, ")@fixup\n");					\
-      fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n");			\
+      fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n");		\
       ASM_OUTPUT_ALIGN (FILE, 2);					\
       fprintf (FILE, "\t.long\t%s\n", p);				\
       fprintf (FILE, "\t.previous\n");					\
@@ -790,6 +792,35 @@ do {									\
     }									\
 } while (0)
 
+/* This is how to output an assembler line defining an address 
+   constant for the dwarf call unwinding information.
+   For -mrelocatable, we mark all addresses that need to be fixed up
+   in the .fixup section.  */
+
+#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL)				 \
+do {									 \
+  if (TARGET_RELOCATABLE)						 \
+    {									 \
+      char buf[256];							 \
+      const char *p;							 \
+									 \
+      ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", fixuplabelno);		 \
+      fixuplabelno++;							 \
+      STRIP_NAME_ENCODING (p, buf);					 \
+      fprintf (FILE, "%s:\t.%dbyte\t", p, POINTER_SIZE / BITS_PER_UNIT); \
+      assemble_name (FILE, LABEL);					 \
+      fprintf (FILE, "\n");						 \
+      fprintf (FILE, "\t.section \".fixup\",\"aw\"\n");			 \
+      ASM_OUTPUT_ALIGN (FILE, 2);					 \
+      fprintf (FILE, "\t.long\t%s\n", p);				 \
+      fprintf (FILE, "\t.previous");					 \
+    }									 \
+  else									 \
+    {									 \
+      fprintf (FILE, "\t.%dbyte\t", POINTER_SIZE / BITS_PER_UNIT);	 \
+      assemble_name (FILE, LABEL);					 \
+    }									 \
+} while (0)
 
 /* This is the end of what might become sysv4.h.  */
 
============================================================

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