public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/arm-12-m-pacbti)] [PATCH 10/15] arm: Implement cortex-M return signing address codegen
@ 2022-08-12 16:30 Andrea Corallo
  0 siblings, 0 replies; 2+ messages in thread
From: Andrea Corallo @ 2022-08-12 16:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:fa1390cc8d21aa9930183dd339ec6f7e58308257

commit fa1390cc8d21aa9930183dd339ec6f7e58308257
Author: Andrea Corallo <andrea.corallo@arm.com>
Date:   Thu Jan 20 15:36:23 2022 +0100

    [PATCH 10/15] arm: Implement cortex-M return signing address codegen
    
    Hi all,
    
    this patch enables address return signature and verification based on
    Armv8.1-M Pointer Authentication [1].
    
    To sign the return address, we use the PAC R12, LR, SP instruction
    upon function entry.  This is signing LR using SP and storing the
    result in R12.  R12 will be pushed into the stack.
    
    During function epilogue R12 will be popped and AUT R12, LR, SP will
    be used to verify that the content of LR is still valid before return.
    
    Here an example of PAC instrumented function prologue and epilogue:
    
    void foo (void);
    
    int main()
    {
      foo ();
      return 0;
    }
    
    Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
    -mthumb' translates into:
    
    main:
            pac     ip, lr, sp
            push    {r3, r7, ip, lr}
            add     r7, sp, #0
            bl      foo
            movs    r3, #0
            mov     r0, r3
            pop     {r3, r7, ip, lr}
            aut     ip, lr, sp
            bx      lr
    
    The patch also takes care of generating a PACBTI instruction in place
    of the sequence BTI+PAC when Branch Target Identification is enabled
    contextually.
    
    Ex. the previous example compiled with '-march=armv8.1-m.main
    -mbranch-protection=pac-ret+bti -mthumb' translates into:
    
    main:
            pacbti  ip, lr, sp
            push    {r3, r7, ip, lr}
            add     r7, sp, #0
            bl      foo
            movs    r3, #0
            mov     r0, r3
            pop     {r3, r7, ip, lr}
            aut     ip, lr, sp
            bx      lr
    
    As part of previous upstream suggestions a test for varargs has been
    added and '-mtpcs-frame' is deemed being incompatible with this return
    signing address feature being introduced.
    
    [1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>
    
    gcc/Changelog
    
    2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
    
            * config/arm/arm.c: (arm_compute_frame_layout)
            (arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
            (arm_conditional_register_usage): Update for pac codegen.
            (arm_current_function_pac_enabled_p): New function.
            * config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
            Add new patterns.
            * config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
            (UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
    
    gcc/testsuite/Changelog
    
    2021-11-03  Andrea Corallo  <andrea.corallo@arm.com>
    
            * gcc.target/arm/pac.h : New file.
            * gcc.target/arm/pac-1.c : New test case.
            * gcc.target/arm/pac-2.c : Likewise.
            * gcc.target/arm/pac-3.c : Likewise.
            * gcc.target/arm/pac-4.c : Likewise.
            * gcc.target/arm/pac-5.c : Likewise.
            * gcc.target/arm/pac-6.c : Likewise.
            * gcc.target/arm/pac-7.c : Likewise.
            * gcc.target/arm/pac-8.c : Likewise.

Diff:
---
 gcc/config/arm/arm-protos.h          |  1 +
 gcc/config/arm/arm.cc                | 68 +++++++++++++++++++++++++++++-------
 gcc/config/arm/arm.md                | 25 ++++++++++++-
 gcc/config/arm/unspecs.md            |  3 ++
 gcc/testsuite/gcc.target/arm/pac-1.c | 12 +++++++
 gcc/testsuite/gcc.target/arm/pac-2.c | 11 ++++++
 gcc/testsuite/gcc.target/arm/pac-3.c | 11 ++++++
 gcc/testsuite/gcc.target/arm/pac-4.c | 10 ++++++
 gcc/testsuite/gcc.target/arm/pac-5.c | 28 +++++++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c | 18 ++++++++++
 gcc/testsuite/gcc.target/arm/pac-7.c | 32 +++++++++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c | 34 ++++++++++++++++++
 gcc/testsuite/gcc.target/arm/pac.h   | 17 +++++++++
 13 files changed, 257 insertions(+), 13 deletions(-)

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index cff7ff1da2a..84764bf27ce 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -379,6 +379,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 5380abeffe8..091db81651a 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -3209,6 +3209,9 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && arm_arch_cmse))
+    error ("This architecture does not support branch protection instructions");
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -21147,6 +21150,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23370,6 +23376,12 @@ output_probe_stack_range (rtx reg1, rtx reg2)
   return "";
 }
 
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Generate the prologue instructions for entry into an ARM or Thumb-2
    function.  */
 void
