diff options
author | Thomas Schwinge <tschwinge@baylibre.com> | 2025-02-11 17:23:28 +0100 |
---|---|---|
committer | Thomas Schwinge <tschwinge@baylibre.com> | 2025-02-14 22:33:25 +0100 |
commit | 2b9bdb2d286e6872f4195ba2e710130cf6b2805d (patch) | |
tree | 1de585330283ab8ef72e8164cd01e1e8ae17ab71 /gcc | |
parent | 9611ce687904a22da2febbc97acba2ae0f0c3780 (diff) | |
download | gcc-2b9bdb2d286e6872f4195ba2e710130cf6b2805d.zip gcc-2b9bdb2d286e6872f4195ba2e710130cf6b2805d.tar.gz gcc-2b9bdb2d286e6872f4195ba2e710130cf6b2805d.tar.bz2 |
GCN: Set 'UI_TARGET' for 'TARGET_EXCEPT_UNWIND_INFO' [PR94282, PR113331]
In commit 7f1989249e25af6fc0f124452efa24b3796b767a
"[gcn] Set 'UI_NONE' for 'TARGET_EXCEPT_UNWIND_INFO' [PR94282]", we've copied
the 'UI_NONE' idea from nvptx to GCN.
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 to 'UI_TARGET', allocating a "fake" 'exception_section'.
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. And, this change also
happens to resolve the class of errors identified in GCC PR113331
"AMDGCN: Compilation failure due to duplicate .LEHB<n>/.LEHE<n> symbols".
(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/94282
PR target/113331
gcc/
* common/config/gcn/gcn-common.cc (gcn_except_unwind_info): 'return UI_TARGET;'.
* config/gcn/gcn.cc (gcn_asm_init_sections): New function.
(TARGET_ASM_INIT_SECTIONS): '#define'.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/common/config/gcn/gcn-common.cc | 2 | ||||
-rw-r--r-- | gcc/config/gcn/gcn.cc | 22 |
2 files changed, 23 insertions, 1 deletions
diff --git a/gcc/common/config/gcn/gcn-common.cc b/gcc/common/config/gcn/gcn-common.cc index 193be59..66c944f 100644 --- a/gcc/common/config/gcn/gcn-common.cc +++ b/gcc/common/config/gcn/gcn-common.cc @@ -37,7 +37,7 @@ static const struct default_options gcn_option_optimization_table[] = static enum unwind_info_type gcn_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED) { - return UI_NONE; + return UI_TARGET; } #undef TARGET_EXCEPT_UNWIND_INFO diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index b0c06d5..48691c3 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -6722,6 +6722,26 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, oacc_get_fn_dim_size (cfun->decl, GOMP_DIM_VECTOR), name); } +/* Implement TARGET_ASM_INIT_SECTIONS. */ + +static void +gcn_asm_init_sections (void) +{ + /* With the default 'exception_section' (via + 'gcc/except.cc:switch_to_exception_section'), the assembler fails: + /tmp/ccTYJljP.s:95:2: error: changed section flags for .gcc_except_table, expected: 0x2 + .section .gcc_except_table,"aw",@progbits + ^ + The flags for '.gcc_except_table' don't match the pre-defined ones that + the assembler expects: 'SHF_ALLOC' ('a'), without 'SHF_WRITE' ('w'). + As we're not actually implementing exception handling, keep things simple, + and allocate a "fake" section. */ + exception_section = get_section (".fake_gcc_except_table", + SECTION_DEBUG /* '!SHF_ALLOC' */ + | SECTION_EXCLUDE /* 'SHF_EXCLUDE' */, + NULL); +} + /* Implement TARGET_ASM_SELECT_SECTION. Return the section into which EXP should be placed. */ @@ -7789,6 +7809,8 @@ gcn_dwarf_register_span (rtx rtl) #define TARGET_ARG_PARTIAL_BYTES gcn_arg_partial_bytes #undef TARGET_ASM_ALIGNED_DI_OP #define TARGET_ASM_ALIGNED_DI_OP "\t.8byte\t" +#undef TARGET_ASM_INIT_SECTIONS +#define TARGET_ASM_INIT_SECTIONS gcn_asm_init_sections #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START output_file_start #undef TARGET_ASM_FUNCTION_PROLOGUE |