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]

exception-section patch, part 10



This patch adds (to except.c) support for multiple sections, and (to final.c
and toplev.c) the pass which actually decides which insns go to which
section. The "interesting" stuff is in final.c.

Sun Jun 28 19:49:33 1998  Bruno Haible  <bruno@linuix.math.u-bordeaux.fr>

        * except.h (add_eh_table_entry, exception_table_p): Change
          declarations.
          (exception_unwind_table_p, exception_table_begin_label): New
          declarations.
        * except.c (output_exception_table_entry): Remove declaration.
          (eh_table_entry): New structure type.
          (eh_table): Change type of variable.
          (eh_table_size, eh_table_max_size): Remove variables.
          (add_eh_table_entry, exception_table_p): Adapt for multiple sections.
          (force_unwind_table): New variable.
          (exception_unwind_table_p): New function.
          (exception_table_begin_label): New function.
          (output_exception_table_entry, output_exception_table): Adapt for
          multiple sections.
          (expand_builtin_unwind_init): Set force_unwind_table.
        * output.h (ehtext): Declare.
        * final.c (*eh_region*, eh_handler*, current_section): New variables.
          (init_final): Initialize pending_eh_regions.
          (ehtext_section_merge, ehtext_jump_optimize): New functions.
          (ehtext_kill_debug_info, ehtext_kill_empty_eh_handlers): Likewise.
          (ehtext, function_current_section): New functions.
          (final_start_function): Initialize eh_region_depth, eh_handler*.
          (final_scan_insn): Change EH_REGION_* handling. Add EH_HANDLER_*
          handling. Don't emit debugging info into the exception section.
          (output_source_line): Likewise.
        * toplev.c (ehtext_dump, ehtext_time): New variables.
          (compile_file): Initialize ehtext_time. Print ehtext_time.
          (rest_of_compilation): Call ehtext and dump_rtl afterwards.
          (main): Accept option "-de".
        * flow.c (find_basic_blocks_1): Remove empty EH_HANDLER_* pairs around
          deleted basic blocks.