@@ -23448,12 +23460,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || (arm_current_function_pac_enabled_p ())));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23529,6 +23542,14 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (aarch_bti_enabled ())
+	emit_insn (gen_pacbti_nop ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27317,7 +27338,7 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (num_regs == 1 && !arm_current_function_pac_enabled_p ())
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27332,10 +27353,20 @@ thumb2_expand_return (bool simple_return)
         }
       else
         {
-          saved_regs_mask &= ~ (1 << LR_REGNUM);
-          saved_regs_mask |=   (1 << PC_REGNUM);
-          arm_emit_multi_reg_pop (saved_regs_mask);
-        }
+	  if (arm_current_function_pac_enabled_p ())
+	    {
+              gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	      emit_insn (gen_aut_nop ());
+	      emit_jump_insn (simple_return_rtx);
+	    }
+	  else
+	    {
+	      saved_regs_mask &= ~ (1 << LR_REGNUM);
+	      saved_regs_mask |=   (1 << PC_REGNUM);
+	      arm_emit_multi_reg_pop (saved_regs_mask);
+	    }
+	}
     }
   else
     {
@@ -27741,7 +27772,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27855,6 +27887,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -32949,6 +32984,15 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+    || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+	&& !crtl->is_leaf);
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 60468f6182c..92269a7819a 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11518,7 +11518,7 @@
      arm_expand_prologue ();
    else
      thumb1_expand_prologue ();
-  DONE;
+   DONE;
   "
 )
 
@@ -12890,6 +12890,29 @@
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PAC_NOP))]
+  "arm_arch7 && arm_arch_cmse"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+                   UNSPEC_PACBTI_NOP))]
+  "arm_arch7 && arm_arch_cmse"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
+(define_insn "aut_nop"
+  [(unspec:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+              UNSPEC_AUT_NOP)]
+  "arm_arch7 && arm_arch_cmse"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "length" "4")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..dbe243a03f6 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,9 @@
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
+  UNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  UNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..6cd64dbd014
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,12 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* 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-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}


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

* [gcc(refs/vendors/ARM/heads/arm-12-m-pacbti)] [PATCH 10/15] arm: Implement cortex-M return signing address codegen
@ 2023-03-10 16:21 Andrea Corallo
  0 siblings, 0 replies; 2+ messages in thread
From: Andrea Corallo @ 2023-03-10 16:21 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:45e636ff48cb905b57e7c047b9e58ab25c7eee01

