diff mbox

[SEH] Hookize exception personality directive

Message ID 4C86AC52.4090802@redhat.com
State New
Headers show

Commit Message

Richard Henderson Sept. 7, 2010, 9:19 p.m. UTC
This fixes the nasty bit of code here:

> -#ifdef TARGET_UNWIND_INFO
> -  /* TODO: Move this into target file.  */
> -  fputs ("\t.personality\t", asm_out_file);
> -  output_addr_const (asm_out_file, personality);
> -  fputs ("\n\t.handlerdata\n", asm_out_file);
> -  /* Note that varasm still thinks we're in the function's code section.
> -     The ".endp" directive that will immediately follow will take us back.  */

The .personality directive is moved to a new hook
TARGET_ASM_EMIT_EXCEPT_PERSONALITY.  The .handlerdata directive is
moved into our much-improved sections support.  We set up the
exception_section structure appropriately so that The Correct Thing
happens with purely generic code.

Tested on x86_64-w64-mingw32 (with additional patches), crosses to
ia64-linux and arm-linux-eabi, and a sanity check with x86_64-linux.


r~
diff mbox

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f544f73..eb54e9e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,28 @@ 
 2010-09-07  Richard Henderson  <rth@redhat.com>
 
+	* target.def (TARGET_ASM_EMIT_EXCEPT_PERSONALITY): New hook.
+	* doc/tm.texi.in: Add doc marker.
+	* doc/tm.texi: Rebuild.
+	* except.c (switch_to_exception_section): Always build.
+	(output_one_function_exception_table): Move section switch,
+	personality output, and label output ...
+	(output_function_exception_table): ... here.  Use the new
+	personality hook.
+
+	* config/ia64/ia64.c (ia64_asm_emit_except_personality,
+	ia64_asm_init_sections, TARGET_ASM_EMIT_EXCEPT_PERSONALITY,
+	TARGET_ASM_INIT_SECTIONS): New.
+	(ia64_asm_unwind_emit): Rename from process_for_unwind_directive,
+	make static.
+	(TARGET_ASM_UNWIND_EMIT): Update to match.
+	* config/ia64/ia64-protos.h (process_for_unwind_directive): Remove.
+
+	* config/arm/arm.c (arm_asm_emit_except_personality): New.
+	(arm_asm_init_sections): New.
+	(TARGET_ASM_EMIT_EXCEPT_PERSONALITY, TARGET_ASM_INIT_SECTIONS): New.
+
+2010-09-07  Richard Henderson  <rth@redhat.com>
+
 	* target.def (unwind_emit_before_insn): New hook.
 	* doc/tm.texi.in: Add @hook marker for it.
 	* doc/tm.texi: Rebuild.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 440995f..1d547b0 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -196,6 +196,8 @@  static bool arm_return_in_memory (const_tree, const_tree);
 #ifdef TARGET_UNWIND_INFO
 static void arm_unwind_emit (FILE *, rtx);
 static bool arm_output_ttype (rtx);
+static void arm_asm_emit_except_personality (rtx);
+static void arm_asm_init_sections (void);
 #endif
 static void arm_dwarf_handle_frame_unspec (const char *, rtx, int);
 static rtx arm_dwarf_register_span (rtx);
@@ -455,6 +457,12 @@  static const struct attribute_spec arm_attribute_table[] =
 
 #undef TARGET_ARM_EABI_UNWINDER
 #define TARGET_ARM_EABI_UNWINDER true
+
+#undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
+#define TARGET_ASM_EMIT_EXCEPT_PERSONALITY arm_asm_emit_except_personality
+
+#undef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS arm_asm_init_sections
 #endif /* TARGET_UNWIND_INFO */
 
 #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
@@ -22209,6 +22217,25 @@  arm_output_ttype (rtx x)
 
   return TRUE;
 }
