public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature.
@ 2022-11-09 14:32 Srinath Parvathaneni
  2022-12-06 11:34 ` Srinath Parvathaneni
  2022-12-08 14:48 ` Richard Earnshaw
  0 siblings, 2 replies; 3+ messages in thread
From: Srinath Parvathaneni @ 2022-11-09 14:32 UTC (permalink / raw)
  To: gcc-patches; +Cc: richard.earnshaw, kyrylo.tkachov

[-- Attachment #1: Type: text/plain, Size: 16867 bytes --]

Hello,

This patch teaches the DWARF support in gcc about RA_AUTH_CODE pseudo hard-register and also 
updates the ".save", ".cfi_register", ".cfi_offset", ".cfi_restore" directives accordingly.
This patch also adds support to emit ".pacspval" directive when "pac ip, lr, sp" instruction
in generated in the assembly.

RA_AUTH_CODE register number is 107 and it's dwarf register number is 143.

Applying this patch on top of PACBTI series posted here
https://gcc.gnu.org/pipermail/gcc-patches/2022-August/599658.html and when compiling the following
test.c with "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard
fasynchronous-unwind-tables -g -O0 -S" command line options, the assembly output after this patch
looks like below:

$cat test.c

void fun1(int a);
void fun(int a,...)
{
  fun1(a);
}

int main()
{
  fun (10);
  return 0;
}

$ arm-none-eabi-gcc -march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard
-fasynchronous-unwind-tables -g -O0 -S test.s

Assembly output:
...
fun:
...
        .pacspval
        pac     ip, lr, sp
        .cfi_register 143, 12
        push    {r3, r7, ip, lr}
        .save {r3, r7, ra_auth_code, lr}
...
        .cfi_offset 143, -24
...
        .cfi_restore 143
...
        aut     ip, lr, sp
        bx      lr
...
main:
...
        .pacspval
        pac     ip, lr, sp
        .cfi_register 143, 12
        push    {r3, r7, ip, lr}
        .save {r3, r7, ra_auth_code, lr}
...
        .cfi_offset 143, -8
...
        .cfi_restore 143
...
        aut     ip, lr, sp
        bx      lr
...

Regression tested on arm-none-eabi target and found no regressions.

Ok for master?

Regards,
Srinath.

gcc/testsuite/ChangeLog:

2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * g++.target/arm/pac-1.C: New test.
        * gcc.target/arm/pac-9.c: New test.


2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * config/arm/aout.h (ra_auth_code): Add entry in enum.
        * config/arm/arm.cc (pac_emit): Declare new global boolean variable.
        (emit_multi_reg_push): Add RA_AUTH_CODE register to
        dwarf frame expression.
        (arm_emit_multi_reg_pop): Restore RA_AUTH_CODE register.
        (arm_expand_prologue): Update frame related infomration and reg notes
        for pac/pacbit insn.
        (arm_regno_class): Check for pac pseudo reigster.
        (arm_dbx_register_number): Assign ra_auth_code register number in dwarf.
        (arm_unwind_emit_sequence): Print .save directive with ra_auth_code
        register.
        (arm_unwind_emit_set): Add entry for IP_REGNUM in switch case.
        (arm_unwind_emit): Update REG_CFA_REGISTER case._
        (arm_conditional_register_usage): Mark ra_auth_code in fixed reigsters.
        * config/arm/arm.h (FIRST_PSEUDO_REGISTER): Modify.
        (IS_PAC_PSEUDO_REGNUM): Define.
        (enum reg_class): Add PAC_REG entry.
        * config/arm/arm.md (RA_AUTH_CODE): Define.

gcc/testsuite/ChangeLog:

2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * g++.target/arm/pac-1.C: New test.
        * gcc.target/arm/pac-9.c: Likewise.


###############     Attachment also inlined for ease of reply    ###############


diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
index b918ad3782fbee82320febb8b6e72ad615780261..ffeed45a678f17c63d5b42c21f020ca416cbf23f 100644
--- a/gcc/config/arm/aout.h
+++ b/gcc/config/arm/aout.h
@@ -74,7 +74,8 @@
   "wr8",   "wr9",   "wr10",  "wr11",				\
   "wr12",  "wr13",  "wr14",  "wr15",				\
   "wcgr0", "wcgr1", "wcgr2", "wcgr3",				\
-  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0"		\
+  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0",		\
+  "ra_auth_code"						\
 }
 #endif
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index a2dc3fc145c52d8381c54634687376089a47e704..91c400f12568156ed29bf5d5e59460bf887fbefb 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -820,7 +820,8 @@ extern const int arm_arch_cde_coproc_bits[];
 	s16-s31	      S	VFP variable (aka d8-d15).
 	vfpcc		Not a real register.  Represents the VFP condition
 			code flags.
-	vpr		Used to represent MVE VPR predication.  */
+	vpr		Used to represent MVE VPR predication.
+	ra_auth_code	Pseudo register to save PAC.  */
 
 /* The stack backtrace structure is as follows:
   fp points to here:  |  save code pointer  |      [fp]
@@ -861,7 +862,7 @@ extern const int arm_arch_cde_coproc_bits[];
   1,1,1,1,1,1,1,1,		\
   1,1,1,1,			\
   /* Specials.  */		\
-  1,1,1,1,1,1,1			\
+  1,1,1,1,1,1,1,1		\
 }
 
 /* 1 for registers not available across function calls.
@@ -891,7 +892,7 @@ extern const int arm_arch_cde_coproc_bits[];
   1,1,1,1,1,1,1,1,		\
   1,1,1,1,			\
   /* Specials.  */		\
-  1,1,1,1,1,1,1			\
+  1,1,1,1,1,1,1,1		\
 }
 
 #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
@@ -1067,10 +1068,10 @@ extern const int arm_arch_cde_coproc_bits[];
    && (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))
 
 /* The number of hard registers is 16 ARM + 1 CC + 1 SFP + 1 AFP
-   + 1 APSRQ + 1 APSRGE + 1 VPR.  */
+   + 1 APSRQ + 1 APSRGE + 1 VPR + 1 Pseudo register to save PAC.  */
 /* Intel Wireless MMX Technology registers add 16 + 4 more.  */
 /* VFP (VFP3) adds 32 (64) + 1 VFPCC.  */
-#define FIRST_PSEUDO_REGISTER   107
+#define FIRST_PSEUDO_REGISTER   108
 
 #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
 
@@ -1257,12 +1258,15 @@ extern int arm_regs_in_sequence[];
   CC_REGNUM, VFPCC_REGNUM,			\
   FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM,	\
   SP_REGNUM, PC_REGNUM, APSRQ_REGNUM,		\
-  APSRGE_REGNUM, VPR_REGNUM			\
+  APSRGE_REGNUM, VPR_REGNUM, RA_AUTH_CODE	\
 }
 
 #define IS_VPR_REGNUM(REGNUM) \
   ((REGNUM) == VPR_REGNUM)
 
+#define IS_PAC_PSEUDO_REGNUM(REGNUM) \
+  ((REGNUM) == RA_AUTH_CODE)
+
 /* Use different register alloc ordering for Thumb.  */
 #define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()
 
@@ -1301,6 +1305,7 @@ enum reg_class
   SFP_REG,
   AFP_REG,
   VPR_REG,
+  PAC_REG,
   GENERAL_AND_VPR_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
@@ -1331,6 +1336,7 @@ enum reg_class
   "SFP_REG",		\
   "AFP_REG",		\
   "VPR_REG",		\
+  "PAC_REG",		\
   "GENERAL_AND_VPR_REGS", \
   "ALL_REGS"		\
 }
@@ -1360,6 +1366,7 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00000040 }, /* SFP_REG */	\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000080 }, /* AFP_REG */	\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000400 }, /* VPR_REG.  */	\
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000800 }, /* PAC_REG.  */	\
   { 0x00005FFF, 0x00000000, 0x00000000, 0x00000400 }, /* GENERAL_AND_VPR_REGS.  */ \
   { 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000040F }  /* ALL_REGS.  */	\
 }
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 3c4722337fdd72586e0655e2009370ad7595fafc..414561624d2eacccc10395db757bfa3c638bb387 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -2452,6 +2452,9 @@ enum tls_reloc {
   TLS_DESCSEQ	/* GNU scheme */
 };
 
+/* True if PACBTI/PAC instruction is emitted.  */
+static bool pac_emit = false;
+
 /* The maximum number of insns to be used when loading a constant.  */
 inline static int
 arm_constant_limit (bool size_p)
@@ -22154,7 +22157,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
     {
       if (mask & (1 << i))
 	{
-	  reg = gen_rtx_REG (SImode, i);
+	  rtx reg1 = reg = gen_rtx_REG (SImode, i);
+	  if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
+	      && pac_emit)
+	    reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
 
 	  XVECEXP (par, 0, 0)
 	    = gen_rtx_SET (gen_frame_mem
@@ -22172,7 +22178,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
 	  if (dwarf_regs_mask & (1 << i))
 	    {
 	      tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx),
-				 reg);
+				 reg1);
 	      RTX_FRAME_RELATED_P (tmp) = 1;
 	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
 	    }