commit 45e636ff48cb905b57e7c047b9e58ab25c7eee01
Author: Andrea Corallo <andrea.corallo@arm.com>
Date:   Thu Jan 20 15:36:23 2022 +0100

    [PATCH 10/15] arm: Implement cortex-M return signing address codegen
    
    Hi all,
    
    this patch enables address return signature and verification based on
    Armv8.1-M Pointer Authentication [1].
    
    To sign the return address, we use the PAC R12, LR, SP instruction
    upon function entry.  This is signing LR using SP and storing the
    result in R12.  R12 will be pushed into the stack.
    
    During function epilogue R12 will be popped and AUT R12, LR, SP will
    be used to verify that the content of LR is still valid before return.
    
    Here an example of PAC instrumented function prologue and epilogue:
    
    void foo (void);
    
    int main()
    {
      foo ();
      return 0;
    }
    
    Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
    -mthumb' translates into:
    
    main:
            pac     ip, lr, sp
            push    {r3, r7, ip, lr}
            add     r7, sp, #0
            bl      foo
            movs    r3, #0
            mov     r0, r3
            pop     {r3, r7, ip, lr}
            aut     ip, lr, sp
            bx      lr
    
    The patch also takes care of generating a PACBTI instruction in place
    of the sequence BTI+PAC when Branch Target Identification is enabled
    contextually.
    
    Ex. the previous example compiled with '-march=armv8.1-m.main
    -mbranch-protection=pac-ret+bti -mthumb' translates into:
    
    main:
            pacbti  ip, lr, sp
            push    {r3, r7, ip, lr}
            add     r7, sp, #0
            bl      foo
            movs    r3, #0
            mov     r0, r3
            pop     {r3, r7, ip, lr}
            aut     ip, lr, sp
            bx      lr
    
    As part of previous upstream suggestions a test for varargs has been
    added and '-mtpcs-frame' is deemed being incompatible with this return
    signing address feature being introduced.
    
    [1] <https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/armv8-1-m-pointer-authentication-and-branch-target-identification-extension>
    
    gcc/
            * config/arm/arm.h (arm_arch8m_main): Declare it.
            * config/arm/arm-protos.h (arm_current_function_pac_enabled_p):
            Declare it.
            * config/arm/arm.cc (arm_arch8m_main): Define it.
            (arm_option_reconfigure_globals): Set arm_arch8m_main.
            (arm_compute_frame_layout, arm_expand_prologue)
            (thumb2_expand_return, arm_expand_epilogue)
            (arm_conditional_register_usage): Update for pac codegen.
            (arm_current_function_pac_enabled_p): New function.
            (aarch_bti_enabled) New function.
            (use_return_insn): Return zero when pac is enabled.
            * config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
            Add new patterns.
            * config/arm/unspecs.md (UNSPEC_PAC_NOP)
            (VUNSPEC_PACBTI_NOP, VUNSPEC_AUT_NOP): Add unspecs.
    
    gcc/testsuite/
    
            * gcc.target/arm/pac.h : New file.
            * gcc.target/arm/pac-1.c : New test case.
            * gcc.target/arm/pac-2.c : Likewise.
            * gcc.target/arm/pac-3.c : Likewise.
            * gcc.target/arm/pac-4.c : Likewise.
            * gcc.target/arm/pac-5.c : Likewise.
            * gcc.target/arm/pac-6.c : Likewise.
            * gcc.target/arm/pac-7.c : Likewise.
            * gcc.target/arm/pac-8.c : Likewise.
            * gcc.target/arm/pac-9.c : Likewise.
            * gcc.target/arm/pac-10.c : Likewise.
            * gcc.target/arm/pac-11.c : Likewise.

Diff:
---
 gcc/config/arm/arm-protos.h           |  1 +
 gcc/config/arm/arm.cc                 | 80 +++++++++++++++++++++++++++++++----
 gcc/config/arm/arm.h                  |  4 ++
 gcc/config/arm/arm.md                 | 23 ++++++++++
 gcc/config/arm/unspecs.md             |  3 ++
 gcc/testsuite/gcc.target/arm/pac-1.c  | 11 +++++
 gcc/testsuite/gcc.target/arm/pac-10.c | 10 +++++
 gcc/testsuite/gcc.target/arm/pac-11.c | 10 +++++
 gcc/testsuite/gcc.target/arm/pac-2.c  | 11 +++++
 gcc/testsuite/gcc.target/arm/pac-3.c  | 11 +++++
 gcc/testsuite/gcc.target/arm/pac-4.c  | 10 +++++
 gcc/testsuite/gcc.target/arm/pac-5.c  | 28 ++++++++++++
 gcc/testsuite/gcc.target/arm/pac-6.c  | 18 ++++++++
 gcc/testsuite/gcc.target/arm/pac-7.c  | 32 ++++++++++++++
 gcc/testsuite/gcc.target/arm/pac-8.c  | 34 +++++++++++++++
 gcc/testsuite/gcc.target/arm/pac-9.c  | 11 +++++
 gcc/testsuite/gcc.target/arm/pac.h    | 17 ++++++++
 17 files changed, 305 insertions(+), 9 deletions(-)

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 2e6db9fac34..9ee1edbe347 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -380,6 +380,7 @@ extern int vfp3_const_double_for_bits (rtx);
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
 					   rtx);
 extern bool arm_fusion_enabled_p (tune_params::fuse_ops);
