Annotation of gcc/integrate.c, revision 1.1.1.8

1.1       root        1: /* Procedure integration for GNU CC.
1.1.1.8 ! root        2:    Copyright (C) 1988, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
1.1       root        3:    Contributed by Michael Tiemann ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.8 ! root       19: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            20: Boston, MA 02111-1307, USA.  */
1.1       root       21: 
                     22: 
                     23: #include <stdio.h>
                     24: 
                     25: #include "config.h"
                     26: #include "rtl.h"
                     27: #include "tree.h"
                     28: #include "flags.h"
                     29: #include "insn-config.h"
                     30: #include "insn-flags.h"
                     31: #include "expr.h"
                     32: #include "output.h"
                     33: #include "integrate.h"
                     34: #include "real.h"
                     35: #include "function.h"
1.1.1.6   root       36: #include "bytecode.h"
1.1       root       37: 
                     38: #include "obstack.h"
                     39: #define        obstack_chunk_alloc     xmalloc
                     40: #define        obstack_chunk_free      free
                     41: 
                     42: extern struct obstack *function_maybepermanent_obstack;
                     43: 
                     44: extern tree pushdecl ();
                     45: extern tree poplevel ();
                     46: 
                     47: /* Similar, but round to the next highest integer that meets the
                     48:    alignment.  */
                     49: #define CEIL_ROUND(VALUE,ALIGN)        (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
                     50: 
                     51: /* Default max number of insns a function can have and still be inline.
                     52:    This is overridden on RISC machines.  */
                     53: #ifndef INTEGRATE_THRESHOLD
                     54: #define INTEGRATE_THRESHOLD(DECL) \
                     55:   (8 * (8 + list_length (DECL_ARGUMENTS (DECL))))
                     56: #endif
                     57: 
1.1.1.7   root       58: static rtx initialize_for_inline PROTO((tree, int, int, int, int));
                     59: static void finish_inline      PROTO((tree, rtx));
                     60: static void adjust_copied_decl_tree PROTO((tree));
                     61: static tree copy_decl_list     PROTO((tree));
                     62: static tree copy_decl_tree     PROTO((tree));
                     63: static void copy_decl_rtls     PROTO((tree));
                     64: static void save_constants     PROTO((rtx *));
                     65: static void note_modified_parmregs PROTO((rtx, rtx));
                     66: static rtx copy_for_inline     PROTO((rtx));
                     67: static void integrate_parm_decls PROTO((tree, struct inline_remap *, rtvec));
                     68: static void integrate_decl_tree        PROTO((tree, int, struct inline_remap *));
                     69: static void subst_constants    PROTO((rtx *, rtx, struct inline_remap *));
                     70: static void restore_constants  PROTO((rtx *));
                     71: static void set_block_origin_self PROTO((tree));
                     72: static void set_decl_origin_self PROTO((tree));
                     73: static void set_block_abstract_flags PROTO((tree, int));
1.1       root       74: 
1.1.1.7   root       75: void set_decl_abstract_flags   PROTO((tree, int));
1.1       root       76: 
                     77: /* Zero if the current function (whose FUNCTION_DECL is FNDECL)
                     78:    is safe and reasonable to integrate into other functions.
                     79:    Nonzero means value is a warning message with a single %s
                     80:    for the function's name.  */
                     81: 
                     82: char *
                     83: function_cannot_inline_p (fndecl)
                     84:      register tree fndecl;
                     85: {
                     86:   register rtx insn;
                     87:   tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
                     88:   int max_insns = INTEGRATE_THRESHOLD (fndecl);
                     89:   register int ninsns = 0;
                     90:   register tree parms;
                     91: 
                     92:   /* No inlines with varargs.  `grokdeclarator' gives a warning
                     93:      message about that if `inline' is specified.  This code
                     94:      it put in to catch the volunteers.  */
                     95:   if ((last && TREE_VALUE (last) != void_type_node)
1.1.1.7   root       96:       || current_function_varargs)
1.1       root       97:     return "varargs function cannot be inline";
                     98: 
                     99:   if (current_function_calls_alloca)
                    100:     return "function using alloca cannot be inline";
                    101: 
                    102:   if (current_function_contains_functions)
                    103:     return "function with nested functions cannot be inline";
                    104: 
                    105:   /* If its not even close, don't even look.  */
1.1.1.4   root      106:   if (!DECL_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
1.1       root      107:     return "function too large to be inline";
                    108: 
                    109: #if 0
                    110:   /* Large stacks are OK now that inlined functions can share them.  */
                    111:   /* Don't inline functions with large stack usage,
                    112:      since they can make other recursive functions burn up stack.  */
1.1.1.4   root      113:   if (!DECL_INLINE (fndecl) && get_frame_size () > 100)
1.1       root      114:     return "function stack frame for inlining";
                    115: #endif
                    116: 
                    117: #if 0
                    118:   /* Don't inline functions which do not specify a function prototype and
                    119:      have BLKmode argument or take the address of a parameter.  */
                    120:   for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
                    121:     {
                    122:       if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
                    123:        TREE_ADDRESSABLE (parms) = 1;
                    124:       if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
                    125:        return "no prototype, and parameter address used; cannot be inline";
                    126:     }
                    127: #endif
                    128: 
                    129:   /* We can't inline functions that return structures
                    130:      the old-fashioned PCC way, copying into a static block.  */
                    131:   if (current_function_returns_pcc_struct)
                    132:     return "inline functions not supported for this return value type";
                    133: 
1.1.1.8 ! root      134:   /* We can't inline functions that return BLKmode structures in registers.  */
        !           135:   if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
        !           136:       && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
        !           137:     return "inline functions not supported for this return value type";
        !           138: 
1.1       root      139:   /* We can't inline functions that return structures of varying size.  */
                    140:   if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
                    141:     return "function with varying-size return value cannot be inline";
                    142: 
1.1.1.7   root      143:   /* Cannot inline a function with a varying size argument or one that
                    144:      receives a transparent union.  */
1.1       root      145:   for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
1.1.1.7   root      146:     {
                    147:       if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
                    148:        return "function with varying-size parameter cannot be inline";
                    149:       else if (TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
                    150:        return "function with transparent unit parameter cannot be inline";
                    151:     }
1.1       root      152: 
1.1.1.4   root      153:   if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns)
1.1       root      154:     {
                    155:       for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns;
                    156:           insn = NEXT_INSN (insn))
                    157:        {
                    158:          if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
                    159:            ninsns++;
                    160:        }
                    161: 
                    162:       if (ninsns >= max_insns)
                    163:        return "function too large to be inline";
                    164:     }
                    165: 
1.1.1.2   root      166:   /* We cannot inline this function if forced_labels is non-zero.  This
                    167:      implies that a label in this function was used as an initializer.
                    168:      Because labels can not be duplicated, all labels in the function
                    169:      will be renamed when it is inlined.  However, there is no way to find
                    170:      and fix all variables initialized with addresses of labels in this
                    171:      function, hence inlining is impossible.  */
                    172: 
                    173:   if (forced_labels)
                    174:     return "function with label addresses used in initializers cannot inline";
                    175: 
1.1.1.6   root      176:   /* We cannot inline a nested function that jumps to a nonlocal label.  */
                    177:   if (current_function_has_nonlocal_goto)
                    178:     return "function with nonlocal goto cannot be inline";
                    179: 
1.1       root      180:   return 0;
                    181: }
                    182: 
                    183: /* Variables used within save_for_inline.  */
                    184: 
                    185: /* Mapping from old pseudo-register to new pseudo-registers.
                    186:    The first element of this map is reg_map[FIRST_PSEUDO_REGISTER].
                    187:    It is allocated in `save_for_inline' and `expand_inline_function',
                    188:    and deallocated on exit from each of those routines.  */
                    189: static rtx *reg_map;
                    190: 
                    191: /* Mapping from old code-labels to new code-labels.
                    192:    The first element of this map is label_map[min_labelno].
                    193:    It is allocated in `save_for_inline' and `expand_inline_function',
                    194:    and deallocated on exit from each of those routines.  */
                    195: static rtx *label_map;
                    196: 
                    197: /* Mapping from old insn uid's to copied insns.
                    198:    It is allocated in `save_for_inline' and `expand_inline_function',
                    199:    and deallocated on exit from each of those routines.  */
                    200: static rtx *insn_map;
                    201: 
                    202: /* Map pseudo reg number into the PARM_DECL for the parm living in the reg.
                    203:    Zero for a reg that isn't a parm's home.
                    204:    Only reg numbers less than max_parm_reg are mapped here.  */
                    205: static tree *parmdecl_map;
                    206: 
                    207: /* Keep track of first pseudo-register beyond those that are parms.  */
                    208: static int max_parm_reg;
                    209: 
                    210: /* When an insn is being copied by copy_for_inline,
                    211:    this is nonzero if we have copied an ASM_OPERANDS.
                    212:    In that case, it is the original input-operand vector.  */
                    213: static rtvec orig_asm_operands_vector;
                    214: 
                    215: /* When an insn is being copied by copy_for_inline,
                    216:    this is nonzero if we have copied an ASM_OPERANDS.
                    217:    In that case, it is the copied input-operand vector.  */
                    218: static rtvec copy_asm_operands_vector;
                    219: 
                    220: /* Likewise, this is the copied constraints vector.  */
                    221: static rtvec copy_asm_constraints_vector;
                    222: 
                    223: /* In save_for_inline, nonzero if past the parm-initialization insns.  */
                    224: static int in_nonparm_insns;
                    225: 
                    226: /* Subroutine for `save_for_inline{copying,nocopy}'.  Performs initialization
                    227:    needed to save FNDECL's insns and info for future inline expansion.  */
                    228:    
                    229: static rtx
                    230: initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
                    231:      tree fndecl;
                    232:      int min_labelno;
                    233:      int max_labelno;
                    234:      int max_reg;
                    235:      int copy;
                    236: {
                    237:   int function_flags, i;
                    238:   rtvec arg_vector;
                    239:   tree parms;
                    240: 
                    241:   /* Compute the values of any flags we must restore when inlining this.  */
                    242: 
                    243:   function_flags
                    244:     = (current_function_calls_alloca * FUNCTION_FLAGS_CALLS_ALLOCA
                    245:        + current_function_calls_setjmp * FUNCTION_FLAGS_CALLS_SETJMP
                    246:        + current_function_calls_longjmp * FUNCTION_FLAGS_CALLS_LONGJMP
                    247:        + current_function_returns_struct * FUNCTION_FLAGS_RETURNS_STRUCT
                    248:        + current_function_returns_pcc_struct * FUNCTION_FLAGS_RETURNS_PCC_STRUCT
                    249:        + current_function_needs_context * FUNCTION_FLAGS_NEEDS_CONTEXT
                    250:        + current_function_has_nonlocal_label * FUNCTION_FLAGS_HAS_NONLOCAL_LABEL
                    251:        + current_function_returns_pointer * FUNCTION_FLAGS_RETURNS_POINTER
                    252:        + current_function_uses_const_pool * FUNCTION_FLAGS_USES_CONST_POOL
                    253:        + current_function_uses_pic_offset_table * FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE);
                    254: 
                    255:   /* Clear out PARMDECL_MAP.  It was allocated in the caller's frame.  */
1.1.1.7   root      256:   bzero ((char *) parmdecl_map, max_parm_reg * sizeof (tree));
1.1       root      257:   arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
                    258: 
                    259:   for (parms = DECL_ARGUMENTS (fndecl), i = 0;
                    260:        parms;
                    261:        parms = TREE_CHAIN (parms), i++)
                    262:     {
                    263:       rtx p = DECL_RTL (parms);
                    264: 
                    265:       if (GET_CODE (p) == MEM && copy)
1.1.1.2   root      266:        {
                    267:          /* Copy the rtl so that modifications of the addresses
                    268:             later in compilation won't affect this arg_vector.
                    269:             Virtual register instantiation can screw the address
                    270:             of the rtl.  */
                    271:          rtx new = copy_rtx (p);
                    272: 
                    273:          /* Don't leave the old copy anywhere in this decl.  */
1.1.1.3   root      274:          if (DECL_RTL (parms) == DECL_INCOMING_RTL (parms)
                    275:              || (GET_CODE (DECL_RTL (parms)) == MEM
                    276:                  && GET_CODE (DECL_INCOMING_RTL (parms)) == MEM
                    277:                  && (XEXP (DECL_RTL (parms), 0)
                    278:                      == XEXP (DECL_INCOMING_RTL (parms), 0))))
1.1.1.2   root      279:            DECL_INCOMING_RTL (parms) = new;
                    280:          DECL_RTL (parms) = new;
                    281:        }
1.1       root      282: 
                    283:       RTVEC_ELT (arg_vector, i) = p;
                    284: 
                    285:       if (GET_CODE (p) == REG)
                    286:        parmdecl_map[REGNO (p)] = parms;
1.1.1.6   root      287:       else if (GET_CODE (p) == CONCAT)
                    288:        {
                    289:          rtx preal = gen_realpart (GET_MODE (XEXP (p, 0)), p);
                    290:          rtx pimag = gen_imagpart (GET_MODE (preal), p);
                    291: 
                    292:          if (GET_CODE (preal) == REG)
                    293:            parmdecl_map[REGNO (preal)] = parms;
                    294:          if (GET_CODE (pimag) == REG)
                    295:            parmdecl_map[REGNO (pimag)] = parms;
                    296:        }
                    297: 
1.1.1.3   root      298:       /* This flag is cleared later
                    299:         if the function ever modifies the value of the parm.  */
1.1       root      300:       TREE_READONLY (parms) = 1;
                    301:     }
                    302: 
                    303:   /* Assume we start out in the insns that set up the parameters.  */
                    304:   in_nonparm_insns = 0;
                    305: 
                    306:   /* The list of DECL_SAVED_INSNS, starts off with a header which
                    307:      contains the following information:
                    308: 
                    309:      the first insn of the function (not including the insns that copy
                    310:      parameters into registers).
                    311:      the first parameter insn of the function,
                    312:      the first label used by that function,
                    313:      the last label used by that function,
                    314:      the highest register number used for parameters,
                    315:      the total number of registers used,
                    316:      the size of the incoming stack area for parameters,
                    317:      the number of bytes popped on return,
                    318:      the stack slot list,
                    319:      some flags that are used to restore compiler globals,
                    320:      the value of current_function_outgoing_args_size,
                    321:      the original argument vector,
                    322:      and the original DECL_INITIAL.  */
                    323: 
1.1.1.4   root      324:   return gen_inline_header_rtx (NULL_RTX, NULL_RTX, min_labelno, max_labelno,
1.1       root      325:                                max_parm_reg, max_reg,
                    326:                                current_function_args_size,
                    327:                                current_function_pops_args,
1.1.1.8 ! root      328:                                stack_slot_list, forced_labels, function_flags,
1.1       root      329:                                current_function_outgoing_args_size,
                    330:                                arg_vector, (rtx) DECL_INITIAL (fndecl));
                    331: }
                    332: 
                    333: /* Subroutine for `save_for_inline{copying,nocopy}'.  Finishes up the
                    334:    things that must be done to make FNDECL expandable as an inline function.
                    335:    HEAD contains the chain of insns to which FNDECL will expand.  */
                    336:    
                    337: static void
                    338: finish_inline (fndecl, head)
                    339:      tree fndecl;
                    340:      rtx head;
                    341: {
                    342:   NEXT_INSN (head) = get_first_nonparm_insn ();
                    343:   FIRST_PARM_INSN (head) = get_insns ();
                    344:   DECL_SAVED_INSNS (fndecl) = head;
                    345:   DECL_FRAME_SIZE (fndecl) = get_frame_size ();
1.1.1.4   root      346: }
                    347: 
                    348: /* Adjust the BLOCK_END_NOTE pointers in a given copied DECL tree so that
                    349:    they all point to the new (copied) rtxs.  */
                    350: 
                    351: static void
                    352: adjust_copied_decl_tree (block)
                    353:      register tree block;
                    354: {
                    355:   register tree subblock;
                    356:   register rtx original_end;
                    357: 
                    358:   original_end = BLOCK_END_NOTE (block);
                    359:   if (original_end)
                    360:     {
                    361:       BLOCK_END_NOTE (block) = (rtx) NOTE_SOURCE_FILE (original_end);
                    362:       NOTE_SOURCE_FILE (original_end) = 0;
                    363:     }
                    364: 
                    365:   /* Process all subblocks.  */
                    366:   for (subblock = BLOCK_SUBBLOCKS (block);
                    367:        subblock;
                    368:        subblock = TREE_CHAIN (subblock))
                    369:     adjust_copied_decl_tree (subblock);
1.1       root      370: }
                    371: 
                    372: /* Make the insns and PARM_DECLs of the current function permanent
                    373:    and record other information in DECL_SAVED_INSNS to allow inlining
                    374:    of this function in subsequent calls.
                    375: 
                    376:    This function is called when we are going to immediately compile
                    377:    the insns for FNDECL.  The insns in maybepermanent_obstack cannot be
                    378:    modified by the compilation process, so we copy all of them to
                    379:    new storage and consider the new insns to be the insn chain to be
1.1.1.4   root      380:    compiled.  Our caller (rest_of_compilation) saves the original
                    381:    DECL_INITIAL and DECL_ARGUMENTS; here we copy them.  */
1.1       root      382: 
1.1.1.8 ! root      383: /* ??? The nonlocal_label list should be adjusted also.  However, since
        !           384:    a function that contains a nested function never gets inlined currently,
        !           385:    the nonlocal_label list will always be empty, so we don't worry about
        !           386:    it for now.  */
        !           387: 
