PR target/41246
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Sep 2009 15:11:37 +0000 (15:11 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Sep 2009 15:11:37 +0000 (15:11 +0000)
* target.h (struct gcc_target): Add asm_out.trampoline_template,
calls.static_chain, calls.trampoline_init,
calls.trampoline_adjust_address.
* target-def.h (TARGET_ASM_TRAMPOLINE_TEMPLATE): New.
(TARGET_STATIC_CHAIN, TARGET_TRAMPOLINE_INIT): New.
(TARGET_TRAMPOLINE_ADJUST_ADDRESS): New.
* builtins.c (expand_builtin_setjmp_receiver): Use
targetm.calls.static_chain; only clobber registers.
(expand_builtin_init_trampoline): Use targetm.calls.trampoline_init;
set up memory attributes properly for the trampoline block.
(expand_builtin_adjust_trampoline): Use
targetm.calls.trampoline_adjust_address.
* calls.c (prepare_call_address): Add fndecl argument.  Use
targetm.calls.static_chain.
* df-scan.c (df_need_static_chain_reg): Remove.
(df_get_entry_block_def_set): Use targetm.calls.static_chain;
consolodate static chain handling.
* doc/tm.texi: Document new hooks.
* emit-rtl.c (static_chain_rtx, static_chain_incoming_rtx): Remove.
(init_emit_regs): Don't initialize them.
* expr.h (prepare_call_address): Update decl.
* final.c (profile_function): Use targetm.calls.static_chain.
* function.c (expand_function_start): Likewise.
* rtl.h (static_chain_rtx, static_chain_incoming_rtx): Remove.
* stmt.c (expand_nl_goto_receiver): Use targetm.calls.static_chain;
only clobber registers.
* targhooks.c (default_static_chain): New.
(default_asm_trampoline_template, default_trampoline_init): New.
(default_trampoline_adjust_address): New.
* targhooks.h: Declare them.
* varasm.c (assemble_trampoline_template): Use
targetm.asm_out.trampoline_template.  Make the memory block const
and set its size.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151983 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/calls.c
gcc/config/darwin.h
gcc/config/netbsd.h
gcc/df-scan.c
gcc/doc/tm.texi
gcc/emit-rtl.c
gcc/expr.h
gcc/final.c
gcc/function.c
gcc/rtl.h
gcc/stmt.c
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/varasm.c

index 25cc781..a918f39 100644 (file)
@@ -1,3 +1,40 @@
+2009-09-22  Richard Henderson  <rth@redhat.com>
+
+       PR target/41246
+       * target.h (struct gcc_target): Add asm_out.trampoline_template,
+       calls.static_chain, calls.trampoline_init,
+       calls.trampoline_adjust_address.
+       * target-def.h (TARGET_ASM_TRAMPOLINE_TEMPLATE): New.
+       (TARGET_STATIC_CHAIN, TARGET_TRAMPOLINE_INIT): New.
+       (TARGET_TRAMPOLINE_ADJUST_ADDRESS): New.
+       * builtins.c (expand_builtin_setjmp_receiver): Use
+       targetm.calls.static_chain; only clobber registers.
+       (expand_builtin_init_trampoline): Use targetm.calls.trampoline_init;
+       set up memory attributes properly for the trampoline block.
+       (expand_builtin_adjust_trampoline): Use
+       targetm.calls.trampoline_adjust_address.
+       * calls.c (prepare_call_address): Add fndecl argument.  Use
+       targetm.calls.static_chain.
+       * df-scan.c (df_need_static_chain_reg): Remove.
+       (df_get_entry_block_def_set): Use targetm.calls.static_chain;
+       consolodate static chain handling.
+       * doc/tm.texi: Document new hooks.
+       * emit-rtl.c (static_chain_rtx, static_chain_incoming_rtx): Remove.
+       (init_emit_regs): Don't initialize them.
+       * expr.h (prepare_call_address): Update decl.
+       * final.c (profile_function): Use targetm.calls.static_chain.
+       * function.c (expand_function_start): Likewise.
+       * rtl.h (static_chain_rtx, static_chain_incoming_rtx): Remove.
+       * stmt.c (expand_nl_goto_receiver): Use targetm.calls.static_chain;
+       only clobber registers.
+       * targhooks.c (default_static_chain): New.
+       (default_asm_trampoline_template, default_trampoline_init): New.
+       (default_trampoline_adjust_address): New.
+       * targhooks.h: Declare them.
+       * varasm.c (assemble_trampoline_template): Use
+       targetm.asm_out.trampoline_template.  Make the memory block const
+       and set its size.
+
 2009-09-22  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/41395
index fddb36c..7227481 100644 (file)
@@ -755,13 +755,17 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
 void
 expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
 {
+  rtx chain;
+
   /* Clobber the FP when we get here, so we have to make sure it's
      marked as used by this function.  */
   emit_use (hard_frame_pointer_rtx);
 
   /* Mark the static chain as clobbered here so life information
      doesn't get messed up for it.  */
-  emit_clobber (static_chain_rtx);
+  chain = targetm.calls.static_chain (current_function_decl, true);
+  if (chain && REG_P (chain))
+    emit_clobber (chain);
 
   /* Now put in the code to restore the frame pointer, and argument
      pointer, if needed.  */
@@ -839,11 +843,8 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
 
   buf_addr = force_reg (Pmode, buf_addr);
 
-  /* We used to store value in static_chain_rtx, but that fails if pointers
-     are smaller than integers.  We instead require that the user must pass
-     a second argument of 1, because that is what builtin_setjmp will
-     return.  This also makes EH slightly more efficient, since we are no
-     longer copying around a value that we don't care about.  */
+  /* We require that the user must pass a second argument of 1, because
+     that is what builtin_setjmp will return.  */
   gcc_assert (value == const1_rtx);
 
   last = get_last_insn ();
@@ -1590,7 +1591,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
     }
 
   /* All arguments and registers used for the call are set up by now!  */
-  function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
+  function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0);
 
   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
      and we don't want to load it into a register as an optimization,