@@ -22185,7 +22191,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
     {
       if (mask & (1 << i))
 	{
-	  reg = gen_rtx_REG (SImode, i);
+	  rtx reg1 = reg = gen_rtx_REG (SImode, i);
+	  if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
+	      && pac_emit)
+	    reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
 
 	  XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
 
@@ -22196,7 +22205,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
 			       (SImode,
 				plus_constant (Pmode, stack_pointer_rtx,
 					       4 * j)),
-			       reg);
+			       reg1);
 	      RTX_FRAME_RELATED_P (tmp) = 1;
 	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
 	    }
@@ -22281,7 +22290,9 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
   for (j = 0, i = 0; j < num_regs; i++)
     if (saved_regs_mask & (1 << i))
       {
-        reg = gen_rtx_REG (SImode, i);
+	rtx reg1 = reg = gen_rtx_REG (SImode, i);
+	if (arm_current_function_pac_enabled_p () && i == IP_REGNUM && pac_emit)
+	  reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
         if ((num_regs == 1) && emit_update && !return_in_pc)
           {
             /* Emit single load with writeback.  */
@@ -22289,7 +22300,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
                                  gen_rtx_POST_INC (Pmode,
                                                    stack_pointer_rtx));
             tmp = emit_insn (gen_rtx_SET (reg, tmp));
-            REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+	    REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
             return;
           }
 
@@ -22303,7 +22314,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
         /* We need to maintain a sequence for DWARF info too.  As dwarf info
            should not have PC, skip PC.  */
         if (i != PC_REGNUM)
-          dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+	  dwarf = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
 
         j++;
       }
@@ -23541,9 +23552,14 @@ arm_expand_prologue (void)
          instruction will be added before the push of the clobbered IP
          (if necessary) by the bti pass.  */
       if (aarch_bti_enabled () && !clobber_ip)
-	emit_insn (gen_pacbti_nop ());
+	insn = emit_insn (gen_pacbti_nop ());
       else
-	emit_insn (gen_pac_nop ());
+	insn = emit_insn (gen_pac_nop ());
+
+      rtx dwarf = gen_rtx_SET (ip_rtx, gen_rtx_REG (SImode, RA_AUTH_CODE));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_CFA_REGISTER, dwarf);
+      pac_emit  = true;
     }
 
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
@@ -25602,6 +25618,9 @@ arm_regno_class (int regno)
   if (IS_VPR_REGNUM (regno))
     return VPR_REG;
 
+  if (IS_PAC_PSEUDO_REGNUM (regno))
+    return PAC_REG;
+
   if (TARGET_THUMB1)
     {
       if (regno == STACK_POINTER_REGNUM)
@@ -29573,6 +29592,9 @@ arm_dbx_register_number (unsigned int regno)
   if (IS_IWMMXT_REGNUM (regno))
     return 112 + regno - FIRST_IWMMXT_REGNUM;
 
+  if (IS_PAC_PSEUDO_REGNUM (regno))
+    return 143;
+
   return DWARF_FRAME_REGISTERS;
 }
 
@@ -29666,7 +29688,7 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
   gcc_assert (nregs);
 
   reg = REGNO (SET_SRC (XVECEXP (p, 0, 1)));
-  if (reg < 16)
+  if (reg < 16 || IS_PAC_PSEUDO_REGNUM (reg))
     {
       /* For -Os dummy registers can be pushed at the beginning to
 	 avoid separate stack pointer adjustment.  */
@@ -29723,6 +29745,8 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
 	 double precision register names.  */
       if (IS_VFP_REGNUM (reg))
 	asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
+      else if (IS_PAC_PSEUDO_REGNUM (reg))
+	asm_fprintf (asm_out_file, "ra_auth_code");
       else
 	asm_fprintf (out_file, "%r", reg);
 
@@ -29817,7 +29841,7 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
 	  /* Move from sp to reg.  */
 	  asm_fprintf (out_file, "\t.movsp %r\n", REGNO (e0));
 	}
-     else if (GET_CODE (e1) == PLUS
+      else if (GET_CODE (e1) == PLUS
 	      && REG_P (XEXP (e1, 0))
 	      && REGNO (XEXP (e1, 0)) == SP_REGNUM
 	      && CONST_INT_P (XEXP (e1, 1)))
@@ -29826,6 +29850,13 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
 	  asm_fprintf (out_file, "\t.movsp %r, #%d\n",
 		       REGNO (e0), (int)INTVAL(XEXP (e1, 1)));
 	}
+      else if (REGNO (e0) == IP_REGNUM && GET_CODE (e1) == UNSPEC)
+	{
+	  if (XINT (e1, 1) == UNSPEC_PAC_NOP)
+	    asm_fprintf (out_file, "\t.pacspval\n");
+	  else if (XINT (e1, 1) != UNSPEC_PACBTI_NOP)
+	    abort ();
+	}
       else
 	abort ();
       break;
@@ -29880,8 +29911,15 @@ arm_unwind_emit (FILE * out_file, rtx_insn *insn)
 	    src = SET_SRC (pat);
 	    dest = SET_DEST (pat);
 
-	    gcc_assert (src == stack_pointer_rtx);
+	    gcc_assert (src == stack_pointer_rtx
+			|| IS_PAC_PSEUDO_REGNUM (REGNO (src)));
 	    reg = REGNO (dest);
+
+	    if (IS_PAC_PSEUDO_REGNUM (REGNO (src)))
+	      {
+		pat = PATTERN (insn);
+		goto found;
+	      }
 	    asm_fprintf (out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
 			 reg + 0x90, reg);
 	  }
@@ -30590,6 +30628,9 @@ arm_conditional_register_usage (void)
 	global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
     }
 
+  if (TARGET_HAVE_PACBTI)
+    fixed_regs[RA_AUTH_CODE] = 0;
+
   /* The Q and GE bits are only accessed via special ACLE patterns.  */
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRGE_REGNUM);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6e86811ee05f54f0e4bec3a5e632e3bb541fc423..3aea721f9b82445f6b318fd09dcd3d260683baa7 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -42,6 +42,7 @@
    (APSRQ_REGNUM    104)	; Q bit pseudo register
    (APSRGE_REGNUM   105)	; GE bits pseudo register
    (VPR_REGNUM      106)	; Vector Predication Register - MVE register.
+   (RA_AUTH_CODE    107)	; Pseudo register to save PAC.
   ]
 )
 ;; 3rd operand to select_dominance_cc_mode
diff --git a/gcc/testsuite/g++.target/arm/pac-1.C b/gcc/testsuite/g++.target/arm/pac-1.C
new file mode 100644
index 0000000000000000000000000000000000000000..96a3ba51362e02a5fe90b517ee28c41e87024475
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/pac-1.C
@@ -0,0 +1,36 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -g -O0" } */
+
+__attribute__((noinline)) void
+fn1 (int a, int b, int c)
+{
+  if (a != b + c)
+    __builtin_abort ();
+  else
+    throw b+c;
+}
+
+int main ()
+{
+  int a = 120;
+  try
+    {
+      fn1 (a, 40, 80);
+    }
+  catch (int x)
+    {
+      if (x != a)
+        __builtin_abort ();
+      else
+	return 0;
+    }
+}
+
+/* { dg-final { scan-assembler-times "\.pacspval" 2 } } */
+/* { dg-final { scan-assembler-times "pac	ip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 1 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r4, r7, ra_auth_code, lr}" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
new file mode 100644
index 0000000000000000000000000000000000000000..283b6786e7fe50f8e3cddea5161743a7553fe6eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,32 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -fasynchronous-unwind-tables -g -O0" } */
+
+#include "stdio.h"
+
+__attribute__((noinline)) int
+fn1 (int a)
+{
+  const char *fmt = "branch-protection";
+  int fun1(int x,const char *fmt,int c,int d)
+    {
+      printf("string = %s\n",fmt);
+      return x+c+d;
+    }
+  return fun1(a,fmt,10,10);
+}
+
+int main (void)
+{
+  return fn1 (40);
+}
+
+/* { dg-final { scan-assembler-times "\.pacspval" 3 } } */
+/* { dg-final { scan-assembler-times "pac	ip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 3 } } */
+/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 2 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r3, r7, ra_auth_code, lr}" 1 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -12" 1 } } */




