Matthieu Longo <matthieu.lo...@arm.com> writes: > Architecture-specific CFI directives are currently declared an processed > among others architecture-independent CFI directives in gcc/dwarf2* files. > This approach creates confusion, specifically in the case of DWARF > instructions in the vendor space and using the same instruction code. > > Such a clash currently happen between DW_CFA_GNU_window_save (used on > SPARC) and DW_CFA_AARCH64_negate_ra_state (used on AArch64), and both > having the same instruction code 0x2d. > Then AArch64 compilers generates a SPARC CFI directive (.cfi_window_save) > instead of .cfi_negate_ra_state, contrarilly to what is expected in > [DWARF for the Arm 64-bit Architecture (AArch64)](https://github.com/ > ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst). > > This refactoring does not solve completely the problem, but improve the > situation by moving some of the processing of those directives (more > specifically their output in the assembly) to the backend via 2 target > hooks: > - DW_CFI_OPRND1_DESC: parse the first operand of the directive (if any). > - OUTPUT_CFI_DIRECTIVE: output the CFI directive as a string. > > Additionally, this patch also contains a renaming of an enum used for > return address mangling on AArch64. > > gcc/ChangeLog: > > * config/aarch64/aarch64.cc > (aarch64_output_cfi_directive): New hook for CFI directives. > (aarch64_dw_cfi_oprnd1_desc): Same. > (TARGET_OUTPUT_CFI_DIRECTIVE): Hook for output_cfi_directive. > (TARGET_DW_CFI_OPRND1_DESC): Hook for dw_cfi_oprnd1_desc. > * config/sparc/sparc.cc > (sparc_output_cfi_directive): New hook for CFI directives. > (sparc_dw_cfi_oprnd1_desc): Same. > (TARGET_OUTPUT_CFI_DIRECTIVE): Hook for output_cfi_directive. > (TARGET_DW_CFI_OPRND1_DESC): Hook for dw_cfi_oprnd1_desc. > * coretypes.h > (struct dw_cfi_node): Forward declaration of CFI type from > gcc/dwarf2out.h. > (enum dw_cfi_oprnd_type): Same. > * doc/tm.texi: Regenerated from doc/tm.texi.in. > * doc/tm.texi.in: Add doc for OUTPUT_CFI_DIRECTIVE and > DW_CFI_OPRND1_DESC. > * dwarf2cfi.cc > (struct dw_cfi_row): Update the description for window_save > and ra_mangled. > (cfi_equal_p): Adapt parameter of dw_cfi_oprnd1_desc. > (dwarf2out_frame_debug_cfa_negate_ra_state): Use AArch64 CFI > directive instead of the SPARC one. > (change_cfi_row): Use the right CFI directive's name for RA > mangling. > (output_cfi): Remove explicit architecture-specific CFI > directive DW_CFA_GNU_window_save that falls into default case. > (output_cfi_directive): Use target hook as default. > * dwarf2out.cc (dw_cfi_oprnd1_desc): Use target hook as default. > * dwarf2out.h (enum dw_cfi_oprnd_type): specify underlying type > of enum to allow forward declaration. > (dw_cfi_oprnd1_desc): Change type of parameter. > (output_cfi_directive): Use dw_cfi_ref instead of struct > dw_cfi_node *. > * target.def: Documentation for new hooks. > > libffi/ChangeLog: > > * include/ffi_cfi.h (cfi_negate_ra_state): Declare AArch64 cfi > directive. > > libgcc/ChangeLog: > > * config/aarch64/aarch64-asm.h (PACIASP): Replace SPARC CFI > directive by AArch64 one. > (AUTIASP): Same. > > libitm/ChangeLog: > > * config/aarch64/sjlj.S: Replace SPARC CFI directive by > AArch64 one. > > gcc/testsuite/ChangeLog: > > * g++.target/aarch64/pr94515-1.C: Replace SPARC CFI directive by > AArch64 one. > * g++.target/aarch64/pr94515-2.C: Same. > --- > gcc/config/aarch64/aarch64.cc | 32 +++++++++++++++++ > gcc/config/sparc/sparc.cc | 36 ++++++++++++++++++++ > gcc/coretypes.h | 6 ++++ > gcc/doc/tm.texi | 28 +++++++++++++++ > gcc/doc/tm.texi.in | 17 +++++++++ > gcc/dwarf2cfi.cc | 29 ++++++---------- > gcc/dwarf2out.cc | 13 ++++--- > gcc/dwarf2out.h | 10 +++--- > gcc/target.def | 20 +++++++++++ > gcc/testsuite/g++.target/aarch64/pr94515-1.C | 6 ++-- > gcc/testsuite/g++.target/aarch64/pr94515-2.C | 2 +- > libffi/include/ffi_cfi.h | 2 ++ > libgcc/config/aarch64/aarch64-asm.h | 4 +-- > libitm/config/aarch64/sjlj.S | 10 +++--- > 14 files changed, 176 insertions(+), 39 deletions(-)
Generally looks good to me. Most of the comments below are very minor, but there's also a question about the hook interface. > > [...] > @@ -12621,6 +12630,33 @@ sparc_output_dwarf_dtprel (FILE *file, int size, rtx > x) > fputs (")", file); > } > > +/* This is called from gcc/dwarf2cfi.cc via TARGET_OUTPUT_CFI_DIRECTIVE. > + It outputs SPARC-specific CFI directives (if any). */ I think we should use the same comments as for aarch64, i.e.: /* Implement TARGET_OUTPUT_CFI_DIRECTIVE. */ ... /* Implement TARGET_DW_CFI_OPRND1_DESC. */ The idea is that the hook descriptions in target.def/tm.texi should be self-contained. > +static bool > +sparc_output_cfi_directive (FILE *f, dw_cfi_ref cfi) > +{ > + if (cfi->dw_cfi_opc == DW_CFA_GNU_window_save) > + { > + fprintf (f, "\t.cfi_window_save\n"); > + return true; > + } > + return false; > +} > + > +/* This is called from gcc/dwarf2out.cc via TARGET_DW_CFI_OPRND1_DESC. > + It describes for the GTY machinery what parts of the first operand > + is used. */ > +static bool > +sparc_dw_cfi_oprnd1_desc (dw_cfi_ref cfi, dw_cfi_oprnd_type_ref oprnd_type) > +{ > + if (cfi->dw_cfi_opc == DW_CFA_GNU_window_save) > + { > + oprnd_type = dw_cfi_oprnd_unused; > + return true; > + } > + return false; > +} > + > /* Do whatever processing is required at the end of a file. */ > > static void > diff --git a/gcc/coretypes.h b/gcc/coretypes.h > index 0544bb8fd97..3b622961b7a 100644 > --- a/gcc/coretypes.h > +++ b/gcc/coretypes.h > @@ -141,6 +141,12 @@ struct gomp_single; > struct gomp_target; > struct gomp_teams; > > +/* Forward declaration of CFI's and DWARF's types. */ > +struct dw_cfi_node; > +using dw_cfi_ref = struct dw_cfi_node *; It'd be good to remove the corresponding typedef in dwarf2out.h. > +enum dw_cfi_oprnd_type: unsigned int; > +using dw_cfi_oprnd_type_ref = enum dw_cfi_oprnd_type &; IMO it'd better to avoid adding this, and instead just use dw_cfi_oprnd_type & directly. I think the use of typedefs for pointers (as for dw_cfi_ref) was more popular when the codebase was written in C, and where the typedef often saved on a struct/union/enum tag. I don't think it's something we should use for C++ references since it hides the fact that: void foo (dw_cfi_ref x, dw_cfi_ref y) { ... x = y; ... } is a normal copy whereas: void foo (dw_cfi_oprnd_type_ref x, dw_cfi_oprnd_type_ref y) { ... x = y; ... } isn't. > + > /* Subclasses of symtab_node, using indentation to show the class > hierarchy. */ > > [...] > diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in > index 64cea3b1eda..051217d68b1 100644 > --- a/gcc/doc/tm.texi.in > +++ b/gcc/doc/tm.texi.in > @@ -3108,7 +3108,20 @@ used in .eh_frame or .debug_frame is different from > that used in other > debug info sections. Given a GCC hard register number, this macro > should return the .eh_frame register number. The default is > @code{DEBUGGER_REGNO (@var{regno})}. > +@end defmac > + > + > +@defmac OUTPUT_CFI_DIRECTIVE (@var{f}, @var{cfi}) > + > +Define this macro if the target has additional CFI directives. Return > +true if an architecture-specific directive was found, false otherwise. > +@end defmac > + > +@defmac DW_CFI_OPRND1_DESC (@var{cfi}, @var{oprnd_type}) > > +Define this macro if the target has additional CFI directives. Return > +true if an architecture-specific directive was found and @var{oprnd_type} > +is set, false otherwise and @var{oprnd_type} is not modified. > @end defmac The new hooks are proper target hooks rather than macros (which is good!) so there's no need to have and document macros as well. (Macros are a hold-over from before target hooks existed.) > @defmac DWARF2_FRAME_REG_OUT (@var{regno}, @var{for_eh}) > [...] > @@ -1547,17 +1549,13 @@ dwarf2out_frame_debug_cfa_window_save (void) > cur_row->window_save = true; > } > > -/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_NEGATE_RA_STATE. > - Note: DW_CFA_GNU_window_save dwarf opcode is reused for toggling RA mangle > - state, this is a target specific operation on AArch64 and can only be used > - on other targets if they don't use the window save operation otherwise. > */ > +/*A subroutine of dwarf2out_frame_debug, process REG_CFA_NEGATE_RA_STATE. */ Nit: should be a space before "A subroutine ...". > > static void > dwarf2out_frame_debug_cfa_negate_ra_state (void) > { > dw_cfi_ref cfi = new_cfi (); > - > - cfi->dw_cfi_opc = DW_CFA_GNU_window_save; > + cfi->dw_cfi_opc = DW_CFA_AARCH64_negate_ra_state; > add_cfi (cfi); > cur_row->ra_mangled = !cur_row->ra_mangled; > } > [...] > diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc > index 357efaa5990..260593421df 100644 > --- a/gcc/dwarf2out.cc > +++ b/gcc/dwarf2out.cc > @@ -516,12 +516,11 @@ switch_to_frame_table_section (int for_eh, bool back) > /* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */ > > enum dw_cfi_oprnd_type > -dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi) > +dw_cfi_oprnd1_desc (dw_cfi_ref cfi) > { > - switch (cfi) > + switch (cfi->dw_cfi_opc) > { > case DW_CFA_nop: > - case DW_CFA_GNU_window_save: > case DW_CFA_remember_state: > case DW_CFA_restore_state: > return dw_cfi_oprnd_unused; > @@ -557,7 +556,13 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi) > return dw_cfi_oprnd_loc; > > default: > - gcc_unreachable (); > + { > + dw_cfi_oprnd_type oprnd_type; > + if (targetm.dw_cfi_oprnd1_desc (cfi, oprnd_type)) Could you say why passing opcode isn't enough? I guess this is to do with some of the changes that are coming later? I think the correspondong: > - return (cfi_oprnd_equal_p (dw_cfi_oprnd1_desc (opc), > + return (cfi_oprnd_equal_p (dw_cfi_oprnd1_desc (a), > &a->dw_cfi_oprnd1, &b->dw_cfi_oprnd1) > && cfi_oprnd_equal_p (dw_cfi_oprnd2_desc (opc), > &a->dw_cfi_oprnd2, &b->dw_cfi_oprnd2)); makes the corretness of cfi_equal_p a bit fuzzier/less obvious, since it seems that dw_cfi_oprnd1_desc (a) is checking something about a that is not checked for b. Thanks, Richard > + return oprnd_type; > + else > + gcc_unreachable (); > + } > } > } >