@@ -5815,10 +5816,7 @@ static rtx
 expand_builtin_init_trampoline (tree exp)
 {
   tree t_tramp, t_func, t_chain;
-  rtx r_tramp, r_func, r_chain;
-#ifdef TRAMPOLINE_TEMPLATE
-  rtx blktramp;
-#endif
+  rtx m_tramp, r_tramp, r_chain, tmp;
 
   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
                         POINTER_TYPE, VOID_TYPE))
@@ -5829,20 +5827,36 @@ expand_builtin_init_trampoline (tree exp)
   t_chain = CALL_EXPR_ARG (exp, 2);
 
   r_tramp = expand_normal (t_tramp);
-  r_func = expand_normal (t_func);
+  m_tramp = gen_rtx_MEM (BLKmode, r_tramp);
+  MEM_NOTRAP_P (m_tramp) = 1;
+
+  /* The TRAMP argument should be the address of a field within the
+     local function's FRAME decl.  Let's see if we can fill in the
+     to fill in the MEM_ATTRs for this memory.  */
+  if (TREE_CODE (t_tramp) == ADDR_EXPR)
+    set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0),
+                                    true, 0);
+
+  tmp = round_trampoline_addr (r_tramp);
+  if (tmp != r_tramp)
+    {
+      m_tramp = change_address (m_tramp, BLKmode, tmp);
+      set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT);
+      set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE));
+    }
+
+  /* The FUNC argument should be the address of the nested function.
+     Extract the actual function decl to pass to the hook.  */
+  gcc_assert (TREE_CODE (t_func) == ADDR_EXPR);
+  t_func = TREE_OPERAND (t_func, 0);
+  gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL);
+
   r_chain = expand_normal (t_chain);
 
   /* Generate insns to initialize the trampoline.  */
-  r_tramp = round_trampoline_addr (r_tramp);
-#ifdef TRAMPOLINE_TEMPLATE
-  blktramp = gen_rtx_MEM (BLKmode, r_tramp);
-  set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
-  emit_block_move (blktramp, assemble_trampoline_template (),
-                  GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
-#endif
-  trampolines_created = 1;
-  INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
+  targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
 
+  trampolines_created = 1;
   return const0_rtx;
 }
 
@@ -5856,9 +5870,8 @@ expand_builtin_adjust_trampoline (tree exp)
 
   tramp = expand_normal (CALL_EXPR_ARG (exp, 0));
   tramp = round_trampoline_addr (tramp);
-#ifdef TRAMPOLINE_ADJUST_ADDRESS
-  TRAMPOLINE_ADJUST_ADDRESS (tramp);
-#endif
+  if (targetm.calls.trampoline_adjust_address)
+    tramp = targetm.calls.trampoline_adjust_address (tramp);
 
   return tramp;
 }