[-- Attachment #2: rb14831.patch --]
[-- Type: text/plain, Size: 13611 bytes --]

diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
index b918ad3782fbee82320febb8b6e72ad615780261..ffeed45a678f17c63d5b42c21f020ca416cbf23f 100644
--- a/gcc/config/arm/aout.h
+++ b/gcc/config/arm/aout.h
@@ -74,7 +74,8 @@
   "wr8",   "wr9",   "wr10",  "wr11",				\
   "wr12",  "wr13",  "wr14",  "wr15",				\
   "wcgr0", "wcgr1", "wcgr2", "wcgr3",				\
-  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0"		\
+  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0",		\
+  "ra_auth_code"						\
 }
 #endif
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index a2dc3fc145c52d8381c54634687376089a47e704..91c400f12568156ed29bf5d5e59460bf887fbefb 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -820,7 +820,8 @@ extern const int arm_arch_cde_coproc_bits[];
 	s16-s31	      S	VFP variable (aka d8-d15).
 	vfpcc		Not a real register.  Represents the VFP condition
 			code flags.
-	vpr		Used to represent MVE VPR predication.  */
+	vpr		Used to represent MVE VPR predication.
+	ra_auth_code	Pseudo register to save PAC.  */
 
 /* The stack backtrace structure is as follows:
   fp points to here:  |  save code pointer  |      [fp]
@@ -861,7 +862,7 @@ extern const int arm_arch_cde_coproc_bits[];
   1,1,1,1,1,1,1,1,		\
   1,1,1,1,			\
   /* Specials.  */		\
-  1,1,1,1,1,1,1			\
+  1,1,1,1,1,1,1,1		\
 }
 
 /* 1 for registers not available across function calls.
@@ -891,7 +892,7 @@ extern const int arm_arch_cde_coproc_bits[];
   1,1,1,1,1,1,1,1,		\
   1,1,1,1,			\
   /* Specials.  */		\
-  1,1,1,1,1,1,1			\
+  1,1,1,1,1,1,1,1		\
 }
 
 #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
@@ -1067,10 +1068,10 @@ extern const int arm_arch_cde_coproc_bits[];
    && (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))
 
 /* The number of hard registers is 16 ARM + 1 CC + 1 SFP + 1 AFP
-   + 1 APSRQ + 1 APSRGE + 1 VPR.  */
+   + 1 APSRQ + 1 APSRGE + 1 VPR + 1 Pseudo register to save PAC.  */
 /* Intel Wireless MMX Technology registers add 16 + 4 more.  */
 /* VFP (VFP3) adds 32 (64) + 1 VFPCC.  */
-#define FIRST_PSEUDO_REGISTER   107
+#define FIRST_PSEUDO_REGISTER   108
 
 #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
 
@@ -1257,12 +1258,15 @@ extern int arm_regs_in_sequence[];
   CC_REGNUM, VFPCC_REGNUM,			\
   FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM,	\
   SP_REGNUM, PC_REGNUM, APSRQ_REGNUM,		\
-  APSRGE_REGNUM, VPR_REGNUM			\
+  APSRGE_REGNUM, VPR_REGNUM, RA_AUTH_CODE	\
 }
 
 #define IS_VPR_REGNUM(REGNUM) \
   ((REGNUM) == VPR_REGNUM)
 
+#define IS_PAC_PSEUDO_REGNUM(REGNUM) \
+  ((REGNUM) == RA_AUTH_CODE)
+
 /* Use different register alloc ordering for Thumb.  */
 #define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()
 
@@ -1301,6 +1305,7 @@ enum reg_class
   SFP_REG,
   AFP_REG,
   VPR_REG,
+  PAC_REG,
   GENERAL_AND_VPR_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
@@ -1331,6 +1336,7 @@ enum reg_class
   "SFP_REG",		\
   "AFP_REG",		\
   "VPR_REG",		\
+  "PAC_REG",		\
   "GENERAL_AND_VPR_REGS", \
   "ALL_REGS"		\
 }
@@ -1360,6 +1366,7 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00000040 }, /* SFP_REG */	\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000080 }, /* AFP_REG */	\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000400 }, /* VPR_REG.  */	\
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000800 }, /* PAC_REG.  */	\
   { 0x00005FFF, 0x00000000, 0x00000000, 0x00000400 }, /* GENERAL_AND_VPR_REGS.  */ \
   { 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000040F }  /* ALL_REGS.  */	\
 }
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 3c4722337fdd72586e0655e2009370ad7595fafc..414561624d2eacccc10395db757bfa3c638bb387 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -2452,6 +2452,9 @@ enum tls_reloc {
   TLS_DESCSEQ	/* GNU scheme */
 };
 
+/* True if PACBTI/PAC instruction is emitted.  */
+static bool pac_emit = false;
+
 /* The maximum number of insns to be used when loading a constant.  */
 inline static int
 arm_constant_limit (bool size_p)
@@ -22154,7 +22157,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
     {
       if (mask & (1 << i))
 	{
-	  reg = gen_rtx_REG (SImode, i);
+	  rtx reg1 = reg = gen_rtx_REG (SImode, i);
+	  if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
+	      && pac_emit)
+	    reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
 
 	  XVECEXP (par, 0, 0)
 	    = gen_rtx_SET (gen_frame_mem
@@ -22172,7 +22178,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
 	  if (dwarf_regs_mask & (1 << i))
 	    {
 	      tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx),
-				 reg);
+				 reg1);
 	      RTX_FRAME_RELATED_P (tmp) = 1;
 	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
 	    }
@@ -22185,7 +22191,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
     {
       if (mask & (1 << i))
 	{
-	  reg = gen_rtx_REG (SImode, i);
+	  rtx reg1 = reg = gen_rtx_REG (SImode, i);
+	  if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
+	      && pac_emit)
+	    reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
 
 	  XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
 
@@ -22196,7 +22205,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
 			       (SImode,
 				plus_constant (Pmode, stack_pointer_rtx,
 					       4 * j)),
-			       reg);
+			       reg1);
 	      RTX_FRAME_RELATED_P (tmp) = 1;
 	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
 	    }
@@ -22281,7 +22290,9 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
   for (j = 0, i = 0; j < num_regs; i++)
     if (saved_regs_mask & (1 << i))
       {
-        reg = gen_rtx_REG (SImode, i);
+	rtx reg1 = reg = gen_rtx_REG (SImode, i);
+	if (arm_current_function_pac_enabled_p () && i == IP_REGNUM && pac_emit)
+	  reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
         if ((num_regs == 1) && emit_update && !return_in_pc)
           {
             /* Emit single load with writeback.  */
@@ -22289,7 +22300,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
                                  gen_rtx_POST_INC (Pmode,
                                                    stack_pointer_rtx));
             tmp = emit_insn (gen_rtx_SET (reg, tmp));
-            REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+	    REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
             return;
           }
 
@@ -22303,7 +22314,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
         /* We need to maintain a sequence for DWARF info too.  As dwarf info
            should not have PC, skip PC.  */
         if (i != PC_REGNUM)
-          dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+	  dwarf = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
 
         j++;
       }
@@ -23541,9 +23552,14 @@ arm_expand_prologue (void)
          instruction will be added before the push of the clobbered IP
          (if necessary) by the bti pass.  */
       if (aarch_bti_enabled () && !clobber_ip)
-	emit_insn (gen_pacbti_nop ());
+	insn = emit_insn (gen_pacbti_nop ());
       else
-	emit_insn (gen_pac_nop ());
+	insn = emit_insn (gen_pac_nop ());
+
+      rtx dwarf = gen_rtx_SET (ip_rtx, gen_rtx_REG (SImode, RA_AUTH_CODE));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_CFA_REGISTER, dwarf);
+      pac_emit  = true;
     }
 
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
@@ -25602,6 +25618,9 @@ arm_regno_class (int regno)
   if (IS_VPR_REGNUM (regno))
     return VPR_REG;
 
+  if (IS_PAC_PSEUDO_REGNUM (regno))
+    return PAC_REG;
+
   if (TARGET_THUMB1)
     {
       if (regno == STACK_POINTER_REGNUM)
@@ -29573,6 +29592,9 @@ arm_dbx_register_number (unsigned int regno)
   if (IS_IWMMXT_REGNUM (regno))
     return 112 + regno - FIRST_IWMMXT_REGNUM;
 
+  if (IS_PAC_PSEUDO_REGNUM (regno))
+    return 143;
+
   return DWARF_FRAME_REGISTERS;
 }
 
@@ -29666,7 +29688,7 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
   gcc_assert (nregs);
 
   reg = REGNO (SET_SRC (XVECEXP (p, 0, 1)));
-  if (reg < 16)
+  if (reg < 16 || IS_PAC_PSEUDO_REGNUM (reg))
     {
       /* For -Os dummy registers can be pushed at the beginning to
 	 avoid separate stack pointer adjustment.  */
@@ -29723,6 +29745,8 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
 	 double precision register names.  */
       if (IS_VFP_REGNUM (reg))
 	asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
+      else if (IS_PAC_PSEUDO_REGNUM (reg))
+	asm_fprintf (asm_out_file, "ra_auth_code");
       else
 	asm_fprintf (out_file, "%r", reg);
 
@@ -29817,7 +29841,7 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
 	  /* Move from sp to reg.  */
 	  asm_fprintf (out_file, "\t.movsp %r\n", REGNO (e0));
 	}
