OSDN Git Service

* function.c (use_return_register): Make it static.
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index 3fcc8b8..473f5d4 100644 (file)
@@ -454,7 +454,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, int align,
 
   /* On a big-endian machine, if we are allocating more space than we will use,
      use the least significant bytes of those that are allocated.  */
-  if (BYTES_BIG_ENDIAN && mode != BLKmode)
+  if (BYTES_BIG_ENDIAN && mode != BLKmode && GET_MODE_SIZE (mode) < size)
     bigend_correction = size - GET_MODE_SIZE (mode);
 
   /* If we have already instantiated virtual registers, return the actual
@@ -474,10 +474,26 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, int align,
     function->x_frame_offset += size;
 
   x = gen_rtx_MEM (mode, addr);
+  MEM_NOTRAP_P (x) = 1;
 
   function->x_stack_slot_list
     = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
 
+  /* Try to detect frame size overflows on native platforms.  */
+#if BITS_PER_WORD >= 32
+  if ((FRAME_GROWS_DOWNWARD
+       ? (unsigned HOST_WIDE_INT) -function->x_frame_offset
+       : (unsigned HOST_WIDE_INT) function->x_frame_offset)
+       > ((unsigned HOST_WIDE_INT) 1 << (BITS_PER_WORD - 1))
+           /* Leave room for the fixed part of the frame.  */
+           - 64 * UNITS_PER_WORD)
+    {
+      error ("%Jtotal size of local objects too large", function->decl);
+      /* Avoid duplicate error messages as much as possible.  */
+      function->x_frame_offset = 0;
+    }
+#endif
+
   return x;
 }
 
@@ -609,22 +625,30 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
 
   /* Try to find an available, already-allocated temporary of the proper
      mode which meets the size and alignment requirements.  Choose the
-     smallest one with the closest alignment.  */
-  for (p = avail_temp_slots; p; p = p->next)
+     smallest one with the closest alignment.
+   
+     If assign_stack_temp is called outside of the tree->rtl expansion,
+     we cannot reuse the stack slots (that may still refer to
+     VIRTUAL_STACK_VARS_REGNUM).  */
+  if (!virtuals_instantiated)
     {
-      if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
-         && objects_must_conflict_p (p->type, type)
-         && (best_p == 0 || best_p->size > p->size
-             || (best_p->size == p->size && best_p->align > p->align)))
+      for (p = avail_temp_slots; p; p = p->next)
        {
-         if (p->align == align && p->size == size)
+         if (p->align >= align && p->size >= size
+             && GET_MODE (p->slot) == mode
+             && objects_must_conflict_p (p->type, type)
+             && (best_p == 0 || best_p->size > p->size
+                 || (best_p->size == p->size && best_p->align > p->align)))
            {
-             selected = p;
-             cut_slot_from_list (selected, &avail_temp_slots);
-             best_p = 0;
-             break;
+             if (p->align == align && p->size == size)
+               {
+                 selected = p;
+                 cut_slot_from_list (selected, &avail_temp_slots);
+                 best_p = 0;
+                 break;
+               }
+             best_p = p;
            }
-         best_p = p;
        }
     }
 
@@ -649,9 +673,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
              p->size = best_p->size - rounded_size;
              p->base_offset = best_p->base_offset + rounded_size;
              p->full_size = best_p->full_size - rounded_size;
-             p->slot = gen_rtx_MEM (BLKmode,
-                                    plus_constant (XEXP (best_p->slot, 0),
-                                                   rounded_size));
+             p->slot = adjust_address_nv (best_p->slot, BLKmode, rounded_size);
              p->align = best_p->align;
              p->address = 0;
              p->type = best_p->type;
@@ -743,6 +765,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
       MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
       MEM_SET_IN_STRUCT_P (slot, AGGREGATE_TYPE_P (type));
     }
+  MEM_NOTRAP_P (slot) = 1;
 
   return slot;
 }
@@ -1211,12 +1234,6 @@ static int cfa_offset;
 #endif
 #endif
 