diff -c3p egcs-19980628/gcc/except.h.bak egcs-19980628/gcc/except.h
*** egcs-19980628/gcc/except.h.bak	Thu Jun 25 16:11:46 1998
--- egcs-19980628/gcc/except.h	Tue Jun 30 13:08:34 1998
*************** extern void init_eh_for_function		PROTO(
*** 221,230 ****
  
  extern rtx gen_exception_label                  PROTO((void));
  
! /* Adds an EH table entry for EH entry number N. Called from
!    final_scan_insn for NOTE_INSN_EH_REGION_BEG.  */
  
! extern void add_eh_table_entry			PROTO((int n));
  
  /* Start a catch clause, triggered by runtime value paramter. */
  
--- 221,231 ----
  
  extern rtx gen_exception_label                  PROTO((void));
  
! /* Adds an EH table entry for EH handler number N, protecting EH inverval
!    number I. Called from final_scan_insn for NOTE_INSN_EH_REGION_BEG
!    and NOTE_INSN_EH_HANDLER_BEG.  */
  
! extern void add_eh_table_entry			PROTO((int n, int i, int section));
  
  /* Start a catch clause, triggered by runtime value paramter. */
  
*************** extern void add_eh_table_entry			PROTO((
*** 232,240 ****
  extern void start_catch_handler                 PROTO((tree));
  #endif
  
! /* Returns a non-zero value if we need to output an exception table.  */
  
! extern int exception_table_p			PROTO((void));
  
  /* Outputs the exception table if we have one.  */
  
--- 233,253 ----
  extern void start_catch_handler                 PROTO((tree));
  #endif
  
! /* Returns a non-zero value if we need to output an exception table for
!    a specified section.  */
  
! extern int exception_table_p			PROTO((int section));
! 
! /* Return a non-zero value if we need to output frame unwind info for
!    a specified section, even though exception_table_p (section) may
!    not require it.  */
! 
! extern int exception_unwind_table_p		PROTO((int section));
! 
! /* Return the name of the label which starts the exception table section
!    for a given text/eh_text section. 0 means "text", 1 means "eh_text".  */
! 
! extern char *exception_table_begin_label	PROTO((int section));
  
  /* Outputs the exception table if we have one.  */
  
diff -c3p egcs-19980628/gcc/except.c.bak egcs-19980628/gcc/except.c
*** egcs-19980628/gcc/except.c.bak	Thu Jun 25 16:11:47 1998
--- egcs-19980628/gcc/except.c	Tue Jun 30 13:08:35 1998
*************** static rtx call_get_eh_context	PROTO((vo
*** 498,504 ****
  static void start_dynamic_cleanup		PROTO((tree, tree));
  static void start_dynamic_handler		PROTO((void));
  static void expand_rethrow	PROTO((rtx));
- static void output_exception_table_entry	PROTO((FILE *, int));
  static int can_throw		PROTO((rtx));
  static rtx scan_region		PROTO((rtx, int, int *));
  static void eh_regs		PROTO((rtx *, rtx *, int));
--- 502,507 ----
*************** protect_with_terminate (e)
*** 1819,1906 ****
     dispatching exceptions, the current number of entries, and its
     maximum size before we have to extend it. 
  
!    The number in eh_table is the code label number of the exception
!    handler for the region. This is added by add_eh_table_entry and
!    used by output_exception_table_entry.  */
  
! static int *eh_table = NULL;
! static int eh_table_size = 0;
! static int eh_table_max_size = 0;
  
! /* Note the need for an exception table entry for region N.  If we
!    don't need to output an explicit exception table, avoid all of the
!    extra work.
  
!    Called from final_scan_insn when a NOTE_INSN_EH_REGION_BEG is seen.
!    (Or NOTE_INSN_EH_REGION_END sometimes)
!    N is the NOTE_BLOCK_NUMBER of the note, which comes from the code
!    label number of the exception handler for the region.  */
  
  void
! add_eh_table_entry (n)
!      int n;
  {
  #ifndef OMIT_EH_TABLE
!   if (eh_table_size >= eh_table_max_size)
      {
!       if (eh_table)
  	{
! 	  eh_table_max_size += eh_table_max_size>>1;
  
! 	  if (eh_table_max_size < 0)
  	    abort ();
  
! 	  eh_table = (int *) xrealloc (eh_table,
! 				       eh_table_max_size * sizeof (int));
  	}
        else
  	{
! 	  eh_table_max_size = 252;
! 	  eh_table = (int *) xmalloc (eh_table_max_size * sizeof (int));
  	}
      }
!   eh_table[eh_table_size++] = n;
  #endif
  }
  
! /* Return a non-zero value if we need to output an exception table.
  
     On some platforms, we don't have to output a table explicitly.
     This routine doesn't mean we don't have one.  */
  
  int
! exception_table_p ()
  {
!   if (eh_table)
      return 1;
  
    return 0;
  }
  
  /* Output the entry of the exception table corresponding to the
!    exception region numbered N to file FILE. 
  
!    N is the code label number corresponding to the handler of the
!    region.  */
  
  static void
! output_exception_table_entry (file, n)
       FILE *file;
!      int n;
  {
    char buf[256];
    rtx sym;
    struct handler_info *handler;
  
!   handler = get_first_handler (n);
  
    for ( ; handler != NULL; handler = handler->next)
      {
!       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
        sym = gen_rtx_SYMBOL_REF (Pmode, buf);
        assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
  
!       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHE", n);
        sym = gen_rtx_SYMBOL_REF (Pmode, buf);
        assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
        
--- 1826,1963 ----
     dispatching exceptions, the current number of entries, and its
     maximum size before we have to extend it. 
  
!    There is one table for the text section and one for the eh_text
!    section.
! 
!    The number in eh_table[section].entries is the code label number of
!    the exception handler for the region. This is added by
!    add_eh_table_entry and used by output_exception_table_entry.  */
  
! struct eh_table_entry
!   {
!     int n;
!     int i;
!   };
  
! static struct eh_table_struct
!   {
!     struct eh_table_entry *entries;
!     int size;
!     int max_size;
!   }
! eh_table[2];
  
! /* Note the need for an exception table entry which protects interval I
!    through handler N.  If we don't need to output an explicit exception
!    table, avoid all of the extra work.
! 
!    Called from final_scan_insn when a NOTE_INSN_EH_REGION_BEG or a
!    NOTE_INSN_EH_HANDLER_BEG is seen.  N is the code label number of the
!    exception handler for the region.  I is the code label number of the
!    special start and end labels (output directly from final_scan_insn)
!    of the regions.  */
  
  void
! add_eh_table_entry (n, i, section)
!      int n, i, section;
  {
  #ifndef OMIT_EH_TABLE
!   struct eh_table_struct *table = &eh_table[section];
! 
!   if (table->size >= table->max_size)
      {
!       if (table->entries)
  	{
! 	  table->max_size += table->max_size>>1;
  
! 	  if (table->max_size < 0)
  	    abort ();
  
! 	  table->entries =
! 	    (struct eh_table_entry *)
! 	      xrealloc (table->entries,
! 			table->max_size * sizeof (struct eh_table_entry));
  	}
        else
  	{
! 	  table->max_size = 252;
! 	  table->entries =
! 	    (struct eh_table_entry *)
! 	      xmalloc (table->max_size * sizeof (struct eh_table_entry));
  	}
      }
!   table->entries[table->size].i = i;
!   table->entries[table->size].n = n;
!   table->size++;
  #endif
  }
  
! /* Return a non-zero value if we need to output an exception table for
!    a specified section.
  
     On some platforms, we don't have to output a table explicitly.
     This routine doesn't mean we don't have one.  */
  
  int
! exception_table_p (section)
!      int section;
  {
!   if (eh_table[section].entries)
      return 1;
  
    return 0;
  }
  
+ /* If this is set to 1, frame unwind info will be output even if no
+    function in the compilation uses exceptions.  */
+ static int force_unwind_table = 0;
+ 
+ /* Return a non-zero value if we need to output frame unwind info for
+    a specified section, even though exception_table_p (section) may
+    not require it.  */
+ 
+ int exception_unwind_table_p (section)
+      int section;
+ {
+   if (section == 0 && force_unwind_table)
+     return 1;
+   return 0;
+ }
+ 
+ /* Return the name of the label which starts the exception table section
+    for a given text/eh_text section. 0 means "text", 1 means "eh_text".  */
+ 
+ char *
+ exception_table_begin_label (section)
+      int section;
+ {
+   return section == 0 ? "__EXCEPTION_TABLE__" : "__EXCEPTION_TABLE2__";
+ }
+ 
  /* Output the entry of the exception table corresponding to the
!    exception region ENTRY to file FILE. 
  
!    ENTRY->N is the code label number corresponding to the handler of
!    the region.  */
  
  static void
! output_exception_table_entry (file, entry)
       FILE *file;
!      const struct eh_table_entry *entry;
  {
    char buf[256];
    rtx sym;
    struct handler_info *handler;
  
!   handler = get_first_handler (entry->n);
  
    for ( ; handler != NULL; handler = handler->next)
      {
!       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", entry->i);
        sym = gen_rtx_SYMBOL_REF (Pmode, buf);
        assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
  
!       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHE", entry->i);
        sym = gen_rtx_SYMBOL_REF (Pmode, buf);
        assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
        
*************** void set_exception_version_code (code)
*** 1946,1993 ****
  void
  output_exception_table ()
  {
!   int i;
    extern FILE *asm_out_file;
  
!   if (! doing_eh (0) || ! eh_table)
      return;
  
    exception_section ();
  
!   /* Beginning marker for table.  */
!   assemble_align (GET_MODE_ALIGNMENT (ptr_mode));
!   assemble_label ("__EXCEPTION_TABLE__");
! 
!   if (flag_new_exceptions)
!     {
!       assemble_integer (GEN_INT (NEW_EH_RUNTIME), 
!                                         POINTER_SIZE / BITS_PER_UNIT, 1);
!       assemble_integer (GEN_INT (language_code), 2 , 1); 
!       assemble_integer (GEN_INT (version_code), 2 , 1);
! 
!       /* Add enough padding to make sure table aligns on a pointer boundry. */
!       i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4;
!       for ( ; i < 0; i = i + GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT)
!         ;
!       if (i != 0)
!         assemble_integer (const0_rtx, i , 1);
!     }
  
!   for (i = 0; i < eh_table_size; ++i)
!     output_exception_table_entry (asm_out_file, eh_table[i]);
  
!   free (eh_table);
!   clear_function_eh_region ();
  
!   /* Ending marker for table.  */
!   assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
  
!   /* for binary compatability, the old __throw checked the second
!      position for a -1, so we should output at least 2 -1's */
!   if (! flag_new_exceptions)
!     assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
  
!   putc ('\n', asm_out_file);		/* blank line */
  }
  
  /* Emit code to get EH context.
--- 2003,2063 ----
  void
  output_exception_table ()
  {
!   int section, i;
    extern FILE *asm_out_file;
  
!   if (! doing_eh (0))
!     return;
! 
!   if (! eh_table[0].entries && ! eh_table[1].entries)
      return;
  
    exception_section ();
  
!   for (section = 0; section < 2; section++)
!     {
!       struct eh_table_struct *table = &eh_table[section];
  
!       if (table->size > 0)
! 	{
! 	  /* Beginning marker for table.  */
! 	  assemble_align (GET_MODE_ALIGNMENT (ptr_mode));
! 	  assemble_label (exception_table_begin_label (section));
  
! 	  if (flag_new_exceptions)
! 	    {
! 	      assemble_integer (GEN_INT (NEW_EH_RUNTIME), 
! 	                        POINTER_SIZE / BITS_PER_UNIT, 1);
! 	      assemble_integer (GEN_INT (language_code), 2 , 1); 
! 	      assemble_integer (GEN_INT (version_code), 2 , 1);
! 
! 	      /* Add enough padding to make sure table aligns on a pointer
! 		 boundary. */
! 	      i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4;
! 	      for ( ; i < 0; i += GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT)
! 	        ;
! 	      if (i != 0)
! 	        assemble_integer (const0_rtx, i , 1);
! 	    }
  
! 	  for (i = 0; i < table->size; ++i)
! 	    output_exception_table_entry (asm_out_file, &table->entries[i]);
  
! 	  /* Ending marker for table.  */
! 	  assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
! 
! 	  /* for binary compatability, the old __throw checked the second
! 	     position for a -1, so we should output at least 2 -1's */
! 	  if (! flag_new_exceptions)
! 	    assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
! 
! 	  putc ('\n', asm_out_file);		/* blank line */
! 	}
! 
!       free (table->entries);
!     }
  
!   clear_function_eh_region ();
  }
  
  /* Emit code to get EH context.
*************** expand_builtin_unwind_init ()
*** 2369,2374 ****
--- 2439,2447 ----
    /* Set this so all the registers get saved in our frame; we need to be
       able to copy the saved values for any registers from frames we unwind. */
    current_function_has_nonlocal_label = 1;
+ 
+   /* Set this so that a DWARF2 unwind info table is emitted.  */
+   force_unwind_table = 1;
  
  #ifdef SETUP_FRAME_ADDRESSES
    SETUP_FRAME_ADDRESSES ();
diff -c3p egcs-19980628/gcc/output.h.bak egcs-19980628/gcc/output.h
*** egcs-19980628/gcc/output.h.bak	Mon Jun  8 20:30:18 1998
--- egcs-19980628/gcc/output.h	Tue Jun 30 13:08:35 1998
*************** extern int get_attr_length	PROTO((rtx));
*** 51,56 ****
--- 51,59 ----
     any branches of variable length if possible.  */
  extern void shorten_branches	PROTO((rtx));
  
+ /* Decide which insns will go into the eh_text section.  */
+ extern void ehtext		PROTO((rtx));
+ 
  /* Output assembler code for the start of a function,
     and initialize some of the variables in this file
     for the new function.  The label for the function and associated
diff -c3p egcs-19980628/gcc/final.c.bak egcs-19980628/gcc/final.c
*** egcs-19980628/gcc/final.c.bak	Thu Jun 25 17:14:39 1998
--- egcs-19980628/gcc/final.c	Tue Jun 30 21:18:38 1998
*************** Boston, MA 02111-1307, USA.  */
*** 69,74 ****
--- 69,75 ----
  #include "except.h"
  #include "toplev.h"
  #include "reload.h"
+ #include "function.h"
  
  /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist.  */
  #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
*************** static int *pending_blocks;
*** 249,254 ****
--- 250,281 ----
  
  static int block_depth;
  
+ /* Length so far allocated in PENDING_EH_REGIONS.  */
+ 
+ static int max_eh_region_depth;
+ 
+ /* Stack of handler block numbers for open exception handling regions.  */
+ 
+ static int *pending_eh_regions;
+ 
+ /* Number of elements currently in use in PENDING_EH_REGIONS.  */
+ 
+ static int eh_region_depth;
+ 
+ /* Number of nested NOTE_INSN_EH_HANDLER_{BEG,END} notes seen.  */
+ 
+ static int eh_handler_depth;
+ 
+ /* If eh_handler_depth > 0, a label used to protect an eh_text region.  */
+ 
+ static rtx eh_handler_region_label;
+ 
+ /* The current section to which insns are being emitted. 0 means "text",
+    1 means "eh_text". The following holds:
+  current_section == (flag_extra_section_for_exceptions && eh_handler_depth > 0)
+  */
+ static int current_section;
+ 
  /* Nonzero if have enabled APP processing of our assembler output.  */
  
  static int app_on;
*************** init_final (filename)
*** 326,332 ****
    next_block_index = 2;
    app_on = 0;
    max_block_depth = 20;
!   pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks);
    final_sequence = 0;
  
  #ifdef ASSEMBLER_DIALECT
--- 353,361 ----
    next_block_index = 2;
    app_on = 0;
    max_block_depth = 20;
!   pending_blocks = (int *) xmalloc (max_block_depth * sizeof (int));
!   max_eh_region_depth = 10;
!   pending_eh_regions = (int *) xmalloc (max_eh_region_depth * sizeof (int));
    final_sequence = 0;
  
  #ifdef ASSEMBLER_DIALECT
*************** asm_insn_count (body)
*** 1568,1573 ****
--- 1597,1896 ----
  }
  #endif
  
+ /* Special treatment of the eh_text section.  */
+ 
+ /* We must make sure that we don't output the difference of two labels in
+    different sections: the text section and the eh_text section. Some pairs
+    of NOTE_INSN_EH_HANDLER_{BEG,END} insns must be deleted.  */
+ static void
+ ehtext_section_merge (first)
+      rtx first;
+ {
+   int max_uid;
+   rtx *outer_table;
+   rtx insn;
+   rtx outer;
+ 
+   max_uid = get_max_uid ();
+   outer_table = (rtx *) alloca (max_uid * sizeof (rtx));
+   bzero ((char *) outer_table, max_uid * sizeof (rtx));
+ 
+   /* Make a single pass through the code, registering the outer enclosing
+      NOTE_INSN_EH_HANDLER_BEG insn in OUTER_TABLE. Also let each
+      EH_HANDLER_BEG note point to its corresponding EH_HANDLER_END note.  */
+   outer = NULL_RTX;
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       outer_table[INSN_UID (insn)] = outer;
+       if (INSN_DELETED_P (insn))
+ 	continue;
+       if (GET_CODE (insn) == NOTE)
+ 	{
+ 	  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_BEG)
+ 	    outer = insn;
+ 	  else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_END)
+ 	    {
+ 	      NOTE_SOURCE_FILE (outer) = (char *) insn;
+ 	      outer = outer_table[INSN_UID (outer)];
+ 	    }
+ 	}
+     }
+   if (outer != NULL_RTX)
+     abort ();
+ 
+   /* Now go through the code once again, looking for suspicious label
+      differences.  */
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       if (INSN_DELETED_P (insn))
+ 	continue;
+       if (GET_CODE (insn) == JUMP_INSN
+ 	  && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ 	{
+ 	  rtx body = PATTERN (insn);
+ 	  int vlen = XVECLEN (body, 1);
+ 	  int idx;
+ 	  for (idx = 0; idx < vlen; idx++)
+ 	    {
+ 	      rtx outer1, outer2;
+ 	      int depth1, depth2;
+ 	      outer1 = XEXP (XEXP (body, 0), 0);
+ 	      outer2 = XEXP (XVECEXP (body, 1, idx), 0);
+ 	      outer1 = outer_table[INSN_UID (outer1)];
+ 	      outer2 = outer_table[INSN_UID (outer2)];
+ 	      for (outer = outer1, depth1 = 0;
+ 		   outer != NULL_RTX;
+ 		   outer = outer_table[INSN_UID (outer)], depth1++);
+ 	      for (outer = outer2, depth2 = 0;
+ 		   outer != NULL_RTX;
+ 		   outer = outer_table[INSN_UID (outer)], depth2++);
+ 	      while (!(depth1 == depth2 && outer1 == outer2))
+ 		{
+ 		  int kill1 = (depth1 >= depth2);
+ 		  int kill2 = (depth1 <= depth2);
+ 		  if (kill1)
+ 		    {
+ 		      /* Kill EH_HANDLER_{BEG,END} corresponding to outer1.  */
+ 		      NOTE_LINE_NUMBER ((rtx) NOTE_SOURCE_FILE (outer1))
+ 			= NOTE_INSN_DELETED;
+ 		      NOTE_LINE_NUMBER (outer1) = NOTE_INSN_DELETED;
+ 		      outer1 = outer_table[INSN_UID (outer1)];
+ 		      depth1--;
+ 		    }
+ 		  if (kill2)
+ 		    {
+ 		      /* Kill EH_HANDLER_{BEG,END} corresponding to outer2.  */
+ 		      NOTE_LINE_NUMBER ((rtx) NOTE_SOURCE_FILE (outer2))
+ 			= NOTE_INSN_DELETED;
+ 		      NOTE_LINE_NUMBER (outer2) = NOTE_INSN_DELETED;
+ 		      outer2 = outer_table[INSN_UID (outer2)];
+ 		      depth2--;
+ 		    }
+ 		}
+ 	    }
+ 	}
+     }
+ }
+ 
+ /* Remove simple jumps which jump "over" some code in another section.
+    The usual jump optimizations don't catch this because they don't know
+    about different code sections. In fact, the usual jump optimizations
+    cannot do this because the partitioning into sections is different
+    between an out-of-line copy and an inline copy of the same function.  */
+ static void
+ ehtext_jump_optimize (first)
+      rtx first;
+ {
+   rtx insn, insn1, insn2, last_jump;
+   int eh_handler_depth;
+ 
+   if (optimize)
+     {
+       eh_handler_depth = 0;
+       last_jump = NULL_RTX;
+       for (insn = first; insn; insn = NEXT_INSN (insn))
+ 	{
+ 	  if (INSN_DELETED_P (insn))
+ 	    continue;
+ 	  switch (GET_CODE (insn))
+ 	    {
+ 	    case NOTE:
+ 	      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_BEG)
+ 		{
+ 		  if (eh_handler_depth++ == 0)
+ 		    {
+ 		      if ((insn1 = PREV_INSN (insn))
+ 			  && GET_CODE (insn1) == BARRIER
+ 			  && (insn2 = PREV_INSN (insn1))
+ 			  && simplejump_p (insn2))
+ 			last_jump = insn2;
+ 		    }
+ 		  break;
+ 		}
+  	      if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_END)
+  		{
+ 		  if (--eh_handler_depth == 0)
+ 		    {
+ 		      if (last_jump)
+ 			{
+ 			  for (insn1 = NEXT_INSN (insn);
+ 			       insn1
+ 			       && GET_CODE (insn1) == NOTE
+ 			       && (NOTE_LINE_NUMBER (insn1)
+ 				   != NOTE_INSN_EH_HANDLER_BEG);
+ 			       insn1 = NEXT_INSN (insn1))
+ 			    ;
+ 			  if (GET_CODE (insn1) == CODE_LABEL
+ 			      && JUMP_LABEL (last_jump) == insn1)
+ 			    /* Delete the jump "over" the section and the
+ 			       barrier in between.  */
+ 			    {
+ 			      INSN_DELETED_P (last_jump) = 1;
+ 			      INSN_DELETED_P (NEXT_INSN (last_jump)) = 1;
+ 			      last_jump = NULL_RTX;
+ 			    }
+ 			}
+ 		    }
+ 		  break;
+ 		}
+ 	      break;
+ 	    default:
+ 	      if (eh_handler_depth == 0)
+ 		last_jump = NULL_RTX;
+ 	      break;
+ 	    }
+ 	}
+     }
+ }
+ 
+ /* Remove the debug info associated to code in the eh_text section.
+    We do this for two reasons:
+    1) In general, we expect debuggers to go mad if a function's code comes
+       in two parts.
+    2) If defined(DBX_DEBUGGING_INFO) && defined(DBX_BLOCKS_FUNCTION_RELATIVE)
+       and (write_symbols == DBX_DEBUG), we must not output block notes
+       for blocks in eh_text -- that would be invalid assembly.  */
+ static void
+ ehtext_kill_debug_info (first)
+      rtx first;
+ {
+   tree *block_vector;
+   rtx insn;
+   int eh_handler_depth;
+ 
+   if (write_symbols == NO_DEBUG)
+     return;
+ 
+   block_vector = identify_blocks (DECL_INITIAL (current_function_decl), first);
+   eh_handler_depth = 0;
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       if (INSN_DELETED_P (insn))
+ 	continue;
+       if (GET_CODE (insn) == NOTE)
+ 	{
+ 	  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_BEG)
+ 	    eh_handler_depth++;
+ 	  else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_END)
+ 	    --eh_handler_depth;
+ 	  else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
+ 		   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
+ 		   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL
+ 		   || NOTE_LINE_NUMBER (insn) > 0)
+ 	    {
+ 	      if (eh_handler_depth > 0)
+ 		{
+ 		  /* Tell final_scan_insn() and dbxout_block() not to
+ 		     output debugging info for this insn.  */
+ 		  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
+ 		    {
+ 		      tree block = block_vector[NOTE_BLOCK_NUMBER (insn)];
+ 		      BLOCK_DELETED (block) = 1;
+ 		    }
+ 		  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ 		}
+ 	    }
+ 	}
+     }
+   free (block_vector);
+ }
+ 
+ /* Remove NOTE_INSN_EH_HANDLER_{BEG,END} pairs with nothing but notes between
+    them. This avoids switching to the eh_text section if it's not needed
+    (wouldn't hurt - the assembly output would just look stupid), and it
+    avoids outputting eh_table entries with no code between them (which
+    would confuse the runtime function find_fde()).  */
+ static void
+ ehtext_kill_empty_eh_handlers (first)
+      rtx first;
+ {
+   rtx insn;
+   int eh_handler_depth;
+   rtx handler_beg = NULL_RTX;
+ 
+   eh_handler_depth = 0;
+   for (insn = first; insn; insn = NEXT_INSN (insn))
+     {
+       if (INSN_DELETED_P (insn))
+ 	continue;
+       if (GET_CODE (insn) == NOTE)
+ 	{
+ 	  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_BEG)
+ 	    {
+ 	      if (eh_handler_depth++ == 0)
+ 		handler_beg = insn;
+ 	    }
+ 	  else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_END)
+ 	    {
+ 	      if (--eh_handler_depth == 0)
+ 		{
+ 		  if (handler_beg)
+ 		    {
+ 		      /* There were only notes between handler_beg and insn.
+ 		         Kill them all.  */
+ 		      do {
+ 			NOTE_LINE_NUMBER (handler_beg) = NOTE_INSN_DELETED;
+ 			handler_beg = NEXT_INSN (handler_beg);
+ 		      } while (handler_beg != insn);
+ 		      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ 		    }
+ 		  handler_beg = NULL_RTX;
+ 		}
+ 	    }
+ 	}
+       else
+ 	handler_beg = NULL_RTX;
+     }
+ }
+ 
+ /* Decide which insns will go into the eh_text section.
+    After this pass, every insn inside some EH_HANDLER_{BEG,END} note
+    will go to the eh_text section, the rest to the text section.
+ 
+    This is called only if flag_extra_section_for_exceptions is true. */
+ 
+ void
+ ehtext (first)
+      rtx first;
+ {
+   ehtext_section_merge (first);
+   ehtext_jump_optimize (first);
+   ehtext_kill_debug_info (first);
+   ehtext_kill_empty_eh_handlers (first);
+ }
+ 
+ /* Switch to the function's code section corresponding to current_section.  */
+ 
+ void
+ function_current_section ()
+ {
+   if (current_section == 0)
+     function_section (current_function_decl);
+   else
+     function_eh_section (current_function_decl);
+ }
+ 
+ 
  /* Output assembler code for the start of a function,
     and initialize some of the variables in this file
     for the new function.  The label for the function and associated
*************** final_start_function (first, file, optim
*** 1585,1590 ****
--- 1908,1917 ----
       int optimize;
  {
    block_depth = 0;
+   eh_region_depth = 0;
+   eh_handler_depth = 0;
+   eh_handler_region_label = NULL_RTX;
+   current_section = 0;
  
    this_is_asm_operands = 0;
  
*************** final_scan_insn (insn, file, optimize, p
*** 2053,2079 ****
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
  	break;
  
!       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
! 	  && ! exceptions_via_longjmp)
  	{
! 	  ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_BLOCK_NUMBER (insn));
!           if (! flag_new_exceptions)
!             add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
  #ifdef ASM_OUTPUT_EH_REGION_BEG
! 	  ASM_OUTPUT_EH_REGION_BEG (file, NOTE_BLOCK_NUMBER (insn));
  #endif
  	  break;
  	}
  
!       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
! 	  && ! exceptions_via_longjmp)
  	{
! 	  ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_BLOCK_NUMBER (insn));
!           if (flag_new_exceptions)
!             add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
  #ifdef ASM_OUTPUT_EH_REGION_END
! 	  ASM_OUTPUT_EH_REGION_END (file, NOTE_BLOCK_NUMBER (insn));
  #endif
  	  break;
  	}
  
--- 2380,2484 ----
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
  	break;
  
!       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
  	{
! 	  int blockno = NOTE_BLOCK_NUMBER (insn);
! 
! 	  if (eh_region_depth == max_eh_region_depth)
! 	    {
! 	      /* PENDING_EH_REGIONS is full; make it longer.  */
! 	      max_eh_region_depth *= 2;
! 	      pending_eh_regions =
! 		(int *) xrealloc (pending_eh_regions,
! 				  max_eh_region_depth * sizeof (int));
! 	    }
! 	  pending_eh_regions[eh_region_depth++] = blockno;
! 
! 	  if (! exceptions_via_longjmp)
! 	    {
! 	      ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", blockno);
! 	      if (! flag_new_exceptions)
! 		add_eh_table_entry (blockno, blockno, current_section);
  #ifdef ASM_OUTPUT_EH_REGION_BEG
! 	      ASM_OUTPUT_EH_REGION_BEG (file, blockno);
  #endif
+ 	    }
+ 
  	  break;
  	}
  