-     else if (GET_CODE (e1) == PLUS
+      else if (GET_CODE (e1) == PLUS
 	      && REG_P (XEXP (e1, 0))
 	      && REGNO (XEXP (e1, 0)) == SP_REGNUM
 	      && CONST_INT_P (XEXP (e1, 1)))
@@ -29826,6 +29850,13 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
 	  asm_fprintf (out_file, "\t.movsp %r, #%d\n",
 		       REGNO (e0), (int)INTVAL(XEXP (e1, 1)));
 	}
+      else if (REGNO (e0) == IP_REGNUM && GET_CODE (e1) == UNSPEC)
+	{
+	  if (XINT (e1, 1) == UNSPEC_PAC_NOP)
+	    asm_fprintf (out_file, "\t.pacspval\n");
+	  else if (XINT (e1, 1) != UNSPEC_PACBTI_NOP)
+	    abort ();
+	}
       else
 	abort ();
       break;
@@ -29880,8 +29911,15 @@ arm_unwind_emit (FILE * out_file, rtx_insn *insn)
 	    src = SET_SRC (pat);
 	    dest = SET_DEST (pat);
 
-	    gcc_assert (src == stack_pointer_rtx);
+	    gcc_assert (src == stack_pointer_rtx
+			|| IS_PAC_PSEUDO_REGNUM (REGNO (src)));
 	    reg = REGNO (dest);
+
+	    if (IS_PAC_PSEUDO_REGNUM (REGNO (src)))
+	      {
+		pat = PATTERN (insn);
+		goto found;
+	      }
 	    asm_fprintf (out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
 			 reg + 0x90, reg);
 	  }
@@ -30590,6 +30628,9 @@ arm_conditional_register_usage (void)
 	global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
     }
 
+  if (TARGET_HAVE_PACBTI)
+    fixed_regs[RA_AUTH_CODE] = 0;
+
   /* The Q and GE bits are only accessed via special ACLE patterns.  */
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRGE_REGNUM);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6e86811ee05f54f0e4bec3a5e632e3bb541fc423..3aea721f9b82445f6b318fd09dcd3d260683baa7 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -42,6 +42,7 @@
    (APSRQ_REGNUM    104)	; Q bit pseudo register
    (APSRGE_REGNUM   105)	; GE bits pseudo register
    (VPR_REGNUM      106)	; Vector Predication Register - MVE register.
+   (RA_AUTH_CODE    107)	; Pseudo register to save PAC.
   ]
 )
 ;; 3rd operand to select_dominance_cc_mode
diff --git a/gcc/testsuite/g++.target/arm/pac-1.C b/gcc/testsuite/g++.target/arm/pac-1.C
new file mode 100644
index 0000000000000000000000000000000000000000..96a3ba51362e02a5fe90b517ee28c41e87024475
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/pac-1.C
@@ -0,0 +1,36 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -g -O0" } */
+
+__attribute__((noinline)) void
+fn1 (int a, int b, int c)
+{
+  if (a != b + c)
+    __builtin_abort ();
+  else
+    throw b+c;
+}
+
+int main ()
+{
+  int a = 120;
+  try
+    {
+      fn1 (a, 40, 80);
+    }
+  catch (int x)
+    {
+      if (x != a)
+        __builtin_abort ();
+      else
+	return 0;
+    }
+}
+
+/* { dg-final { scan-assembler-times "\.pacspval" 2 } } */
+/* { dg-final { scan-assembler-times "pac	ip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 1 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r4, r7, ra_auth_code, lr}" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
new file mode 100644
index 0000000000000000000000000000000000000000..283b6786e7fe50f8e3cddea5161743a7553fe6eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,32 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -fasynchronous-unwind-tables -g -O0" } */
+
+#include "stdio.h"
+
+__attribute__((noinline)) int
+fn1 (int a)
+{
+  const char *fmt = "branch-protection";
+  int fun1(int x,const char *fmt,int c,int d)
+    {
+      printf("string = %s\n",fmt);
+      return x+c+d;
+    }
+  return fun1(a,fmt,10,10);
+}
+
+int main (void)
+{
+  return fn1 (40);
+}
+
+/* { dg-final { scan-assembler-times "\.pacspval" 3 } } */
+/* { dg-final { scan-assembler-times "pac	ip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 3 } } */
+/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 2 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r3, r7, ra_auth_code, lr}" 1 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -12" 1 } } */




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature.
  2022-11-09 14:32 [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature Srinath Parvathaneni
@ 2022-12-06 11:34 ` Srinath Parvathaneni
  2022-12-08 14:48 ` Richard Earnshaw
  1 sibling, 0 replies; 3+ messages in thread
From: Srinath Parvathaneni @ 2022-12-06 11:34 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw; +Cc: Kyrylo Tkachov, Srinath Parvathaneni

[-- Attachment #1: Type: text/plain, Size: 19020 bytes --]

Ping!!
________________________________
From: Gcc-patches <gcc-patches-bounces+srinath.parvathaneni=arm.com@gcc.gnu.org> on behalf of Srinath Parvathaneni via Gcc-patches <gcc-patches@gcc.gnu.org>
Sent: 09 November 2022 14:32
To: gcc-patches@gcc.gnu.org <gcc-patches@gcc.gnu.org>
Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
Subject: [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature.

Hello,

This patch teaches the DWARF support in gcc about RA_AUTH_CODE pseudo hard-register and also
updates the ".save", ".cfi_register", ".cfi_offset", ".cfi_restore" directives accordingly.
This patch also adds support to emit ".pacspval" directive when "pac ip, lr, sp" instruction
in generated in the assembly.

RA_AUTH_CODE register number is 107 and it's dwarf register number is 143.

Applying this patch on top of PACBTI series posted here
https://gcc.gnu.org/pipermail/gcc-patches/2022-August/599658.html and when compiling the following
test.c with "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard
fasynchronous-unwind-tables -g -O0 -S" command line options, the assembly output after this patch
looks like below:

$cat test.c

void fun1(int a);
void fun(int a,...)
{
  fun1(a);
}

int main()
{
  fun (10);
  return 0;
}

$ arm-none-eabi-gcc -march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard
-fasynchronous-unwind-tables -g -O0 -S test.s

Assembly output:
...
fun:
...
        .pacspval
        pac     ip, lr, sp
        .cfi_register 143, 12
        push    {r3, r7, ip, lr}
        .save {r3, r7, ra_auth_code, lr}
...
        .cfi_offset 143, -24
...
        .cfi_restore 143
...
        aut     ip, lr, sp
        bx      lr
...
main:
...
        .pacspval
        pac     ip, lr, sp
        .cfi_register 143, 12
        push    {r3, r7, ip, lr}
        .save {r3, r7, ra_auth_code, lr}
...
        .cfi_offset 143, -8
...
        .cfi_restore 143
...
        aut     ip, lr, sp
        bx      lr
...

Regression tested on arm-none-eabi target and found no regressions.

Ok for master?

Regards,
Srinath.

gcc/testsuite/ChangeLog:

2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * g++.target/arm/pac-1.C: New test.
        * gcc.target/arm/pac-9.c: New test.


2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * config/arm/aout.h (ra_auth_code): Add entry in enum.
        * config/arm/arm.cc (pac_emit): Declare new global boolean variable.
        (emit_multi_reg_push): Add RA_AUTH_CODE register to
        dwarf frame expression.
        (arm_emit_multi_reg_pop): Restore RA_AUTH_CODE register.
        (arm_expand_prologue): Update frame related infomration and reg notes
        for pac/pacbit insn.
        (arm_regno_class): Check for pac pseudo reigster.
        (arm_dbx_register_number): Assign ra_auth_code register number in dwarf.
        (arm_unwind_emit_sequence): Print .save directive with ra_auth_code
        register.
        (arm_unwind_emit_set): Add entry for IP_REGNUM in switch case.
        (arm_unwind_emit): Update REG_CFA_REGISTER case._
        (arm_conditional_register_usage): Mark ra_auth_code in fixed reigsters.
        * config/arm/arm.h (FIRST_PSEUDO_REGISTER): Modify.
        (IS_PAC_PSEUDO_REGNUM): Define.
        (enum reg_class): Add PAC_REG entry.
        * config/arm/arm.md (RA_AUTH_CODE): Define.

gcc/testsuite/ChangeLog:

2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>

        * g++.target/arm/pac-1.C: New test.
        * gcc.target/arm/pac-9.c: Likewise.


###############     Attachment also inlined for ease of reply    ###############


diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
index b918ad3782fbee82320febb8b6e72ad615780261..ffeed45a678f17c63d5b42c21f020ca416cbf23f 100644
--- a/gcc/config/arm/aout.h
+++ b/gcc/config/arm/aout.h
@@ -74,7 +74,8 @@
   "wr8",   "wr9",   "wr10",  "wr11",                           \
   "wr12",  "wr13",  "wr14",  "wr15",                           \
   "wcgr0", "wcgr1", "wcgr2", "wcgr3",                          \
-  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0"         \
+  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0",                \
+  "ra_auth_code"                                               \
 }
 #endif

diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index a2dc3fc145c52d8381c54634687376089a47e704..91c400f12568156ed29bf5d5e59460bf887fbefb 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -820,7 +820,8 @@ extern const int arm_arch_cde_coproc_bits[];
         s16-s31       S  VFP variable (aka d8-d15).
         vfpcc           Not a real register.  Represents the VFP condition
                         code flags.
-       vpr             Used to represent MVE VPR predication.  */
+       vpr             Used to represent MVE VPR predication.
+       ra_auth_code    Pseudo register to save PAC.  */

 /* The stack backtrace structure is as follows:
   fp points to here:  |  save code pointer  |      [fp]
@@ -861,7 +862,7 @@ extern const int arm_arch_cde_coproc_bits[];
   1,1,1,1,1,1,1,1,             \
   1,1,1,1,                     \
   /* Specials.  */             \
-  1,1,1,1,1,1,1                        \
+  1,1,1,1,1,1,1,1              \
 }

 /* 1 for registers not available across function calls.
@@ -891,7 +892,7 @@ extern const int arm_arch_cde_coproc_bits[];
   1,1,1,1,1,1,1,1,             \
   1,1,1,1,                     \
   /* Specials.  */             \
-  1,1,1,1,1,1,1                        \
+  1,1,1,1,1,1,1,1              \
 }

 #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