1.1       root      388: void
                    389: save_for_inline_copying (fndecl)
                    390:      tree fndecl;
                    391: {
                    392:   rtx first_insn, last_insn, insn;
                    393:   rtx head, copy;
                    394:   int max_labelno, min_labelno, i, len;
                    395:   int max_reg;
                    396:   int max_uid;
                    397:   rtx first_nonparm_insn;
                    398: 
                    399:   /* Make and emit a return-label if we have not already done so. 
                    400:      Do this before recording the bounds on label numbers. */
                    401: 
                    402:   if (return_label == 0)
                    403:     {
                    404:       return_label = gen_label_rtx ();
                    405:       emit_label (return_label);
                    406:     }
                    407: 
                    408:   /* Get some bounds on the labels and registers used.  */
                    409: 
                    410:   max_labelno = max_label_num ();
                    411:   min_labelno = get_first_label_num ();
                    412:   max_reg = max_reg_num ();
                    413: 
                    414:   /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
                    415:      Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
                    416:      Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
                    417:      for the parms, prior to elimination of virtual registers.
                    418:      These values are needed for substituting parms properly.  */
                    419: 
                    420:   max_parm_reg = max_parm_reg_num ();
                    421:   parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
                    422: 
                    423:   head = initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, 1);
                    424: 
                    425:   if (current_function_uses_const_pool)
                    426:     {
                    427:       /* Replace any constant pool references with the actual constant.  We
                    428:         will put the constants back in the copy made below.  */
                    429:       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                    430:        if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
                    431:          {
                    432:            save_constants (&PATTERN (insn));
                    433:            if (REG_NOTES (insn))
                    434:              save_constants (&REG_NOTES (insn));
                    435:          }
                    436: 
                    437:       /* Clear out the constant pool so that we can recreate it with the
                    438:         copied constants below.  */
                    439:       init_const_rtx_hash_table ();
                    440:       clear_const_double_mem ();
                    441:     }
                    442: 
                    443:   max_uid = INSN_UID (head);
                    444: 
                    445:   /* We have now allocated all that needs to be allocated permanently
                    446:      on the rtx obstack.  Set our high-water mark, so that we
                    447:      can free the rest of this when the time comes.  */
                    448: 
                    449:   preserve_data ();
                    450: 
                    451:   /* Copy the chain insns of this function.
                    452:      Install the copied chain as the insns of this function,
                    453:      for continued compilation;
                    454:      the original chain is recorded as the DECL_SAVED_INSNS
                    455:      for inlining future calls.  */
                    456: 
                    457:   /* If there are insns that copy parms from the stack into pseudo registers,
                    458:      those insns are not copied.  `expand_inline_function' must
                    459:      emit the correct code to handle such things.  */
                    460: 
                    461:   insn = get_insns ();
                    462:   if (GET_CODE (insn) != NOTE)
                    463:     abort ();
                    464:   first_insn = rtx_alloc (NOTE);
                    465:   NOTE_SOURCE_FILE (first_insn) = NOTE_SOURCE_FILE (insn);
                    466:   NOTE_LINE_NUMBER (first_insn) = NOTE_LINE_NUMBER (insn);
                    467:   INSN_UID (first_insn) = INSN_UID (insn);
                    468:   PREV_INSN (first_insn) = NULL;
                    469:   NEXT_INSN (first_insn) = NULL;
                    470:   last_insn = first_insn;
                    471: 
                    472:   /* Each pseudo-reg in the old insn chain must have a unique rtx in the copy.
                    473:      Make these new rtx's now, and install them in regno_reg_rtx, so they
                    474:      will be the official pseudo-reg rtx's for the rest of compilation.  */
                    475: 
                    476:   reg_map = (rtx *) alloca ((max_reg + 1) * sizeof (rtx));
                    477: 
                    478:   len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);
                    479:   for (i = max_reg - 1; i > LAST_VIRTUAL_REGISTER; i--)
                    480:     reg_map[i] = (rtx)obstack_copy (function_maybepermanent_obstack,
                    481:                                    regno_reg_rtx[i], len);
                    482: 
1.1.1.7   root      483:   bcopy ((char *) (reg_map + LAST_VIRTUAL_REGISTER + 1),
                    484:         (char *) (regno_reg_rtx + LAST_VIRTUAL_REGISTER + 1),
1.1       root      485:         (max_reg - (LAST_VIRTUAL_REGISTER + 1)) * sizeof (rtx));
                    486: 
                    487:   /* Likewise each label rtx must have a unique rtx as its copy.  */
                    488: 
                    489:   label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
                    490:   label_map -= min_labelno;
                    491: 
                    492:   for (i = min_labelno; i < max_labelno; i++)
                    493:     label_map[i] = gen_label_rtx ();
                    494: 
                    495:   /* Record the mapping of old insns to copied insns.  */
                    496: 
                    497:   insn_map = (rtx *) alloca (max_uid * sizeof (rtx));
1.1.1.7   root      498:   bzero ((char *) insn_map, max_uid * sizeof (rtx));
1.1       root      499: 
                    500:   /* Get the insn which signals the end of parameter setup code.  */
                    501:   first_nonparm_insn = get_first_nonparm_insn ();
                    502: 
                    503:   /* Copy any entries in regno_reg_rtx or DECL_RTLs that reference MEM
                    504:      (the former occurs when a variable has its address taken)
                    505:      since these may be shared and can be changed by virtual
                    506:      register instantiation.  DECL_RTL values for our arguments
                    507:      have already been copied by initialize_for_inline.  */
                    508:   for (i = LAST_VIRTUAL_REGISTER + 1; i < max_reg; i++)
                    509:     if (GET_CODE (regno_reg_rtx[i]) == MEM)
                    510:       XEXP (regno_reg_rtx[i], 0)
                    511:        = copy_for_inline (XEXP (regno_reg_rtx[i], 0));
                    512: 
                    513:   /* Copy the tree of subblocks of the function, and the decls in them.
                    514:      We will use the copy for compiling this function, then restore the original
                    515:      subblocks and decls for use when inlining this function.
                    516: 
                    517:      Several parts of the compiler modify BLOCK trees.  In particular,
                    518:      instantiate_virtual_regs will instantiate any virtual regs
                    519:      mentioned in the DECL_RTLs of the decls, and loop
                    520:      unrolling will replicate any BLOCK trees inside an unrolled loop.
                    521: 
                    522:      The modified subblocks or DECL_RTLs would be incorrect for the original rtl
                    523:      which we will use for inlining.  The rtl might even contain pseudoregs
                    524:      whose space has been freed.  */
                    525: 
                    526:   DECL_INITIAL (fndecl) = copy_decl_tree (DECL_INITIAL (fndecl));
1.1.1.4   root      527:   DECL_ARGUMENTS (fndecl) = copy_decl_list (DECL_ARGUMENTS (fndecl));
1.1       root      528: 
                    529:   /* Now copy each DECL_RTL which is a MEM,
                    530:      so it is safe to modify their addresses.  */
                    531:   copy_decl_rtls (DECL_INITIAL (fndecl));
                    532: 
1.1.1.4   root      533:   /* The fndecl node acts as its own progenitor, so mark it as such.  */
                    534:   DECL_ABSTRACT_ORIGIN (fndecl) = fndecl;
                    535: 
1.1       root      536:   /* Now copy the chain of insns.  Do this twice.  The first copy the insn
                    537:      itself and its body.  The second time copy of REG_NOTES.  This is because
                    538:      a REG_NOTE may have a forward pointer to another insn.  */
                    539: 
                    540:   for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
                    541:     {
                    542:       orig_asm_operands_vector = 0;
                    543: 
                    544:       if (insn == first_nonparm_insn)
                    545:        in_nonparm_insns = 1;
                    546: 
                    547:       switch (GET_CODE (insn))
                    548:        {
                    549:        case NOTE:
                    550:          /* No need to keep these.  */
                    551:          if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
                    552:            continue;
                    553: 
                    554:          copy = rtx_alloc (NOTE);
                    555:          NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn);
1.1.1.4   root      556:          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END)
                    557:            NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
                    558:          else
                    559:            {
                    560:              NOTE_SOURCE_FILE (insn) = (char *) copy;
                    561:              NOTE_SOURCE_FILE (copy) = 0;
                    562:            }
1.1       root      563:          break;
                    564: 
                    565:        case INSN:
                    566:        case JUMP_INSN:
1.1.1.7   root      567:        case CALL_INSN:
1.1       root      568:          copy = rtx_alloc (GET_CODE (insn));
1.1.1.7   root      569: 
                    570:          if (GET_CODE (insn) == CALL_INSN)
                    571:            CALL_INSN_FUNCTION_USAGE (copy) =
                    572:                   copy_for_inline (CALL_INSN_FUNCTION_USAGE (insn));
                    573: 
1.1       root      574:          PATTERN (copy) = copy_for_inline (PATTERN (insn));
                    575:          INSN_CODE (copy) = -1;
1.1.1.7   root      576:          LOG_LINKS (copy) = NULL_RTX;
1.1       root      577:          RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
                    578:          break;
                    579: 
                    580:        case CODE_LABEL:
                    581:          copy = label_map[CODE_LABEL_NUMBER (insn)];
1.1.1.2   root      582:          LABEL_NAME (copy) = LABEL_NAME (insn);
1.1       root      583:          break;
                    584: 
                    585:        case BARRIER:
                    586:          copy = rtx_alloc (BARRIER);
                    587:          break;
                    588: 
                    589:        default:
                    590:          abort ();
                    591:        }
                    592:       INSN_UID (copy) = INSN_UID (insn);
                    593:       insn_map[INSN_UID (insn)] = copy;
                    594:       NEXT_INSN (last_insn) = copy;
                    595:       PREV_INSN (copy) = last_insn;
                    596:       last_insn = copy;
                    597:     }
                    598: 
1.1.1.4   root      599:   adjust_copied_decl_tree (DECL_INITIAL (fndecl));
                    600: 
1.1       root      601:   /* Now copy the REG_NOTES.  */
                    602:   for (insn = NEXT_INSN (get_insns ()); insn; insn = NEXT_INSN (insn))
                    603:     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
                    604:        && insn_map[INSN_UID(insn)])
                    605:       REG_NOTES (insn_map[INSN_UID (insn)])
                    606:        = copy_for_inline (REG_NOTES (insn));
                    607: 
                    608:   NEXT_INSN (last_insn) = NULL;
                    609: 
                    610:   finish_inline (fndecl, head);
                    611: 
                    612:   set_new_first_and_last_insn (first_insn, last_insn);
                    613: }
                    614: 
1.1.1.4   root      615: /* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
                    616:    For example, this can copy a list made of TREE_LIST nodes.  While copying,
                    617:    for each node copied which doesn't already have is DECL_ABSTRACT_ORIGIN
                    618:    set to some non-zero value, set the DECL_ABSTRACT_ORIGIN of the copy to
                    619:    point to the corresponding (abstract) original node.  */
                    620: 
                    621: static tree
                    622: copy_decl_list (list)
                    623:      tree list;
                    624: {
                    625:   tree head;
                    626:   register tree prev, next;
                    627: 
                    628:   if (list == 0)
                    629:     return 0;
                    630: 
                    631:   head = prev = copy_node (list);
                    632:   if (DECL_ABSTRACT_ORIGIN (head) == NULL_TREE)
                    633:     DECL_ABSTRACT_ORIGIN (head) = list;
                    634:   next = TREE_CHAIN (list);
                    635:   while (next)
                    636:     {
                    637:       register tree copy;
                    638: 
                    639:       copy = copy_node (next);
                    640:       if (DECL_ABSTRACT_ORIGIN (copy) == NULL_TREE)
                    641:        DECL_ABSTRACT_ORIGIN (copy) = next;
                    642:       TREE_CHAIN (prev) = copy;
                    643:       prev = copy;
                    644:       next = TREE_CHAIN (next);
                    645:     }
                    646:   return head;
                    647: }
                    648: 
1.1       root      649: /* Make a copy of the entire tree of blocks BLOCK, and return it.  */
                    650: 
                    651: static tree
                    652: copy_decl_tree (block)
                    653:      tree block;
                    654: {
                    655:   tree t, vars, subblocks;
                    656: 
1.1.1.4   root      657:   vars = copy_decl_list (BLOCK_VARS (block));
1.1       root      658:   subblocks = 0;
                    659: 
                    660:   /* Process all subblocks.  */
                    661:   for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
                    662:     {
                    663:       tree copy = copy_decl_tree (t);
                    664:       TREE_CHAIN (copy) = subblocks;
                    665:       subblocks = copy;
                    666:     }
                    667: 
                    668:   t = copy_node (block);
                    669:   BLOCK_VARS (t) = vars;
                    670:   BLOCK_SUBBLOCKS (t) = nreverse (subblocks);
1.1.1.4   root      671:   /* If the BLOCK being cloned is already marked as having been instantiated
1.1.1.8 ! root      672:      from something else, then leave that `origin' marking alone.  Otherwise,
1.1.1.4   root      673:      mark the clone as having originated from the BLOCK we are cloning.  */
                    674:   if (BLOCK_ABSTRACT_ORIGIN (t) == NULL_TREE)
                    675:     BLOCK_ABSTRACT_ORIGIN (t) = block;
1.1       root      676:   return t;
                    677: }
                    678: 
                    679: /* Copy DECL_RTLs in all decls in the given BLOCK node.  */
                    680: 
                    681: static void
                    682: copy_decl_rtls (block)
                    683:      tree block;
                    684: {
                    685:   tree t;
                    686: 
                    687:   for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
                    688:     if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)
                    689:       DECL_RTL (t) = copy_for_inline (DECL_RTL (t));
                    690: 
                    691:   /* Process all subblocks.  */
                    692:   for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
                    693:     copy_decl_rtls (t);
                    694: }
                    695: 
                    696: /* Make the insns and PARM_DECLs of the current function permanent
                    697:    and record other information in DECL_SAVED_INSNS to allow inlining
                    698:    of this function in subsequent calls.
                    699: 
                    700:    This routine need not copy any insns because we are not going
                    701:    to immediately compile the insns in the insn chain.  There
                    702:    are two cases when we would compile the insns for FNDECL:
                    703:    (1) when FNDECL is expanded inline, and (2) when FNDECL needs to
                    704:    be output at the end of other compilation, because somebody took
                    705:    its address.  In the first case, the insns of FNDECL are copied
                    706:    as it is expanded inline, so FNDECL's saved insns are not
                    707:    modified.  In the second case, FNDECL is used for the last time,
                    708:    so modifying the rtl is not a problem.
                    709: 
1.1.1.8 ! root      710:    We don't have to worry about FNDECL being inline expanded by
        !           711:    other functions which are written at the end of compilation
        !           712:    because flag_no_inline is turned on when we begin writing
        !           713:    functions at the end of compilation.  */
