re PR target/9350 (-fomit-frame-pointer does not work for main)
authorRichard Henderson <rth@redhat.com>
Thu, 3 Nov 2005 01:40:33 +0000 (17:40 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 3 Nov 2005 01:40:33 +0000 (17:40 -0800)
        PR target/9350
        PR target/24374
        * dwarf2out.c (dwarf2out_reg_save_reg): New.
        (dwarf2out_frame_debug_expr): Return after dwarf_handle_frame_unspec.
        * function.c (assign_parms): Use calls.internal_arg_pointer.
        (expand_main_function): Remove FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
        code.
        * target-def.h (TARGET_INTERNAL_ARG_POINTER): New.
        (TARGET_CALLS): Add it.
        * target.h (struct gcc_target): Add calls.internal_arg_pointer.
        * targhooks.c (default_internal_arg_pointer): New.
        * targhooks.h (default_internal_arg_pointer): Declare.
        * tree.h (dwarf2out_reg_save_reg): Declare.
        * doc/tm.texi (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN): Remove.
        * config/i386/i386.c (dbx_register_map): Add return column.
        (dbx64_register_map, svr4_dbx_register_map): Likewise.
        (TARGET_INTERNAL_ARG_POINTER, ix86_internal_arg_pointer): New.
        (TARGET_DWARF_HANDLE_FRAME_UNSPEC, ix86_dwarf_handle_frame_unspec): New.        (ix86_function_ok_for_sibcall): Disable if force_align_arg_pointer.
        (ix86_save_reg): Save force_align_arg_pointer.
        (ix86_emit_save_regs): Make regno unsigned.
        (ix86_emit_save_regs_using_mov): Likewise.
        (ix86_expand_prologue): Handle force_align_arg_pointer.
        (ix86_expand_epilogue): Likewise.
        * config/i386/i386.h: (dbx_register_map): Update.
        (dbx64_register_map, svr4_dbx_register_map): Update.
        (struct machine_function): Add force_align_arg_pointer.
        * config/i386/i386.md (UNSPEC_REG_SAVE, UNSPEC_DEF_CFA): New.
        (UNSPEC_TP, UNSPEC_TLS_GD, UNSPEC_TLS_LD_BASE): Renumber.
        (TARGET_PUSH_MEMORY peepholes): Disable if RTX_FRAME_RELATED_P.

From-SVN: r106420

12 files changed:
gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/doc/tm.texi
gcc/dwarf2out.c
gcc/function.c
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/tree.h

index afca62bfa1ae325279eba422e30cb9ec4a35e5b4..a2e518a14f53495b5a17a2d4f774a3d0553eabdb 100644 (file)
@@ -1,3 +1,36 @@
+2005-11-02  Richard Henderson  <rth@redhat.com>
+
+       PR target/9350
+       PR target/24374
+       * dwarf2out.c (dwarf2out_reg_save_reg): New.
+       (dwarf2out_frame_debug_expr): Return after dwarf_handle_frame_unspec.
+       * function.c (assign_parms): Use calls.internal_arg_pointer.
+       (expand_main_function): Remove FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
+       code.
+       * target-def.h (TARGET_INTERNAL_ARG_POINTER): New.
+       (TARGET_CALLS): Add it.
+       * target.h (struct gcc_target): Add calls.internal_arg_pointer.
+       * targhooks.c (default_internal_arg_pointer): New.
+       * targhooks.h (default_internal_arg_pointer): Declare.
+       * tree.h (dwarf2out_reg_save_reg): Declare.
+       * doc/tm.texi (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN): Remove.
+       * config/i386/i386.c (dbx_register_map): Add return column.
+       (dbx64_register_map, svr4_dbx_register_map): Likewise.
+       (TARGET_INTERNAL_ARG_POINTER, ix86_internal_arg_pointer): New.
+       (TARGET_DWARF_HANDLE_FRAME_UNSPEC, ix86_dwarf_handle_frame_unspec): New.
+       (ix86_function_ok_for_sibcall): Disable if force_align_arg_pointer.
+       (ix86_save_reg): Save force_align_arg_pointer.
+       (ix86_emit_save_regs): Make regno unsigned.
+       (ix86_emit_save_regs_using_mov): Likewise.
+       (ix86_expand_prologue): Handle force_align_arg_pointer.
+       (ix86_expand_epilogue): Likewise.
+       * config/i386/i386.h: (dbx_register_map): Update.
+       (dbx64_register_map, svr4_dbx_register_map): Update.
+       (struct machine_function): Add force_align_arg_pointer.
+       * config/i386/i386.md (UNSPEC_REG_SAVE, UNSPEC_DEF_CFA): New.
+       (UNSPEC_TP, UNSPEC_TLS_GD, UNSPEC_TLS_LD_BASE): Renumber.
+       (TARGET_PUSH_MEMORY peepholes): Disable if RTX_FRAME_RELATED_P.
+
 2005-11-02  Jan Hubicka  <jh@suse.cz>
 
        PR target/23303
index 7b3f8887996abd407387ebe3e6c48f4f915c0000..26f0299b52bcfe4b52deda803dda428461d81a8c 100644 (file)
@@ -913,6 +913,8 @@ static void ix86_init_builtins (void);
 static rtx ix86_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
 static const char *ix86_mangle_fundamental_type (tree);
 static tree ix86_stack_protect_fail (void);
+static rtx ix86_internal_arg_pointer (void);
+static void ix86_dwarf_handle_frame_unspec (const char *, rtx, int);
 
 /* This function is only used on Solaris.  */
 static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
@@ -1081,6 +1083,10 @@ static void x86_64_elf_select_section (tree decl, int reloc,
 #define TARGET_MUST_PASS_IN_STACK ix86_must_pass_in_stack
 #undef TARGET_PASS_BY_REFERENCE
 #define TARGET_PASS_BY_REFERENCE ix86_pass_by_reference
+#undef TARGET_INTERNAL_ARG_POINTER
+#define TARGET_INTERNAL_ARG_POINTER ix86_internal_arg_pointer
+#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
+#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec
 
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg
@@ -1987,6 +1993,11 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
     return false;
 #endif
 
+  /* If we forced aligned the stack, then sibcalling would unalign the
+     stack, which may break the called function.  */
+  if (cfun->machine->force_align_arg_pointer)
+    return false;
+
   /* Otherwise okay.  That also includes certain types of indirect calls.  */
   return true;
 }
@@ -4508,6 +4519,10 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return)
        }
     }
 