+
+/* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY.  */
+
+static void
+arm_asm_emit_except_personality (rtx personality)
+{
+  fputs ("\t.personality\t", asm_out_file);
+  output_addr_const (asm_out_file, personality);
+  fputc ('\n', asm_out_file);
+}
+
+/* Implement TARGET_ASM_INITIALIZE_SECTIONS.  */
+
+static void
+arm_asm_init_sections (void)
+{
+  exception_section = get_unnamed_section (0, output_section_asm_op,
+					   "\t.handlerdata");
+}
 #endif /* TARGET_UNWIND_INFO */
 
 
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index 0a5af40..4fc6a42 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -59,7 +59,6 @@  extern void ia64_print_operand (FILE *, rtx, int);
 extern enum reg_class ia64_preferred_reload_class (rtx, enum reg_class);
 extern enum reg_class ia64_secondary_reload_class (enum reg_class,
 						   enum machine_mode, rtx);
-extern void process_for_unwind_directive (FILE *, rtx);
 extern const char *get_bundle_name (int);
 #endif /* RTX_CODE */
 
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 7f5d929..17b6a47 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -247,6 +247,10 @@  static int ia64_sched_reorder (FILE *, int, rtx *, int *, int);
 static int ia64_sched_reorder2 (FILE *, int, rtx *, int *, int);
 static int ia64_variable_issue (FILE *, int, rtx, int);
 
+static void ia64_asm_unwind_emit (FILE *, rtx);
+static void ia64_asm_emit_except_personality (rtx);
+static void ia64_asm_init_sections (void);
+
 static struct bundle_state *get_free_bundle_state (void);
 static void free_bundle_state (struct bundle_state *);
 static void initiate_bundle_states (void);
@@ -521,7 +525,11 @@  static const struct attribute_spec ia64_attribute_table[] =
 #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
 
 #undef TARGET_ASM_UNWIND_EMIT
-#define TARGET_ASM_UNWIND_EMIT process_for_unwind_directive
+#define TARGET_ASM_UNWIND_EMIT ia64_asm_unwind_emit
+#undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
+#define TARGET_ASM_EMIT_EXCEPT_PERSONALITY  ia64_asm_emit_except_personality
+#undef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS  ia64_asm_init_sections
 
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
@@ -9845,8 +9853,8 @@  process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
 
 /* This function looks at a single insn and emits any directives
    required to unwind this insn.  */
-void
-process_for_unwind_directive (FILE *asm_out_file, rtx insn)
+static void
+ia64_asm_unwind_emit (FILE *asm_out_file, rtx insn)
 {
   bool unwind = (flag_unwind_tables
 		 || (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
@@ -9909,6 +9917,24 @@  process_for_unwind_directive (FILE *asm_out_file, rtx insn)
     }
 }
 
+/* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY.  */
+
+static void
+ia64_asm_emit_except_personality (rtx personality)
+{
+  fputs ("\t.personality\t", asm_out_file);
+  output_addr_const (asm_out_file, personality);
+  fputc ('\n', asm_out_file);
+}
+
+/* Implement TARGET_ASM_INITIALIZE_SECTIONS.  */
+
+static void
+ia64_asm_init_sections (void)
+{
+  exception_section = get_unnamed_section (0, output_section_asm_op,
+					   "\t.handlerdata");
+}
 
 enum ia64_builtins
 {
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index a8db902..e60392f 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8744,6 +8744,10 @@  to be broken up according to function.
 The default is that no label is emitted.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_ASM_EMIT_EXCEPT_PERSONALITY (rtx @var{personality})
+If the target implements @code{TARGET_ASM_UNWIND_EMIT}, this hook may be used to emit a directive to install a personality hook into the unwind info.  This hook should not be used if dwarf2 unwind info is used.
+@end deftypefn
+
 @deftypefn {Target Hook} void TARGET_ASM_UNWIND_EMIT (FILE *@var{stream}, rtx @var{insn})
 This target hook emits assembly directives required to unwind the
 given instruction.  This is only used when TARGET_UNWIND_INFO is set.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 2efc1ae..17fcd4b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -8734,6 +8734,8 @@  to be broken up according to function.
 The default is that no label is emitted.
 @end deftypefn
 
+@hook TARGET_ASM_EMIT_EXCEPT_PERSONALITY
+
 @hook TARGET_ASM_UNWIND_EMIT
 This target hook emits assembly directives required to unwind the
 given instruction.  This is only used when TARGET_UNWIND_INFO is set.
diff --git a/gcc/except.c b/gcc/except.c
index 0df1996..bfffa44 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -2794,7 +2794,6 @@  sjlj_output_call_site_table (void)
   call_site_base += n;
 }
 
-#ifndef TARGET_UNWIND_INFO
 /* Switch to the section that should be used for exception tables.  */
 
 static void
@@ -2844,7 +2843,6 @@  switch_to_exception_section (const char * ARG_UNUSED (fnname))
 
   switch_to_section (s);
 }