!       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
  	{
! 	  int blockno = NOTE_BLOCK_NUMBER (insn);
! 
! 	  eh_region_depth--;
! 
! 	  if (! exceptions_via_longjmp)
! 	    {
! 	      ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", blockno);
! 	      if (flag_new_exceptions)
! 		add_eh_table_entry (blockno, blockno, current_section);
  #ifdef ASM_OUTPUT_EH_REGION_END
! 	      ASM_OUTPUT_EH_REGION_END (file, blockno);
! #endif
! 	    }
! 
! 	  break;
! 	}
! 
!       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_BEG)
! 	{
! 	  /* NOTE_INSN_EH_HANDLER_BEG followed by NOTE_INSN_EH_HANDLER_END
! 	     cancel each other and can be ignored.  */
! 	  rtx next_insn = NEXT_INSN (insn);
! 	  if (GET_CODE (next_insn) == NOTE
! 	      && NOTE_LINE_NUMBER (next_insn) == NOTE_INSN_EH_HANDLER_END)
! 	    return NEXT_INSN (next_insn);
! 
! 	  if (eh_handler_depth++ == 0 && flag_extra_section_for_exceptions)
! 	    {
! 	      current_section = 1;
! 	      function_current_section ();
! 	      if (! exceptions_via_longjmp && eh_region_depth > 0)
! 		{
! 		  int i, n;
! 		  eh_handler_region_label = gen_label_rtx ();
! 		  i = CODE_LABEL_NUMBER (eh_handler_region_label);
! 		  n = pending_eh_regions[eh_region_depth - 1];
! 		  ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", i);
! 		  if (!flag_new_exceptions)
! 		    add_eh_table_entry (n, i, 1);
! 		}
! #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
! 	      if (dwarf2out_do_frame ())
! 		dwarf2out_goto_section (1, eh_handler_region_label);
  #endif
+ 	    }
+ 	  break;
+ 	}
+ 
+       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_END)
+ 	{
+ 	  if (--eh_handler_depth == 0 && flag_extra_section_for_exceptions)
+ 	    {
+ #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
+ 	      if (dwarf2out_do_frame ())
+ 		dwarf2out_goto_section (0, eh_handler_region_label);
+ #endif
+ 	      if (! exceptions_via_longjmp && eh_region_depth > 0)
+ 		{
+ 		  int i, n;
+ 		  i = CODE_LABEL_NUMBER (eh_handler_region_label);
+ 		  n = pending_eh_regions[eh_region_depth - 1];
+ 		  ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", i);
+ 		  if (flag_new_exceptions)
+ 		    add_eh_table_entry (n, i, 1);
+ 		  rtx_free (eh_handler_region_label);
+ 		  eh_handler_region_label = NULL_RTX;
+ 		}
+ 	      current_section = 0;
+ 	      function_current_section ();
+ 	    }
  	  break;
  	}
  