@@ -1067,10 +1068,10 @@ extern const int arm_arch_cde_coproc_bits[];
    && (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))

 /* The number of hard registers is 16 ARM + 1 CC + 1 SFP + 1 AFP
-   + 1 APSRQ + 1 APSRGE + 1 VPR.  */
+   + 1 APSRQ + 1 APSRGE + 1 VPR + 1 Pseudo register to save PAC.  */
 /* Intel Wireless MMX Technology registers add 16 + 4 more.  */
 /* VFP (VFP3) adds 32 (64) + 1 VFPCC.  */
-#define FIRST_PSEUDO_REGISTER   107
+#define FIRST_PSEUDO_REGISTER   108

 #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)

@@ -1257,12 +1258,15 @@ extern int arm_regs_in_sequence[];
   CC_REGNUM, VFPCC_REGNUM,                     \
   FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM,    \
   SP_REGNUM, PC_REGNUM, APSRQ_REGNUM,          \
-  APSRGE_REGNUM, VPR_REGNUM                    \
+  APSRGE_REGNUM, VPR_REGNUM, RA_AUTH_CODE      \
 }

 #define IS_VPR_REGNUM(REGNUM) \
   ((REGNUM) == VPR_REGNUM)

+#define IS_PAC_PSEUDO_REGNUM(REGNUM) \
+  ((REGNUM) == RA_AUTH_CODE)
+
 /* Use different register alloc ordering for Thumb.  */
 #define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()

@@ -1301,6 +1305,7 @@ enum reg_class
   SFP_REG,
   AFP_REG,
   VPR_REG,
+  PAC_REG,
   GENERAL_AND_VPR_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
@@ -1331,6 +1336,7 @@ enum reg_class
   "SFP_REG",           \
   "AFP_REG",           \
   "VPR_REG",           \
+  "PAC_REG",           \
   "GENERAL_AND_VPR_REGS", \
   "ALL_REGS"           \
 }
@@ -1360,6 +1366,7 @@ enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00000040 }, /* SFP_REG */    \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000080 }, /* AFP_REG */    \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000400 }, /* VPR_REG.  */  \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000800 }, /* PAC_REG.  */  \
   { 0x00005FFF, 0x00000000, 0x00000000, 0x00000400 }, /* GENERAL_AND_VPR_REGS.  */ \
   { 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000040F }  /* ALL_REGS.  */ \
 }
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 3c4722337fdd72586e0655e2009370ad7595fafc..414561624d2eacccc10395db757bfa3c638bb387 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -2452,6 +2452,9 @@ enum tls_reloc {
   TLS_DESCSEQ  /* GNU scheme */
 };

+/* True if PACBTI/PAC instruction is emitted.  */
+static bool pac_emit = false;
+
 /* The maximum number of insns to be used when loading a constant.  */
 inline static int
 arm_constant_limit (bool size_p)
@@ -22154,7 +22157,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
     {
       if (mask & (1 << i))
         {
-         reg = gen_rtx_REG (SImode, i);
+         rtx reg1 = reg = gen_rtx_REG (SImode, i);
+         if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
+             && pac_emit)
+           reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);

           XVECEXP (par, 0, 0)
             = gen_rtx_SET (gen_frame_mem
@@ -22172,7 +22178,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
           if (dwarf_regs_mask & (1 << i))
             {
               tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx),
-                                reg);
+                                reg1);
               RTX_FRAME_RELATED_P (tmp) = 1;
               XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
             }
@@ -22185,7 +22191,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
     {
       if (mask & (1 << i))
         {
-         reg = gen_rtx_REG (SImode, i);
+         rtx reg1 = reg = gen_rtx_REG (SImode, i);
+         if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
+             && pac_emit)
+           reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);

           XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);

@@ -22196,7 +22205,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
                                (SImode,
                                 plus_constant (Pmode, stack_pointer_rtx,
                                                4 * j)),
-                              reg);
+                              reg1);
               RTX_FRAME_RELATED_P (tmp) = 1;
               XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
             }
@@ -22281,7 +22290,9 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
   for (j = 0, i = 0; j < num_regs; i++)
     if (saved_regs_mask & (1 << i))
       {
-        reg = gen_rtx_REG (SImode, i);
+       rtx reg1 = reg = gen_rtx_REG (SImode, i);
+       if (arm_current_function_pac_enabled_p () && i == IP_REGNUM && pac_emit)
+         reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
         if ((num_regs == 1) && emit_update && !return_in_pc)
           {
             /* Emit single load with writeback.  */
@@ -22289,7 +22300,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
                                  gen_rtx_POST_INC (Pmode,
                                                    stack_pointer_rtx));
             tmp = emit_insn (gen_rtx_SET (reg, tmp));
-            REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+           REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
             return;
           }

@@ -22303,7 +22314,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
         /* We need to maintain a sequence for DWARF info too.  As dwarf info
            should not have PC, skip PC.  */
         if (i != PC_REGNUM)
-          dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+         dwarf = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);

         j++;
       }
@@ -23541,9 +23552,14 @@ arm_expand_prologue (void)
          instruction will be added before the push of the clobbered IP
          (if necessary) by the bti pass.  */
       if (aarch_bti_enabled () && !clobber_ip)
-       emit_insn (gen_pacbti_nop ());
+       insn = emit_insn (gen_pacbti_nop ());
       else
-       emit_insn (gen_pac_nop ());
+       insn = emit_insn (gen_pac_nop ());
+
+      rtx dwarf = gen_rtx_SET (ip_rtx, gen_rtx_REG (SImode, RA_AUTH_CODE));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_CFA_REGISTER, dwarf);
+      pac_emit  = true;
     }

   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
@@ -25602,6 +25618,9 @@ arm_regno_class (int regno)
   if (IS_VPR_REGNUM (regno))
     return VPR_REG;

+  if (IS_PAC_PSEUDO_REGNUM (regno))
+    return PAC_REG;
+
   if (TARGET_THUMB1)
     {
       if (regno == STACK_POINTER_REGNUM)
@@ -29573,6 +29592,9 @@ arm_dbx_register_number (unsigned int regno)
   if (IS_IWMMXT_REGNUM (regno))
     return 112 + regno - FIRST_IWMMXT_REGNUM;

+  if (IS_PAC_PSEUDO_REGNUM (regno))
+    return 143;
+
   return DWARF_FRAME_REGISTERS;
 }

@@ -29666,7 +29688,7 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
   gcc_assert (nregs);

   reg = REGNO (SET_SRC (XVECEXP (p, 0, 1)));
-  if (reg < 16)
+  if (reg < 16 || IS_PAC_PSEUDO_REGNUM (reg))
     {
       /* For -Os dummy registers can be pushed at the beginning to
          avoid separate stack pointer adjustment.  */
@@ -29723,6 +29745,8 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
          double precision register names.  */
       if (IS_VFP_REGNUM (reg))
         asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
+      else if (IS_PAC_PSEUDO_REGNUM (reg))
+       asm_fprintf (asm_out_file, "ra_auth_code");
       else
         asm_fprintf (out_file, "%r", reg);

@@ -29817,7 +29841,7 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
           /* Move from sp to reg.  */
           asm_fprintf (out_file, "\t.movsp %r\n", REGNO (e0));
         }