-/* On most machines, the CFA coincides with the first incoming parm.  */
-
-#ifndef ARG_POINTER_CFA_OFFSET
-#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
-#endif
-
 \f
 /* Given a piece of RTX and a pointer to a HOST_WIDE_INT, if the RTX
    is a virtual register, return the equivalent hard register and set the
@@ -1237,7 +1254,14 @@ instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset)
   else if (x == virtual_outgoing_args_rtx)
     new = stack_pointer_rtx, offset = out_arg_offset;
   else if (x == virtual_cfa_rtx)
-    new = arg_pointer_rtx, offset = cfa_offset;
+    {
+#ifdef FRAME_POINTER_CFA_OFFSET
+      new = frame_pointer_rtx;
+#else
+      new = arg_pointer_rtx;
+#endif
+      offset = cfa_offset;
+    }
   else
     return NULL_RTX;
 
@@ -1574,6 +1598,22 @@ instantiate_decl (rtx x)
   for_each_rtx (&XEXP (x, 0), instantiate_virtual_regs_in_rtx, NULL);
 }
 
+/* Helper for instantiate_decls called via walk_tree: Process all decls
+   in the given DECL_VALUE_EXPR.  */
+
+static tree
+instantiate_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+  tree t = *tp;
+  if (! EXPR_P (t))
+    {
+      *walk_subtrees = 0;
+      if (DECL_P (t) && DECL_RTL_SET_P (t))
+       instantiate_decl (DECL_RTL (t));
+    }
+  return NULL;
+}
+
 /* Subroutine of instantiate_decls: Process all decls in the given
    BLOCK node and all its subblocks.  */
 
@@ -1583,8 +1623,15 @@ instantiate_decls_1 (tree let)
   tree t;
 
   for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
-    if (DECL_RTL_SET_P (t))
-      instantiate_decl (DECL_RTL (t));
+    {
+      if (DECL_RTL_SET_P (t))
+       instantiate_decl (DECL_RTL (t));
+      if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
+       {
+         tree v = DECL_VALUE_EXPR (t);
+         walk_tree (&v, instantiate_expr, NULL, NULL);
+       }
+    }
 
   /* Process all subblocks.  */
   for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
@@ -1604,6 +1651,11 @@ instantiate_decls (tree fndecl)
     {
       instantiate_decl (DECL_RTL (decl));
       instantiate_decl (DECL_INCOMING_RTL (decl));
+      if (DECL_HAS_VALUE_EXPR_P (decl))
+       {
+         tree v = DECL_VALUE_EXPR (decl);
+         walk_tree (&v, instantiate_expr, NULL, NULL);
+       }
     }
 
   /* Now process all variables defined in the function or its subblocks.  */
@@ -1613,7 +1665,7 @@ instantiate_decls (tree fndecl)
 /* Pass through the INSNS of function FNDECL and convert virtual register
    references to hard register references.  */
 
-void
+static unsigned int
 instantiate_virtual_regs (void)
 {
   rtx insn;
@@ -1623,7 +1675,11 @@ instantiate_virtual_regs (void)
   var_offset = STARTING_FRAME_OFFSET;
   dynamic_offset = STACK_DYNAMIC_OFFSET (current_function_decl);
   out_arg_offset = STACK_POINTER_OFFSET;
+#ifdef FRAME_POINTER_CFA_OFFSET
+  cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
+#else
   cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
+#endif
 
   /* Initialize recognition, indicating that volatile is OK.  */
   init_recog ();
@@ -1661,11 +1717,12 @@ instantiate_virtual_regs (void)
   /* Indicate that, from now on, assign_stack_local should use
      frame_pointer_rtx.  */
   virtuals_instantiated = 1;
+  return 0;
 }
 
 struct tree_opt_pass pass_instantiate_virtual_regs =
 {
-  NULL,                                 /* name */
+  "vregs",                              /* name */
   NULL,                                 /* gate */
   instantiate_virtual_regs,             /* execute */
   NULL,                                 /* sub */
@@ -1676,7 +1733,7 @@ struct tree_opt_pass pass_instantiate_virtual_regs =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
+  TODO_dump_func,                       /* todo_flags_finish */
   0                                     /* letter */
 };
 