+  if (cfun->machine->force_align_arg_pointer
+      && regno == REGNO (cfun->machine->force_align_arg_pointer))
+    return 1;
+
   return (regs_ever_live[regno]
          && !call_used_regs[regno]
          && !fixed_regs[regno]
@@ -4719,10 +4734,10 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
 static void
 ix86_emit_save_regs (void)
 {
-  int regno;
+  unsigned int regno;
   rtx insn;
 
-  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
+  for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0; )
     if (ix86_save_reg (regno, true))
       {
        insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
@@ -4735,7 +4750,7 @@ ix86_emit_save_regs (void)
 static void
 ix86_emit_save_regs_using_mov (rtx pointer, HOST_WIDE_INT offset)
 {
-  int regno;
+  unsigned int regno;
   rtx insn;
 
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
@@ -4783,6 +4798,47 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
     RTX_FRAME_RELATED_P (insn) = 1;
 }
 
+/* Handle the TARGET_INTERNAL_ARG_POINTER hook.  */
+
+static rtx
+ix86_internal_arg_pointer (void)
+{
+  if (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
+      && DECL_NAME (current_function_decl)
+      && MAIN_NAME_P (DECL_NAME (current_function_decl))
+      && DECL_FILE_SCOPE_P (current_function_decl))
+    {
+      cfun->machine->force_align_arg_pointer = gen_rtx_REG (Pmode, 2);
+      return copy_to_reg (cfun->machine->force_align_arg_pointer);
+    }
+  else
+    return virtual_incoming_args_rtx;
+}
+
+/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
+   This is called from dwarf2out.c to emit call frame instructions
+   for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
+static void
+ix86_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
+{
+  rtx unspec = SET_SRC (pattern);
+  gcc_assert (GET_CODE (unspec) == UNSPEC);
+
+  switch (index)
+    {
+    case UNSPEC_REG_SAVE:
+      dwarf2out_reg_save_reg (label, XVECEXP (unspec, 0, 0),
+                             SET_DEST (pattern));
+      break;
+    case UNSPEC_DEF_CFA:
+      dwarf2out_def_cfa (label, REGNO (SET_DEST (pattern)),
+                        INTVAL (XVECEXP (unspec, 0, 0)));
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Expand the prologue into a bunch of separate insns.  */
 
 void
@@ -4795,6 +4851,52 @@ ix86_expand_prologue (void)
 
   ix86_compute_frame_layout (&frame);
 
+  if (cfun->machine->force_align_arg_pointer)
+    {
+      rtx x, y;
+
+      /* Grab the argument pointer.  */
+      x = plus_constant (stack_pointer_rtx, 4);
+      y = cfun->machine->force_align_arg_pointer;
+      insn = emit_insn (gen_rtx_SET (VOIDmode, y, x));
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      /* The unwind info consists of two parts: install the fafp as the cfa,
+        and record the fafp as the "save register" of the stack pointer.
+        The later is there in order that the unwinder can see where it
+        should restore the stack pointer across the and insn.  */
+      x = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_DEF_CFA);
+      x = gen_rtx_SET (VOIDmode, y, x);
+      RTX_FRAME_RELATED_P (x) = 1;
+      y = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, stack_pointer_rtx),
+                         UNSPEC_REG_SAVE);
+      y = gen_rtx_SET (VOIDmode, cfun->machine->force_align_arg_pointer, y);
+      RTX_FRAME_RELATED_P (y) = 1;
+      x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x, y));
+      x = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, x, NULL);
+      REG_NOTES (insn) = x;
+
+      /* Align the stack.  */
+      emit_insn (gen_andsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                            GEN_INT (-16)));
+
+      /* And here we cheat like madmen with the unwind info.  We force the
+        cfa register back to sp+4, which is exactly what it was at the
+        start of the function.  Re-pushing the return address results in
+        the return at the same spot relative to the cfa, and thus is 
+        correct wrt the unwind info.  */
+      x = cfun->machine->force_align_arg_pointer;
+      x = gen_frame_mem (Pmode, plus_constant (x, -4));
+      insn = emit_insn (gen_push (x));
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      x = GEN_INT (4);
+      x = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, x), UNSPEC_DEF_CFA);
+      x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
+      x = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, x, NULL);
+      REG_NOTES (insn) = x;
+    }
+
   /* Note: AT&T enter does NOT have reversed args.  Enter is probably
      slower on all targets.  Also sdb doesn't like it.  */
 