index 16229cc..f28fb51 100644 (file)
@@ -166,7 +166,7 @@ static void restore_fixed_argument_area (rtx, rtx, int, int);
    CALL_INSN_FUNCTION_USAGE information.  */
 
 rtx
-prepare_call_address (rtx funexp, rtx static_chain_value,
+prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value,
                      rtx *call_fusage, int reg_parm_seen, int sibcallp)
 {
   /* Make a valid memory address and copy constants through pseudo-regs,
@@ -187,11 +187,15 @@ prepare_call_address (rtx funexp, rtx static_chain_value,
 
   if (static_chain_value != 0)
     {
+      rtx chain;
+
+      gcc_assert (fndecl);
+      chain = targetm.calls.static_chain (fndecl, false);
       static_chain_value = convert_memory_address (Pmode, static_chain_value);
-      emit_move_insn (static_chain_rtx, static_chain_value);
 
-      if (REG_P (static_chain_rtx))
-       use_reg (call_fusage, static_chain_rtx);
+      emit_move_insn (chain, static_chain_value);
+      if (REG_P (chain))
+       use_reg (call_fusage, chain);
     }
 
   return funexp;
@@ -2807,7 +2811,7 @@ expand_call (tree exp, rtx target, int ignore)
        }
 
       after_args = get_last_insn ();
-      funexp = prepare_call_address (funexp, static_chain_value,
+      funexp = prepare_call_address (fndecl, funexp, static_chain_value,
                                     &call_fusage, reg_parm_seen, pass == 0);
 
       load_register_parameters (args, num_actuals, &call_fusage, flags,
@@ -3735,7 +3739,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   else
     argnum = 0;
 
-  fun = prepare_call_address (fun, NULL, &call_fusage, 0, 0);
+  fun = prepare_call_address (NULL, fun, NULL, &call_fusage, 0, 0);
 
   /* Now load any reg parms into their regs.  */
 
index 6fb1ec0..33af848 100644 (file)
@@ -982,7 +982,7 @@ void add_framework_path (char *);
 #endif
 
 /* Attempt to turn on execute permission for the stack.  This may be
-    used by INITIALIZE_TRAMPOLINE of the target needs it (that is,
+    used by TARGET_TRAMPOLINE_INIT if the target needs it (that is,
     if the target machine can change execute permissions on a page).
 
     There is no way to query the execute permission of the stack, so
index 3f42452..4f82809 100644 (file)
@@ -180,7 +180,7 @@ along with GCC; see the file COPYING3.  If not see
 \f
 
 /* Attempt to turn on execute permission for the stack.  This may be
-   used by INITIALIZE_TRAMPOLINE of the target needs it (that is,
+   used by TARGET_TRAMPOLINE_INIT if the target needs it (that is,
    if the target machine can change execute permissions on a page).
 
    There is no way to query the execute permission of the stack, so
index 35be03c..45df29e 100644 (file)
@@ -3601,18 +3601,6 @@ df_recompute_luids (basic_block bb)
 }
 
 
-/* Returns true if the function entry needs to 
-   define the static chain register.  */
-
-static bool
-df_need_static_chain_reg (struct function *fun)
-{
-  tree fun_context = decl_function_context (fun->decl);
-  return fun_context
-         && DECL_NO_STATIC_CHAIN (fun_context) == false;
-}
-
-
 /* Collect all artificial refs at the block level for BB and add them
    to COLLECTION_REC.  */
 
@@ -3891,24 +3879,17 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
        if ((call_used_regs[i] == 0) && (df_regs_ever_live_p (i)))
          bitmap_set_bit (entry_block_defs, i);
     }