1.1       root      714: 
                    715: void
                    716: save_for_inline_nocopy (fndecl)
                    717:      tree fndecl;
                    718: {
                    719:   rtx insn;
1.1.1.7   root      720:   rtx head;
1.1       root      721:   rtx first_nonparm_insn;
                    722: 
                    723:   /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
                    724:      Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
                    725:      Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
                    726:      for the parms, prior to elimination of virtual registers.
                    727:      These values are needed for substituting parms properly.  */
                    728: 
                    729:   max_parm_reg = max_parm_reg_num ();
                    730:   parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
                    731: 
                    732:   /* Make and emit a return-label if we have not already done so.  */
                    733: 
                    734:   if (return_label == 0)
                    735:     {
                    736:       return_label = gen_label_rtx ();
                    737:       emit_label (return_label);
                    738:     }
                    739: 
                    740:   head = initialize_for_inline (fndecl, get_first_label_num (),
                    741:                                max_label_num (), max_reg_num (), 0);
                    742: 
                    743:   /* If there are insns that copy parms from the stack into pseudo registers,
                    744:      those insns are not copied.  `expand_inline_function' must
                    745:      emit the correct code to handle such things.  */
                    746: 
                    747:   insn = get_insns ();
                    748:   if (GET_CODE (insn) != NOTE)
                    749:     abort ();
                    750: 
                    751:   /* Get the insn which signals the end of parameter setup code.  */
                    752:   first_nonparm_insn = get_first_nonparm_insn ();
                    753: 
                    754:   /* Now just scan the chain of insns to see what happens to our
                    755:      PARM_DECLs.  If a PARM_DECL is used but never modified, we
                    756:      can substitute its rtl directly when expanding inline (and
                    757:      perform constant folding when its incoming value is constant).
                    758:      Otherwise, we have to copy its value into a new register and track
                    759:      the new register's life.  */
                    760: 
                    761:   for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
                    762:     {
                    763:       if (insn == first_nonparm_insn)
                    764:        in_nonparm_insns = 1;
                    765: 
                    766:       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
                    767:        {
                    768:          if (current_function_uses_const_pool)
                    769:            {
                    770:              /* Replace any constant pool references with the actual constant.
                    771:                 We will put the constant back if we need to write the
                    772:                 function out after all.  */
                    773:              save_constants (&PATTERN (insn));
                    774:              if (REG_NOTES (insn))
                    775:                save_constants (&REG_NOTES (insn));
                    776:            }
                    777: 
                    778:          /* Record what interesting things happen to our parameters.  */
                    779:          note_stores (PATTERN (insn), note_modified_parmregs);
                    780:        }
                    781:     }
                    782: 
                    783:   /* We have now allocated all that needs to be allocated permanently
                    784:      on the rtx obstack.  Set our high-water mark, so that we
                    785:      can free the rest of this when the time comes.  */
                    786: 
                    787:   preserve_data ();
                    788: 
                    789:   finish_inline (fndecl, head);
                    790: }
                    791: 
                    792: /* Given PX, a pointer into an insn, search for references to the constant
                    793:    pool.  Replace each with a CONST that has the mode of the original
                    794:    constant, contains the constant, and has RTX_INTEGRATED_P set.
                    795:    Similarly, constant pool addresses not enclosed in a MEM are replaced
                    796:    with an ADDRESS rtx which also gives the constant, mode, and has
                    797:    RTX_INTEGRATED_P set.  */
                    798: 
                    799: static void
                    800: save_constants (px)
                    801:      rtx *px;
                    802: {
                    803:   rtx x;
                    804:   int i, j;
                    805: 
                    806:  again:
                    807:   x = *px;
                    808: 
                    809:   /* If this is a CONST_DOUBLE, don't try to fix things up in 
                    810:      CONST_DOUBLE_MEM, because this is an infinite recursion.  */
                    811:   if (GET_CODE (x) == CONST_DOUBLE)
                    812:     return;
                    813:   else if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
                    814:           && CONSTANT_POOL_ADDRESS_P (XEXP (x,0)))
                    815:     {
                    816:       enum machine_mode const_mode = get_pool_mode (XEXP (x, 0));
                    817:       rtx new = gen_rtx (CONST, const_mode, get_pool_constant (XEXP (x, 0)));
                    818:       RTX_INTEGRATED_P (new) = 1;
                    819: 
                    820:       /* If the MEM was in a different mode than the constant (perhaps we
                    821:         were only looking at the low-order part), surround it with a 
                    822:         SUBREG so we can save both modes.  */
                    823: 
                    824:       if (GET_MODE (x) != const_mode)
                    825:        {
                    826:          new = gen_rtx (SUBREG, GET_MODE (x), new, 0);
                    827:          RTX_INTEGRATED_P (new) = 1;
                    828:        }
                    829: 
                    830:       *px = new;
                    831:       save_constants (&XEXP (*px, 0));
                    832:     }
                    833:   else if (GET_CODE (x) == SYMBOL_REF
                    834:           && CONSTANT_POOL_ADDRESS_P (x))
                    835:     {
                    836:       *px = gen_rtx (ADDRESS, get_pool_mode (x), get_pool_constant (x));
                    837:       save_constants (&XEXP (*px, 0));
                    838:       RTX_INTEGRATED_P (*px) = 1;
                    839:     }
                    840: 
                    841:   else
                    842:     {
                    843:       char *fmt = GET_RTX_FORMAT (GET_CODE (x));
                    844:       int len = GET_RTX_LENGTH (GET_CODE (x));
                    845: 
                    846:       for (i = len-1; i >= 0; i--)
                    847:        {
                    848:          switch (fmt[i])
                    849:            {
                    850:            case 'E':
                    851:              for (j = 0; j < XVECLEN (x, i); j++)
                    852:                save_constants (&XVECEXP (x, i, j));
                    853:              break;
                    854: 
                    855:            case 'e':
                    856:              if (XEXP (x, i) == 0)
                    857:                continue;
                    858:              if (i == 0)
                    859:                {
                    860:                  /* Hack tail-recursion here.  */
                    861:                  px = &XEXP (x, 0);
                    862:                  goto again;
                    863:                }
                    864:              save_constants (&XEXP (x, i));
                    865:              break;
                    866:            }
                    867:        }
                    868:     }
                    869: }
                    870: 
                    871: /* Note whether a parameter is modified or not.  */
                    872: 
                    873: static void
                    874: note_modified_parmregs (reg, x)
                    875:      rtx reg;
                    876:      rtx x;
                    877: {
                    878:   if (GET_CODE (reg) == REG && in_nonparm_insns
                    879:       && REGNO (reg) < max_parm_reg
                    880:       && REGNO (reg) >= FIRST_PSEUDO_REGISTER
                    881:       && parmdecl_map[REGNO (reg)] != 0)
                    882:     TREE_READONLY (parmdecl_map[REGNO (reg)]) = 0;
                    883: }
                    884: 
                    885: /* Copy the rtx ORIG recursively, replacing pseudo-regs and labels
                    886:    according to `reg_map' and `label_map'.  The original rtl insns
                    887:    will be saved for inlining; this is used to make a copy
                    888:    which is used to finish compiling the inline function itself.
                    889: 
                    890:    If we find a "saved" constant pool entry, one which was replaced with
                    891:    the value of the constant, convert it back to a constant pool entry.
                    892:    Since the pool wasn't touched, this should simply restore the old
                    893:    address.
                    894: 
                    895:    All other kinds of rtx are copied except those that can never be
                    896:    changed during compilation.  */
                    897: 
                    898: static rtx
                    899: copy_for_inline (orig)
                    900:      rtx orig;
                    901: {
                    902:   register rtx x = orig;
                    903:   register int i;
                    904:   register enum rtx_code code;
                    905:   register char *format_ptr;
                    906: 
                    907:   if (x == 0)
                    908:     return x;
                    909: 
                    910:   code = GET_CODE (x);
                    911: 
                    912:   /* These types may be freely shared.  */
                    913: 
                    914:   switch (code)
                    915:     {
                    916:     case QUEUED:
                    917:     case CONST_INT:
                    918:     case SYMBOL_REF:
                    919:     case PC:
                    920:     case CC0:
                    921:       return x;
                    922: 
                    923:     case CONST_DOUBLE:
                    924:       /* We have to make a new CONST_DOUBLE to ensure that we account for
                    925:         it correctly.  Using the old CONST_DOUBLE_MEM data is wrong.  */
                    926:       if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
                    927:        {
                    928:          REAL_VALUE_TYPE d;
                    929: 
                    930:          REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1.1.1.7   root      931:          return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (x));
1.1       root      932:        }
                    933:       else
                    934:        return immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
                    935:                                   VOIDmode);
                    936: 
                    937:     case CONST:
                    938:       /* Get constant pool entry for constant in the pool.  */
                    939:       if (RTX_INTEGRATED_P (x))
                    940:        return validize_mem (force_const_mem (GET_MODE (x),
                    941:                                              copy_for_inline (XEXP (x, 0))));
                    942:       break;
                    943: 
                    944:     case SUBREG:
                    945:       /* Get constant pool entry, but access in different mode.  */
                    946:       if (RTX_INTEGRATED_P (x))
                    947:        {
                    948:          rtx new
                    949:            = force_const_mem (GET_MODE (SUBREG_REG (x)),
                    950:                               copy_for_inline (XEXP (SUBREG_REG (x), 0)));
                    951: 
                    952:          PUT_MODE (new, GET_MODE (x));
                    953:          return validize_mem (new);
                    954:        }
                    955:       break;
                    956: 
                    957:     case ADDRESS:
                    958:       /* If not special for constant pool error.  Else get constant pool
                    959:         address.  */
                    960:       if (! RTX_INTEGRATED_P (x))
                    961:        abort ();
                    962: 
                    963:       return XEXP (force_const_mem (GET_MODE (x),
                    964:                                    copy_for_inline (XEXP (x, 0))), 0);
                    965: 
                    966:     case ASM_OPERANDS:
                    967:       /* If a single asm insn contains multiple output operands
                    968:         then it contains multiple ASM_OPERANDS rtx's that share operand 3.
                    969:         We must make sure that the copied insn continues to share it.  */
                    970:       if (orig_asm_operands_vector == XVEC (orig, 3))
                    971:        {
                    972:          x = rtx_alloc (ASM_OPERANDS);
1.1.1.6   root      973:          x->volatil = orig->volatil;
1.1       root      974:          XSTR (x, 0) = XSTR (orig, 0);
                    975:          XSTR (x, 1) = XSTR (orig, 1);
                    976:          XINT (x, 2) = XINT (orig, 2);
                    977:          XVEC (x, 3) = copy_asm_operands_vector;
                    978:          XVEC (x, 4) = copy_asm_constraints_vector;
                    979:          XSTR (x, 5) = XSTR (orig, 5);
                    980:          XINT (x, 6) = XINT (orig, 6);
                    981:          return x;
                    982:        }
                    983:       break;
                    984: 
                    985:     case MEM:
                    986:       /* A MEM is usually allowed to be shared if its address is constant
                    987:         or is a constant plus one of the special registers.
                    988: 
                    989:         We do not allow sharing of addresses that are either a special
                    990:         register or the sum of a constant and a special register because
                    991:         it is possible for unshare_all_rtl to copy the address, into memory
                    992:         that won't be saved.  Although the MEM can safely be shared, and
                    993:         won't be copied there, the address itself cannot be shared, and may
                    994:         need to be copied. 
                    995: 
                    996:         There are also two exceptions with constants: The first is if the
                    997:         constant is a LABEL_REF or the sum of the LABEL_REF
                    998:         and an integer.  This case can happen if we have an inline
                    999:         function that supplies a constant operand to the call of another
                   1000:         inline function that uses it in a switch statement.  In this case,
                   1001:         we will be replacing the LABEL_REF, so we have to replace this MEM
                   1002:         as well.
                   1003: 
                   1004:         The second case is if we have a (const (plus (address ..) ...)).
                   1005:         In that case we need to put back the address of the constant pool
                   1006:         entry.  */
                   1007: 
                   1008:       if (CONSTANT_ADDRESS_P (XEXP (x, 0))
                   1009:          && GET_CODE (XEXP (x, 0)) != LABEL_REF
                   1010:          && ! (GET_CODE (XEXP (x, 0)) == CONST
                   1011:                && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
                   1012:                    && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
                   1013:                        == LABEL_REF)
                   1014:                        || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
                   1015:                            == ADDRESS)))))
                   1016:        return x;
                   1017:       break;
                   1018: 
                   1019:     case LABEL_REF:
1.1.1.6   root     1020:       /* If this is a non-local label, just make a new LABEL_REF.
                   1021:         Otherwise, use the new label as well.  */
                   1022:       x = gen_rtx (LABEL_REF, GET_MODE (orig),
                   1023:                   LABEL_REF_NONLOCAL_P (orig) ? XEXP (orig, 0)
                   1024:                   : label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]);
                   1025:       LABEL_REF_NONLOCAL_P (x) = LABEL_REF_NONLOCAL_P (orig);
                   1026:       LABEL_OUTSIDE_LOOP_P (x) = LABEL_OUTSIDE_LOOP_P (orig);
                   1027:       return x;
1.1       root     1028: 
                   1029:     case REG:
                   1030:       if (REGNO (x) > LAST_VIRTUAL_REGISTER)
                   1031:        return reg_map [REGNO (x)];
                   1032:       else
                   1033:        return x;
                   1034: 
                   1035:     case SET:
                   1036:       /* If a parm that gets modified lives in a pseudo-reg,
                   1037:         clear its TREE_READONLY to prevent certain optimizations.  */
                   1038:       {
                   1039:        rtx dest = SET_DEST (x);
                   1040: 
                   1041:        while (GET_CODE (dest) == STRICT_LOW_PART
                   1042:               || GET_CODE (dest) == ZERO_EXTRACT
                   1043:               || GET_CODE (dest) == SUBREG)
                   1044:          dest = XEXP (dest, 0);
                   1045: 
                   1046:        if (GET_CODE (dest) == REG
                   1047:            && REGNO (dest) < max_parm_reg
                   1048:            && REGNO (dest) >= FIRST_PSEUDO_REGISTER
                   1049:            && parmdecl_map[REGNO (dest)] != 0
                   1050:            /* The insn to load an arg pseudo from a stack slot
                   1051:               does not count as modifying it.  */
                   1052:            && in_nonparm_insns)
                   1053:          TREE_READONLY (parmdecl_map[REGNO (dest)]) = 0;
                   1054:       }
                   1055:       break;
                   1056: 
                   1057: #if 0 /* This is a good idea, but here is the wrong place for it.  */
                   1058:       /* Arrange that CONST_INTs always appear as the second operand
                   1059:         if they appear, and that `frame_pointer_rtx' or `arg_pointer_rtx'
                   1060:         always appear as the first.  */
                   1061:     case PLUS:
                   1062:       if (GET_CODE (XEXP (x, 0)) == CONST_INT
                   1063:          || (XEXP (x, 1) == frame_pointer_rtx
                   1064:              || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   1065:                  && XEXP (x, 1) == arg_pointer_rtx)))
                   1066:        {
                   1067:          rtx t = XEXP (x, 0);
                   1068:          XEXP (x, 0) = XEXP (x, 1);
                   1069:          XEXP (x, 1) = t;
                   1070:        }
                   1071:       break;
                   1072: #endif
                   1073:     }
                   1074: 
                   1075:   /* Replace this rtx with a copy of itself.  */
                   1076: 
                   1077:   x = rtx_alloc (code);
1.1.1.7   root     1078:   bcopy ((char *) orig, (char *) x,
                   1079:         (sizeof (*x) - sizeof (x->fld)
                   1080:          + sizeof (x->fld[0]) * GET_RTX_LENGTH (code)));
1.1       root     1081: 
                   1082:   /* Now scan the subexpressions recursively.
                   1083:      We can store any replaced subexpressions directly into X
                   1084:      since we know X is not shared!  Any vectors in X
                   1085:      must be copied if X was copied.  */
                   1086: 
                   1087:   format_ptr = GET_RTX_FORMAT (code);
                   1088: 
                   1089:   for (i = 0; i < GET_RTX_LENGTH (code); i++)
                   1090:     {
                   1091:       switch (*format_ptr++)
                   1092:        {
                   1093:        case 'e':
                   1094:          XEXP (x, i) = copy_for_inline (XEXP (x, i));
                   1095:          break;
                   1096: 
                   1097:        case 'u':
                   1098:          /* Change any references to old-insns to point to the
                   1099:             corresponding copied insns.  */
                   1100:          XEXP (x, i) = insn_map[INSN_UID (XEXP (x, i))];
                   1101:          break;
                   1102: 
                   1103:        case 'E':
                   1104:          if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
                   1105:            {
                   1106:              register int j;
                   1107: 
                   1108:              XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));
                   1109:              for (j = 0; j < XVECLEN (x, i); j++)
                   1110:                XVECEXP (x, i, j)
                   1111:                  = copy_for_inline (XVECEXP (x, i, j));
                   1112:            }
                   1113:          break;
                   1114:        }
                   1115:     }
                   1116: 
                   1117:   if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)
                   1118:     {
                   1119:       orig_asm_operands_vector = XVEC (orig, 3);
                   1120:       copy_asm_operands_vector = XVEC (x, 3);
                   1121:       copy_asm_constraints_vector = XVEC (x, 4);
                   1122:     }
                   1123: 
                   1124:   return x;
                   1125: }
                   1126: 
                   1127: /* Unfortunately, we need a global copy of const_equiv map for communication
                   1128:    with a function called from note_stores.  Be *very* careful that this
                   1129:    is used properly in the presence of recursion.  */
                   1130: 
                   1131: rtx *global_const_equiv_map;
1.1.1.6   root     1132: int global_const_equiv_map_size;
1.1       root     1133: 
                   1134: #define FIXED_BASE_PLUS_P(X) \
                   1135:   (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
                   1136:    && GET_CODE (XEXP (X, 0)) == REG                            \
                   1137:    && REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER            \
1.1.1.5   root     1138:    && REGNO (XEXP (X, 0)) <= LAST_VIRTUAL_REGISTER)
1.1       root     1139: 
                   1140: /* Integrate the procedure defined by FNDECL.  Note that this function
                   1141:    may wind up calling itself.  Since the static variables are not
                   1142:    reentrant, we do not assign them until after the possibility
1.1.1.3   root     1143:    of recursion is eliminated.
1.1       root     1144: 
                   1145:    If IGNORE is nonzero, do not produce a value.
                   1146:    Otherwise store the value in TARGET if it is nonzero and that is convenient.
                   1147: 
                   1148:    Value is:
                   1149:    (rtx)-1 if we could not substitute the function
                   1150:    0 if we substituted it and it does not produce a value
                   1151:    else an rtx for where the value is stored.  */
                   1152: 
                   1153: rtx
                   1154: expand_inline_function (fndecl, parms, target, ignore, type, structure_value_addr)
                   1155:      tree fndecl, parms;
                   1156:      rtx target;
                   1157:      int ignore;
                   1158:      tree type;
                   1159:      rtx structure_value_addr;
                   1160: {
1.1.1.4   root     1161:   tree formal, actual, block;
1.1       root     1162:   rtx header = DECL_SAVED_INSNS (fndecl);
                   1163:   rtx insns = FIRST_FUNCTION_INSN (header);
                   1164:   rtx parm_insns = FIRST_PARM_INSN (header);
                   1165:   tree *arg_trees;
                   1166:   rtx *arg_vals;
                   1167:   rtx insn;
                   1168:   int max_regno;
                   1169:   register int i;
                   1170:   int min_labelno = FIRST_LABELNO (header);
                   1171:   int max_labelno = LAST_LABELNO (header);
                   1172:   int nargs;
                   1173:   rtx local_return_label = 0;
                   1174:   rtx loc;
1.1.1.8 ! root     1175:   rtx stack_save = 0;
1.1       root     1176:   rtx temp;
                   1177:   struct inline_remap *map;
                   1178:   rtx cc0_insn = 0;
                   1179:   rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);
1.1.1.6   root     1180:   rtx static_chain_value = 0;
1.1       root     1181: 
                   1182:   /* Allow for equivalences of the pseudos we make for virtual fp and ap.  */
                   1183:   max_regno = MAX_REGNUM (header) + 3;
                   1184:   if (max_regno < FIRST_PSEUDO_REGISTER)
                   1185:     abort ();
                   1186: 
                   1187:   nargs = list_length (DECL_ARGUMENTS (fndecl));
                   1188: 
1.1.1.7   root     1189:   /* Check that the parms type match and that sufficient arguments were
                   1190:      passed.  Since the appropriate conversions or default promotions have
                   1191:      already been applied, the machine modes should match exactly.  */
                   1192: 
1.1       root     1193:   for (formal = DECL_ARGUMENTS (fndecl),
                   1194:        actual = parms;
                   1195:        formal;
                   1196:        formal = TREE_CHAIN (formal),
                   1197:        actual = TREE_CHAIN (actual))
                   1198:     {
1.1.1.7   root     1199:       tree arg;
                   1200:       enum machine_mode mode;
                   1201: 
                   1202:       if (actual == 0)
1.1.1.4   root     1203:        return (rtx) (HOST_WIDE_INT) -1;
1.1.1.7   root     1204: 
                   1205:       arg = TREE_VALUE (actual);
                   1206:       mode= TYPE_MODE (DECL_ARG_TYPE (formal));
                   1207: 
                   1208:       if (mode != TYPE_MODE (TREE_TYPE (arg))
                   1209:          /* If they are block mode, the types should match exactly.
                   1210:             They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE,
                   1211:             which could happen if the parameter has incomplete type.  */
                   1212:          || (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal)))
1.1.1.4   root     1213:        return (rtx) (HOST_WIDE_INT) -1;
1.1       root     1214:     }
                   1215: 
