Make MicroBlaze support DWARF EH (old Xilinx patch, needed for glibc build).
authorEdgar E. Iglesias <edgar.iglesias@xilinx.com>
Fri, 6 Jan 2017 20:54:34 +0000 (20:54 +0000)
committerJoseph Myers <jsm28@gcc.gnu.org>
Fri, 6 Jan 2017 20:54:34 +0000 (20:54 +0000)
This patch, taken from
<https://git.busybox.net/buildroot/tree/package/gcc/5.4.0/840-microblaze-enable-dwarf-eh-support.patch>
and with a few formatting cleanups and an update for the removal of
gen_rtx_raw_REG, enables DWARF EH support for MicroBlaze.

This is needed for building glibc with a compiler that includes shared
libgcc; right now all glibc builds for MicroBlaze are failing with my
bot for lack of this support.  (It's dubious if we should have glibc
ports at all where required support is missing in FSF GCC.)

Tested building glibc with build-many-glibcs.py.  I have *not* done
any other testing or any execution testing for MicroBlaze.

2017-01-06  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
    David Holsgrove <david.holsgrove@xilinx.com>

* common/config/microblaze/microblaze-common.c
(TARGET_EXCEPT_UNWIND_INFO): Remove.
* config/microblaze/microblaze-protos.h (microblaze_eh_return):
New prototype.
* config/microblaze/microblaze.c (microblaze_must_save_register)
(microblaze_expand_epilogue, microblaze_return_addr): Handle
calls_eh_return.
(microblaze_eh_return): New function.
* config/microblaze/microblaze.h (RETURN_ADDR_OFFSET)
(EH_RETURN_DATA_REGNO, MB_EH_STACKADJ_REGNUM)
(EH_RETURN_STACKADJ_RTX, ASM_PREFERRED_EH_DATA_FORMAT): New macros.
* config/microblaze/microblaze.md (eh_return): New pattern.

Co-Authored-By: David Holsgrove <david.holsgrove@xilinx.com>
From-SVN: r244183

gcc/ChangeLog
gcc/common/config/microblaze/microblaze-common.c
gcc/config/microblaze/microblaze-protos.h
gcc/config/microblaze/microblaze.c
gcc/config/microblaze/microblaze.h
gcc/config/microblaze/microblaze.md

index 9600c4371ea1f7fc267e7c37ca63263f765df4c3..88cc61bf9328c89096aea37b5d1d9729668ace7c 100644 (file)
@@ -1,3 +1,19 @@
+2017-01-06  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+           David Holsgrove <david.holsgrove@xilinx.com>
+
+       * common/config/microblaze/microblaze-common.c
+       (TARGET_EXCEPT_UNWIND_INFO): Remove.
+       * config/microblaze/microblaze-protos.h (microblaze_eh_return):
+       New prototype.
+       * config/microblaze/microblaze.c (microblaze_must_save_register)
+       (microblaze_expand_epilogue, microblaze_return_addr): Handle
+       calls_eh_return.
+       (microblaze_eh_return): New function.
+       * config/microblaze/microblaze.h (RETURN_ADDR_OFFSET)
+       (EH_RETURN_DATA_REGNO, MB_EH_STACKADJ_REGNUM)
+       (EH_RETURN_STACKADJ_RTX, ASM_PREFERRED_EH_DATA_FORMAT): New macros.
+       * config/microblaze/microblaze.md (eh_return): New pattern.
+
 2017-01-06  Jakub Jelinek  <jakub@redhat.com>
 
        * system.h (GCC_DIAGNOSTIC_PUSH_IGNORED, GCC_DIAGNOSTIC_POP,
index 57a30999761feffb286f695e103729b6ed8c9299..49756633056f0d6080b32d4621a48426a841b09f 100644 (file)
@@ -37,7 +37,4 @@ static const struct default_options microblaze_option_optimization_table[] =
 #undef  TARGET_OPTION_OPTIMIZATION_TABLE
 #define TARGET_OPTION_OPTIMIZATION_TABLE microblaze_option_optimization_table
 
-#undef TARGET_EXCEPT_UNWIND_INFO
-#define TARGET_EXCEPT_UNWIND_INFO  sjlj_except_unwind_info
-
 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
index 6fb3066207e43b2f6bdae419098d208c3858b566..9ba8f2d46f94dc546818ca5d0ec2da76828e877d 100644 (file)
@@ -57,6 +57,7 @@ extern bool microblaze_tls_referenced_p (rtx);
 extern int symbol_mentioned_p (rtx);
 extern int label_mentioned_p (rtx);
 extern bool microblaze_cannot_force_const_mem (machine_mode, rtx);
+extern void microblaze_eh_return (rtx op0);
 #endif  /* RTX_CODE */
 
 /* Declare functions in microblaze-c.c.  */
index 03b70e1dadd56ab74878778d5de31ee63570420c..746bef1faea4367ba4afaefd81cc472eda9dc589 100644 (file)
@@ -1926,6 +1926,10 @@ microblaze_must_save_register (int regno)
   if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM))
     return 1;
 