+extern bool arm_current_function_pac_enabled_p (void);
 extern bool arm_valid_symbolic_address_p (rtx);
 extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 extern bool arm_expand_vector_compare (rtx, rtx_code, rtx, rtx, bool);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index eccd6c0f529..d608d566b5f 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -927,6 +927,11 @@ int arm_arch8_3 = 0;
 
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 int arm_arch8_4 = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+int arm_arch8m_main = 0;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 int arm_arch8_1m_main = 0;
@@ -3209,6 +3214,15 @@ arm_option_override_internal (struct gcc_options *opts,
       arm_stack_protector_guard_offset = offs;
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      if (!arm_arch8m_main)
+        error ("This architecture does not support branch protection "
+               "instructions");
+      if (TARGET_TPCS_FRAME)
+        sorry ("Return address signing is not supported with %<-mtpcs-frame%>.");
+    }
+
 #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS
   SUBTARGET_OVERRIDE_INTERNAL_OPTIONS;
 #endif
@@ -3855,6 +3869,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_arm_hwdiv = bitmap_bit_p (arm_active_target.isa, isa_bit_adiv);
   arm_arch_crc = bitmap_bit_p (arm_active_target.isa, isa_bit_crc32);
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
+  arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
@@ -4354,6 +4369,12 @@ use_return_insn (int iscond, rtx sibling)
   if (!reload_completed)
     return 0;
 
+  /* Never use a return instruction when return address signing
+     mechanism is enabled as it requires more than one
+     instruction.  */
+  if (arm_current_function_pac_enabled_p ())
+    return 0;
+
   func_type = arm_current_func_type ();
 
   /* Naked, volatile and stack alignment functions need special
@@ -21165,6 +21186,9 @@ arm_compute_save_core_reg_mask (void)
 
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
 
+  if (arm_current_function_pac_enabled_p ())
+    save_reg_mask |= 1 << IP_REGNUM;
+
   /* Decide if we need to save the link register.
      Interrupt routines have their own banked link register,
      so they never need to save it.
@@ -23456,12 +23480,13 @@ arm_expand_prologue (void)
 
   /* The static chain register is the same as the IP register.  If it is
      clobbered when creating the frame, we need to save and restore it.  */
-  clobber_ip = IS_NESTED (func_type)
-	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
-		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-			|| flag_stack_clash_protection)
-		       && !df_regs_ever_live_p (LR_REGNUM)
-		       && arm_r3_live_at_start_p ()));
+  clobber_ip = (IS_NESTED (func_type)
+                && (((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+                     || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+                          || flag_stack_clash_protection)
+                         && !df_regs_ever_live_p (LR_REGNUM)
+                         && arm_r3_live_at_start_p ()))
+                    || arm_current_function_pac_enabled_p ()));
 
   /* Find somewhere to store IP whilst the frame is being created.
      We try the following places in order:
@@ -23486,7 +23511,6 @@ arm_expand_prologue (void)
 	{
 	  rtx addr, dwarf;
 
-	  gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
 	  saved_regs += 4;
 
 	  addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
@@ -23537,6 +23561,17 @@ arm_expand_prologue (void)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    {
+      /* If IP was clobbered we only emit a PAC instruction as the BTI
+         one 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 ());
+      else
+	emit_insn (gen_pac_nop ());
+    }
+
   if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
     {
       if (IS_INTERRUPT (func_type))
@@ -27325,7 +27360,14 @@ thumb2_expand_return (bool simple_return)
 	 to assert it for now to ensure that future code changes do not silently
 	 change this behavior.  */
       gcc_assert (!IS_CMSE_ENTRY (arm_current_func_type ()));