-  else
-    {
-      /* If STATIC_CHAIN_INCOMING_REGNUM == STATIC_CHAIN_REGNUM
-        only STATIC_CHAIN_REGNUM is defined.  If they are different,
-        we only care about the STATIC_CHAIN_INCOMING_REGNUM.  */
-#ifdef STATIC_CHAIN_INCOMING_REGNUM
-      bitmap_set_bit (entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
-#else 
-#ifdef STATIC_CHAIN_REGNUM
-      bitmap_set_bit (entry_block_defs, STATIC_CHAIN_REGNUM);
-#endif
-#endif
-    }
 
   r = targetm.calls.struct_value_rtx (current_function_decl, true);
   if (r && REG_P (r))
     bitmap_set_bit (entry_block_defs, REGNO (r));
 
+  /* If the function has an incoming STATIC_CHAIN, it has to show up
+     in the entry def set.  */
+  r = targetm.calls.static_chain (current_function_decl, true);
+  if (r && REG_P (r))
+    bitmap_set_bit (entry_block_defs, REGNO (r));
+
   if ((!reload_completed) || frame_pointer_needed)
     {
       /* Any reference to any pseudo before reload is a potential
@@ -3946,19 +3927,6 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
 #endif
             
   targetm.live_on_entry (entry_block_defs);
-
-  /* If the function has an incoming STATIC_CHAIN,
-     it has to show up in the entry def set.  */
-  if (df_need_static_chain_reg (cfun))
-    {
-#ifdef STATIC_CHAIN_INCOMING_REGNUM
-      bitmap_set_bit (entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
-#else 
-#ifdef STATIC_CHAIN_REGNUM
-      bitmap_set_bit (entry_block_defs, STATIC_CHAIN_REGNUM);
-#endif
-#endif
-    }
 }
 
 
index 0139a8b..8a51a9f 100644 (file)
@@ -3684,6 +3684,16 @@ If the static chain is passed in a register, the two previous macros should
 be defined instead.
 @end defmac
 
+@deftypefn {Target Hook} rtx TARGET_STATIC_CHAIN (const_tree @var{fndecl}, bool @var{incoming_p})
+This hook replaces the use of @code{STATIC_CHAIN_REGNUM} et al for
+targets that may use different static chain locations for different
+nested functions.  This may be required if the target has function
+attributes that affect the calling conventions of the function and
+those calling conventions use different static chain locations.
+
+The default version of this hook uses @code{STATIC_CHAIN_REGNUM} et al.
+@end deftypefn
+
 @defmac DWARF_FRAME_REGISTERS
 This macro specifies the maximum number of hard registers that can be
 saved in a call frame.  This is used to size data structures used in
@@ -5099,17 +5109,17 @@ proper offset from the start of the trampoline.  On a RISC machine, it
 may be necessary to take out pieces of the address and store them
 separately.
 
-@defmac TRAMPOLINE_TEMPLATE (@var{file})
-A C statement to output, on the stream @var{file}, assembler code for a
-block of data that contains the constant parts of a trampoline.  This
-code should not include a label---the label is taken care of
-automatically.
+@deftypefn {Target Hook} void TARGET_ASM_TRAMPOLINE_TEMPLATE (FILE *@var{f})
+This hook is called by @code{assemble_trampoline_template} to output,
+on the stream @var{f}, assembler code for a block of data that contains
+the constant parts of a trampoline.  This code should not include a
+label---the label is taken care of automatically.
 
-If you do not define this macro, it means no template is needed
-for the target.  Do not define this macro on systems where the block move
+If you do not define this hook, it means no template is needed
+for the target.  Do not define this hook on systems where the block move
 code to copy the trampoline into place would be larger than the code
 to generate it on the spot.
-@end defmac
+@end deftypefn
 
 @defmac TRAMPOLINE_SECTION
 Return the section into which the trampoline template is to be placed
@@ -5123,43 +5133,38 @@ A C expression for the size in bytes of the trampoline, as an integer.
 @defmac TRAMPOLINE_ALIGNMENT
 Alignment required for trampolines, in bits.
 
-If you don't define this macro, the value of @code{BIGGEST_ALIGNMENT}
+If you don't define this macro, the value of @code{FUNCTION_ALIGNMENT}
 is used for aligning trampolines.
 @end defmac
 
-@defmac INITIALIZE_TRAMPOLINE (@var{addr}, @var{fnaddr}, @var{static_chain})
-A C statement to initialize the variable parts of a trampoline.
-@var{addr} is an RTX for the address of the trampoline; @var{fnaddr} is
-an RTX for the address of the nested function; @var{static_chain} is an
+@deftypefn {Target Hook} void TARGET_TRAMPOLINE_INIT (rtx @var{m_tramp}, tree @var{fndecl}, rtx @var{static_chain})
+This hook is called to initialize a trampoline.
+@var{m_tramp} is an RTX for the memory block for the trampoline; @var{fndecl}
+is the @code{FUNCTION_DECL} for the nested function; @var{static_chain} is an
 RTX for the static chain value that should be passed to the function
 when it is called.
-@end defmac
 
-@defmac TRAMPOLINE_ADJUST_ADDRESS (@var{addr})
-A C statement that should perform any machine-specific adjustment in
-the address of the trampoline.  Its argument contains the address that
-was passed to @code{INITIALIZE_TRAMPOLINE}.  In case the address to be
-used for a function call should be different from the address in which
-the template was stored, the different address should be assigned to
-@var{addr}.  If this macro is not defined, @var{addr} will be used for
-function calls.
+If the target defines @code{TARGET_ASM_TRAMPOLINE_TEMPLATE}, then the
+first thing this hook should do is emit a block move into @var{m_tramp}
+from the memory block returned by @code{assemble_trampoline_template}.
+Note that the block move need only cover the constant parts of the 
+trampoline.  If the target isolates the variable parts of the trampoline
+to the end, not all @code{TRAMPOLINE_SIZE} bytes need be copied.
 
-@cindex @code{TARGET_ASM_FUNCTION_EPILOGUE} and trampolines
-@cindex @code{TARGET_ASM_FUNCTION_PROLOGUE} and trampolines
-If this macro is not defined, by default the trampoline is allocated as
-a stack slot.  This default is right for most machines.  The exceptions
-are machines where it is impossible to execute instructions in the stack
-area.  On such machines, you may have to implement a separate stack,
-using this macro in conjunction with @code{TARGET_ASM_FUNCTION_PROLOGUE}
-and @code{TARGET_ASM_FUNCTION_EPILOGUE}.
-
-@var{fp} points to a data structure, a @code{struct function}, which
-describes the compilation status of the immediate containing function of
-the function which the trampoline is for.  The stack slot for the
-trampoline is in the stack frame of this containing function.  Other
-allocation strategies probably must do something analogous with this
-information.
-@end defmac
+If the target requires any other actions, such as flushing caches or
+enabling stack execution, these actions should be performed after 
+initializing the trampoline proper.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_TRAMPOLINE_ADJUST_ADDRESS (rtx @var{addr})
+This hook should perform any machine-specific adjustment in
+the address of the trampoline.  Its argument contains the address of the
+memory block that was passed to @code{TARGET_TRAMPOLINE_INIT}.  In case
+the address to be used for a function call should be different from the
+address at which the template was stored, the different address should
+be returned; otherwise @var{addr} should be returned unchanged.
+If this hook is not defined, @var{addr} will be used for function calls.
+@end deftypefn
 
 Implementing trampolines is difficult on many machines because they have
 separate instruction and data caches.  Writing into a stack location
@@ -5192,7 +5197,7 @@ code located on the stack.  The macro should expand to a series of C
 file-scope constructs (e.g.@: functions) and provide a unique entry point
 named @code{__enable_execute_stack}.  The target is responsible for
 emitting calls to the entry point in the code, for example from the
-@code{INITIALIZE_TRAMPOLINE} macro.
+@code{TARGET_TRAMPOLINE_INIT} hook.
 @end defmac
 
 To use a standard subroutine, define the following macro.  In addition,
index 9ed36b3..b3672e3 100644 (file)
@@ -136,8 +136,6 @@ FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
 
    In an inline procedure, the stack and frame pointer rtxs may not be
    used for anything else.  */
-rtx static_chain_rtx;          /* (REG:Pmode STATIC_CHAIN_REGNUM) */
-rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
 rtx pic_offset_table_rtx;      /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
 
 /* This is used to implement __builtin_return_address for some machines.
@@ -5671,28 +5669,6 @@ init_emit_regs (void)
     = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
 #endif
 
-#ifdef STATIC_CHAIN_REGNUM
-  static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
-
-#ifdef STATIC_CHAIN_INCOMING_REGNUM
-  if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
-    static_chain_incoming_rtx
-      = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
-  else
-#endif
-    static_chain_incoming_rtx = static_chain_rtx;
-#endif
-
-#ifdef STATIC_CHAIN
-  static_chain_rtx = STATIC_CHAIN;
-
-#ifdef STATIC_CHAIN_INCOMING
-  static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;
-#else
-  static_chain_incoming_rtx = static_chain_rtx;
-#endif
-#endif
-
   if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
     pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
   else
index 9bf0c38..4e02c24 100644 (file)
@@ -618,7 +618,7 @@ extern HOST_WIDE_INT int_expr_size (tree);
    in its original home.  This becomes invalid if any more code is emitted.  */
 extern rtx hard_function_value (const_tree, const_tree, const_tree, int);
 
-extern rtx prepare_call_address (rtx, rtx, rtx *, int, int);
+extern rtx prepare_call_address (tree, rtx, rtx, rtx *, int, int);
 
 extern bool shift_return_value (enum machine_mode, bool, rtx);
 
index cd36860..78a698b 100644 (file)
@@ -1594,12 +1594,14 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
 #ifndef NO_PROFILE_COUNTERS
 # define NO_PROFILE_COUNTERS   0
 #endif
-#if defined(ASM_OUTPUT_REG_PUSH)
-  int sval = cfun->returns_struct;
-  rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
-#if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
-  int cxt = cfun->static_chain_decl != NULL;
-#endif
+#ifdef ASM_OUTPUT_REG_PUSH
+  rtx sval = NULL, chain = NULL;
+
+  if (cfun->returns_struct)
+    sval = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl),
+                                          true);
+  if (cfun->static_chain_decl)
+    chain = targetm.calls.static_chain (current_function_decl, true);
 #endif /* ASM_OUTPUT_REG_PUSH */
 
   if (! NO_PROFILE_COUNTERS)
