@@ -60,6 +60,7 @@
#include "opts.h"
#include "gimplify.h"
#include "dwarf2.h"
+#include "dwarf2out.h"
#include "gimple-iterator.h"
#include "tree-vectorizer.h"
#include "aarch64-cost-tables.h"
@@ -1450,6 +1451,32 @@ aarch64_dwarf_frame_reg_mode (int regno)
return default_dwarf_frame_reg_mode (regno);
}
+/* Implement TARGET_OUTPUT_CFI_DIRECTIVE. */
+static bool
+aarch64_output_cfi_directive (FILE *f, dw_cfi_ref cfi)
+{
+ bool found = false;
+ if (cfi->dw_cfi_opc == DW_CFA_AARCH64_negate_ra_state)
+ {
+ fprintf (f, "\t.cfi_negate_ra_state\n");
+ found = true;
+ }
+ return found;
+}
+
+/* Implement TARGET_DW_CFI_OPRND1_DESC. */
+static bool
+aarch64_dw_cfi_oprnd1_desc (dwarf_call_frame_info cfi_opc,
+ dw_cfi_oprnd_type &oprnd_type)
+{
+ if (cfi_opc == DW_CFA_AARCH64_negate_ra_state)
+ {
+ oprnd_type = dw_cfi_oprnd_unused;
+ return true;
+ }
+ return false;
+}
+
/* If X is a CONST_DOUBLE, return its bit representation as a constant
integer, otherwise return X unmodified. */
static rtx
@@ -30822,6 +30849,12 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_DWARF_FRAME_REG_MODE
#define TARGET_DWARF_FRAME_REG_MODE aarch64_dwarf_frame_reg_mode
+#undef TARGET_OUTPUT_CFI_DIRECTIVE
+#define TARGET_OUTPUT_CFI_DIRECTIVE aarch64_output_cfi_directive
+
+#undef TARGET_DW_CFI_OPRND1_DESC
+#define TARGET_DW_CFI_OPRND1_DESC aarch64_dw_cfi_oprnd1_desc
+
#undef TARGET_PROMOTED_TYPE
#define TARGET_PROMOTED_TYPE aarch64_promoted_type
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "tree-vector-builder.h"
#include "opts.h"
+#include "dwarf2out.h"
/* This file should be included last. */
#include "target-def.h"
@@ -681,6 +682,9 @@ static rtx sparc_libcall_value (machine_mode, const_rtx);
static bool sparc_function_value_regno_p (const unsigned int);
static unsigned HOST_WIDE_INT sparc_asan_shadow_offset (void);
static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
+static bool sparc_output_cfi_directive (FILE *, dw_cfi_ref);
+static bool sparc_dw_cfi_oprnd1_desc (dwarf_call_frame_info,
+ dw_cfi_oprnd_type &);
static void sparc_file_end (void);
static bool sparc_frame_pointer_required (void);
static bool sparc_can_eliminate (const int, const int);
@@ -878,6 +882,12 @@ char sparc_hard_reg_printed[8];
#define TARGET_ASM_OUTPUT_DWARF_DTPREL sparc_output_dwarf_dtprel
#endif
+#undef TARGET_OUTPUT_CFI_DIRECTIVE
+#define TARGET_OUTPUT_CFI_DIRECTIVE sparc_output_cfi_directive
+
+#undef TARGET_DW_CFI_OPRND1_DESC
+#define TARGET_DW_CFI_OPRND1_DESC sparc_dw_cfi_oprnd1_desc
+
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END sparc_file_end
@@ -12621,6 +12631,31 @@ sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
fputs (")", file);
}
+/* Implement TARGET_OUTPUT_CFI_DIRECTIVE. */
+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;
+}
+
+/* Implement TARGET_DW_CFI_OPRND1_DESC. */
+static bool
+sparc_dw_cfi_oprnd1_desc (dwarf_call_frame_info cfi_opc,
+ dw_cfi_oprnd_type &oprnd_type)
+{
+ if (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
@@ -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 *;
+enum dw_cfi_oprnd_type: int;
+enum dwarf_call_frame_info: int;
+
/* Subclasses of symtab_node, using indentation to show the class
hierarchy. */
@@ -3911,7 +3911,6 @@ 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 DWARF2_FRAME_REG_OUT (@var{regno}, @var{for_eh})
@@ -10050,6 +10049,21 @@ used to return a smaller mode than the raw mode to prevent call
clobbered parts of a register altering the frame register size
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_OUTPUT_CFI_DIRECTIVE (FILE * @var{f}, dw_cfi_ref @var{cfi})
+This hook handles architecture-specific CFI directives and prints
+them out to the assembly file @var{f}.
+Return true if a architecture-specific directive was found, false
+otherwise.
+@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_DW_CFI_OPRND1_DESC (dwarf_call_frame_info @var{cfi_opc}, dw_cfi_oprnd_type & @var{oprnd_type})
+This hook informs the caller what the architecture-specific directives
+takes as a first operand.
+Return true if a architecture-specific directive was found and
+@var{oprnd_type} is set, false otherwise and @var{oprnd_type} is not
+modified.
+@end deftypefn
+
@deftypefn {Target Hook} void TARGET_INIT_DWARF_REG_SIZES_EXTRA (tree @var{address})
If some registers are represented in Dwarf-2 unwind information in
multiple pieces, define this hook to fill in information about the
@@ -3108,7 +3108,6 @@ 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 DWARF2_FRAME_REG_OUT (@var{regno}, @var{for_eh})
@@ -6614,6 +6613,10 @@ the target supports DWARF 2 frame unwind information.
@hook TARGET_DWARF_FRAME_REG_MODE
+@hook TARGET_OUTPUT_CFI_DIRECTIVE
+
+@hook TARGET_DW_CFI_OPRND1_DESC
+
@hook TARGET_INIT_DWARF_REG_SIZES_EXTRA
@hook TARGET_ASM_TTYPE
@@ -69,10 +69,12 @@ struct GTY(()) dw_cfi_row
/* The expressions for any register column that is saved. */
cfi_vec reg_save;
- /* True if the register window is saved. */
+ /* SPARC extension for DW_CFA_GNU_window_save.
+ True if the register window is saved. */
bool window_save;
- /* True if the return address is in a mangled state. */
+ /* AArch64 extension for DW_CFA_AARCH64_negate_ra_state.
+ True if the return address is in a mangled state. */
bool ra_mangled;
};
@@ -801,8 +803,6 @@ cfi_oprnd_equal_p (enum dw_cfi_oprnd_type t, dw_cfi_oprnd *a, dw_cfi_oprnd *b)
static bool
cfi_equal_p (dw_cfi_ref a, dw_cfi_ref b)
{
- enum dwarf_call_frame_info opc;
-
/* Make things easier for our callers, including missing operands. */
if (a == b)
return true;
@@ -810,7 +810,7 @@ cfi_equal_p (dw_cfi_ref a, dw_cfi_ref b)
return false;
/* Obviously, the opcodes must match. */
- opc = a->dw_cfi_opc;
+ dwarf_call_frame_info opc = a->dw_cfi_opc;
if (opc != b->dw_cfi_opc)
return false;
@@ -1547,17 +1547,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. */
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;
}
@@ -2426,8 +2422,7 @@ change_cfi_row (dw_cfi_row *old_row, dw_cfi_row *new_row)
dw_cfi_ref cfi = new_cfi ();
gcc_assert (!old_row->window_save && !new_row->window_save);
- /* DW_CFA_GNU_window_save is reused for toggling RA mangle state. */
- cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+ cfi->dw_cfi_opc = DW_CFA_AARCH64_negate_ra_state;
add_cfi (cfi);
}
}
@@ -3516,9 +3511,6 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
dw2_asm_output_data_sleb128 (off, NULL);
break;
- case DW_CFA_GNU_window_save:
- break;
-
case DW_CFA_def_cfa_expression:
case DW_CFA_expression:
case DW_CFA_val_expression:
@@ -3631,10 +3623,6 @@ output_cfi_directive (FILE *f, dw_cfi_ref cfi)
}
break;
- case DW_CFA_GNU_window_save:
- fprintf (f, "\t.cfi_window_save\n");
- break;
-
case DW_CFA_def_cfa_expression:
case DW_CFA_expression:
case DW_CFA_val_expression:
@@ -3651,7 +3639,8 @@ output_cfi_directive (FILE *f, dw_cfi_ref cfi)
break;
default:
- gcc_unreachable ();
+ if (!targetm.output_cfi_directive (f, cfi))
+ gcc_unreachable ();
}
}
@@ -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 (dwarf_call_frame_info cfi)
{
switch (cfi)
{
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,14 +556,20 @@ 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))
+ return oprnd_type;
+ else
+ gcc_unreachable ();
+ }
}
}
/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used. */
enum dw_cfi_oprnd_type
-dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
+dw_cfi_oprnd2_desc (dwarf_call_frame_info cfi)
{
switch (cfi)
{
@@ -37,8 +37,7 @@ typedef struct dw_wide_int *dw_wide_int_ptr;
Information instructions. The register number, offset
and address fields are provided as possible operands;
their use is selected by the opcode field. */
-
-enum dw_cfi_oprnd_type {
+enum dw_cfi_oprnd_type: int {
dw_cfi_oprnd_unused,
dw_cfi_oprnd_reg_num,
dw_cfi_oprnd_offset,
@@ -405,12 +404,10 @@ extern void output_cfi (dw_cfi_ref, dw_fde_ref, int);
extern GTY(()) cfi_vec cie_cfi_vec;
/* Interface from dwarf2*.c to the rest of the compiler. */
-extern enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
- (enum dwarf_call_frame_info cfi);
-extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
- (enum dwarf_call_frame_info cfi);
+extern enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc (dwarf_call_frame_info cfi);
+extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc (dwarf_call_frame_info cfi);
-extern void output_cfi_directive (FILE *f, struct dw_cfi_node *cfi);
+extern void output_cfi_directive (FILE *f, dw_cfi_ref cfi);
extern void dwarf2out_emit_cfi (dw_cfi_ref cfi);
@@ -62,6 +62,20 @@ hook_bool_bool_gcc_optionsp_false (bool, struct gcc_options *)
return false;
}
+/* Generic hook that takes (dwarf_call_frame_info, dw_cfi_oprnd_type &) and
+ return false. */
+bool hook_bool_dwcfi_dwcfioprndtyperef_false (dwarf_call_frame_info,
+ dw_cfi_oprnd_type &)
+{
+ return false;
+}
+
+/* Generic hook that takes (FILE *, dw_cfi_ref) and return false. */
+bool hook_bool_FILEptr_dwcfiptr_false (FILE *, dw_cfi_ref)
+{
+ return false;
+}
+
/* Generic hook that takes const int, const int) and returns true. */
bool hook_bool_const_int_const_int_true (const int, const int)
{
@@ -27,6 +27,9 @@ extern bool hook_bool_void_false (void);
extern bool hook_bool_void_true (void);
extern bool hook_bool_bool_false (bool);
extern bool hook_bool_bool_gcc_optionsp_false (bool, struct gcc_options *);
+extern bool hook_bool_dwcfi_dwcfioprndtyperef_false (dwarf_call_frame_info,
+ dw_cfi_oprnd_type &);
+extern bool hook_bool_FILEptr_dwcfiptr_false (FILE *, dw_cfi_ref);
extern bool hook_bool_const_int_const_int_true (const int, const int);
extern bool hook_bool_mode_false (machine_mode);
extern bool hook_bool_mode_true (machine_mode);
@@ -4127,6 +4127,26 @@ clobbered parts of a register altering the frame register size",
machine_mode, (int regno),
default_dwarf_frame_reg_mode)
+/* Print out architecture-specific CFI directives to the assembly file. */
+DEFHOOK
+(output_cfi_directive,
+ "This hook handles architecture-specific CFI directives and prints\n\
+them out to the assembly file @var{f}.\n\
+Return true if a architecture-specific directive was found, false\n\
+otherwise.",
+ bool, (FILE * f, dw_cfi_ref cfi),
+ hook_bool_FILEptr_dwcfiptr_false)
+
+DEFHOOK
+(dw_cfi_oprnd1_desc,
+ "This hook informs the caller what the architecture-specific directives\n\
+takes as a first operand.\n\
+Return true if a architecture-specific directive was found and\n\
+@var{oprnd_type} is set, false otherwise and @var{oprnd_type} is not\n\
+modified.",
+ bool, (dwarf_call_frame_info cfi_opc, dw_cfi_oprnd_type & oprnd_type),
+ hook_bool_dwcfi_dwcfioprndtyperef_false)
+
/* If expand_builtin_init_dwarf_reg_sizes needs to fill in table
entries not corresponding directly to registers below
FIRST_PSEUDO_REGISTER, this hook should generate the necessary
@@ -1,4 +1,4 @@
-/* PR target/94515. Check .cfi_window_save with multiple return paths. */
+/* PR target/94515. Check .cfi_negate_ra_state with multiple return paths. */
/* { dg-do run } */
/* { dg-require-effective-target lp64 } */
/* { dg-additional-options "-O2 --save-temps" } */
@@ -38,7 +38,7 @@ int main ()
}
/* This check only works if there are two return paths in test and
- cfi_window_save is used for both instead of cfi_remember_state
+ cfi_negate_ra_state is used for both instead of cfi_remember_state
plus cfi_restore_state. This is currently the case with -O2. */
-/* { dg-final { scan-assembler-times {\t\.cfi_window_save\n} 4 } } */
+/* { dg-final { scan-assembler-times {\t\.cfi_negate_ra_state\n} 4 } } */
@@ -1,4 +1,4 @@
-/* PR target/94515. Check .cfi_window_save with multiple return paths. */
+/* PR target/94515. Check .cfi_negate_ra_state with multiple return paths. */
/* { dg-do run } */
/* { dg-require-effective-target lp64 } */
/* { dg-additional-options "-O2 -mbranch-protection=pac-ret" } */
@@ -72,8 +72,13 @@
#define DW_FIRST_ATE(name, value) enum dwarf_type { \
name = value
#define DW_END_ATE };
+#ifdef __cplusplus
+#define DW_FIRST_CFA(name, value) enum dwarf_call_frame_info: int { \
+ name = value
+#else
#define DW_FIRST_CFA(name, value) enum dwarf_call_frame_info { \
name = value
+#endif
#define DW_END_CFA };
#define DW_FIRST_IDX(name, value) enum dwarf_name_index_attribute { \
name = value
@@ -46,6 +46,7 @@
# define cfi_remember_state .cfi_remember_state
# define cfi_restore_state .cfi_restore_state
# define cfi_window_save .cfi_window_save
+# define cfi_negate_ra_state .cfi_negate_ra_state
# define cfi_personality(enc, exp) .cfi_personality enc, exp
# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
# define cfi_escape(...) .cfi_escape __VA_ARGS__
@@ -68,6 +69,7 @@
# define cfi_remember_state
# define cfi_restore_state
# define cfi_window_save
+# define cfi_negate_ra_state
# define cfi_personality(enc, exp)
# define cfi_lsda(enc, exp)
# define cfi_escape(...)
@@ -50,8 +50,8 @@
#if __ARM_FEATURE_PAC_DEFAULT & 3
# define PAC_FLAG FEATURE_1_PAC
-# define PACIASP hint 25; .cfi_window_save
-# define AUTIASP hint 29; .cfi_window_save
+# define PACIASP hint 25; .cfi_negate_ra_state
+# define AUTIASP hint 29; .cfi_negate_ra_state
#else
# define PAC_FLAG 0
# define PACIASP
@@ -31,20 +31,20 @@
#define AUTIBSP hint 31
#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
-# define cfi_window_save .cfi_window_save
-# define cfi_b_key_frame .cfi_b_key_frame
+# define cfi_negate_ra_state .cfi_negate_ra_state
+# define cfi_b_key_frame .cfi_b_key_frame
#else
-# define cfi_window_save
+# define cfi_negate_ra_state
# define cfi_b_key_frame
#endif
#if __ARM_FEATURE_PAC_DEFAULT & 1
-# define CFI_PAC_TOGGLE cfi_window_save
+# define CFI_PAC_TOGGLE cfi_negate_ra_state
# define CFI_PAC_KEY
# define PAC_AND_BTI PACIASP
# define AUT AUTIASP
#elif __ARM_FEATURE_PAC_DEFAULT & 2
-# define CFI_PAC_TOGGLE cfi_window_save
+# define CFI_PAC_TOGGLE cfi_negate_ra_state
# define CFI_PAC_KEY cfi_b_key_frame
# define PAC_AND_BTI PACIBSP
# define AUT AUTIBSP