Hi!

On 2018-08-03T11:52:36+0200, Jakub Jelinek <ja...@redhat.com> wrote:
> On Fri, Aug 03, 2018 at 11:45:31AM +0200, Tom de Vries wrote:
>> If a target does not support exceptions, it can indicate this by returning
>> UI_NONE in TARGET_EXCEPT_UNWIND_INFO.

Well, not quite...  ;-/

>> Currently the compiler still emits
>> exception tables for such a target.
>> 
>> This patch makes sure that no exception tables are emitted if the target does
>> not support exceptions.  This allows us to remove a workaround in
>> TARGET_ASM_BYTE_OP in the nvptx port.

> LGTM (for UI_NONE there is no personality function either, so nothing to
> decode .gcc_except_table ...).
>
>> 2018-08-03  Tom de Vries  <tdevr...@suse.de>
>> 
>>      * common/config/nvptx/nvptx-common.c (nvptx_except_unwind_info): Return
>>      UI_NONE.
>>      * config/nvptx/nvptx.c (TARGET_ASM_BYTE_OP): Remove define.
>>      * except.c (output_function_exception_table): Do early exit if
>>      targetm_common.except_unwind_info (&global_options) == UI_NONE.

Yes, that made 'UI_NONE' work in one part of the code -- but there's more
to be done.  Until that's all done (if actually desirable?), I've
pushed to trunk branch commit 9611ce687904a22da2febbc97acba2ae0f0c3780
"nvptx: Set 'UI_TARGET' for 'TARGET_EXCEPT_UNWIND_INFO' [PR86660]", see
attached.

With that, we get 'diff's such as the following, for example:

     .visible .func _Z3foov
     {
     [...]
     $LFB0:
     [...]
     $LEHB0:
            {
     [...]
            }
     $LEHE0:
    +       /* BEGIN '.gcc_except_table'
    +$LLSDA0:
    +       .byte   0xff
    +       .byte   0xff
    +       .byte   0x3
    +       .byte   0xd
    +       .byte   [4]: $LEHB0 - $LFB0
    +       .byte   [4]: $LEHE0 - $LEHB0
    +       .byte   0
    +       .byte   0
    +       .byte   0
    +       .byte   0
    +
    +       .byte   0
    +       END '.gcc_except_table' */
     }


Grüße
 Thomas


>From 9611ce687904a22da2febbc97acba2ae0f0c3780 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <tschwi...@baylibre.com>
Date: Tue, 11 Feb 2025 17:23:28 +0100
Subject: [PATCH] nvptx: Set 'UI_TARGET' for 'TARGET_EXCEPT_UNWIND_INFO'
 [PR86660]

Subversion r263265 (Git commit 77e0a97acf7b00c1e68e4738fdf275a4cffc2e50)
"[nvptx] Ignore c++ exceptions", originally had set 'UI_TARGET', but as part of
Subversion r263287 (Git commit d989dba8ef02c2406b7c9e62b352197dffc6b880)
"[c++] Don't emit exception tables for UI_NONE", then switched to 'UI_NONE'.

I understand the intention of using 'UI_NONE' like this, and it happens to work
in a lot of cases, but there are ICEs elsewhere: code paths where we run into
'internal compiler error: in get_personality_function, at expr.cc:13512':

    13494 /* Extracts the personality function of DECL and returns the corresponding
    13495    libfunc.  */
    13496
    13497 rtx
    13498 get_personality_function (tree decl)
    13499 {
    13500   tree personality = DECL_FUNCTION_PERSONALITY (decl);
    13501   enum eh_personality_kind pk;
    13502
    13503   pk = function_needs_eh_personality (DECL_STRUCT_FUNCTION (decl));
    13504   if (pk == eh_personality_none)
    13505     return NULL;
    13506
    13507   if (!personality
    13508       && pk == eh_personality_any)
    13509     personality = lang_hooks.eh_personality ();
    13510
    13511   if (pk == eh_personality_lang)
    13512     gcc_assert (personality != NULL_TREE);
    13513
    13514   return XEXP (DECL_RTL (personality), 0);
    13515 }

