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 ();
> +      }
>      }
>  }
>  

Reply via email to