@@ -1732,7 +1789,7 @@ aggregate_value_p (tree exp, tree fntype)
     return 1;
   /* Make sure we have suitable call-clobbered regs to return
      the value in; if not, we must return it in memory.  */
-  reg = hard_function_value (type, 0, 0);
+  reg = hard_function_value (type, 0, fntype, 0);
 
   /* If we have something other than a REG (e.g. a PARALLEL), then assume
      it is OK.  */
@@ -2019,9 +2076,8 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
   /* If the parm is to be passed as a transparent union, use the type of
      the first field for the tests below.  We have already verified that
      the modes are the same.  */
-  if (DECL_TRANSPARENT_UNION (parm)
-      || (TREE_CODE (passed_type) == UNION_TYPE
-         && TYPE_TRANSPARENT_UNION (passed_type)))
+  if (TREE_CODE (passed_type) == UNION_TYPE
+      && TYPE_TRANSPARENT_UNION (passed_type))
     passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
 
   /* See if this arg was passed by invisible reference.  */
@@ -2577,8 +2633,10 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
   /* Store the parm in a pseudoregister during the function, but we may
      need to do it in a wider mode.  */
 
+  /* This is not really promoting for a call.  However we need to be
+     consistent with assign_parm_find_data_types and expand_expr_real_1.  */
   promoted_nominal_mode
-    = promote_mode (data->nominal_type, data->nominal_mode, &unsignedp, 0);
+    = promote_mode (data->nominal_type, data->nominal_mode, &unsignedp, 1);
 
   parmreg = gen_reg_rtx (promoted_nominal_mode);
 
@@ -2901,22 +2959,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);
@@ -3007,9 +3052,8 @@ assign_parms (tree fndecl)
                                    REG_PARM_STACK_SPACE (fndecl));
 #endif
 
-  current_function_args_size
-    = ((current_function_args_size + STACK_BYTES - 1)
-       / STACK_BYTES) * STACK_BYTES;
+  current_function_args_size = CEIL_ROUND (current_function_args_size,
+                                          PARM_BOUNDARY / BITS_PER_UNIT);
 
 #ifdef ARGS_GROW_DOWNWARD
   current_function_arg_offset_rtx
@@ -3055,13 +3099,8 @@ assign_parms (tree fndecl)
        {
          rtx real_decl_rtl;
 
-#ifdef FUNCTION_OUTGOING_VALUE
-         real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
-                                                  fndecl);
-#else
-         real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
-                                         fndecl);
-#endif
+         real_decl_rtl = targetm.calls.function_value (TREE_TYPE (decl_result),
+                                                       fndecl, true);
          REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
          /* The delay slot scheduler assumes that current_function_return_rtx
             holds the hard register containing the return value, not a
@@ -3383,10 +3422,9 @@ pad_to_arg_alignment (struct args_size *offset_ptr, int boundary,
   HOST_WIDE_INT sp_offset = STACK_POINTER_OFFSET;
 
 #ifdef SPARC_STACK_BOUNDARY_HACK
-  /* The sparc port has a bug.  It sometimes claims a STACK_BOUNDARY
-     higher than the real alignment of %sp.  However, when it does this,
-     the alignment of %sp+STACK_POINTER_OFFSET will be STACK_BOUNDARY.
-     This is a temporary hack while the sparc port is fixed.  */
+  /* ??? The SPARC port may claim a STACK_BOUNDARY higher than
+     the real alignment of %sp.  However, when it does this, the
+     alignment of %sp+STACK_POINTER_OFFSET is STACK_BOUNDARY.  */
   if (SPARC_STACK_BOUNDARY_HACK)
     sp_offset = 0;
 #endif
@@ -3717,7 +3755,7 @@ get_block_vector (tree block, int *n_blocks_p)
   tree *block_vector;
 
   *n_blocks_p = all_blocks (block, NULL);