*************** final_scan_insn (insn, file, optimize, p
*** 2096,2101 ****
--- 2501,2507 ----
  
        if (write_symbols == NO_DEBUG)
  	break;
+ 
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
  	{
  #if defined(SDB_DEBUGGING_INFO) && defined(MIPS_DEBUGGING_INFO)
*************** final_scan_insn (insn, file, optimize, p
*** 2296,2318 ****
        FINAL_PRESCAN_INSN (insn, NULL_PTR, 0);
  #endif
  
  #ifdef SDB_DEBUGGING_INFO
!       if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))
! 	sdbout_label (insn);
  #endif
  #ifdef DWARF_DEBUGGING_INFO
!       if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn))
! 	dwarfout_label (insn);
  #endif
  #ifdef DWARF2_DEBUGGING_INFO
!       if (write_symbols == DWARF2_DEBUG && LABEL_NAME (insn))
! 	dwarf2out_label (insn);
  #endif
        if (app_on)
  	{
  	  fputs (ASM_APP_OFF, file);
  	  app_on = 0;
  	}
        if (NEXT_INSN (insn) != 0
  	  && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
  	{
--- 2702,2729 ----
        FINAL_PRESCAN_INSN (insn, NULL_PTR, 0);
  #endif
  
+       if (!current_section)
+ 	{
  #ifdef SDB_DEBUGGING_INFO
! 	  if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))
! 	    sdbout_label (insn);
  #endif
  #ifdef DWARF_DEBUGGING_INFO
! 	  if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn))
! 	    dwarfout_label (insn);
  #endif
  #ifdef DWARF2_DEBUGGING_INFO