@@ -5072,6 +5174,13 @@ ix86_expand_epilogue (int style)
        }
     }
 
+  if (cfun->machine->force_align_arg_pointer)
+    {
+      emit_insn (gen_addsi3 (stack_pointer_rtx,
+                            cfun->machine->force_align_arg_pointer,
+                            GEN_INT (-4)));
+    }
+
   /* Sibcall epilogues don't want a return instruction.  */
   if (style == 0)
     return;
index a00e0e043abc414bed74898f03dad22ea7ec88b0..256c0e49e20963866125d2287985e96a11accd7a 100644 (file)
@@ -2263,6 +2263,7 @@ struct machine_function GTY(())
 {
   struct stack_local_entry *stack_locals;
   const char *some_ld_name;
+  rtx force_align_arg_pointer;
   int save_varrargs_registers;
   int accesses_prev_frame;
   int optimize_mode_switching[MAX_386_ENTITIES];
index 19d874bce845726ab0eca3097404d653b422bd64..b739e5004971ae9c36d992e63b08a50bd5b4790d 100644 (file)
    (UNSPEC_STACK_ALLOC         11)
    (UNSPEC_SET_GOT             12)
    (UNSPEC_SSE_PROLOGUE_SAVE   13)
+   (UNSPEC_REG_SAVE            14)
+   (UNSPEC_DEF_CFA             15)
 
    ; TLS support
-   (UNSPEC_TP                  15)
-   (UNSPEC_TLS_GD              16)
-   (UNSPEC_TLS_LD_BASE         17)
+   (UNSPEC_TP                  16)
+   (UNSPEC_TLS_GD              17)
+   (UNSPEC_TLS_LD_BASE         18)
 
    ; Other random patterns
    (UNSPEC_SCAS                        20)
   [(set (match_operand:SI 0 "push_operand" "")
        (match_operand:SI 1 "memory_operand" ""))
    (match_scratch:SI 2 "r")]
-  "! optimize_size && ! TARGET_PUSH_MEMORY"
+  "!optimize_size && !TARGET_PUSH_MEMORY
+   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
   [(set (match_operand:DI 0 "push_operand" "")
        (match_operand:DI 1 "memory_operand" ""))
    (match_scratch:DI 2 "r")]
-  "! optimize_size && ! TARGET_PUSH_MEMORY"
+  "!optimize_size && !TARGET_PUSH_MEMORY
+   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
   [(set (match_operand:SF 0 "push_operand" "")
        (match_operand:SF 1 "memory_operand" ""))
    (match_scratch:SF 2 "r")]
-  "! optimize_size && ! TARGET_PUSH_MEMORY"
+  "!optimize_size && !TARGET_PUSH_MEMORY
+   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
   [(set (match_operand:HI 0 "push_operand" "")
        (match_operand:HI 1 "memory_operand" ""))
    (match_scratch:HI 2 "r")]
-  "! optimize_size && ! TARGET_PUSH_MEMORY"
+  "!optimize_size && !TARGET_PUSH_MEMORY
+   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
   [(set (match_operand:QI 0 "push_operand" "")
        (match_operand:QI 1 "memory_operand" ""))
    (match_scratch:QI 2 "q")]
-  "! optimize_size && ! TARGET_PUSH_MEMORY"
+  "!optimize_size && !TARGET_PUSH_MEMORY
+   && !RTX_FRAME_RELATED_P (peep2_next_insn (0))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
index 46d24b6b7896dd030d099f7d0ec153747f6759ad..b339c4ccdc0554eee591015489e9148621f42d09 100644 (file)
@@ -1033,18 +1033,6 @@ macro must evaluate to a value equal to or larger than
 @code{STACK_BOUNDARY}.
 @end defmac
 
-@defmac FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
-A C expression that evaluates true if @code{PREFERRED_STACK_BOUNDARY} is
-not guaranteed by the runtime and we should emit code to align the stack
-at the beginning of @code{main}.
-
-@cindex @code{PUSH_ROUNDING}, interaction with @code{PREFERRED_STACK_BOUNDARY}
-If @code{PUSH_ROUNDING} is not defined, the stack will always be aligned
-to the specified boundary.  If @code{PUSH_ROUNDING} is defined and specifies
-a less strict alignment than @code{PREFERRED_STACK_BOUNDARY}, the stack may
-be momentarily unaligned while pushing arguments.
-@end defmac
-
 @defmac FUNCTION_BOUNDARY
 Alignment required for a function entry point, in bits.
 @end defmac
index d780914fe1ea1c2b4dbd3a9b9561590c03b960ab..314652b15470133fabd603cb8d2581343e5f936f 100644 (file)
@@ -1271,6 +1271,30 @@ clobbers_queued_reg_save (rtx insn)
   return false;
 }
 