-     else if (GET_CODE (e1) == PLUS
+      else if (GET_CODE (e1) == PLUS
               && REG_P (XEXP (e1, 0))
               && REGNO (XEXP (e1, 0)) == SP_REGNUM
               && CONST_INT_P (XEXP (e1, 1)))
@@ -29826,6 +29850,13 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
           asm_fprintf (out_file, "\t.movsp %r, #%d\n",
                        REGNO (e0), (int)INTVAL(XEXP (e1, 1)));
         }
+      else if (REGNO (e0) == IP_REGNUM && GET_CODE (e1) == UNSPEC)
+       {
+         if (XINT (e1, 1) == UNSPEC_PAC_NOP)
+           asm_fprintf (out_file, "\t.pacspval\n");
+         else if (XINT (e1, 1) != UNSPEC_PACBTI_NOP)
+           abort ();
+       }
       else
         abort ();
       break;
@@ -29880,8 +29911,15 @@ arm_unwind_emit (FILE * out_file, rtx_insn *insn)
             src = SET_SRC (pat);
             dest = SET_DEST (pat);

-           gcc_assert (src == stack_pointer_rtx);
+           gcc_assert (src == stack_pointer_rtx
+                       || IS_PAC_PSEUDO_REGNUM (REGNO (src)));
             reg = REGNO (dest);
+
+           if (IS_PAC_PSEUDO_REGNUM (REGNO (src)))
+             {
+               pat = PATTERN (insn);
+               goto found;
+             }
             asm_fprintf (out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
                          reg + 0x90, reg);
           }
@@ -30590,6 +30628,9 @@ arm_conditional_register_usage (void)
         global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
     }

+  if (TARGET_HAVE_PACBTI)
+    fixed_regs[RA_AUTH_CODE] = 0;
+
   /* The Q and GE bits are only accessed via special ACLE patterns.  */
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
   CLEAR_HARD_REG_BIT (operand_reg_set, APSRGE_REGNUM);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6e86811ee05f54f0e4bec3a5e632e3bb541fc423..3aea721f9b82445f6b318fd09dcd3d260683baa7 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -42,6 +42,7 @@
    (APSRQ_REGNUM    104)       ; Q bit pseudo register
    (APSRGE_REGNUM   105)       ; GE bits pseudo register
    (VPR_REGNUM      106)       ; Vector Predication Register - MVE register.
+   (RA_AUTH_CODE    107)       ; Pseudo register to save PAC.
   ]
 )
 ;; 3rd operand to select_dominance_cc_mode
diff --git a/gcc/testsuite/g++.target/arm/pac-1.C b/gcc/testsuite/g++.target/arm/pac-1.C
new file mode 100644
index 0000000000000000000000000000000000000000..96a3ba51362e02a5fe90b517ee28c41e87024475
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/pac-1.C
@@ -0,0 +1,36 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -g -O0" } */
+
+__attribute__((noinline)) void
+fn1 (int a, int b, int c)
+{
+  if (a != b + c)
+    __builtin_abort ();
+  else
+    throw b+c;
+}
+
+int main ()
+{
+  int a = 120;
+  try
+    {
+      fn1 (a, 40, 80);
+    }
+  catch (int x)
+    {
+      if (x != a)
+        __builtin_abort ();
+      else
+       return 0;
+    }
+}
+
+/* { dg-final { scan-assembler-times "\.pacspval" 2 } } */
+/* { dg-final { scan-assembler-times "pac      ip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 1 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r4, r7, ra_auth_code, lr}" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
new file mode 100644
index 0000000000000000000000000000000000000000..283b6786e7fe50f8e3cddea5161743a7553fe6eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,32 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -fasynchronous-unwind-tables -g -O0" } */
+
+#include "stdio.h"
+
+__attribute__((noinline)) int
+fn1 (int a)
+{
+  const char *fmt = "branch-protection";
+  int fun1(int x,const char *fmt,int c,int d)
+    {
+      printf("string = %s\n",fmt);
+      return x+c+d;
+    }
+  return fun1(a,fmt,10,10);
+}
+
+int main (void)
+{
+  return fn1 (40);
+}
+
+/* { dg-final { scan-assembler-times "\.pacspval" 3 } } */
+/* { dg-final { scan-assembler-times "pac      ip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 3 } } */
+/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 2 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
+/* { dg-final { scan-assembler-times "\.save {r3, r7, ra_auth_code, lr}" 1 } } */
+/* { dg-final { scan-assembler-times "\.cfi_offset 143, -12" 1 } } */




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature.
  2022-11-09 14:32 [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature Srinath Parvathaneni
  2022-12-06 11:34 ` Srinath Parvathaneni
@ 2022-12-08 14:48 ` Richard Earnshaw
  1 sibling, 0 replies; 3+ messages in thread
From: Richard Earnshaw @ 2022-12-08 14:48 UTC (permalink / raw)
  To: Srinath Parvathaneni, gcc-patches; +Cc: richard.earnshaw, kyrylo.tkachov



On 09/11/2022 14:32, Srinath Parvathaneni via Gcc-patches wrote:
> Hello,
> 
> This patch teaches the DWARF support in gcc about RA_AUTH_CODE pseudo hard-register and also
> updates the ".save", ".cfi_register", ".cfi_offset", ".cfi_restore" directives accordingly.
> This patch also adds support to emit ".pacspval" directive when "pac ip, lr, sp" instruction
> in generated in the assembly.
> 
> RA_AUTH_CODE register number is 107 and it's dwarf register number is 143.
> 
> Applying this patch on top of PACBTI series posted here
> https://gcc.gnu.org/pipermail/gcc-patches/2022-August/599658.html and when compiling the following
> test.c with "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard
> fasynchronous-unwind-tables -g -O0 -S" command line options, the assembly output after this patch
> looks like below:
> 
> $cat test.c
> 
> void fun1(int a);
> void fun(int a,...)
> {
>    fun1(a);
> }
> 
> int main()
> {
>    fun (10);
>    return 0;
> }
> 
> $ arm-none-eabi-gcc -march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard
> -fasynchronous-unwind-tables -g -O0 -S test.s
> 
> Assembly output:
> ...
> fun:
> ...
>          .pacspval
>          pac     ip, lr, sp
>          .cfi_register 143, 12
>          push    {r3, r7, ip, lr}
>          .save {r3, r7, ra_auth_code, lr}
> ...
>          .cfi_offset 143, -24
> ...
>          .cfi_restore 143
> ...
>          aut     ip, lr, sp
>          bx      lr
> ...
> main:
> ...
>          .pacspval
>          pac     ip, lr, sp
>          .cfi_register 143, 12
>          push    {r3, r7, ip, lr}
>          .save {r3, r7, ra_auth_code, lr}
> ...
>          .cfi_offset 143, -8
> ...
>          .cfi_restore 143
> ...
>          aut     ip, lr, sp
>          bx      lr
> ...
> 
> Regression tested on arm-none-eabi target and found no regressions.
> 
> Ok for master?
> 
> Regards,
> Srinath.
> 
> gcc/testsuite/ChangeLog:
> 
> 2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>
> 
>          * g++.target/arm/pac-1.C: New test.
>          * gcc.target/arm/pac-9.c: New test.
> 
> 
> 2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>
> 
>          * config/arm/aout.h (ra_auth_code): Add entry in enum.
>          * config/arm/arm.cc (pac_emit): Declare new global boolean variable.
>          (emit_multi_reg_push): Add RA_AUTH_CODE register to
>          dwarf frame expression.
>          (arm_emit_multi_reg_pop): Restore RA_AUTH_CODE register.
>          (arm_expand_prologue): Update frame related infomration and reg notes
>          for pac/pacbit insn.
>          (arm_regno_class): Check for pac pseudo reigster.
>          (arm_dbx_register_number): Assign ra_auth_code register number in dwarf.
>          (arm_unwind_emit_sequence): Print .save directive with ra_auth_code
>          register.
>          (arm_unwind_emit_set): Add entry for IP_REGNUM in switch case.
>          (arm_unwind_emit): Update REG_CFA_REGISTER case._
>          (arm_conditional_register_usage): Mark ra_auth_code in fixed reigsters.
>          * config/arm/arm.h (FIRST_PSEUDO_REGISTER): Modify.
>          (IS_PAC_PSEUDO_REGNUM): Define.
>          (enum reg_class): Add PAC_REG entry.
>          * config/arm/arm.md (RA_AUTH_CODE): Define.
> 
> gcc/testsuite/ChangeLog:
> 
> 2022-11-04  Srinath Parvathaneni  <srinath.parvathaneni@arm.com>
> 
>          * g++.target/arm/pac-1.C: New test.
>          * gcc.target/arm/pac-9.c: Likewise.
> 
> 
> ###############     Attachment also inlined for ease of reply    ###############
> 
> 
> diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
> index b918ad3782fbee82320febb8b6e72ad615780261..ffeed45a678f17c63d5b42c21f020ca416cbf23f 100644
> --- a/gcc/config/arm/aout.h
> +++ b/gcc/config/arm/aout.h
> @@ -74,7 +74,8 @@
>     "wr8",   "wr9",   "wr10",  "wr11",				\
>     "wr12",  "wr13",  "wr14",  "wr15",				\
>     "wcgr0", "wcgr1", "wcgr2", "wcgr3",				\
> -  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0"		\
> +  "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0",		\
> +  "ra_auth_code"						\
>   }
>   #endif
>   
> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> index a2dc3fc145c52d8381c54634687376089a47e704..91c400f12568156ed29bf5d5e59460bf887fbefb 100644
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -820,7 +820,8 @@ extern const int arm_arch_cde_coproc_bits[];
>   	s16-s31	      S	VFP variable (aka d8-d15).
>   	vfpcc		Not a real register.  Represents the VFP condition
>   			code flags.
> -	vpr		Used to represent MVE VPR predication.  */
> +	vpr		Used to represent MVE VPR predication.
> +	ra_auth_code	Pseudo register to save PAC.  */
>   
>   /* The stack backtrace structure is as follows:
>     fp points to here:  |  save code pointer  |      [fp]
> @@ -861,7 +862,7 @@ extern const int arm_arch_cde_coproc_bits[];
>     1,1,1,1,1,1,1,1,		\
>     1,1,1,1,			\
>     /* Specials.  */		\
> -  1,1,1,1,1,1,1			\
> +  1,1,1,1,1,1,1,1		\
>   }
>   
>   /* 1 for registers not available across function calls.
> @@ -891,7 +892,7 @@ extern const int arm_arch_cde_coproc_bits[];
>     1,1,1,1,1,1,1,1,		\
>     1,1,1,1,			\
>     /* Specials.  */		\
> -  1,1,1,1,1,1,1			\
> +  1,1,1,1,1,1,1,1		\
>   }
>   
>   #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
> @@ -1067,10 +1068,10 @@ extern const int arm_arch_cde_coproc_bits[];
>      && (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))
>   
>   /* The number of hard registers is 16 ARM + 1 CC + 1 SFP + 1 AFP
> -   + 1 APSRQ + 1 APSRGE + 1 VPR.  */
> +   + 1 APSRQ + 1 APSRGE + 1 VPR + 1 Pseudo register to save PAC.  */
>   /* Intel Wireless MMX Technology registers add 16 + 4 more.  */
>   /* VFP (VFP3) adds 32 (64) + 1 VFPCC.  */
> -#define FIRST_PSEUDO_REGISTER   107
> +#define FIRST_PSEUDO_REGISTER   108
>   
>   #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
>   
> @@ -1257,12 +1258,15 @@ extern int arm_regs_in_sequence[];
>     CC_REGNUM, VFPCC_REGNUM,			\
>     FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM,	\
>     SP_REGNUM, PC_REGNUM, APSRQ_REGNUM,		\
> -  APSRGE_REGNUM, VPR_REGNUM			\
> +  APSRGE_REGNUM, VPR_REGNUM, RA_AUTH_CODE	\
>   }
>   
>   #define IS_VPR_REGNUM(REGNUM) \
>     ((REGNUM) == VPR_REGNUM)
>   
> +#define IS_PAC_PSEUDO_REGNUM(REGNUM) \
> +  ((REGNUM) == RA_AUTH_CODE)

