OSDN Git Service

ch:
[pf3gnuchains/gcc-fork.git] / gcc / except.c
index 00816ef..efa61e5 100644 (file)
@@ -463,7 +463,6 @@ static void start_dynamic_cleanup   PARAMS ((tree, tree));
 static void start_dynamic_handler      PARAMS ((void));
 static void expand_rethrow     PARAMS ((rtx));
 static void output_exception_table_entry       PARAMS ((FILE *, int));
-static int can_throw           PARAMS ((rtx));
 static rtx scan_region         PARAMS ((rtx, int, int *));
 static void eh_regs            PARAMS ((rtx *, rtx *, rtx *, int));
 static void set_insn_eh_region PARAMS ((rtx *, int));
@@ -698,6 +697,7 @@ struct func_eh_entry
   int range_number;   /* EH region number from EH NOTE insn's.  */
   rtx rethrow_label;  /* Label for rethrow.  */
   int rethrow_ref;    /* Is rethrow_label referenced?  */
+  int emitted;        /* 1 if this entry has been emitted in assembly file.  */
   struct handler_info *handlers;
 };
 
@@ -739,7 +739,8 @@ new_eh_region_entry (note_eh_region, rethrow)
   else
     function_eh_regions[current_func_eh_entry].rethrow_label = rethrow;
   function_eh_regions[current_func_eh_entry].handlers = NULL;
-
+  function_eh_regions[current_func_eh_entry].emitted = 0;
   return current_func_eh_entry++;
 }
 
@@ -930,7 +931,8 @@ clear_function_eh_region ()
         next = ptr->next;
         free (ptr);
       }
-  free (function_eh_regions);
+  if (function_eh_regions)
+    free (function_eh_regions);
   num_func_eh_entries  = 0;
   current_func_eh_entry = 0;
 }
@@ -1361,7 +1363,7 @@ start_dynamic_handler ()
   buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
 
 #ifdef DONT_USE_BUILTIN_SETJMP
-  x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1,
+  x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST,
                               TYPE_MODE (integer_type_node), 1,
                               buf, Pmode);
   /* If we come back here for a catch, transfer control to the handler.  */
@@ -1759,7 +1761,8 @@ start_catch_handler (rtime)
 
       /* Now issue the call, and branch around handler if needed */
       call_rtx = emit_library_call_value (eh_rtime_match_libfunc, NULL_RTX, 
-                                          0, TYPE_MODE (integer_type_node),
+                                          LCT_NORMAL,
+                                         TYPE_MODE (integer_type_node),
                                          1, rtime_address, Pmode);
 
       /* Did the function return true? */
@@ -2221,40 +2224,44 @@ output_exception_table_entry (file, n)
   else
     rethrow = NULL_RTX;
 
+  if (function_eh_regions[index].emitted)
+    return;
+  function_eh_regions[index].emitted  = 1;
+
   for ( ; handler != NULL || rethrow != NULL_RTX; handler = handler->next)
     {
       /* rethrow label should indicate the LAST entry for a region */
       if (rethrow != NULL_RTX && (handler == NULL || handler->next == NULL))
         {
           ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", n);
-          assemble_label(buf);
+          assemble_eh_label(buf);
           rethrow = NULL_RTX;
         }
 
       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
       sym = gen_rtx_SYMBOL_REF (Pmode, buf);
-      assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
+      assemble_eh_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);
+      assemble_eh_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
       
       if (handler == NULL)
-        assemble_integer (GEN_INT (0), POINTER_SIZE / BITS_PER_UNIT, 1);
+        assemble_eh_integer (GEN_INT (0), POINTER_SIZE / BITS_PER_UNIT, 1);
       else
         {
           ASM_GENERATE_INTERNAL_LABEL (buf, "L", handler->handler_number);
           sym = gen_rtx_SYMBOL_REF (Pmode, buf);
-          assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
+          assemble_eh_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
         }
 
       if (flag_new_exceptions)
         {
           if (handler == NULL || handler->type_info == NULL)
-            assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
+            assemble_eh_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
           else
             if (handler->type_info == CATCH_ALL_TYPE)
-              assemble_integer (GEN_INT (CATCH_ALL_TYPE), 
+              assemble_eh_integer (GEN_INT (CATCH_ALL_TYPE), 
                                              POINTER_SIZE / BITS_PER_UNIT, 1);
             else
               output_constant ((tree)(handler->type_info), 
@@ -2288,61 +2295,101 @@ set_exception_version_code (code)
   version_code = code;
 }
 
-
+/* Free the EH table structures.  */
 void
-output_exception_table ()
+free_exception_table ()
+{
+  if (eh_table)
+    free (eh_table);
+  clear_function_eh_region ();
+}
+  
+/* Output the common content of an exception table.  */
+void
+output_exception_table_data ()
 {
   int i;
   char buf[256];
   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), 
+      assemble_eh_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);
+      assemble_eh_integer (GEN_INT (language_code), 2 , 1); 
+      assemble_eh_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);
+        assemble_eh_integer (const0_rtx, i , 1);
 
       /* Generate the label for offset calculations on rethrows.  */
       ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", 0);
-      assemble_label(buf);
+      assemble_eh_label(buf);
     }
 
   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 ();
+}
+
+/* Output an exception table for the entire compilation unit.  */
+void
+output_exception_table ()
+{
+  char buf[256];
+  extern FILE *asm_out_file;
+
+  if (! doing_eh (0) || ! eh_table)
+    return;
+
+  exception_section ();
+
+  /* Beginning marker for table.  */
+  assemble_eh_align (GET_MODE_ALIGNMENT (ptr_mode));
+  assemble_eh_label ("__EXCEPTION_TABLE__");
+
+  output_exception_table_data ();
 
   /* Ending marker for table.  */
   /* Generate the label for end of table. */
   ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", CODE_LABEL_NUMBER (final_rethrow));
-  assemble_label(buf);
-  assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
+  assemble_eh_label(buf);
+  assemble_eh_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
 
   /* For binary compatibility, 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);
+    assemble_eh_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
 
   putc ('\n', asm_out_file);           /* blank line */
 }
+
+/* Used by the ia64 unwind format to output data for an individual 
+   function.  */
+void
+output_function_exception_table ()
+{
+  extern FILE *asm_out_file;
+
+  if (! doing_eh (0) || ! eh_table)
+    return;
+
+#ifdef HANDLER_SECTION
+  HANDLER_SECTION;
+#endif
+
+  output_exception_table_data ();
+
+  /* Ending marker for table.  */
+  assemble_eh_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
+
+  putc ('\n', asm_out_file);           /* blank line */
+}
+
 \f
 /* Emit code to get EH context.
    
@@ -2560,7 +2607,8 @@ mark_eh_status (eh)
   mark_eh_queue (eh->x_ehqueue);
   ggc_mark_rtx (eh->x_catch_clauses);
 
-  lang_mark_false_label_stack (eh->x_false_label_stack);
+  if (lang_mark_false_label_stack)
+    (*lang_mark_false_label_stack) (eh->x_false_label_stack);
   mark_tree_label_node (eh->x_caught_return_label_stack);
 
   ggc_mark_tree (eh->x_protect_list);
@@ -2643,12 +2691,11 @@ free_eh_status (f)
 }
 \f
 /* This section is for the exception handling specific optimization
-   pass.  First are the internal routines, and then the main
-   optimization pass.  */
+   pass.  */
 
 /* Determine if the given INSN can throw an exception.  */
 
-static int
+int
 can_throw (insn)
      rtx insn;
 {