+  if (crtl->calls_eh_return
+      && regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
+    return 1;
+
   if (!crtl->is_leaf)
     {
       if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
@@ -1953,6 +1957,11 @@ microblaze_must_save_register (int regno)
        return 1;
     }
 
+  if (crtl->calls_eh_return
+      && (regno == EH_RETURN_DATA_REGNO (0)
+          || regno == EH_RETURN_DATA_REGNO (1)))
+    return 1;
+
   return 0;
 }
 
@@ -3029,6 +3038,12 @@ microblaze_expand_epilogue (void)
       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
     }
 
+  if (crtl->calls_eh_return)
+    emit_insn (gen_addsi3 (stack_pointer_rtx,
+                           stack_pointer_rtx,
+                           gen_raw_REG (SImode,
+                                       MB_EH_STACKADJ_REGNUM)));
+
   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
                                                    MB_ABI_SUB_RETURN_ADDR_REGNUM)));
 }
@@ -3326,10 +3341,14 @@ microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
   if (count != 0)
     return NULL_RTX;
 
-  return gen_rtx_PLUS (Pmode,
-                      get_hard_reg_initial_val (Pmode,
-                                                MB_ABI_SUB_RETURN_ADDR_REGNUM),
-                      GEN_INT (8));
+  return get_hard_reg_initial_val (Pmode,
+                                   MB_ABI_SUB_RETURN_ADDR_REGNUM);
+}
+
+void
+microblaze_eh_return (rtx op0)
+{
+  emit_insn (gen_movsi (gen_rtx_MEM (Pmode, stack_pointer_rtx), op0));
 }
 
 /* Queue an .ident string in the queue of top-level asm statements.
index 527f4d3837bc498acdf20e9a9b44c1c80940a5f4..8fdadbf27a05ead58c4769f4a9233d42e8891b27 100644 (file)
@@ -184,6 +184,22 @@ extern enum pipeline_type microblaze_pipe;
 #define INCOMING_RETURN_ADDR_RTX                       \
   gen_rtx_REG (Pmode, GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)
 
+/* Specifies the offset from INCOMING_RETURN_ADDR_RTX and the actual return PC.  */
+#define RETURN_ADDR_OFFSET (8)
+
+/* Describe how we implement __builtin_eh_return.  */
+#define EH_RETURN_DATA_REGNO(N)                                        \
+  (((N) < 2) ? MB_ABI_FIRST_ARG_REGNUM + (N) : INVALID_REGNUM)
+
+#define MB_EH_STACKADJ_REGNUM  MB_ABI_INT_RETURN_VAL2_REGNUM
+#define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, MB_EH_STACKADJ_REGNUM)
+
+/* Select a format to encode pointers in exception handling data.  CODE
+   is 0 for data, 1 for code labels, 2 for function pointers.  GLOBAL is
+   true if the symbol may be affected by dynamic relocations.  */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+  ((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
+
 /* Use DWARF 2 debugging information by default.  */
 #define DWARF2_DEBUGGING_INFO
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
index 8f83daa0af144fa66abcaf8873122d67bb74e5fa..66ebc1e5949821df936b00bc65dfcb43eea08259 100644 (file)
   (set_attr "mode"      "SI")
   (set_attr "length"    "4")])
 
+; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+  [(use (match_operand 0 "general_operand" ""))]
+  ""
+  "
+{
+  microblaze_eh_return (operands[0]);
+  DONE;
+}")
+
 (include "sync.md")