+/* Entry point for saving the first register into the second.  */
+
+void
+dwarf2out_reg_save_reg (const char *label, rtx reg, rtx sreg)
+{
+  size_t i;
+  unsigned int regno, sregno;
+
+  for (i = 0; i < num_regs_saved_in_regs; i++)
+    if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (reg))
+      break;
+  if (i == num_regs_saved_in_regs)
+    {
+      gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
+      num_regs_saved_in_regs++;
+    }
+  regs_saved_in_regs[i].orig_reg = reg;
+  regs_saved_in_regs[i].saved_in_reg = sreg;
+
+  regno = DWARF_FRAME_REGNUM (REGNO (reg));
+  sregno = DWARF_FRAME_REGNUM (REGNO (sreg));
+  reg_save (label, regno, sregno, 0);
+}
+
 /* What register, if any, is currently saved in REG?  */
 
 static rtx
@@ -1659,7 +1683,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
        case UNSPEC_VOLATILE:
          gcc_assert (targetm.dwarf_handle_frame_unspec);
          targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
-         break;
+         return;
 
        default:
          gcc_unreachable ();
index 941021edc6678ac7783f9305d9da15d191763453..9e36af74d72344d9cb3c33eae0a3285e5c44d13a 100644 (file)
@@ -2894,22 +2894,9 @@ assign_parms (tree fndecl)
 {
   struct assign_parm_data_all all;
   tree fnargs, parm;
-  rtx internal_arg_pointer;
 
-  /* If the reg that the virtual arg pointer will be translated into is
-     not a fixed reg or is the stack pointer, make a copy of the virtual
-     arg pointer, and address parms via the copy.  The frame pointer is
-     considered fixed even though it is not marked as such.
-
-     The second time through, simply use ap to avoid generating rtx.  */
-
-  if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
-       || ! (fixed_regs[ARG_POINTER_REGNUM]
-            || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
-    internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
-  else
-    internal_arg_pointer = virtual_incoming_args_rtx;
-  current_function_internal_arg_pointer = internal_arg_pointer;
+  current_function_internal_arg_pointer
+    = targetm.calls.internal_arg_pointer ();
 
   assign_parms_initialize_all (&all);
   fnargs = assign_parms_augmented_arg_list (&all);
@@ -3916,42 +3903,6 @@ struct tree_opt_pass pass_init_function =
 void
 expand_main_function (void)
 {
-#ifdef FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
-  if (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN)
-    {
-      int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
-      rtx tmp, seq;
-
-      start_sequence ();
-      /* Forcibly align the stack.  */
-#ifdef STACK_GROWS_DOWNWARD
-      tmp = expand_simple_binop (Pmode, AND, stack_pointer_rtx, GEN_INT(-align),
-                                stack_pointer_rtx, 1, OPTAB_WIDEN);
-#else
-      tmp = expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
-                                GEN_INT (align - 1), NULL_RTX, 1, OPTAB_WIDEN);
-      tmp = expand_simple_binop (Pmode, AND, tmp, GEN_INT (-align),
-                                stack_pointer_rtx, 1, OPTAB_WIDEN);
-#endif
-      if (tmp != stack_pointer_rtx)
-       emit_move_insn (stack_pointer_rtx, tmp);
-
-      /* Enlist allocate_dynamic_stack_space to pick up the pieces.  */
-      tmp = force_reg (Pmode, const0_rtx);
-      allocate_dynamic_stack_space (tmp, NULL_RTX, BIGGEST_ALIGNMENT);
-      seq = get_insns ();
-      end_sequence ();
-
-      for (tmp = get_last_insn (); tmp; tmp = PREV_INSN (tmp))
-       if (NOTE_P (tmp) && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_FUNCTION_BEG)
-         break;
-      if (tmp)
-       emit_insn_before (seq, tmp);
-      else
-       emit_insn (seq);
-    }
-#endif
-
 #if (defined(INVOKE__main)                             \
      || (!defined(HAS_INIT_SECTION)                    \
         && !defined(INIT_SECTION_ASM_OP)               \
index 6dd121d952f6846e55db02c60499a410748ed953..7e8837451f3c2e8249fe0886ebc79d7fbbe062ab 100644 (file)
@@ -445,6 +445,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #define TARGET_ARG_PARTIAL_BYTES hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
 
 #define TARGET_FUNCTION_VALUE default_function_value
+#define TARGET_INTERNAL_ARG_POINTER default_internal_arg_pointer
 
 #define TARGET_CALLS {                                         \
    TARGET_PROMOTE_FUNCTION_ARGS,                               \
@@ -463,7 +464,8 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    TARGET_CALLEE_COPIES,                                       \
    TARGET_ARG_PARTIAL_BYTES,                                   \
    TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN,                     \
-   TARGET_FUNCTION_VALUE                                       \
+   TARGET_FUNCTION_VALUE,                                      \
+   TARGET_INTERNAL_ARG_POINTER                                 \
    }
 
 #ifndef TARGET_UNWIND_TABLES_DEFAULT
index cd850d1a4b5eb782d43e57b5c350c1028fffd980..0f775f1de157291e20f4f85f6424f74c39e923b9 100644 (file)
@@ -613,6 +613,10 @@ struct gcc_target
        specified by FN_DECL_OR_TYPE with a return type of RET_TYPE.  */
     rtx (*function_value) (tree ret_type, tree fn_decl_or_type,
                           bool outgoing);
+
+    /* Return an rtx for the argument pointer incoming to the
+       current function.  */
+    rtx (*internal_arg_pointer) (void);
   } calls;
 
   /* Return the diagnostic message string if conversion from FROMTYPE
index c0c42019a04a6bee45a48af7e7563606a1acf167..94469a76b0fb9b33158d3aed889a7728d933a3e0 100644 (file)
@@ -62,6 +62,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "tm_p.h"
 #include "target-def.h"
 #include "ggc.h"
+#include "hard-reg-set.h"
 
 
 void
@@ -439,4 +440,19 @@ default_function_value (tree ret_type ATTRIBUTE_UNUSED,
 #endif
 }
 
+rtx
+default_internal_arg_pointer (void)
+{
+  /* If the reg that the virtual arg pointer will be translated into is
+     not a fixed reg or is the stack pointer, make a copy of the virtual
+     arg pointer, and address parms via the copy.  The frame pointer is
+     considered fixed even though it is not marked as such.  */
+  if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
+       || ! (fixed_regs[ARG_POINTER_REGNUM]
+            || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
+    return copy_to_reg (virtual_incoming_args_rtx);
+  else
+    return virtual_incoming_args_rtx;
+}
+
 #include "gt-targhooks.h"
index a39d27df33707ae69ea024759583d6ded7b73390..24e3b6d38be27a162f5c1811be20b45d6b229947 100644 (file)
@@ -68,4 +68,4 @@ extern const char *hook_invalid_arg_for_unprototyped_fn
   (tree, tree, tree);
 extern bool hook_bool_rtx_commutative_p (rtx, int);
 extern rtx default_function_value (tree, tree, bool);
-
+extern rtx default_internal_arg_pointer (void);
index f54f6d34977f39509b118209df100d8d12531dd9..4705bb12b83fdaa8d482179551eab2d764a4b377 100644 (file)
@@ -4119,6 +4119,10 @@ extern void dwarf2out_return_save (const char *, HOST_WIDE_INT);
 
 extern void dwarf2out_return_reg (const char *, unsigned);
 
+/* Entry point for saving the first register into the second.  */
+
+extern void dwarf2out_reg_save_reg (const char *, rtx, rtx);
+
 /* In tree-inline.c  */
 
 /* The type of a set of already-visited pointers.  Functions for creating