The "io", "io_low", and "address" attributes require to asm output the definition of respective symbols in a manner that was not supported until the introduction of the new target hook TARGET_ASM_VARIABLE.
The previous implementation of these attributes abused tls_common_section which is a noswitch section. Notice that the middle-end doesn't allow to introduce own, custom noswitch sections. The tls_comm_section->noswitch.callback allowed for a custom asm output regardless of -f[no-]data-sections and -f[no-]common. However, it would not work with checking enabled due to varasm.cc::assemble_variable()'s /* Emulated TLS had better not get this far. */ gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl)); This patch avoids that hack and uses the new TARGET_ASM_VARIABLE target hook to output variables with the mentioned attributes. Ok for trunk? Johann -- AVR: target/112952 - Use new TARGET_ASM_VARIABLE for io, io_low, address. The "io", "io_low", and "address" attributes require to asm output the definition of respective symbols in a manner that was not supported until the introduction of the new target hook TARGET_ASM_VARIABLE. The previous implementation of these attributes abused tls_common_section which is a noswitch section. Notice that the middle-end doesn't allow to introduce own, custom noswitch sections. The tls_comm_section->noswitch.callback allowed for a custom asm output regardless of -f[no-]data-sections and -f[no-]common. However, it would not work with checking enabled due to varasm.cc::assemble_variable()'s /* Emulated TLS had better not get this far. */ gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl)); This patch avoids that hack and uses the new TARGET_ASM_VARIABLE target hook to output variables with the mentioned attributes. PR target/112952 gcc/ * config/avr/avr.cc (avr_output_addr_attrib): Rename and rewrite to avr_asm_variable. (avr_asm_init_sections): Leave tls_comm_section alone. (avr_encode_section_info) [io, io_low, address]: Don't abuse tls_comm_section. (TARGET_ASM_VARIABLE): New define to avr_asm_variable.
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 05a6905b5d6..a326d029412 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -11689,24 +11689,25 @@ avr_output_progmem_section_asm_op (const char *data) } -/* A noswitch section callback to output symbol definitions for - attributes "io", "io_low" and "address". */ +/* Implement `TARGET_ASM_VARIABLE'. */ +/* Output symbol definitions for attributes "io", "io_low" and "address". + This hook is the only way to output the definitions in the required way + since the middle-end makes assumptions on the asm representation that + don't hold for these attributes. */ static bool -avr_output_addr_attrib (tree decl, const char *name, - unsigned HOST_WIDE_INT /* size */, - unsigned HOST_WIDE_INT /* align */) +avr_asm_variable (FILE *stream, tree decl, const char *name) { - gcc_assert (DECL_RTL_SET_P (decl)); + rtx mem, symbol; - FILE *stream = asm_out_file; - bool local_p = ! DECL_WEAK (decl) && ! TREE_PUBLIC (decl); - rtx symbol, mem = DECL_RTL (decl); - - if (mem != NULL_RTX && MEM_P (mem) - && SYMBOL_REF_P ((symbol = XEXP (mem, 0))) + if (VAR_P (decl) + && DECL_RTL_SET_P (decl) + && MEM_P (mem = DECL_RTL (decl)) + && SYMBOL_REF_P (symbol = XEXP (mem, 0)) && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS))) { + bool local_p = ! DECL_WEAK (decl) && ! TREE_PUBLIC (decl); + if (! local_p) { fprintf (stream, "\t%s\t", DECL_WEAK (decl) ? ".weak" : ".globl"); @@ -11735,8 +11736,6 @@ avr_output_addr_attrib (tree decl, const char *name, return true; } - gcc_unreachable (); - return false; } @@ -11754,7 +11753,6 @@ avr_asm_init_sections (void) readonly_data_section->unnamed.callback = avr_output_data_section_asm_op; data_section->unnamed.callback = avr_output_data_section_asm_op; bss_section->unnamed.callback = avr_output_bss_section_asm_op; - tls_comm_section->noswitch.callback = avr_output_addr_attrib; } @@ -11974,18 +11972,11 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p) } else { - /* PR112952: The only way to output a variable declaration in a - custom manner is by means of a noswitch section callback. - There are only three noswitch sections: comm_section, - lcomm_section and tls_comm_section. And there is no way to - wire a custom noswitch section to a decl. As lcomm_section - is bypassed with -fdata-sections -fno-common, there is no - other way than making use of tls_comm_section. As we are - using that section anyway, also use it in the public case. */ - - DECL_COMMON (decl) = 1; + /* PR112952: Thanks to TARGET_ASM_VARIABLE, we can output + a variable / symbol definition in a custom way entirely. + There's no more need to abuse tls_comm_section. */ + set_decl_section_name (decl, (const char *) nullptr); - set_decl_tls_model (decl, (tls_model) 2); } } } @@ -16076,6 +16067,9 @@ avr_use_lra_p () #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue +#undef TARGET_ASM_VARIABLE +#define TARGET_ASM_VARIABLE avr_asm_variable + #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE avr_function_value #undef TARGET_LIBCALL_VALUE