! 	  if (write_symbols == DWARF2_DEBUG && LABEL_NAME (insn))
! 	    dwarf2out_label (insn);
  #endif
+ 	}
+ 
        if (app_on)
  	{
  	  fputs (ASM_APP_OFF, file);
  	  app_on = 0;
  	}
+ 
        if (NEXT_INSN (insn) != 0
  	  && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
  	{
*************** final_scan_insn (insn, file, optimize, p
*** 2335,2341 ****
  #endif /* READONLY_DATA_SECTION */
  		}
  	      else
! 		function_section (current_function_decl);
  
  #ifdef ASM_OUTPUT_CASE_LABEL
  	      ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
--- 2746,2752 ----
  #endif /* READONLY_DATA_SECTION */
  		}
  	      else
! 		function_current_section ();
  
  #ifdef ASM_OUTPUT_CASE_LABEL
  	      ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
*************** final_scan_insn (insn, file, optimize, p
*** 2427,2433 ****
  				 insn);
  #endif
  
! 	    function_section (current_function_decl);
  
  	    break;
  	  }
--- 2838,2844 ----
  				 insn);
  #endif
  
! 	    function_current_section ();
  
  	    break;
  	  }
*************** output_source_line (file, insn)
*** 2935,2941 ****
    high_block_linenum = MAX (last_linenum, high_block_linenum);
    high_function_linenum = MAX (last_linenum, high_function_linenum);
  