1.1.1.7   root     1216:   /* Extra arguments are valid, but will be ignored below, so we must
                   1217:      evaluate them here for side-effects.  */
                   1218:   for (; actual; actual = TREE_CHAIN (actual))
                   1219:     expand_expr (TREE_VALUE (actual), const0_rtx,
                   1220:                 TYPE_MODE (TREE_TYPE (TREE_VALUE (actual))), 0);
                   1221: 
1.1       root     1222:   /* Make a binding contour to keep inline cleanups called at
                   1223:      outer function-scope level from looking like they are shadowing
                   1224:      parameter declarations.  */
                   1225:   pushlevel (0);
                   1226: 
                   1227:   /* Make a fresh binding contour that we can easily remove.  */
                   1228:   pushlevel (0);
                   1229:   expand_start_bindings (0);
                   1230: 
                   1231:   /* Expand the function arguments.  Do this first so that any
                   1232:      new registers get created before we allocate the maps.  */
                   1233: 
                   1234:   arg_vals = (rtx *) alloca (nargs * sizeof (rtx));
                   1235:   arg_trees = (tree *) alloca (nargs * sizeof (tree));
                   1236: 
                   1237:   for (formal = DECL_ARGUMENTS (fndecl), actual = parms, i = 0;
                   1238:        formal;
                   1239:        formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual), i++)
                   1240:     {
                   1241:       /* Actual parameter, converted to the type of the argument within the
                   1242:         function.  */
                   1243:       tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
                   1244:       /* Mode of the variable used within the function.  */
                   1245:       enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
1.1.1.7   root     1246:       int invisiref = 0;
1.1       root     1247: 
                   1248:       arg_trees[i] = arg;
                   1249:       loc = RTVEC_ELT (arg_vector, i);
                   1250: 
                   1251:       /* If this is an object passed by invisible reference, we copy the
                   1252:         object into a stack slot and save its address.  If this will go
                   1253:         into memory, we do nothing now.  Otherwise, we just expand the
                   1254:         argument.  */
                   1255:       if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
                   1256:          && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
                   1257:        {
1.1.1.4   root     1258:          rtx stack_slot
                   1259:            = assign_stack_temp (TYPE_MODE (TREE_TYPE (arg)),
                   1260:                                 int_size_in_bytes (TREE_TYPE (arg)), 1);
1.1.1.8 ! root     1261:          MEM_IN_STRUCT_P (stack_slot) = AGGREGATE_TYPE_P (TREE_TYPE (arg));
1.1       root     1262: 
                   1263:          store_expr (arg, stack_slot, 0);
                   1264: 
                   1265:          arg_vals[i] = XEXP (stack_slot, 0);
1.1.1.7   root     1266:          invisiref = 1;
1.1       root     1267:        }
                   1268:       else if (GET_CODE (loc) != MEM)
1.1.1.5   root     1269:        {
                   1270:          if (GET_MODE (loc) != TYPE_MODE (TREE_TYPE (arg)))
                   1271:            /* The mode if LOC and ARG can differ if LOC was a variable
                   1272:               that had its mode promoted via PROMOTED_MODE.  */
1.1.1.6   root     1273:            arg_vals[i] = convert_modes (GET_MODE (loc),
                   1274:                                         TYPE_MODE (TREE_TYPE (arg)),
                   1275:                                         expand_expr (arg, NULL_RTX, mode,
                   1276:                                                      EXPAND_SUM),
                   1277:                                         TREE_UNSIGNED (TREE_TYPE (formal)));
1.1.1.5   root     1278:          else
                   1279:            arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
                   1280:        }
1.1       root     1281:       else
                   1282:        arg_vals[i] = 0;
                   1283: 
                   1284:       if (arg_vals[i] != 0
                   1285:          && (! TREE_READONLY (formal)
                   1286:              /* If the parameter is not read-only, copy our argument through
                   1287:                 a register.  Also, we cannot use ARG_VALS[I] if it overlaps
                   1288:                 TARGET in any way.  In the inline function, they will likely
                   1289:                 be two different pseudos, and `safe_from_p' will make all
                   1290:                 sorts of smart assumptions about their not conflicting.
                   1291:                 But if ARG_VALS[I] overlaps TARGET, these assumptions are
1.1.1.7   root     1292:                 wrong, so put ARG_VALS[I] into a fresh register.
                   1293:                 Don't worry about invisible references, since their stack
                   1294:                 temps will never overlap the target.  */
1.1       root     1295:              || (target != 0
1.1.1.7   root     1296:                  && ! invisiref
1.1       root     1297:                  && (GET_CODE (arg_vals[i]) == REG
                   1298:                      || GET_CODE (arg_vals[i]) == SUBREG
                   1299:                      || GET_CODE (arg_vals[i]) == MEM)
1.1.1.5   root     1300:                  && reg_overlap_mentioned_p (arg_vals[i], target))
                   1301:              /* ??? We must always copy a SUBREG into a REG, because it might
                   1302:                 get substituted into an address, and not all ports correctly
                   1303:                 handle SUBREGs in addresses.  */
                   1304:              || (GET_CODE (arg_vals[i]) == SUBREG)))
1.1.1.4   root     1305:        arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]);
1.1       root     1306:     }
                   1307:        
                   1308:   /* Allocate the structures we use to remap things.  */
                   1309: 
                   1310:   map = (struct inline_remap *) alloca (sizeof (struct inline_remap));
                   1311:   map->fndecl = fndecl;
                   1312: 
                   1313:   map->reg_map = (rtx *) alloca (max_regno * sizeof (rtx));
1.1.1.7   root     1314:   bzero ((char *) map->reg_map, max_regno * sizeof (rtx));
1.1       root     1315: 
                   1316:   map->label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
                   1317:   map->label_map -= min_labelno;
                   1318: 
                   1319:   map->insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));
1.1.1.7   root     1320:   bzero ((char *) map->insn_map, INSN_UID (header) * sizeof (rtx));
1.1       root     1321:   map->min_insnno = 0;
                   1322:   map->max_insnno = INSN_UID (header);
                   1323: 
1.1.1.5   root     1324:   map->integrating = 1;
                   1325: 
1.1       root     1326:   /* const_equiv_map maps pseudos in our routine to constants, so it needs to
                   1327:      be large enough for all our pseudos.  This is the number we are currently
                   1328:      using plus the number in the called routine, plus 15 for each arg,
                   1329:      five to compute the virtual frame pointer, and five for the return value.
                   1330:      This should be enough for most cases.  We do not reference entries
                   1331:      outside the range of the map.
                   1332: 
                   1333:      ??? These numbers are quite arbitrary and were obtained by
                   1334:      experimentation.  At some point, we should try to allocate the
                   1335:      table after all the parameters are set up so we an more accurately
                   1336:      estimate the number of pseudos we will need.  */
                   1337: 
                   1338:   map->const_equiv_map_size
                   1339:     = max_reg_num () + (max_regno - FIRST_PSEUDO_REGISTER) + 15 * nargs + 10;
                   1340: 
                   1341:   map->const_equiv_map
                   1342:     = (rtx *)alloca (map->const_equiv_map_size * sizeof (rtx));
1.1.1.7   root     1343:   bzero ((char *) map->const_equiv_map,
                   1344:         map->const_equiv_map_size * sizeof (rtx));
1.1       root     1345: 
                   1346:   map->const_age_map
                   1347:     = (unsigned *)alloca (map->const_equiv_map_size * sizeof (unsigned));
1.1.1.7   root     1348:   bzero ((char *) map->const_age_map,
                   1349:         map->const_equiv_map_size * sizeof (unsigned));
1.1       root     1350:   map->const_age = 0;
                   1351: 
                   1352:   /* Record the current insn in case we have to set up pointers to frame
                   1353:      and argument memory blocks.  */
                   1354:   map->insns_at_start = get_last_insn ();
                   1355: 
                   1356:   /* Update the outgoing argument size to allow for those in the inlined
                   1357:      function.  */
                   1358:   if (OUTGOING_ARGS_SIZE (header) > current_function_outgoing_args_size)
                   1359:     current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (header);
                   1360: 
                   1361:   /* If the inline function needs to make PIC references, that means
                   1362:      that this function's PIC offset table must be used.  */
                   1363:   if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
                   1364:     current_function_uses_pic_offset_table = 1;
                   1365: 
1.1.1.6   root     1366:   /* If this function needs a context, set it up.  */
                   1367:   if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_NEEDS_CONTEXT)
                   1368:     static_chain_value = lookup_static_chain (fndecl);
                   1369: 
1.1.1.8 ! root     1370:   if (GET_CODE (parm_insns) == NOTE
        !          1371:       && NOTE_LINE_NUMBER (parm_insns) > 0)
        !          1372:     {
        !          1373:       rtx note = emit_note (NOTE_SOURCE_FILE (parm_insns),
        !          1374:                            NOTE_LINE_NUMBER (parm_insns));
        !          1375:       if (note)
        !          1376:        RTX_INTEGRATED_P (note) = 1;
        !          1377:     }
        !          1378: 
1.1       root     1379:   /* Process each argument.  For each, set up things so that the function's
                   1380:      reference to the argument will refer to the argument being passed.
                   1381:      We only replace REG with REG here.  Any simplifications are done
                   1382:      via const_equiv_map.
                   1383: 
                   1384:      We make two passes:  In the first, we deal with parameters that will
                   1385:      be placed into registers, since we need to ensure that the allocated
                   1386:      register number fits in const_equiv_map.  Then we store all non-register
                   1387:      parameters into their memory location.  */
                   1388: 
1.1.1.6   root     1389:   /* Don't try to free temp stack slots here, because we may put one of the
                   1390:      parameters into a temp stack slot.  */
                   1391: 
1.1       root     1392:   for (i = 0; i < nargs; i++)
                   1393:     {
                   1394:       rtx copy = arg_vals[i];
                   1395: 
                   1396:       loc = RTVEC_ELT (arg_vector, i);
                   1397: 
                   1398:       /* There are three cases, each handled separately.  */
                   1399:       if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
                   1400:          && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
                   1401:        {
                   1402:          /* This must be an object passed by invisible reference (it could
                   1403:             also be a variable-sized object, but we forbid inlining functions
                   1404:             with variable-sized arguments).  COPY is the address of the
                   1405:             actual value (this computation will cause it to be copied).  We
                   1406:             map that address for the register, noting the actual address as
                   1407:             an equivalent in case it can be substituted into the insns.  */
                   1408: 
                   1409:          if (GET_CODE (copy) != REG)
                   1410:            {
                   1411:              temp = copy_addr_to_reg (copy);
1.1.1.6   root     1412:              if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
                   1413:                  && REGNO (temp) < map->const_equiv_map_size)
1.1       root     1414:                {
                   1415:                  map->const_equiv_map[REGNO (temp)] = copy;
                   1416:                  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   1417:                }
                   1418:              copy = temp;
                   1419:            }
                   1420:          map->reg_map[REGNO (XEXP (loc, 0))] = copy;
                   1421:        }
                   1422:       else if (GET_CODE (loc) == MEM)
                   1423:        {
                   1424:          /* This is the case of a parameter that lives in memory.
                   1425:             It will live in the block we allocate in the called routine's
                   1426:             frame that simulates the incoming argument area.  Do nothing
                   1427:             now; we will call store_expr later.  */
                   1428:          ;
                   1429:        }
                   1430:       else if (GET_CODE (loc) == REG)
                   1431:        {
                   1432:          /* This is the good case where the parameter is in a register.
                   1433:             If it is read-only and our argument is a constant, set up the
1.1.1.4   root     1434:             constant equivalence.
                   1435: 
                   1436:             If LOC is REG_USERVAR_P, the usual case, COPY must also have
1.1.1.6   root     1437:             that flag set if it is a register.
                   1438: 
                   1439:             Also, don't allow hard registers here; they might not be valid
                   1440:             when substituted into insns. */
1.1.1.4   root     1441: 
                   1442:          if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
                   1443:              || (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
1.1.1.6   root     1444:                  && ! REG_USERVAR_P (copy))
                   1445:              || (GET_CODE (copy) == REG
                   1446:                  && REGNO (copy) < FIRST_PSEUDO_REGISTER))
1.1       root     1447:            {
                   1448:              temp = copy_to_mode_reg (GET_MODE (loc), copy);
1.1.1.4   root     1449:              REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
1.1.1.6   root     1450:              if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
                   1451:                  && REGNO (temp) < map->const_equiv_map_size)
1.1       root     1452:                {
                   1453:                  map->const_equiv_map[REGNO (temp)] = copy;
                   1454:                  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   1455:                }
                   1456:              copy = temp;
                   1457:            }
                   1458:          map->reg_map[REGNO (loc)] = copy;
                   1459:        }
1.1.1.6   root     1460:       else if (GET_CODE (loc) == CONCAT)
                   1461:        {
                   1462:          /* This is the good case where the parameter is in a
                   1463:             pair of separate pseudos.
                   1464:             If it is read-only and our argument is a constant, set up the
                   1465:             constant equivalence.
                   1466: 
                   1467:             If LOC is REG_USERVAR_P, the usual case, COPY must also have
                   1468:             that flag set if it is a register.
                   1469: 
                   1470:             Also, don't allow hard registers here; they might not be valid
                   1471:             when substituted into insns. */
                   1472:          rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);
                   1473:          rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);
                   1474:          rtx copyreal = gen_realpart (GET_MODE (locreal), copy);
                   1475:          rtx copyimag = gen_imagpart (GET_MODE (locimag), copy);
                   1476: 
                   1477:          if ((GET_CODE (copyreal) != REG && GET_CODE (copyreal) != SUBREG)
                   1478:              || (GET_CODE (copyreal) == REG && REG_USERVAR_P (locreal)
                   1479:                  && ! REG_USERVAR_P (copyreal))
                   1480:              || (GET_CODE (copyreal) == REG
                   1481:                  && REGNO (copyreal) < FIRST_PSEUDO_REGISTER))
                   1482:            {
                   1483:              temp = copy_to_mode_reg (GET_MODE (locreal), copyreal);
                   1484:              REG_USERVAR_P (temp) = REG_USERVAR_P (locreal);
                   1485:              if ((CONSTANT_P (copyreal) || FIXED_BASE_PLUS_P (copyreal))
                   1486:                  && REGNO (temp) < map->const_equiv_map_size)
                   1487:                {
                   1488:                  map->const_equiv_map[REGNO (temp)] = copyreal;
                   1489:                  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   1490:                }
                   1491:              copyreal = temp;
                   1492:            }
                   1493:          map->reg_map[REGNO (locreal)] = copyreal;
                   1494: 
                   1495:          if ((GET_CODE (copyimag) != REG && GET_CODE (copyimag) != SUBREG)
                   1496:              || (GET_CODE (copyimag) == REG && REG_USERVAR_P (locimag)
                   1497:                  && ! REG_USERVAR_P (copyimag))
                   1498:              || (GET_CODE (copyimag) == REG
                   1499:                  && REGNO (copyimag) < FIRST_PSEUDO_REGISTER))
                   1500:            {
                   1501:              temp = copy_to_mode_reg (GET_MODE (locimag), copyimag);
                   1502:              REG_USERVAR_P (temp) = REG_USERVAR_P (locimag);
                   1503:              if ((CONSTANT_P (copyimag) || FIXED_BASE_PLUS_P (copyimag))
                   1504:                  && REGNO (temp) < map->const_equiv_map_size)
                   1505:                {
                   1506:                  map->const_equiv_map[REGNO (temp)] = copyimag;
                   1507:                  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   1508:                }
                   1509:              copyimag = temp;
                   1510:            }
                   1511:          map->reg_map[REGNO (locimag)] = copyimag;
                   1512:        }