Pseudo is probably a poor name for this, given the compiler's use of 
pseudo in a subtly different context.  It's probably better to drop 
PSEUDO and just use IS_PAC_REGNUM.

> +
>   /* Use different register alloc ordering for Thumb.  */
>   #define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()
>   
> @@ -1301,6 +1305,7 @@ enum reg_class
>     SFP_REG,
>     AFP_REG,
>     VPR_REG,
> +  PAC_REG,
>     GENERAL_AND_VPR_REGS,
>     ALL_REGS,
>     LIM_REG_CLASSES
> @@ -1331,6 +1336,7 @@ enum reg_class
>     "SFP_REG",		\
>     "AFP_REG",		\
>     "VPR_REG",		\
> +  "PAC_REG",		\
>     "GENERAL_AND_VPR_REGS", \
>     "ALL_REGS"		\
>   }
> @@ -1360,6 +1366,7 @@ enum reg_class
>     { 0x00000000, 0x00000000, 0x00000000, 0x00000040 }, /* SFP_REG */	\
>     { 0x00000000, 0x00000000, 0x00000000, 0x00000080 }, /* AFP_REG */	\
>     { 0x00000000, 0x00000000, 0x00000000, 0x00000400 }, /* VPR_REG.  */	\
> +  { 0x00000000, 0x00000000, 0x00000000, 0x00000800 }, /* PAC_REG.  */	\
>     { 0x00005FFF, 0x00000000, 0x00000000, 0x00000400 }, /* GENERAL_AND_VPR_REGS.  */ \
>     { 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000040F }  /* ALL_REGS.  */	\
>   }
> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
> index 3c4722337fdd72586e0655e2009370ad7595fafc..414561624d2eacccc10395db757bfa3c638bb387 100644
> --- a/gcc/config/arm/arm.cc
> +++ b/gcc/config/arm/arm.cc
> @@ -2452,6 +2452,9 @@ enum tls_reloc {
>     TLS_DESCSEQ	/* GNU scheme */
>   };
>   
> +/* True if PACBTI/PAC instruction is emitted.  */
> +static bool pac_emit = false;

The logic behind this global looks incorrect.  It's initialized here to 
false, but the only other time it is changed is in arm_expand_prologue 
where it is unconditionally (and permanently) set to true if 
current_function_pac_enabled_p () returns true.  But once set, it is 
never reset for the rest of the compilation.

I think you should remove this entirely and just use 
current_function_pac_enabled_p() where you've used this.

> +
>   /* The maximum number of insns to be used when loading a constant.  */
>   inline static int
>   arm_constant_limit (bool size_p)
> @@ -22154,7 +22157,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
>       {
>         if (mask & (1 << i))
>   	{
> -	  reg = gen_rtx_REG (SImode, i);
> +	  rtx reg1 = reg = gen_rtx_REG (SImode, i);
> +	  if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
> +	      && pac_emit)
> +	    reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);

The dwarf code emitter should be able to handle register-register copies 
like this if the original set operation is marked correctly. 
Unfortunately, I think this is still needed to get the Arm-specific 
.save directive to emit the right output.  This needs to be mentioned in 
a comment somewhere.

See also the comment above about pac_emit.

reg and reg1 is also somewhat confusing.  I think it would be better to 
use 'dwarf_reg' in place of 'reg1'.