@@ -1613,44 +1615,20 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
 
   switch_to_section (current_function_section ());
 
-#if defined(ASM_OUTPUT_REG_PUSH)
-  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
-    {
-      ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
-    }
-#endif
-
-#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (cxt)
-    ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
-#else
-#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (cxt)
-    {
-      ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
-    }
-#endif
+#ifdef ASM_OUTPUT_REG_PUSH
+  if (sval && REG_P (sval))
+    ASM_OUTPUT_REG_PUSH (file, REGNO (sval));
+  if (chain && REG_P (chain))
+    ASM_OUTPUT_REG_PUSH (file, REGNO (chain));
 #endif
 
   FUNCTION_PROFILER (file, current_function_funcdef_no);
 
-#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (cxt)
-    ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
-#else
-#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
-  if (cxt)
-    {
-      ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
-    }
-#endif
-#endif
-
-#if defined(ASM_OUTPUT_REG_PUSH)
-  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
-    {
-      ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
-    }
+#ifdef ASM_OUTPUT_REG_PUSH
+  if (chain && REG_P (chain))
+    ASM_OUTPUT_REG_POP (file, REGNO (chain));
+  if (sval && REG_P (sval))
+    ASM_OUTPUT_REG_POP (file, REGNO (sval));
 #endif
 }
 
index 85e2f05..6c9bea8 100644 (file)
@@ -4453,13 +4453,21 @@ expand_function_start (tree subr)
   if (cfun->static_chain_decl)
     {
       tree parm = cfun->static_chain_decl;
-      rtx local = gen_reg_rtx (Pmode);
+      rtx local, chain, insn;
 
-      set_decl_incoming_rtl (parm, static_chain_incoming_rtx, false);
+      local = gen_reg_rtx (Pmode);
+      chain = targetm.calls.static_chain (current_function_decl, true);
+
+      set_decl_incoming_rtl (parm, chain, false);
       SET_DECL_RTL (parm, local);
       mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
 
-      emit_move_insn (local, static_chain_incoming_rtx);
+      insn = emit_move_insn (local, chain);
+
+      /* Mark the register as eliminable, similar to parameters.  */
+      if (MEM_P (chain)
+         && reg_mentioned_p (arg_pointer_rtx, XEXP (chain, 0)))
+       set_unique_reg_note (insn, REG_EQUIV, chain);
     }
 
   /* If the function receives a non-local goto, then store the
index 925246f..d415ba4 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2024,8 +2024,6 @@ extern GTY(()) rtx global_rtl[GR_MAX];
 #define arg_pointer_rtx                (global_rtl[GR_ARG_POINTER])
 
 extern GTY(()) rtx pic_offset_table_rtx;
-extern GTY(()) rtx static_chain_rtx;
-extern GTY(()) rtx static_chain_incoming_rtx;
 extern GTY(()) rtx return_address_pointer_rtx;
 
 /* Include the RTL generation functions.  */