-  block_vector = xmalloc (*n_blocks_p * sizeof (tree));
+  block_vector = XNEWVEC (tree, *n_blocks_p);
   all_blocks (block, block_vector);
 
   return block_vector;
@@ -3897,7 +3935,7 @@ init_function_start (tree subr)
 
 /* Make sure all values used by the optimization passes have sane
    defaults.  */
-void
+unsigned int
 init_function_for_compilation (void)
 {
   reg_renumber = 0;
@@ -3907,6 +3945,7 @@ init_function_for_compilation (void)
   gcc_assert (VEC_length (int, prologue) == 0);
   gcc_assert (VEC_length (int, epilogue) == 0);
   gcc_assert (VEC_length (int, sibcall_epilogue) == 0);
+  return 0;
 }
 
 struct tree_opt_pass pass_init_function =
@@ -3930,42 +3969,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)               \
@@ -4019,7 +4022,7 @@ stack_protect_prologue (void)
 # define gen_stack_protect_test(x, y, z)       (gcc_unreachable (), NULL_RTX)
 #endif
 
-static void
+void
 stack_protect_epilogue (void)
 {
   tree guard_decl = targetm.stack_protect_guard ();
@@ -4149,7 +4152,7 @@ expand_function_start (tree subr)
          /* In order to figure out what mode to use for the pseudo, we
             figure out what the mode of the eventual return register will
             actually be, and use that.  */
-         rtx hard_reg = hard_function_value (return_type, subr, 1);
+         rtx hard_reg = hard_function_value (return_type, subr, 0, 1);
 
          /* Structures that are returned in registers are not
             aggregate_value_p, so we may see a PARALLEL or a REG.  */
@@ -4304,7 +4307,7 @@ do_use_return_reg (rtx reg, void *arg ATTRIBUTE_UNUSED)
   emit_insn (gen_rtx_USE (VOIDmode, reg));
 }
 
-void
+static void
 use_return_register (void)
 {
   diddle_return_value (do_use_return_reg, NULL);
@@ -4320,7 +4323,7 @@ do_warn_unused_parameter (tree fn)
        decl; decl = TREE_CHAIN (decl))
     if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
        && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl))
-      warning (0, "unused parameter %q+D", decl);
+      warning (OPT_Wunused_parameter, "unused parameter %q+D", decl);
 }
 
 static GTY(()) rtx initial_trampoline;
@@ -4371,14 +4374,6 @@ expand_function_end (void)
   clear_pending_stack_adjust ();
   do_pending_stack_adjust ();
 
-  /* @@@ This is a kludge.  We want to ensure that instructions that
-     may trap are not moved into the epilogue by scheduling, because
-     we don't always emit unwind information for the epilogue.
-     However, not all machine descriptions define a blockage insn, so
-     emit an ASM_INPUT to act as one.  */
-  if (flag_non_call_exceptions)
-    emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
-
   /* Mark the end of the function body.
      If control reaches this insn, the function can drop through
      without returning a value.  */
@@ -4410,10 +4405,27 @@ expand_function_end (void)
   /* Output the label for the actual return from the function.  */
   emit_label (return_label);
 