!   if (write_symbols != NO_DEBUG)
      {
  #ifdef SDB_DEBUGGING_INFO
        if (write_symbols == SDB_DEBUG
--- 3346,3354 ----
    high_block_linenum = MAX (last_linenum, high_block_linenum);
    high_function_linenum = MAX (last_linenum, high_function_linenum);
  
!   /* Don't emit debugging info for the eh_text section. That would confuse
!      debuggers.  */
!   if (write_symbols != NO_DEBUG && !current_section)
      {
  #ifdef SDB_DEBUGGING_INFO
        if (write_symbols == SDB_DEBUG
diff -c3p egcs-19980628/gcc/toplev.c.bak egcs-19980628/gcc/toplev.c
*** egcs-19980628/gcc/toplev.c.bak	Sat Jun 27 17:51:49 1998
--- egcs-19980628/gcc/toplev.c	Tue Jun 30 13:08:35 1998
*************** int stack_reg_dump = 0;
*** 289,294 ****
--- 289,295 ----
  #ifdef MACHINE_DEPENDENT_REORG
  int mach_dep_reorg_dump = 0;
  #endif
+ int ehtext_dump = 0;
  
  /* Name for output file of assembly code, specified with -o.  */
  
*************** int dbr_sched_time;
*** 1029,1034 ****
--- 1031,1037 ----
  #endif
  int shorten_branch_time;
  int stack_reg_time;
+ int ehtext_time;
  int final_time;
  int symout_time;
  int dump_time;
*************** compile_file (name)
*** 2327,2332 ****
--- 2330,2336 ----
  #endif
    shorten_branch_time = 0;
    stack_reg_time = 0;
+   ehtext_time = 0;
    final_time = 0;
    symout_time = 0;
    dump_time = 0;
*************** compile_file (name)
*** 2408,2413 ****
--- 2412,2419 ----
    if (mach_dep_reorg_dump)
      clean_dump_file (".mach");
  #endif
+   if (ehtext_dump)
+     clean_dump_file (".ehtext");
  
    /* Open assembler code output file.  */
  
*************** compile_file (name)
*** 2874,2879 ****
--- 2895,2901 ----
  #endif
        print_time ("shorten-branch", shorten_branch_time);
        print_time ("stack-reg", stack_reg_time);
+       print_time ("ehtext", ehtext_time);
        print_time ("final", final_time);
        print_time ("varconst", varconst_time);
        print_time ("symout", symout_time);
*************** rest_of_compilation (decl)
*** 3612,3617 ****
--- 3634,3648 ----
      dump_rtl (".stack", decl, print_rtl_with_bb, insns);
  #endif
  
+   /* Decide which insns will go into the eh_text section.  */
+   if (flag_extra_section_for_exceptions)
+     {
+       TIMEVAR (ehtext_time, ehtext (get_insns ()));
+ 
+       if (ehtext_dump)
+         dump_rtl (".ehtext", decl, print_rtl_with_bb, insns);
+     }
+ 
    /* Now turn the rtl into assembler code.  */
  
    TIMEVAR (final_time,
*************** main (argc, argv, envp)
*** 3930,3935 ****
--- 3964,3970 ----
  #ifdef MACHINE_DEPENDENT_REORG
  		    mach_dep_reorg_dump = 1;
  #endif
+                     ehtext_dump = 1;
  		    break;
  		  case 'A':
  		    flag_debug_asm = 1;
*************** main (argc, argv, envp)
*** 3945,3950 ****
--- 3980,3988 ----
  		    dbr_sched_dump = 1;
  		    break;
  #endif
+ 		  case 'e':
+                     ehtext_dump = 1;
+ 		    break;
  		  case 'f':
  		    flow_dump = 1;
  		    break;
diff -c3p egcs-19980628/gcc/flow.c.bak egcs-19980628/gcc/flow.c
*** egcs-19980628/gcc/flow.c.bak	Sat Jun 27 17:51:46 1998
--- egcs-19980628/gcc/flow.c	Tue Jun 30 21:32:02 1998
*************** find_basic_blocks_1 (f, nonlocal_label_l
*** 865,870 ****
--- 865,901 ----
                      }
                  }
              }
+       /* If we deleted a basic block enclosed in NOTE_EH_HANDLER_{BEG,END}
+ 	 notes, remove these notes too. (Because GCSE may append insns to
+ 	 the end of this deleted basic block.)  */
+       /* This loop deletes all balanced NOTE_EH_HANDLER_{BEG,END} notes
+ 	 with only notes between them.  */
+       {
+ 	rtx handler_beg = NULL_RTX;
+ 
+ 	for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ 	  {
+ 	    if (INSN_DELETED_P (insn))
+ 	      continue;
+ 	    if (GET_CODE (insn) == NOTE)
+ 	      {
+ 		if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_BEG)
+ 		  {
+ 		    NOTE_SOURCE_FILE (insn) = (char *) handler_beg;
+ 		    handler_beg = insn;
+ 		  }
+ 		else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_HANDLER_END
+ 			 && handler_beg)
+ 		  {
+ 		    NOTE_LINE_NUMBER (handler_beg) = NOTE_INSN_DELETED;
+ 		    NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ 		    handler_beg = (rtx) NOTE_SOURCE_FILE (handler_beg);
+ 		  }
+ 	      }
+ 	    else
+ 	      handler_beg = NULL_RTX;
+ 	  }
+       }
  
        /* There are pathological cases where one function calling hundreds of
  	 nested inline functions can generate lots and lots of unreachable


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