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