-      if (num_regs == 1)
+      if (arm_current_function_pac_enabled_p ())
+        {
+          gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
+          arm_emit_multi_reg_pop (saved_regs_mask);
+          emit_insn (gen_aut_nop ());
+          emit_jump_insn (simple_return_rtx);
+        }
+      else if (num_regs == 1)
         {
           rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
           rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
@@ -27749,7 +27791,8 @@ arm_expand_epilogue (bool really_return)
           && really_return
           && crtl->args.pretend_args_size == 0
           && saved_regs_mask & (1 << LR_REGNUM)
-          && !crtl->calls_eh_return)
+          && !crtl->calls_eh_return
+	  && !arm_current_function_pac_enabled_p ())
         {
           saved_regs_mask &= ~(1 << LR_REGNUM);
           saved_regs_mask |= (1 << PC_REGNUM);
@@ -27863,6 +27906,9 @@ arm_expand_epilogue (bool really_return)
 	}
     }
 
+  if (arm_current_function_pac_enabled_p ())
+    emit_insn (gen_aut_nop ());
+
   if (!really_return)
     return;
 
@@ -32957,6 +33003,22 @@ arm_fusion_enabled_p (tune_params::fuse_ops op)
   return current_tune->fusible_ops & op;
 }
 
+/* Return TRUE if return address signing mechanism is enabled.  */
+bool
+arm_current_function_pac_enabled_p (void)
+{
+  return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+          || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
+              && !crtl->is_leaf));
+}
+
+/* Return TRUE if Branch Target Identification Mechanism is enabled.  */
+static bool
+aarch_bti_enabled ()
+{
+  return false;
+}
+
 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN.  Return true if INSN can be
    scheduled for speculative execution.  Reject the long-running division
    and square-root instructions.  */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 3d718f947bb..965c161f74f 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -506,6 +506,10 @@ extern int arm_arch8_3;
 /* Nonzero if this chip supports the ARM Architecture 8.4 extensions.  */
 extern int arm_arch8_4;
 
+/* Nonzero if this chip supports the ARM Architecture 8-M Mainline
+   extensions.  */
+extern int arm_arch8m_main;
+
 /* Nonzero if this chip supports the ARM Architecture 8.1-M Mainline
    extensions.  */
 extern int arm_arch8_1m_main;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 60468f6182c..21aaa765a3e 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12890,6 +12890,29 @@
    (set_attr "length" "8")]
 )
 