index ffd180e..d2583ca 100644 (file)
@@ -1799,13 +1799,17 @@ expand_return (tree retval)
 static void
 expand_nl_goto_receiver (void)
 {
+  rtx chain;
+
   /* Clobber the FP when we get here, so we have to make sure it's
      marked as used by this function.  */
   emit_use (hard_frame_pointer_rtx);
 
   /* Mark the static chain as clobbered here so life information
      doesn't get messed up for it.  */
-  emit_clobber (static_chain_rtx);
+  chain = targetm.calls.static_chain (current_function_decl, true);
+  if (chain && REG_P (chain))
+    emit_clobber (chain);
 
 #ifdef HAVE_nonlocal_goto
   if (! HAVE_nonlocal_goto)
index 728e018..2ccdc66 100644 (file)
 #define TARGET_ASM_RECORD_GCC_SWITCHES_SECTION ".GCC.command.line"
 #endif
 
+#ifdef TRAMPOLINE_TEMPLATE
+# define TARGET_ASM_TRAMPOLINE_TEMPLATE default_asm_trampoline_template
+#else
+# define TARGET_ASM_TRAMPOLINE_TEMPLATE NULL
+#endif
+
 #define TARGET_ASM_ALIGNED_INT_OP                              \
                       {TARGET_ASM_ALIGNED_HI_OP,               \
                        TARGET_ASM_ALIGNED_SI_OP,               \
                        TARGET_ASM_RECORD_GCC_SWITCHES_SECTION, \
                        TARGET_ASM_OUTPUT_ANCHOR,               \
                        TARGET_ASM_OUTPUT_DWARF_DTPREL,         \
-                       TARGET_ASM_FINAL_POSTSCAN_INSN}
+                       TARGET_ASM_FINAL_POSTSCAN_INSN,         \
+                       TARGET_ASM_TRAMPOLINE_TEMPLATE }
 
 /* Scheduler hooks.  All of these default to null pointers, which
    haifa-sched.c looks for and handles.  */
 #define TARGET_UPDATE_STACK_BOUNDARY NULL
 #define TARGET_GET_DRAP_RTX NULL
 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS hook_bool_void_true