-  /* Let except.c know where it should emit the call to unregister
-     the function context for sjlj exceptions.  */
-  if (flag_exceptions && USING_SJLJ_EXCEPTIONS)
-    sjlj_emit_function_exit_after (get_last_insn ());
+  if (USING_SJLJ_EXCEPTIONS)
+    {
+      /* Let except.c know where it should emit the call to unregister
+        the function context for sjlj exceptions.  */
+      if (flag_exceptions)
+       sjlj_emit_function_exit_after (get_last_insn ());
+    }
+  else
+    {
+      /* @@@ This is a kludge.  We want to ensure that instructions that
+        may trap are not moved into the epilogue by scheduling, because
+        we don't always emit unwind information for the epilogue.
+        However, not all machine descriptions define a blockage insn, so
+        emit an ASM_INPUT to act as one.  */
+      if (flag_non_call_exceptions)
+       emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
+    }
+
+  /* If this is an implementation of throw, do what's necessary to
+     communicate between __builtin_eh_return and the epilogue.  */
+  expand_eh_return ();
 
   /* If scalar return value was computed in a pseudo-reg, or was a named
      return value that got dumped to the stack, copy that to the hard
@@ -4476,6 +4488,24 @@ expand_function_end (void)
                                 TREE_TYPE (decl_result),
                                 int_size_in_bytes (TREE_TYPE (decl_result)));
            }
+         /* In the case of complex integer modes smaller than a word, we'll
+            need to generate some non-trivial bitfield insertions.  Do that
+            on a pseudo and not the hard register.  */
+         else if (GET_CODE (decl_rtl) == CONCAT
+                  && GET_MODE_CLASS (GET_MODE (decl_rtl)) == MODE_COMPLEX_INT
+                  && GET_MODE_BITSIZE (GET_MODE (decl_rtl)) <= BITS_PER_WORD)
+           {
+             int old_generating_concat_p;
+             rtx tmp;
+
+             old_generating_concat_p = generating_concat_p;
+             generating_concat_p = 0;
+             tmp = gen_reg_rtx (GET_MODE (decl_rtl));
+             generating_concat_p = old_generating_concat_p;
+
+             emit_move_insn (tmp, decl_rtl);
+             emit_move_insn (real_decl_rtl, tmp);
+           }
          else
            emit_move_insn (real_decl_rtl, decl_rtl);
        }
@@ -4499,13 +4529,8 @@ expand_function_end (void)
       else
        value_address = XEXP (value_address, 0);
 
-#ifdef FUNCTION_OUTGOING_VALUE
-      outgoing = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
-                                         current_function_decl);
-#else
-      outgoing = FUNCTION_VALUE (build_pointer_type (type),
-                                current_function_decl);
-#endif 
+      outgoing = targetm.calls.function_value (build_pointer_type (type),
+                                              current_function_decl, true);
 
       /* Mark this as a function return value so integrate will delete the
         assignment and USE below when inlining this function.  */
@@ -4522,10 +4547,6 @@ expand_function_end (void)
       current_function_return_rtx = outgoing;
     }
 
-  /* If this is an implementation of throw, do what's necessary to
-     communicate between __builtin_eh_return and the epilogue.  */
-  expand_eh_return ();
-
   /* Emit the actual code to clobber return register.  */
   {
     rtx seq;
@@ -4833,6 +4854,7 @@ keep_stack_depressed (rtx insns)
                                                           info.sp_offset));
 
          retaddr = gen_rtx_MEM (Pmode, retaddr);
+         MEM_NOTRAP_P (retaddr) = 1;
 
          /* If there is a pending load to the equivalent register for SP
             and we reference that register, we must load our address into
@@ -5274,7 +5296,8 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
        fixup_fallthru_exit_predecessor.  */
       cfg_layout_initialize (0);
       FOR_EACH_BB (cur_bb)
-       if (cur_bb->index >= 0 && cur_bb->next_bb->index >= 0)
+       if (cur_bb->index >= NUM_FIXED_BLOCKS
+           && cur_bb->next_bb->index >= NUM_FIXED_BLOCKS)
          cur_bb->aux = cur_bb->next_bb;
       cfg_layout_finalize ();
     }
@@ -5502,6 +5525,9 @@ record_block_change (tree block)
   if (!block)
     return;
 
+  if(!cfun->ib_boundaries_block)
+    return;
+
   last_block = VARRAY_TOP_TREE (cfun->ib_boundaries_block);
   VARRAY_POP (cfun->ib_boundaries_block);
   n = get_max_uid ();
@@ -5544,13 +5570,14 @@ current_function_name (void)
 }
 \f
 
-static void
+static unsigned int
 rest_of_handle_check_leaf_regs (void)
 {
 #ifdef LEAF_REGISTERS
   current_function_uses_only_leaf_regs
     = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
 #endif
+  return 0;
 }
 
 struct tree_opt_pass pass_leaf_regs =