..., where 'lang_hooks.eh_personality ()' ends up calling
'gcc/expr.cc:build_personality_function', and we 'return NULL;' for 'UI_NONE':

    13448 /* Build a decl for a personality function given a language prefix.  */
    13449
    13450 tree
    13451 build_personality_function (const char *lang)
    13452 {
    13453   const char *unwind_and_version;
    13454   tree decl, type;
    13455   char *name;
    13456
    13457   switch (targetm_common.except_unwind_info (&global_options))
    13458     {
    13459     case UI_NONE:
    13460       return NULL;
    [...]

(Comparing to nvptx' current use of 'UI_NONE', this problem (ICEs mentioned
above) is way more prevalent for GCN.)

The GCC internals documentation indeed states, 'gcc/doc/tm.texi':

    @deftypefn {Common Target Hook} {enum unwind_info_type} TARGET_EXCEPT_UNWIND_INFO (struct gcc_options *@var{opts})
    This hook defines the mechanism that will be used for exception handling
    by the target.  If the target has ABI specified unwind tables, the hook
    should return @code{UI_TARGET}.  If the target is to use the
    @code{setjmp}/@code{longjmp}-based exception handling scheme, the hook
    should return @code{UI_SJLJ}.  If the target supports DWARF 2 frame unwind
    information, the hook should return @code{UI_DWARF2}.

    A target may, if exceptions are disabled, choose to return @code{UI_NONE}.
    This may end up simplifying other parts of target-specific code.  [...]

Here, note: "if exceptions are disabled" (meaning: '-fno-exceptions' etc.) may
"return @code{UI_NONE}".  That's what other back ends do with code like:

    /* For simplicity elsewhere in this file, indicate that all unwind
       info is disabled if we're not emitting unwind tables.  */
    if (!opts->x_flag_exceptions && !opts->x_flag_unwind_tables)
      return UI_NONE;
    else
      return UI_TARGET;

The corresponding "simplifying other parts of target-specific code"/
"simplicity elsewhere" would then be the early returns from
'TARGET_ASM_UNWIND_EMIT', 'ARM_OUTPUT_FN_UNWIND', etc. for
'TARGET_EXCEPT_UNWIND_INFO != UI_TARGET' (that is, for 'UI_NONE').

>From the documentation (and implementation), however, it does *not* follow that
if a target doesn't implement support for exception handling, it may just set
'UI_NONE' for 'TARGET_EXCEPT_UNWIND_INFO'.

Therefore, switch (back) to 'UI_TARGET', implementing some basic support for
'exception_section': discard (via a PTX comment block) whatever GCC writes into
it.

With that, all these 'internal compiler error: in get_personality_function'
test cases turn into PASS, or UNSUPPORTED ('exception handling not supported'),
or re-classify into a few other, already known issues.

(In case that use of 'UI_NONE' like originally intended really makes sense, and
is preferable over this 'UI_TARGET' solution, then more work will be necessary
for implementing the missing parts, where 'UI_NONE' currently isn't handled.)

	PR target/86660
	gcc/
	* common/config/nvptx/nvptx-common.cc (nvptx_except_unwind_info):
	'return UI_TARGET;'.
	* config/nvptx/nvptx.cc (nvptx_assemble_integer): Handle
	'exception_section'.
	(nvptx_output_section_asm_op, nvptx_asm_init_sections): New
	functions.
	(TARGET_ASM_INIT_SECTIONS): '#define'.
	* config/nvptx/nvptx.h (TEXT_SECTION_ASM_OP, DATA_SECTION_ASM_OP):
	Don't '#define'.
	(ASM_OUTPUT_DWARF_DELTA): '#define'.
---
 gcc/common/config/nvptx/nvptx-common.cc |  2 +-
 gcc/config/nvptx/nvptx.cc               | 58 +++++++++++++++++++++++++
 gcc/config/nvptx/nvptx.h                | 19 ++++++--
 3 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/gcc/common/config/nvptx/nvptx-common.cc b/gcc/common/config/nvptx/nvptx-common.cc
index 84c241f141f..0af5f75bfc7 100644
--- a/gcc/common/config/nvptx/nvptx-common.cc
+++ b/gcc/common/config/nvptx/nvptx-common.cc
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 enum unwind_info_type
 nvptx_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED)
 {
-  return UI_NONE;
+  return UI_TARGET;
 }
 
 #undef TARGET_HAVE_NAMED_SECTIONS
diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
index 96f258c5573..af952a29796 100644
--- a/gcc/config/nvptx/nvptx.cc
+++ b/gcc/config/nvptx/nvptx.cc
@@ -2333,6 +2333,13 @@ nvptx_assemble_value (unsigned HOST_WIDE_INT val, unsigned size)
 static bool
 nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
 {
+  if (in_section == exception_section)
+    {
+      gcc_checking_assert (!init_frag.active);
+      /* Just use the default machinery; it's not getting used, anyway.  */
+      return default_assemble_integer (x, size, aligned_p);
+    }
+
   gcc_checking_assert (init_frag.active);
 
   HOST_WIDE_INT val = 0;
@@ -5991,6 +5998,55 @@ nvptx_record_offload_symbol (tree decl)
     }
 }
 