1.1       root     1513:       else
                   1514:        abort ();
                   1515:     }
                   1516: 
                   1517:   /* Now do the parameters that will be placed in memory.  */
                   1518: 
                   1519:   for (formal = DECL_ARGUMENTS (fndecl), i = 0;
                   1520:        formal; formal = TREE_CHAIN (formal), i++)
                   1521:     {
                   1522:       loc = RTVEC_ELT (arg_vector, i);
                   1523: 
                   1524:       if (GET_CODE (loc) == MEM
                   1525:          /* Exclude case handled above.  */
                   1526:          && ! (GET_CODE (XEXP (loc, 0)) == REG
                   1527:                && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))
                   1528:        {
1.1.1.4   root     1529:          rtx note = emit_note (DECL_SOURCE_FILE (formal),
                   1530:                                DECL_SOURCE_LINE (formal));
                   1531:          if (note)
                   1532:            RTX_INTEGRATED_P (note) = 1;
1.1       root     1533: 
                   1534:          /* Compute the address in the area we reserved and store the
                   1535:             value there.  */
                   1536:          temp = copy_rtx_and_substitute (loc, map);
1.1.1.4   root     1537:          subst_constants (&temp, NULL_RTX, map);
1.1       root     1538:          apply_change_group ();
                   1539:          if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
                   1540:            temp = change_address (temp, VOIDmode, XEXP (temp, 0));
                   1541:          store_expr (arg_trees[i], temp, 0);
                   1542:        }
                   1543:     }
                   1544: 
                   1545:   /* Deal with the places that the function puts its result.
                   1546:      We are driven by what is placed into DECL_RESULT.
                   1547: 
                   1548:      Initially, we assume that we don't have anything special handling for
                   1549:      REG_FUNCTION_RETURN_VALUE_P.  */
                   1550: 
                   1551:   map->inline_target = 0;
                   1552:   loc = DECL_RTL (DECL_RESULT (fndecl));
                   1553:   if (TYPE_MODE (type) == VOIDmode)
                   1554:     /* There is no return value to worry about.  */
                   1555:     ;
                   1556:   else if (GET_CODE (loc) == MEM)
                   1557:     {
                   1558:       if (! structure_value_addr || ! aggregate_value_p (DECL_RESULT (fndecl)))
                   1559:        abort ();
                   1560:   
                   1561:       /* Pass the function the address in which to return a structure value.
                   1562:         Note that a constructor can cause someone to call us with
                   1563:         STRUCTURE_VALUE_ADDR, but the initialization takes place
                   1564:         via the first parameter, rather than the struct return address.
                   1565: 
                   1566:         We have two cases:  If the address is a simple register indirect,
                   1567:         use the mapping mechanism to point that register to our structure
                   1568:         return address.  Otherwise, store the structure return value into
                   1569:         the place that it will be referenced from.  */
                   1570: 
                   1571:       if (GET_CODE (XEXP (loc, 0)) == REG)
                   1572:        {
                   1573:          temp = force_reg (Pmode, structure_value_addr);
                   1574:          map->reg_map[REGNO (XEXP (loc, 0))] = temp;
1.1.1.6   root     1575:          if ((CONSTANT_P (structure_value_addr)
                   1576:               || (GET_CODE (structure_value_addr) == PLUS
                   1577:                   && XEXP (structure_value_addr, 0) == virtual_stack_vars_rtx
                   1578:                   && GET_CODE (XEXP (structure_value_addr, 1)) == CONST_INT))
                   1579:              && REGNO (temp) < map->const_equiv_map_size)
1.1       root     1580:            {
                   1581:              map->const_equiv_map[REGNO (temp)] = structure_value_addr;
                   1582:              map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   1583:            }
                   1584:        }
                   1585:       else
                   1586:        {
                   1587:          temp = copy_rtx_and_substitute (loc, map);
1.1.1.4   root     1588:          subst_constants (&temp, NULL_RTX, map);
1.1       root     1589:          apply_change_group ();
                   1590:          emit_move_insn (temp, structure_value_addr);
                   1591:        }
                   1592:     }
                   1593:   else if (ignore)
                   1594:     /* We will ignore the result value, so don't look at its structure.
                   1595:        Note that preparations for an aggregate return value
                   1596:        do need to be made (above) even if it will be ignored.  */
                   1597:     ;
                   1598:   else if (GET_CODE (loc) == REG)
                   1599:     {
                   1600:       /* The function returns an object in a register and we use the return
                   1601:         value.  Set up our target for remapping.  */
                   1602: 
                   1603:       /* Machine mode function was declared to return.   */
                   1604:       enum machine_mode departing_mode = TYPE_MODE (type);
                   1605:       /* (Possibly wider) machine mode it actually computes
                   1606:         (for the sake of callers that fail to declare it right).  */
                   1607:       enum machine_mode arriving_mode
                   1608:        = TYPE_MODE (TREE_TYPE (DECL_RESULT (fndecl)));
                   1609:       rtx reg_to_map;
                   1610: 
                   1611:       /* Don't use MEMs as direct targets because on some machines
                   1612:         substituting a MEM for a REG makes invalid insns.
                   1613:         Let the combiner substitute the MEM if that is valid.  */
                   1614:       if (target == 0 || GET_CODE (target) != REG
                   1615:          || GET_MODE (target) != departing_mode)
                   1616:        target = gen_reg_rtx (departing_mode);
                   1617: 
                   1618:       /* If function's value was promoted before return,
                   1619:         avoid machine mode mismatch when we substitute INLINE_TARGET.
                   1620:         But TARGET is what we will return to the caller.  */
                   1621:       if (arriving_mode != departing_mode)
                   1622:        reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);
                   1623:       else
                   1624:        reg_to_map = target;
                   1625: 
                   1626:       /* Usually, the result value is the machine's return register.
                   1627:         Sometimes it may be a pseudo. Handle both cases.  */
                   1628:       if (REG_FUNCTION_VALUE_P (loc))
                   1629:        map->inline_target = reg_to_map;
                   1630:       else
                   1631:        map->reg_map[REGNO (loc)] = reg_to_map;
                   1632:     }
                   1633: 
                   1634:   /* Make new label equivalences for the labels in the called function.  */
                   1635:   for (i = min_labelno; i < max_labelno; i++)
                   1636:     map->label_map[i] = gen_label_rtx ();
                   1637: 
                   1638:   /* Perform postincrements before actually calling the function.  */
                   1639:   emit_queue ();
                   1640: 
                   1641:   /* Clean up stack so that variables might have smaller offsets.  */
                   1642:   do_pending_stack_adjust ();
                   1643: 
                   1644:   /* Save a copy of the location of const_equiv_map for mark_stores, called
                   1645:      via note_stores.  */
                   1646:   global_const_equiv_map = map->const_equiv_map;
1.1.1.6   root     1647:   global_const_equiv_map_size = map->const_equiv_map_size;
1.1       root     1648: 
1.1.1.8 ! root     1649:   /* If the called function does an alloca, save and restore the
        !          1650:      stack pointer around the call.  This saves stack space, but
        !          1651:      also is required if this inline is being done between two
        !          1652:      pushes.  */
        !          1653:   if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_ALLOCA)
        !          1654:     emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);
        !          1655: 
1.1       root     1656:   /* Now copy the insns one by one.  Do this in two passes, first the insns and
                   1657:      then their REG_NOTES, just like save_for_inline.  */
                   1658: 
                   1659:   /* This loop is very similar to the loop in copy_loop_body in unroll.c.  */
                   1660: 
                   1661:   for (insn = insns; insn; insn = NEXT_INSN (insn))
                   1662:     {
1.1.1.7   root     1663:       rtx copy, pattern, set;
1.1       root     1664: 
                   1665:       map->orig_asm_operands_vector = 0;
                   1666: 
                   1667:       switch (GET_CODE (insn))
                   1668:        {
                   1669:        case INSN:
                   1670:          pattern = PATTERN (insn);
1.1.1.7   root     1671:          set = single_set (insn);
1.1       root     1672:          copy = 0;
                   1673:          if (GET_CODE (pattern) == USE
                   1674:              && GET_CODE (XEXP (pattern, 0)) == REG
                   1675:              && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
                   1676:            /* The (USE (REG n)) at return from the function should
                   1677:               be ignored since we are changing (REG n) into
                   1678:               inline_target.  */
                   1679:            break;
                   1680: 
                   1681:          /* Ignore setting a function value that we don't want to use.  */
                   1682:          if (map->inline_target == 0
1.1.1.7   root     1683:              && set != 0
                   1684:              && GET_CODE (SET_DEST (set)) == REG
                   1685:              && REG_FUNCTION_VALUE_P (SET_DEST (set)))
1.1.1.3   root     1686:            {
1.1.1.7   root     1687:              if (volatile_refs_p (SET_SRC (set)))
1.1.1.3   root     1688:                {
1.1.1.7   root     1689:                  rtx new_set;
                   1690: 
1.1.1.3   root     1691:                  /* If we must not delete the source,
                   1692:                     load it into a new temporary.  */
                   1693:                  copy = emit_insn (copy_rtx_and_substitute (pattern, map));
1.1.1.7   root     1694: 
                   1695:                  new_set = single_set (copy);
                   1696:                  if (new_set == 0)
                   1697:                    abort ();
                   1698: 
                   1699:                  SET_DEST (new_set)
                   1700:                    = gen_reg_rtx (GET_MODE (SET_DEST (new_set)));
1.1.1.3   root     1701:                }
1.1.1.8 ! root     1702:              /* If the source and destination are the same and it
        !          1703:                 has a note on it, keep the insn.  */
        !          1704:              else if (rtx_equal_p (SET_DEST (set), SET_SRC (set))
        !          1705:                       && REG_NOTES (insn) != 0)
        !          1706:                copy = emit_insn (copy_rtx_and_substitute (pattern, map));
1.1.1.3   root     1707:              else
                   1708:                break;
                   1709:            }
1.1.1.7   root     1710: 
                   1711:          /* If this is setting the static chain rtx, omit it.  */
                   1712:          else if (static_chain_value != 0
                   1713:                   && set != 0
                   1714:                   && GET_CODE (SET_DEST (set)) == REG
                   1715:                   && rtx_equal_p (SET_DEST (set),
                   1716:                                   static_chain_incoming_rtx))
                   1717:            break;
                   1718: 
1.1.1.6   root     1719:          /* If this is setting the static chain pseudo, set it from
                   1720:             the value we want to give it instead.  */
                   1721:          else if (static_chain_value != 0
1.1.1.7   root     1722:                   && set != 0
                   1723:                   && rtx_equal_p (SET_SRC (set),
1.1.1.6   root     1724:                                   static_chain_incoming_rtx))
                   1725:            {
1.1.1.7   root     1726:              rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map);
1.1.1.6   root     1727: 
1.1.1.7   root     1728:              copy = emit_move_insn (newdest, static_chain_value);
1.1.1.6   root     1729:              static_chain_value = 0;
                   1730:            }
1.1.1.3   root     1731:          else
                   1732:            copy = emit_insn (copy_rtx_and_substitute (pattern, map));
1.1       root     1733:          /* REG_NOTES will be copied later.  */
                   1734: 
                   1735: #ifdef HAVE_cc0
                   1736:          /* If this insn is setting CC0, it may need to look at
                   1737:             the insn that uses CC0 to see what type of insn it is.
                   1738:             In that case, the call to recog via validate_change will
                   1739:             fail.  So don't substitute constants here.  Instead,
                   1740:             do it when we emit the following insn.
                   1741: 
                   1742:             For example, see the pyr.md file.  That machine has signed and
                   1743:             unsigned compares.  The compare patterns must check the
                   1744:             following branch insn to see which what kind of compare to
                   1745:             emit.
                   1746: 
                   1747:             If the previous insn set CC0, substitute constants on it as
                   1748:             well.  */
                   1749:          if (sets_cc0_p (PATTERN (copy)) != 0)
                   1750:            cc0_insn = copy;
                   1751:          else
                   1752:            {
                   1753:              if (cc0_insn)
                   1754:                try_constants (cc0_insn, map);
                   1755:              cc0_insn = 0;
                   1756:              try_constants (copy, map);
                   1757:            }
                   1758: #else
                   1759:          try_constants (copy, map);
                   1760: #endif
                   1761:          break;
                   1762: 
                   1763:        case JUMP_INSN:
                   1764:          if (GET_CODE (PATTERN (insn)) == RETURN)
                   1765:            {
                   1766:              if (local_return_label == 0)
                   1767:                local_return_label = gen_label_rtx ();
                   1768:              pattern = gen_jump (local_return_label);
                   1769:            }
                   1770:          else
                   1771:            pattern = copy_rtx_and_substitute (PATTERN (insn), map);
                   1772: 
                   1773:          copy = emit_jump_insn (pattern);
                   1774: 
                   1775: #ifdef HAVE_cc0
                   1776:          if (cc0_insn)
                   1777:            try_constants (cc0_insn, map);
                   1778:          cc0_insn = 0;
                   1779: #endif
                   1780:          try_constants (copy, map);
                   1781: 
                   1782:          /* If this used to be a conditional jump insn but whose branch
                   1783:             direction is now know, we must do something special.  */
                   1784:          if (condjump_p (insn) && ! simplejump_p (insn) && map->last_pc_value)
                   1785:            {
                   1786: #ifdef HAVE_cc0
                   1787:              /* The previous insn set cc0 for us.  So delete it.  */
                   1788:              delete_insn (PREV_INSN (copy));
                   1789: #endif
                   1790: 
                   1791:              /* If this is now a no-op, delete it.  */
                   1792:              if (map->last_pc_value == pc_rtx)
                   1793:                {
                   1794:                  delete_insn (copy);
                   1795:                  copy = 0;
                   1796:                }
                   1797:              else
                   1798:                /* Otherwise, this is unconditional jump so we must put a
                   1799:                   BARRIER after it.  We could do some dead code elimination
                   1800:                   here, but jump.c will do it just as well.  */
                   1801:                emit_barrier ();
                   1802:            }
                   1803:          break;
                   1804: 
                   1805:        case CALL_INSN:
                   1806:          pattern = copy_rtx_and_substitute (PATTERN (insn), map);
                   1807:          copy = emit_call_insn (pattern);
                   1808: 
1.1.1.7   root     1809:          /* Because the USAGE information potentially contains objects other
                   1810:             than hard registers, we need to copy it.  */
                   1811:          CALL_INSN_FUNCTION_USAGE (copy) =
                   1812:             copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn), map);
                   1813: 
1.1       root     1814: #ifdef HAVE_cc0
                   1815:          if (cc0_insn)
                   1816:            try_constants (cc0_insn, map);
                   1817:          cc0_insn = 0;
                   1818: #endif
                   1819:          try_constants (copy, map);
                   1820: 
                   1821:          /* Be lazy and assume CALL_INSNs clobber all hard registers.  */
                   1822:          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1823:            map->const_equiv_map[i] = 0;
                   1824:          break;
                   1825: 
                   1826:        case CODE_LABEL:
                   1827:          copy = emit_label (map->label_map[CODE_LABEL_NUMBER (insn)]);
1.1.1.3   root     1828:          LABEL_NAME (copy) = LABEL_NAME (insn);
1.1       root     1829:          map->const_age++;
                   1830:          break;
                   1831: 
                   1832:        case BARRIER:
                   1833:          copy = emit_barrier ();
                   1834:          break;
                   1835: 
                   1836:        case NOTE:
                   1837:          /* It is important to discard function-end and function-beg notes,
                   1838:             so we have only one of each in the current function.
                   1839:             Also, NOTE_INSN_DELETED notes aren't useful (save_for_inline
                   1840:             deleted these in the copy used for continuing compilation,
                   1841:             not the copy used for inlining).  */
                   1842:          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
                   1843:              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
                   1844:              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
                   1845:            copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
                   1846:          else
                   1847:            copy = 0;
                   1848:          break;
                   1849: 
                   1850:        default:
                   1851:          abort ();
                   1852:          break;
                   1853:        }
                   1854: 
                   1855:       if (copy)
                   1856:        RTX_INTEGRATED_P (copy) = 1;
                   1857: 
                   1858:       map->insn_map[INSN_UID (insn)] = copy;
                   1859:     }
                   1860: 
1.1.1.5   root     1861:   /* Now copy the REG_NOTES.  Increment const_age, so that only constants
                   1862:      from parameters can be substituted in.  These are the only ones that
                   1863:      are valid across the entire function.  */
                   1864:   map->const_age++;
1.1       root     1865:   for (insn = insns; insn; insn = NEXT_INSN (insn))
                   1866:     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
1.1.1.5   root     1867:        && map->insn_map[INSN_UID (insn)]
                   1868:        && REG_NOTES (insn))
                   1869:       {
                   1870:        rtx tem = copy_rtx_and_substitute (REG_NOTES (insn), map);
                   1871:        /* We must also do subst_constants, in case one of our parameters
                   1872:           has const type and constant value.  */
                   1873:        subst_constants (&tem, NULL_RTX, map);
                   1874:        apply_change_group ();
                   1875:        REG_NOTES (map->insn_map[INSN_UID (insn)]) = tem;
                   1876:       }
1.1       root     1877: 
                   1878:   if (local_return_label)
                   1879:     emit_label (local_return_label);
                   1880: 
1.1.1.8 ! root     1881:   /* Restore the stack pointer if we saved it above.  */
        !          1882:   if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_CALLS_ALLOCA)
        !          1883:     emit_stack_restore (SAVE_BLOCK, stack_save, NULL_RTX);
        !          1884: 
1.1       root     1885:   /* Make copies of the decls of the symbols in the inline function, so that
                   1886:      the copies of the variables get declared in the current function.  Set
                   1887:      up things so that lookup_static_chain knows that to interpret registers
                   1888:      in SAVE_EXPRs for TYPE_SIZEs as local.  */
                   1889: 
                   1890:   inline_function_decl = fndecl;
                   1891:   integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
1.1.1.4   root     1892:   integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map);
1.1       root     1893:   inline_function_decl = 0;
                   1894: 
1.1.1.4   root     1895:   /* End the scope containing the copied formal parameter variables
                   1896:      and copied LABEL_DECLs.  */
1.1       root     1897: 
                   1898:   expand_end_bindings (getdecls (), 1, 1);
1.1.1.4   root     1899:   block = poplevel (1, 1, 0);
                   1900:   BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL
                   1901:                                   ? fndecl : DECL_ABSTRACT_ORIGIN (fndecl));
1.1       root     1902:   poplevel (0, 0, 0);
                   1903:   emit_line_note (input_filename, lineno);
                   1904: 
                   1905:   if (structure_value_addr)
1.1.1.5   root     1906:     {
                   1907:       target = gen_rtx (MEM, TYPE_MODE (type),
                   1908:                        memory_address (TYPE_MODE (type), structure_value_addr));
                   1909:       MEM_IN_STRUCT_P (target) = 1;
                   1910:     }
1.1       root     1911:   return target;
                   1912: }
                   1913: 
                   1914: /* Given a chain of PARM_DECLs, ARGS, copy each decl into a VAR_DECL,
                   1915:    push all of those decls and give each one the corresponding home.  */
                   1916: 
                   1917: static void
                   1918: integrate_parm_decls (args, map, arg_vector)
                   1919:      tree args;
                   1920:      struct inline_remap *map;
                   1921:      rtvec arg_vector;
                   1922: {
                   1923:   register tree tail;
                   1924:   register int i;
                   1925: 
                   1926:   for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)
                   1927:     {
                   1928:       register tree decl = build_decl (VAR_DECL, DECL_NAME (tail),
                   1929:                                       TREE_TYPE (tail));
                   1930:       rtx new_decl_rtl
                   1931:        = copy_rtx_and_substitute (RTVEC_ELT (arg_vector, i), map);
                   1932: 
1.1.1.5   root     1933:       DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (tail);
                   1934:       /* We really should be setting DECL_INCOMING_RTL to something reasonable
                   1935:         here, but that's going to require some more work.  */
                   1936:       /* DECL_INCOMING_RTL (decl) = ?; */
1.1       root     1937:       /* These args would always appear unused, if not for this.  */
                   1938:       TREE_USED (decl) = 1;
                   1939:       /* Prevent warning for shadowing with these.  */
1.1.1.4   root     1940:       DECL_ABSTRACT_ORIGIN (decl) = tail;
1.1       root     1941:       pushdecl (decl);
                   1942:       /* Fully instantiate the address with the equivalent form so that the
                   1943:         debugging information contains the actual register, instead of the
                   1944:         virtual register.   Do this by not passing an insn to
                   1945:         subst_constants.  */
1.1.1.4   root     1946:       subst_constants (&new_decl_rtl, NULL_RTX, map);
1.1       root     1947:       apply_change_group ();
                   1948:       DECL_RTL (decl) = new_decl_rtl;
                   1949:     }
                   1950: }
                   1951: 
                   1952: /* Given a BLOCK node LET, push decls and levels so as to construct in the
                   1953:    current function a tree of contexts isomorphic to the one that is given.
                   1954: 
                   1955:    LEVEL indicates how far down into the BLOCK tree is the node we are
1.1.1.4   root     1956:    currently traversing.  It is always zero except for recursive calls.
1.1       root     1957: 
1.1.1.4   root     1958:    MAP, if nonzero, is a pointer to an inline_remap map which indicates how
1.1       root     1959:    registers used in the DECL_RTL field should be remapped.  If it is zero,
1.1.1.4   root     1960:    no mapping is necessary.  */
1.1       root     1961: 
                   1962: static void
