Our ABI says the blink is pushed first on stack followed by an unknown
number of register saves, and finally by fp.  Hence we cannot use the
EH_RETURN_ADDRESS macro as the stack is not finalized at that moment.
The alternative is to use the eh_return pattern and to initialize all
the bits after register allocation when the stack layout is finalized.

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claz...@synopsys.com>

        * config/arc/arc.c (arc_eh_return_address_location): Repurpose it
        to fit the eh_return pattern.
        * config/arc/arc.md (eh_return): Define.
        (VUNSPEC_ARC_EH_RETURN): Likewise.
        * config/arc/arc-protos.h (arc_eh_return_address_location): Match
        new implementation.
        * config/arc/arc.h (EH_RETURN_HANDLER_RTX): Remove it.

testsuite/
xxxx-xx-xx  Claudiu Zissulescu  <claz...@synopsys.com>

        * gcc.target/arc/builtin_eh.c: New test.
---
 gcc/config/arc/arc-protos.h               |  2 +-
 gcc/config/arc/arc.c                      | 13 ++++++++-----
 gcc/config/arc/arc.h                      |  2 --
 gcc/config/arc/arc.md                     | 15 +++++++++++++++
 gcc/testsuite/gcc.target/arc/builtin_eh.c | 22 ++++++++++++++++++++++
 5 files changed, 46 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/builtin_eh.c

diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index 6450b6a014e..4f72a06e3dc 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -110,7 +110,7 @@ extern bool arc_legitimize_reload_address (rtx *, 
machine_mode, int, int);
 extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
 extern void arc_cpu_cpp_builtins (cpp_reader *);
 extern bool arc_store_addr_hazard_p (rtx_insn *, rtx_insn *);
-extern rtx arc_eh_return_address_location (void);
+extern void arc_eh_return_address_location (rtx);
 extern bool arc_is_jli_call_p (rtx);
 extern void arc_file_end (void);
 extern bool arc_is_secure_call_p (rtx);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 6802ca66554..a92456b457d 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -3858,10 +3858,13 @@ arc_check_multi (rtx op, bool push_p)
 /* Return rtx for the location of the return address on the stack,
    suitable for use in __builtin_eh_return.  The new return address
    will be written to this location in order to redirect the return to
-   the exception handler.  */
+   the exception handler.  Our ABI says the blink is pushed first on
+   stack followed by an unknown number of register saves, and finally
+   by fp.  Hence we cannot use the EH_RETURN_ADDRESS macro as the
+   stack is not finalized.  */
 
-rtx
-arc_eh_return_address_location (void)
+void
+arc_eh_return_address_location (rtx source)
 {
   rtx mem;
   int offset;
@@ -3889,8 +3892,8 @@ arc_eh_return_address_location (void)
      remove this store seems perfectly sensible.  Marking the memory
      address as volatile obviously has the effect of preventing DSE
      from removing the store.  */
-  MEM_VOLATILE_P (mem) = 1;
-  return mem;
+  MEM_VOLATILE_P (mem) = true;
+  emit_move_insn (mem, source);
 }
 
 /* PIC */
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index afd6d7681cf..a0a84900917 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1355,8 +1355,6 @@ do { \
 
 #define EH_RETURN_STACKADJ_RTX   gen_rtx_REG (Pmode, 2)
 
-#define EH_RETURN_HANDLER_RTX    arc_eh_return_address_location ()
-
 /* Turn off splitting of long stabs.  */
 #define DBX_CONTIN_LENGTH 0
 
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index a28c67ac184..a6bac0e8bee 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -163,6 +163,7 @@
   VUNSPEC_ARC_SC
   VUNSPEC_ARC_LL
   VUNSPEC_ARC_BLOCKAGE
+  VUNSPEC_ARC_EH_RETURN
   ])
 
 (define_constants
@@ -6627,6 +6628,20 @@ core_3, archs4x, archs4xd, archs4xd_slow"
   [(set_attr "type" "call_no_delay_slot")
    (set_attr "length" "2")])
 
+;; Patterns for exception handling
+(define_insn_and_split "eh_return"
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
+                   VUNSPEC_ARC_EH_RETURN)]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  "
+  {
+    arc_eh_return_address_location (operands[0]);
+    DONE;
+  }"
+)
 ;; include the arc-FPX instructions
 (include "fpx.md")
 
diff --git a/gcc/testsuite/gcc.target/arc/builtin_eh.c 
b/gcc/testsuite/gcc.target/arc/builtin_eh.c
new file mode 100644
index 00000000000..717a54bb084
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_eh.c
@@ -0,0 +1,22 @@
+/* Check if we have the right offset for @bar function.  */
+/* { dg-options "-O1" } */
+
+void bar (void);
+
+void
+foo (int x)
+{
+  __builtin_unwind_init ();
+  __builtin_eh_return (x, bar);
+}
+
+/* { dg-final { scan-assembler "r24" } } */
+/* { dg-final { scan-assembler "r22" } } */
+/* { dg-final { scan-assembler "r20" } } */
+/* { dg-final { scan-assembler "r18" } } */
+/* { dg-final { scan-assembler "r16" } } */
+/* { dg-final { scan-assembler "r14" } } */
+/* { dg-final { scan-assembler "r13" } } */
+/* { dg-final { scan-assembler "r0" } } */
+/* { dg-final { scan-assembler "fp" } } */
+/* { dg-final { scan-assembler "fp,64" } } */
-- 
2.19.1

Reply via email to