>   
>   	  XVECEXP (par, 0, 0)
>   	    = gen_rtx_SET (gen_frame_mem
> @@ -22172,7 +22178,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
>   	  if (dwarf_regs_mask & (1 << i))
>   	    {
>   	      tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx),
> -				 reg);
> +				 reg1);
>   	      RTX_FRAME_RELATED_P (tmp) = 1;
>   	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
>   	    }
> @@ -22185,7 +22191,10 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
>       {
>         if (mask & (1 << i))
>   	{
> -	  reg = gen_rtx_REG (SImode, i);
> +	  rtx reg1 = reg = gen_rtx_REG (SImode, i);
> +	  if (arm_current_function_pac_enabled_p () && i == IP_REGNUM
> +	      && pac_emit)
> +	    reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
>   
>   	  XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
>   
> @@ -22196,7 +22205,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
>   			       (SImode,
>   				plus_constant (Pmode, stack_pointer_rtx,
>   					       4 * j)),
> -			       reg);
> +			       reg1);
>   	      RTX_FRAME_RELATED_P (tmp) = 1;
>   	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
>   	    }
> @@ -22281,7 +22290,9 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
>     for (j = 0, i = 0; j < num_regs; i++)
>       if (saved_regs_mask & (1 << i))
>         {
> -        reg = gen_rtx_REG (SImode, i);
> +	rtx reg1 = reg = gen_rtx_REG (SImode, i);
> +	if (arm_current_function_pac_enabled_p () && i == IP_REGNUM && pac_emit)
> +	  reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
>           if ((num_regs == 1) && emit_update && !return_in_pc)
>             {
>               /* Emit single load with writeback.  */
> @@ -22289,7 +22300,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
>                                    gen_rtx_POST_INC (Pmode,
>                                                      stack_pointer_rtx));
>               tmp = emit_insn (gen_rtx_SET (reg, tmp));
> -            REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
> +	    REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
>               return;
>             }
>   
> @@ -22303,7 +22314,7 @@ arm_emit_multi_reg_pop (unsigned long saved_regs_mask)
>           /* We need to maintain a sequence for DWARF info too.  As dwarf info
>              should not have PC, skip PC.  */
>           if (i != PC_REGNUM)
> -          dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
> +	  dwarf = alloc_reg_note (REG_CFA_RESTORE, reg1, dwarf);
>   
>           j++;
>         }
> @@ -23541,9 +23552,14 @@ arm_expand_prologue (void)
>            instruction will be added before the push of the clobbered IP
>            (if necessary) by the bti pass.  */
>         if (aarch_bti_enabled () && !clobber_ip)
> -	emit_insn (gen_pacbti_nop ());
> +	insn = emit_insn (gen_pacbti_nop ());
>         else
> -	emit_insn (gen_pac_nop ());
> +	insn = emit_insn (gen_pac_nop ());
> +
> +      rtx dwarf = gen_rtx_SET (ip_rtx, gen_rtx_REG (SImode, RA_AUTH_CODE));
> +      RTX_FRAME_RELATED_P (insn) = 1;
> +      add_reg_note (insn, REG_CFA_REGISTER, dwarf);
> +      pac_emit  = true;
>       }
>   
>     if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
> @@ -25602,6 +25618,9 @@ arm_regno_class (int regno)
>     if (IS_VPR_REGNUM (regno))
>       return VPR_REG;
>   
> +  if (IS_PAC_PSEUDO_REGNUM (regno))
> +    return PAC_REG;
> +
>     if (TARGET_THUMB1)
>       {
>         if (regno == STACK_POINTER_REGNUM)
> @@ -29573,6 +29592,9 @@ arm_dbx_register_number (unsigned int regno)
>     if (IS_IWMMXT_REGNUM (regno))
>       return 112 + regno - FIRST_IWMMXT_REGNUM;
>   
> +  if (IS_PAC_PSEUDO_REGNUM (regno))
> +    return 143;

This value should be #defined somewhere and then the macro definition 
used here.  DWARF_PAC_REGNUM ?

> +
>     return DWARF_FRAME_REGISTERS;
>   }
>   
> @@ -29666,7 +29688,7 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
>     gcc_assert (nregs);
>   
>     reg = REGNO (SET_SRC (XVECEXP (p, 0, 1)));
> -  if (reg < 16)
> +  if (reg < 16 || IS_PAC_PSEUDO_REGNUM (reg))
>       {
>         /* For -Os dummy registers can be pushed at the beginning to
>   	 avoid separate stack pointer adjustment.  */
> @@ -29723,6 +29745,8 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
>   	 double precision register names.  */
>         if (IS_VFP_REGNUM (reg))
>   	asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
> +      else if (IS_PAC_PSEUDO_REGNUM (reg))
> +	asm_fprintf (asm_out_file, "ra_auth_code");
>         else
>   	asm_fprintf (out_file, "%r", reg);
>   
> @@ -29817,7 +29841,7 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
>   	  /* Move from sp to reg.  */
>   	  asm_fprintf (out_file, "\t.movsp %r\n", REGNO (e0));
>   	}
> -     else if (GET_CODE (e1) == PLUS
> +      else if (GET_CODE (e1) == PLUS
>   	      && REG_P (XEXP (e1, 0))
>   	      && REGNO (XEXP (e1, 0)) == SP_REGNUM
>   	      && CONST_INT_P (XEXP (e1, 1)))
> @@ -29826,6 +29850,13 @@ arm_unwind_emit_set (FILE * out_file, rtx p)
>   	  asm_fprintf (out_file, "\t.movsp %r, #%d\n",
>   		       REGNO (e0), (int)INTVAL(XEXP (e1, 1)));
>   	}
> +      else if (REGNO (e0) == IP_REGNUM && GET_CODE (e1) == UNSPEC)
> +	{
> +	  if (XINT (e1, 1) == UNSPEC_PAC_NOP)
> +	    asm_fprintf (out_file, "\t.pacspval\n");
> +	  else if (XINT (e1, 1) != UNSPEC_PACBTI_NOP)
> +	    abort ();

Just use
    else
      gcc_assert (XINT (e1, 1) == USPEC_PACBTI_NOP);

> +	}
>         else
>   	abort ();
>         break;
> @@ -29880,8 +29911,15 @@ arm_unwind_emit (FILE * out_file, rtx_insn *insn)
>   	    src = SET_SRC (pat);
>   	    dest = SET_DEST (pat);
>   
> -	    gcc_assert (src == stack_pointer_rtx);
> +	    gcc_assert (src == stack_pointer_rtx
> +			|| IS_PAC_PSEUDO_REGNUM (REGNO (src)));
>   	    reg = REGNO (dest);
> +
> +	    if (IS_PAC_PSEUDO_REGNUM (REGNO (src)))
> +	      {
> +		pat = PATTERN (insn);
> +		goto found;
> +	      }

This is rather convoluted.  I think it would be better to structure this as

     if (IS_PAC_REGNUM (REGNO (src)))
       // code just for pac
     else
       // existing code for stack_pointer_rtx

>   	    asm_fprintf (out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n",
>   			 reg + 0x90, reg);
>   	  }
> @@ -30590,6 +30628,9 @@ arm_conditional_register_usage (void)
>   	global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1;
>       }
>   
> +  if (TARGET_HAVE_PACBTI)
> +    fixed_regs[RA_AUTH_CODE] = 0;

Really?  RA_AUTH_CODE should always be fixed.  It's not generally 
available to the register allocator.

> +
>     /* The Q and GE bits are only accessed via special ACLE patterns.  */
>     CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
>     CLEAR_HARD_REG_BIT (operand_reg_set, APSRGE_REGNUM);
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 6e86811ee05f54f0e4bec3a5e632e3bb541fc423..3aea721f9b82445f6b318fd09dcd3d260683baa7 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -42,6 +42,7 @@
>      (APSRQ_REGNUM    104)	; Q bit pseudo register
>      (APSRGE_REGNUM   105)	; GE bits pseudo register
>      (VPR_REGNUM      106)	; Vector Predication Register - MVE register.
> +   (RA_AUTH_CODE    107)	; Pseudo register to save PAC.
>     ]
>   )
>   ;; 3rd operand to select_dominance_cc_mode
> diff --git a/gcc/testsuite/g++.target/arm/pac-1.C b/gcc/testsuite/g++.target/arm/pac-1.C
> new file mode 100644
> index 0000000000000000000000000000000000000000..96a3ba51362e02a5fe90b517ee28c41e87024475
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/arm/pac-1.C
> @@ -0,0 +1,36 @@
> +/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
> +/* { dg-do compile } */
> +/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
> +/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -g -O0" } */
> +
> +__attribute__((noinline)) void
> +fn1 (int a, int b, int c)
> +{
> +  if (a != b + c)
> +    __builtin_abort ();
> +  else
> +    throw b+c;
> +}
> +
> +int main ()
> +{
> +  int a = 120;
> +  try
> +    {
> +      fn1 (a, 40, 80);
> +    }
> +  catch (int x)
> +    {
> +      if (x != a)
> +        __builtin_abort ();
> +      else
> +	return 0;
> +    }
> +}
> +
> +/* { dg-final { scan-assembler-times "\.pacspval" 2 } } */
> +/* { dg-final { scan-assembler-times "pac	ip, lr, sp" 2 } } */
> +/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 2 } } */
> +/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 1 } } */
> +/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
> +/* { dg-final { scan-assembler-times "\.save {r4, r7, ra_auth_code, lr}" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/arm/pac-9.c b/gcc/testsuite/gcc.target/arm/pac-9.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..283b6786e7fe50f8e3cddea5161743a7553fe6eb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/pac-9.c
> @@ -0,0 +1,32 @@
> +/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register.  */
> +/* { dg-do compile } */
> +/* { dg-require-effective-target mbranch_protection_ok } */
> +/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
> +/* { dg-options "-march=armv8.1-m.main+mve+pacbti -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard -fasynchronous-unwind-tables -g -O0" } */
> +
> +#include "stdio.h"
> +
> +__attribute__((noinline)) int
> +fn1 (int a)
> +{
> +  const char *fmt = "branch-protection";
> +  int fun1(int x,const char *fmt,int c,int d)
> +    {
> +      printf("string = %s\n",fmt);
> +      return x+c+d;
> +    }
> +  return fun1(a,fmt,10,10);
> +}
> +
> +int main (void)
> +{
> +  return fn1 (40);
> +}
> +
> +/* { dg-final { scan-assembler-times "\.pacspval" 3 } } */
> +/* { dg-final { scan-assembler-times "pac	ip, lr, sp" 3 } } */
> +/* { dg-final { scan-assembler-times "\.cfi_register 143, 12" 3 } } */
> +/* { dg-final { scan-assembler-times "\.save {r7, ra_auth_code, lr}" 2 } } */
> +/* { dg-final { scan-assembler-times "\.cfi_offset 143, -8" 2 } } */
> +/* { dg-final { scan-assembler-times "\.save {r3, r7, ra_auth_code, lr}" 1 } } */
> +/* { dg-final { scan-assembler-times "\.cfi_offset 143, -12" 1 } } */
> 
> 
> 

R.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-12-08 14:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-09 14:32 [GCC][PATCH 13/15, v4] arm: Add support for dwarf debug directives and pseudo hard-register for PAC feature Srinath Parvathaneni
2022-12-06 11:34 ` Srinath Parvathaneni
2022-12-08 14:48 ` Richard Earnshaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).