1.1.1.4   root     1963: integrate_decl_tree (let, level, map)
1.1       root     1964:      tree let;
                   1965:      int level;
                   1966:      struct inline_remap *map;
                   1967: {
                   1968:   tree t, node;
                   1969: 
1.1.1.4   root     1970:   if (level > 0)
                   1971:     pushlevel (0);
1.1       root     1972:   
                   1973:   for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
                   1974:     {
1.1.1.7   root     1975:       tree d;
1.1.1.8 ! root     1976:       tree newd;
1.1.1.7   root     1977: 
                   1978:       push_obstacks_nochange ();
                   1979:       saveable_allocation ();
                   1980:       d = copy_node (t);
                   1981:       pop_obstacks ();
                   1982: 
1.1.1.4   root     1983:       if (DECL_RTL (t) != 0)
1.1       root     1984:        {
                   1985:          DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t), map);
                   1986:          /* Fully instantiate the address with the equivalent form so that the
                   1987:             debugging information contains the actual register, instead of the
                   1988:             virtual register.   Do this by not passing an insn to
                   1989:             subst_constants.  */
1.1.1.4   root     1990:          subst_constants (&DECL_RTL (d), NULL_RTX, map);
1.1       root     1991:          apply_change_group ();
                   1992:        }
                   1993:       /* These args would always appear unused, if not for this.  */
                   1994:       TREE_USED (d) = 1;
1.1.1.7   root     1995: 
                   1996:       if (DECL_LANG_SPECIFIC (d))
                   1997:        copy_lang_decl (d);
                   1998: 
1.1.1.8 ! root     1999:       /* Must set DECL_ABSTRACT_ORIGIN here for local variables, to ensure
        !          2000:         that we don't get -Wshadow warnings.  But don't set it here if
        !          2001:         pushdecl might return a duplicate decl, as that will result in
        !          2002:         incorrect DWARF debug info.  */
        !          2003:       if (! DECL_EXTERNAL (d) || ! TREE_PUBLIC (d))
        !          2004:        /* Prevent warning for shadowing with these.  */
        !          2005:        DECL_ABSTRACT_ORIGIN (d) = t;
        !          2006: 
        !          2007:       newd = pushdecl (d);
        !          2008: 
        !          2009:       /* If we didn't set DECL_ABSTRACT_ORIGIN above, then set it now.
        !          2010:         Simpler to just set it always rather than checking.
        !          2011:         If the decl we get back is the copy of 't' that we started with,
        !          2012:         then set the DECL_ABSTRACT_ORIGIN.  Otherwise, we must have a
        !          2013:         duplicate decl, and we got the older one back.  In that case, setting
        !          2014:         DECL_ABSTRACT_ORIGIN is not appropriate.  */
        !          2015:       if (newd == d)
        !          2016:        DECL_ABSTRACT_ORIGIN (d) = t;
1.1       root     2017:     }
                   2018: 
                   2019:   for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
1.1.1.4   root     2020:     integrate_decl_tree (t, level + 1, map);
1.1       root     2021: 
1.1.1.4   root     2022:   if (level > 0)
                   2023:     {
                   2024:       node = poplevel (1, 0, 0);
                   2025:       if (node)
                   2026:        {
                   2027:          TREE_USED (node) = TREE_USED (let);
                   2028:          BLOCK_ABSTRACT_ORIGIN (node) = let;
                   2029:        }
                   2030:     }
1.1       root     2031: }
                   2032: 
                   2033: /* Create a new copy of an rtx.
                   2034:    Recursively copies the operands of the rtx,
                   2035:    except for those few rtx codes that are sharable.
                   2036: 
                   2037:    We always return an rtx that is similar to that incoming rtx, with the
                   2038:    exception of possibly changing a REG to a SUBREG or vice versa.  No
                   2039:    rtl is ever emitted.
                   2040: 
                   2041:    Handle constants that need to be placed in the constant pool by
                   2042:    calling `force_const_mem'.  */
                   2043: 
                   2044: rtx
                   2045: copy_rtx_and_substitute (orig, map)
                   2046:      register rtx orig;
                   2047:      struct inline_remap *map;
                   2048: {
                   2049:   register rtx copy, temp;
                   2050:   register int i, j;
                   2051:   register RTX_CODE code;
                   2052:   register enum machine_mode mode;
                   2053:   register char *format_ptr;
                   2054:   int regno;
                   2055: 
                   2056:   if (orig == 0)
                   2057:     return 0;
                   2058: 
                   2059:   code = GET_CODE (orig);
                   2060:   mode = GET_MODE (orig);
                   2061: 
                   2062:   switch (code)
                   2063:     {
                   2064:     case REG:
                   2065:       /* If the stack pointer register shows up, it must be part of
                   2066:         stack-adjustments (*not* because we eliminated the frame pointer!).
                   2067:         Small hard registers are returned as-is.  Pseudo-registers
                   2068:         go through their `reg_map'.  */
                   2069:       regno = REGNO (orig);
                   2070:       if (regno <= LAST_VIRTUAL_REGISTER)
                   2071:        {
                   2072:          /* Some hard registers are also mapped,
                   2073:             but others are not translated.  */
                   2074:          if (map->reg_map[regno] != 0)
                   2075:            return map->reg_map[regno];
                   2076: 
                   2077:          /* If this is the virtual frame pointer, make space in current
                   2078:             function's stack frame for the stack frame of the inline function.
                   2079: 
                   2080:             Copy the address of this area into a pseudo.  Map
                   2081:             virtual_stack_vars_rtx to this pseudo and set up a constant
                   2082:             equivalence for it to be the address.  This will substitute the
                   2083:             address into insns where it can be substituted and use the new
                   2084:             pseudo where it can't.  */
                   2085:          if (regno == VIRTUAL_STACK_VARS_REGNUM)
                   2086:            {
                   2087:              rtx loc, seq;
                   2088:              int size = DECL_FRAME_SIZE (map->fndecl);
                   2089:              int rounded;
                   2090: 
                   2091:              start_sequence ();
                   2092:              loc = assign_stack_temp (BLKmode, size, 1);
                   2093:              loc = XEXP (loc, 0);
                   2094: #ifdef FRAME_GROWS_DOWNWARD
                   2095:              /* In this case, virtual_stack_vars_rtx points to one byte
                   2096:                 higher than the top of the frame area.  So compute the offset
                   2097:                 to one byte higher than our substitute frame.
                   2098:                 Keep the fake frame pointer aligned like a real one.  */
                   2099:              rounded = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT);
                   2100:              loc = plus_constant (loc, rounded);
                   2101: #endif
1.1.1.4   root     2102:              map->reg_map[regno] = temp
                   2103:                = force_reg (Pmode, force_operand (loc, NULL_RTX));
1.1.1.6   root     2104: 
                   2105:              if (REGNO (temp) < map->const_equiv_map_size)
                   2106:                {
                   2107:                  map->const_equiv_map[REGNO (temp)] = loc;
                   2108:                  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   2109:                }
1.1       root     2110: 
                   2111:              seq = gen_sequence ();
                   2112:              end_sequence ();
                   2113:              emit_insn_after (seq, map->insns_at_start);
1.1.1.2   root     2114:              return temp;
1.1       root     2115:            }
                   2116:          else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
                   2117:            {
                   2118:              /* Do the same for a block to contain any arguments referenced
                   2119:                 in memory. */
                   2120:              rtx loc, seq;
                   2121:              int size = FUNCTION_ARGS_SIZE (DECL_SAVED_INSNS (map->fndecl));
                   2122: 
                   2123:              start_sequence ();
                   2124:              loc = assign_stack_temp (BLKmode, size, 1);
                   2125:              loc = XEXP (loc, 0);
1.1.1.4   root     2126:              /* When arguments grow downward, the virtual incoming 
                   2127:                 args pointer points to the top of the argument block,
                   2128:                 so the remapped location better do the same. */
                   2129: #ifdef ARGS_GROW_DOWNWARD
                   2130:              loc = plus_constant (loc, size);
                   2131: #endif
                   2132:              map->reg_map[regno] = temp
                   2133:                = force_reg (Pmode, force_operand (loc, NULL_RTX));
1.1.1.6   root     2134: 
                   2135:              if (REGNO (temp) < map->const_equiv_map_size)
                   2136:                {
                   2137:                  map->const_equiv_map[REGNO (temp)] = loc;
                   2138:                  map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
                   2139:                }
1.1       root     2140: 
                   2141:              seq = gen_sequence ();
                   2142:              end_sequence ();
                   2143:              emit_insn_after (seq, map->insns_at_start);
1.1.1.2   root     2144:              return temp;
1.1       root     2145:            }
                   2146:          else if (REG_FUNCTION_VALUE_P (orig))
                   2147:            {
                   2148:              /* This is a reference to the function return value.  If
                   2149:                 the function doesn't have a return value, error.  If the
                   2150:                 mode doesn't agree, make a SUBREG.  */
                   2151:              if (map->inline_target == 0)
                   2152:                /* Must be unrolling loops or replicating code if we
                   2153:                   reach here, so return the register unchanged.  */
                   2154:                return orig;
                   2155:              else if (mode != GET_MODE (map->inline_target))
1.1.1.5   root     2156:                return gen_lowpart (mode, map->inline_target);
1.1       root     2157:              else
                   2158:                return map->inline_target;
                   2159:            }
                   2160:          return orig;
                   2161:        }
                   2162:       if (map->reg_map[regno] == NULL)
                   2163:        {
                   2164:          map->reg_map[regno] = gen_reg_rtx (mode);
                   2165:          REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
                   2166:          REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
                   2167:          RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
                   2168:          /* A reg with REG_FUNCTION_VALUE_P true will never reach here.  */
                   2169:        }
                   2170:       return map->reg_map[regno];
                   2171: 
                   2172:     case SUBREG:
                   2173:       copy = copy_rtx_and_substitute (SUBREG_REG (orig), map);
                   2174:       /* SUBREG is ordinary, but don't make nested SUBREGs.  */
                   2175:       if (GET_CODE (copy) == SUBREG)
                   2176:        return gen_rtx (SUBREG, GET_MODE (orig), SUBREG_REG (copy),
                   2177:                        SUBREG_WORD (orig) + SUBREG_WORD (copy));
1.1.1.6   root     2178:       else if (GET_CODE (copy) == CONCAT)
1.1.1.7   root     2179:        return (subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1));
1.1       root     2180:       else
                   2181:        return gen_rtx (SUBREG, GET_MODE (orig), copy,
                   2182:                        SUBREG_WORD (orig));
                   2183: 
                   2184:     case USE:
                   2185:     case CLOBBER:
                   2186:       /* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
1.1.1.5   root     2187:         to (use foo) if the original insn didn't have a subreg.
                   2188:         Removing the subreg distorts the VAX movstrhi pattern
                   2189:         by changing the mode of an operand.  */
1.1       root     2190:       copy = copy_rtx_and_substitute (XEXP (orig, 0), map);
1.1.1.5   root     2191:       if (GET_CODE (copy) == SUBREG && GET_CODE (XEXP (orig, 0)) != SUBREG)
1.1       root     2192:        copy = SUBREG_REG (copy);
                   2193:       return gen_rtx (code, VOIDmode, copy);
                   2194: 
                   2195:     case CODE_LABEL:
                   2196:       LABEL_PRESERVE_P (map->label_map[CODE_LABEL_NUMBER (orig)])
                   2197:        = LABEL_PRESERVE_P (orig);
                   2198:       return map->label_map[CODE_LABEL_NUMBER (orig)];
                   2199: 
                   2200:     case LABEL_REF:
1.1.1.6   root     2201:       copy = gen_rtx (LABEL_REF, mode,
                   2202:                      LABEL_REF_NONLOCAL_P (orig) ? XEXP (orig, 0)
                   2203:                      : map->label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]);
1.1       root     2204:       LABEL_OUTSIDE_LOOP_P (copy) = LABEL_OUTSIDE_LOOP_P (orig);
1.1.1.6   root     2205: 
                   2206:       /* The fact that this label was previously nonlocal does not mean
                   2207:         it still is, so we must check if it is within the range of
                   2208:         this function's labels.  */
                   2209:       LABEL_REF_NONLOCAL_P (copy)
                   2210:        = (LABEL_REF_NONLOCAL_P (orig)
                   2211:           && ! (CODE_LABEL_NUMBER (XEXP (copy, 0)) >= get_first_label_num ()
                   2212:                 && CODE_LABEL_NUMBER (XEXP (copy, 0)) < max_label_num ()));
                   2213: 
                   2214:       /* If we have made a nonlocal label local, it means that this
1.1.1.8 ! root     2215:         inlined call will be referring to our nonlocal goto handler.
1.1.1.6   root     2216:         So make sure we create one for this block; we normally would
                   2217:         not since this is not otherwise considered a "call".  */
                   2218:       if (LABEL_REF_NONLOCAL_P (orig) && ! LABEL_REF_NONLOCAL_P (copy))
                   2219:        function_call_count++;
                   2220: 
1.1       root     2221:       return copy;
                   2222: 
                   2223:     case PC:
                   2224:     case CC0:
                   2225:     case CONST_INT:
1.1.1.3   root     2226:       return orig;
                   2227: 
1.1       root     2228:     case SYMBOL_REF:
1.1.1.3   root     2229:       /* Symbols which represent the address of a label stored in the constant
                   2230:         pool must be modified to point to a constant pool entry for the
                   2231:         remapped label.  Otherwise, symbols are returned unchanged.  */
                   2232:       if (CONSTANT_POOL_ADDRESS_P (orig))
                   2233:        {
                   2234:          rtx constant = get_pool_constant (orig);
                   2235:          if (GET_CODE (constant) == LABEL_REF)
1.1.1.6   root     2236:            return XEXP (force_const_mem (Pmode, 
                   2237:                                          copy_rtx_and_substitute (constant,
                   2238:                                                                   map)),
                   2239:                         0);
1.1.1.3   root     2240:        }
1.1.1.6   root     2241: 
1.1       root     2242:       return orig;
                   2243: 
                   2244:     case CONST_DOUBLE:
                   2245:       /* We have to make a new copy of this CONST_DOUBLE because don't want
                   2246:         to use the old value of CONST_DOUBLE_MEM.  Also, this may be a
                   2247:         duplicate of a CONST_DOUBLE we have already seen.  */
                   2248:       if (GET_MODE_CLASS (GET_MODE (orig)) == MODE_FLOAT)
                   2249:        {
                   2250:          REAL_VALUE_TYPE d;
                   2251: 
                   2252:          REAL_VALUE_FROM_CONST_DOUBLE (d, orig);
1.1.1.7   root     2253:          return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (orig));
1.1       root     2254:        }
                   2255:       else
                   2256:        return immed_double_const (CONST_DOUBLE_LOW (orig),
                   2257:                                   CONST_DOUBLE_HIGH (orig), VOIDmode);
                   2258: 
                   2259:     case CONST:
                   2260:       /* Make new constant pool entry for a constant
                   2261:         that was in the pool of the inline function.  */
                   2262:       if (RTX_INTEGRATED_P (orig))
                   2263:        {
                   2264:          /* If this was an address of a constant pool entry that itself
                   2265:             had to be placed in the constant pool, it might not be a
                   2266:             valid address.  So the recursive call below might turn it
                   2267:             into a register.  In that case, it isn't a constant any
                   2268:             more, so return it.  This has the potential of changing a
                   2269:             MEM into a REG, but we'll assume that it safe.  */
                   2270:          temp = copy_rtx_and_substitute (XEXP (orig, 0), map);
                   2271:          if (! CONSTANT_P (temp))
                   2272:            return temp;
                   2273:          return validize_mem (force_const_mem (GET_MODE (orig), temp));
                   2274:        }
                   2275:       break;
                   2276: 
                   2277:     case ADDRESS:
                   2278:       /* If from constant pool address, make new constant pool entry and
                   2279:         return its address.  */
                   2280:       if (! RTX_INTEGRATED_P (orig))
                   2281:        abort ();
                   2282: 
                   2283:       temp = force_const_mem (GET_MODE (orig),
                   2284:                              copy_rtx_and_substitute (XEXP (orig, 0), map));
                   2285: 
                   2286: #if 0
                   2287:       /* Legitimizing the address here is incorrect.
                   2288: 
                   2289:         The only ADDRESS rtx's that can reach here are ones created by
1.1.1.8 ! root     2290:         save_constants.  Hence the operand of the ADDRESS is always valid
1.1       root     2291:         in this position of the instruction, since the original rtx without
1.1.1.8 ! root     2292:         the ADDRESS was valid.
1.1       root     2293: 
                   2294:         The reason we don't legitimize the address here is that on the
                   2295:         Sparc, the caller may have a (high ...) surrounding this ADDRESS.
                   2296:         This code forces the operand of the address to a register, which
                   2297:         fails because we can not take the HIGH part of a register.
                   2298: 
                   2299:         Also, change_address may create new registers.  These registers
                   2300:         will not have valid reg_map entries.  This can cause try_constants()
                   2301:         to fail because assumes that all registers in the rtx have valid
                   2302:         reg_map entries, and it may end up replacing one of these new
                   2303:         registers with junk. */
                   2304: 
                   2305:       if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
                   2306:        temp = change_address (temp, GET_MODE (temp), XEXP (temp, 0));
                   2307: #endif
                   2308: 
                   2309:       return XEXP (temp, 0);
                   2310: 
                   2311:     case ASM_OPERANDS:
                   2312:       /* If a single asm insn contains multiple output operands
                   2313:         then it contains multiple ASM_OPERANDS rtx's that share operand 3.
                   2314:         We must make sure that the copied insn continues to share it.  */
                   2315:       if (map->orig_asm_operands_vector == XVEC (orig, 3))
                   2316:        {
                   2317:          copy = rtx_alloc (ASM_OPERANDS);
1.1.1.6   root     2318:          copy->volatil = orig->volatil;
1.1       root     2319:          XSTR (copy, 0) = XSTR (orig, 0);
                   2320:          XSTR (copy, 1) = XSTR (orig, 1);
                   2321:          XINT (copy, 2) = XINT (orig, 2);
                   2322:          XVEC (copy, 3) = map->copy_asm_operands_vector;
                   2323:          XVEC (copy, 4) = map->copy_asm_constraints_vector;
                   2324:          XSTR (copy, 5) = XSTR (orig, 5);
                   2325:          XINT (copy, 6) = XINT (orig, 6);
                   2326:          return copy;
                   2327:        }
                   2328:       break;
                   2329: 
                   2330:     case CALL:
                   2331:       /* This is given special treatment because the first
                   2332:         operand of a CALL is a (MEM ...) which may get
                   2333:         forced into a register for cse.  This is undesirable
                   2334:         if function-address cse isn't wanted or if we won't do cse.  */
                   2335: #ifndef NO_FUNCTION_CSE
                   2336:       if (! (optimize && ! flag_no_function_cse))
                   2337: #endif
                   2338:        return gen_rtx (CALL, GET_MODE (orig),
                   2339:                        gen_rtx (MEM, GET_MODE (XEXP (orig, 0)),
                   2340:                                 copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0), map)),
                   2341:                        copy_rtx_and_substitute (XEXP (orig, 1), map));
                   2342:       break;
                   2343: 
                   2344: #if 0
                   2345:       /* Must be ifdefed out for loop unrolling to work.  */
                   2346:     case RETURN:
                   2347:       abort ();
                   2348: #endif
                   2349: 
                   2350:     case SET:
                   2351:       /* If this is setting fp or ap, it means that we have a nonlocal goto.
                   2352:         Don't alter that.
                   2353:         If the nonlocal goto is into the current function,
                   2354:         this will result in unnecessarily bad code, but should work.  */
                   2355:       if (SET_DEST (orig) == virtual_stack_vars_rtx
                   2356:          || SET_DEST (orig) == virtual_incoming_args_rtx)
                   2357:        return gen_rtx (SET, VOIDmode, SET_DEST (orig),
                   2358:                        copy_rtx_and_substitute (SET_SRC (orig), map));
                   2359:       break;
                   2360: 
                   2361:     case MEM:
                   2362:       copy = rtx_alloc (MEM);
                   2363:       PUT_MODE (copy, mode);
                   2364:       XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map);
                   2365:       MEM_IN_STRUCT_P (copy) = MEM_IN_STRUCT_P (orig);
                   2366:       MEM_VOLATILE_P (copy) = MEM_VOLATILE_P (orig);