+/* Fake "sections support", just for 'exception_section'.  */
+
+static void
+nvptx_output_section_asm_op (const char *directive)
+{
+  static char prev_section = '?';
+
+  gcc_checking_assert (directive[1] == '\0');
+  const char new_section = directive[0];
+  gcc_checking_assert (new_section != prev_section);
+  switch (new_section)
+    {
+    case 'T':
+    case 'D':
+      if (prev_section == 'E')
+	/* We're leaving the 'exception_section'.  End the comment block.  */
+	fprintf (asm_out_file, "\tEND '.gcc_except_table' */\n");
+      break;
+    case 'E':
+      /* We're entering the 'exception_section'.  Put into a comment block
+	 whatever GCC decides to emit.  We assume:
+           - No nested comment blocks.
+           - Going to leave 'exception_section' before end of file.
+	 Should any of these ever get violated, this will result in PTX-level
+	 syntax errors.  */
+      fprintf (asm_out_file, "\t/* BEGIN '.gcc_except_table'\n");
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  prev_section = new_section;
+}
+
+static void
+nvptx_asm_init_sections (void)
+{
+  /* Like '#define TEXT_SECTION_ASM_OP ""', just with different 'callback'.  */
+  text_section = get_unnamed_section (SECTION_CODE,
+				      nvptx_output_section_asm_op, "T");
+  /* Like '#define DATA_SECTION_ASM_OP ""', just with different 'callback'.  */
+  data_section = get_unnamed_section (SECTION_WRITE,
+				      nvptx_output_section_asm_op, "D");
+  /* In order to later be able to recognize the 'exception_section', we set it
+     up here, instead of letting 'gcc/except.cc:switch_to_exception_section'
+     pick the 'data_section'.  */
+  exception_section = get_unnamed_section (0,
+					   nvptx_output_section_asm_op, "E");
+}
+
 /* Implement TARGET_ASM_FILE_START.  Write the kinds of things ptxas expects
    at the start of a file.  */
 
@@ -7745,6 +7801,8 @@ nvptx_asm_output_def_from_decls (FILE *stream, tree name,
 #undef TARGET_END_CALL_ARGS
 #define TARGET_END_CALL_ARGS nvptx_end_call_args
 
+#undef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS nvptx_asm_init_sections
 #undef TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START nvptx_file_start
 #undef TARGET_ASM_FILE_END
diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h
index 4b51d176103..c21e7cb960d 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -273,9 +273,6 @@ struct GTY(()) machine_function
 
 #define DEBUGGER_REGNO(N) N
 
-#define TEXT_SECTION_ASM_OP ""
-#define DATA_SECTION_ASM_OP ""
-
 #undef  ASM_GENERATE_INTERNAL_LABEL
 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM)		\
   do								\
@@ -384,4 +381,20 @@ struct GTY(()) machine_function
    Tell it to instead link against the innocuous libgcc.  */
 #define LIBSTDCXX "gcc"
 
+/* The default doesn't fly ('internal compiler error: in simplify_subreg' when
+   'dw2_assemble_integer' -> 'assemble_integer' attempts to simplify
+   '(minus:DI (symbol_ref:DI ("$LEHB0")) (symbol_ref:DI ("$LFB3")))', for
+   example.  Just emit something; it's not getting used, anyway.  */
+#define ASM_OUTPUT_DWARF_DELTA(STREAM, SIZE, LABEL1, LABEL2) \
+  do \
+    { \
+      fprintf (STREAM, "%s[%d]: ", targetm.asm_out.byte_op, SIZE); \
+      const char *label1 = LABEL1; \
+      assemble_name_raw (STREAM, label1 ? label1 : "*nil"); \
+      fprintf (STREAM, " - "); \
+      const char *label2 = LABEL2; \
+      assemble_name_raw (STREAM, label2 ? label2 : "*nil"); \
+    } \
+  while (0)
+
 #endif /* GCC_NVPTX_H */
-- 
2.34.1

Reply via email to