+#define TARGET_STATIC_CHAIN default_static_chain
+#define TARGET_TRAMPOLINE_INIT default_trampoline_init
+
+#ifdef TRAMPOLINE_ADJUST_ADDRESS
+# define TARGET_TRAMPOLINE_ADJUST_ADDRESS default_trampoline_adjust_address
+#else
+# define TARGET_TRAMPOLINE_ADJUST_ADDRESS NULL
+#endif
 
 #define TARGET_CALLS {                                         \
    TARGET_PROMOTE_FUNCTION_MODE,                               \
    TARGET_INTERNAL_ARG_POINTER,                                        \
    TARGET_UPDATE_STACK_BOUNDARY,                               \
    TARGET_GET_DRAP_RTX,                                                \
-   TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS                                \
+   TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS,                       \
+   TARGET_STATIC_CHAIN,                                                \
+   TARGET_TRAMPOLINE_INIT,                                     \
+   TARGET_TRAMPOLINE_ADJUST_ADDRESS                            \
    }
 
 #ifndef TARGET_UNWIND_TABLES_DEFAULT
index c57b683..f964b69 100644 (file)
@@ -253,6 +253,9 @@ struct gcc_target
 
     /* Some target machines need to postscan each insn after it is output.  */
     void (*final_postscan_insn) (FILE *, rtx, rtx *, int);
+
+    /* Emit the trampoline template.  This hook may be NULL.  */
+    void (*trampoline_template) (FILE *);
   } asm_out;
 
   /* Functions relating to instruction scheduling.  */
@@ -915,7 +918,17 @@ struct gcc_target
     /* Return true if all function parameters should be spilled to the
        stack.  */
     bool (*allocate_stack_slots_for_args) (void);