1.1.1.5   root     2367: 
                   2368:       /* If doing function inlining, this MEM might not be const in the
                   2369:         function that it is being inlined into, and thus may not be
                   2370:         unchanging after function inlining.  Constant pool references are
                   2371:         handled elsewhere, so this doesn't lose RTX_UNCHANGING_P bits
                   2372:         for them.  */
                   2373:       if (! map->integrating)
                   2374:        RTX_UNCHANGING_P (copy) = RTX_UNCHANGING_P (orig);
                   2375: 
1.1       root     2376:       return copy;
                   2377:     }
                   2378: 
                   2379:   copy = rtx_alloc (code);
                   2380:   PUT_MODE (copy, mode);
                   2381:   copy->in_struct = orig->in_struct;
                   2382:   copy->volatil = orig->volatil;
                   2383:   copy->unchanging = orig->unchanging;
                   2384: 
                   2385:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
                   2386: 
                   2387:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
                   2388:     {
                   2389:       switch (*format_ptr++)
                   2390:        {
                   2391:        case '0':
                   2392:          break;
                   2393: 
                   2394:        case 'e':
                   2395:          XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i), map);
                   2396:          break;
                   2397: 
                   2398:        case 'u':
                   2399:          /* Change any references to old-insns to point to the
                   2400:             corresponding copied insns.  */
                   2401:          XEXP (copy, i) = map->insn_map[INSN_UID (XEXP (orig, i))];
                   2402:          break;
                   2403: 
                   2404:        case 'E':
                   2405:          XVEC (copy, i) = XVEC (orig, i);
                   2406:          if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
                   2407:            {
                   2408:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
                   2409:              for (j = 0; j < XVECLEN (copy, i); j++)
                   2410:                XVECEXP (copy, i, j)
                   2411:                  = copy_rtx_and_substitute (XVECEXP (orig, i, j), map);
                   2412:            }
                   2413:          break;
                   2414: 
1.1.1.4   root     2415:        case 'w':
                   2416:          XWINT (copy, i) = XWINT (orig, i);
                   2417:          break;
                   2418: 
1.1       root     2419:        case 'i':
                   2420:          XINT (copy, i) = XINT (orig, i);
                   2421:          break;
                   2422: 
                   2423:        case 's':
                   2424:          XSTR (copy, i) = XSTR (orig, i);
                   2425:          break;
                   2426: 
                   2427:        default:
                   2428:          abort ();
                   2429:        }
                   2430:     }
                   2431: 
                   2432:   if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
                   2433:     {
                   2434:       map->orig_asm_operands_vector = XVEC (orig, 3);
                   2435:       map->copy_asm_operands_vector = XVEC (copy, 3);
                   2436:       map->copy_asm_constraints_vector = XVEC (copy, 4);
                   2437:     }
                   2438: 
                   2439:   return copy;
                   2440: }
                   2441: 
                   2442: /* Substitute known constant values into INSN, if that is valid.  */
                   2443: 
                   2444: void
                   2445: try_constants (insn, map)
                   2446:      rtx insn;
                   2447:      struct inline_remap *map;
                   2448: {
                   2449:   int i;
                   2450: 
                   2451:   map->num_sets = 0;
                   2452:   subst_constants (&PATTERN (insn), insn, map);
                   2453: 
                   2454:   /* Apply the changes if they are valid; otherwise discard them.  */
                   2455:   apply_change_group ();
                   2456: 
                   2457:   /* Show we don't know the value of anything stored or clobbered.  */
                   2458:   note_stores (PATTERN (insn), mark_stores);
                   2459:   map->last_pc_value = 0;
                   2460: #ifdef HAVE_cc0
                   2461:   map->last_cc0_value = 0;
                   2462: #endif
                   2463: 
                   2464:   /* Set up any constant equivalences made in this insn.  */
                   2465:   for (i = 0; i < map->num_sets; i++)
                   2466:     {
                   2467:       if (GET_CODE (map->equiv_sets[i].dest) == REG)
                   2468:        {
                   2469:          int regno = REGNO (map->equiv_sets[i].dest);
                   2470: 
1.1.1.6   root     2471:          if (regno < map->const_equiv_map_size
                   2472:              && (map->const_equiv_map[regno] == 0
                   2473:                  /* Following clause is a hack to make case work where GNU C++
                   2474:                     reassigns a variable to make cse work right.  */
                   2475:                  || ! rtx_equal_p (map->const_equiv_map[regno],
                   2476:                                    map->equiv_sets[i].equiv)))
1.1       root     2477:            {
                   2478:              map->const_equiv_map[regno] = map->equiv_sets[i].equiv;
                   2479:              map->const_age_map[regno] = map->const_age;
                   2480:            }
                   2481:        }
                   2482:       else if (map->equiv_sets[i].dest == pc_rtx)
                   2483:        map->last_pc_value = map->equiv_sets[i].equiv;
                   2484: #ifdef HAVE_cc0
                   2485:       else if (map->equiv_sets[i].dest == cc0_rtx)
                   2486:        map->last_cc0_value = map->equiv_sets[i].equiv;
                   2487: #endif
                   2488:     }
                   2489: }
                   2490: 
                   2491: /* Substitute known constants for pseudo regs in the contents of LOC,
                   2492:    which are part of INSN.
1.1.1.2   root     2493:    If INSN is zero, the substitution should always be done (this is used to
1.1       root     2494:    update DECL_RTL).
                   2495:    These changes are taken out by try_constants if the result is not valid.
                   2496: 
                   2497:    Note that we are more concerned with determining when the result of a SET
                   2498:    is a constant, for further propagation, than actually inserting constants
                   2499:    into insns; cse will do the latter task better.
                   2500: 
                   2501:    This function is also used to adjust address of items previously addressed
                   2502:    via the virtual stack variable or virtual incoming arguments registers.  */
                   2503: 
                   2504: static void
                   2505: subst_constants (loc, insn, map)
                   2506:      rtx *loc;
                   2507:      rtx insn;
                   2508:      struct inline_remap *map;
                   2509: {
                   2510:   rtx x = *loc;
                   2511:   register int i;
                   2512:   register enum rtx_code code;
                   2513:   register char *format_ptr;
                   2514:   int num_changes = num_validated_changes ();
                   2515:   rtx new = 0;
                   2516:   enum machine_mode op0_mode;
                   2517: 
                   2518:   code = GET_CODE (x);
                   2519: 
                   2520:   switch (code)
                   2521:     {
                   2522:     case PC:
                   2523:     case CONST_INT:
                   2524:     case CONST_DOUBLE:
                   2525:     case SYMBOL_REF:
                   2526:     case CONST:
                   2527:     case LABEL_REF:
                   2528:     case ADDRESS:
                   2529:       return;
                   2530: 
                   2531: #ifdef HAVE_cc0
                   2532:     case CC0:
                   2533:       validate_change (insn, loc, map->last_cc0_value, 1);
                   2534:       return;
                   2535: #endif
                   2536: 
                   2537:     case USE:
                   2538:     case CLOBBER:
                   2539:       /* The only thing we can do with a USE or CLOBBER is possibly do
                   2540:         some substitutions in a MEM within it.  */
                   2541:       if (GET_CODE (XEXP (x, 0)) == MEM)
                   2542:        subst_constants (&XEXP (XEXP (x, 0), 0), insn, map);
                   2543:       return;
                   2544: 
                   2545:     case REG:
                   2546:       /* Substitute for parms and known constants.  Don't replace
                   2547:         hard regs used as user variables with constants.  */
                   2548:       {
                   2549:        int regno = REGNO (x);
                   2550: 
                   2551:        if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
                   2552:            && regno < map->const_equiv_map_size
                   2553:            && map->const_equiv_map[regno] != 0
                   2554:            && map->const_age_map[regno] >= map->const_age)
                   2555:          validate_change (insn, loc, map->const_equiv_map[regno], 1);
                   2556:        return;
                   2557:       }
                   2558: 
                   2559:     case SUBREG:
1.1.1.4   root     2560:       /* SUBREG applied to something other than a reg
                   2561:         should be treated as ordinary, since that must
                   2562:         be a special hack and we don't know how to treat it specially.
                   2563:         Consider for example mulsidi3 in m68k.md.
                   2564:         Ordinary SUBREG of a REG needs this special treatment.  */
                   2565:       if (GET_CODE (SUBREG_REG (x)) == REG)
                   2566:        {
                   2567:          rtx inner = SUBREG_REG (x);
                   2568:          rtx new = 0;
                   2569: 
                   2570:          /* We can't call subst_constants on &SUBREG_REG (x) because any
                   2571:             constant or SUBREG wouldn't be valid inside our SUBEG.  Instead,
                   2572:             see what is inside, try to form the new SUBREG and see if that is
                   2573:             valid.  We handle two cases: extracting a full word in an 
                   2574:             integral mode and extracting the low part.  */
                   2575:          subst_constants (&inner, NULL_RTX, map);
                   2576: 
                   2577:          if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
                   2578:              && GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
                   2579:              && GET_MODE (SUBREG_REG (x)) != VOIDmode)
                   2580:            new = operand_subword (inner, SUBREG_WORD (x), 0,
                   2581:                                   GET_MODE (SUBREG_REG (x)));
1.1       root     2582: 
1.1.1.4   root     2583:          if (new == 0 && subreg_lowpart_p (x))
                   2584:            new = gen_lowpart_common (GET_MODE (x), inner);
1.1       root     2585: 
1.1.1.4   root     2586:          if (new)
                   2587:            validate_change (insn, loc, new, 1);
1.1       root     2588: 
1.1.1.4   root     2589:          return;
                   2590:        }
                   2591:       break;
1.1       root     2592: 
                   2593:     case MEM:
                   2594:       subst_constants (&XEXP (x, 0), insn, map);
                   2595: 
                   2596:       /* If a memory address got spoiled, change it back.  */
                   2597:       if (insn != 0 && num_validated_changes () != num_changes
                   2598:          && !memory_address_p (GET_MODE (x), XEXP (x, 0)))
                   2599:        cancel_changes (num_changes);
                   2600:       return;
                   2601: 
                   2602:     case SET:
                   2603:       {
                   2604:        /* Substitute constants in our source, and in any arguments to a
                   2605:           complex (e..g, ZERO_EXTRACT) destination, but not in the destination
                   2606:           itself.  */
                   2607:        rtx *dest_loc = &SET_DEST (x);
                   2608:        rtx dest = *dest_loc;
                   2609:        rtx src, tem;
                   2610: 
                   2611:        subst_constants (&SET_SRC (x), insn, map);
                   2612:        src = SET_SRC (x);
                   2613: 
                   2614:        while (GET_CODE (*dest_loc) == ZERO_EXTRACT
1.1.1.4   root     2615:               /* By convention, we always use ZERO_EXTRACT in the dest.  */
                   2616: /*            || GET_CODE (*dest_loc) == SIGN_EXTRACT */
1.1       root     2617:               || GET_CODE (*dest_loc) == SUBREG
                   2618:               || GET_CODE (*dest_loc) == STRICT_LOW_PART)
                   2619:          {
                   2620:            if (GET_CODE (*dest_loc) == ZERO_EXTRACT)
                   2621:              {
                   2622:                subst_constants (&XEXP (*dest_loc, 1), insn, map);
                   2623:                subst_constants (&XEXP (*dest_loc, 2), insn, map);
                   2624:              }
                   2625:            dest_loc = &XEXP (*dest_loc, 0);
                   2626:          }
                   2627: 
1.1.1.4   root     2628:        /* Do substitute in the address of a destination in memory.  */
                   2629:        if (GET_CODE (*dest_loc) == MEM)
                   2630:          subst_constants (&XEXP (*dest_loc, 0), insn, map);
                   2631: 
1.1       root     2632:        /* Check for the case of DEST a SUBREG, both it and the underlying
                   2633:           register are less than one word, and the SUBREG has the wider mode.
                   2634:           In the case, we are really setting the underlying register to the
                   2635:           source converted to the mode of DEST.  So indicate that.  */
                   2636:        if (GET_CODE (dest) == SUBREG
                   2637:            && GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD
                   2638:            && GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) <= UNITS_PER_WORD
                   2639:            && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
                   2640:                      <= GET_MODE_SIZE (GET_MODE (dest)))
1.1.1.5   root     2641:            && (tem = gen_lowpart_if_possible (GET_MODE (SUBREG_REG (dest)),
                   2642:                                               src)))
