]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/integrate.c
integrate.c (expand_inline_function): Don't put a virtual register into the reg map.
[gcc.git] / gcc / integrate.c
index 8e0f9101c35b31ed4028ef96b05e33173949a07b..f6e43027580d3f23c94dd4db1ddb33d271f22cff 100644 (file)
@@ -1,6 +1,6 @@
 /* Procedure integration for GNU CC.
    Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -20,7 +20,6 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 #include "config.h"
 #include "system.h"
 
@@ -63,7 +62,7 @@ extern struct obstack *function_maybepermanent_obstack;
    : (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
 #endif
 
-/* Decide whether a function with a target specific attribute 
+/* Decide whether a function with a target specific attribute
    attached can be inlined.  By default we disallow this.  */
 #ifndef FUNCTION_ATTRIBUTE_INLINABLE_P
 #define FUNCTION_ATTRIBUTE_INLINABLE_P(FNDECL) 0
@@ -118,7 +117,7 @@ get_label_from_map (map, i)
   rtx x = map->label_map[i];
 
   if (x == NULL_RTX)
-    x = map->label_map[i] = gen_label_rtx();
+    x = map->label_map[i] = gen_label_rtx ();
 
   return x;
 }
@@ -201,7 +200,8 @@ function_cannot_inline_p (fndecl)
     {
       if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
        return N_("function with varying-size parameter cannot be inline");
-      else if (TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
+      else if (TREE_CODE (TREE_TYPE (parms)) == UNION_TYPE
+              && TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
        return N_("function with transparent unit parameter cannot be inline");
     }
 
@@ -210,7 +210,7 @@ function_cannot_inline_p (fndecl)
       for (ninsns = 0, insn = get_first_nonparm_insn ();
           insn && ninsns < max_insns;
           insn = NEXT_INSN (insn))
-       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+       if (INSN_P (insn))
          ninsns++;
 
       if (ninsns >= max_insns)
@@ -263,7 +263,7 @@ static tree *parmdecl_map;
 /* In save_for_inline, nonzero if past the parm-initialization insns.  */
 static int in_nonparm_insns;
 \f
-/* Subroutine for `save_for_inline_nocopy'.  Performs initialization
+/* Subroutine for `save_for_inline'.  Performs initialization
    needed to save FNDECL's insns and info for future inline expansion.  */
 
 static rtvec
@@ -275,7 +275,7 @@ initialize_for_inline (fndecl)
   tree parms;
 
   /* Clear out PARMDECL_MAP.  It was allocated in the caller's frame.  */
-  bzero ((char *) parmdecl_map, max_parm_reg * sizeof (tree));
+  memset ((char *) parmdecl_map, 0, max_parm_reg * sizeof (tree));
   arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
 
   for (parms = DECL_ARGUMENTS (fndecl), i = 0;
@@ -315,7 +315,7 @@ initialize_for_inline (fndecl)
 }
 
 /* Copy NODE (which must be a DECL, but not a PARM_DECL).  The DECL
-   originally was in the FROM_FN, but now it will be in the 
+   originally was in the FROM_FN, but now it will be in the
    TO_FN.  */
 
 tree
@@ -362,7 +362,7 @@ copy_decl_for_inlining (decl, from_fn, to_fn)
   /* Set the context for the new declaration.  */
   if (!DECL_CONTEXT (decl))
     /* Globals stay global.  */
-       ;
+    ;
   else if (DECL_CONTEXT (decl) != from_fn)
     /* Things that weren't in the scope of the function we're inlining
        from aren't in the scope we're inlining too, either.  */
@@ -399,7 +399,7 @@ copy_decl_for_inlining (decl, from_fn, to_fn)
    functions at the end of compilation.  */
 
 void
-save_for_inline_nocopy (fndecl)
+save_for_inline (fndecl)
      tree fndecl;
 {
   rtx insn;
@@ -444,16 +444,11 @@ save_for_inline_nocopy (fndecl)
   in_nonparm_insns = 0;
   save_parm_insns (insn, first_nonparm_insn);
 
-  /* We have now allocated all that needs to be allocated permanently
-     on the rtx obstack.  Set our high-water mark, so that we
-     can free the rest of this when the time comes.  */
-
-  preserve_data ();
-
   cfun->inl_max_label_num = max_label_num ();
   cfun->inl_last_parm_insn = cfun->x_last_parm_insn;
   cfun->original_arg_vector = argvec;
   cfun->original_decl_initial = DECL_INITIAL (fndecl);
+  cfun->no_debugging_symbols = (write_symbols == NO_DEBUG);
   DECL_SAVED_INSNS (fndecl) = cfun;
 
   /* Clean up.  */
@@ -468,8 +463,8 @@ save_for_inline_nocopy (fndecl)
 
 static void
 save_parm_insns (insn, first_nonparm_insn)
-    rtx insn;
-    rtx first_nonparm_insn;
+     rtx insn;
+     rtx first_nonparm_insn;
 {
   if (insn == NULL_RTX)
     return;
@@ -479,14 +474,14 @@ save_parm_insns (insn, first_nonparm_insn)
       if (insn == first_nonparm_insn)
        in_nonparm_insns = 1;
 
-      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+      if (INSN_P (insn))
        {
          /* Record what interesting things happen to our parameters.  */
          note_stores (PATTERN (insn), note_modified_parmregs, NULL);
 
          /* If this is a CALL_PLACEHOLDER insn then we need to look into the
             three attached sequences: normal call, sibling call and tail
-            recursion. */
+            recursion.  */
          if (GET_CODE (insn) == CALL_INSN
              && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
            {
@@ -559,9 +554,9 @@ process_reg_param (map, loc, copy)
 /* Used by duplicate_eh_handlers to map labels for the exception table */
 static struct inline_remap *eif_eh_map;
 
-static rtx 
+static rtx
 expand_inline_function_eh_labelmap (label)
-   rtx label;
+     rtx label;
 {
   int index = CODE_LABEL_NUMBER (label);
   return get_label_from_map (eif_eh_map, index);
@@ -578,7 +573,7 @@ compare_blocks (v1, v2)
   tree b1 = *((const tree *) v1);
   tree b2 = *((const tree *) v2);
 
-  return ((char *) BLOCK_ABSTRACT_ORIGIN (b1) 
+  return ((char *) BLOCK_ABSTRACT_ORIGIN (b1)
          - (char *) BLOCK_ABSTRACT_ORIGIN (b2));
 }
 
@@ -652,6 +647,10 @@ expand_inline_function (fndecl, parms, target, ignore, type,
   if (max_regno < FIRST_PSEUDO_REGISTER)
     abort ();
 
+  /* Pull out the decl for the function definition; fndecl may be a
+     local declaration, which would break DECL_ABSTRACT_ORIGIN.  */
+  fndecl = inl_f->decl;
+
   nargs = list_length (DECL_ARGUMENTS (fndecl));
 
   if (cfun->preferred_stack_boundary < inl_f->preferred_stack_boundary)
@@ -717,14 +716,9 @@ expand_inline_function (fndecl, parms, target, ignore, type,
       if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
          && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
        {
-         rtx stack_slot
-           = assign_stack_temp (TYPE_MODE (TREE_TYPE (arg)),
-                                int_size_in_bytes (TREE_TYPE (arg)), 1);
-         MEM_SET_IN_STRUCT_P (stack_slot,
-                              AGGREGATE_TYPE_P (TREE_TYPE (arg)));
+         rtx stack_slot = assign_temp (TREE_TYPE (arg), 1, 1, 1);
 
          store_expr (arg, stack_slot, 0);
-
          arg_vals[i] = XEXP (stack_slot, 0);
          invisiref = 1;
        }
@@ -772,7 +766,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
        mark_reg_pointer (arg_vals[i],
                          TYPE_ALIGN (TREE_TYPE (TREE_TYPE (formal))));
     }
-       
+
   /* Allocate the structures we use to remap things.  */
 
   map = (struct inline_remap *) xmalloc (sizeof (struct inline_remap));
@@ -823,8 +817,8 @@ expand_inline_function (fndecl, parms, target, ignore, type,
   if (map->insns_at_start == 0)
     map->insns_at_start = emit_note (NULL_PTR, NOTE_INSN_DELETED);
 
-  map->regno_pointer_flag = inl_f->emit->regno_pointer_flag;
   map->regno_pointer_align = inl_f->emit->regno_pointer_align;
+  map->x_regno_reg_rtx = inl_f->emit->x_regno_reg_rtx;
 
   /* Update the outgoing argument size to allow for those in the inlined
      function.  */
@@ -980,7 +974,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
          if (! structure_value_addr
              || ! aggregate_value_p (DECL_RESULT (fndecl)))
            abort ();
-  
+
          /* Pass the function the address in which to return a structure
             value.  Note that a constructor can cause someone to call us
             with STRUCTURE_VALUE_ADDR, but the initialization takes place
@@ -995,6 +989,15 @@ expand_inline_function (fndecl, parms, target, ignore, type,
            {
              temp = force_operand (structure_value_addr, NULL_RTX);
              temp = force_reg (Pmode, temp);
+             /* A virtual register might be invalid in an insn, because
+                it can cause trouble in reload.  Since we don't have access
+                to the expanders at map translation time, make sure we have
+                a proper register now.
+                If a virtual register is actually valid, cse or combine
+                can put it into the mapped insns.  */
+             if (REGNO (temp) >= FIRST_VIRTUAL_REGISTER
+                 && REGNO (temp) <= LAST_VIRTUAL_REGISTER)
+             temp = copy_to_mode_reg (Pmode, temp);
              map->reg_map[REGNO (XEXP (loc, 0))] = temp;
 
              if (CONSTANT_P (structure_value_addr)
@@ -1046,7 +1049,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
        {
          /* Don't make BLKmode registers.  If this looks like
             a BLKmode object being returned in a register, get
-            the mode from that, otherwise abort. */
+            the mode from that, otherwise abort.  */
          if (departing_mode == BLKmode)
            {
              if (REG == GET_CODE (DECL_RTL (DECL_RESULT (fndecl))))
@@ -1055,10 +1058,10 @@ expand_inline_function (fndecl, parms, target, ignore, type,
                  arriving_mode = departing_mode;
                }
              else
-               abort();
+               abort ();
            }
-             
-       target = gen_reg_rtx (departing_mode);
+
+         target = gen_reg_rtx (departing_mode);
        }
 
       /* If function's value was promoted before return,
@@ -1095,7 +1098,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
 
   /* Initialize label_map.  get_label_from_map will actually make
      the labels.  */
-  bzero ((char *) &map->label_map [min_labelno],
+  memset ((char *) &map->label_map[min_labelno], 0,
         (max_labelno - min_labelno) * sizeof (rtx));
 
   /* Make copies of the decls of the symbols in the inline function, so that
@@ -1114,7 +1117,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
 
   /* Sort the block-map so that it will be easy to find remapped
      blocks later.  */
-  qsort (&VARRAY_TREE (map->block_map, 0), 
+  qsort (&VARRAY_TREE (map->block_map, 0),
         map->block_map->elements_used,
         sizeof (tree),
         compare_blocks);
@@ -1151,7 +1154,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
     insert_block (block);
   else
     {
-      BLOCK_CHAIN (block) 
+      BLOCK_CHAIN (block)
        = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
       BLOCK_CHAIN (DECL_INITIAL (current_function_decl)) = block;
     }
@@ -1175,18 +1178,18 @@ expand_inline_function (fndecl, parms, target, ignore, type,
   emit_line_note (input_filename, lineno);
 
   /* If the function returns a BLKmode object in a register, copy it
-     out of the temp register into a BLKmode memory object. */
-  if (target 
+     out of the temp register into a BLKmode memory object.  */
+  if (target
       && TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
       && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
     target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
-  
+
   if (structure_value_addr)
     {
       target = gen_rtx_MEM (TYPE_MODE (type),
                            memory_address (TYPE_MODE (type),
                                            structure_value_addr));
-      MEM_SET_IN_STRUCT_P (target, 1);
+      set_mem_attributes (target, type, 1);
     }
 
   /* Make sure we free the things we explicitly allocated with xmalloc.  */
@@ -1208,18 +1211,17 @@ expand_inline_function (fndecl, parms, target, ignore, type,
 /* Make copies of each insn in the given list using the mapping
    computed in expand_inline_function. This function may call itself for
    insns containing sequences.
-   
-   Copying is done in two passes, first the insns and then their REG_NOTES,
-   just like save_for_inline.
+
+   Copying is done in two passes, first the insns and then their REG_NOTES.
 
    If static_chain_value is non-zero, it represents the context-pointer
-   register for the function. */
+   register for the function.  */
 
 static void
 copy_insn_list (insns, map, static_chain_value)
-    rtx insns;
-    struct inline_remap *map;
-    rtx static_chain_value;
+     rtx insns;
+     struct inline_remap *map;
+     rtx static_chain_value;
 {
   register int i;
   rtx insn;
@@ -1230,7 +1232,7 @@ copy_insn_list (insns, map, static_chain_value)
 #endif
 
   /* Copy the insns one by one.  Do this in two passes, first the insns and
-     then their REG_NOTES, just like save_for_inline.  */
+     then their REG_NOTES.  */
 
   /* This loop is very similar to the loop in copy_loop_body in unroll.c.  */
 
@@ -1255,7 +1257,7 @@ copy_insn_list (insns, map, static_chain_value)
            break;
 
          /* If the inline fn needs eh context, make sure that
-            the current fn has one. */
+            the current fn has one.  */
          if (GET_CODE (pattern) == USE
              && find_reg_note (insn, REG_EH_CONTEXT, 0) != 0)
            get_eh_context ();
@@ -1290,6 +1292,13 @@ copy_insn_list (insns, map, static_chain_value)
                break;
            }
 
+         /* Similarly if an ignored return value is clobbered.  */
+         else if (map->inline_target == 0
+                  && GET_CODE (pattern) == CLOBBER
+                  && GET_CODE (XEXP (pattern, 0)) == REG
+                  && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
+           break;
+
          /* If this is setting the static chain rtx, omit it.  */
          else if (static_chain_value != 0
                   && set != 0
@@ -1400,7 +1409,7 @@ copy_insn_list (insns, map, static_chain_value)
 
          /* If this used to be a conditional jump insn but whose branch
             direction is now know, we must do something special.  */
-         if (condjump_p (insn) && ! simplejump_p (insn) && map->last_pc_value)
+         if (any_condjump_p (insn) && onlyjump_p (insn) && map->last_pc_value)
            {
 #ifdef HAVE_cc0
              /* If the previous insn set cc0 for us, delete it.  */
@@ -1425,7 +1434,7 @@ copy_insn_list (insns, map, static_chain_value)
        case CALL_INSN:
          /* If this is a CALL_PLACEHOLDER insn then we need to copy the
             three attached sequences: normal call, sibling call and tail
-            recursion. */
+            recursion.  */
          if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
            {
              rtx sequence[3];
@@ -1434,7 +1443,7 @@ copy_insn_list (insns, map, static_chain_value)
              for (i = 0; i < 3; i++)
                {
                  rtx seq;
-                 
+
                  sequence[i] = NULL_RTX;
                  seq = XEXP (PATTERN (insn), i);
                  if (seq)
@@ -1446,16 +1455,16 @@ copy_insn_list (insns, map, static_chain_value)
                    }
                }
 
-             /* Find the new tail recursion label.  
+             /* Find the new tail recursion label.
                 It will already be substituted into sequence[2].  */
              tail_label = copy_rtx_and_substitute (XEXP (PATTERN (insn), 3),
                                                    map, 0);
 
-             copy = emit_call_insn (gen_rtx_CALL_PLACEHOLDER (VOIDmode, 
-                                                       sequence[0],
-                                                       sequence[1],
-                                                       sequence[2],
-                                                       tail_label));
+             copy = emit_call_insn (gen_rtx_CALL_PLACEHOLDER (VOIDmode,
+                                                              sequence[0],
+                                                              sequence[1],
+                                                              sequence[2],
+                                                              tail_label));
              break;
            }
 
@@ -1463,6 +1472,7 @@ copy_insn_list (insns, map, static_chain_value)
          copy = emit_call_insn (pattern);
 
          SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
+         CONST_CALL_P (copy) = CONST_CALL_P (insn);
 
          /* Because the USAGE information potentially contains objects other
             than hard registers, we need to copy it.  */
@@ -1478,7 +1488,7 @@ copy_insn_list (insns, map, static_chain_value)
 #endif
          try_constants (copy, map);
 
-             /* Be lazy and assume CALL_INSNs clobber all hard registers.  */
+         /* Be lazy and assume CALL_INSNs clobber all hard registers.  */
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
            VARRAY_CONST_EQUIV (map->const_equiv_varray, i).rtx = 0;
          break;
@@ -1495,13 +1505,11 @@ copy_insn_list (insns, map, static_chain_value)
          break;
 
        case NOTE:
-         /* NOTE_INSN_FUNCTION_END and NOTE_INSN_FUNCTION_BEG are 
-            discarded because it is important to have only one of 
+         /* NOTE_INSN_FUNCTION_END and NOTE_INSN_FUNCTION_BEG are
+            discarded because it is important to have only one of
             each in the current function.
 
-            NOTE_INSN_DELETED notes aren't useful (save_for_inline
-            deleted these in the copy used for continuing compilation,
-            not the copy used for inlining).
+            NOTE_INSN_DELETED notes aren't useful.
 
             NOTE_INSN_BASIC_BLOCK is discarded because the saved bb
             pointer (which will soon be dangling) confuses flow's
@@ -1522,16 +1530,16 @@ copy_insn_list (insns, map, static_chain_value)
                  rtx label
                    = get_label_from_map (map, NOTE_EH_HANDLER (copy));
 
-                  /* we have to duplicate the handlers for the original */
-                  if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
-                    {
-                      /* We need to duplicate the handlers for the EH region
-                         and we need to indicate where the label map is */
-                      eif_eh_map = map;
-                      duplicate_eh_handlers (NOTE_EH_HANDLER (copy), 
-                                             CODE_LABEL_NUMBER (label),
-                                             expand_inline_function_eh_labelmap);
-                    }
+                 /* We have to duplicate the handlers for the original.  */
+                 if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
+                   {
+                     /* We need to duplicate the handlers for the EH region
+                        and we need to indicate where the label map is */
+                     eif_eh_map = map;
+                     duplicate_eh_handlers (NOTE_EH_HANDLER (copy),
+                                            CODE_LABEL_NUMBER (label),
+                                            expand_inline_function_eh_labelmap);
+                   }
 
                  /* We have to forward these both to match the new exception
                     region.  */
@@ -1545,12 +1553,12 @@ copy_insn_list (insns, map, static_chain_value)
                  tree *mapped_block_p;
 
                  mapped_block_p
-                   = (tree *) bsearch (NOTE_BLOCK (insn), 
+                   = (tree *) bsearch (NOTE_BLOCK (insn),
                                        &VARRAY_TREE (map->block_map, 0),
                                        map->block_map->elements_used,
                                        sizeof (tree),
                                        find_block);
-                 
+
                  if (!mapped_block_p)
                    abort ();
                  else
@@ -1576,17 +1584,25 @@ copy_insn_list (insns, map, static_chain_value)
      are valid across the entire function.  */
   map->const_age++;
   for (insn = insns; insn; insn = NEXT_INSN (insn))
-    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+    if (INSN_P (insn)
        && map->insn_map[INSN_UID (insn)]
        && REG_NOTES (insn))
       {
-       rtx tem = copy_rtx_and_substitute (REG_NOTES (insn), map, 0);
+       rtx next, note = copy_rtx_and_substitute (REG_NOTES (insn), map, 0);
 
        /* We must also do subst_constants, in case one of our parameters
           has const type and constant value.  */
-       subst_constants (&tem, NULL_RTX, map, 0);
+       subst_constants (&note, NULL_RTX, map, 0);
        apply_change_group ();
-       REG_NOTES (map->insn_map[INSN_UID (insn)]) = tem;
+       REG_NOTES (map->insn_map[INSN_UID (insn)]) = note;
+
+       /* Finally, delete any REG_LABEL notes from the chain.  */
+       for (; note; note = next)
+         {
+           next = XEXP (note, 1);
+           if (REG_NOTE_KIND (note) == REG_LABEL)
+             remove_note (map->insn_map[INSN_UID (insn)], note);
+         }
       }
 
   if (local_return_label)
@@ -1649,10 +1665,7 @@ integrate_decl_tree (let, map)
     {
       tree d;
 
-      push_obstacks_nochange ();
-      saveable_allocation ();
       d = copy_decl_for_inlining (t, map->fndecl, current_function_decl);
-      pop_obstacks ();
 
       if (DECL_RTL (t) != 0)
        {
@@ -1682,7 +1695,7 @@ integrate_decl_tree (let, map)
 
   TREE_USED (new_block) = TREE_USED (let);
   BLOCK_ABSTRACT_ORIGIN (new_block) = let;
-  
+
   return new_block;
 }
 \f
@@ -1734,7 +1747,15 @@ copy_rtx_and_substitute (orig, map, for_lhs)
        {
          /* Some hard registers are also mapped,
             but others are not translated.  */
-         if (map->reg_map[regno] != 0)
+         if (map->reg_map[regno] != 0
+             /* We shouldn't usually have reg_map set for return
+                register, but it may happen if we have leaf-register
+                remapping and the return register is used in one of
+                the calling sequences of a call_placeholer.  In this
+                case, we'll end up with a reg_map set for this
+                register, but we don't want to use for registers
+                marked as return values.  */
+             && ! REG_FUNCTION_VALUE_P (orig))
            return map->reg_map[regno];
 
          /* If this is the virtual frame pointer, make space in current
@@ -1745,7 +1766,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
             equivalence for it to be the address.  This will substitute the
             address into insns where it can be substituted and use the new
             pseudo where it can't.  */
-         if (regno == VIRTUAL_STACK_VARS_REGNUM)
+         else if (regno == VIRTUAL_STACK_VARS_REGNUM)
            {
              rtx loc, seq;
              int size = get_func_frame_size (DECL_SAVED_INSNS (map->fndecl));
@@ -1797,7 +1818,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
              start_sequence ();
              loc = assign_stack_temp (BLKmode, size, 1);
              loc = XEXP (loc, 0);
-             /* When arguments grow downward, the virtual incoming 
+             /* When arguments grow downward, the virtual incoming
                 args pointer points to the top of the argument block,
                 so the remapped location better do the same.  */
 #ifdef ARGS_GROW_DOWNWARD
@@ -1832,7 +1853,26 @@ copy_rtx_and_substitute (orig, map, for_lhs)
              else
                return map->inline_target;
            }
-         return orig;
+#if defined (LEAF_REGISTERS) && defined (LEAF_REG_REMAP)
+         /* If leaf_renumber_regs_insn() might remap this register to
+            some other number, make sure we don't share it with the
+            inlined function, otherwise delayed optimization of the
+            inlined function may change it in place, breaking our
+            reference to it.  We may still shared it within the
+            function, so create an entry for this register in the
+            reg_map.  */
+         if (map->integrating && regno < FIRST_PSEUDO_REGISTER
+             && LEAF_REGISTERS[regno] && LEAF_REG_REMAP (regno) != regno)
+           {
+             temp = gen_rtx_REG (mode, regno);
+             map->reg_map[regno] = temp;
+             return temp;
+           }
+#endif
+         else
+           return orig;
+
+         abort ();
        }
       if (map->reg_map[regno] == NULL)
        {
@@ -1842,7 +1882,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
          RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
          /* A reg with REG_FUNCTION_VALUE_P true will never reach here.  */
 
-         if (map->regno_pointer_flag[regno])
+         if (REG_POINTER (map->x_regno_reg_rtx[regno]))
            mark_reg_pointer (map->reg_map[regno],
                              map->regno_pointer_align[regno]);
        }
@@ -1874,7 +1914,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
       copy = gen_rtx_ADDRESSOF (mode,
                                copy_rtx_and_substitute (XEXP (orig, 0),
                                                         map, for_lhs),
-                               0, ADDRESSOF_DECL(orig));
+                               0, ADDRESSOF_DECL (orig));
       regno = ADDRESSOF_REGNO (orig);
       if (map->reg_map[regno])
        regno = REGNO (map->reg_map[regno]);
@@ -1887,7 +1927,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
          RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
          /* A reg with REG_FUNCTION_VALUE_P true will never reach here.  */
 
-         if (map->regno_pointer_flag[regno])
+         if (REG_POINTER (map->x_regno_reg_rtx[regno]))
            mark_reg_pointer (map->reg_map[regno],
                              map->regno_pointer_align[regno]);
          regno = REGNO (map->reg_map[regno]);
@@ -1994,13 +2034,12 @@ copy_rtx_and_substitute (orig, map, for_lhs)
                          copy_rtx_and_substitute (constant, map, for_lhs)),
                         0);
        }
-      else
-        if (SYMBOL_REF_NEED_ADJUST (orig)) 
-          {
-            eif_eh_map = map;
-            return rethrow_symbol_map (orig, 
-                                       expand_inline_function_eh_labelmap);
-          }
+      else if (SYMBOL_REF_NEED_ADJUST (orig))
+       {
+         eif_eh_map = map;
+         return rethrow_symbol_map (orig,
+                                    expand_inline_function_eh_labelmap);
+       }
 
       return orig;
 
@@ -2027,20 +2066,24 @@ copy_rtx_and_substitute (orig, map, for_lhs)
       break;
 
     case ASM_OPERANDS:
-      /* If a single asm insn contains multiple output operands
-        then it contains multiple ASM_OPERANDS rtx's that share operand 3.
-        We must make sure that the copied insn continues to share it.  */
-      if (map->orig_asm_operands_vector == XVEC (orig, 3))
+      /* If a single asm insn contains multiple output operands then
+        it contains multiple ASM_OPERANDS rtx's that share the input
+        and constraint vecs.  We must make sure that the copied insn
+        continues to share it.  */
+      if (map->orig_asm_operands_vector == ASM_OPERANDS_INPUT_VEC (orig))
        {
          copy = rtx_alloc (ASM_OPERANDS);
          copy->volatil = orig->volatil;
-         XSTR (copy, 0) = XSTR (orig, 0);
-         XSTR (copy, 1) = XSTR (orig, 1);
-         XINT (copy, 2) = XINT (orig, 2);
-         XVEC (copy, 3) = map->copy_asm_operands_vector;
-         XVEC (copy, 4) = map->copy_asm_constraints_vector;
-         XSTR (copy, 5) = XSTR (orig, 5);
-         XINT (copy, 6) = XINT (orig, 6);
+         PUT_MODE (copy, GET_MODE (orig));
+         ASM_OPERANDS_TEMPLATE (copy) = ASM_OPERANDS_TEMPLATE (orig);
+         ASM_OPERANDS_OUTPUT_CONSTRAINT (copy)
+           = ASM_OPERANDS_OUTPUT_CONSTRAINT (orig);
+         ASM_OPERANDS_OUTPUT_IDX (copy) = ASM_OPERANDS_OUTPUT_IDX (orig);
+         ASM_OPERANDS_INPUT_VEC (copy) = map->copy_asm_operands_vector;
+         ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy)
+           = map->copy_asm_constraints_vector;
+         ASM_OPERANDS_SOURCE_FILE (copy) = ASM_OPERANDS_SOURCE_FILE (orig);
+         ASM_OPERANDS_SOURCE_LINE (copy) = ASM_OPERANDS_SOURCE_LINE (orig);
          return copy;
        }
       break;
@@ -2076,7 +2119,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
       if (SET_DEST (orig) == virtual_stack_vars_rtx
          || SET_DEST (orig) == virtual_incoming_args_rtx)
        {
-         /* In case a translation hasn't occurred already, make one now. */
+         /* In case a translation hasn't occurred already, make one now.  */
          rtx equiv_reg;
          rtx equiv_loc;
          HOST_WIDE_INT loc_offset;
@@ -2087,7 +2130,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
                                          REGNO (equiv_reg)).rtx;
          loc_offset
            = GET_CODE (equiv_loc) == REG ? 0 : INTVAL (XEXP (equiv_loc, 1));
-             
+
          return gen_rtx_SET (VOIDmode, SET_DEST (orig),
                              force_operand
                              (plus_constant
@@ -2131,7 +2174,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
       XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map, 0);
       MEM_COPY_ATTRIBUTES (copy, orig);
       return copy;
-      
+
     default:
       break;
     }
@@ -2199,9 +2242,10 @@ copy_rtx_and_substitute (orig, map, for_lhs)
 
   if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
     {
-      map->orig_asm_operands_vector = XVEC (orig, 3);
-      map->copy_asm_operands_vector = XVEC (copy, 3);
-      map->copy_asm_constraints_vector = XVEC (copy, 4);
+      map->orig_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (orig);
+      map->copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy);
+      map->copy_asm_constraints_vector
+       = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy);
     }
 
   return copy;
@@ -2271,7 +2315,7 @@ try_constants (insn, map)
    into insns; cse will do the latter task better.
 
    This function is also used to adjust address of items previously addressed
-   via the virtual stack variable or virtual incoming arguments registers. 
+   via the virtual stack variable or virtual incoming arguments registers.
 
    If MEMONLY is nonzero, only make changes inside a MEM.  */
 
@@ -2349,7 +2393,7 @@ subst_constants (loc, insn, map, memonly)
          /* We can't call subst_constants on &SUBREG_REG (x) because any
             constant or SUBREG wouldn't be valid inside our SUBEG.  Instead,
             see what is inside, try to form the new SUBREG and see if that is
-            valid.  We handle two cases: extracting a full word in an 
+            valid.  We handle two cases: extracting a full word in an
             integral mode and extracting the low part.  */
          subst_constants (&inner, NULL_RTX, map, 0);
 
@@ -2453,7 +2497,7 @@ subst_constants (loc, insn, map, memonly)
     }
 
   format_ptr = GET_RTX_FORMAT (code);
-  
+
   /* If the first operand is an expression, save its mode for later.  */
   if (*format_ptr == 'e')
     op0_mode = GET_MODE (XEXP (x, 0));
@@ -2474,7 +2518,7 @@ subst_constants (loc, insn, map, memonly)
        case 'i':
        case 's':
        case 'w':
-       case 'n':
+       case 'n':
        case 't':
          break;
 
@@ -2534,7 +2578,7 @@ subst_constants (loc, insn, map, memonly)
            }
 #endif
          break;
-      }
+       }
 
       case '2':
       case 'c':
@@ -2584,7 +2628,7 @@ mark_stores (dest, x, data)
     {
       unsigned int uregno = regno;
       unsigned int last_reg = (uregno >= FIRST_PSEUDO_REGISTER ? uregno
-                             : uregno + HARD_REGNO_NREGS (uregno, mode) - 1);
+                              : uregno + HARD_REGNO_NREGS (uregno, mode) - 1);
       unsigned int i;
 
       /* Ignore virtual stack var or virtual arg register since those
@@ -2616,21 +2660,21 @@ set_block_origin_self (stmt)
       BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
 
       {
-        register tree local_decl;
+       register tree local_decl;
 
-        for (local_decl = BLOCK_VARS (stmt);
+       for (local_decl = BLOCK_VARS (stmt);
             local_decl != NULL_TREE;
             local_decl = TREE_CHAIN (local_decl))
-          set_decl_origin_self (local_decl);   /* Potential recursion.  */
+         set_decl_origin_self (local_decl);    /* Potential recursion.  */
       }
 
       {
-        register tree subblock;
+       register tree subblock;
 
-        for (subblock = BLOCK_SUBBLOCKS (stmt);
+       for (subblock = BLOCK_SUBBLOCKS (stmt);
             subblock != NULL_TREE;
             subblock = BLOCK_CHAIN (subblock))
-          set_block_origin_self (subblock);    /* Recurse.  */
+         set_block_origin_self (subblock);     /* Recurse.  */
       }
     }
 }
@@ -2725,21 +2769,22 @@ output_inline_function (fndecl)
      tree fndecl;
 {
   struct function *old_cfun = cfun;
+  enum debug_info_type old_write_symbols = write_symbols;
   struct function *f = DECL_SAVED_INSNS (fndecl);
 
   cfun = f;
   current_function_decl = fndecl;
   clear_emit_caches ();
 
-  /* Things we allocate from here on are part of this function, not
-     permanent.  */
-  temporary_allocation ();
-
   set_new_last_label_num (f->inl_max_label_num);
 
   /* We're not deferring this any longer.  */
   DECL_DEFER_OUTPUT (fndecl) = 0;
 
+  /* If requested, suppress debugging information.  */
+  if (f->no_debugging_symbols)
+    write_symbols = NO_DEBUG;
+
   /* Compile this function all the way down to assembly code.  */
   rest_of_compilation (fndecl);
 
@@ -2749,4 +2794,5 @@ output_inline_function (fndecl)
 
   cfun = old_cfun;
   current_function_decl = old_cfun ? old_cfun->decl : 0;
+  write_symbols = old_write_symbols;
 }
This page took 0.056029 seconds and 5 git commands to generate.