-    
+
+    /* Return an rtx for the static chain for FNDECL.  If INCOMING_P is true,
+       then it should be for the callee; otherwise for the caller.  */
+    rtx (*static_chain) (const_tree fndecl, bool incoming_p);
+
+    /* Fill in the trampoline at MEM with a call to FNDECL and a 
+       static chain value of CHAIN.  */
+    void (*trampoline_init) (rtx mem, tree fndecl, rtx chain);
+
+    /* Adjust the address of the trampoline in a target-specific way.  */
+    rtx (*trampoline_adjust_address) (rtx addr);
   } calls;
 
   /* Return the diagnostic message string if conversion from FROMTYPE
index 8480c0b..48401fb 100644 (file)
@@ -628,6 +628,69 @@ default_internal_arg_pointer (void)
     return virtual_incoming_args_rtx;
 }
 
+rtx
+default_static_chain (const_tree fndecl, bool incoming_p)
+{
+  if (DECL_NO_STATIC_CHAIN (fndecl))
+    return NULL;
+
+  if (incoming_p)
+    {
+#ifdef STATIC_CHAIN_INCOMING
+      return STATIC_CHAIN_INCOMING;
+#endif
+#ifdef STATIC_CHAIN_INCOMING_REGNUM
+      return gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM);
+#endif
+    }
+
+#ifdef STATIC_CHAIN
+  return STATIC_CHAIN;
+#endif
+#ifdef STATIC_CHAIN_REGNUM
+  return gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+#endif
+
+  gcc_unreachable ();
+}
+
+#ifdef TRAMPOLINE_TEMPLATE
+void
+default_asm_trampoline_template (FILE *f)
+{
+  TRAMPOLINE_TEMPLATE (f);
+}
+#endif
+
+void
+default_trampoline_init (rtx ARG_UNUSED (m_tramp), tree ARG_UNUSED (t_func),
+                        rtx ARG_UNUSED (r_chain))
+{
+#ifdef INITIALIZE_TRAMPOLINE
+  rtx r_tramp, r_func;
+
+  if (targetm.asm_out.trampoline_template)
+    emit_block_move (m_tramp, assemble_trampoline_template (),
+                    GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+  r_func = XEXP (DECL_RTL (t_func), 0);
+  r_tramp = XEXP (m_tramp, 0);
+
+  INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
+#else
+  sorry ("nested function trampolines not supported on this target");
+#endif
+}
+
+rtx
+default_trampoline_adjust_address (rtx addr)
+{
+#ifdef TRAMPOLINE_ADJUST_ADDRESS
+  TRAMPOLINE_ADJUST_ADDRESS (addr);
+#endif
+  return addr;
+}
+
 enum reg_class
 default_branch_target_register_class (void)
 {
index 7a93552..1a0dc56 100644 (file)
@@ -100,6 +100,10 @@ extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
 extern rtx default_function_value (const_tree, const_tree, bool);
 extern rtx default_libcall_value (enum machine_mode, rtx);
 extern rtx default_internal_arg_pointer (void);
+extern rtx default_static_chain (const_tree, bool);
+extern void default_asm_trampoline_template (FILE *);
+extern void default_trampoline_init (rtx, tree, rtx);
+extern rtx default_trampoline_adjust_address (rtx);
 extern enum reg_class default_branch_target_register_class (void);
 #ifdef IRA_COVER_CLASSES
 extern const enum reg_class *default_ira_cover_classes (void);
index 8a61fd2..f4532b8 100644 (file)
@@ -2507,7 +2507,6 @@ assemble_static_space (unsigned HOST_WIDE_INT size)
 
 static GTY(()) rtx initial_trampoline;
 
-#ifdef TRAMPOLINE_TEMPLATE
 rtx
 assemble_trampoline_template (void)
 {
@@ -2516,6 +2515,8 @@ assemble_trampoline_template (void)
   int align;
   rtx symbol;
 
+  gcc_assert (targetm.asm_out.trampoline_template != NULL);
+
   if (initial_trampoline)
     return initial_trampoline;
 
@@ -2530,12 +2531,10 @@ assemble_trampoline_template (void)
   /* Write the assembler code to define one.  */
   align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
   if (align > 0)
-    {
-      ASM_OUTPUT_ALIGN (asm_out_file, align);
-    }
+    ASM_OUTPUT_ALIGN (asm_out_file, align);
 
   targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
-  TRAMPOLINE_TEMPLATE (asm_out_file);
+  targetm.asm_out.trampoline_template (asm_out_file);
 
   /* Record the rtl to refer to it.  */
   ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
@@ -2543,12 +2542,12 @@ assemble_trampoline_template (void)
   symbol = gen_rtx_SYMBOL_REF (Pmode, name);
   SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
 
-  initial_trampoline = gen_rtx_MEM (BLKmode, symbol);
+  initial_trampoline = gen_const_mem (BLKmode, symbol);
   set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
+  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
 
   return initial_trampoline;
 }
-#endif
 \f
 /* A and B are either alignments or offsets.  Return the minimum alignment
    that may be assumed after adding the two together.  */