+(define_insn "pac_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		   UNSPEC_PAC_NOP))]
+  "arm_arch8m_main"
+  "pac\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "pacbti_nop"
+  [(set (reg:SI IP_REGNUM)
+	(unspec_volatile:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+			    VUNSPEC_PACBTI_NOP))]
+  "arm_arch8m_main"
+  "pacbti\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
+(define_insn "aut_nop"
+  [(unspec_volatile:SI [(reg:SI IP_REGNUM) (reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
+		       VUNSPEC_AUT_NOP)]
+  "arm_arch8m_main"
+  "aut\t%|ip, %|lr, %|sp"
+  [(set_attr "conds" "unconditional")])
+
 ;; Vector bits common to IWMMXT, Neon and MVE
 (include "vec-common.md")
 ;; Load the Intel Wireless Multimedia Extension patterns
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 7748e784379..370f0b12da1 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -159,6 +159,7 @@
   UNSPEC_VCDE		; Custom Datapath Extension instruction.
   UNSPEC_VCDEA		; Custom Datapath Extension instruction.
   UNSPEC_DLS		; Used for DLS (Do Loop Start), Armv8.1-M Mainline instruction
+  UNSPEC_PAC_NOP	; Represents PAC signing LR
 ])
 
 
@@ -254,6 +255,8 @@
 			; instruction.
   VUNSPEC_VLLDM		; Represent the lazy load multiple with vlldm
 			; instruction.
+  VUNSPEC_PACBTI_NOP	; Represents PAC signing LR + valid landing pad
+  VUNSPEC_AUT_NOP	; Represents PAC verifying LR
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/pac-1.c b/gcc/testsuite/gcc.target/arm/pac-1.c
new file mode 100644
index 00000000000..9b26f62b65f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-1.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-10.c b/gcc/testsuite/gcc.target/arm/pac-10.c
new file mode 100644
index 00000000000..a794195e8f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-10.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-11.c b/gcc/testsuite/gcc.target/arm/pac-11.c
new file mode 100644
index 00000000000..37ffc93b41b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-11.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-2.c b/gcc/testsuite/gcc.target/arm/pac-2.c
new file mode 100644
index 00000000000..945ce938592
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-2.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-3.c b/gcc/testsuite/gcc.target/arm/pac-3.c
new file mode 100644
index 00000000000..47e290a5840
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-3.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=bti+pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pacbti\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-4.c b/gcc/testsuite/gcc.target/arm/pac-4.c
new file mode 100644
index 00000000000..cf915cdba50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-4.c
@@ -0,0 +1,10 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mthumb -mfloat-abi=hard --save-temps -O2" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-not "\tbti\t" } } */
+/* { dg-final { scan-assembler-not "\tpac\t" } } */
+/* { dg-final { scan-assembler-not "\tpacbti\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-5.c b/gcc/testsuite/gcc.target/arm/pac-5.c
new file mode 100644
index 00000000000..c70087eb6b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-5.c
@@ -0,0 +1,28 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int square (int z) { return z * z; }
+  return square (a) + square (b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 5)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-6.c b/gcc/testsuite/gcc.target/arm/pac-6.c
new file mode 100644
index 00000000000..c5329f0ef48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-6.c
@@ -0,0 +1,18 @@
+/* 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-options "-march=armv8.1-m.main+fp -mbranch-protection=pac-ret+leaf -mthumb --save-temps -O0 -g" } */
+
+int i;
+
+void foo (int);
+
+int bar()
+{
+  foo (i);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "pac\tip, lr, sp" } } */
+/* { dg-final { scan-assembler "aut\tip, lr, sp" } } */
+/* { dg-final { scan-assembler-not "bti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-7.c b/gcc/testsuite/gcc.target/arm/pac-7.c
new file mode 100644
index 00000000000..cdaebca5cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-7.c
@@ -0,0 +1,32 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  int x = 4;
+  int foo2 (int a, int b)
+  {
+    return a + b + x;
+  }
+  return foo2 (a, b);
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 7)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 3 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pac-8.c b/gcc/testsuite/gcc.target/arm/pac-8.c
new file mode 100644
index 00000000000..3f37dcfa5c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-8.c
@@ -0,0 +1,34 @@
+/* Testing return address signing.  */
+/* { dg-do run } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-require-effective-target arm_pacbti_hw } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+int acc (int n, ...)
+{
+    int sum = 0;
+    va_list ptr;
+
+    va_start (ptr, n);
+
+    for (int i = 0; i < n; i++)
+        sum += va_arg (ptr, int);
+    va_end (ptr);
+
+    return sum;
+}
+
+int main()
+{
+  if (acc (3, 1, 2, 3) != 6)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
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 00000000000..ee2fad290b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac-9.c
@@ -0,0 +1,11 @@
+/* Testing return address signing.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target mbranch_protection_ok } */
+/* { dg-options "-march=armv8.1-m.main+pacbti+fp -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=hard --save-temps -O0" } */
+
+#include "pac.h"
+
+/* { dg-final { scan-assembler-times "pac\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-times "aut\tip, lr, sp" 2 } } */
+/* { dg-final { scan-assembler-not "\tbti" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/pac.h b/gcc/testsuite/gcc.target/arm/pac.h
new file mode 100644
index 00000000000..7355e6b2954
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pac.h
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int
+__attribute__((noinline))
+foo1 (int a, int b)
+{
+  return a + b;
+}
+
+int
+main (void)
+{
+  if (foo1 (1, 2) != 3)
+    abort ();
+
+  return 0;
+}

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

end of thread, other threads:[~2023-03-10 16:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-12 16:30 [gcc(refs/vendors/ARM/heads/arm-12-m-pacbti)] [PATCH 10/15] arm: Implement cortex-M return signing address codegen Andrea Corallo
2023-03-10 16:21 Andrea Corallo

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).