-#endif
 
 
 /* Output a reference from an exception table to the type_info object TYPE.
@@ -2904,8 +2902,7 @@  output_ttype (tree type, int tt_format, int tt_format_size)
 }
 
 static void
-output_one_function_exception_table (const char * ARG_UNUSED (fnname),
-				     int section, rtx ARG_UNUSED (personality))
+output_one_function_exception_table (int section)
 {
   int tt_format, cs_format, lp_format, i;
 #ifdef HAVE_AS_LEB128
@@ -2918,20 +2915,6 @@  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
   int have_tt_data;
   int tt_format_size = 0;
 
-#ifdef TARGET_UNWIND_INFO
-  /* TODO: Move this into target file.  */
-  fputs ("\t.personality\t", asm_out_file);
-  output_addr_const (asm_out_file, personality);
-  fputs ("\n\t.handlerdata\n", asm_out_file);
-  /* Note that varasm still thinks we're in the function's code section.
-     The ".endp" directive that will immediately follow will take us back.  */
-#else
-  switch_to_exception_section (fnname);
-#endif
-
-  /* If the target wants a label to begin the table, emit it here.  */
-  targetm.asm_out.emit_except_table_label (asm_out_file);
-
   have_tt_data = (VEC_length (tree, cfun->eh->ttype_data)
 		  || (targetm.arm_eabi_unwinder
 		      ? VEC_length (tree, cfun->eh->ehspec_data.arm_eabi)
@@ -3095,7 +3078,7 @@  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
 }
 
 void
-output_function_exception_table (const char * ARG_UNUSED (fnname))
+output_function_exception_table (const char *fnname)
 {
   rtx personality = get_personality_function (current_function_decl);
 
@@ -3104,11 +3087,21 @@  output_function_exception_table (const char * ARG_UNUSED (fnname))
     return;
 
   if (personality)
-    assemble_external_libcall (personality);
+    {
+      assemble_external_libcall (personality);
+
+      if (targetm.asm_out.emit_except_personality)
+	targetm.asm_out.emit_except_personality (personality);
+    }
+
+  switch_to_exception_section (fnname);
+
+  /* If the target wants a label to begin the table, emit it here.  */
+  targetm.asm_out.emit_except_table_label (asm_out_file);
 
-  output_one_function_exception_table (fnname, 0, personality);
+  output_one_function_exception_table (0);
   if (crtl->eh.call_site_record[1] != NULL)
-    output_one_function_exception_table (fnname, 1, personality);
+    output_one_function_exception_table (1);
 
   switch_to_section (current_function_section ());
 }
diff --git a/gcc/target.def b/gcc/target.def
index e62a977..6910ce9 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -145,6 +145,15 @@  DEFHOOK
  void, (FILE *stream),
  default_emit_except_table_label)
 
+/* Emit a directive for setting the personality for the function.  */
+DEFHOOK
+(emit_except_personality,
+ "If the target implements @code{TARGET_ASM_UNWIND_EMIT}, this hook may be\
+ used to emit a directive to install a personality hook into the unwind\
+ info.  This hook should not be used if dwarf2 unwind info is used.",
+ void, (rtx personality),
+ NULL)
+
 /* Emit any directives required to unwind this instruction.  */
 DEFHOOK
 (unwind_emit,