summaryrefslogtreecommitdiffstats
path: root/gcc/except.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/except.c')
-rw-r--r--gcc/except.c103
1 files changed, 74 insertions, 29 deletions
diff --git a/gcc/except.c b/gcc/except.c
index 00816ef1282..627c32ffbf4 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -698,6 +698,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 +740,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++;
}
@@ -2221,40 +2223,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 +2294,100 @@ set_exception_version_code (code)
version_code = code;
}
-
+/* Free the EH table structures. */
void
-output_exception_table ()
+free_exception_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 */
+}
+
/* Emit code to get EH context.
OpenPOWER on IntegriCloud