1.1       root     2643:          src = tem, dest = SUBREG_REG (dest);
                   2644: 
                   2645:        /* If storing a recognizable value save it for later recording.  */
                   2646:        if ((map->num_sets < MAX_RECOG_OPERANDS)
                   2647:            && (CONSTANT_P (src)
1.1.1.7   root     2648:                || (GET_CODE (src) == REG
1.1.1.8 ! root     2649:                    && (REGNO (src) == VIRTUAL_INCOMING_ARGS_REGNUM
        !          2650:                        || REGNO (src) == VIRTUAL_STACK_VARS_REGNUM))
1.1       root     2651:                || (GET_CODE (src) == PLUS
                   2652:                    && GET_CODE (XEXP (src, 0)) == REG
1.1.1.8 ! root     2653:                    && (REGNO (XEXP (src, 0)) == VIRTUAL_INCOMING_ARGS_REGNUM
        !          2654:                        || REGNO (XEXP (src, 0)) == VIRTUAL_STACK_VARS_REGNUM)
1.1       root     2655:                    && CONSTANT_P (XEXP (src, 1)))
                   2656:                || GET_CODE (src) == COMPARE
                   2657: #ifdef HAVE_cc0
                   2658:                || dest == cc0_rtx
                   2659: #endif
                   2660:                || (dest == pc_rtx
                   2661:                    && (src == pc_rtx || GET_CODE (src) == RETURN
                   2662:                        || GET_CODE (src) == LABEL_REF))))
                   2663:          {
                   2664:            /* Normally, this copy won't do anything.  But, if SRC is a COMPARE
                   2665:               it will cause us to save the COMPARE with any constants
                   2666:               substituted, which is what we want for later.  */
                   2667:            map->equiv_sets[map->num_sets].equiv = copy_rtx (src);
                   2668:            map->equiv_sets[map->num_sets++].dest = dest;
                   2669:          }
                   2670: 
                   2671:        return;
                   2672:       }
                   2673:     }
                   2674: 
                   2675:   format_ptr = GET_RTX_FORMAT (code);
                   2676:   
                   2677:   /* If the first operand is an expression, save its mode for later.  */
                   2678:   if (*format_ptr == 'e')
                   2679:     op0_mode = GET_MODE (XEXP (x, 0));
                   2680: 
                   2681:   for (i = 0; i < GET_RTX_LENGTH (code); i++)
                   2682:     {
                   2683:       switch (*format_ptr++)
                   2684:        {
                   2685:        case '0':
                   2686:          break;
                   2687: 
                   2688:        case 'e':
                   2689:          if (XEXP (x, i))
                   2690:            subst_constants (&XEXP (x, i), insn, map);
                   2691:          break;
                   2692: 
                   2693:        case 'u':
                   2694:        case 'i':
                   2695:        case 's':
1.1.1.4   root     2696:        case 'w':
1.1       root     2697:          break;
                   2698: 
                   2699:        case 'E':
                   2700:          if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
                   2701:            {
                   2702:              int j;
                   2703:              for (j = 0; j < XVECLEN (x, i); j++)
                   2704:                subst_constants (&XVECEXP (x, i, j), insn, map);
                   2705:            }
                   2706:          break;
                   2707: 
                   2708:        default:
                   2709:          abort ();
                   2710:        }
                   2711:     }
                   2712: 
                   2713:   /* If this is a commutative operation, move a constant to the second
                   2714:      operand unless the second operand is already a CONST_INT.  */
                   2715:   if ((GET_RTX_CLASS (code) == 'c' || code == NE || code == EQ)
                   2716:       && CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
                   2717:     {
                   2718:       rtx tem = XEXP (x, 0);
                   2719:       validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
                   2720:       validate_change (insn, &XEXP (x, 1), tem, 1);
                   2721:     }
                   2722: 
                   2723:   /* Simplify the expression in case we put in some constants.  */
                   2724:   switch (GET_RTX_CLASS (code))
                   2725:     {
                   2726:     case '1':
                   2727:       new = simplify_unary_operation (code, GET_MODE (x),
                   2728:                                      XEXP (x, 0), op0_mode);
                   2729:       break;
                   2730: 
                   2731:     case '<':
                   2732:       {
                   2733:        enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
                   2734:        if (op_mode == VOIDmode)
                   2735:          op_mode = GET_MODE (XEXP (x, 1));
                   2736:        new = simplify_relational_operation (code, op_mode,
                   2737:                                             XEXP (x, 0), XEXP (x, 1));
1.1.1.4   root     2738: #ifdef FLOAT_STORE_FLAG_VALUE
                   2739:        if (new != 0 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
                   2740:          new = ((new == const0_rtx) ? CONST0_RTX (GET_MODE (x))
1.1.1.7   root     2741:                 : CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE,
                   2742:                                                 GET_MODE (x)));
1.1.1.4   root     2743: #endif
1.1       root     2744:        break;
                   2745:       }
                   2746: 
                   2747:     case '2':
                   2748:     case 'c':
                   2749:       new = simplify_binary_operation (code, GET_MODE (x),
                   2750:                                       XEXP (x, 0), XEXP (x, 1));
                   2751:       break;
                   2752: 
                   2753:     case 'b':
                   2754:     case '3':
                   2755:       new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
                   2756:                                        XEXP (x, 0), XEXP (x, 1), XEXP (x, 2));
                   2757:       break;
                   2758:     }
                   2759: 
                   2760:   if (new)
                   2761:     validate_change (insn, loc, new, 1);
                   2762: }
                   2763: 
                   2764: /* Show that register modified no longer contain known constants.  We are
                   2765:    called from note_stores with parts of the new insn.  */
                   2766: 
                   2767: void
                   2768: mark_stores (dest, x)
                   2769:      rtx dest;
                   2770:      rtx x;
                   2771: {
1.1.1.5   root     2772:   int regno = -1;
                   2773:   enum machine_mode mode;
                   2774: 
                   2775:   /* DEST is always the innermost thing set, except in the case of
                   2776:      SUBREGs of hard registers.  */
1.1       root     2777: 
                   2778:   if (GET_CODE (dest) == REG)
1.1.1.5   root     2779:     regno = REGNO (dest), mode = GET_MODE (dest);
                   2780:   else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
                   2781:     {
                   2782:       regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
                   2783:       mode = GET_MODE (SUBREG_REG (dest));
                   2784:     }
                   2785: 
                   2786:   if (regno >= 0)
                   2787:     {
                   2788:       int last_reg = (regno >= FIRST_PSEUDO_REGISTER ? regno
                   2789:                      : regno + HARD_REGNO_NREGS (regno, mode) - 1);
                   2790:       int i;
                   2791: 
                   2792:       for (i = regno; i <= last_reg; i++)
1.1.1.6   root     2793:        if (i < global_const_equiv_map_size)
                   2794:          global_const_equiv_map[i] = 0;
1.1.1.5   root     2795:     }
1.1       root     2796: }
                   2797: 
                   2798: /* If any CONST expressions with RTX_INTEGRATED_P are present in the rtx
                   2799:    pointed to by PX, they represent constants in the constant pool.
                   2800:    Replace these with a new memory reference obtained from force_const_mem.
                   2801:    Similarly, ADDRESS expressions with RTX_INTEGRATED_P represent the
                   2802:    address of a constant pool entry.  Replace them with the address of
                   2803:    a new constant pool entry obtained from force_const_mem.  */
                   2804: 
                   2805: static void
                   2806: restore_constants (px)
                   2807:      rtx *px;
                   2808: {
                   2809:   rtx x = *px;
                   2810:   int i, j;
                   2811:   char *fmt;
                   2812: 
                   2813:   if (x == 0)
                   2814:     return;
                   2815: 
                   2816:   if (GET_CODE (x) == CONST_DOUBLE)
                   2817:     {
                   2818:       /* We have to make a new CONST_DOUBLE to ensure that we account for
                   2819:         it correctly.  Using the old CONST_DOUBLE_MEM data is wrong.  */
                   2820:       if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
                   2821:        {
                   2822:          REAL_VALUE_TYPE d;
                   2823: 
                   2824:          REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1.1.1.7   root     2825:          *px = CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (x));
1.1       root     2826:        }
                   2827:       else
                   2828:        *px = immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
                   2829:                                  VOIDmode);
                   2830:     }
                   2831: 
                   2832:   else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == CONST)
                   2833:     {
                   2834:       restore_constants (&XEXP (x, 0));
                   2835:       *px = validize_mem (force_const_mem (GET_MODE (x), XEXP (x, 0)));
                   2836:     }
                   2837:   else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == SUBREG)
                   2838:     {
                   2839:       /* This must be (subreg/i:M1 (const/i:M2 ...) 0).  */
                   2840:       rtx new = XEXP (SUBREG_REG (x), 0);
                   2841: 
                   2842:       restore_constants (&new);
                   2843:       new = force_const_mem (GET_MODE (SUBREG_REG (x)), new);
                   2844:       PUT_MODE (new, GET_MODE (x));
                   2845:       *px = validize_mem (new);
                   2846:     }
                   2847:   else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == ADDRESS)
                   2848:     {
                   2849:       restore_constants (&XEXP (x, 0));
                   2850:       *px = XEXP (force_const_mem (GET_MODE (x), XEXP (x, 0)), 0);
                   2851:     }
                   2852:   else
                   2853:     {
                   2854:       fmt = GET_RTX_FORMAT (GET_CODE (x));
                   2855:       for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
                   2856:        {
                   2857:          switch (*fmt++)
                   2858:            {
                   2859:            case 'E':
                   2860:              for (j = 0; j < XVECLEN (x, i); j++)
                   2861:                restore_constants (&XVECEXP (x, i, j));
                   2862:              break;
                   2863: 
                   2864:            case 'e':
                   2865:              restore_constants (&XEXP (x, i));
                   2866:              break;
                   2867:            }
                   2868:        }
                   2869:     }
                   2870: }
                   2871: 
1.1.1.4   root     2872: /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
                   2873:    given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
                   2874:    that it points to the node itself, thus indicating that the node is its
                   2875:    own (abstract) origin.  Additionally, if the BLOCK_ABSTRACT_ORIGIN for
                   2876:    the given node is NULL, recursively descend the decl/block tree which
                   2877:    it is the root of, and for each other ..._DECL or BLOCK node contained
                   2878:    therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
                   2879:    still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
                   2880:    values to point to themselves.  */
                   2881: 
                   2882: static void
                   2883: set_block_origin_self (stmt)
                   2884:      register tree stmt;
                   2885: {
                   2886:   if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
                   2887:     {
                   2888:       BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
                   2889: 
                   2890:       {
                   2891:         register tree local_decl;
                   2892: 
                   2893:         for (local_decl = BLOCK_VARS (stmt);
                   2894:             local_decl != NULL_TREE;
                   2895:             local_decl = TREE_CHAIN (local_decl))
                   2896:           set_decl_origin_self (local_decl);   /* Potential recursion.  */
                   2897:       }
                   2898: 
                   2899:       {
                   2900:         register tree subblock;
                   2901: 
                   2902:         for (subblock = BLOCK_SUBBLOCKS (stmt);
                   2903:             subblock != NULL_TREE;
                   2904:             subblock = BLOCK_CHAIN (subblock))
                   2905:           set_block_origin_self (subblock);    /* Recurse.  */
                   2906:       }
                   2907:     }
                   2908: }
                   2909: 
                   2910: /* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
                   2911:    the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
                   2912:    node to so that it points to the node itself, thus indicating that the
                   2913:    node represents its own (abstract) origin.  Additionally, if the
                   2914:    DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
                   2915:    the decl/block tree of which the given node is the root of, and for
                   2916:    each other ..._DECL or BLOCK node contained therein whose
                   2917:    DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
                   2918:    set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
                   2919:    point to themselves.  */
                   2920: 
                   2921: static void
                   2922: set_decl_origin_self (decl)
                   2923:      register tree decl;
                   2924: {
                   2925:   if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
                   2926:     {
                   2927:       DECL_ABSTRACT_ORIGIN (decl) = decl;
                   2928:       if (TREE_CODE (decl) == FUNCTION_DECL)
                   2929:        {
                   2930:          register tree arg;
                   2931: 
                   2932:          for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
                   2933:            DECL_ABSTRACT_ORIGIN (arg) = arg;
1.1.1.8 ! root     2934:          if (DECL_INITIAL (decl) != NULL_TREE
        !          2935:              && DECL_INITIAL (decl) != error_mark_node)
1.1.1.4   root     2936:            set_block_origin_self (DECL_INITIAL (decl));
                   2937:        }
                   2938:     }
                   2939: }
                   2940: 
                   2941: /* Given a pointer to some BLOCK node, and a boolean value to set the
                   2942:    "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
                   2943:    the given block, and for all local decls and all local sub-blocks
                   2944:    (recursively) which are contained therein.  */
                   2945: 
                   2946: static void
                   2947: set_block_abstract_flags (stmt, setting)
                   2948:      register tree stmt;
                   2949:      register int setting;
                   2950: {
                   2951:   BLOCK_ABSTRACT (stmt) = setting;
                   2952: 
                   2953:   {
                   2954:     register tree local_decl;
                   2955: 
                   2956:     for (local_decl = BLOCK_VARS (stmt);
                   2957:         local_decl != NULL_TREE;
                   2958:         local_decl = TREE_CHAIN (local_decl))
                   2959:       set_decl_abstract_flags (local_decl, setting);
                   2960:   }
                   2961: 
                   2962:   {
                   2963:     register tree subblock;
                   2964: 
                   2965:     for (subblock = BLOCK_SUBBLOCKS (stmt);
                   2966:         subblock != NULL_TREE;
                   2967:         subblock = BLOCK_CHAIN (subblock))
                   2968:       set_block_abstract_flags (subblock, setting);
                   2969:   }
                   2970: }
                   2971: 
                   2972: /* Given a pointer to some ..._DECL node, and a boolean value to set the
                   2973:    "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
                   2974:    given decl, and (in the case where the decl is a FUNCTION_DECL) also
                   2975:    set the abstract flags for all of the parameters, local vars, local
                   2976:    blocks and sub-blocks (recursively) to the same setting.  */
                   2977: 
                   2978: void
                   2979: set_decl_abstract_flags (decl, setting)
                   2980:      register tree decl;
                   2981:      register int setting;
                   2982: {
                   2983:   DECL_ABSTRACT (decl) = setting;
                   2984:   if (TREE_CODE (decl) == FUNCTION_DECL)
                   2985:     {
                   2986:       register tree arg;
                   2987: 
                   2988:       for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
                   2989:        DECL_ABSTRACT (arg) = setting;
1.1.1.8 ! root     2990:       if (DECL_INITIAL (decl) != NULL_TREE
        !          2991:          && DECL_INITIAL (decl) != error_mark_node)
1.1.1.4   root     2992:        set_block_abstract_flags (DECL_INITIAL (decl), setting);
                   2993:     }
                   2994: }
                   2995: 
1.1       root     2996: /* Output the assembly language code for the function FNDECL
                   2997:    from its DECL_SAVED_INSNS.  Used for inline functions that are output
                   2998:    at end of compilation instead of where they came in the source.  */
                   2999: 
                   3000: void
                   3001: output_inline_function (fndecl)
                   3002:      tree fndecl;
                   3003: {
1.1.1.6   root     3004:   rtx head;
1.1       root     3005:   rtx last;
1.1.1.8 ! root     3006:   int save_flag_no_inline = flag_no_inline;
1.1       root     3007: 
1.1.1.6   root     3008:   if (output_bytecode)
                   3009:     {
                   3010:       warning ("`inline' ignored for bytecode output");
                   3011:       return;
                   3012:     }
1.1       root     3013: 
1.1.1.8 ! root     3014:   /* Things we allocate from here on are part of this function, not
        !          3015:      permanent.  */
        !          3016:   temporary_allocation ();
        !          3017: 
1.1.1.6   root     3018:   head = DECL_SAVED_INSNS (fndecl);
1.1       root     3019:   current_function_decl = fndecl;
                   3020: 
                   3021:   /* This call is only used to initialize global variables.  */
                   3022:   init_function_start (fndecl, "lossage", 1);
                   3023: 
                   3024:   /* Redo parameter determinations in case the FUNCTION_...
                   3025:      macros took machine-specific actions that need to be redone.  */
                   3026:   assign_parms (fndecl, 1);
                   3027: 
                   3028:   /* Set stack frame size.  */
                   3029:   assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl), 0);
                   3030: 
                   3031:   restore_reg_data (FIRST_PARM_INSN (head));
                   3032: 
                   3033:   stack_slot_list = STACK_SLOT_LIST (head);
1.1.1.8 ! root     3034:   forced_labels = FORCED_LABELS (head);
1.1       root     3035: 
                   3036:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_ALLOCA)
                   3037:     current_function_calls_alloca = 1;
                   3038: 
                   3039:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_SETJMP)
                   3040:     current_function_calls_setjmp = 1;
                   3041: 
                   3042:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_LONGJMP)
                   3043:     current_function_calls_longjmp = 1;
                   3044: 
                   3045:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_STRUCT)
                   3046:     current_function_returns_struct = 1;
                   3047: 
                   3048:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_PCC_STRUCT)
                   3049:     current_function_returns_pcc_struct = 1;
                   3050: 
                   3051:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_NEEDS_CONTEXT)
                   3052:     current_function_needs_context = 1;
                   3053: 
                   3054:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_HAS_NONLOCAL_LABEL)
                   3055:     current_function_has_nonlocal_label = 1;
                   3056: 
                   3057:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_POINTER)
                   3058:     current_function_returns_pointer = 1;
                   3059: 
                   3060:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_CONST_POOL)
                   3061:     current_function_uses_const_pool = 1;
                   3062: 
                   3063:   if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
                   3064:     current_function_uses_pic_offset_table = 1;
                   3065: 
                   3066:   current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (head);
                   3067:   current_function_pops_args = POPS_ARGS (head);
                   3068: 
1.1.1.8 ! root     3069:   /* This is the only thing the expand_function_end call that uses to be here
        !          3070:      actually does and that call can cause problems.  */
        !          3071:   immediate_size_expand--;
1.1       root     3072: 
                   3073:   /* Find last insn and rebuild the constant pool.  */
                   3074:   for (last = FIRST_PARM_INSN (head);
                   3075:        NEXT_INSN (last); last = NEXT_INSN (last))
                   3076:     {
                   3077:       if (GET_RTX_CLASS (GET_CODE (last)) == 'i')
                   3078:        {
                   3079:          restore_constants (&PATTERN (last));
                   3080:          restore_constants (&REG_NOTES (last));
                   3081:        }
                   3082:     }
                   3083: 
                   3084:   set_new_first_and_last_insn (FIRST_PARM_INSN (head), last);
                   3085:   set_new_first_and_last_label_num (FIRST_LABELNO (head), LAST_LABELNO (head));
                   3086: 
1.1.1.4   root     3087:   /* We must have already output DWARF debugging information for the
                   3088:      original (abstract) inline function declaration/definition, so
                   3089:      we want to make sure that the debugging information we generate
                   3090:      for this special instance of the inline function refers back to
                   3091:      the information we already generated.  To make sure that happens,
                   3092:      we simply have to set the DECL_ABSTRACT_ORIGIN for the function
                   3093:      node (and for all of the local ..._DECL nodes which are its children)
                   3094:      so that they all point to themselves.  */
                   3095: 
                   3096:   set_decl_origin_self (fndecl);
                   3097: 
1.1.1.7   root     3098:   /* We're not deferring this any longer.  */
                   3099:   DECL_DEFER_OUTPUT (fndecl) = 0;
                   3100: 
1.1.1.8 ! root     3101:   /* Integrating function calls isn't safe anymore, so turn on
        !          3102:      flag_no_inline.  */
        !          3103:   flag_no_inline = 1;
        !          3104: 
1.1       root     3105:   /* Compile this function all the way down to assembly code.  */
                   3106:   rest_of_compilation (fndecl);
                   3107: 
1.1.1.8 ! root     3108:   /* Reset flag_no_inline to its original value.  */
        !          3109:   flag_no_inline = save_flag_no_inline;
        !          3110: 
1.1       root     3111:   current_function_decl = 0;
                   3112: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.