Annotation of gcc/function.c, revision 1.1.1.7

1.1       root        1: /* Expands front end tree to back end RTL for GNU C-Compiler
1.1.1.7 ! root        2:    Copyright (C) 1987, 88, 89, 91, 92, 93, 1994 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: 
                     21: /* This file handles the generation of rtl code from tree structure
                     22:    at the level of the function as a whole.
                     23:    It creates the rtl expressions for parameters and auto variables
                     24:    and has full responsibility for allocating stack slots.
                     25: 
                     26:    `expand_function_start' is called at the beginning of a function,
                     27:    before the function body is parsed, and `expand_function_end' is
                     28:    called after parsing the body.
                     29: 
                     30:    Call `assign_stack_local' to allocate a stack slot for a local variable.
                     31:    This is usually done during the RTL generation for the function body,
                     32:    but it can also be done in the reload pass when a pseudo-register does
                     33:    not get a hard register.
                     34: 
                     35:    Call `put_var_into_stack' when you learn, belatedly, that a variable
                     36:    previously given a pseudo-register must in fact go in the stack.
                     37:    This function changes the DECL_RTL to be a stack slot instead of a reg
                     38:    then scans all the RTL instructions so far generated to correct them.  */
                     39: 
                     40: #include "config.h"
                     41: 
                     42: #include <stdio.h>
                     43: 
                     44: #include "rtl.h"
                     45: #include "tree.h"
                     46: #include "flags.h"
                     47: #include "function.h"
                     48: #include "insn-flags.h"
                     49: #include "expr.h"
                     50: #include "insn-codes.h"
                     51: #include "regs.h"
                     52: #include "hard-reg-set.h"
                     53: #include "insn-config.h"
                     54: #include "recog.h"
                     55: #include "output.h"
1.1.1.4   root       56: #include "basic-block.h"
1.1.1.6   root       57: #include "obstack.h"
                     58: #include "bytecode.h"
                     59: 
                     60: /* Some systems use __main in a way incompatible with its use in gcc, in these
                     61:    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
                     62:    give the same symbol without quotes for an alternative entry point.  You
                     63:    must define both, or niether. */
                     64: #ifndef NAME__MAIN
                     65: #define NAME__MAIN "__main"
                     66: #define SYMBOL__MAIN __main
                     67: #endif
1.1       root       68: 
                     69: /* Round a value to the lowest integer less than it that is a multiple of
                     70:    the required alignment.  Avoid using division in case the value is
                     71:    negative.  Assume the alignment is a power of two.  */
                     72: #define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
                     73: 
                     74: /* Similar, but round to the next highest integer that meets the
                     75:    alignment.  */
                     76: #define CEIL_ROUND(VALUE,ALIGN)        (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
                     77: 
                     78: /* NEED_SEPARATE_AP means that we cannot derive ap from the value of fp
                     79:    during rtl generation.  If they are different register numbers, this is
                     80:    always true.  It may also be true if
                     81:    FIRST_PARM_OFFSET - STARTING_FRAME_OFFSET is not a constant during rtl
                     82:    generation.  See fix_lexical_addr for details.  */
                     83: 
                     84: #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                     85: #define NEED_SEPARATE_AP
                     86: #endif
                     87: 
                     88: /* Number of bytes of args popped by function being compiled on its return.
                     89:    Zero if no bytes are to be popped.
                     90:    May affect compilation of return insn or of function epilogue.  */
                     91: 
                     92: int current_function_pops_args;
                     93: 
                     94: /* Nonzero if function being compiled needs to be given an address
                     95:    where the value should be stored.  */
                     96: 
                     97: int current_function_returns_struct;
                     98: 
                     99: /* Nonzero if function being compiled needs to
                    100:    return the address of where it has put a structure value.  */
                    101: 
                    102: int current_function_returns_pcc_struct;
                    103: 
                    104: /* Nonzero if function being compiled needs to be passed a static chain.  */
                    105: 
                    106: int current_function_needs_context;
                    107: 
                    108: /* Nonzero if function being compiled can call setjmp.  */
                    109: 
                    110: int current_function_calls_setjmp;
                    111: 
                    112: /* Nonzero if function being compiled can call longjmp.  */
                    113: 
                    114: int current_function_calls_longjmp;
                    115: 
                    116: /* Nonzero if function being compiled receives nonlocal gotos
                    117:    from nested functions.  */
                    118: 
                    119: int current_function_has_nonlocal_label;
                    120: 
1.1.1.6   root      121: /* Nonzero if function being compiled has nonlocal gotos to parent
                    122:    function.  */
                    123: 
                    124: int current_function_has_nonlocal_goto;
                    125: 
1.1       root      126: /* Nonzero if function being compiled contains nested functions.  */
                    127: 
                    128: int current_function_contains_functions;
                    129: 
                    130: /* Nonzero if function being compiled can call alloca,
                    131:    either as a subroutine or builtin.  */
                    132: 
                    133: int current_function_calls_alloca;
                    134: 
                    135: /* Nonzero if the current function returns a pointer type */
                    136: 
                    137: int current_function_returns_pointer;
                    138: 
                    139: /* If some insns can be deferred to the delay slots of the epilogue, the
                    140:    delay list for them is recorded here.  */
                    141: 
                    142: rtx current_function_epilogue_delay_list;
                    143: 
                    144: /* If function's args have a fixed size, this is that size, in bytes.
                    145:    Otherwise, it is -1.
                    146:    May affect compilation of return insn or of function epilogue.  */
                    147: 
                    148: int current_function_args_size;
                    149: 
                    150: /* # bytes the prologue should push and pretend that the caller pushed them.
                    151:    The prologue must do this, but only if parms can be passed in registers.  */
                    152: 
                    153: int current_function_pretend_args_size;
                    154: 
1.1.1.7 ! root      155: /* # of bytes of outgoing arguments.  If ACCUMULATE_OUTGOING_ARGS is
        !           156:    defined, the needed space is pushed by the prologue. */
1.1       root      157: 
                    158: int current_function_outgoing_args_size;
                    159: 
                    160: /* This is the offset from the arg pointer to the place where the first
                    161:    anonymous arg can be found, if there is one.  */
                    162: 
                    163: rtx current_function_arg_offset_rtx;
                    164: 
                    165: /* Nonzero if current function uses varargs.h or equivalent.
                    166:    Zero for functions that use stdarg.h.  */
                    167: 
                    168: int current_function_varargs;
                    169: 
                    170: /* Quantities of various kinds of registers
                    171:    used for the current function's args.  */
                    172: 
                    173: CUMULATIVE_ARGS current_function_args_info;
                    174: 
                    175: /* Name of function now being compiled.  */
                    176: 
                    177: char *current_function_name;
                    178: 
                    179: /* If non-zero, an RTL expression for that location at which the current
                    180:    function returns its result.  Always equal to
                    181:    DECL_RTL (DECL_RESULT (current_function_decl)), but provided
                    182:    independently of the tree structures.  */
                    183: 
                    184: rtx current_function_return_rtx;
                    185: 
                    186: /* Nonzero if the current function uses the constant pool.  */
                    187: 
                    188: int current_function_uses_const_pool;
                    189: 
                    190: /* Nonzero if the current function uses pic_offset_table_rtx.  */
                    191: int current_function_uses_pic_offset_table;
                    192: 
                    193: /* The arg pointer hard register, or the pseudo into which it was copied.  */
                    194: rtx current_function_internal_arg_pointer;
                    195: 
                    196: /* The FUNCTION_DECL for an inline function currently being expanded.  */
                    197: tree inline_function_decl;
                    198: 
                    199: /* Number of function calls seen so far in current function.  */
                    200: 
                    201: int function_call_count;
                    202: 
                    203: /* List (chain of TREE_LIST) of LABEL_DECLs for all nonlocal labels
                    204:    (labels to which there can be nonlocal gotos from nested functions)
                    205:    in this function.  */
                    206: 
                    207: tree nonlocal_labels;
                    208: 
                    209: /* RTX for stack slot that holds the current handler for nonlocal gotos.
                    210:    Zero when function does not have nonlocal labels.  */
                    211: 
                    212: rtx nonlocal_goto_handler_slot;
                    213: 
                    214: /* RTX for stack slot that holds the stack pointer value to restore
                    215:    for a nonlocal goto.
                    216:    Zero when function does not have nonlocal labels.  */
                    217: 
                    218: rtx nonlocal_goto_stack_level;
                    219: 
                    220: /* Label that will go on parm cleanup code, if any.
                    221:    Jumping to this label runs cleanup code for parameters, if
                    222:    such code must be run.  Following this code is the logical return label.  */
                    223: 
                    224: rtx cleanup_label;
                    225: 
                    226: /* Label that will go on function epilogue.
                    227:    Jumping to this label serves as a "return" instruction
                    228:    on machines which require execution of the epilogue on all returns.  */
                    229: 
                    230: rtx return_label;
                    231: 
                    232: /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
                    233:    So we can mark them all live at the end of the function, if nonopt.  */
                    234: rtx save_expr_regs;
                    235: 
                    236: /* List (chain of EXPR_LISTs) of all stack slots in this function.
                    237:    Made for the sake of unshare_all_rtl.  */
                    238: rtx stack_slot_list;
                    239: 
                    240: /* Chain of all RTL_EXPRs that have insns in them.  */
                    241: tree rtl_expr_chain;
                    242: 
                    243: /* Label to jump back to for tail recursion, or 0 if we have
                    244:    not yet needed one for this function.  */
                    245: rtx tail_recursion_label;
                    246: 
                    247: /* Place after which to insert the tail_recursion_label if we need one.  */
                    248: rtx tail_recursion_reentry;
                    249: 
                    250: /* Location at which to save the argument pointer if it will need to be
                    251:    referenced.  There are two cases where this is done: if nonlocal gotos
                    252:    exist, or if vars stored at an offset from the argument pointer will be
                    253:    needed by inner routines.  */
                    254: 
                    255: rtx arg_pointer_save_area;
                    256: 
                    257: /* Offset to end of allocated area of stack frame.
                    258:    If stack grows down, this is the address of the last stack slot allocated.
                    259:    If stack grows up, this is the address for the next slot.  */
                    260: int frame_offset;
                    261: 
                    262: /* List (chain of TREE_LISTs) of static chains for containing functions.
                    263:    Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
                    264:    in an RTL_EXPR in the TREE_VALUE.  */
                    265: static tree context_display;
                    266: 
                    267: /* List (chain of TREE_LISTs) of trampolines for nested functions.
                    268:    The trampoline sets up the static chain and jumps to the function.
                    269:    We supply the trampoline's address when the function's address is requested.
                    270: 
                    271:    Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
                    272:    in an RTL_EXPR in the TREE_VALUE.  */
                    273: static tree trampoline_list;
                    274: 
                    275: /* Insn after which register parms and SAVE_EXPRs are born, if nonopt.  */
                    276: static rtx parm_birth_insn;
                    277: 
                    278: #if 0
                    279: /* Nonzero if a stack slot has been generated whose address is not
                    280:    actually valid.  It means that the generated rtl must all be scanned
                    281:    to detect and correct the invalid addresses where they occur.  */
                    282: static int invalid_stack_slot;
                    283: #endif
                    284: 
                    285: /* Last insn of those whose job was to put parms into their nominal homes.  */
                    286: static rtx last_parm_insn;
                    287: 
                    288: /* 1 + last pseudo register number used for loading a copy
                    289:    of a parameter of this function.  */
                    290: static int max_parm_reg;
                    291: 
                    292: /* Vector indexed by REGNO, containing location on stack in which
                    293:    to put the parm which is nominally in pseudo register REGNO,
                    294:    if we discover that that parm must go in the stack.  */
                    295: static rtx *parm_reg_stack_loc;
                    296: 
                    297: #if 0  /* Turned off because 0 seems to work just as well.  */
                    298: /* Cleanup lists are required for binding levels regardless of whether
                    299:    that binding level has cleanups or not.  This node serves as the
                    300:    cleanup list whenever an empty list is required.  */
                    301: static tree empty_cleanup_list;
                    302: #endif
                    303: 
                    304: /* Nonzero once virtual register instantiation has been done.
                    305:    assign_stack_local uses frame_pointer_rtx when this is nonzero.  */
                    306: static int virtuals_instantiated;
                    307: 
1.1.1.6   root      308: /* These variables hold pointers to functions to
                    309:    save and restore machine-specific data,
                    310:    in push_function_context and pop_function_context.  */
                    311: void (*save_machine_status) ();
                    312: void (*restore_machine_status) ();
                    313: 
1.1       root      314: /* Nonzero if we need to distinguish between the return value of this function
                    315:    and the return value of a function called by this function.  This helps
                    316:    integrate.c  */
                    317: 
                    318: extern int rtx_equal_function_value_matters;
1.1.1.6   root      319: extern tree sequence_rtl_expr;
                    320: extern tree bc_runtime_type_code ();
                    321: extern rtx bc_build_calldesc ();
                    322: extern char *bc_emit_trampoline ();
                    323: extern char *bc_end_function ();
1.1       root      324: 
                    325: /* In order to evaluate some expressions, such as function calls returning
                    326:    structures in memory, we need to temporarily allocate stack locations.
                    327:    We record each allocated temporary in the following structure.
                    328: 
                    329:    Associated with each temporary slot is a nesting level.  When we pop up
                    330:    one level, all temporaries associated with the previous level are freed.
                    331:    Normally, all temporaries are freed after the execution of the statement
                    332:    in which they were created.  However, if we are inside a ({...}) grouping,
                    333:    the result may be in a temporary and hence must be preserved.  If the
                    334:    result could be in a temporary, we preserve it if we can determine which
                    335:    one it is in.  If we cannot determine which temporary may contain the
                    336:    result, all temporaries are preserved.  A temporary is preserved by
                    337:    pretending it was allocated at the previous nesting level.
                    338: 
                    339:    Automatic variables are also assigned temporary slots, at the nesting
                    340:    level where they are defined.  They are marked a "kept" so that
                    341:    free_temp_slots will not free them.  */
                    342: 
                    343: struct temp_slot
                    344: {
                    345:   /* Points to next temporary slot.  */
                    346:   struct temp_slot *next;
                    347:   /* The rtx to used to reference the slot. */
                    348:   rtx slot;
1.1.1.7 ! root      349:   /* The rtx used to represent the address if not the address of the
        !           350:      slot above.  May be an EXPR_LIST if multiple addresses exist.  */
        !           351:   rtx address;
1.1       root      352:   /* The size, in units, of the slot.  */
                    353:   int size;
1.1.1.6   root      354:   /* The value of `sequence_rtl_expr' when this temporary is allocated.  */
                    355:   tree rtl_expr;
1.1       root      356:   /* Non-zero if this temporary is currently in use.  */
                    357:   char in_use;
1.1.1.7 ! root      358:   /* Non-zero if this temporary has its address taken.  */
        !           359:   char addr_taken;
1.1       root      360:   /* Nesting level at which this slot is being used.  */
                    361:   int level;
                    362:   /* Non-zero if this should survive a call to free_temp_slots.  */
                    363:   int keep;
                    364: };
                    365: 
                    366: /* List of all temporaries allocated, both available and in use.  */
                    367: 
                    368: struct temp_slot *temp_slots;
                    369: 
                    370: /* Current nesting level for temporaries.  */
                    371: 
                    372: int temp_slot_level;
                    373: 
1.1.1.6   root      374: /* The FUNCTION_DECL node for the current function.  */
                    375: static tree this_function_decl;
                    376: 
                    377: /* Callinfo pointer for the current function.  */
                    378: static rtx this_function_callinfo;
                    379: 
                    380: /* The label in the bytecode file of this function's actual bytecode.
                    381:    Not an rtx.  */
                    382: static char *this_function_bytecode;
                    383: 
                    384: /* The call description vector for the current function.  */
                    385: static rtx this_function_calldesc;
                    386: 
                    387: /* Size of the local variables allocated for the current function.  */
                    388: int local_vars_size;
                    389: 
                    390: /* Current depth of the bytecode evaluation stack.  */
                    391: int stack_depth;
                    392: 
                    393: /* Maximum depth of the evaluation stack in this function.  */
                    394: int max_stack_depth;
                    395: 
                    396: /* Current depth in statement expressions.  */
                    397: static int stmt_expr_depth;
1.1.1.7 ! root      398: 
        !           399: /* This structure is used to record MEMs or pseudos used to replace VAR, any
        !           400:    SUBREGs of VAR, and any MEMs containing VAR as an address.  We need to
        !           401:    maintain this list in case two operands of an insn were required to match;
        !           402:    in that case we must ensure we use the same replacement.  */
        !           403: 
        !           404: struct fixup_replacement
        !           405: {
        !           406:   rtx old;
        !           407:   rtx new;
        !           408:   struct fixup_replacement *next;
        !           409: };
        !           410:    
        !           411: /* Forward declarations.  */
        !           412: 
        !           413: static struct temp_slot *find_temp_slot_from_address  PROTO((rtx));
        !           414: static void put_reg_into_stack PROTO((struct function *, rtx, tree,
        !           415:                                       enum machine_mode, enum machine_mode));
        !           416: static void fixup_var_refs     PROTO((rtx, enum machine_mode, int));
        !           417: static struct fixup_replacement
        !           418:   *find_fixup_replacement      PROTO((struct fixup_replacement **, rtx));
        !           419: static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,
        !           420:                                        rtx, int));
        !           421: static void fixup_var_refs_1   PROTO((rtx, enum machine_mode, rtx *, rtx,
        !           422:                                       struct fixup_replacement **));
        !           423: static rtx fixup_memory_subreg PROTO((rtx, rtx, int));
        !           424: static rtx walk_fixup_memory_subreg  PROTO((rtx, rtx, int));
        !           425: static rtx fixup_stack_1       PROTO((rtx, rtx));
        !           426: static void optimize_bit_field PROTO((rtx, rtx, rtx *));
        !           427: static void instantiate_decls  PROTO((tree, int));
        !           428: static void instantiate_decls_1        PROTO((tree, int));
        !           429: static void instantiate_decl   PROTO((rtx, int, int));
        !           430: static int instantiate_virtual_regs_1 PROTO((rtx *, rtx, int));
        !           431: static void delete_handlers    PROTO((void));
        !           432: static void pad_to_arg_alignment PROTO((struct args_size *, int));
        !           433: static void pad_below          PROTO((struct args_size *, enum  machine_mode,
        !           434:                                       tree));
        !           435: static tree round_down         PROTO((tree, int));
        !           436: static rtx round_trampoline_addr PROTO((rtx));
        !           437: static tree blocks_nreverse    PROTO((tree));
        !           438: static int all_blocks          PROTO((tree, tree *));
        !           439: static int *record_insns       PROTO((rtx));
        !           440: static int contains            PROTO((rtx, int *));
1.1.1.6   root      441: 
1.1       root      442: /* Pointer to chain of `struct function' for containing functions.  */
                    443: struct function *outer_function_chain;
                    444: 
                    445: /* Given a function decl for a containing function,
                    446:    return the `struct function' for it.  */
                    447: 
                    448: struct function *
                    449: find_function_data (decl)
                    450:      tree decl;
                    451: {
                    452:   struct function *p;
                    453:   for (p = outer_function_chain; p; p = p->next)
                    454:     if (p->decl == decl)
                    455:       return p;
                    456:   abort ();
                    457: }
                    458: 
                    459: /* Save the current context for compilation of a nested function.
                    460:    This is called from language-specific code.
                    461:    The caller is responsible for saving any language-specific status,
1.1.1.3   root      462:    since this function knows only about language-independent variables.  */
1.1       root      463: 
                    464: void
1.1.1.7 ! root      465: push_function_context_to (toplevel)
        !           466:      int toplevel;
1.1       root      467: {
                    468:   struct function *p = (struct function *) xmalloc (sizeof (struct function));
                    469: 
                    470:   p->next = outer_function_chain;
                    471:   outer_function_chain = p;
                    472: 
                    473:   p->name = current_function_name;
                    474:   p->decl = current_function_decl;
                    475:   p->pops_args = current_function_pops_args;
                    476:   p->returns_struct = current_function_returns_struct;
                    477:   p->returns_pcc_struct = current_function_returns_pcc_struct;
                    478:   p->needs_context = current_function_needs_context;
                    479:   p->calls_setjmp = current_function_calls_setjmp;
                    480:   p->calls_longjmp = current_function_calls_longjmp;
                    481:   p->calls_alloca = current_function_calls_alloca;
                    482:   p->has_nonlocal_label = current_function_has_nonlocal_label;
1.1.1.6   root      483:   p->has_nonlocal_goto = current_function_has_nonlocal_goto;
1.1       root      484:   p->args_size = current_function_args_size;
                    485:   p->pretend_args_size = current_function_pretend_args_size;
                    486:   p->arg_offset_rtx = current_function_arg_offset_rtx;
1.1.1.7 ! root      487:   p->varargs = current_function_varargs;
1.1       root      488:   p->uses_const_pool = current_function_uses_const_pool;
                    489:   p->uses_pic_offset_table = current_function_uses_pic_offset_table;
                    490:   p->internal_arg_pointer = current_function_internal_arg_pointer;
                    491:   p->max_parm_reg = max_parm_reg;
                    492:   p->parm_reg_stack_loc = parm_reg_stack_loc;
                    493:   p->outgoing_args_size = current_function_outgoing_args_size;
                    494:   p->return_rtx = current_function_return_rtx;
                    495:   p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;
                    496:   p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
                    497:   p->nonlocal_labels = nonlocal_labels;
                    498:   p->cleanup_label = cleanup_label;
                    499:   p->return_label = return_label;
                    500:   p->save_expr_regs = save_expr_regs;
                    501:   p->stack_slot_list = stack_slot_list;
                    502:   p->parm_birth_insn = parm_birth_insn;
                    503:   p->frame_offset = frame_offset;
                    504:   p->tail_recursion_label = tail_recursion_label;
                    505:   p->tail_recursion_reentry = tail_recursion_reentry;
                    506:   p->arg_pointer_save_area = arg_pointer_save_area;
                    507:   p->rtl_expr_chain = rtl_expr_chain;
                    508:   p->last_parm_insn = last_parm_insn;
                    509:   p->context_display = context_display;
                    510:   p->trampoline_list = trampoline_list;
                    511:   p->function_call_count = function_call_count;
                    512:   p->temp_slots = temp_slots;
                    513:   p->temp_slot_level = temp_slot_level;
                    514:   p->fixup_var_refs_queue = 0;
1.1.1.4   root      515:   p->epilogue_delay_list = current_function_epilogue_delay_list;
1.1       root      516: 
1.1.1.7 ! root      517:   save_tree_status (p, toplevel);
1.1       root      518:   save_storage_status (p);
                    519:   save_emit_status (p);
                    520:   init_emit ();
                    521:   save_expr_status (p);
                    522:   save_stmt_status (p);
1.1.1.4   root      523:   save_varasm_status (p);
1.1.1.6   root      524: 
                    525:   if (save_machine_status)
                    526:     (*save_machine_status) (p);
1.1       root      527: }
                    528: 
1.1.1.7 ! root      529: void
        !           530: push_function_context ()
        !           531: {
        !           532:   push_function_context_to (0);
        !           533: }
        !           534: 
1.1       root      535: /* Restore the last saved context, at the end of a nested function.
                    536:    This function is called from language-specific code.  */
                    537: 
                    538: void
1.1.1.7 ! root      539: pop_function_context_from (toplevel)
        !           540:      int toplevel;
1.1       root      541: {
                    542:   struct function *p = outer_function_chain;
                    543: 
                    544:   outer_function_chain = p->next;
                    545: 
                    546:   current_function_name = p->name;
                    547:   current_function_decl = p->decl;
                    548:   current_function_pops_args = p->pops_args;
                    549:   current_function_returns_struct = p->returns_struct;
                    550:   current_function_returns_pcc_struct = p->returns_pcc_struct;
                    551:   current_function_needs_context = p->needs_context;
                    552:   current_function_calls_setjmp = p->calls_setjmp;
                    553:   current_function_calls_longjmp = p->calls_longjmp;
                    554:   current_function_calls_alloca = p->calls_alloca;
                    555:   current_function_has_nonlocal_label = p->has_nonlocal_label;
1.1.1.6   root      556:   current_function_has_nonlocal_goto = p->has_nonlocal_goto;
1.1.1.7 ! root      557:   if (! toplevel)
        !           558:     current_function_contains_functions = 1;
1.1       root      559:   current_function_args_size = p->args_size;
                    560:   current_function_pretend_args_size = p->pretend_args_size;
                    561:   current_function_arg_offset_rtx = p->arg_offset_rtx;
1.1.1.7 ! root      562:   current_function_varargs = p->varargs;
1.1       root      563:   current_function_uses_const_pool = p->uses_const_pool;
                    564:   current_function_uses_pic_offset_table = p->uses_pic_offset_table;
                    565:   current_function_internal_arg_pointer = p->internal_arg_pointer;
                    566:   max_parm_reg = p->max_parm_reg;
                    567:   parm_reg_stack_loc = p->parm_reg_stack_loc;
                    568:   current_function_outgoing_args_size = p->outgoing_args_size;
                    569:   current_function_return_rtx = p->return_rtx;
                    570:   nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;
                    571:   nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
                    572:   nonlocal_labels = p->nonlocal_labels;
                    573:   cleanup_label = p->cleanup_label;
                    574:   return_label = p->return_label;
                    575:   save_expr_regs = p->save_expr_regs;
                    576:   stack_slot_list = p->stack_slot_list;
                    577:   parm_birth_insn = p->parm_birth_insn;
                    578:   frame_offset = p->frame_offset;
                    579:   tail_recursion_label = p->tail_recursion_label;
                    580:   tail_recursion_reentry = p->tail_recursion_reentry;
                    581:   arg_pointer_save_area = p->arg_pointer_save_area;
                    582:   rtl_expr_chain = p->rtl_expr_chain;
                    583:   last_parm_insn = p->last_parm_insn;
                    584:   context_display = p->context_display;
                    585:   trampoline_list = p->trampoline_list;
                    586:   function_call_count = p->function_call_count;
                    587:   temp_slots = p->temp_slots;
                    588:   temp_slot_level = p->temp_slot_level;
1.1.1.4   root      589:   current_function_epilogue_delay_list = p->epilogue_delay_list;
1.1.1.7 ! root      590:   reg_renumber = 0;
1.1       root      591: 
1.1.1.7 ! root      592:   restore_tree_status (p, toplevel);
1.1       root      593:   restore_storage_status (p);
                    594:   restore_expr_status (p);
                    595:   restore_emit_status (p);
                    596:   restore_stmt_status (p);
1.1.1.4   root      597:   restore_varasm_status (p);
1.1       root      598: 
1.1.1.6   root      599:   if (restore_machine_status)
                    600:     (*restore_machine_status) (p);
                    601: 
1.1       root      602:   /* Finish doing put_var_into_stack for any of our variables
                    603:      which became addressable during the nested function.  */
                    604:   {
                    605:     struct var_refs_queue *queue = p->fixup_var_refs_queue;
                    606:     for (; queue; queue = queue->next)
1.1.1.4   root      607:       fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
1.1       root      608:   }
                    609: 
                    610:   free (p);
                    611: 
                    612:   /* Reset variables that have known state during rtx generation.  */
                    613:   rtx_equal_function_value_matters = 1;
                    614:   virtuals_instantiated = 0;
                    615: }
1.1.1.7 ! root      616: 
        !           617: void pop_function_context ()
        !           618: {
        !           619:   pop_function_context_from (0);
        !           620: }
1.1       root      621: 
                    622: /* Allocate fixed slots in the stack frame of the current function.  */
                    623: 
                    624: /* Return size needed for stack frame based on slots so far allocated.
                    625:    This size counts from zero.  It is not rounded to STACK_BOUNDARY;
                    626:    the caller may have to do that.  */
                    627: 
                    628: int
                    629: get_frame_size ()
                    630: {
                    631: #ifdef FRAME_GROWS_DOWNWARD
                    632:   return -frame_offset;
                    633: #else
                    634:   return frame_offset;
                    635: #endif
                    636: }
                    637: 
                    638: /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
                    639:    with machine mode MODE.
                    640:    
                    641:    ALIGN controls the amount of alignment for the address of the slot:
                    642:    0 means according to MODE,
                    643:    -1 means use BIGGEST_ALIGNMENT and round size to multiple of that,
                    644:    positive specifies alignment boundary in bits.
                    645: 
                    646:    We do not round to stack_boundary here.  */
                    647: 
                    648: rtx
                    649: assign_stack_local (mode, size, align)
                    650:      enum machine_mode mode;
                    651:      int size;
                    652:      int align;
                    653: {
                    654:   register rtx x, addr;
                    655:   int bigend_correction = 0;
                    656:   int alignment;
                    657: 
                    658:   if (align == 0)
                    659:     {
                    660:       alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                    661:       if (mode == BLKmode)
                    662:        alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
                    663:     }
                    664:   else if (align == -1)
                    665:     {
                    666:       alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
                    667:       size = CEIL_ROUND (size, alignment);
                    668:     }
                    669:   else
                    670:     alignment = align / BITS_PER_UNIT;
                    671: 
                    672:   /* Round frame offset to that alignment.
                    673:      We must be careful here, since FRAME_OFFSET might be negative and
                    674:      division with a negative dividend isn't as well defined as we might
                    675:      like.  So we instead assume that ALIGNMENT is a power of two and
                    676:      use logical operations which are unambiguous.  */
                    677: #ifdef FRAME_GROWS_DOWNWARD
                    678:   frame_offset = FLOOR_ROUND (frame_offset, alignment);
                    679: #else
                    680:   frame_offset = CEIL_ROUND (frame_offset, alignment);
                    681: #endif
                    682: 
                    683:   /* On a big-endian machine, if we are allocating more space than we will use,
                    684:      use the least significant bytes of those that are allocated.  */
                    685: #if BYTES_BIG_ENDIAN
                    686:   if (mode != BLKmode)
                    687:     bigend_correction = size - GET_MODE_SIZE (mode);
                    688: #endif
                    689: 
                    690: #ifdef FRAME_GROWS_DOWNWARD
                    691:   frame_offset -= size;
                    692: #endif
                    693: 
                    694:   /* If we have already instantiated virtual registers, return the actual
                    695:      address relative to the frame pointer.  */
                    696:   if (virtuals_instantiated)
                    697:     addr = plus_constant (frame_pointer_rtx,
                    698:                          (frame_offset + bigend_correction
                    699:                           + STARTING_FRAME_OFFSET));
                    700:   else
                    701:     addr = plus_constant (virtual_stack_vars_rtx,
                    702:                          frame_offset + bigend_correction);
                    703: 
                    704: #ifndef FRAME_GROWS_DOWNWARD
                    705:   frame_offset += size;
                    706: #endif
                    707: 
                    708:   x = gen_rtx (MEM, mode, addr);
                    709: 
                    710:   stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, x, stack_slot_list);
                    711: 
                    712:   return x;
                    713: }
                    714: 
                    715: /* Assign a stack slot in a containing function.
                    716:    First three arguments are same as in preceding function.
                    717:    The last argument specifies the function to allocate in.  */
                    718: 
                    719: rtx
                    720: assign_outer_stack_local (mode, size, align, function)
                    721:      enum machine_mode mode;
                    722:      int size;
                    723:      int align;
                    724:      struct function *function;
                    725: {
                    726:   register rtx x, addr;
                    727:   int bigend_correction = 0;
                    728:   int alignment;
                    729: 
                    730:   /* Allocate in the memory associated with the function in whose frame
                    731:      we are assigning.  */
                    732:   push_obstacks (function->function_obstack,
                    733:                 function->function_maybepermanent_obstack);
                    734: 
                    735:   if (align == 0)
                    736:     {
                    737:       alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
                    738:       if (mode == BLKmode)
                    739:        alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
                    740:     }
                    741:   else if (align == -1)
                    742:     {
                    743:       alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
                    744:       size = CEIL_ROUND (size, alignment);
                    745:     }
                    746:   else
                    747:     alignment = align / BITS_PER_UNIT;
                    748: 
                    749:   /* Round frame offset to that alignment.  */
                    750: #ifdef FRAME_GROWS_DOWNWARD
1.1.1.4   root      751:   function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment);
1.1       root      752: #else
1.1.1.4   root      753:   function->frame_offset = CEIL_ROUND (function->frame_offset, alignment);
1.1       root      754: #endif
                    755: 
                    756:   /* On a big-endian machine, if we are allocating more space than we will use,
                    757:      use the least significant bytes of those that are allocated.  */
                    758: #if BYTES_BIG_ENDIAN
                    759:   if (mode != BLKmode)
                    760:     bigend_correction = size - GET_MODE_SIZE (mode);
                    761: #endif
                    762: 
                    763: #ifdef FRAME_GROWS_DOWNWARD
                    764:   function->frame_offset -= size;
                    765: #endif
                    766:   addr = plus_constant (virtual_stack_vars_rtx,
                    767:                        function->frame_offset + bigend_correction);
                    768: #ifndef FRAME_GROWS_DOWNWARD
                    769:   function->frame_offset += size;
                    770: #endif
                    771: 
                    772:   x = gen_rtx (MEM, mode, addr);
                    773: 
                    774:   function->stack_slot_list
                    775:     = gen_rtx (EXPR_LIST, VOIDmode, x, function->stack_slot_list);
                    776: 
                    777:   pop_obstacks ();
                    778: 
                    779:   return x;
                    780: }
                    781: 
                    782: /* Allocate a temporary stack slot and record it for possible later
                    783:    reuse.
                    784: 
                    785:    MODE is the machine mode to be given to the returned rtx.
                    786: 
                    787:    SIZE is the size in units of the space required.  We do no rounding here
                    788:    since assign_stack_local will do any required rounding.
                    789: 
1.1.1.7 ! root      790:    KEEP is 1 if this slot is to be retained after a call to
        !           791:    free_temp_slots.  Automatic variables for a block are allocated
        !           792:    with this flag.  KEEP is 2, if we allocate a longer term temporary,
        !           793:    whose lifetime is controlled by CLEANUP_POINT_EXPRs.  */
1.1       root      794: 
                    795: rtx
                    796: assign_stack_temp (mode, size, keep)
                    797:      enum machine_mode mode;
                    798:      int size;
                    799:      int keep;
                    800: {
                    801:   struct temp_slot *p, *best_p = 0;
                    802: 
1.1.1.7 ! root      803:   /* If SIZE is -1 it means that somebody tried to allocate a temporary
        !           804:      of a variable size.  */
        !           805:   if (size == -1)
        !           806:     abort ();
        !           807: 
1.1       root      808:   /* First try to find an available, already-allocated temporary that is the
                    809:      exact size we require.  */
                    810:   for (p = temp_slots; p; p = p->next)
                    811:     if (p->size == size && GET_MODE (p->slot) == mode && ! p->in_use)
                    812:       break;
                    813: 
                    814:   /* If we didn't find, one, try one that is larger than what we want.  We
                    815:      find the smallest such.  */
                    816:   if (p == 0)
                    817:     for (p = temp_slots; p; p = p->next)
                    818:       if (p->size > size && GET_MODE (p->slot) == mode && ! p->in_use
                    819:          && (best_p == 0 || best_p->size > p->size))
                    820:        best_p = p;
                    821: 
                    822:   /* Make our best, if any, the one to use.  */
                    823:   if (best_p)
1.1.1.6   root      824:     {
                    825:       /* If there are enough aligned bytes left over, make them into a new
                    826:         temp_slot so that the extra bytes don't get wasted.  Do this only
                    827:         for BLKmode slots, so that we can be sure of the alignment.  */
                    828:       if (GET_MODE (best_p->slot) == BLKmode)
                    829:        {
                    830:          int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
                    831:          int rounded_size = CEIL_ROUND (size, alignment);
                    832: 
                    833:          if (best_p->size - rounded_size >= alignment)
                    834:            {
                    835:              p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
1.1.1.7 ! root      836:              p->in_use = p->addr_taken = 0;
1.1.1.6   root      837:              p->size = best_p->size - rounded_size;
                    838:              p->slot = gen_rtx (MEM, BLKmode,
                    839:                                 plus_constant (XEXP (best_p->slot, 0),
                    840:                                                rounded_size));
1.1.1.7 ! root      841:              p->address = 0;
        !           842:              p->rtl_expr = 0;
1.1.1.6   root      843:              p->next = temp_slots;
                    844:              temp_slots = p;
                    845: 
                    846:              stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, p->slot,
                    847:                                         stack_slot_list);
                    848: 
                    849:              best_p->size = rounded_size;
                    850:            }
                    851:        }
                    852: 
                    853:       p = best_p;
                    854:     }
                    855:              
1.1       root      856:   /* If we still didn't find one, make a new temporary.  */
                    857:   if (p == 0)
                    858:     {
                    859:       p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
                    860:       p->size = size;
                    861:       /* If the temp slot mode doesn't indicate the alignment,
                    862:         use the largest possible, so no one will be disappointed.  */
1.1.1.7 ! root      863:       p->slot = assign_stack_local (mode, size, mode == BLKmode ? -1 : 0);
        !           864:       p->address = 0;
1.1       root      865:       p->next = temp_slots;
                    866:       temp_slots = p;
                    867:     }
                    868: 
                    869:   p->in_use = 1;
1.1.1.7 ! root      870:   p->addr_taken = 0;
1.1.1.6   root      871:   p->rtl_expr = sequence_rtl_expr;
1.1.1.7 ! root      872: 
        !           873:   if (keep == 2)
        !           874:     {
        !           875:       p->level = target_temp_slot_level;
        !           876:       p->keep = 0;
        !           877:     }
        !           878:   else
        !           879:     {
        !           880:       p->level = temp_slot_level;
        !           881:       p->keep = keep;
        !           882:     }
1.1       root      883:   return p->slot;
                    884: }
1.1.1.6   root      885: 
                    886: /* Combine temporary stack slots which are adjacent on the stack.
                    887: 
                    888:    This allows for better use of already allocated stack space.  This is only
                    889:    done for BLKmode slots because we can be sure that we won't have alignment
                    890:    problems in this case.  */
                    891: 
                    892: void
                    893: combine_temp_slots ()
                    894: {
                    895:   struct temp_slot *p, *q;
                    896:   struct temp_slot *prev_p, *prev_q;
                    897:   /* Determine where to free back to after this function.  */
                    898:   rtx free_pointer = rtx_alloc (CONST_INT);
                    899: 
                    900:   for (p = temp_slots, prev_p = 0; p; p = prev_p ? prev_p->next : temp_slots)
                    901:     {
                    902:       int delete_p = 0;
                    903:       if (! p->in_use && GET_MODE (p->slot) == BLKmode)
                    904:        for (q = p->next, prev_q = p; q; q = prev_q->next)
                    905:          {
                    906:            int delete_q = 0;
                    907:            if (! q->in_use && GET_MODE (q->slot) == BLKmode)
                    908:              {
                    909:                if (rtx_equal_p (plus_constant (XEXP (p->slot, 0), p->size),
                    910:                                 XEXP (q->slot, 0)))
                    911:                  {
                    912:                    /* Q comes after P; combine Q into P.  */
                    913:                    p->size += q->size;
                    914:                    delete_q = 1;
                    915:                  }
                    916:                else if (rtx_equal_p (plus_constant (XEXP (q->slot, 0), q->size),
                    917:                                      XEXP (p->slot, 0)))
                    918:                  {
                    919:                    /* P comes after Q; combine P into Q.  */
                    920:                    q->size += p->size;
                    921:                    delete_p = 1;
                    922:                    break;
                    923:                  }
                    924:              }
                    925:            /* Either delete Q or advance past it.  */
                    926:            if (delete_q)
                    927:              prev_q->next = q->next;
                    928:            else
                    929:              prev_q = q;
                    930:          }
                    931:       /* Either delete P or advance past it.  */
                    932:       if (delete_p)
                    933:        {
                    934:          if (prev_p)
                    935:            prev_p->next = p->next;
                    936:          else
                    937:            temp_slots = p->next;
                    938:        }
                    939:       else
                    940:        prev_p = p;
                    941:     }
                    942: 
                    943:   /* Free all the RTL made by plus_constant.  */ 
                    944:   rtx_free (free_pointer);
                    945: }
1.1       root      946: 
1.1.1.7 ! root      947: /* Find the temp slot corresponding to the object at address X.  */
        !           948: 
        !           949: static struct temp_slot *
        !           950: find_temp_slot_from_address (x)
        !           951:      rtx x;
        !           952: {
        !           953:   struct temp_slot *p;
        !           954:   rtx next;
        !           955: 
        !           956:   for (p = temp_slots; p; p = p->next)
        !           957:     {
        !           958:       if (! p->in_use)
        !           959:        continue;
        !           960:       else if (XEXP (p->slot, 0) == x
        !           961:               || p->address == x)
        !           962:        return p;
        !           963: 
        !           964:       else if (p->address != 0 && GET_CODE (p->address) == EXPR_LIST)
        !           965:        for (next = p->address; next; next = XEXP (next, 1))
        !           966:          if (XEXP (next, 0) == x)
        !           967:            return p;
        !           968:     }
        !           969: 
        !           970:   return 0;
        !           971: }
        !           972:       
        !           973: /* Indicate that NEW is an alternate way of refering to the temp slot
        !           974:    that previous was known by OLD.  */
        !           975: 
        !           976: void
        !           977: update_temp_slot_address (old, new)
        !           978:      rtx old, new;
        !           979: {
        !           980:   struct temp_slot *p = find_temp_slot_from_address (old);
        !           981: 
        !           982:   /* If none, return.  Else add NEW as an alias.  */
        !           983:   if (p == 0)
        !           984:     return;
        !           985:   else if (p->address == 0)
        !           986:     p->address = new;
        !           987:   else
        !           988:     {
        !           989:       if (GET_CODE (p->address) != EXPR_LIST)
        !           990:        p->address = gen_rtx (EXPR_LIST, VOIDmode, p->address, NULL_RTX);
        !           991: 
        !           992:       p->address = gen_rtx (EXPR_LIST, VOIDmode, new, p->address);
        !           993:     }
        !           994: }
        !           995: 
        !           996: /* If X could be a reference to a temporary slot, mark the fact that its
        !           997:    adddress was taken.  */
        !           998: 
        !           999: void
        !          1000: mark_temp_addr_taken (x)
        !          1001:      rtx x;
        !          1002: {
        !          1003:   struct temp_slot *p;
        !          1004: 
        !          1005:   if (x == 0)
        !          1006:     return;
        !          1007: 
        !          1008:   /* If X is not in memory or is at a constant address, it cannot be in
        !          1009:      a temporary slot.  */
        !          1010:   if (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
        !          1011:     return;
        !          1012: 
        !          1013:   p = find_temp_slot_from_address (XEXP (x, 0));
        !          1014:   if (p != 0)
        !          1015:     p->addr_taken = 1;
        !          1016: }
        !          1017: 
1.1       root     1018: /* If X could be a reference to a temporary slot, mark that slot as belonging
                   1019:    to the to one level higher.  If X matched one of our slots, just mark that
                   1020:    one.  Otherwise, we can't easily predict which it is, so upgrade all of
                   1021:    them.  Kept slots need not be touched.
                   1022: 
                   1023:    This is called when an ({...}) construct occurs and a statement
                   1024:    returns a value in memory.  */
                   1025: 
                   1026: void
                   1027: preserve_temp_slots (x)
                   1028:      rtx x;
                   1029: {
1.1.1.7 ! root     1030:   struct temp_slot *p = 0;
        !          1031: 
        !          1032:   /* If there is no result, we still might have some objects whose address
        !          1033:      were taken, so we need to make sure they stay around.  */
        !          1034:   if (x == 0)
        !          1035:     {
        !          1036:       for (p = temp_slots; p; p = p->next)
        !          1037:        if (p->in_use && p->level == temp_slot_level && p->addr_taken)
        !          1038:          p->level--;
        !          1039: 
        !          1040:       return;
        !          1041:     }
        !          1042: 
        !          1043:   /* If X is a register that is being used as a pointer, see if we have
        !          1044:      a temporary slot we know it points to.  To be consistent with
        !          1045:      the code below, we really should preserve all non-kept slots
        !          1046:      if we can't find a match, but that seems to be much too costly.  */
        !          1047:   if (GET_CODE (x) == REG && REGNO_POINTER_FLAG (REGNO (x)))
        !          1048:     p = find_temp_slot_from_address (x);
1.1       root     1049: 
                   1050:   /* If X is not in memory or is at a constant address, it cannot be in
1.1.1.7 ! root     1051:      a temporary slot, but it can contain something whose address was
        !          1052:      taken.  */
        !          1053:   if (p == 0 && (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0))))
        !          1054:     {
        !          1055:       for (p = temp_slots; p; p = p->next)
        !          1056:        if (p->in_use && p->level == temp_slot_level && p->addr_taken)
        !          1057:          p->level--;
        !          1058: 
        !          1059:       return;
        !          1060:     }
1.1       root     1061: 
                   1062:   /* First see if we can find a match.  */
1.1.1.7 ! root     1063:   if (p == 0)
        !          1064:     p = find_temp_slot_from_address (XEXP (x, 0));
        !          1065: 
        !          1066:   if (p != 0)
        !          1067:     {
        !          1068:       /* Move everything at our level whose address was taken to our new
        !          1069:         level in case we used its address.  */
        !          1070:       struct temp_slot *q;
        !          1071: 
        !          1072:       for (q = temp_slots; q; q = q->next)
        !          1073:        if (q != p && q->addr_taken && q->level == p->level)
        !          1074:          q->level--;
        !          1075: 
        !          1076:       p->level--;
        !          1077:       return;
        !          1078:     }
1.1       root     1079: 
                   1080:   /* Otherwise, preserve all non-kept slots at this level.  */
                   1081:   for (p = temp_slots; p; p = p->next)
                   1082:     if (p->in_use && p->level == temp_slot_level && ! p->keep)
                   1083:       p->level--;
                   1084: }
                   1085: 
1.1.1.6   root     1086: /* X is the result of an RTL_EXPR.  If it is a temporary slot associated
                   1087:    with that RTL_EXPR, promote it into a temporary slot at the present
                   1088:    level so it will not be freed when we free slots made in the
                   1089:    RTL_EXPR.  */
                   1090: 
                   1091: void
                   1092: preserve_rtl_expr_result (x)
                   1093:      rtx x;
                   1094: {
                   1095:   struct temp_slot *p;
                   1096: 
                   1097:   /* If X is not in memory or is at a constant address, it cannot be in
                   1098:      a temporary slot.  */
                   1099:   if (x == 0 || GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
                   1100:     return;
                   1101: 
1.1.1.7 ! root     1102:   /* If we can find a match, move it to our level unless it is already at
        !          1103:      an upper level.  */
        !          1104:   p = find_temp_slot_from_address (XEXP (x, 0));
        !          1105:   if (p != 0)
        !          1106:     {
        !          1107:       p->level = MIN (p->level, temp_slot_level);
        !          1108:       p->rtl_expr = 0;
        !          1109:     }
1.1.1.6   root     1110: 
                   1111:   return;
                   1112: }
                   1113: 
1.1       root     1114: /* Free all temporaries used so far.  This is normally called at the end
1.1.1.6   root     1115:    of generating code for a statement.  Don't free any temporaries
                   1116:    currently in use for an RTL_EXPR that hasn't yet been emitted.
                   1117:    We could eventually do better than this since it can be reused while
                   1118:    generating the same RTL_EXPR, but this is complex and probably not
                   1119:    worthwhile.  */
1.1       root     1120: 
                   1121: void
                   1122: free_temp_slots ()
                   1123: {
                   1124:   struct temp_slot *p;
                   1125: 
                   1126:   for (p = temp_slots; p; p = p->next)
1.1.1.6   root     1127:     if (p->in_use && p->level == temp_slot_level && ! p->keep
                   1128:        && p->rtl_expr == 0)
1.1       root     1129:       p->in_use = 0;
1.1.1.6   root     1130: 
                   1131:   combine_temp_slots ();
                   1132: }
                   1133: 
                   1134: /* Free all temporary slots used in T, an RTL_EXPR node.  */
                   1135: 
                   1136: void
                   1137: free_temps_for_rtl_expr (t)
                   1138:      tree t;
                   1139: {
                   1140:   struct temp_slot *p;
                   1141: 
                   1142:   for (p = temp_slots; p; p = p->next)
                   1143:     if (p->rtl_expr == t)
                   1144:       p->in_use = 0;
                   1145: 
                   1146:   combine_temp_slots ();
1.1       root     1147: }
                   1148: 
                   1149: /* Push deeper into the nesting level for stack temporaries.  */
                   1150: 
                   1151: void
                   1152: push_temp_slots ()
                   1153: {
                   1154:   temp_slot_level++;
                   1155: }
                   1156: 
                   1157: /* Pop a temporary nesting level.  All slots in use in the current level
                   1158:    are freed.  */
                   1159: 
                   1160: void
                   1161: pop_temp_slots ()
                   1162: {
                   1163:   struct temp_slot *p;
                   1164: 
                   1165:   for (p = temp_slots; p; p = p->next)
1.1.1.6   root     1166:     if (p->in_use && p->level == temp_slot_level && p->rtl_expr == 0)
1.1       root     1167:       p->in_use = 0;
                   1168: 
1.1.1.6   root     1169:   combine_temp_slots ();
                   1170: 
1.1       root     1171:   temp_slot_level--;
                   1172: }
                   1173: 
                   1174: /* Retroactively move an auto variable from a register to a stack slot.
                   1175:    This is done when an address-reference to the variable is seen.  */
                   1176: 
                   1177: void
                   1178: put_var_into_stack (decl)
                   1179:      tree decl;
                   1180: {
                   1181:   register rtx reg;
1.1.1.4   root     1182:   enum machine_mode promoted_mode, decl_mode;
1.1       root     1183:   struct function *function = 0;
1.1.1.6   root     1184:   tree context;
                   1185: 
                   1186:   if (output_bytecode)
                   1187:     return;
                   1188:   
                   1189:   context = decl_function_context (decl);
1.1       root     1190: 
1.1.1.4   root     1191:   /* Get the current rtl used for this object and it's original mode.  */
1.1       root     1192:   reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl);
                   1193: 
1.1.1.4   root     1194:   /* No need to do anything if decl has no rtx yet
                   1195:      since in that case caller is setting TREE_ADDRESSABLE
                   1196:      and a stack slot will be assigned when the rtl is made.  */
                   1197:   if (reg == 0)
                   1198:     return;
                   1199: 
                   1200:   /* Get the declared mode for this object.  */
                   1201:   decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
                   1202:               : DECL_MODE (decl));
                   1203:   /* Get the mode it's actually stored in.  */
                   1204:   promoted_mode = GET_MODE (reg);
                   1205: 
1.1       root     1206:   /* If this variable comes from an outer function,
                   1207:      find that function's saved context.  */
                   1208:   if (context != current_function_decl)
                   1209:     for (function = outer_function_chain; function; function = function->next)
                   1210:       if (function->decl == context)
                   1211:        break;
                   1212: 
                   1213:   /* If this is a variable-size object with a pseudo to address it,
                   1214:      put that pseudo into the stack, if the var is nonlocal.  */
1.1.1.4   root     1215:   if (DECL_NONLOCAL (decl)
1.1       root     1216:       && GET_CODE (reg) == MEM
                   1217:       && GET_CODE (XEXP (reg, 0)) == REG
                   1218:       && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)
1.1.1.4   root     1219:     {
                   1220:       reg = XEXP (reg, 0);
                   1221:       decl_mode = promoted_mode = GET_MODE (reg);
                   1222:     }
1.1.1.5   root     1223: 
1.1.1.6   root     1224:   /* Now we should have a value that resides in one or more pseudo regs.  */
                   1225: 
                   1226:   if (GET_CODE (reg) == REG)
                   1227:     put_reg_into_stack (function, reg, TREE_TYPE (decl),
                   1228:                        promoted_mode, decl_mode);
                   1229:   else if (GET_CODE (reg) == CONCAT)
                   1230:     {
                   1231:       /* A CONCAT contains two pseudos; put them both in the stack.
                   1232:         We do it so they end up consecutive.  */
                   1233:       enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
                   1234:       tree part_type = TREE_TYPE (TREE_TYPE (decl));
                   1235: #ifdef STACK_GROWS_DOWNWARD
                   1236:       /* Since part 0 should have a lower address, do it second.  */
                   1237:       put_reg_into_stack (function, XEXP (reg, 1),
                   1238:                          part_type, part_mode, part_mode);
                   1239:       put_reg_into_stack (function, XEXP (reg, 0),
                   1240:                          part_type, part_mode, part_mode);
                   1241: #else
                   1242:       put_reg_into_stack (function, XEXP (reg, 0),
                   1243:                          part_type, part_mode, part_mode);
                   1244:       put_reg_into_stack (function, XEXP (reg, 1),
                   1245:                          part_type, part_mode, part_mode);
                   1246: #endif
                   1247: 
                   1248:       /* Change the CONCAT into a combined MEM for both parts.  */
                   1249:       PUT_CODE (reg, MEM);
                   1250:       /* The two parts are in memory order already.
                   1251:         Use the lower parts address as ours.  */
                   1252:       XEXP (reg, 0) = XEXP (XEXP (reg, 0), 0);
                   1253:       /* Prevent sharing of rtl that might lose.  */
                   1254:       if (GET_CODE (XEXP (reg, 0)) == PLUS)
                   1255:        XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
                   1256:     }
                   1257: }
                   1258: 
                   1259: /* Subroutine of put_var_into_stack.  This puts a single pseudo reg REG
                   1260:    into the stack frame of FUNCTION (0 means the current function).
                   1261:    DECL_MODE is the machine mode of the user-level data type.
                   1262:    PROMOTED_MODE is the machine mode of the register.  */
                   1263: 
                   1264: static void
                   1265: put_reg_into_stack (function, reg, type, promoted_mode, decl_mode)
                   1266:      struct function *function;
                   1267:      rtx reg;
                   1268:      tree type;
                   1269:      enum machine_mode promoted_mode, decl_mode;
                   1270: {
                   1271:   rtx new = 0;
1.1       root     1272: 
                   1273:   if (function)
                   1274:     {
                   1275:       if (REGNO (reg) < function->max_parm_reg)
                   1276:        new = function->parm_reg_stack_loc[REGNO (reg)];
                   1277:       if (new == 0)
1.1.1.5   root     1278:        new = assign_outer_stack_local (decl_mode, GET_MODE_SIZE (decl_mode),
1.1       root     1279:                                        0, function);
                   1280:     }
                   1281:   else
                   1282:     {
                   1283:       if (REGNO (reg) < max_parm_reg)
                   1284:        new = parm_reg_stack_loc[REGNO (reg)];
                   1285:       if (new == 0)
1.1.1.5   root     1286:        new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
1.1       root     1287:     }
                   1288: 
                   1289:   XEXP (reg, 0) = XEXP (new, 0);
                   1290:   /* `volatil' bit means one thing for MEMs, another entirely for REGs.  */
                   1291:   REG_USERVAR_P (reg) = 0;
                   1292:   PUT_CODE (reg, MEM);
1.1.1.4   root     1293:   PUT_MODE (reg, decl_mode);
1.1       root     1294: 
                   1295:   /* If this is a memory ref that contains aggregate components,
                   1296:      mark it as such for cse and loop optimize.  */
1.1.1.7 ! root     1297:   MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);
1.1       root     1298: 
                   1299:   /* Now make sure that all refs to the variable, previously made
                   1300:      when it was a register, are fixed up to be valid again.  */
                   1301:   if (function)
                   1302:     {
                   1303:       struct var_refs_queue *temp;
                   1304: 
                   1305:       /* Variable is inherited; fix it up when we get back to its function.  */
                   1306:       push_obstacks (function->function_obstack,
                   1307:                     function->function_maybepermanent_obstack);
1.1.1.6   root     1308: 
                   1309:       /* See comment in restore_tree_status in tree.c for why this needs to be
                   1310:         on saveable obstack.  */
1.1       root     1311:       temp
1.1.1.6   root     1312:        = (struct var_refs_queue *) savealloc (sizeof (struct var_refs_queue));
1.1       root     1313:       temp->modified = reg;
1.1.1.4   root     1314:       temp->promoted_mode = promoted_mode;
1.1.1.6   root     1315:       temp->unsignedp = TREE_UNSIGNED (type);
1.1       root     1316:       temp->next = function->fixup_var_refs_queue;
                   1317:       function->fixup_var_refs_queue = temp;
                   1318:       pop_obstacks ();
                   1319:     }
                   1320:   else
                   1321:     /* Variable is local; fix it up now.  */
1.1.1.6   root     1322:     fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type));
1.1       root     1323: }
                   1324: 
                   1325: static void
1.1.1.4   root     1326: fixup_var_refs (var, promoted_mode, unsignedp)
1.1       root     1327:      rtx var;
1.1.1.4   root     1328:      enum machine_mode promoted_mode;
                   1329:      int unsignedp;
1.1       root     1330: {
                   1331:   tree pending;
                   1332:   rtx first_insn = get_insns ();
                   1333:   struct sequence_stack *stack = sequence_stack;
                   1334:   tree rtl_exps = rtl_expr_chain;
                   1335: 
                   1336:   /* Must scan all insns for stack-refs that exceed the limit.  */
1.1.1.4   root     1337:   fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);
1.1       root     1338: 
                   1339:   /* Scan all pending sequences too.  */
                   1340:   for (; stack; stack = stack->next)
                   1341:     {
                   1342:       push_to_sequence (stack->first);
1.1.1.4   root     1343:       fixup_var_refs_insns (var, promoted_mode, unsignedp,
                   1344:                            stack->first, stack->next != 0);
1.1       root     1345:       /* Update remembered end of sequence
                   1346:         in case we added an insn at the end.  */
                   1347:       stack->last = get_last_insn ();
                   1348:       end_sequence ();
                   1349:     }
                   1350: 
                   1351:   /* Scan all waiting RTL_EXPRs too.  */
                   1352:   for (pending = rtl_exps; pending; pending = TREE_CHAIN (pending))
                   1353:     {
                   1354:       rtx seq = RTL_EXPR_SEQUENCE (TREE_VALUE (pending));
                   1355:       if (seq != const0_rtx && seq != 0)
                   1356:        {
                   1357:          push_to_sequence (seq);
1.1.1.4   root     1358:          fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0);
1.1       root     1359:          end_sequence ();
                   1360:        }
                   1361:     }
                   1362: }
                   1363: 
1.1.1.7 ! root     1364: /* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
1.1       root     1365:    some part of an insn.  Return a struct fixup_replacement whose OLD
                   1366:    value is equal to X.  Allocate a new structure if no such entry exists. */
                   1367: 
                   1368: static struct fixup_replacement *
1.1.1.4   root     1369: find_fixup_replacement (replacements, x)
1.1       root     1370:      struct fixup_replacement **replacements;
                   1371:      rtx x;
                   1372: {
                   1373:   struct fixup_replacement *p;
                   1374: 
                   1375:   /* See if we have already replaced this.  */
                   1376:   for (p = *replacements; p && p->old != x; p = p->next)
                   1377:     ;
                   1378: 
                   1379:   if (p == 0)
                   1380:     {
                   1381:       p = (struct fixup_replacement *) oballoc (sizeof (struct fixup_replacement));
                   1382:       p->old = x;
                   1383:       p->new = 0;
                   1384:       p->next = *replacements;
                   1385:       *replacements = p;
                   1386:     }
                   1387: 
                   1388:   return p;
                   1389: }
                   1390: 
                   1391: /* Scan the insn-chain starting with INSN for refs to VAR
                   1392:    and fix them up.  TOPLEVEL is nonzero if this chain is the
                   1393:    main chain of insns for the current function.  */
                   1394: 
                   1395: static void
1.1.1.4   root     1396: fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
1.1       root     1397:      rtx var;
1.1.1.4   root     1398:      enum machine_mode promoted_mode;
                   1399:      int unsignedp;
1.1       root     1400:      rtx insn;
                   1401:      int toplevel;
                   1402: {
1.1.1.5   root     1403:   rtx call_dest = 0;
                   1404: 
1.1       root     1405:   while (insn)
                   1406:     {
                   1407:       rtx next = NEXT_INSN (insn);
                   1408:       rtx note;
1.1.1.5   root     1409:       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
1.1       root     1410:        {
1.1.1.7 ! root     1411:          /* If this is a CLOBBER of VAR, delete it.
        !          1412: 
        !          1413:             If it has a REG_LIBCALL note, delete the REG_LIBCALL
        !          1414:             and REG_RETVAL notes too.  */
        !          1415:          if (GET_CODE (PATTERN (insn)) == CLOBBER
        !          1416:              && XEXP (PATTERN (insn), 0) == var)
        !          1417:            {
        !          1418:              if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)
        !          1419:                /* The REG_LIBCALL note will go away since we are going to
        !          1420:                   turn INSN into a NOTE, so just delete the
        !          1421:                   corresponding REG_RETVAL note.  */
        !          1422:                remove_note (XEXP (note, 0),
        !          1423:                             find_reg_note (XEXP (note, 0), REG_RETVAL,
        !          1424:                                            NULL_RTX));
        !          1425: 
        !          1426:              /* In unoptimized compilation, we shouldn't call delete_insn
        !          1427:                 except in jump.c doing warnings.  */
        !          1428:              PUT_CODE (insn, NOTE);
        !          1429:              NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
        !          1430:              NOTE_SOURCE_FILE (insn) = 0;
        !          1431:            }
        !          1432: 
1.1       root     1433:          /* The insn to load VAR from a home in the arglist
                   1434:             is now a no-op.  When we see it, just delete it.  */
1.1.1.7 ! root     1435:          else if (toplevel
        !          1436:                   && GET_CODE (PATTERN (insn)) == SET
        !          1437:                   && SET_DEST (PATTERN (insn)) == var
        !          1438:                   /* If this represents the result of an insn group,
        !          1439:                      don't delete the insn.  */
        !          1440:                   && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0
        !          1441:                   && rtx_equal_p (SET_SRC (PATTERN (insn)), var))
1.1       root     1442:            {
1.1.1.4   root     1443:              /* In unoptimized compilation, we shouldn't call delete_insn
                   1444:                 except in jump.c doing warnings.  */
                   1445:              PUT_CODE (insn, NOTE);
                   1446:              NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
                   1447:              NOTE_SOURCE_FILE (insn) = 0;
1.1       root     1448:              if (insn == last_parm_insn)
                   1449:                last_parm_insn = PREV_INSN (next);
                   1450:            }
                   1451:          else
                   1452:            {
1.1.1.5   root     1453:              struct fixup_replacement *replacements = 0;
                   1454:              rtx next_insn = NEXT_INSN (insn);
                   1455: 
                   1456: #ifdef SMALL_REGISTER_CLASSES
                   1457:              /* If the insn that copies the results of a CALL_INSN
                   1458:                 into a pseudo now references VAR, we have to use an
                   1459:                 intermediate pseudo since we want the life of the
                   1460:                 return value register to be only a single insn.
                   1461: 
                   1462:                 If we don't use an intermediate pseudo, such things as
                   1463:                 address computations to make the address of VAR valid
                   1464:                 if it is not can be placed beween the CALL_INSN and INSN.
                   1465: 
                   1466:                 To make sure this doesn't happen, we record the destination
                   1467:                 of the CALL_INSN and see if the next insn uses both that
                   1468:                 and VAR.  */
                   1469: 
                   1470:              if (call_dest != 0 && GET_CODE (insn) == INSN
                   1471:                  && reg_mentioned_p (var, PATTERN (insn))
                   1472:                  && reg_mentioned_p (call_dest, PATTERN (insn)))
                   1473:                {
                   1474:                  rtx temp = gen_reg_rtx (GET_MODE (call_dest));
                   1475: 
                   1476:                  emit_insn_before (gen_move_insn (temp, call_dest), insn);
                   1477: 
                   1478:                  PATTERN (insn) = replace_rtx (PATTERN (insn),
                   1479:                                                call_dest, temp);
                   1480:                }
                   1481:              
                   1482:              if (GET_CODE (insn) == CALL_INSN
                   1483:                  && GET_CODE (PATTERN (insn)) == SET)
                   1484:                call_dest = SET_DEST (PATTERN (insn));
                   1485:              else if (GET_CODE (insn) == CALL_INSN
                   1486:                       && GET_CODE (PATTERN (insn)) == PARALLEL
                   1487:                       && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
                   1488:                call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
                   1489:              else
                   1490:                call_dest = 0;
                   1491: #endif
                   1492: 
1.1       root     1493:              /* See if we have to do anything to INSN now that VAR is in
                   1494:                 memory.  If it needs to be loaded into a pseudo, use a single
                   1495:                 pseudo for the entire insn in case there is a MATCH_DUP
                   1496:                 between two operands.  We pass a pointer to the head of
                   1497:                 a list of struct fixup_replacements.  If fixup_var_refs_1
                   1498:                 needs to allocate pseudos or replacement MEMs (for SUBREGs),
                   1499:                 it will record them in this list.
                   1500:                 
                   1501:                 If it allocated a pseudo for any replacement, we copy into
                   1502:                 it here.  */
                   1503: 
1.1.1.4   root     1504:              fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
                   1505:                                &replacements);
1.1       root     1506: 
1.1.1.5   root     1507:              /* If this is last_parm_insn, and any instructions were output
                   1508:                 after it to fix it up, then we must set last_parm_insn to
                   1509:                 the last such instruction emitted.  */
                   1510:              if (insn == last_parm_insn)
                   1511:                last_parm_insn = PREV_INSN (next_insn);
                   1512: 
1.1       root     1513:              while (replacements)
                   1514:                {
                   1515:                  if (GET_CODE (replacements->new) == REG)
                   1516:                    {
                   1517:                      rtx insert_before;
1.1.1.4   root     1518:                      rtx seq;
1.1       root     1519: 
                   1520:                      /* OLD might be a (subreg (mem)).  */
                   1521:                      if (GET_CODE (replacements->old) == SUBREG)
                   1522:                        replacements->old
                   1523:                          = fixup_memory_subreg (replacements->old, insn, 0);
                   1524:                      else
                   1525:                        replacements->old
                   1526:                          = fixup_stack_1 (replacements->old, insn);
                   1527: 
1.1.1.7 ! root     1528:                      insert_before = insn;
1.1       root     1529: 
1.1.1.4   root     1530:                      /* If we are changing the mode, do a conversion.
                   1531:                         This might be wasteful, but combine.c will
                   1532:                         eliminate much of the waste.  */
                   1533: 
                   1534:                      if (GET_MODE (replacements->new)
                   1535:                          != GET_MODE (replacements->old))
                   1536:                        {
                   1537:                          start_sequence ();
                   1538:                          convert_move (replacements->new,
                   1539:                                        replacements->old, unsignedp);
                   1540:                          seq = gen_sequence ();
                   1541:                          end_sequence ();
                   1542:                        }
                   1543:                      else
                   1544:                        seq = gen_move_insn (replacements->new,
                   1545:                                             replacements->old);
                   1546: 
                   1547:                      emit_insn_before (seq, insert_before);
1.1       root     1548:                    }
                   1549: 
                   1550:                  replacements = replacements->next;
                   1551:                }
                   1552:            }
                   1553: 
                   1554:          /* Also fix up any invalid exprs in the REG_NOTES of this insn.
                   1555:             But don't touch other insns referred to by reg-notes;
                   1556:             we will get them elsewhere.  */
                   1557:          for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
                   1558:            if (GET_CODE (note) != INSN_LIST)
1.1.1.5   root     1559:              XEXP (note, 0)
                   1560:                = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
1.1       root     1561:        }
                   1562:       insn = next;
                   1563:     }
                   1564: }
                   1565: 
1.1.1.4   root     1566: /* VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE.
                   1567:    See if the rtx expression at *LOC in INSN needs to be changed.  
1.1       root     1568: 
                   1569:    REPLACEMENTS is a pointer to a list head that starts out zero, but may
                   1570:    contain a list of original rtx's and replacements. If we find that we need
                   1571:    to modify this insn by replacing a memory reference with a pseudo or by
                   1572:    making a new MEM to implement a SUBREG, we consult that list to see if
                   1573:    we have already chosen a replacement. If none has already been allocated,
                   1574:    we allocate it and update the list.  fixup_var_refs_insns will copy VAR
                   1575:    or the SUBREG, as appropriate, to the pseudo.  */
                   1576: 
                   1577: static void
1.1.1.4   root     1578: fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
1.1       root     1579:      register rtx var;
1.1.1.4   root     1580:      enum machine_mode promoted_mode;
1.1       root     1581:      register rtx *loc;
                   1582:      rtx insn;
                   1583:      struct fixup_replacement **replacements;
                   1584: {
                   1585:   register int i;
                   1586:   register rtx x = *loc;
                   1587:   RTX_CODE code = GET_CODE (x);
                   1588:   register char *fmt;
                   1589:   register rtx tem, tem1;
                   1590:   struct fixup_replacement *replacement;
                   1591: 
                   1592:   switch (code)
                   1593:     {
                   1594:     case MEM:
                   1595:       if (var == x)
                   1596:        {
                   1597:          /* If we already have a replacement, use it.  Otherwise, 
                   1598:             try to fix up this address in case it is invalid.  */
                   1599: 
1.1.1.4   root     1600:          replacement = find_fixup_replacement (replacements, var);
1.1       root     1601:          if (replacement->new)
                   1602:            {
                   1603:              *loc = replacement->new;
                   1604:              return;
                   1605:            }
                   1606: 
                   1607:          *loc = replacement->new = x = fixup_stack_1 (x, insn);
                   1608: 
1.1.1.4   root     1609:          /* Unless we are forcing memory to register or we changed the mode,
                   1610:             we can leave things the way they are if the insn is valid.  */
1.1       root     1611:             
                   1612:          INSN_CODE (insn) = -1;
1.1.1.4   root     1613:          if (! flag_force_mem && GET_MODE (x) == promoted_mode
                   1614:              && recog_memoized (insn) >= 0)
1.1       root     1615:            return;
                   1616: 
1.1.1.4   root     1617:          *loc = replacement->new = gen_reg_rtx (promoted_mode);
1.1       root     1618:          return;
                   1619:        }
                   1620: 
                   1621:       /* If X contains VAR, we need to unshare it here so that we update
                   1622:         each occurrence separately.  But all identical MEMs in one insn
                   1623:         must be replaced with the same rtx because of the possibility of
                   1624:         MATCH_DUPs.  */
                   1625: 
                   1626:       if (reg_mentioned_p (var, x))
                   1627:        {
1.1.1.4   root     1628:          replacement = find_fixup_replacement (replacements, x);
1.1       root     1629:          if (replacement->new == 0)
                   1630:            replacement->new = copy_most_rtx (x, var);
                   1631: 
                   1632:          *loc = x = replacement->new;
                   1633:        }
                   1634:       break;
                   1635: 
                   1636:     case REG:
                   1637:     case CC0:
                   1638:     case PC:
                   1639:     case CONST_INT:
                   1640:     case CONST:
                   1641:     case SYMBOL_REF:
                   1642:     case LABEL_REF:
                   1643:     case CONST_DOUBLE:
                   1644:       return;
                   1645: 
                   1646:     case SIGN_EXTRACT:
                   1647:     case ZERO_EXTRACT:
                   1648:       /* Note that in some cases those types of expressions are altered
                   1649:         by optimize_bit_field, and do not survive to get here.  */
                   1650:       if (XEXP (x, 0) == var
                   1651:          || (GET_CODE (XEXP (x, 0)) == SUBREG
                   1652:              && SUBREG_REG (XEXP (x, 0)) == var))
                   1653:        {
                   1654:          /* Get TEM as a valid MEM in the mode presently in the insn.
                   1655: 
                   1656:             We don't worry about the possibility of MATCH_DUP here; it
                   1657:             is highly unlikely and would be tricky to handle.  */
                   1658: 
                   1659:          tem = XEXP (x, 0);
                   1660:          if (GET_CODE (tem) == SUBREG)
                   1661:            tem = fixup_memory_subreg (tem, insn, 1);
                   1662:          tem = fixup_stack_1 (tem, insn);
                   1663: 
                   1664:          /* Unless we want to load from memory, get TEM into the proper mode
                   1665:             for an extract from memory.  This can only be done if the
                   1666:             extract is at a constant position and length.  */
                   1667: 
                   1668:          if (! flag_force_mem && GET_CODE (XEXP (x, 1)) == CONST_INT
                   1669:              && GET_CODE (XEXP (x, 2)) == CONST_INT
                   1670:              && ! mode_dependent_address_p (XEXP (tem, 0))
                   1671:              && ! MEM_VOLATILE_P (tem))
                   1672:            {
                   1673:              enum machine_mode wanted_mode = VOIDmode;
                   1674:              enum machine_mode is_mode = GET_MODE (tem);
                   1675:              int width = INTVAL (XEXP (x, 1));
                   1676:              int pos = INTVAL (XEXP (x, 2));
                   1677: 
                   1678: #ifdef HAVE_extzv
                   1679:              if (GET_CODE (x) == ZERO_EXTRACT)
                   1680:                wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
                   1681: #endif
                   1682: #ifdef HAVE_extv
                   1683:              if (GET_CODE (x) == SIGN_EXTRACT)
                   1684:                wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
                   1685: #endif
1.1.1.3   root     1686:              /* If we have a narrower mode, we can do something.  */
1.1       root     1687:              if (wanted_mode != VOIDmode
                   1688:                  && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
                   1689:                {
                   1690:                  int offset = pos / BITS_PER_UNIT;
                   1691:                  rtx old_pos = XEXP (x, 2);
                   1692:                  rtx newmem;
                   1693: 
                   1694:                  /* If the bytes and bits are counted differently, we
                   1695:                     must adjust the offset.  */
                   1696: #if BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
                   1697:                  offset = (GET_MODE_SIZE (is_mode)
                   1698:                            - GET_MODE_SIZE (wanted_mode) - offset);
                   1699: #endif
                   1700: 
                   1701:                  pos %= GET_MODE_BITSIZE (wanted_mode);
                   1702: 
                   1703:                  newmem = gen_rtx (MEM, wanted_mode,
                   1704:                                    plus_constant (XEXP (tem, 0), offset));
                   1705:                  RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
                   1706:                  MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
                   1707:                  MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
                   1708: 
                   1709:                  /* Make the change and see if the insn remains valid.  */
                   1710:                  INSN_CODE (insn) = -1;
                   1711:                  XEXP (x, 0) = newmem;
1.1.1.4   root     1712:                  XEXP (x, 2) = GEN_INT (pos);
1.1       root     1713: 
                   1714:                  if (recog_memoized (insn) >= 0)
                   1715:                    return;
                   1716: 
                   1717:                  /* Otherwise, restore old position.  XEXP (x, 0) will be
                   1718:                     restored later.  */
                   1719:                  XEXP (x, 2) = old_pos;
                   1720:                }
                   1721:            }
                   1722: 
                   1723:          /* If we get here, the bitfield extract insn can't accept a memory
                   1724:             reference.  Copy the input into a register.  */
                   1725: 
                   1726:          tem1 = gen_reg_rtx (GET_MODE (tem));
                   1727:          emit_insn_before (gen_move_insn (tem1, tem), insn);
                   1728:          XEXP (x, 0) = tem1;
                   1729:          return;
                   1730:        }
                   1731:       break;
                   1732:              
                   1733:     case SUBREG:
                   1734:       if (SUBREG_REG (x) == var)
                   1735:        {
1.1.1.4   root     1736:          /* If this is a special SUBREG made because VAR was promoted
                   1737:             from a wider mode, replace it with VAR and call ourself
                   1738:             recursively, this time saying that the object previously
                   1739:             had its current mode (by virtue of the SUBREG).  */
                   1740: 
                   1741:          if (SUBREG_PROMOTED_VAR_P (x))
                   1742:            {
                   1743:              *loc = var;
                   1744:              fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements);
                   1745:              return;
                   1746:            }
                   1747: 
1.1       root     1748:          /* If this SUBREG makes VAR wider, it has become a paradoxical
                   1749:             SUBREG with VAR in memory, but these aren't allowed at this 
                   1750:             stage of the compilation.  So load VAR into a pseudo and take
                   1751:             a SUBREG of that pseudo.  */
                   1752:          if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var)))
                   1753:            {
1.1.1.4   root     1754:              replacement = find_fixup_replacement (replacements, var);
1.1       root     1755:              if (replacement->new == 0)
                   1756:                replacement->new = gen_reg_rtx (GET_MODE (var));
                   1757:              SUBREG_REG (x) = replacement->new;
                   1758:              return;
                   1759:            }
                   1760: 
                   1761:          /* See if we have already found a replacement for this SUBREG.
                   1762:             If so, use it.  Otherwise, make a MEM and see if the insn
                   1763:             is recognized.  If not, or if we should force MEM into a register,
                   1764:             make a pseudo for this SUBREG.  */
1.1.1.4   root     1765:          replacement = find_fixup_replacement (replacements, x);
1.1       root     1766:          if (replacement->new)
                   1767:            {
                   1768:              *loc = replacement->new;
                   1769:              return;
                   1770:            }
                   1771:          
                   1772:          replacement->new = *loc = fixup_memory_subreg (x, insn, 0);
                   1773: 
1.1.1.5   root     1774:          INSN_CODE (insn) = -1;
1.1       root     1775:          if (! flag_force_mem && recog_memoized (insn) >= 0)
                   1776:            return;
                   1777: 
                   1778:          *loc = replacement->new = gen_reg_rtx (GET_MODE (x));
                   1779:          return;
                   1780:        }
                   1781:       break;
                   1782: 
                   1783:     case SET:
                   1784:       /* First do special simplification of bit-field references.  */
                   1785:       if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT
                   1786:          || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
                   1787:        optimize_bit_field (x, insn, 0);
                   1788:       if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT
                   1789:          || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
1.1.1.4   root     1790:        optimize_bit_field (x, insn, NULL_PTR);
1.1       root     1791: 
                   1792:       /* If SET_DEST is now a paradoxical SUBREG, put the result of this
                   1793:         insn into a pseudo and store the low part of the pseudo into VAR. */
                   1794:       if (GET_CODE (SET_DEST (x)) == SUBREG
                   1795:          && SUBREG_REG (SET_DEST (x)) == var
                   1796:          && (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
                   1797:              > GET_MODE_SIZE (GET_MODE (var))))
                   1798:        {
                   1799:          SET_DEST (x) = tem = gen_reg_rtx (GET_MODE (SET_DEST (x)));
                   1800:          emit_insn_after (gen_move_insn (var, gen_lowpart (GET_MODE (var),
                   1801:                                                            tem)),
                   1802:                           insn);
                   1803:          break;
                   1804:        }
                   1805:          
                   1806:       {
                   1807:        rtx dest = SET_DEST (x);
                   1808:        rtx src = SET_SRC (x);
                   1809:        rtx outerdest = dest;
                   1810: 
                   1811:        while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
                   1812:               || GET_CODE (dest) == SIGN_EXTRACT
                   1813:               || GET_CODE (dest) == ZERO_EXTRACT)
                   1814:          dest = XEXP (dest, 0);
                   1815: 
                   1816:        if (GET_CODE (src) == SUBREG)
                   1817:          src = XEXP (src, 0);
                   1818: 
                   1819:        /* If VAR does not appear at the top level of the SET
                   1820:           just scan the lower levels of the tree.  */
                   1821: 
                   1822:         if (src != var && dest != var)
                   1823:          break;
                   1824: 
                   1825:        /* We will need to rerecognize this insn.  */
                   1826:        INSN_CODE (insn) = -1;
                   1827: 
                   1828: #ifdef HAVE_insv
                   1829:        if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var)
                   1830:          {
                   1831:            /* Since this case will return, ensure we fixup all the
                   1832:               operands here.  */
1.1.1.4   root     1833:            fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
                   1834:                              insn, replacements);
                   1835:            fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
                   1836:                              insn, replacements);
                   1837:            fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
                   1838:                              insn, replacements);
1.1       root     1839: 
                   1840:            tem = XEXP (outerdest, 0);
                   1841: 
                   1842:            /* Clean up (SUBREG:SI (MEM:mode ...) 0)
                   1843:               that may appear inside a ZERO_EXTRACT.
                   1844:               This was legitimate when the MEM was a REG.  */
                   1845:            if (GET_CODE (tem) == SUBREG
                   1846:                && SUBREG_REG (tem) == var)
                   1847:              tem = fixup_memory_subreg (tem, insn, 1);
                   1848:            else
                   1849:              tem = fixup_stack_1 (tem, insn);
                   1850: 
                   1851:            if (GET_CODE (XEXP (outerdest, 1)) == CONST_INT
                   1852:                && GET_CODE (XEXP (outerdest, 2)) == CONST_INT
                   1853:                && ! mode_dependent_address_p (XEXP (tem, 0))
                   1854:                && ! MEM_VOLATILE_P (tem))
                   1855:              {
                   1856:                enum machine_mode wanted_mode
                   1857:                  = insn_operand_mode[(int) CODE_FOR_insv][0];
                   1858:                enum machine_mode is_mode = GET_MODE (tem);
                   1859:                int width = INTVAL (XEXP (outerdest, 1));
                   1860:                int pos = INTVAL (XEXP (outerdest, 2));
                   1861: 
1.1.1.3   root     1862:                /* If we have a narrower mode, we can do something.  */
1.1       root     1863:                if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
                   1864:                  {
                   1865:                    int offset = pos / BITS_PER_UNIT;
                   1866:                    rtx old_pos = XEXP (outerdest, 2);
                   1867:                    rtx newmem;
                   1868: 
                   1869: #if BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
                   1870:                    offset = (GET_MODE_SIZE (is_mode)
                   1871:                              - GET_MODE_SIZE (wanted_mode) - offset);
                   1872: #endif
                   1873: 
                   1874:                    pos %= GET_MODE_BITSIZE (wanted_mode);
                   1875: 
                   1876:                    newmem = gen_rtx (MEM, wanted_mode,
                   1877:                                      plus_constant (XEXP (tem, 0), offset));
                   1878:                    RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
                   1879:                    MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
                   1880:                    MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
                   1881: 
                   1882:                    /* Make the change and see if the insn remains valid.  */
                   1883:                    INSN_CODE (insn) = -1;
                   1884:                    XEXP (outerdest, 0) = newmem;
1.1.1.4   root     1885:                    XEXP (outerdest, 2) = GEN_INT (pos);
1.1       root     1886:                    
                   1887:                    if (recog_memoized (insn) >= 0)
                   1888:                      return;
                   1889:                    
                   1890:                    /* Otherwise, restore old position.  XEXP (x, 0) will be
                   1891:                       restored later.  */
                   1892:                    XEXP (outerdest, 2) = old_pos;
                   1893:                  }
                   1894:              }
                   1895: 
                   1896:            /* If we get here, the bit-field store doesn't allow memory
                   1897:               or isn't located at a constant position.  Load the value into
                   1898:               a register, do the store, and put it back into memory.  */
                   1899: 
                   1900:            tem1 = gen_reg_rtx (GET_MODE (tem));
                   1901:            emit_insn_before (gen_move_insn (tem1, tem), insn);
                   1902:            emit_insn_after (gen_move_insn (tem, tem1), insn);
                   1903:            XEXP (outerdest, 0) = tem1;
                   1904:            return;
                   1905:          }
                   1906: #endif
                   1907: 
                   1908:        /* STRICT_LOW_PART is a no-op on memory references
                   1909:           and it can cause combinations to be unrecognizable,
                   1910:           so eliminate it.  */
                   1911: 
                   1912:        if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
                   1913:          SET_DEST (x) = XEXP (SET_DEST (x), 0);
                   1914: 
                   1915:        /* A valid insn to copy VAR into or out of a register
                   1916:           must be left alone, to avoid an infinite loop here.
                   1917:           If the reference to VAR is by a subreg, fix that up,
                   1918:           since SUBREG is not valid for a memref.
1.1.1.5   root     1919:           Also fix up the address of the stack slot.
                   1920: 
                   1921:           Note that we must not try to recognize the insn until
                   1922:           after we know that we have valid addresses and no
                   1923:           (subreg (mem ...) ...) constructs, since these interfere
                   1924:           with determining the validity of the insn.  */
1.1       root     1925: 
                   1926:        if ((SET_SRC (x) == var
                   1927:             || (GET_CODE (SET_SRC (x)) == SUBREG
                   1928:                 && SUBREG_REG (SET_SRC (x)) == var))
                   1929:            && (GET_CODE (SET_DEST (x)) == REG
                   1930:                || (GET_CODE (SET_DEST (x)) == SUBREG
                   1931:                    && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))
1.1.1.5   root     1932:            && x == single_set (PATTERN (insn)))
1.1       root     1933:          {
1.1.1.5   root     1934:            rtx pat;
                   1935: 
1.1.1.4   root     1936:            replacement = find_fixup_replacement (replacements, SET_SRC (x));
1.1       root     1937:            if (replacement->new)
                   1938:              SET_SRC (x) = replacement->new;
                   1939:            else if (GET_CODE (SET_SRC (x)) == SUBREG)
                   1940:              SET_SRC (x) = replacement->new
                   1941:                = fixup_memory_subreg (SET_SRC (x), insn, 0);
                   1942:            else
                   1943:              SET_SRC (x) = replacement->new
                   1944:                = fixup_stack_1 (SET_SRC (x), insn);
1.1.1.5   root     1945: 
                   1946:            if (recog_memoized (insn) >= 0)
                   1947:              return;
                   1948: 
                   1949:            /* INSN is not valid, but we know that we want to
                   1950:               copy SET_SRC (x) to SET_DEST (x) in some way.  So
                   1951:               we generate the move and see whether it requires more
                   1952:               than one insn.  If it does, we emit those insns and
                   1953:               delete INSN.  Otherwise, we an just replace the pattern 
                   1954:               of INSN; we have already verified above that INSN has
                   1955:               no other function that to do X.  */
                   1956: 
                   1957:            pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
                   1958:            if (GET_CODE (pat) == SEQUENCE)
                   1959:              {
                   1960:                emit_insn_after (pat, insn);
                   1961:                PUT_CODE (insn, NOTE);
                   1962:                NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
                   1963:                NOTE_SOURCE_FILE (insn) = 0;
                   1964:              }
                   1965:            else
                   1966:              PATTERN (insn) = pat;
                   1967: 
1.1       root     1968:            return;
                   1969:          }
                   1970: 
                   1971:        if ((SET_DEST (x) == var
                   1972:             || (GET_CODE (SET_DEST (x)) == SUBREG
                   1973:                 && SUBREG_REG (SET_DEST (x)) == var))
                   1974:            && (GET_CODE (SET_SRC (x)) == REG
                   1975:                || (GET_CODE (SET_SRC (x)) == SUBREG
                   1976:                    && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG))
1.1.1.5   root     1977:            && x == single_set (PATTERN (insn)))
1.1       root     1978:          {
1.1.1.5   root     1979:            rtx pat;
                   1980: 
1.1       root     1981:            if (GET_CODE (SET_DEST (x)) == SUBREG)
                   1982:              SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);
                   1983:            else
                   1984:              SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
1.1.1.5   root     1985: 
                   1986:            if (recog_memoized (insn) >= 0)
                   1987:              return;
                   1988: 
                   1989:            pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
                   1990:            if (GET_CODE (pat) == SEQUENCE)
                   1991:              {
                   1992:                emit_insn_after (pat, insn);
                   1993:                PUT_CODE (insn, NOTE);
                   1994:                NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
                   1995:                NOTE_SOURCE_FILE (insn) = 0;
                   1996:              }
                   1997:            else
                   1998:              PATTERN (insn) = pat;
                   1999: 
1.1       root     2000:            return;
                   2001:          }
                   2002: 
                   2003:        /* Otherwise, storing into VAR must be handled specially
                   2004:           by storing into a temporary and copying that into VAR
1.1.1.4   root     2005:           with a new insn after this one.  Note that this case
                   2006:           will be used when storing into a promoted scalar since
                   2007:           the insn will now have different modes on the input
                   2008:           and output and hence will be invalid (except for the case
                   2009:           of setting it to a constant, which does not need any
                   2010:           change if it is valid).  We generate extra code in that case,
                   2011:           but combine.c will eliminate it.  */
1.1       root     2012: 
                   2013:        if (dest == var)
                   2014:          {
                   2015:            rtx temp;
1.1.1.4   root     2016:            rtx fixeddest = SET_DEST (x);
                   2017: 
1.1       root     2018:            /* STRICT_LOW_PART can be discarded, around a MEM.  */
1.1.1.4   root     2019:            if (GET_CODE (fixeddest) == STRICT_LOW_PART)
                   2020:              fixeddest = XEXP (fixeddest, 0);
1.1       root     2021:            /* Convert (SUBREG (MEM)) to a MEM in a changed mode.  */
1.1.1.4   root     2022:            if (GET_CODE (fixeddest) == SUBREG)
                   2023:              fixeddest = fixup_memory_subreg (fixeddest, insn, 0);
1.1       root     2024:            else
1.1.1.4   root     2025:              fixeddest = fixup_stack_1 (fixeddest, insn);
                   2026: 
                   2027:            temp = gen_reg_rtx (GET_MODE (SET_SRC (x)) == VOIDmode
                   2028:                                ? GET_MODE (fixeddest)
                   2029:                                : GET_MODE (SET_SRC (x)));
                   2030: 
                   2031:            emit_insn_after (gen_move_insn (fixeddest,
                   2032:                                            gen_lowpart (GET_MODE (fixeddest),
                   2033:                                                         temp)),
                   2034:                             insn);
1.1       root     2035: 
                   2036:            SET_DEST (x) = temp;
                   2037:          }
                   2038:       }
                   2039:     }
                   2040: 
                   2041:   /* Nothing special about this RTX; fix its operands.  */
                   2042: 
                   2043:   fmt = GET_RTX_FORMAT (code);
                   2044:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                   2045:     {
                   2046:       if (fmt[i] == 'e')
1.1.1.4   root     2047:        fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements);
1.1       root     2048:       if (fmt[i] == 'E')
                   2049:        {
                   2050:          register int j;
                   2051:          for (j = 0; j < XVECLEN (x, i); j++)
1.1.1.4   root     2052:            fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
                   2053:                              insn, replacements);
1.1       root     2054:        }
                   2055:     }
                   2056: }
                   2057: 
                   2058: /* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
                   2059:    return an rtx (MEM:m1 newaddr) which is equivalent.
                   2060:    If any insns must be emitted to compute NEWADDR, put them before INSN.
                   2061: 
                   2062:    UNCRITICAL nonzero means accept paradoxical subregs.
1.1.1.5   root     2063:    This is used for subregs found inside of ZERO_EXTRACTs and in REG_NOTES. */
1.1       root     2064: 
                   2065: static rtx
                   2066: fixup_memory_subreg (x, insn, uncritical)
                   2067:      rtx x;
                   2068:      rtx insn;
                   2069:      int uncritical;
                   2070: {
                   2071:   int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
                   2072:   rtx addr = XEXP (SUBREG_REG (x), 0);
                   2073:   enum machine_mode mode = GET_MODE (x);
                   2074:   rtx saved, result;
                   2075: 
                   2076:   /* Paradoxical SUBREGs are usually invalid during RTL generation.  */
                   2077:   if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
                   2078:       && ! uncritical)
                   2079:     abort ();
                   2080: 
                   2081: #if BYTES_BIG_ENDIAN
                   2082:   offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
                   2083:             - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
                   2084: #endif
                   2085:   addr = plus_constant (addr, offset);
                   2086:   if (!flag_force_addr && memory_address_p (mode, addr))
                   2087:     /* Shortcut if no insns need be emitted.  */
                   2088:     return change_address (SUBREG_REG (x), mode, addr);
                   2089:   start_sequence ();
                   2090:   result = change_address (SUBREG_REG (x), mode, addr);
                   2091:   emit_insn_before (gen_sequence (), insn);
                   2092:   end_sequence ();
                   2093:   return result;
                   2094: }
                   2095: 
                   2096: /* Do fixup_memory_subreg on all (SUBREG (MEM ...) ...) contained in X.
                   2097:    Replace subexpressions of X in place.
                   2098:    If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
                   2099:    Otherwise return X, with its contents possibly altered.
                   2100: 
1.1.1.5   root     2101:    If any insns must be emitted to compute NEWADDR, put them before INSN. 
                   2102: 
                   2103:    UNCRITICAL is as in fixup_memory_subreg.  */
1.1       root     2104: 
                   2105: static rtx
1.1.1.5   root     2106: walk_fixup_memory_subreg (x, insn, uncritical)
1.1       root     2107:      register rtx x;
                   2108:      rtx insn;
1.1.1.5   root     2109:      int uncritical;
1.1       root     2110: {
                   2111:   register enum rtx_code code;
                   2112:   register char *fmt;
                   2113:   register int i;
                   2114: 
                   2115:   if (x == 0)
                   2116:     return 0;
                   2117: 
                   2118:   code = GET_CODE (x);
                   2119: 
                   2120:   if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
1.1.1.5   root     2121:     return fixup_memory_subreg (x, insn, uncritical);
1.1       root     2122: 
                   2123:   /* Nothing special about this RTX; fix its operands.  */
                   2124: 
                   2125:   fmt = GET_RTX_FORMAT (code);
                   2126:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                   2127:     {
                   2128:       if (fmt[i] == 'e')
1.1.1.5   root     2129:        XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, uncritical);
1.1       root     2130:       if (fmt[i] == 'E')
                   2131:        {
                   2132:          register int j;
                   2133:          for (j = 0; j < XVECLEN (x, i); j++)
                   2134:            XVECEXP (x, i, j)
1.1.1.5   root     2135:              = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, uncritical);
1.1       root     2136:        }
                   2137:     }
                   2138:   return x;
                   2139: }
                   2140: 
                   2141: /* For each memory ref within X, if it refers to a stack slot
                   2142:    with an out of range displacement, put the address in a temp register
                   2143:    (emitting new insns before INSN to load these registers)
                   2144:    and alter the memory ref to use that register.
                   2145:    Replace each such MEM rtx with a copy, to avoid clobberage.  */
                   2146: 
                   2147: static rtx
                   2148: fixup_stack_1 (x, insn)
                   2149:      rtx x;
                   2150:      rtx insn;
                   2151: {
                   2152:   register int i;
                   2153:   register RTX_CODE code = GET_CODE (x);
                   2154:   register char *fmt;
                   2155: 
                   2156:   if (code == MEM)
                   2157:     {
                   2158:       register rtx ad = XEXP (x, 0);
                   2159:       /* If we have address of a stack slot but it's not valid
                   2160:         (displacement is too large), compute the sum in a register.  */
                   2161:       if (GET_CODE (ad) == PLUS
                   2162:          && GET_CODE (XEXP (ad, 0)) == REG
1.1.1.6   root     2163:          && ((REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER
                   2164:               && REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER)
                   2165:              || XEXP (ad, 0) == current_function_internal_arg_pointer)
1.1       root     2166:          && GET_CODE (XEXP (ad, 1)) == CONST_INT)
                   2167:        {
                   2168:          rtx temp, seq;
                   2169:          if (memory_address_p (GET_MODE (x), ad))
                   2170:            return x;
                   2171: 
                   2172:          start_sequence ();
                   2173:          temp = copy_to_reg (ad);
                   2174:          seq = gen_sequence ();
                   2175:          end_sequence ();
                   2176:          emit_insn_before (seq, insn);
                   2177:          return change_address (x, VOIDmode, temp);
                   2178:        }
                   2179:       return x;
                   2180:     }
                   2181: 
                   2182:   fmt = GET_RTX_FORMAT (code);
                   2183:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                   2184:     {
                   2185:       if (fmt[i] == 'e')
                   2186:        XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);
                   2187:       if (fmt[i] == 'E')
                   2188:        {
                   2189:          register int j;
                   2190:          for (j = 0; j < XVECLEN (x, i); j++)
                   2191:            XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);
                   2192:        }
                   2193:     }
                   2194:   return x;
                   2195: }
                   2196: 
                   2197: /* Optimization: a bit-field instruction whose field
                   2198:    happens to be a byte or halfword in memory
                   2199:    can be changed to a move instruction.
                   2200: 
                   2201:    We call here when INSN is an insn to examine or store into a bit-field.
                   2202:    BODY is the SET-rtx to be altered.
                   2203: 
                   2204:    EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0.
                   2205:    (Currently this is called only from function.c, and EQUIV_MEM
                   2206:    is always 0.)  */
                   2207: 
                   2208: static void
                   2209: optimize_bit_field (body, insn, equiv_mem)
                   2210:      rtx body;
                   2211:      rtx insn;
                   2212:      rtx *equiv_mem;
                   2213: {
                   2214:   register rtx bitfield;
                   2215:   int destflag;
                   2216:   rtx seq = 0;
                   2217:   enum machine_mode mode;
                   2218: 
                   2219:   if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT
                   2220:       || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)
                   2221:     bitfield = SET_DEST (body), destflag = 1;
                   2222:   else
                   2223:     bitfield = SET_SRC (body), destflag = 0;
                   2224: 
                   2225:   /* First check that the field being stored has constant size and position
                   2226:      and is in fact a byte or halfword suitably aligned.  */
                   2227: 
                   2228:   if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT
                   2229:       && GET_CODE (XEXP (bitfield, 2)) == CONST_INT
                   2230:       && ((mode = mode_for_size (INTVAL (XEXP (bitfield, 1)), MODE_INT, 1))
                   2231:          != BLKmode)
                   2232:       && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)
                   2233:     {
                   2234:       register rtx memref = 0;
                   2235: 
                   2236:       /* Now check that the containing word is memory, not a register,
                   2237:         and that it is safe to change the machine mode.  */
                   2238: 
                   2239:       if (GET_CODE (XEXP (bitfield, 0)) == MEM)
                   2240:        memref = XEXP (bitfield, 0);
                   2241:       else if (GET_CODE (XEXP (bitfield, 0)) == REG
                   2242:               && equiv_mem != 0)
                   2243:        memref = equiv_mem[REGNO (XEXP (bitfield, 0))];
                   2244:       else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
                   2245:               && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM)
                   2246:        memref = SUBREG_REG (XEXP (bitfield, 0));
                   2247:       else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
                   2248:               && equiv_mem != 0
                   2249:               && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG)
                   2250:        memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];
                   2251: 
                   2252:       if (memref
                   2253:          && ! mode_dependent_address_p (XEXP (memref, 0))
                   2254:          && ! MEM_VOLATILE_P (memref))
                   2255:        {
                   2256:          /* Now adjust the address, first for any subreg'ing
                   2257:             that we are now getting rid of,
                   2258:             and then for which byte of the word is wanted.  */
                   2259: 
                   2260:          register int offset = INTVAL (XEXP (bitfield, 2));
1.1.1.7 ! root     2261:          rtx insns;
        !          2262: 
1.1       root     2263:          /* Adjust OFFSET to count bits from low-address byte.  */
                   2264: #if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN
                   2265:          offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))
                   2266:                    - offset - INTVAL (XEXP (bitfield, 1)));
                   2267: #endif
                   2268:          /* Adjust OFFSET to count bytes from low-address byte.  */
                   2269:          offset /= BITS_PER_UNIT;
                   2270:          if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
                   2271:            {
                   2272:              offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
                   2273: #if BYTES_BIG_ENDIAN
                   2274:              offset -= (MIN (UNITS_PER_WORD,
                   2275:                              GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
                   2276:                         - MIN (UNITS_PER_WORD,
                   2277:                                GET_MODE_SIZE (GET_MODE (memref))));
                   2278: #endif
                   2279:            }
                   2280: 
1.1.1.7 ! root     2281:          start_sequence ();
        !          2282:          memref = change_address (memref, mode,
1.1       root     2283:                                   plus_constant (XEXP (memref, 0), offset));
1.1.1.7 ! root     2284:          insns = get_insns ();
        !          2285:          end_sequence ();
        !          2286:          emit_insns_before (insns, insn);
1.1       root     2287: 
                   2288:          /* Store this memory reference where
                   2289:             we found the bit field reference.  */
                   2290: 
                   2291:          if (destflag)
                   2292:            {
                   2293:              validate_change (insn, &SET_DEST (body), memref, 1);
                   2294:              if (! CONSTANT_ADDRESS_P (SET_SRC (body)))
                   2295:                {
                   2296:                  rtx src = SET_SRC (body);
                   2297:                  while (GET_CODE (src) == SUBREG
                   2298:                         && SUBREG_WORD (src) == 0)
                   2299:                    src = SUBREG_REG (src);
                   2300:                  if (GET_MODE (src) != GET_MODE (memref))
                   2301:                    src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
                   2302:                  validate_change (insn, &SET_SRC (body), src, 1);
                   2303:                }
                   2304:              else if (GET_MODE (SET_SRC (body)) != VOIDmode
                   2305:                       && GET_MODE (SET_SRC (body)) != GET_MODE (memref))
                   2306:                /* This shouldn't happen because anything that didn't have
                   2307:                   one of these modes should have got converted explicitly
                   2308:                   and then referenced through a subreg.
                   2309:                   This is so because the original bit-field was
                   2310:                   handled by agg_mode and so its tree structure had
                   2311:                   the same mode that memref now has.  */
                   2312:                abort ();
                   2313:            }
                   2314:          else
                   2315:            {
                   2316:              rtx dest = SET_DEST (body);
                   2317: 
                   2318:              while (GET_CODE (dest) == SUBREG
                   2319:                     && SUBREG_WORD (dest) == 0)
                   2320:                dest = SUBREG_REG (dest);
                   2321: 
                   2322:              validate_change (insn, &SET_DEST (body), dest, 1);
                   2323: 
                   2324:              if (GET_MODE (dest) == GET_MODE (memref))
                   2325:                validate_change (insn, &SET_SRC (body), memref, 1);
                   2326:              else
                   2327:                {
                   2328:                  /* Convert the mem ref to the destination mode.  */
                   2329:                  rtx newreg = gen_reg_rtx (GET_MODE (dest));
                   2330: 
                   2331:                  start_sequence ();
                   2332:                  convert_move (newreg, memref,
                   2333:                                GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);
                   2334:                  seq = get_insns ();
                   2335:                  end_sequence ();
                   2336: 
                   2337:                  validate_change (insn, &SET_SRC (body), newreg, 1);
                   2338:                }
                   2339:            }
                   2340: 
                   2341:          /* See if we can convert this extraction or insertion into
                   2342:             a simple move insn.  We might not be able to do so if this
                   2343:             was, for example, part of a PARALLEL.
                   2344: 
                   2345:             If we succeed, write out any needed conversions.  If we fail,
                   2346:             it is hard to guess why we failed, so don't do anything
                   2347:             special; just let the optimization be suppressed.  */
                   2348: 
                   2349:          if (apply_change_group () && seq)
                   2350:            emit_insns_before (seq, insn);
                   2351:        }
                   2352:     }
                   2353: }
                   2354: 
                   2355: /* These routines are responsible for converting virtual register references
                   2356:    to the actual hard register references once RTL generation is complete.
                   2357: 
                   2358:    The following four variables are used for communication between the
                   2359:    routines.  They contain the offsets of the virtual registers from their
                   2360:    respective hard registers.  */
                   2361: 
                   2362: static int in_arg_offset;
                   2363: static int var_offset;
                   2364: static int dynamic_offset;
                   2365: static int out_arg_offset;
                   2366: 
                   2367: /* In most machines, the stack pointer register is equivalent to the bottom
                   2368:    of the stack.  */
                   2369: 
                   2370: #ifndef STACK_POINTER_OFFSET
                   2371: #define STACK_POINTER_OFFSET   0
                   2372: #endif
                   2373: 
                   2374: /* If not defined, pick an appropriate default for the offset of dynamically
                   2375:    allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,
                   2376:    REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */
                   2377: 
                   2378: #ifndef STACK_DYNAMIC_OFFSET
                   2379: 
                   2380: #ifdef ACCUMULATE_OUTGOING_ARGS
                   2381: /* The bottom of the stack points to the actual arguments.  If
                   2382:    REG_PARM_STACK_SPACE is defined, this includes the space for the register
                   2383:    parameters.  However, if OUTGOING_REG_PARM_STACK space is not defined,
                   2384:    stack space for register parameters is not pushed by the caller, but 
                   2385:    rather part of the fixed stack areas and hence not included in
                   2386:    `current_function_outgoing_args_size'.  Nevertheless, we must allow
                   2387:    for it when allocating stack dynamic objects.  */
                   2388: 
                   2389: #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
                   2390: #define STACK_DYNAMIC_OFFSET(FNDECL)   \
                   2391: (current_function_outgoing_args_size   \
                   2392:  + REG_PARM_STACK_SPACE (FNDECL) + (STACK_POINTER_OFFSET))
                   2393: 
                   2394: #else
                   2395: #define STACK_DYNAMIC_OFFSET(FNDECL)   \
                   2396: (current_function_outgoing_args_size + (STACK_POINTER_OFFSET))
                   2397: #endif
                   2398: 
                   2399: #else
                   2400: #define STACK_DYNAMIC_OFFSET(FNDECL) STACK_POINTER_OFFSET
                   2401: #endif
                   2402: #endif
                   2403: 
                   2404: /* Pass through the INSNS of function FNDECL and convert virtual register
                   2405:    references to hard register references.  */
                   2406: 
                   2407: void
                   2408: instantiate_virtual_regs (fndecl, insns)
                   2409:      tree fndecl;
                   2410:      rtx insns;
                   2411: {
                   2412:   rtx insn;
                   2413: 
                   2414:   /* Compute the offsets to use for this function.  */
                   2415:   in_arg_offset = FIRST_PARM_OFFSET (fndecl);
                   2416:   var_offset = STARTING_FRAME_OFFSET;
                   2417:   dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
                   2418:   out_arg_offset = STACK_POINTER_OFFSET;
                   2419: 
                   2420:   /* Scan all variables and parameters of this function.  For each that is
                   2421:      in memory, instantiate all virtual registers if the result is a valid
                   2422:      address.  If not, we do it later.  That will handle most uses of virtual
                   2423:      regs on many machines.  */
                   2424:   instantiate_decls (fndecl, 1);
                   2425: 
                   2426:   /* Initialize recognition, indicating that volatile is OK.  */
                   2427:   init_recog ();
                   2428: 
                   2429:   /* Scan through all the insns, instantiating every virtual register still
                   2430:      present.  */
                   2431:   for (insn = insns; insn; insn = NEXT_INSN (insn))
                   2432:     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
                   2433:        || GET_CODE (insn) == CALL_INSN)
                   2434:       {
                   2435:        instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1);
1.1.1.4   root     2436:        instantiate_virtual_regs_1 (&REG_NOTES (insn), NULL_RTX, 0);
1.1       root     2437:       }
                   2438: 
                   2439:   /* Now instantiate the remaining register equivalences for debugging info.
                   2440:      These will not be valid addresses.  */
                   2441:   instantiate_decls (fndecl, 0);
                   2442: 
                   2443:   /* Indicate that, from now on, assign_stack_local should use
                   2444:      frame_pointer_rtx.  */
                   2445:   virtuals_instantiated = 1;
                   2446: }
                   2447: 
                   2448: /* Scan all decls in FNDECL (both variables and parameters) and instantiate
                   2449:    all virtual registers in their DECL_RTL's.
                   2450: 
                   2451:    If VALID_ONLY, do this only if the resulting address is still valid.
                   2452:    Otherwise, always do it.  */
                   2453: 
                   2454: static void
                   2455: instantiate_decls (fndecl, valid_only)
                   2456:      tree fndecl;
                   2457:      int valid_only;
                   2458: {
                   2459:   tree decl;
                   2460: 
1.1.1.4   root     2461:   if (DECL_INLINE (fndecl))
1.1       root     2462:     /* When compiling an inline function, the obstack used for
                   2463:        rtl allocation is the maybepermanent_obstack.  Calling
                   2464:        `resume_temporary_allocation' switches us back to that
                   2465:        obstack while we process this function's parameters.  */
                   2466:     resume_temporary_allocation ();
                   2467: 
                   2468:   /* Process all parameters of the function.  */
                   2469:   for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
                   2470:     {
1.1.1.4   root     2471:       instantiate_decl (DECL_RTL (decl), int_size_in_bytes (TREE_TYPE (decl)),
                   2472:                        valid_only);    
                   2473:       instantiate_decl (DECL_INCOMING_RTL (decl),
                   2474:                        int_size_in_bytes (TREE_TYPE (decl)), valid_only);
1.1       root     2475:     }
                   2476: 
                   2477:   /* Now process all variables defined in the function or its subblocks. */
                   2478:   instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only);
                   2479: 
1.1.1.4   root     2480:   if (DECL_INLINE (fndecl))
1.1       root     2481:     {
                   2482:       /* Save all rtl allocated for this function by raising the
                   2483:         high-water mark on the maybepermanent_obstack.  */
                   2484:       preserve_data ();
                   2485:       /* All further rtl allocation is now done in the current_obstack.  */
                   2486:       rtl_in_current_obstack ();
                   2487:     }
                   2488: }
                   2489: 
                   2490: /* Subroutine of instantiate_decls: Process all decls in the given
                   2491:    BLOCK node and all its subblocks.  */
                   2492: 
                   2493: static void
                   2494: instantiate_decls_1 (let, valid_only)
                   2495:      tree let;
                   2496:      int valid_only;
                   2497: {
                   2498:   tree t;
                   2499: 
                   2500:   for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
1.1.1.4   root     2501:     instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)),
                   2502:                      valid_only);
1.1       root     2503: 
                   2504:   /* Process all subblocks.  */
                   2505:   for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
                   2506:     instantiate_decls_1 (t, valid_only);
                   2507: }
1.1.1.4   root     2508: 
1.1.1.5   root     2509: /* Subroutine of the preceding procedures: Given RTL representing a
1.1.1.4   root     2510:    decl and the size of the object, do any instantiation required.
                   2511: 
                   2512:    If VALID_ONLY is non-zero, it means that the RTL should only be
                   2513:    changed if the new address is valid.  */
                   2514: 
                   2515: static void
                   2516: instantiate_decl (x, size, valid_only)
                   2517:      rtx x;
                   2518:      int size;
                   2519:      int valid_only;
                   2520: {
                   2521:   enum machine_mode mode;
                   2522:   rtx addr;
                   2523: 
                   2524:   /* If this is not a MEM, no need to do anything.  Similarly if the
                   2525:      address is a constant or a register that is not a virtual register.  */
                   2526: 
                   2527:   if (x == 0 || GET_CODE (x) != MEM)
                   2528:     return;
                   2529: 
                   2530:   addr = XEXP (x, 0);
                   2531:   if (CONSTANT_P (addr)
                   2532:       || (GET_CODE (addr) == REG
                   2533:          && (REGNO (addr) < FIRST_VIRTUAL_REGISTER
                   2534:              || REGNO (addr) > LAST_VIRTUAL_REGISTER)))
                   2535:     return;
                   2536: 
                   2537:   /* If we should only do this if the address is valid, copy the address.
                   2538:      We need to do this so we can undo any changes that might make the
                   2539:      address invalid.  This copy is unfortunate, but probably can't be
                   2540:      avoided.  */
                   2541: 
                   2542:   if (valid_only)
                   2543:     addr = copy_rtx (addr);
                   2544: 
                   2545:   instantiate_virtual_regs_1 (&addr, NULL_RTX, 0);
                   2546: 
                   2547:   if (! valid_only)
                   2548:     return;
                   2549: 
                   2550:   /* Now verify that the resulting address is valid for every integer or
                   2551:      floating-point mode up to and including SIZE bytes long.  We do this
                   2552:      since the object might be accessed in any mode and frame addresses
                   2553:      are shared.  */
                   2554: 
                   2555:   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   2556:        mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
                   2557:        mode = GET_MODE_WIDER_MODE (mode))
                   2558:     if (! memory_address_p (mode, addr))
                   2559:       return;
                   2560: 
                   2561:   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
                   2562:        mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
                   2563:        mode = GET_MODE_WIDER_MODE (mode))
                   2564:     if (! memory_address_p (mode, addr))
                   2565:       return;
                   2566: 
                   2567:   /* Otherwise, put back the address, now that we have updated it and we
                   2568:      know it is valid.  */
                   2569: 
                   2570:   XEXP (x, 0) = addr;
                   2571: }
1.1       root     2572: 
                   2573: /* Given a pointer to a piece of rtx and an optional pointer to the
                   2574:    containing object, instantiate any virtual registers present in it.
                   2575: 
                   2576:    If EXTRA_INSNS, we always do the replacement and generate
                   2577:    any extra insns before OBJECT.  If it zero, we do nothing if replacement
                   2578:    is not valid.
                   2579: 
                   2580:    Return 1 if we either had nothing to do or if we were able to do the
                   2581:    needed replacement.  Return 0 otherwise; we only return zero if 
                   2582:    EXTRA_INSNS is zero.
                   2583: 
                   2584:    We first try some simple transformations to avoid the creation of extra
                   2585:    pseudos.  */
                   2586: 
                   2587: static int
                   2588: instantiate_virtual_regs_1 (loc, object, extra_insns)
                   2589:      rtx *loc;
                   2590:      rtx object;
                   2591:      int extra_insns;
                   2592: {
                   2593:   rtx x;
                   2594:   RTX_CODE code;
                   2595:   rtx new = 0;
                   2596:   int offset;
                   2597:   rtx temp;
                   2598:   rtx seq;
                   2599:   int i, j;
                   2600:   char *fmt;
                   2601: 
                   2602:   /* Re-start here to avoid recursion in common cases.  */
                   2603:  restart:
                   2604: 
                   2605:   x = *loc;
                   2606:   if (x == 0)
                   2607:     return 1;
                   2608: 
                   2609:   code = GET_CODE (x);
                   2610: 
                   2611:   /* Check for some special cases.  */
                   2612:   switch (code)
                   2613:     {
                   2614:     case CONST_INT:
                   2615:     case CONST_DOUBLE:
                   2616:     case CONST:
                   2617:     case SYMBOL_REF:
                   2618:     case CODE_LABEL:
                   2619:     case PC:
                   2620:     case CC0:
                   2621:     case ASM_INPUT:
                   2622:     case ADDR_VEC:
                   2623:     case ADDR_DIFF_VEC:
                   2624:     case RETURN:
                   2625:       return 1;
                   2626: 
                   2627:     case SET:
                   2628:       /* We are allowed to set the virtual registers.  This means that
                   2629:         that the actual register should receive the source minus the
                   2630:         appropriate offset.  This is used, for example, in the handling
                   2631:         of non-local gotos.  */
                   2632:       if (SET_DEST (x) == virtual_incoming_args_rtx)
                   2633:        new = arg_pointer_rtx, offset = - in_arg_offset;
                   2634:       else if (SET_DEST (x) == virtual_stack_vars_rtx)
                   2635:        new = frame_pointer_rtx, offset = - var_offset;
                   2636:       else if (SET_DEST (x) == virtual_stack_dynamic_rtx)
                   2637:        new = stack_pointer_rtx, offset = - dynamic_offset;
                   2638:       else if (SET_DEST (x) == virtual_outgoing_args_rtx)
                   2639:        new = stack_pointer_rtx, offset = - out_arg_offset;
                   2640: 
                   2641:       if (new)
                   2642:        {
                   2643:          /* The only valid sources here are PLUS or REG.  Just do
                   2644:             the simplest possible thing to handle them.  */
                   2645:          if (GET_CODE (SET_SRC (x)) != REG
                   2646:              && GET_CODE (SET_SRC (x)) != PLUS)
                   2647:            abort ();
                   2648: 
                   2649:          start_sequence ();
                   2650:          if (GET_CODE (SET_SRC (x)) != REG)
1.1.1.4   root     2651:            temp = force_operand (SET_SRC (x), NULL_RTX);
1.1       root     2652:          else
                   2653:            temp = SET_SRC (x);
1.1.1.4   root     2654:          temp = force_operand (plus_constant (temp, offset), NULL_RTX);
1.1       root     2655:          seq = get_insns ();
                   2656:          end_sequence ();
                   2657: 
                   2658:          emit_insns_before (seq, object);
                   2659:          SET_DEST (x) = new;
                   2660: 
                   2661:          if (!validate_change (object, &SET_SRC (x), temp, 0)
                   2662:              || ! extra_insns)
                   2663:            abort ();
                   2664: 
                   2665:          return 1;
                   2666:        }
                   2667: 
                   2668:       instantiate_virtual_regs_1 (&SET_DEST (x), object, extra_insns);
                   2669:       loc = &SET_SRC (x);
                   2670:       goto restart;
                   2671: 
                   2672:     case PLUS:
                   2673:       /* Handle special case of virtual register plus constant.  */
                   2674:       if (CONSTANT_P (XEXP (x, 1)))
                   2675:        {
                   2676:          rtx old;
                   2677: 
                   2678:          /* Check for (plus (plus VIRT foo) (const_int)) first.  */
                   2679:          if (GET_CODE (XEXP (x, 0)) == PLUS)
                   2680:            {
                   2681:              rtx inner = XEXP (XEXP (x, 0), 0);
                   2682: 
                   2683:              if (inner == virtual_incoming_args_rtx)
                   2684:                new = arg_pointer_rtx, offset = in_arg_offset;
                   2685:              else if (inner == virtual_stack_vars_rtx)
                   2686:                new = frame_pointer_rtx, offset = var_offset;
                   2687:              else if (inner == virtual_stack_dynamic_rtx)
                   2688:                new = stack_pointer_rtx, offset = dynamic_offset;
                   2689:              else if (inner == virtual_outgoing_args_rtx)
                   2690:                new = stack_pointer_rtx, offset = out_arg_offset;
                   2691:              else
                   2692:                {
                   2693:                  loc = &XEXP (x, 0);
                   2694:                  goto restart;
                   2695:                }
                   2696: 
                   2697:              instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
                   2698:                                          extra_insns);
                   2699:              new = gen_rtx (PLUS, Pmode, new, XEXP (XEXP (x, 0), 1));
                   2700:            }
                   2701: 
                   2702:          else if (XEXP (x, 0) == virtual_incoming_args_rtx)
                   2703:            new = arg_pointer_rtx, offset = in_arg_offset;
                   2704:          else if (XEXP (x, 0) == virtual_stack_vars_rtx)
                   2705:            new = frame_pointer_rtx, offset = var_offset;
                   2706:          else if (XEXP (x, 0) == virtual_stack_dynamic_rtx)
                   2707:            new = stack_pointer_rtx, offset = dynamic_offset;
                   2708:          else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
                   2709:            new = stack_pointer_rtx, offset = out_arg_offset;
                   2710:          else
                   2711:            {
                   2712:              /* We know the second operand is a constant.  Unless the
                   2713:                 first operand is a REG (which has been already checked),
                   2714:                 it needs to be checked.  */
                   2715:              if (GET_CODE (XEXP (x, 0)) != REG)
                   2716:                {
                   2717:                  loc = &XEXP (x, 0);
                   2718:                  goto restart;
                   2719:                }
                   2720:              return 1;
                   2721:            }
                   2722: 
                   2723:          old = XEXP (x, 0);
                   2724:          XEXP (x, 0) = new;
                   2725:          new = plus_constant (XEXP (x, 1), offset);
                   2726: 
                   2727:          /* If the new constant is zero, try to replace the sum with its
                   2728:             first operand.  */
                   2729:          if (new == const0_rtx
                   2730:              && validate_change (object, loc, XEXP (x, 0), 0))
                   2731:            return 1;
                   2732: 
                   2733:          /* Next try to replace constant with new one.  */
                   2734:          if (!validate_change (object, &XEXP (x, 1), new, 0))
                   2735:            {
                   2736:              if (! extra_insns)
                   2737:                {
                   2738:                  XEXP (x, 0) = old;
                   2739:                  return 0;
                   2740:                }
                   2741: 
                   2742:              /* Otherwise copy the new constant into a register and replace
                   2743:                 constant with that register.  */
                   2744:              temp = gen_reg_rtx (Pmode);
                   2745:              if (validate_change (object, &XEXP (x, 1), temp, 0))
                   2746:                emit_insn_before (gen_move_insn (temp, new), object);
                   2747:              else
                   2748:                {
                   2749:                  /* If that didn't work, replace this expression with a
                   2750:                     register containing the sum.  */
                   2751: 
                   2752:                  new = gen_rtx (PLUS, Pmode, XEXP (x, 0), new);
                   2753:                  XEXP (x, 0) = old;
                   2754: 
                   2755:                  start_sequence ();
1.1.1.4   root     2756:                  temp = force_operand (new, NULL_RTX);
1.1       root     2757:                  seq = get_insns ();
                   2758:                  end_sequence ();
                   2759: 
                   2760:                  emit_insns_before (seq, object);
                   2761:                  if (! validate_change (object, loc, temp, 0)
                   2762:                      && ! validate_replace_rtx (x, temp, object))
                   2763:                    abort ();
                   2764:                }
                   2765:            }
                   2766: 
                   2767:          return 1;
                   2768:        }
                   2769: 
                   2770:       /* Fall through to generic two-operand expression case.  */
                   2771:     case EXPR_LIST:
                   2772:     case CALL:
                   2773:     case COMPARE:
                   2774:     case MINUS:
                   2775:     case MULT:
                   2776:     case DIV:      case UDIV:
                   2777:     case MOD:      case UMOD:
                   2778:     case AND:      case IOR:      case XOR:
1.1.1.7 ! root     2779:     case ROTATERT: case ROTATE:
        !          2780:     case ASHIFTRT: case LSHIFTRT: case ASHIFT:
1.1       root     2781:     case NE:       case EQ:
                   2782:     case GE:       case GT:       case GEU:    case GTU:
                   2783:     case LE:       case LT:       case LEU:    case LTU:
                   2784:       if (XEXP (x, 1) && ! CONSTANT_P (XEXP (x, 1)))
                   2785:        instantiate_virtual_regs_1 (&XEXP (x, 1), object, extra_insns);
                   2786:       loc = &XEXP (x, 0);
                   2787:       goto restart;
                   2788: 
                   2789:     case MEM:
                   2790:       /* Most cases of MEM that convert to valid addresses have already been
                   2791:         handled by our scan of regno_reg_rtx.  The only special handling we
                   2792:         need here is to make a copy of the rtx to ensure it isn't being
1.1.1.2   root     2793:         shared if we have to change it to a pseudo. 
1.1       root     2794: 
                   2795:         If the rtx is a simple reference to an address via a virtual register,
                   2796:         it can potentially be shared.  In such cases, first try to make it
                   2797:         a valid address, which can also be shared.  Otherwise, copy it and
                   2798:         proceed normally. 
                   2799: 
                   2800:         First check for common cases that need no processing.  These are
                   2801:         usually due to instantiation already being done on a previous instance
                   2802:         of a shared rtx.  */
                   2803: 
                   2804:       temp = XEXP (x, 0);
                   2805:       if (CONSTANT_ADDRESS_P (temp)
                   2806: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
                   2807:          || temp == arg_pointer_rtx
                   2808: #endif
1.1.1.6   root     2809: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   2810:          || temp == hard_frame_pointer_rtx
                   2811: #endif
1.1       root     2812:          || temp == frame_pointer_rtx)
                   2813:        return 1;
                   2814: 
                   2815:       if (GET_CODE (temp) == PLUS
                   2816:          && CONSTANT_ADDRESS_P (XEXP (temp, 1))
                   2817:          && (XEXP (temp, 0) == frame_pointer_rtx
1.1.1.6   root     2818: #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   2819:              || XEXP (temp, 0) == hard_frame_pointer_rtx
                   2820: #endif
1.1       root     2821: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
                   2822:              || XEXP (temp, 0) == arg_pointer_rtx
                   2823: #endif
                   2824:              ))
                   2825:        return 1;
                   2826: 
                   2827:       if (temp == virtual_stack_vars_rtx
                   2828:          || temp == virtual_incoming_args_rtx
                   2829:          || (GET_CODE (temp) == PLUS
                   2830:              && CONSTANT_ADDRESS_P (XEXP (temp, 1))
                   2831:              && (XEXP (temp, 0) == virtual_stack_vars_rtx
                   2832:                  || XEXP (temp, 0) == virtual_incoming_args_rtx)))
                   2833:        {
                   2834:          /* This MEM may be shared.  If the substitution can be done without
                   2835:             the need to generate new pseudos, we want to do it in place
                   2836:             so all copies of the shared rtx benefit.  The call below will
                   2837:             only make substitutions if the resulting address is still
                   2838:             valid.
                   2839: 
                   2840:             Note that we cannot pass X as the object in the recursive call
                   2841:             since the insn being processed may not allow all valid
1.1.1.2   root     2842:             addresses.  However, if we were not passed on object, we can
                   2843:             only modify X without copying it if X will have a valid
                   2844:             address.
                   2845: 
                   2846:             ??? Also note that this can still lose if OBJECT is an insn that
                   2847:             has less restrictions on an address that some other insn.
                   2848:             In that case, we will modify the shared address.  This case
                   2849:             doesn't seem very likely, though.  */
1.1       root     2850: 
1.1.1.2   root     2851:          if (instantiate_virtual_regs_1 (&XEXP (x, 0),
                   2852:                                          object ? object : x, 0))
1.1       root     2853:            return 1;
                   2854: 
                   2855:          /* Otherwise make a copy and process that copy.  We copy the entire
                   2856:             RTL expression since it might be a PLUS which could also be
                   2857:             shared.  */
                   2858:          *loc = x = copy_rtx (x);
                   2859:        }
                   2860: 
                   2861:       /* Fall through to generic unary operation case.  */
                   2862:     case USE:
                   2863:     case CLOBBER:
                   2864:     case SUBREG:
                   2865:     case STRICT_LOW_PART:
                   2866:     case NEG:          case NOT:
                   2867:     case PRE_DEC:      case PRE_INC:      case POST_DEC:    case POST_INC:
                   2868:     case SIGN_EXTEND:  case ZERO_EXTEND:
                   2869:     case TRUNCATE:     case FLOAT_EXTEND: case FLOAT_TRUNCATE:
                   2870:     case FLOAT:        case FIX:
                   2871:     case UNSIGNED_FIX: case UNSIGNED_FLOAT:
                   2872:     case ABS:
                   2873:     case SQRT:
                   2874:     case FFS:
                   2875:       /* These case either have just one operand or we know that we need not
                   2876:         check the rest of the operands.  */
                   2877:       loc = &XEXP (x, 0);
                   2878:       goto restart;
                   2879: 
                   2880:     case REG:
                   2881:       /* Try to replace with a PLUS.  If that doesn't work, compute the sum
                   2882:         in front of this insn and substitute the temporary.  */
                   2883:       if (x == virtual_incoming_args_rtx)
                   2884:        new = arg_pointer_rtx, offset = in_arg_offset;
                   2885:       else if (x == virtual_stack_vars_rtx)
                   2886:        new = frame_pointer_rtx, offset = var_offset;
                   2887:       else if (x == virtual_stack_dynamic_rtx)
                   2888:        new = stack_pointer_rtx, offset = dynamic_offset;
                   2889:       else if (x == virtual_outgoing_args_rtx)
                   2890:        new = stack_pointer_rtx, offset = out_arg_offset;
                   2891: 
                   2892:       if (new)
                   2893:        {
                   2894:          temp = plus_constant (new, offset);
                   2895:          if (!validate_change (object, loc, temp, 0))
                   2896:            {
                   2897:              if (! extra_insns)
                   2898:                return 0;
                   2899: 
                   2900:              start_sequence ();
1.1.1.4   root     2901:              temp = force_operand (temp, NULL_RTX);
1.1       root     2902:              seq = get_insns ();
                   2903:              end_sequence ();
                   2904: 
                   2905:              emit_insns_before (seq, object);
                   2906:              if (! validate_change (object, loc, temp, 0)
                   2907:                  && ! validate_replace_rtx (x, temp, object))
                   2908:                abort ();
                   2909:            }
                   2910:        }
                   2911: 
                   2912:       return 1;
                   2913:     }
                   2914: 
                   2915:   /* Scan all subexpressions.  */
                   2916:   fmt = GET_RTX_FORMAT (code);
                   2917:   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
                   2918:     if (*fmt == 'e')
                   2919:       {
                   2920:        if (!instantiate_virtual_regs_1 (&XEXP (x, i), object, extra_insns))
                   2921:          return 0;
                   2922:       }
                   2923:     else if (*fmt == 'E')
                   2924:       for (j = 0; j < XVECLEN (x, i); j++)
                   2925:        if (! instantiate_virtual_regs_1 (&XVECEXP (x, i, j), object,
                   2926:                                          extra_insns))
                   2927:          return 0;
                   2928: 
                   2929:   return 1;
                   2930: }
                   2931: 
                   2932: /* Optimization: assuming this function does not receive nonlocal gotos,
                   2933:    delete the handlers for such, as well as the insns to establish
                   2934:    and disestablish them.  */
                   2935: 
                   2936: static void
                   2937: delete_handlers ()
                   2938: {
                   2939:   rtx insn;
                   2940:   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                   2941:     {
                   2942:       /* Delete the handler by turning off the flag that would
                   2943:         prevent jump_optimize from deleting it.
                   2944:         Also permit deletion of the nonlocal labels themselves
                   2945:         if nothing local refers to them.  */
                   2946:       if (GET_CODE (insn) == CODE_LABEL)
                   2947:        LABEL_PRESERVE_P (insn) = 0;
                   2948:       if (GET_CODE (insn) == INSN
1.1.1.3   root     2949:          && ((nonlocal_goto_handler_slot != 0
                   2950:               && reg_mentioned_p (nonlocal_goto_handler_slot, PATTERN (insn)))
                   2951:              || (nonlocal_goto_stack_level != 0
                   2952:                  && reg_mentioned_p (nonlocal_goto_stack_level,
                   2953:                                      PATTERN (insn)))))
1.1       root     2954:        delete_insn (insn);
                   2955:     }
                   2956: }
                   2957: 
                   2958: /* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels
                   2959:    of the current function.  */
                   2960: 
                   2961: rtx
                   2962: nonlocal_label_rtx_list ()
                   2963: {
                   2964:   tree t;
                   2965:   rtx x = 0;
                   2966: 
                   2967:   for (t = nonlocal_labels; t; t = TREE_CHAIN (t))
                   2968:     x = gen_rtx (EXPR_LIST, VOIDmode, label_rtx (TREE_VALUE (t)), x);
                   2969: 
                   2970:   return x;
                   2971: }
                   2972: 
                   2973: /* Output a USE for any register use in RTL.
                   2974:    This is used with -noreg to mark the extent of lifespan
                   2975:    of any registers used in a user-visible variable's DECL_RTL.  */
                   2976: 
                   2977: void
                   2978: use_variable (rtl)
                   2979:      rtx rtl;
                   2980: {
                   2981:   if (GET_CODE (rtl) == REG)
                   2982:     /* This is a register variable.  */
                   2983:     emit_insn (gen_rtx (USE, VOIDmode, rtl));
                   2984:   else if (GET_CODE (rtl) == MEM
                   2985:           && GET_CODE (XEXP (rtl, 0)) == REG
                   2986:           && (REGNO (XEXP (rtl, 0)) < FIRST_VIRTUAL_REGISTER
                   2987:               || REGNO (XEXP (rtl, 0)) > LAST_VIRTUAL_REGISTER)
                   2988:           && XEXP (rtl, 0) != current_function_internal_arg_pointer)
                   2989:     /* This is a variable-sized structure.  */
                   2990:     emit_insn (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)));
                   2991: }
                   2992: 
                   2993: /* Like use_variable except that it outputs the USEs after INSN
                   2994:    instead of at the end of the insn-chain.  */
                   2995: 
                   2996: void
                   2997: use_variable_after (rtl, insn)
                   2998:      rtx rtl, insn;
                   2999: {
                   3000:   if (GET_CODE (rtl) == REG)
                   3001:     /* This is a register variable.  */
                   3002:     emit_insn_after (gen_rtx (USE, VOIDmode, rtl), insn);
                   3003:   else if (GET_CODE (rtl) == MEM
                   3004:           && GET_CODE (XEXP (rtl, 0)) == REG
                   3005:           && (REGNO (XEXP (rtl, 0)) < FIRST_VIRTUAL_REGISTER
                   3006:               || REGNO (XEXP (rtl, 0)) > LAST_VIRTUAL_REGISTER)
                   3007:           && XEXP (rtl, 0) != current_function_internal_arg_pointer)
                   3008:     /* This is a variable-sized structure.  */
                   3009:     emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)), insn);
                   3010: }
                   3011: 
                   3012: int
                   3013: max_parm_reg_num ()
                   3014: {
                   3015:   return max_parm_reg;
                   3016: }
                   3017: 
                   3018: /* Return the first insn following those generated by `assign_parms'.  */
                   3019: 
                   3020: rtx
                   3021: get_first_nonparm_insn ()
                   3022: {
                   3023:   if (last_parm_insn)
                   3024:     return NEXT_INSN (last_parm_insn);
                   3025:   return get_insns ();
                   3026: }
                   3027: 
1.1.1.4   root     3028: /* Return the first NOTE_INSN_BLOCK_BEG note in the function.
                   3029:    Crash if there is none.  */
                   3030: 
                   3031: rtx
                   3032: get_first_block_beg ()
                   3033: {
                   3034:   register rtx searcher;
                   3035:   register rtx insn = get_first_nonparm_insn ();
                   3036: 
                   3037:   for (searcher = insn; searcher; searcher = NEXT_INSN (searcher))
                   3038:     if (GET_CODE (searcher) == NOTE
                   3039:        && NOTE_LINE_NUMBER (searcher) == NOTE_INSN_BLOCK_BEG)
                   3040:       return searcher;
                   3041: 
                   3042:   abort ();    /* Invalid call to this function.  (See comments above.)  */
                   3043:   return NULL_RTX;
                   3044: }
                   3045: 
1.1.1.6   root     3046: /* Return 1 if EXP is an aggregate type (or a value with aggregate type).
                   3047:    This means a type for which function calls must pass an address to the
                   3048:    function or get an address back from the function.
                   3049:    EXP may be a type node or an expression (whose type is tested).  */
1.1       root     3050: 
                   3051: int
                   3052: aggregate_value_p (exp)
                   3053:      tree exp;
                   3054: {
1.1.1.4   root     3055:   int i, regno, nregs;
                   3056:   rtx reg;
1.1.1.6   root     3057:   tree type;
                   3058:   if (TREE_CODE_CLASS (TREE_CODE (exp)) == 't')
                   3059:     type = exp;
                   3060:   else
                   3061:     type = TREE_TYPE (exp);
                   3062: 
                   3063:   if (RETURN_IN_MEMORY (type))
1.1       root     3064:     return 1;
1.1.1.7 ! root     3065:   if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
1.1       root     3066:     return 1;
1.1.1.4   root     3067:   /* Make sure we have suitable call-clobbered regs to return
                   3068:      the value in; if not, we must return it in memory.  */
1.1.1.6   root     3069:   reg = hard_function_value (type, 0);
1.1.1.4   root     3070:   regno = REGNO (reg);
1.1.1.6   root     3071:   nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (type));
1.1.1.4   root     3072:   for (i = 0; i < nregs; i++)
                   3073:     if (! call_used_regs[regno + i])
                   3074:       return 1;
1.1       root     3075:   return 0;
                   3076: }
                   3077: 
                   3078: /* Assign RTL expressions to the function's parameters.
                   3079:    This may involve copying them into registers and using
                   3080:    those registers as the RTL for them.
                   3081: 
                   3082:    If SECOND_TIME is non-zero it means that this function is being
                   3083:    called a second time.  This is done by integrate.c when a function's
                   3084:    compilation is deferred.  We need to come back here in case the
                   3085:    FUNCTION_ARG macro computes items needed for the rest of the compilation
                   3086:    (such as changing which registers are fixed or caller-saved).  But suppress
                   3087:    writing any insns or setting DECL_RTL of anything in this case.  */
                   3088: 
                   3089: void
                   3090: assign_parms (fndecl, second_time)
                   3091:      tree fndecl;
                   3092:      int second_time;
                   3093: {
                   3094:   register tree parm;
                   3095:   register rtx entry_parm = 0;
                   3096:   register rtx stack_parm = 0;
                   3097:   CUMULATIVE_ARGS args_so_far;
1.1.1.4   root     3098:   enum machine_mode promoted_mode, passed_mode, nominal_mode;
                   3099:   int unsignedp;
1.1       root     3100:   /* Total space needed so far for args on the stack,
                   3101:      given as a constant and a tree-expression.  */
                   3102:   struct args_size stack_args_size;
                   3103:   tree fntype = TREE_TYPE (fndecl);
                   3104:   tree fnargs = DECL_ARGUMENTS (fndecl);
                   3105:   /* This is used for the arg pointer when referring to stack args.  */
                   3106:   rtx internal_arg_pointer;
                   3107:   /* This is a dummy PARM_DECL that we used for the function result if 
                   3108:      the function returns a structure.  */
                   3109:   tree function_result_decl = 0;
                   3110:   int nparmregs = list_length (fnargs) + LAST_VIRTUAL_REGISTER + 1;
                   3111:   int varargs_setup = 0;
1.1.1.5   root     3112:   rtx conversion_insns = 0;
                   3113:   /* FUNCTION_ARG may look at this variable.  Since this is not
                   3114:      expanding a call it will always be zero in this function.  */
                   3115:   int current_call_is_indirect = 0;
1.1       root     3116: 
                   3117:   /* Nonzero if the last arg is named `__builtin_va_alist',
                   3118:      which is used on some machines for old-fashioned non-ANSI varargs.h;
                   3119:      this should be stuck onto the stack as if it had arrived there.  */
1.1.1.7 ! root     3120:   int hide_last_arg
        !          3121:     = (current_function_varargs
        !          3122:        && fnargs
1.1       root     3123:        && (parm = tree_last (fnargs)) != 0
                   3124:        && DECL_NAME (parm)
                   3125:        && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)),
                   3126:                     "__builtin_va_alist")));
                   3127: 
                   3128:   /* Nonzero if function takes extra anonymous args.
                   3129:      This means the last named arg must be on the stack
                   3130:      right before the anonymous ones. */
                   3131:   int stdarg
                   3132:     = (TYPE_ARG_TYPES (fntype) != 0
                   3133:        && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
                   3134:           != void_type_node));
                   3135: 
                   3136:   /* If the reg that the virtual arg pointer will be translated into is
                   3137:      not a fixed reg or is the stack pointer, make a copy of the virtual
                   3138:      arg pointer, and address parms via the copy.  The frame pointer is
                   3139:      considered fixed even though it is not marked as such.
                   3140: 
                   3141:      The second time through, simply use ap to avoid generating rtx.  */
                   3142: 
                   3143:   if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
                   3144:        || ! (fixed_regs[ARG_POINTER_REGNUM]
                   3145:             || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM))
                   3146:       && ! second_time)
                   3147:     internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
                   3148:   else
                   3149:     internal_arg_pointer = virtual_incoming_args_rtx;
                   3150:   current_function_internal_arg_pointer = internal_arg_pointer;
                   3151: 
                   3152:   stack_args_size.constant = 0;
                   3153:   stack_args_size.var = 0;
                   3154: 
                   3155:   /* If struct value address is treated as the first argument, make it so.  */
                   3156:   if (aggregate_value_p (DECL_RESULT (fndecl))
                   3157:       && ! current_function_returns_pcc_struct
                   3158:       && struct_value_incoming_rtx == 0)
                   3159:     {
                   3160:       tree type = build_pointer_type (fntype);
                   3161: 
1.1.1.4   root     3162:       function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
1.1       root     3163: 
                   3164:       DECL_ARG_TYPE (function_result_decl) = type;
                   3165:       TREE_CHAIN (function_result_decl) = fnargs;
                   3166:       fnargs = function_result_decl;
                   3167:     }
                   3168:                               
                   3169:   parm_reg_stack_loc = (rtx *) oballoc (nparmregs * sizeof (rtx));
1.1.1.7 ! root     3170:   bzero ((char *) parm_reg_stack_loc, nparmregs * sizeof (rtx));
1.1       root     3171: 
                   3172: #ifdef INIT_CUMULATIVE_INCOMING_ARGS
1.1.1.5   root     3173:   INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
1.1       root     3174: #else
1.1.1.5   root     3175:   INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX);
1.1       root     3176: #endif
                   3177: 
                   3178:   /* We haven't yet found an argument that we must push and pretend the
                   3179:      caller did.  */
                   3180:   current_function_pretend_args_size = 0;
                   3181: 
                   3182:   for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
                   3183:     {
1.1.1.7 ! root     3184:       int aggregate = AGGREGATE_TYPE_P (TREE_TYPE (parm));
1.1       root     3185:       struct args_size stack_offset;
                   3186:       struct args_size arg_size;
                   3187:       int passed_pointer = 0;
                   3188:       tree passed_type = DECL_ARG_TYPE (parm);
                   3189: 
                   3190:       /* Set LAST_NAMED if this is last named arg before some
                   3191:         anonymous args.  We treat it as if it were anonymous too.  */
                   3192:       int last_named = ((TREE_CHAIN (parm) == 0
                   3193:                         || DECL_NAME (TREE_CHAIN (parm)) == 0)
1.1.1.7 ! root     3194:                        && (stdarg || current_function_varargs));
1.1       root     3195: 
                   3196:       if (TREE_TYPE (parm) == error_mark_node
                   3197:          /* This can happen after weird syntax errors
                   3198:             or if an enum type is defined among the parms.  */
                   3199:          || TREE_CODE (parm) != PARM_DECL
                   3200:          || passed_type == NULL)
                   3201:        {
1.1.1.4   root     3202:          DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = gen_rtx (MEM, BLKmode,
                   3203:                                                                const0_rtx);
1.1       root     3204:          TREE_USED (parm) = 1;
                   3205:          continue;
                   3206:        }
                   3207: 
                   3208:       /* For varargs.h function, save info about regs and stack space
                   3209:         used by the individual args, not including the va_alist arg.  */
1.1.1.7 ! root     3210:       if (hide_last_arg && last_named)
1.1       root     3211:        current_function_args_info = args_so_far;
                   3212: 
                   3213:       /* Find mode of arg as it is passed, and mode of arg
                   3214:         as it should be during execution of this function.  */
                   3215:       passed_mode = TYPE_MODE (passed_type);
                   3216:       nominal_mode = TYPE_MODE (TREE_TYPE (parm));
                   3217: 
1.1.1.4   root     3218:       /* If the parm's mode is VOID, its value doesn't matter,
                   3219:         and avoid the usual things like emit_move_insn that could crash.  */
                   3220:       if (nominal_mode == VOIDmode)
                   3221:        {
                   3222:          DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = const0_rtx;
                   3223:          continue;
                   3224:        }
                   3225: 
1.1.1.7 ! root     3226:       /* If the parm is to be passed as a transparent union, use the
        !          3227:         type of the first field for the tests below.  We have already
        !          3228:         verified that the modes are the same.  */
        !          3229:       if (DECL_TRANSPARENT_UNION (parm)
        !          3230:          || TYPE_TRANSPARENT_UNION (passed_type))
        !          3231:        passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
        !          3232: 
1.1.1.6   root     3233:       /* See if this arg was passed by invisible reference.  It is if
                   3234:         it is an object whose size depends on the contents of the
                   3235:         object itself or if the machine requires these objects be passed
                   3236:         that way.  */
                   3237: 
                   3238:       if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
                   3239:           && contains_placeholder_p (TYPE_SIZE (passed_type)))
1.1.1.7 ! root     3240:          || TYPE_NEEDS_CONSTRUCTING (passed_type)
1.1       root     3241: #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
1.1.1.6   root     3242:          || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
                   3243:                                              passed_type, ! last_named)
                   3244: #endif
                   3245:          )
1.1       root     3246:        {
                   3247:          passed_type = build_pointer_type (passed_type);
                   3248:          passed_pointer = 1;
                   3249:          passed_mode = nominal_mode = Pmode;
                   3250:        }
                   3251: 
1.1.1.4   root     3252:       promoted_mode = passed_mode;
                   3253: 
                   3254: #ifdef PROMOTE_FUNCTION_ARGS
                   3255:       /* Compute the mode in which the arg is actually extended to.  */
1.1.1.7 ! root     3256:       promoted_mode = promote_mode (passed_type, promoted_mode, &unsignedp, 1);
1.1.1.4   root     3257: #endif
                   3258: 
1.1       root     3259:       /* Let machine desc say which reg (if any) the parm arrives in.
                   3260:         0 means it arrives on the stack.  */
                   3261: #ifdef FUNCTION_INCOMING_ARG
1.1.1.4   root     3262:       entry_parm = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
1.1       root     3263:                                          passed_type, ! last_named);
                   3264: #else
1.1.1.4   root     3265:       entry_parm = FUNCTION_ARG (args_so_far, promoted_mode,
1.1       root     3266:                                 passed_type, ! last_named);
                   3267: #endif
                   3268: 
1.1.1.4   root     3269:       if (entry_parm)
                   3270:        passed_mode = promoted_mode;
                   3271: 
1.1       root     3272: #ifdef SETUP_INCOMING_VARARGS
                   3273:       /* If this is the last named parameter, do any required setup for
                   3274:         varargs or stdargs.  We need to know about the case of this being an
                   3275:         addressable type, in which case we skip the registers it
                   3276:         would have arrived in.
                   3277: 
                   3278:         For stdargs, LAST_NAMED will be set for two parameters, the one that
                   3279:         is actually the last named, and the dummy parameter.  We only
                   3280:         want to do this action once.
                   3281: 
                   3282:         Also, indicate when RTL generation is to be suppressed.  */
                   3283:       if (last_named && !varargs_setup)
                   3284:        {
                   3285:          SETUP_INCOMING_VARARGS (args_so_far, passed_mode, passed_type,
                   3286:                                  current_function_pretend_args_size,
                   3287:                                  second_time);
                   3288:          varargs_setup = 1;
                   3289:        }
                   3290: #endif
                   3291: 
                   3292:       /* Determine parm's home in the stack,
                   3293:         in case it arrives in the stack or we should pretend it did.
                   3294: 
                   3295:         Compute the stack position and rtx where the argument arrives
                   3296:         and its size.
                   3297: 
                   3298:         There is one complexity here:  If this was a parameter that would
                   3299:         have been passed in registers, but wasn't only because it is
                   3300:         __builtin_va_alist, we want locate_and_pad_parm to treat it as if
                   3301:         it came in a register so that REG_PARM_STACK_SPACE isn't skipped.
                   3302:         In this case, we call FUNCTION_ARG with NAMED set to 1 instead of
                   3303:         0 as it was the previous time.  */
                   3304: 
                   3305:       locate_and_pad_parm (passed_mode, passed_type,
                   3306: #ifdef STACK_PARMS_IN_REG_PARM_AREA
                   3307:                           1,
                   3308: #else
                   3309: #ifdef FUNCTION_INCOMING_ARG
                   3310:                           FUNCTION_INCOMING_ARG (args_so_far, passed_mode,
                   3311:                                                  passed_type,
                   3312:                                                  (! last_named
                   3313:                                                   || varargs_setup)) != 0,
                   3314: #else
                   3315:                           FUNCTION_ARG (args_so_far, passed_mode,
                   3316:                                         passed_type,
                   3317:                                         ! last_named || varargs_setup) != 0,
                   3318: #endif
                   3319: #endif
                   3320:                           fndecl, &stack_args_size, &stack_offset, &arg_size);
                   3321: 
                   3322:       if (! second_time)
                   3323:        {
                   3324:          rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
                   3325: 
                   3326:          if (offset_rtx == const0_rtx)
                   3327:            stack_parm = gen_rtx (MEM, passed_mode, internal_arg_pointer);
                   3328:          else
                   3329:            stack_parm = gen_rtx (MEM, passed_mode,
                   3330:                                  gen_rtx (PLUS, Pmode,
                   3331:                                           internal_arg_pointer, offset_rtx));
                   3332: 
                   3333:          /* If this is a memory ref that contains aggregate components,
                   3334:             mark it as such for cse and loop optimize.  */
                   3335:          MEM_IN_STRUCT_P (stack_parm) = aggregate;
                   3336:        }
                   3337: 
                   3338:       /* If this parameter was passed both in registers and in the stack,
                   3339:         use the copy on the stack.  */
                   3340:       if (MUST_PASS_IN_STACK (passed_mode, passed_type))
                   3341:        entry_parm = 0;
                   3342: 
1.1.1.5   root     3343: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1.1       root     3344:       /* If this parm was passed part in regs and part in memory,
                   3345:         pretend it arrived entirely in memory
                   3346:         by pushing the register-part onto the stack.
                   3347: 
                   3348:         In the special case of a DImode or DFmode that is split,
                   3349:         we could put it together in a pseudoreg directly,
                   3350:         but for now that's not worth bothering with.  */
                   3351: 
                   3352:       if (entry_parm)
                   3353:        {
1.1.1.5   root     3354:          int nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, passed_mode,
                   3355:                                                  passed_type, ! last_named);
1.1       root     3356: 
                   3357:          if (nregs > 0)
                   3358:            {
                   3359:              current_function_pretend_args_size
                   3360:                = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
                   3361:                   / (PARM_BOUNDARY / BITS_PER_UNIT)
                   3362:                   * (PARM_BOUNDARY / BITS_PER_UNIT));
                   3363: 
                   3364:              if (! second_time)
                   3365:                move_block_from_reg (REGNO (entry_parm),
1.1.1.6   root     3366:                                     validize_mem (stack_parm), nregs,
                   3367:                                     int_size_in_bytes (TREE_TYPE (parm)));
1.1       root     3368:              entry_parm = stack_parm;
                   3369:            }
                   3370:        }
1.1.1.5   root     3371: #endif
1.1       root     3372: 
                   3373:       /* If we didn't decide this parm came in a register,
                   3374:         by default it came on the stack.  */
                   3375:       if (entry_parm == 0)
                   3376:        entry_parm = stack_parm;
                   3377: 
                   3378:       /* Record permanently how this parm was passed.  */
                   3379:       if (! second_time)
                   3380:        DECL_INCOMING_RTL (parm) = entry_parm;
                   3381: 
                   3382:       /* If there is actually space on the stack for this parm,
                   3383:         count it in stack_args_size; otherwise set stack_parm to 0
                   3384:         to indicate there is no preallocated stack slot for the parm.  */
                   3385: 
                   3386:       if (entry_parm == stack_parm
1.1.1.3   root     3387: #if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
1.1       root     3388:          /* On some machines, even if a parm value arrives in a register
1.1.1.3   root     3389:             there is still an (uninitialized) stack slot allocated for it.
                   3390: 
                   3391:             ??? When MAYBE_REG_PARM_STACK_SPACE is defined, we can't tell
                   3392:             whether this parameter already has a stack slot allocated,
                   3393:             because an arg block exists only if current_function_args_size
                   3394:             is larger than some threshhold, and we haven't calculated that
                   3395:             yet.  So, for now, we just assume that stack slots never exist
                   3396:             in this case.  */
1.1       root     3397:          || REG_PARM_STACK_SPACE (fndecl) > 0
                   3398: #endif
                   3399:          )
                   3400:        {
                   3401:          stack_args_size.constant += arg_size.constant;
                   3402:          if (arg_size.var)
                   3403:            ADD_PARM_SIZE (stack_args_size, arg_size.var);
                   3404:        }
                   3405:       else
                   3406:        /* No stack slot was pushed for this parm.  */
                   3407:        stack_parm = 0;
                   3408: 
                   3409:       /* Update info on where next arg arrives in registers.  */
                   3410: 
                   3411:       FUNCTION_ARG_ADVANCE (args_so_far, passed_mode,
                   3412:                            passed_type, ! last_named);
                   3413: 
                   3414:       /* If this is our second time through, we are done with this parm. */
                   3415:       if (second_time)
                   3416:        continue;
                   3417: 
1.1.1.3   root     3418:       /* If we can't trust the parm stack slot to be aligned enough
                   3419:         for its ultimate type, don't use that slot after entry.
                   3420:         We'll make another stack slot, if we need one.  */
                   3421:       {
                   3422:        int thisparm_boundary
                   3423:          = FUNCTION_ARG_BOUNDARY (passed_mode, passed_type);
                   3424: 
                   3425:        if (GET_MODE_ALIGNMENT (nominal_mode) > thisparm_boundary)
                   3426:          stack_parm = 0;
                   3427:       }
                   3428: 
1.1.1.6   root     3429:       /* If parm was passed in memory, and we need to convert it on entry,
                   3430:         don't store it back in that same slot.  */
                   3431:       if (entry_parm != 0
                   3432:          && nominal_mode != BLKmode && nominal_mode != passed_mode)
                   3433:        stack_parm = 0;
                   3434: 
                   3435: #if 0
1.1       root     3436:       /* Now adjust STACK_PARM to the mode and precise location
                   3437:         where this parameter should live during execution,
                   3438:         if we discover that it must live in the stack during execution.
                   3439:         To make debuggers happier on big-endian machines, we store
                   3440:         the value in the last bytes of the space available.  */
                   3441: 
                   3442:       if (nominal_mode != BLKmode && nominal_mode != passed_mode
                   3443:          && stack_parm != 0)
                   3444:        {
                   3445:          rtx offset_rtx;
                   3446: 
                   3447: #if BYTES_BIG_ENDIAN
                   3448:          if (GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD)
                   3449:            stack_offset.constant += (GET_MODE_SIZE (passed_mode)
                   3450:                                      - GET_MODE_SIZE (nominal_mode));
                   3451: #endif
                   3452: 
                   3453:          offset_rtx = ARGS_SIZE_RTX (stack_offset);
                   3454:          if (offset_rtx == const0_rtx)
                   3455:            stack_parm = gen_rtx (MEM, nominal_mode, internal_arg_pointer);
                   3456:          else
                   3457:            stack_parm = gen_rtx (MEM, nominal_mode,
                   3458:                                  gen_rtx (PLUS, Pmode,
                   3459:                                           internal_arg_pointer, offset_rtx));
                   3460: 
                   3461:          /* If this is a memory ref that contains aggregate components,
                   3462:             mark it as such for cse and loop optimize.  */
                   3463:          MEM_IN_STRUCT_P (stack_parm) = aggregate;
                   3464:        }
1.1.1.6   root     3465: #endif /* 0 */
1.1       root     3466: 
                   3467:       /* ENTRY_PARM is an RTX for the parameter as it arrives,
                   3468:         in the mode in which it arrives.
                   3469:         STACK_PARM is an RTX for a stack slot where the parameter can live
                   3470:         during the function (in case we want to put it there).
                   3471:         STACK_PARM is 0 if no stack slot was pushed for it.
                   3472: 
                   3473:         Now output code if necessary to convert ENTRY_PARM to
                   3474:         the type in which this function declares it,
                   3475:         and store that result in an appropriate place,
                   3476:         which may be a pseudo reg, may be STACK_PARM,
                   3477:         or may be a local stack slot if STACK_PARM is 0.
                   3478: 
                   3479:         Set DECL_RTL to that place.  */
                   3480: 
                   3481:       if (nominal_mode == BLKmode)
                   3482:        {
                   3483:          /* If a BLKmode arrives in registers, copy it to a stack slot.  */
                   3484:          if (GET_CODE (entry_parm) == REG)
                   3485:            {
                   3486:              int size_stored = CEIL_ROUND (int_size_in_bytes (TREE_TYPE (parm)),
                   3487:                                            UNITS_PER_WORD);
                   3488: 
                   3489:              /* Note that we will be storing an integral number of words.
                   3490:                 So we have to be careful to ensure that we allocate an
                   3491:                 integral number of words.  We do this below in the
                   3492:                 assign_stack_local if space was not allocated in the argument
                   3493:                 list.  If it was, this will not work if PARM_BOUNDARY is not
                   3494:                 a multiple of BITS_PER_WORD.  It isn't clear how to fix this
                   3495:                 if it becomes a problem.  */
                   3496: 
                   3497:              if (stack_parm == 0)
1.1.1.4   root     3498:                {
                   3499:                  stack_parm
                   3500:                    = assign_stack_local (GET_MODE (entry_parm), size_stored, 0);
                   3501:                  /* If this is a memory ref that contains aggregate components,
                   3502:                     mark it as such for cse and loop optimize.  */
                   3503:                  MEM_IN_STRUCT_P (stack_parm) = aggregate;
                   3504:                }
                   3505: 
1.1       root     3506:              else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
                   3507:                abort ();
                   3508: 
1.1.1.7 ! root     3509:              if (TREE_READONLY (parm))
        !          3510:                RTX_UNCHANGING_P (stack_parm) = 1;
        !          3511: 
1.1       root     3512:              move_block_from_reg (REGNO (entry_parm),
                   3513:                                   validize_mem (stack_parm),
1.1.1.6   root     3514:                                   size_stored / UNITS_PER_WORD,
                   3515:                                   int_size_in_bytes (TREE_TYPE (parm)));
1.1       root     3516:            }
                   3517:          DECL_RTL (parm) = stack_parm;
                   3518:        }
1.1.1.4   root     3519:       else if (! ((obey_regdecls && ! DECL_REGISTER (parm)
                   3520:                   && ! DECL_INLINE (fndecl))
1.1       root     3521:                  /* layout_decl may set this.  */
                   3522:                  || TREE_ADDRESSABLE (parm)
                   3523:                  || TREE_SIDE_EFFECTS (parm)
                   3524:                  /* If -ffloat-store specified, don't put explicit
                   3525:                     float variables into registers.  */
                   3526:                  || (flag_float_store
                   3527:                      && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))
                   3528:               /* Always assign pseudo to structure return or item passed
                   3529:                  by invisible reference.  */
                   3530:               || passed_pointer || parm == function_result_decl)
                   3531:        {
1.1.1.4   root     3532:          /* Store the parm in a pseudoregister during the function, but we
                   3533:             may need to do it in a wider mode.  */
                   3534: 
                   3535:          register rtx parmreg;
1.1.1.7 ! root     3536:          int regno, regnoi, regnor;
1.1.1.4   root     3537: 
                   3538:          unsignedp = TREE_UNSIGNED (TREE_TYPE (parm));
1.1.1.7 ! root     3539:          nominal_mode = promote_mode (TREE_TYPE (parm), nominal_mode,
        !          3540:                                       &unsignedp, 1);
1.1       root     3541: 
1.1.1.4   root     3542:          parmreg = gen_reg_rtx (nominal_mode);
1.1       root     3543:          REG_USERVAR_P (parmreg) = 1;
                   3544: 
                   3545:          /* If this was an item that we received a pointer to, set DECL_RTL
                   3546:             appropriately.  */
                   3547:          if (passed_pointer)
                   3548:            {
                   3549:              DECL_RTL (parm) = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
                   3550:              MEM_IN_STRUCT_P (DECL_RTL (parm)) = aggregate;
                   3551:            }
                   3552:          else
                   3553:            DECL_RTL (parm) = parmreg;
                   3554: 
                   3555:          /* Copy the value into the register.  */
                   3556:          if (GET_MODE (parmreg) != GET_MODE (entry_parm))
1.1.1.2   root     3557:            {
                   3558:              /* If ENTRY_PARM is a hard register, it might be in a register
                   3559:                 not valid for operating in its mode (e.g., an odd-numbered
                   3560:                 register for a DFmode).  In that case, moves are the only
                   3561:                 thing valid, so we can't do a convert from there.  This
                   3562:                 occurs when the calling sequence allow such misaligned
1.1.1.5   root     3563:                 usages.
                   3564: 
                   3565:                 In addition, the conversion may involve a call, which could
                   3566:                 clobber parameters which haven't been copied to pseudo
                   3567:                 registers yet.  Therefore, we must first copy the parm to
                   3568:                 a pseudo reg here, and save the conversion until after all
                   3569:                 parameters have been moved.  */
                   3570: 
                   3571:              rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
                   3572: 
                   3573:              emit_move_insn (tempreg, validize_mem (entry_parm));
                   3574: 
                   3575:              push_to_sequence (conversion_insns);
                   3576:              convert_move (parmreg, tempreg, unsignedp);
                   3577:              conversion_insns = get_insns ();
                   3578:              end_sequence ();
1.1.1.2   root     3579:            }
1.1       root     3580:          else
                   3581:            emit_move_insn (parmreg, validize_mem (entry_parm));
                   3582: 
1.1.1.4   root     3583:          /* If we were passed a pointer but the actual value
                   3584:             can safely live in a register, put it in one.  */
                   3585:          if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
                   3586:              && ! ((obey_regdecls && ! DECL_REGISTER (parm)
                   3587:                     && ! DECL_INLINE (fndecl))
                   3588:                    /* layout_decl may set this.  */
                   3589:                    || TREE_ADDRESSABLE (parm)
                   3590:                    || TREE_SIDE_EFFECTS (parm)
                   3591:                    /* If -ffloat-store specified, don't put explicit
                   3592:                       float variables into registers.  */
                   3593:                    || (flag_float_store
                   3594:                        && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE)))
                   3595:            {
                   3596:              /* We can't use nominal_mode, because it will have been set to
                   3597:                 Pmode above.  We must use the actual mode of the parm.  */
                   3598:              parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
1.1.1.7 ! root     3599:              REG_USERVAR_P (parmreg) = 1;
1.1.1.4   root     3600:              emit_move_insn (parmreg, DECL_RTL (parm));
                   3601:              DECL_RTL (parm) = parmreg;
1.1.1.6   root     3602:              /* STACK_PARM is the pointer, not the parm, and PARMREG is
                   3603:                 now the parm.  */
                   3604:              stack_parm = 0;
1.1.1.4   root     3605:            }
1.1.1.5   root     3606: #ifdef FUNCTION_ARG_CALLEE_COPIES
                   3607:          /* If we are passed an arg by reference and it is our responsibility
                   3608:             to make a copy, do it now.
                   3609:             PASSED_TYPE and PASSED mode now refer to the pointer, not the
                   3610:             original argument, so we must recreate them in the call to
                   3611:             FUNCTION_ARG_CALLEE_COPIES.  */
                   3612:          /* ??? Later add code to handle the case that if the argument isn't
                   3613:             modified, don't do the copy.  */
                   3614: 
                   3615:          else if (passed_pointer
                   3616:                   && FUNCTION_ARG_CALLEE_COPIES (args_so_far,
                   3617:                                                  TYPE_MODE (DECL_ARG_TYPE (parm)),
                   3618:                                                  DECL_ARG_TYPE (parm),
                   3619:                                                  ! last_named))
                   3620:            {
                   3621:              rtx copy;
                   3622:              tree type = DECL_ARG_TYPE (parm);
                   3623: 
                   3624:              /* This sequence may involve a library call perhaps clobbering
                   3625:                 registers that haven't been copied to pseudos yet.  */
                   3626: 
                   3627:              push_to_sequence (conversion_insns);
                   3628: 
                   3629:              if (TYPE_SIZE (type) == 0
                   3630:                  || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
1.1.1.7 ! root     3631:                /* This is a variable sized object.  */
        !          3632:                copy = gen_rtx (MEM, BLKmode,
        !          3633:                                allocate_dynamic_stack_space
        !          3634:                                (expr_size (parm), NULL_RTX,
        !          3635:                                 TYPE_ALIGN (type)));
1.1.1.5   root     3636:              else
1.1.1.7 ! root     3637:                copy = assign_stack_temp (TYPE_MODE (type),
        !          3638:                                          int_size_in_bytes (type), 1);
1.1.1.5   root     3639: 
                   3640:              store_expr (parm, copy, 0);
                   3641:              emit_move_insn (parmreg, XEXP (copy, 0));
                   3642:              conversion_insns = get_insns ();
                   3643:              end_sequence ();
                   3644:            }
                   3645: #endif /* FUNCTION_ARG_CALLEE_COPIES */
1.1.1.4   root     3646: 
1.1       root     3647:          /* In any case, record the parm's desired stack location
1.1.1.6   root     3648:             in case we later discover it must live in the stack. 
                   3649: 
                   3650:             If it is a COMPLEX value, store the stack location for both
                   3651:             halves.  */
                   3652: 
                   3653:          if (GET_CODE (parmreg) == CONCAT)
                   3654:            regno = MAX (REGNO (XEXP (parmreg, 0)), REGNO (XEXP (parmreg, 1)));
                   3655:          else
                   3656:            regno = REGNO (parmreg);
                   3657: 
                   3658:          if (regno >= nparmregs)
1.1       root     3659:            {
                   3660:              rtx *new;
1.1.1.6   root     3661:              int old_nparmregs = nparmregs;
                   3662: 
                   3663:              nparmregs = regno + 5;
1.1       root     3664:              new = (rtx *) oballoc (nparmregs * sizeof (rtx));
1.1.1.7 ! root     3665:              bcopy ((char *) parm_reg_stack_loc, (char *) new,
        !          3666:                     old_nparmregs * sizeof (rtx));
        !          3667:              bzero ((char *) (new + old_nparmregs),
1.1.1.6   root     3668:                     (nparmregs - old_nparmregs) * sizeof (rtx));
1.1       root     3669:              parm_reg_stack_loc = new;
                   3670:            }
1.1.1.6   root     3671: 
                   3672:          if (GET_CODE (parmreg) == CONCAT)
                   3673:            {
                   3674:              enum machine_mode submode = GET_MODE (XEXP (parmreg, 0));
                   3675: 
1.1.1.7 ! root     3676:              regnor = REGNO (gen_realpart (submode, parmreg));
        !          3677:              regnoi = REGNO (gen_imagpart (submode, parmreg));
        !          3678: 
1.1.1.6   root     3679:              if (stack_parm != 0)
                   3680:                {
1.1.1.7 ! root     3681:                  parm_reg_stack_loc[regnor]
        !          3682:                    = gen_realpart (submode, stack_parm);
        !          3683:                  parm_reg_stack_loc[regnoi]
        !          3684:                    = gen_imagpart (submode, stack_parm);
1.1.1.6   root     3685:                }
                   3686:              else
                   3687:                {
1.1.1.7 ! root     3688:                  parm_reg_stack_loc[regnor] = 0;
        !          3689:                  parm_reg_stack_loc[regnoi] = 0;
1.1.1.6   root     3690:                }
                   3691:            }
                   3692:          else
                   3693:            parm_reg_stack_loc[REGNO (parmreg)] = stack_parm;
1.1       root     3694: 
                   3695:          /* Mark the register as eliminable if we did no conversion
                   3696:             and it was copied from memory at a fixed offset,
                   3697:             and the arg pointer was not copied to a pseudo-reg.
                   3698:             If the arg pointer is a pseudo reg or the offset formed
                   3699:             an invalid address, such memory-equivalences
                   3700:             as we make here would screw up life analysis for it.  */
                   3701:          if (nominal_mode == passed_mode
1.1.1.7 ! root     3702:              && ! conversion_insns
1.1       root     3703:              && GET_CODE (entry_parm) == MEM
1.1.1.3   root     3704:              && entry_parm == stack_parm
1.1       root     3705:              && stack_offset.var == 0
                   3706:              && reg_mentioned_p (virtual_incoming_args_rtx,
                   3707:                                  XEXP (entry_parm, 0)))
1.1.1.7 ! root     3708:            {
        !          3709:              rtx linsn = get_last_insn ();
        !          3710: 
        !          3711:              /* Mark complex types separately.  */
        !          3712:              if (GET_CODE (parmreg) == CONCAT)
        !          3713:                {
        !          3714:                  REG_NOTES (linsn)
        !          3715:                      = gen_rtx (EXPR_LIST, REG_EQUIV,
        !          3716:                                 parm_reg_stack_loc[regnoi], REG_NOTES (linsn));
        !          3717: 
        !          3718:                  /* Now search backward for where we set the real part.  */
        !          3719:                  for (; linsn != 0
        !          3720:                       && ! reg_referenced_p (parm_reg_stack_loc[regnor],
        !          3721:                                              PATTERN (linsn));
        !          3722:                       linsn = prev_nonnote_insn (linsn))
        !          3723:                    ;
        !          3724: 
        !          3725:                  REG_NOTES (linsn)
        !          3726:                      = gen_rtx (EXPR_LIST, REG_EQUIV,
        !          3727:                                 parm_reg_stack_loc[regnor], REG_NOTES (linsn));
        !          3728:                }
        !          3729:              else
        !          3730:                REG_NOTES (linsn)
        !          3731:                 = gen_rtx (EXPR_LIST, REG_EQUIV,
        !          3732:                            entry_parm, REG_NOTES (linsn));
        !          3733:            }
1.1       root     3734: 
                   3735:          /* For pointer data type, suggest pointer register.  */
                   3736:          if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
                   3737:            mark_reg_pointer (parmreg);
                   3738:        }
                   3739:       else
                   3740:        {
                   3741:          /* Value must be stored in the stack slot STACK_PARM
                   3742:             during function execution.  */
                   3743: 
                   3744:          if (passed_mode != nominal_mode)
1.1.1.2   root     3745:            {
                   3746:              /* Conversion is required.   */
1.1.1.5   root     3747:              rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
1.1.1.2   root     3748: 
1.1.1.5   root     3749:              emit_move_insn (tempreg, validize_mem (entry_parm));
                   3750: 
                   3751:              push_to_sequence (conversion_insns);
                   3752:              entry_parm = convert_to_mode (nominal_mode, tempreg,
1.1.1.4   root     3753:                                            TREE_UNSIGNED (TREE_TYPE (parm)));
1.1.1.5   root     3754:              conversion_insns = get_insns ();
                   3755:              end_sequence ();
1.1.1.2   root     3756:            }
1.1       root     3757: 
                   3758:          if (entry_parm != stack_parm)
                   3759:            {
                   3760:              if (stack_parm == 0)
1.1.1.4   root     3761:                {
                   3762:                  stack_parm
                   3763:                    = assign_stack_local (GET_MODE (entry_parm),
                   3764:                                          GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
                   3765:                  /* If this is a memory ref that contains aggregate components,
                   3766:                     mark it as such for cse and loop optimize.  */
                   3767:                  MEM_IN_STRUCT_P (stack_parm) = aggregate;
                   3768:                }
                   3769: 
1.1.1.5   root     3770:              if (passed_mode != nominal_mode)
                   3771:                {
                   3772:                  push_to_sequence (conversion_insns);
                   3773:                  emit_move_insn (validize_mem (stack_parm),
                   3774:                                  validize_mem (entry_parm));
                   3775:                  conversion_insns = get_insns ();
                   3776:                  end_sequence ();
                   3777:                }
                   3778:              else
                   3779:                emit_move_insn (validize_mem (stack_parm),
                   3780:                                validize_mem (entry_parm));
1.1       root     3781:            }
                   3782: 
                   3783:          DECL_RTL (parm) = stack_parm;
                   3784:        }
                   3785:       
                   3786:       /* If this "parameter" was the place where we are receiving the
                   3787:         function's incoming structure pointer, set up the result.  */
                   3788:       if (parm == function_result_decl)
1.1.1.7 ! root     3789:        {
        !          3790:          tree result = DECL_RESULT (fndecl);
        !          3791:          tree restype = TREE_TYPE (result);
        !          3792: 
        !          3793:          DECL_RTL (result)
        !          3794:            = gen_rtx (MEM, DECL_MODE (result), DECL_RTL (parm));
        !          3795: 
        !          3796:          MEM_IN_STRUCT_P (DECL_RTL (result)) = AGGREGATE_TYPE_P (restype);
        !          3797:        }
1.1       root     3798: 
                   3799:       if (TREE_THIS_VOLATILE (parm))
                   3800:        MEM_VOLATILE_P (DECL_RTL (parm)) = 1;
                   3801:       if (TREE_READONLY (parm))
                   3802:        RTX_UNCHANGING_P (DECL_RTL (parm)) = 1;
                   3803:     }
                   3804: 
1.1.1.5   root     3805:   /* Output all parameter conversion instructions (possibly including calls)
                   3806:      now that all parameters have been copied out of hard registers.  */
                   3807:   emit_insns (conversion_insns);
                   3808: 
1.1       root     3809:   max_parm_reg = max_reg_num ();
                   3810:   last_parm_insn = get_last_insn ();
                   3811: 
                   3812:   current_function_args_size = stack_args_size.constant;
                   3813: 
                   3814:   /* Adjust function incoming argument size for alignment and
                   3815:      minimum length.  */
                   3816: 
                   3817: #ifdef REG_PARM_STACK_SPACE
1.1.1.3   root     3818: #ifndef MAYBE_REG_PARM_STACK_SPACE
1.1       root     3819:   current_function_args_size = MAX (current_function_args_size,
                   3820:                                    REG_PARM_STACK_SPACE (fndecl));
                   3821: #endif
1.1.1.3   root     3822: #endif
1.1       root     3823: 
                   3824: #ifdef STACK_BOUNDARY
                   3825: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
                   3826: 
                   3827:   current_function_args_size
                   3828:     = ((current_function_args_size + STACK_BYTES - 1)
                   3829:        / STACK_BYTES) * STACK_BYTES;
                   3830: #endif  
                   3831: 
                   3832: #ifdef ARGS_GROW_DOWNWARD
                   3833:   current_function_arg_offset_rtx
1.1.1.4   root     3834:     = (stack_args_size.var == 0 ? GEN_INT (-stack_args_size.constant)
1.1       root     3835:        : expand_expr (size_binop (MINUS_EXPR, stack_args_size.var,     
                   3836:                                  size_int (-stack_args_size.constant)),   
1.1.1.4   root     3837:                      NULL_RTX, VOIDmode, 0));
1.1       root     3838: #else
                   3839:   current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size);
                   3840: #endif
                   3841: 
                   3842:   /* See how many bytes, if any, of its args a function should try to pop
                   3843:      on return.  */
                   3844: 
                   3845:   current_function_pops_args = RETURN_POPS_ARGS (TREE_TYPE (fndecl),
                   3846:                                                 current_function_args_size);
                   3847: 
1.1.1.7 ! root     3848:   /* For stdarg.h function, save info about
        !          3849:      regs and stack space used by the named args.  */
1.1       root     3850: 
1.1.1.7 ! root     3851:   if (!hide_last_arg)
1.1       root     3852:     current_function_args_info = args_so_far;
                   3853: 
                   3854:   /* Set the rtx used for the function return value.  Put this in its
                   3855:      own variable so any optimizers that need this information don't have
                   3856:      to include tree.h.  Do this here so it gets done when an inlined
                   3857:      function gets output.  */
                   3858: 
                   3859:   current_function_return_rtx = DECL_RTL (DECL_RESULT (fndecl));
                   3860: }
                   3861: 
1.1.1.5   root     3862: /* Indicate whether REGNO is an incoming argument to the current function
                   3863:    that was promoted to a wider mode.  If so, return the RTX for the
                   3864:    register (to get its mode).  PMODE and PUNSIGNEDP are set to the mode
                   3865:    that REGNO is promoted from and whether the promotion was signed or
                   3866:    unsigned.  */
                   3867: 
                   3868: #ifdef PROMOTE_FUNCTION_ARGS
                   3869: 
                   3870: rtx
                   3871: promoted_input_arg (regno, pmode, punsignedp)
                   3872:      int regno;
                   3873:      enum machine_mode *pmode;
                   3874:      int *punsignedp;
                   3875: {
                   3876:   tree arg;
                   3877: 
                   3878:   for (arg = DECL_ARGUMENTS (current_function_decl); arg;
                   3879:        arg = TREE_CHAIN (arg))
                   3880:     if (GET_CODE (DECL_INCOMING_RTL (arg)) == REG
1.1.1.7 ! root     3881:        && REGNO (DECL_INCOMING_RTL (arg)) == regno)
1.1.1.5   root     3882:       {
                   3883:        enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
                   3884:        int unsignedp = TREE_UNSIGNED (TREE_TYPE (arg));
                   3885: 
1.1.1.7 ! root     3886:        mode = promote_mode (TREE_TYPE (arg), mode, &unsignedp, 1);
1.1.1.5   root     3887:        if (mode == GET_MODE (DECL_INCOMING_RTL (arg))
                   3888:            && mode != DECL_MODE (arg))
                   3889:          {
                   3890:            *pmode = DECL_MODE (arg);
                   3891:            *punsignedp = unsignedp;
                   3892:            return DECL_INCOMING_RTL (arg);
                   3893:          }
                   3894:       }
                   3895: 
                   3896:   return 0;
                   3897: }
                   3898: 
                   3899: #endif
                   3900: 
1.1       root     3901: /* Compute the size and offset from the start of the stacked arguments for a
                   3902:    parm passed in mode PASSED_MODE and with type TYPE.
                   3903: 
                   3904:    INITIAL_OFFSET_PTR points to the current offset into the stacked
                   3905:    arguments.
                   3906: 
                   3907:    The starting offset and size for this parm are returned in *OFFSET_PTR
                   3908:    and *ARG_SIZE_PTR, respectively.
                   3909: 
                   3910:    IN_REGS is non-zero if the argument will be passed in registers.  It will
                   3911:    never be set if REG_PARM_STACK_SPACE is not defined.
                   3912: 
                   3913:    FNDECL is the function in which the argument was defined.
                   3914: 
                   3915:    There are two types of rounding that are done.  The first, controlled by
                   3916:    FUNCTION_ARG_BOUNDARY, forces the offset from the start of the argument
                   3917:    list to be aligned to the specific boundary (in bits).  This rounding
                   3918:    affects the initial and starting offsets, but not the argument size.
                   3919: 
                   3920:    The second, controlled by FUNCTION_ARG_PADDING and PARM_BOUNDARY,
                   3921:    optionally rounds the size of the parm to PARM_BOUNDARY.  The
                   3922:    initial offset is not affected by this rounding, while the size always
                   3923:    is and the starting offset may be.  */
                   3924: 
                   3925: /*  offset_ptr will be negative for ARGS_GROW_DOWNWARD case; 
                   3926:     initial_offset_ptr is positive because locate_and_pad_parm's
                   3927:     callers pass in the total size of args so far as
                   3928:     initial_offset_ptr. arg_size_ptr is always positive.*/
                   3929: 
                   3930: void
                   3931: locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
                   3932:                     initial_offset_ptr, offset_ptr, arg_size_ptr)
                   3933:      enum machine_mode passed_mode;
                   3934:      tree type;
                   3935:      int in_regs;
                   3936:      tree fndecl;
                   3937:      struct args_size *initial_offset_ptr;
                   3938:      struct args_size *offset_ptr;
                   3939:      struct args_size *arg_size_ptr;
                   3940: {
                   3941:   tree sizetree
                   3942:     = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
                   3943:   enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
                   3944:   int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
                   3945:   int boundary_in_bytes = boundary / BITS_PER_UNIT;
                   3946:   int reg_parm_stack_space = 0;
                   3947: 
                   3948: #ifdef REG_PARM_STACK_SPACE
                   3949:   /* If we have found a stack parm before we reach the end of the
                   3950:      area reserved for registers, skip that area.  */
                   3951:   if (! in_regs)
                   3952:     {
1.1.1.3   root     3953: #ifdef MAYBE_REG_PARM_STACK_SPACE
                   3954:       reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
                   3955: #else
1.1       root     3956:       reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
1.1.1.3   root     3957: #endif
1.1       root     3958:       if (reg_parm_stack_space > 0)
                   3959:        {
                   3960:          if (initial_offset_ptr->var)
                   3961:            {
                   3962:              initial_offset_ptr->var
                   3963:                = size_binop (MAX_EXPR, ARGS_SIZE_TREE (*initial_offset_ptr),
                   3964:                              size_int (reg_parm_stack_space));
                   3965:              initial_offset_ptr->constant = 0;
                   3966:            }
                   3967:          else if (initial_offset_ptr->constant < reg_parm_stack_space)
                   3968:            initial_offset_ptr->constant = reg_parm_stack_space;
                   3969:        }
                   3970:     }
                   3971: #endif /* REG_PARM_STACK_SPACE */
                   3972: 
                   3973:   arg_size_ptr->var = 0;
                   3974:   arg_size_ptr->constant = 0;
                   3975: 
                   3976: #ifdef ARGS_GROW_DOWNWARD
                   3977:   if (initial_offset_ptr->var)
                   3978:     {
                   3979:       offset_ptr->constant = 0;
                   3980:       offset_ptr->var = size_binop (MINUS_EXPR, integer_zero_node,
                   3981:                                    initial_offset_ptr->var);
                   3982:     }
                   3983:   else
                   3984:     {
                   3985:       offset_ptr->constant = - initial_offset_ptr->constant;
                   3986:       offset_ptr->var = 0;
                   3987:     }
1.1.1.7 ! root     3988:   if (where_pad != none
1.1       root     3989:       && (TREE_CODE (sizetree) != INTEGER_CST
                   3990:          || ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
                   3991:     sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
                   3992:   SUB_PARM_SIZE (*offset_ptr, sizetree);
1.1.1.4   root     3993:   if (where_pad != downward)
                   3994:     pad_to_arg_alignment (offset_ptr, boundary);
1.1       root     3995:   if (initial_offset_ptr->var)
                   3996:     {
                   3997:       arg_size_ptr->var = size_binop (MINUS_EXPR,
                   3998:                                      size_binop (MINUS_EXPR,
                   3999:                                                  integer_zero_node,
                   4000:                                                  initial_offset_ptr->var),
                   4001:                                      offset_ptr->var);
                   4002:     }
                   4003:   else
                   4004:     {
                   4005:       arg_size_ptr->constant = (- initial_offset_ptr->constant -
                   4006:                                offset_ptr->constant); 
                   4007:     }
                   4008: #else /* !ARGS_GROW_DOWNWARD */
                   4009:   pad_to_arg_alignment (initial_offset_ptr, boundary);
                   4010:   *offset_ptr = *initial_offset_ptr;
                   4011: 
                   4012: #ifdef PUSH_ROUNDING
                   4013:   if (passed_mode != BLKmode)
                   4014:     sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
                   4015: #endif
                   4016: 
                   4017:   if (where_pad != none
                   4018:       && (TREE_CODE (sizetree) != INTEGER_CST
                   4019:          || ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
                   4020:     sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
                   4021: 
1.1.1.6   root     4022:   /* This must be done after rounding sizetree, so that it will subtract
                   4023:      the same value that we explicitly add below.  */
                   4024:   if (where_pad == downward)
                   4025:     pad_below (offset_ptr, passed_mode, sizetree);
1.1       root     4026:   ADD_PARM_SIZE (*arg_size_ptr, sizetree);
                   4027: #endif /* ARGS_GROW_DOWNWARD */
                   4028: }
                   4029: 
1.1.1.3   root     4030: /* Round the stack offset in *OFFSET_PTR up to a multiple of BOUNDARY.
                   4031:    BOUNDARY is measured in bits, but must be a multiple of a storage unit.  */
                   4032: 
1.1       root     4033: static void
                   4034: pad_to_arg_alignment (offset_ptr, boundary)
                   4035:      struct args_size *offset_ptr;
                   4036:      int boundary;
                   4037: {
                   4038:   int boundary_in_bytes = boundary / BITS_PER_UNIT;
                   4039:   
                   4040:   if (boundary > BITS_PER_UNIT)
                   4041:     {
                   4042:       if (offset_ptr->var)
                   4043:        {
                   4044:          offset_ptr->var  =
                   4045: #ifdef ARGS_GROW_DOWNWARD
                   4046:            round_down 
                   4047: #else
                   4048:            round_up
                   4049: #endif
                   4050:              (ARGS_SIZE_TREE (*offset_ptr),
                   4051:               boundary / BITS_PER_UNIT);
                   4052:          offset_ptr->constant = 0; /*?*/
                   4053:        }
                   4054:       else
                   4055:        offset_ptr->constant =
                   4056: #ifdef ARGS_GROW_DOWNWARD
                   4057:          FLOOR_ROUND (offset_ptr->constant, boundary_in_bytes);
                   4058: #else
                   4059:          CEIL_ROUND (offset_ptr->constant, boundary_in_bytes);
                   4060: #endif
                   4061:     }
                   4062: }
                   4063: 
                   4064: static void
                   4065: pad_below (offset_ptr, passed_mode, sizetree)
                   4066:      struct args_size *offset_ptr;
                   4067:      enum machine_mode passed_mode;
                   4068:      tree sizetree;
                   4069: {
                   4070:   if (passed_mode != BLKmode)
                   4071:     {
                   4072:       if (GET_MODE_BITSIZE (passed_mode) % PARM_BOUNDARY)
                   4073:        offset_ptr->constant
                   4074:          += (((GET_MODE_BITSIZE (passed_mode) + PARM_BOUNDARY - 1)
                   4075:               / PARM_BOUNDARY * PARM_BOUNDARY / BITS_PER_UNIT)
                   4076:              - GET_MODE_SIZE (passed_mode));
                   4077:     }
                   4078:   else
                   4079:     {
                   4080:       if (TREE_CODE (sizetree) != INTEGER_CST
                   4081:          || (TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
                   4082:        {
                   4083:          /* Round the size up to multiple of PARM_BOUNDARY bits.  */
                   4084:          tree s2 = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
                   4085:          /* Add it in.  */
                   4086:          ADD_PARM_SIZE (*offset_ptr, s2);
                   4087:          SUB_PARM_SIZE (*offset_ptr, sizetree);
                   4088:        }
                   4089:     }
                   4090: }
                   4091: 
                   4092: static tree
                   4093: round_down (value, divisor)
                   4094:      tree value;
                   4095:      int divisor;
                   4096: {
                   4097:   return size_binop (MULT_EXPR,
                   4098:                     size_binop (FLOOR_DIV_EXPR, value, size_int (divisor)),
                   4099:                     size_int (divisor));
                   4100: }
                   4101: 
                   4102: /* Walk the tree of blocks describing the binding levels within a function
                   4103:    and warn about uninitialized variables.
                   4104:    This is done after calling flow_analysis and before global_alloc
                   4105:    clobbers the pseudo-regs to hard regs.  */
                   4106: 
                   4107: void
                   4108: uninitialized_vars_warning (block)
                   4109:      tree block;
                   4110: {
                   4111:   register tree decl, sub;
                   4112:   for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
                   4113:     {
                   4114:       if (TREE_CODE (decl) == VAR_DECL
                   4115:          /* These warnings are unreliable for and aggregates
                   4116:             because assigning the fields one by one can fail to convince
                   4117:             flow.c that the entire aggregate was initialized.
                   4118:             Unions are troublesome because members may be shorter.  */
1.1.1.7 ! root     4119:          && ! AGGREGATE_TYPE_P (TREE_TYPE (decl))
1.1       root     4120:          && DECL_RTL (decl) != 0
                   4121:          && GET_CODE (DECL_RTL (decl)) == REG
                   4122:          && regno_uninitialized (REGNO (DECL_RTL (decl))))
                   4123:        warning_with_decl (decl,
1.1.1.7 ! root     4124:                           "`%s' might be used uninitialized in this function");
1.1       root     4125:       if (TREE_CODE (decl) == VAR_DECL
                   4126:          && DECL_RTL (decl) != 0
                   4127:          && GET_CODE (DECL_RTL (decl)) == REG
                   4128:          && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
                   4129:        warning_with_decl (decl,
1.1.1.7 ! root     4130:                           "variable `%s' might be clobbered by `longjmp' or `vfork'");
1.1       root     4131:     }
                   4132:   for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
                   4133:     uninitialized_vars_warning (sub);
                   4134: }
                   4135: 
                   4136: /* Do the appropriate part of uninitialized_vars_warning
                   4137:    but for arguments instead of local variables.  */
                   4138: 
                   4139: void
                   4140: setjmp_args_warning (block)
                   4141:      tree block;
                   4142: {
                   4143:   register tree decl;
                   4144:   for (decl = DECL_ARGUMENTS (current_function_decl);
                   4145:        decl; decl = TREE_CHAIN (decl))
                   4146:     if (DECL_RTL (decl) != 0
                   4147:        && GET_CODE (DECL_RTL (decl)) == REG
                   4148:        && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
1.1.1.7 ! root     4149:       warning_with_decl (decl, "argument `%s' might be clobbered by `longjmp' or `vfork'");
1.1       root     4150: }
                   4151: 
                   4152: /* If this function call setjmp, put all vars into the stack
                   4153:    unless they were declared `register'.  */
                   4154: 
                   4155: void
                   4156: setjmp_protect (block)
                   4157:      tree block;
                   4158: {
                   4159:   register tree decl, sub;
                   4160:   for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
                   4161:     if ((TREE_CODE (decl) == VAR_DECL
                   4162:         || TREE_CODE (decl) == PARM_DECL)
                   4163:        && DECL_RTL (decl) != 0
                   4164:        && GET_CODE (DECL_RTL (decl)) == REG
1.1.1.2   root     4165:        /* If this variable came from an inline function, it must be
                   4166:           that it's life doesn't overlap the setjmp.  If there was a
                   4167:           setjmp in the function, it would already be in memory.  We
                   4168:           must exclude such variable because their DECL_RTL might be
                   4169:           set to strange things such as virtual_stack_vars_rtx.  */
                   4170:        && ! DECL_FROM_INLINE (decl)
1.1       root     4171:        && (
                   4172: #ifdef NON_SAVING_SETJMP
                   4173:            /* If longjmp doesn't restore the registers,
                   4174:               don't put anything in them.  */
                   4175:            NON_SAVING_SETJMP
                   4176:            ||
                   4177: #endif
1.1.1.4   root     4178:            ! DECL_REGISTER (decl)))
1.1       root     4179:       put_var_into_stack (decl);
                   4180:   for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
                   4181:     setjmp_protect (sub);
                   4182: }
                   4183: 
                   4184: /* Like the previous function, but for args instead of local variables.  */
                   4185: 
                   4186: void
                   4187: setjmp_protect_args ()
                   4188: {
                   4189:   register tree decl, sub;
                   4190:   for (decl = DECL_ARGUMENTS (current_function_decl);
                   4191:        decl; decl = TREE_CHAIN (decl))
                   4192:     if ((TREE_CODE (decl) == VAR_DECL
                   4193:         || TREE_CODE (decl) == PARM_DECL)
                   4194:        && DECL_RTL (decl) != 0
                   4195:        && GET_CODE (DECL_RTL (decl)) == REG
                   4196:        && (
                   4197:            /* If longjmp doesn't restore the registers,
                   4198:               don't put anything in them.  */
                   4199: #ifdef NON_SAVING_SETJMP
                   4200:            NON_SAVING_SETJMP
                   4201:            ||
                   4202: #endif
1.1.1.4   root     4203:            ! DECL_REGISTER (decl)))
1.1       root     4204:       put_var_into_stack (decl);
                   4205: }
                   4206: 
                   4207: /* Return the context-pointer register corresponding to DECL,
                   4208:    or 0 if it does not need one.  */
                   4209: 
                   4210: rtx
                   4211: lookup_static_chain (decl)
                   4212:      tree decl;
                   4213: {
                   4214:   tree context = decl_function_context (decl);
                   4215:   tree link;
                   4216: 
                   4217:   if (context == 0)
                   4218:     return 0;
                   4219:   
                   4220:   /* We treat inline_function_decl as an alias for the current function
                   4221:      because that is the inline function whose vars, types, etc.
                   4222:      are being merged into the current function.
                   4223:      See expand_inline_function.  */
                   4224:   if (context == current_function_decl || context == inline_function_decl)
                   4225:     return virtual_stack_vars_rtx;
                   4226: 
                   4227:   for (link = context_display; link; link = TREE_CHAIN (link))
                   4228:     if (TREE_PURPOSE (link) == context)
                   4229:       return RTL_EXPR_RTL (TREE_VALUE (link));
                   4230: 
                   4231:   abort ();
                   4232: }
                   4233: 
                   4234: /* Convert a stack slot address ADDR for variable VAR
                   4235:    (from a containing function)
                   4236:    into an address valid in this function (using a static chain).  */
                   4237: 
                   4238: rtx
                   4239: fix_lexical_addr (addr, var)
                   4240:      rtx addr;
                   4241:      tree var;
                   4242: {
                   4243:   rtx basereg;
                   4244:   int displacement;
                   4245:   tree context = decl_function_context (var);
                   4246:   struct function *fp;
                   4247:   rtx base = 0;
                   4248: 
                   4249:   /* If this is the present function, we need not do anything.  */
                   4250:   if (context == current_function_decl || context == inline_function_decl)
                   4251:     return addr;
                   4252: 
                   4253:   for (fp = outer_function_chain; fp; fp = fp->next)
                   4254:     if (fp->decl == context)
                   4255:       break;
                   4256: 
                   4257:   if (fp == 0)
                   4258:     abort ();
                   4259: 
                   4260:   /* Decode given address as base reg plus displacement.  */
                   4261:   if (GET_CODE (addr) == REG)
                   4262:     basereg = addr, displacement = 0;
                   4263:   else if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT)
                   4264:     basereg = XEXP (addr, 0), displacement = INTVAL (XEXP (addr, 1));
                   4265:   else
                   4266:     abort ();
                   4267: 
                   4268:   /* We accept vars reached via the containing function's
                   4269:      incoming arg pointer and via its stack variables pointer.  */
                   4270:   if (basereg == fp->internal_arg_pointer)
                   4271:     {
                   4272:       /* If reached via arg pointer, get the arg pointer value
                   4273:         out of that function's stack frame.
                   4274: 
                   4275:         There are two cases:  If a separate ap is needed, allocate a
                   4276:         slot in the outer function for it and dereference it that way.
                   4277:         This is correct even if the real ap is actually a pseudo.
                   4278:         Otherwise, just adjust the offset from the frame pointer to
                   4279:         compensate.  */
                   4280: 
                   4281: #ifdef NEED_SEPARATE_AP
                   4282:       rtx addr;
                   4283: 
                   4284:       if (fp->arg_pointer_save_area == 0)
                   4285:        fp->arg_pointer_save_area
                   4286:          = assign_outer_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0, fp);
                   4287: 
                   4288:       addr = fix_lexical_addr (XEXP (fp->arg_pointer_save_area, 0), var);
                   4289:       addr = memory_address (Pmode, addr);
                   4290: 
                   4291:       base = copy_to_reg (gen_rtx (MEM, Pmode, addr));
                   4292: #else
                   4293:       displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET);
1.1.1.2   root     4294:       base = lookup_static_chain (var);
1.1       root     4295: #endif
                   4296:     }
                   4297: 
                   4298:   else if (basereg == virtual_stack_vars_rtx)
                   4299:     {
                   4300:       /* This is the same code as lookup_static_chain, duplicated here to
                   4301:         avoid an extra call to decl_function_context.  */
                   4302:       tree link;
                   4303: 
                   4304:       for (link = context_display; link; link = TREE_CHAIN (link))
                   4305:        if (TREE_PURPOSE (link) == context)
                   4306:          {
                   4307:            base = RTL_EXPR_RTL (TREE_VALUE (link));
                   4308:            break;
                   4309:          }
                   4310:     }
                   4311: 
                   4312:   if (base == 0)
                   4313:     abort ();
                   4314: 
                   4315:   /* Use same offset, relative to appropriate static chain or argument
                   4316:      pointer.  */
                   4317:   return plus_constant (base, displacement);
                   4318: }
                   4319: 
                   4320: /* Return the address of the trampoline for entering nested fn FUNCTION.
                   4321:    If necessary, allocate a trampoline (in the stack frame)
                   4322:    and emit rtl to initialize its contents (at entry to this function).  */
                   4323: 
                   4324: rtx
                   4325: trampoline_address (function)
                   4326:      tree function;
                   4327: {
                   4328:   tree link;
                   4329:   tree rtlexp;
                   4330:   rtx tramp;
                   4331:   struct function *fp;
                   4332:   tree fn_context;
                   4333: 
                   4334:   /* Find an existing trampoline and return it.  */
                   4335:   for (link = trampoline_list; link; link = TREE_CHAIN (link))
                   4336:     if (TREE_PURPOSE (link) == function)
1.1.1.7 ! root     4337:       return
        !          4338:        round_trampoline_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0));
        !          4339: 
1.1       root     4340:   for (fp = outer_function_chain; fp; fp = fp->next)
                   4341:     for (link = fp->trampoline_list; link; link = TREE_CHAIN (link))
                   4342:       if (TREE_PURPOSE (link) == function)
                   4343:        {
                   4344:          tramp = fix_lexical_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0),
                   4345:                                    function);
                   4346:          return round_trampoline_addr (tramp);
                   4347:        }
                   4348: 
                   4349:   /* None exists; we must make one.  */
                   4350: 
                   4351:   /* Find the `struct function' for the function containing FUNCTION.  */
                   4352:   fp = 0;
                   4353:   fn_context = decl_function_context (function);
                   4354:   if (fn_context != current_function_decl)
                   4355:     for (fp = outer_function_chain; fp; fp = fp->next)
                   4356:       if (fp->decl == fn_context)
                   4357:        break;
                   4358: 
                   4359:   /* Allocate run-time space for this trampoline
                   4360:      (usually in the defining function's stack frame).  */
                   4361: #ifdef ALLOCATE_TRAMPOLINE
                   4362:   tramp = ALLOCATE_TRAMPOLINE (fp);
                   4363: #else
                   4364:   /* If rounding needed, allocate extra space
                   4365:      to ensure we have TRAMPOLINE_SIZE bytes left after rounding up.  */
                   4366: #ifdef TRAMPOLINE_ALIGNMENT
                   4367: #define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE + TRAMPOLINE_ALIGNMENT - 1)
                   4368: #else
                   4369: #define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
                   4370: #endif
                   4371:   if (fp != 0)
                   4372:     tramp = assign_outer_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp);
                   4373:   else
                   4374:     tramp = assign_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0);
                   4375: #endif
                   4376: 
                   4377:   /* Record the trampoline for reuse and note it for later initialization
                   4378:      by expand_function_end.  */
                   4379:   if (fp != 0)
                   4380:     {
1.1.1.6   root     4381:       push_obstacks (fp->function_maybepermanent_obstack,
                   4382:                     fp->function_maybepermanent_obstack);
1.1       root     4383:       rtlexp = make_node (RTL_EXPR);
                   4384:       RTL_EXPR_RTL (rtlexp) = tramp;
                   4385:       fp->trampoline_list = tree_cons (function, rtlexp, fp->trampoline_list);
                   4386:       pop_obstacks ();
                   4387:     }
                   4388:   else
                   4389:     {
                   4390:       /* Make the RTL_EXPR node temporary, not momentary, so that the
                   4391:         trampoline_list doesn't become garbage.  */
                   4392:       int momentary = suspend_momentary ();
                   4393:       rtlexp = make_node (RTL_EXPR);
                   4394:       resume_momentary (momentary);
                   4395: 
                   4396:       RTL_EXPR_RTL (rtlexp) = tramp;
                   4397:       trampoline_list = tree_cons (function, rtlexp, trampoline_list);
                   4398:     }
                   4399: 
                   4400:   tramp = fix_lexical_addr (XEXP (tramp, 0), function);
                   4401:   return round_trampoline_addr (tramp);
                   4402: }
                   4403: 
                   4404: /* Given a trampoline address,
                   4405:    round it to multiple of TRAMPOLINE_ALIGNMENT.  */
                   4406: 
                   4407: static rtx
                   4408: round_trampoline_addr (tramp)
                   4409:      rtx tramp;
                   4410: {
                   4411: #ifdef TRAMPOLINE_ALIGNMENT
                   4412:   /* Round address up to desired boundary.  */
                   4413:   rtx temp = gen_reg_rtx (Pmode);
                   4414:   temp = expand_binop (Pmode, add_optab, tramp,
1.1.1.4   root     4415:                       GEN_INT (TRAMPOLINE_ALIGNMENT - 1),
1.1       root     4416:                       temp, 0, OPTAB_LIB_WIDEN);
                   4417:   tramp = expand_binop (Pmode, and_optab, temp,
1.1.1.4   root     4418:                        GEN_INT (- TRAMPOLINE_ALIGNMENT),
1.1       root     4419:                        temp, 0, OPTAB_LIB_WIDEN);
                   4420: #endif
                   4421:   return tramp;
                   4422: }
                   4423: 
1.1.1.4   root     4424: /* The functions identify_blocks and reorder_blocks provide a way to
                   4425:    reorder the tree of BLOCK nodes, for optimizers that reshuffle or
                   4426:    duplicate portions of the RTL code.  Call identify_blocks before
                   4427:    changing the RTL, and call reorder_blocks after.  */
                   4428: 
                   4429: /* Put all this function's BLOCK nodes into a vector, and return it.
                   4430:    Also store in each NOTE for the beginning or end of a block
                   4431:    the index of that block in the vector.
                   4432:    The arguments are TOP_BLOCK, the top-level block of the function,
                   4433:    and INSNS, the insn chain of the function.  */
                   4434: 
                   4435: tree *
                   4436: identify_blocks (top_block, insns)
                   4437:      tree top_block;
                   4438:      rtx insns;
                   4439: {
                   4440:   int n_blocks;
                   4441:   tree *block_vector;
                   4442:   int *block_stack;
                   4443:   int depth = 0;
                   4444:   int next_block_number = 0;
                   4445:   int current_block_number = 0;
                   4446:   rtx insn;
                   4447: 
                   4448:   if (top_block == 0)
                   4449:     return 0;
                   4450: 
                   4451:   n_blocks = all_blocks (top_block, 0);
                   4452:   block_vector = (tree *) xmalloc (n_blocks * sizeof (tree));
                   4453:   block_stack = (int *) alloca (n_blocks * sizeof (int));
                   4454: 
                   4455:   all_blocks (top_block, block_vector);
                   4456: 
                   4457:   for (insn = insns; insn; insn = NEXT_INSN (insn))
                   4458:     if (GET_CODE (insn) == NOTE)
                   4459:       {
                   4460:        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
                   4461:          {
                   4462:            block_stack[depth++] = current_block_number;
                   4463:            current_block_number = next_block_number;
                   4464:            NOTE_BLOCK_NUMBER (insn) =  next_block_number++;
                   4465:          }
                   4466:        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
                   4467:          {
                   4468:            current_block_number = block_stack[--depth];
                   4469:            NOTE_BLOCK_NUMBER (insn) = current_block_number;
                   4470:          }
                   4471:       }
                   4472: 
                   4473:   return block_vector;
                   4474: }
                   4475: 
                   4476: /* Given BLOCK_VECTOR which was returned by identify_blocks,
                   4477:    and a revised instruction chain, rebuild the tree structure
                   4478:    of BLOCK nodes to correspond to the new order of RTL.
                   4479:    The new block tree is inserted below TOP_BLOCK.
                   4480:    Returns the current top-level block.  */
                   4481: 
                   4482: tree
                   4483: reorder_blocks (block_vector, top_block, insns)
                   4484:      tree *block_vector;
                   4485:      tree top_block;
                   4486:      rtx insns;
                   4487: {
                   4488:   tree current_block = top_block;
                   4489:   rtx insn;
                   4490: 
                   4491:   if (block_vector == 0)
                   4492:     return top_block;
                   4493: 
                   4494:   /* Prune the old tree away, so that it doesn't get in the way.  */
                   4495:   BLOCK_SUBBLOCKS (current_block) = 0;
                   4496: 
                   4497:   for (insn = insns; insn; insn = NEXT_INSN (insn))
                   4498:     if (GET_CODE (insn) == NOTE)
                   4499:       {
                   4500:        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
                   4501:          {
                   4502:            tree block = block_vector[NOTE_BLOCK_NUMBER (insn)];
                   4503:            /* If we have seen this block before, copy it.  */
                   4504:            if (TREE_ASM_WRITTEN (block))
                   4505:              block = copy_node (block);
                   4506:            BLOCK_SUBBLOCKS (block) = 0;
                   4507:            TREE_ASM_WRITTEN (block) = 1;
                   4508:            BLOCK_SUPERCONTEXT (block) = current_block; 
                   4509:            BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
                   4510:            BLOCK_SUBBLOCKS (current_block) = block;
                   4511:            current_block = block;
                   4512:            NOTE_SOURCE_FILE (insn) = 0;
                   4513:          }
                   4514:        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
                   4515:          {
                   4516:            BLOCK_SUBBLOCKS (current_block)
                   4517:              = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
                   4518:            current_block = BLOCK_SUPERCONTEXT (current_block);
                   4519:            NOTE_SOURCE_FILE (insn) = 0;
                   4520:          }
                   4521:       }
                   4522: 
                   4523:   return current_block;
                   4524: }
                   4525: 
                   4526: /* Reverse the order of elements in the chain T of blocks,
                   4527:    and return the new head of the chain (old last element).  */
                   4528: 
                   4529: static tree
                   4530: blocks_nreverse (t)
                   4531:      tree t;
                   4532: {
                   4533:   register tree prev = 0, decl, next;
                   4534:   for (decl = t; decl; decl = next)
                   4535:     {
                   4536:       next = BLOCK_CHAIN (decl);
                   4537:       BLOCK_CHAIN (decl) = prev;
                   4538:       prev = decl;
                   4539:     }
                   4540:   return prev;
                   4541: }
                   4542: 
                   4543: /* Count the subblocks of BLOCK, and list them all into the vector VECTOR.
                   4544:    Also clear TREE_ASM_WRITTEN in all blocks.  */
                   4545: 
                   4546: static int
                   4547: all_blocks (block, vector)
                   4548:      tree block;
                   4549:      tree *vector;
                   4550: {
                   4551:   int n_blocks = 1;
                   4552:   tree subblocks; 
                   4553: 
                   4554:   TREE_ASM_WRITTEN (block) = 0;
                   4555:   /* Record this block.  */
                   4556:   if (vector)
                   4557:     vector[0] = block;
                   4558: 
                   4559:   /* Record the subblocks, and their subblocks.  */
                   4560:   for (subblocks = BLOCK_SUBBLOCKS (block);
                   4561:        subblocks; subblocks = BLOCK_CHAIN (subblocks))
                   4562:     n_blocks += all_blocks (subblocks, vector ? vector + n_blocks : 0);
                   4563: 
                   4564:   return n_blocks;
                   4565: }
                   4566: 
1.1.1.6   root     4567: /* Build bytecode call descriptor for function SUBR. */
1.1.1.7 ! root     4568: 
1.1.1.6   root     4569: rtx
                   4570: bc_build_calldesc (subr)
                   4571:   tree subr;
                   4572: {
                   4573:   tree calldesc = 0, arg;
                   4574:   int nargs = 0;
                   4575: 
                   4576:   /* Build the argument description vector in reverse order.  */
                   4577:   DECL_ARGUMENTS (subr) = nreverse (DECL_ARGUMENTS (subr));
                   4578:   nargs = 0;
                   4579: 
                   4580:   for (arg = DECL_ARGUMENTS (subr); arg; arg = TREE_CHAIN (arg))
                   4581:     {
                   4582:       ++nargs;
                   4583: 
                   4584:       calldesc = tree_cons ((tree) 0, size_in_bytes (TREE_TYPE (arg)), calldesc);
                   4585:       calldesc = tree_cons ((tree) 0, bc_runtime_type_code (TREE_TYPE (arg)), calldesc);
                   4586:     }
                   4587: 
                   4588:   DECL_ARGUMENTS (subr) = nreverse (DECL_ARGUMENTS (subr));
                   4589: 
                   4590:   /* Prepend the function's return type.  */
                   4591:   calldesc = tree_cons ((tree) 0,
                   4592:                        size_in_bytes (TREE_TYPE (TREE_TYPE (subr))),
                   4593:                        calldesc);
                   4594: 
                   4595:   calldesc = tree_cons ((tree) 0,
                   4596:                        bc_runtime_type_code (TREE_TYPE (TREE_TYPE (subr))),
                   4597:                        calldesc);
                   4598: 
                   4599:   /* Prepend the arg count.  */
                   4600:   calldesc = tree_cons ((tree) 0, build_int_2 (nargs, 0), calldesc);
                   4601: 
                   4602:   /* Output the call description vector and get its address.  */
                   4603:   calldesc = build_nt (CONSTRUCTOR, (tree) 0, calldesc);
                   4604:   TREE_TYPE (calldesc) = build_array_type (integer_type_node,
                   4605:                                           build_index_type (build_int_2 (nargs * 2, 0)));
                   4606: 
                   4607:   return output_constant_def (calldesc);
                   4608: }
                   4609: 
                   4610: 
1.1       root     4611: /* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node)
                   4612:    and initialize static variables for generating RTL for the statements
                   4613:    of the function.  */
                   4614: 
                   4615: void
                   4616: init_function_start (subr, filename, line)
                   4617:      tree subr;
                   4618:      char *filename;
                   4619:      int line;
                   4620: {
                   4621:   char *junk;
                   4622: 
1.1.1.6   root     4623:   if (output_bytecode)
                   4624:     {
                   4625:       this_function_decl = subr;
                   4626:       this_function_calldesc = bc_build_calldesc (subr);
                   4627:       local_vars_size = 0;
                   4628:       stack_depth = 0;
                   4629:       max_stack_depth = 0;
                   4630:       stmt_expr_depth = 0;
                   4631:       return;
                   4632:     }
                   4633: 
1.1       root     4634:   init_stmt_for_function ();
                   4635: 
                   4636:   cse_not_expected = ! optimize;
                   4637: 
                   4638:   /* Caller save not needed yet.  */
                   4639:   caller_save_needed = 0;
                   4640: 
                   4641:   /* No stack slots have been made yet.  */
                   4642:   stack_slot_list = 0;
                   4643: 
                   4644:   /* There is no stack slot for handling nonlocal gotos.  */
                   4645:   nonlocal_goto_handler_slot = 0;
                   4646:   nonlocal_goto_stack_level = 0;
                   4647: 
                   4648:   /* No labels have been declared for nonlocal use.  */
                   4649:   nonlocal_labels = 0;
                   4650: 
                   4651:   /* No function calls so far in this function.  */
                   4652:   function_call_count = 0;
                   4653: 
                   4654:   /* No parm regs have been allocated.
                   4655:      (This is important for output_inline_function.)  */
                   4656:   max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
                   4657: 
                   4658:   /* Initialize the RTL mechanism.  */
                   4659:   init_emit ();
                   4660: 
                   4661:   /* Initialize the queue of pending postincrement and postdecrements,
                   4662:      and some other info in expr.c.  */
                   4663:   init_expr ();
                   4664: 
                   4665:   /* We haven't done register allocation yet.  */
                   4666:   reg_renumber = 0;
                   4667: 
                   4668:   init_const_rtx_hash_table ();
                   4669: 
                   4670:   current_function_name = (*decl_printable_name) (subr, &junk);
                   4671: 
                   4672:   /* Nonzero if this is a nested function that uses a static chain.  */
                   4673: 
                   4674:   current_function_needs_context
                   4675:     = (decl_function_context (current_function_decl) != 0);
                   4676: 
                   4677:   /* Set if a call to setjmp is seen.  */
                   4678:   current_function_calls_setjmp = 0;
                   4679: 
                   4680:   /* Set if a call to longjmp is seen.  */
                   4681:   current_function_calls_longjmp = 0;
                   4682: 
                   4683:   current_function_calls_alloca = 0;
                   4684:   current_function_has_nonlocal_label = 0;
1.1.1.6   root     4685:   current_function_has_nonlocal_goto = 0;
1.1       root     4686:   current_function_contains_functions = 0;
                   4687: 
                   4688:   current_function_returns_pcc_struct = 0;
                   4689:   current_function_returns_struct = 0;
                   4690:   current_function_epilogue_delay_list = 0;
                   4691:   current_function_uses_const_pool = 0;
                   4692:   current_function_uses_pic_offset_table = 0;
                   4693: 
                   4694:   /* We have not yet needed to make a label to jump to for tail-recursion.  */
                   4695:   tail_recursion_label = 0;
                   4696: 
                   4697:   /* We haven't had a need to make a save area for ap yet.  */
                   4698: 
                   4699:   arg_pointer_save_area = 0;
                   4700: 
                   4701:   /* No stack slots allocated yet.  */
                   4702:   frame_offset = 0;
                   4703: 
                   4704:   /* No SAVE_EXPRs in this function yet.  */
                   4705:   save_expr_regs = 0;
                   4706: 
                   4707:   /* No RTL_EXPRs in this function yet.  */
                   4708:   rtl_expr_chain = 0;
                   4709: 
                   4710:   /* We have not allocated any temporaries yet.  */
                   4711:   temp_slots = 0;
                   4712:   temp_slot_level = 0;
1.1.1.7 ! root     4713:   target_temp_slot_level = 0;
1.1       root     4714: 
                   4715:   /* Within function body, compute a type's size as soon it is laid out.  */
                   4716:   immediate_size_expand++;
                   4717: 
1.1.1.6   root     4718:   /* We haven't made any trampolines for this function yet.  */
                   4719:   trampoline_list = 0;
                   4720: 
1.1       root     4721:   init_pending_stack_adjust ();
                   4722:   inhibit_defer_pop = 0;
                   4723: 
                   4724:   current_function_outgoing_args_size = 0;
                   4725: 
                   4726:   /* Initialize the insn lengths.  */
                   4727:   init_insn_lengths ();
                   4728: 
                   4729:   /* Prevent ever trying to delete the first instruction of a function.
                   4730:      Also tell final how to output a linenum before the function prologue.  */
                   4731:   emit_line_note (filename, line);
                   4732: 
                   4733:   /* Make sure first insn is a note even if we don't want linenums.
                   4734:      This makes sure the first insn will never be deleted.
                   4735:      Also, final expects a note to appear there.  */
1.1.1.4   root     4736:   emit_note (NULL_PTR, NOTE_INSN_DELETED);
1.1       root     4737: 
                   4738:   /* Set flags used by final.c.  */
                   4739:   if (aggregate_value_p (DECL_RESULT (subr)))
                   4740:     {
                   4741: #ifdef PCC_STATIC_STRUCT_RETURN
1.1.1.5   root     4742:       current_function_returns_pcc_struct = 1;
1.1       root     4743: #endif
1.1.1.5   root     4744:       current_function_returns_struct = 1;
1.1       root     4745:     }
                   4746: 
                   4747:   /* Warn if this value is an aggregate type,
                   4748:      regardless of which calling convention we are using for it.  */
                   4749:   if (warn_aggregate_return
1.1.1.7 ! root     4750:       && AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr))))
1.1       root     4751:     warning ("function returns an aggregate");
                   4752: 
                   4753:   current_function_returns_pointer
                   4754:     = (TREE_CODE (TREE_TYPE (DECL_RESULT (subr))) == POINTER_TYPE);
                   4755: 
                   4756:   /* Indicate that we need to distinguish between the return value of the
                   4757:      present function and the return value of a function being called.  */
                   4758:   rtx_equal_function_value_matters = 1;
                   4759: 
                   4760:   /* Indicate that we have not instantiated virtual registers yet.  */
                   4761:   virtuals_instantiated = 0;
                   4762: 
                   4763:   /* Indicate we have no need of a frame pointer yet.  */
                   4764:   frame_pointer_needed = 0;
                   4765: 
                   4766:   /* By default assume not varargs.  */
                   4767:   current_function_varargs = 0;
                   4768: }
                   4769: 
                   4770: /* Indicate that the current function uses extra args
                   4771:    not explicitly mentioned in the argument list in any fashion.  */
                   4772: 
                   4773: void
                   4774: mark_varargs ()
                   4775: {
                   4776:   current_function_varargs = 1;
                   4777: }
                   4778: 
                   4779: /* Expand a call to __main at the beginning of a possible main function.  */
                   4780: 
1.1.1.7 ! root     4781: #if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
        !          4782: #undef HAS_INIT_SECTION
        !          4783: #define HAS_INIT_SECTION
        !          4784: #endif
        !          4785: 
1.1       root     4786: void
                   4787: expand_main_function ()
                   4788: {
1.1.1.6   root     4789:   if (!output_bytecode)
                   4790:     {
                   4791:       /* The zero below avoids a possible parse error */
                   4792:       0;
1.1.1.7 ! root     4793: #if !defined (HAS_INIT_SECTION)
1.1.1.6   root     4794:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, NAME__MAIN), 0,
                   4795:                         VOIDmode, 0);
1.1.1.7 ! root     4796: #endif /* not HAS_INIT_SECTION */
1.1.1.6   root     4797:     }
1.1       root     4798: }
                   4799: 
1.1.1.6   root     4800: extern struct obstack permanent_obstack;
                   4801: 
                   4802: /* Expand start of bytecode function. See comment at
                   4803:    expand_function_start below for details. */
                   4804: 
                   4805: void
                   4806: bc_expand_function_start (subr, parms_have_cleanups)
                   4807:   tree subr;
                   4808:   int parms_have_cleanups;
                   4809: {
                   4810:   char label[20], *name;
                   4811:   static int nlab;
                   4812:   tree thisarg;
                   4813:   int argsz;
                   4814: 
                   4815:   if (TREE_PUBLIC (subr))
                   4816:     bc_globalize_label (IDENTIFIER_POINTER (DECL_NAME (subr)));
                   4817: 
                   4818: #ifdef DEBUG_PRINT_CODE
                   4819:   fprintf (stderr, "\n<func %s>\n", IDENTIFIER_POINTER (DECL_NAME (subr)));
                   4820: #endif
                   4821: 
                   4822:   for (argsz = 0, thisarg = DECL_ARGUMENTS (subr); thisarg; thisarg = TREE_CHAIN (thisarg))
                   4823:     {
                   4824:       if (DECL_RTL (thisarg))
                   4825:        abort ();               /* Should be NULL here I think.  */
                   4826:       else if (TREE_CONSTANT (DECL_SIZE (thisarg)))
                   4827:        {
                   4828:          DECL_RTL (thisarg) = bc_gen_rtx ((char *) 0, argsz, (struct bc_label *) 0);
                   4829:          argsz += TREE_INT_CST_LOW (DECL_SIZE (thisarg));
                   4830:        }
                   4831:       else
                   4832:        {
                   4833:          /* Variable-sized objects are pointers to their storage. */
                   4834:          DECL_RTL (thisarg) = bc_gen_rtx ((char *) 0, argsz, (struct bc_label *) 0);
                   4835:          argsz += POINTER_SIZE;
                   4836:        }
                   4837:     }
                   4838: 
                   4839:   bc_begin_function (bc_xstrdup (IDENTIFIER_POINTER (DECL_NAME (subr))));
                   4840: 
                   4841:   ASM_GENERATE_INTERNAL_LABEL (label, "LX", nlab);
                   4842: 
                   4843:   ++nlab;
                   4844:   name = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
                   4845:   this_function_callinfo = bc_gen_rtx (name, 0, (struct bc_label *) 0);
                   4846:   this_function_bytecode =
                   4847:     bc_emit_trampoline (BYTECODE_LABEL (this_function_callinfo));
                   4848: }
                   4849: 
                   4850: 
                   4851: /* Expand end of bytecode function. See details the comment of
                   4852:    expand_function_end(), below. */
                   4853: 
                   4854: void
                   4855: bc_expand_function_end ()
                   4856: {
                   4857:   char *ptrconsts;
                   4858: 
                   4859:   expand_null_return ();
                   4860: 
                   4861:   /* Emit any fixup code. This must be done before the call to
                   4862:      to BC_END_FUNCTION (), since that will cause the bytecode
                   4863:      segment to be finished off and closed. */
                   4864: 
1.1.1.7 ! root     4865:   expand_fixups (NULL_RTX);
1.1.1.6   root     4866: 
                   4867:   ptrconsts = bc_end_function ();
                   4868: 
                   4869:   bc_align_const (2 /* INT_ALIGN */);
                   4870: 
                   4871:   /* If this changes also make sure to change bc-interp.h!  */
                   4872: 
                   4873:   bc_emit_const_labeldef (BYTECODE_LABEL (this_function_callinfo));
                   4874:   bc_emit_const ((char *) &max_stack_depth, sizeof max_stack_depth);
                   4875:   bc_emit_const ((char *) &local_vars_size, sizeof local_vars_size);
                   4876:   bc_emit_const_labelref (this_function_bytecode, 0);
                   4877:   bc_emit_const_labelref (ptrconsts, 0);
                   4878:   bc_emit_const_labelref (BYTECODE_LABEL (this_function_calldesc), 0);
                   4879: }
                   4880: 
                   4881: 
1.1       root     4882: /* Start the RTL for a new function, and set variables used for
                   4883:    emitting RTL.
                   4884:    SUBR is the FUNCTION_DECL node.
                   4885:    PARMS_HAVE_CLEANUPS is nonzero if there are cleanups associated with
                   4886:    the function's parameters, which must be run at any return statement.  */
                   4887: 
                   4888: void
                   4889: expand_function_start (subr, parms_have_cleanups)
                   4890:      tree subr;
                   4891:      int parms_have_cleanups;
                   4892: {
                   4893:   register int i;
                   4894:   tree tem;
                   4895:   rtx last_ptr;
                   4896: 
1.1.1.6   root     4897:   if (output_bytecode)
                   4898:     {
                   4899:       bc_expand_function_start (subr, parms_have_cleanups);
                   4900:       return;
                   4901:     }
                   4902: 
1.1       root     4903:   /* Make sure volatile mem refs aren't considered
                   4904:      valid operands of arithmetic insns.  */
                   4905:   init_recog_no_volatile ();
                   4906: 
                   4907:   /* If function gets a static chain arg, store it in the stack frame.
                   4908:      Do this first, so it gets the first stack slot offset.  */
                   4909:   if (current_function_needs_context)
1.1.1.4   root     4910:     {
                   4911:       last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
1.1.1.7 ! root     4912: 
        !          4913: #ifdef SMALL_REGISTER_CLASSES
        !          4914:       /* Delay copying static chain if it is not a register to avoid
        !          4915:         conflicts with regs used for parameters.  */
        !          4916:       if (GET_CODE (static_chain_incoming_rtx) == REG)
        !          4917: #endif
        !          4918:         emit_move_insn (last_ptr, static_chain_incoming_rtx);
1.1.1.4   root     4919:     }
1.1       root     4920: 
                   4921:   /* If the parameters of this function need cleaning up, get a label
                   4922:      for the beginning of the code which executes those cleanups.  This must
                   4923:      be done before doing anything with return_label.  */
                   4924:   if (parms_have_cleanups)
                   4925:     cleanup_label = gen_label_rtx ();
                   4926:   else
                   4927:     cleanup_label = 0;
                   4928: 
                   4929:   /* Make the label for return statements to jump to, if this machine
                   4930:      does not have a one-instruction return and uses an epilogue,
                   4931:      or if it returns a structure, or if it has parm cleanups.  */
                   4932: #ifdef HAVE_return
                   4933:   if (cleanup_label == 0 && HAVE_return
                   4934:       && ! current_function_returns_pcc_struct
                   4935:       && ! (current_function_returns_struct && ! optimize))
                   4936:     return_label = 0;
                   4937:   else
                   4938:     return_label = gen_label_rtx ();
                   4939: #else
                   4940:   return_label = gen_label_rtx ();
                   4941: #endif
                   4942: 
                   4943:   /* Initialize rtx used to return the value.  */
                   4944:   /* Do this before assign_parms so that we copy the struct value address
                   4945:      before any library calls that assign parms might generate.  */
                   4946: 
                   4947:   /* Decide whether to return the value in memory or in a register.  */
                   4948:   if (aggregate_value_p (DECL_RESULT (subr)))
                   4949:     {
                   4950:       /* Returning something that won't go in a register.  */
1.1.1.7 ! root     4951:       register rtx value_address = 0;
1.1       root     4952: 
                   4953: #ifdef PCC_STATIC_STRUCT_RETURN
                   4954:       if (current_function_returns_pcc_struct)
                   4955:        {
                   4956:          int size = int_size_in_bytes (TREE_TYPE (DECL_RESULT (subr)));
                   4957:          value_address = assemble_static_space (size);
                   4958:        }
                   4959:       else
                   4960: #endif
                   4961:        {
                   4962:          /* Expect to be passed the address of a place to store the value.
                   4963:             If it is passed as an argument, assign_parms will take care of
                   4964:             it.  */
                   4965:          if (struct_value_incoming_rtx)
                   4966:            {
                   4967:              value_address = gen_reg_rtx (Pmode);
                   4968:              emit_move_insn (value_address, struct_value_incoming_rtx);
                   4969:            }
                   4970:        }
                   4971:       if (value_address)
1.1.1.7 ! root     4972:        {
        !          4973:          DECL_RTL (DECL_RESULT (subr))
        !          4974:            = gen_rtx (MEM, DECL_MODE (DECL_RESULT (subr)), value_address);
        !          4975:          MEM_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)))
        !          4976:            = AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
        !          4977:        }
1.1       root     4978:     }
                   4979:   else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
                   4980:     /* If return mode is void, this decl rtl should not be used.  */
                   4981:     DECL_RTL (DECL_RESULT (subr)) = 0;
                   4982:   else if (parms_have_cleanups)
1.1.1.4   root     4983:     {
                   4984:       /* If function will end with cleanup code for parms,
                   4985:         compute the return values into a pseudo reg,
                   4986:         which we will copy into the true return register
                   4987:         after the cleanups are done.  */
                   4988: 
                   4989:       enum machine_mode mode = DECL_MODE (DECL_RESULT (subr));
1.1.1.7 ! root     4990: 
1.1.1.4   root     4991: #ifdef PROMOTE_FUNCTION_RETURN
                   4992:       tree type = TREE_TYPE (DECL_RESULT (subr));
                   4993:       int unsignedp = TREE_UNSIGNED (type);
                   4994: 
1.1.1.7 ! root     4995:       mode = promote_mode (type, mode, &unsignedp, 1);
1.1.1.4   root     4996: #endif
                   4997: 
                   4998:       DECL_RTL (DECL_RESULT (subr)) = gen_reg_rtx (mode);
                   4999:     }
1.1       root     5000:   else
                   5001:     /* Scalar, returned in a register.  */
                   5002:     {
                   5003: #ifdef FUNCTION_OUTGOING_VALUE
                   5004:       DECL_RTL (DECL_RESULT (subr))
                   5005:        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
                   5006: #else
                   5007:       DECL_RTL (DECL_RESULT (subr))
                   5008:        = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
                   5009: #endif
                   5010: 
                   5011:       /* Mark this reg as the function's return value.  */
                   5012:       if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
                   5013:        {
                   5014:          REG_FUNCTION_VALUE_P (DECL_RTL (DECL_RESULT (subr))) = 1;
                   5015:          /* Needed because we may need to move this to memory
                   5016:             in case it's a named return value whose address is taken.  */
1.1.1.4   root     5017:          DECL_REGISTER (DECL_RESULT (subr)) = 1;
1.1       root     5018:        }
                   5019:     }
                   5020: 
                   5021:   /* Initialize rtx for parameters and local variables.
                   5022:      In some cases this requires emitting insns.  */
                   5023: 
                   5024:   assign_parms (subr, 0);
                   5025: 
1.1.1.7 ! root     5026: #ifdef SMALL_REGISTER_CLASSES
        !          5027:   /* Copy the static chain now if it wasn't a register.  The delay is to
        !          5028:      avoid conflicts with the parameter passing registers.  */
        !          5029: 
        !          5030:   if (current_function_needs_context)
        !          5031:       if (GET_CODE (static_chain_incoming_rtx) != REG)
        !          5032:         emit_move_insn (last_ptr, static_chain_incoming_rtx);
        !          5033: #endif
        !          5034: 
1.1       root     5035:   /* The following was moved from init_function_start.
                   5036:      The move is supposed to make sdb output more accurate.  */
                   5037:   /* Indicate the beginning of the function body,
                   5038:      as opposed to parm setup.  */
1.1.1.4   root     5039:   emit_note (NULL_PTR, NOTE_INSN_FUNCTION_BEG);
1.1       root     5040: 
                   5041:   /* If doing stupid allocation, mark parms as born here.  */
                   5042: 
                   5043:   if (GET_CODE (get_last_insn ()) != NOTE)
1.1.1.4   root     5044:     emit_note (NULL_PTR, NOTE_INSN_DELETED);
1.1       root     5045:   parm_birth_insn = get_last_insn ();
                   5046: 
                   5047:   if (obey_regdecls)
                   5048:     {
                   5049:       for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; i++)
                   5050:        use_variable (regno_reg_rtx[i]);
                   5051: 
                   5052:       if (current_function_internal_arg_pointer != virtual_incoming_args_rtx)
                   5053:        use_variable (current_function_internal_arg_pointer);
                   5054:     }
                   5055: 
                   5056:   /* Fetch static chain values for containing functions.  */
                   5057:   tem = decl_function_context (current_function_decl);
1.1.1.7 ! root     5058:   /* If not doing stupid register allocation copy the static chain
        !          5059:      pointer into a psuedo.  If we have small register classes, copy the
        !          5060:      value from memory if static_chain_incoming_rtx is a REG.  If we do
        !          5061:      stupid register allocation, we use the stack address generated above.  */
1.1.1.4   root     5062:   if (tem && ! obey_regdecls)
1.1.1.7 ! root     5063:     {
        !          5064: #ifdef SMALL_REGISTER_CLASSES
        !          5065:       /* If the static chain originally came in a register, put it back
        !          5066:         there, then move it out in the next insn.  The reason for
        !          5067:         this peculiar code is to satisfy function integration.  */
        !          5068:       if (GET_CODE (static_chain_incoming_rtx) == REG)
        !          5069:        emit_move_insn (static_chain_incoming_rtx, last_ptr);
        !          5070: #endif
        !          5071: 
        !          5072:       last_ptr = copy_to_reg (static_chain_incoming_rtx);
        !          5073:     }
        !          5074: 
1.1       root     5075:   context_display = 0;
                   5076:   while (tem)
                   5077:     {
                   5078:       tree rtlexp = make_node (RTL_EXPR);
                   5079: 
                   5080:       RTL_EXPR_RTL (rtlexp) = last_ptr;
                   5081:       context_display = tree_cons (tem, rtlexp, context_display);
                   5082:       tem = decl_function_context (tem);
                   5083:       if (tem == 0)
                   5084:        break;
                   5085:       /* Chain thru stack frames, assuming pointer to next lexical frame
                   5086:         is found at the place we always store it.  */
                   5087: #ifdef FRAME_GROWS_DOWNWARD
                   5088:       last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
                   5089: #endif
                   5090:       last_ptr = copy_to_reg (gen_rtx (MEM, Pmode,
                   5091:                                       memory_address (Pmode, last_ptr)));
1.1.1.6   root     5092: 
                   5093:       /* If we are not optimizing, ensure that we know that this
                   5094:         piece of context is live over the entire function.  */
                   5095:       if (! optimize)
                   5096:        save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, last_ptr,
                   5097:                                  save_expr_regs);
1.1       root     5098:     }
                   5099: 
                   5100:   /* After the display initializations is where the tail-recursion label
                   5101:      should go, if we end up needing one.   Ensure we have a NOTE here
                   5102:      since some things (like trampolines) get placed before this.  */
1.1.1.4   root     5103:   tail_recursion_reentry = emit_note (NULL_PTR, NOTE_INSN_DELETED);
1.1       root     5104: 
                   5105:   /* Evaluate now the sizes of any types declared among the arguments.  */
                   5106:   for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
1.1.1.5   root     5107:     expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode, 0);
1.1       root     5108: 
                   5109:   /* Make sure there is a line number after the function entry setup code.  */
                   5110:   force_next_line_note ();
                   5111: }
                   5112: 
                   5113: /* Generate RTL for the end of the current function.
1.1.1.6   root     5114:    FILENAME and LINE are the current position in the source file. 
1.1       root     5115: 
1.1.1.6   root     5116:    It is up to language-specific callers to do cleanups for parameters--
                   5117:    or else, supply 1 for END_BINDINGS and we will call expand_end_bindings.  */
1.1       root     5118: 
                   5119: void
1.1.1.6   root     5120: expand_function_end (filename, line, end_bindings)
1.1       root     5121:      char *filename;
                   5122:      int line;
1.1.1.6   root     5123:      int end_bindings;
1.1       root     5124: {
                   5125:   register int i;
                   5126:   tree link;
                   5127: 
                   5128:   static rtx initial_trampoline;
                   5129: 
1.1.1.6   root     5130:   if (output_bytecode)
                   5131:     {
                   5132:       bc_expand_function_end ();
                   5133:       return;
                   5134:     }
                   5135: 
1.1       root     5136: #ifdef NON_SAVING_SETJMP
                   5137:   /* Don't put any variables in registers if we call setjmp
                   5138:      on a machine that fails to restore the registers.  */
                   5139:   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
                   5140:     {
1.1.1.7 ! root     5141:       if (DECL_INITIAL (current_function_decl) != error_mark_node)
        !          5142:        setjmp_protect (DECL_INITIAL (current_function_decl));
        !          5143: 
1.1       root     5144:       setjmp_protect_args ();
                   5145:     }
                   5146: #endif
                   5147: 
                   5148:   /* Save the argument pointer if a save area was made for it.  */
                   5149:   if (arg_pointer_save_area)
                   5150:     {
                   5151:       rtx x = gen_move_insn (arg_pointer_save_area, virtual_incoming_args_rtx);
                   5152:       emit_insn_before (x, tail_recursion_reentry);
                   5153:     }
                   5154: 
                   5155:   /* Initialize any trampolines required by this function.  */
                   5156:   for (link = trampoline_list; link; link = TREE_CHAIN (link))
                   5157:     {
                   5158:       tree function = TREE_PURPOSE (link);
                   5159:       rtx context = lookup_static_chain (function);
                   5160:       rtx tramp = RTL_EXPR_RTL (TREE_VALUE (link));
                   5161:       rtx seq;
                   5162: 
                   5163:       /* First make sure this compilation has a template for
                   5164:         initializing trampolines.  */
                   5165:       if (initial_trampoline == 0)
1.1.1.2   root     5166:        {
                   5167:          end_temporary_allocation ();
                   5168:          initial_trampoline
                   5169:            = gen_rtx (MEM, BLKmode, assemble_trampoline_template ());
                   5170:          resume_temporary_allocation ();
                   5171:        }
1.1       root     5172: 
                   5173:       /* Generate insns to initialize the trampoline.  */
                   5174:       start_sequence ();
                   5175:       tramp = change_address (initial_trampoline, BLKmode,
                   5176:                              round_trampoline_addr (XEXP (tramp, 0)));
1.1.1.4   root     5177:       emit_block_move (tramp, initial_trampoline, GEN_INT (TRAMPOLINE_SIZE),
1.1       root     5178:                       FUNCTION_BOUNDARY / BITS_PER_UNIT);
                   5179:       INITIALIZE_TRAMPOLINE (XEXP (tramp, 0),
                   5180:                             XEXP (DECL_RTL (function), 0), context);
                   5181:       seq = get_insns ();
                   5182:       end_sequence ();
                   5183: 
                   5184:       /* Put those insns at entry to the containing function (this one).  */
                   5185:       emit_insns_before (seq, tail_recursion_reentry);
                   5186:     }
                   5187: 
                   5188: #if 0  /* I think unused parms are legitimate enough.  */
                   5189:   /* Warn about unused parms.  */
                   5190:   if (warn_unused)
                   5191:     {
                   5192:       rtx decl;
                   5193: 
                   5194:       for (decl = DECL_ARGUMENTS (current_function_decl);
                   5195:           decl; decl = TREE_CHAIN (decl))
                   5196:        if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL)
                   5197:          warning_with_decl (decl, "unused parameter `%s'");
                   5198:     }
                   5199: #endif
                   5200: 
                   5201:   /* Delete handlers for nonlocal gotos if nothing uses them.  */
                   5202:   if (nonlocal_goto_handler_slot != 0 && !current_function_has_nonlocal_label)
                   5203:     delete_handlers ();
                   5204: 
                   5205:   /* End any sequences that failed to be closed due to syntax errors.  */
                   5206:   while (in_sequence_p ())
1.1.1.4   root     5207:     end_sequence ();
1.1       root     5208: 
                   5209:   /* Outside function body, can't compute type's actual size
                   5210:      until next function's body starts.  */
                   5211:   immediate_size_expand--;
                   5212: 
                   5213:   /* If doing stupid register allocation,
                   5214:      mark register parms as dying here.  */
                   5215: 
                   5216:   if (obey_regdecls)
                   5217:     {
                   5218:       rtx tem;
                   5219:       for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; i++)
                   5220:        use_variable (regno_reg_rtx[i]);
                   5221: 
                   5222:       /* Likewise for the regs of all the SAVE_EXPRs in the function.  */
                   5223: 
                   5224:       for (tem = save_expr_regs; tem; tem = XEXP (tem, 1))
                   5225:        {
                   5226:          use_variable (XEXP (tem, 0));
                   5227:          use_variable_after (XEXP (tem, 0), parm_birth_insn);
                   5228:        }
                   5229: 
                   5230:       if (current_function_internal_arg_pointer != virtual_incoming_args_rtx)
                   5231:        use_variable (current_function_internal_arg_pointer);
                   5232:     }
                   5233: 
                   5234:   clear_pending_stack_adjust ();
                   5235:   do_pending_stack_adjust ();
                   5236: 
                   5237:   /* Mark the end of the function body.
                   5238:      If control reaches this insn, the function can drop through
                   5239:      without returning a value.  */
1.1.1.4   root     5240:   emit_note (NULL_PTR, NOTE_INSN_FUNCTION_END);
1.1       root     5241: 
                   5242:   /* Output a linenumber for the end of the function.
                   5243:      SDB depends on this.  */
                   5244:   emit_line_note_force (filename, line);
                   5245: 
                   5246:   /* Output the label for the actual return from the function,
                   5247:      if one is expected.  This happens either because a function epilogue
                   5248:      is used instead of a return instruction, or because a return was done
                   5249:      with a goto in order to run local cleanups, or because of pcc-style
                   5250:      structure returning.  */
                   5251: 
                   5252:   if (return_label)
                   5253:     emit_label (return_label);
                   5254: 
1.1.1.6   root     5255:   /* C++ uses this.  */
                   5256:   if (end_bindings)
                   5257:     expand_end_bindings (0, 0, 0);
                   5258: 
1.1       root     5259:   /* If we had calls to alloca, and this machine needs
                   5260:      an accurate stack pointer to exit the function,
                   5261:      insert some code to save and restore the stack pointer.  */
                   5262: #ifdef EXIT_IGNORE_STACK
                   5263:   if (! EXIT_IGNORE_STACK)
                   5264: #endif
                   5265:     if (current_function_calls_alloca)
                   5266:       {
1.1.1.3   root     5267:        rtx tem = 0;
                   5268: 
                   5269:        emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
1.1.1.4   root     5270:        emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
1.1       root     5271:       }
                   5272: 
                   5273:   /* If scalar return value was computed in a pseudo-reg,
                   5274:      copy that to the hard return register.  */
                   5275:   if (DECL_RTL (DECL_RESULT (current_function_decl)) != 0
                   5276:       && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG
                   5277:       && (REGNO (DECL_RTL (DECL_RESULT (current_function_decl)))
                   5278:          >= FIRST_PSEUDO_REGISTER))
                   5279:     {
                   5280:       rtx real_decl_result;
                   5281: 
                   5282: #ifdef FUNCTION_OUTGOING_VALUE
                   5283:       real_decl_result
                   5284:        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
                   5285:                                   current_function_decl);
                   5286: #else
                   5287:       real_decl_result
                   5288:        = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
                   5289:                          current_function_decl);
                   5290: #endif
                   5291:       REG_FUNCTION_VALUE_P (real_decl_result) = 1;
                   5292:       emit_move_insn (real_decl_result,
                   5293:                      DECL_RTL (DECL_RESULT (current_function_decl)));
                   5294:       emit_insn (gen_rtx (USE, VOIDmode, real_decl_result));
                   5295:     }
                   5296: 
                   5297:   /* If returning a structure, arrange to return the address of the value
                   5298:      in a place where debuggers expect to find it.
                   5299: 
                   5300:      If returning a structure PCC style,
                   5301:      the caller also depends on this value.
                   5302:      And current_function_returns_pcc_struct is not necessarily set.  */
                   5303:   if (current_function_returns_struct
                   5304:       || current_function_returns_pcc_struct)
                   5305:     {
                   5306:       rtx value_address = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
                   5307:       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
                   5308: #ifdef FUNCTION_OUTGOING_VALUE
                   5309:       rtx outgoing
                   5310:        = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
                   5311:                                   current_function_decl);
                   5312: #else
                   5313:       rtx outgoing
                   5314:        = FUNCTION_VALUE (build_pointer_type (type),
                   5315:                          current_function_decl);
                   5316: #endif
                   5317: 
                   5318:       /* Mark this as a function return value so integrate will delete the
                   5319:         assignment and USE below when inlining this function.  */
                   5320:       REG_FUNCTION_VALUE_P (outgoing) = 1;
                   5321: 
                   5322:       emit_move_insn (outgoing, value_address);
                   5323:       use_variable (outgoing);
                   5324:     }
                   5325: 
                   5326:   /* Output a return insn if we are using one.
                   5327:      Otherwise, let the rtl chain end here, to drop through
                   5328:      into the epilogue.  */
                   5329: 
                   5330: #ifdef HAVE_return
                   5331:   if (HAVE_return)
                   5332:     {
                   5333:       emit_jump_insn (gen_return ());
                   5334:       emit_barrier ();
                   5335:     }
                   5336: #endif
                   5337: 
                   5338:   /* Fix up any gotos that jumped out to the outermost
                   5339:      binding level of the function.
                   5340:      Must follow emitting RETURN_LABEL.  */
                   5341: 
                   5342:   /* If you have any cleanups to do at this point,
                   5343:      and they need to create temporary variables,
                   5344:      then you will lose.  */
1.1.1.7 ! root     5345:   expand_fixups (get_insns ());
1.1.1.4   root     5346: }
                   5347: 
                   5348: /* These arrays record the INSN_UIDs of the prologue and epilogue insns.  */
                   5349: 
                   5350: static int *prologue;
                   5351: static int *epilogue;
                   5352: 
                   5353: /* Create an array that records the INSN_UIDs of INSNS (either a sequence
                   5354:    or a single insn).  */
                   5355: 
                   5356: static int *
                   5357: record_insns (insns)
                   5358:      rtx insns;
                   5359: {
                   5360:   int *vec;
                   5361: 
                   5362:   if (GET_CODE (insns) == SEQUENCE)
                   5363:     {
                   5364:       int len = XVECLEN (insns, 0);
                   5365:       vec = (int *) oballoc ((len + 1) * sizeof (int));
                   5366:       vec[len] = 0;
                   5367:       while (--len >= 0)
                   5368:        vec[len] = INSN_UID (XVECEXP (insns, 0, len));
                   5369:     }
                   5370:   else
                   5371:     {
                   5372:       vec = (int *) oballoc (2 * sizeof (int));
                   5373:       vec[0] = INSN_UID (insns);
                   5374:       vec[1] = 0;
                   5375:     }
                   5376:   return vec;
                   5377: }
                   5378: 
                   5379: /* Determine how many INSN_UIDs in VEC are part of INSN.  */
                   5380: 
                   5381: static int
                   5382: contains (insn, vec)
                   5383:      rtx insn;
                   5384:      int *vec;
                   5385: {
                   5386:   register int i, j;
                   5387: 
                   5388:   if (GET_CODE (insn) == INSN
                   5389:       && GET_CODE (PATTERN (insn)) == SEQUENCE)
                   5390:     {
                   5391:       int count = 0;
                   5392:       for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
                   5393:        for (j = 0; vec[j]; j++)
                   5394:          if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == vec[j])
                   5395:            count++;
                   5396:       return count;
                   5397:     }
                   5398:   else
                   5399:     {
                   5400:       for (j = 0; vec[j]; j++)
                   5401:        if (INSN_UID (insn) == vec[j])
                   5402:          return 1;
                   5403:     }
                   5404:   return 0;
                   5405: }
                   5406: 
                   5407: /* Generate the prologe and epilogue RTL if the machine supports it.  Thread
                   5408:    this into place with notes indicating where the prologue ends and where
                   5409:    the epilogue begins.  Update the basic block information when possible.  */
                   5410: 
                   5411: void
                   5412: thread_prologue_and_epilogue_insns (f)
                   5413:      rtx f;
                   5414: {
                   5415: #ifdef HAVE_prologue
                   5416:   if (HAVE_prologue)
                   5417:     {
                   5418:       rtx head, seq, insn;
                   5419: 
                   5420:       /* The first insn (a NOTE_INSN_DELETED) is followed by zero or more
                   5421:         prologue insns and a NOTE_INSN_PROLOGUE_END.  */
                   5422:       emit_note_after (NOTE_INSN_PROLOGUE_END, f);
                   5423:       seq = gen_prologue ();
                   5424:       head = emit_insn_after (seq, f);
                   5425: 
                   5426:       /* Include the new prologue insns in the first block.  Ignore them
                   5427:         if they form a basic block unto themselves.  */
                   5428:       if (basic_block_head && n_basic_blocks
                   5429:          && GET_CODE (basic_block_head[0]) != CODE_LABEL)
                   5430:        basic_block_head[0] = NEXT_INSN (f);
                   5431: 
                   5432:       /* Retain a map of the prologue insns.  */
                   5433:       prologue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : head);
                   5434:     }
                   5435:   else
                   5436: #endif
                   5437:     prologue = 0;
                   5438: 
                   5439: #ifdef HAVE_epilogue
                   5440:   if (HAVE_epilogue)
                   5441:     {
                   5442:       rtx insn = get_last_insn ();
                   5443:       rtx prev = prev_nonnote_insn (insn);
                   5444: 
                   5445:       /* If we end with a BARRIER, we don't need an epilogue.  */
                   5446:       if (! (prev && GET_CODE (prev) == BARRIER))
                   5447:        {
1.1.1.6   root     5448:          rtx tail, seq, tem;
                   5449:          rtx first_use = 0;
                   5450:          rtx last_use = 0;
                   5451: 
                   5452:          /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
                   5453:             epilogue insns, the USE insns at the end of a function,
                   5454:             the jump insn that returns, and then a BARRIER.  */
1.1.1.4   root     5455: 
1.1.1.6   root     5456:          /* Move the USE insns at the end of a function onto a list.  */
1.1.1.4   root     5457:          while (prev
                   5458:                 && GET_CODE (prev) == INSN
                   5459:                 && GET_CODE (PATTERN (prev)) == USE)
                   5460:            {
1.1.1.6   root     5461:              tem = prev;
1.1.1.4   root     5462:              prev = prev_nonnote_insn (prev);
1.1.1.6   root     5463: 
                   5464:              NEXT_INSN (PREV_INSN (tem)) = NEXT_INSN (tem);
                   5465:              PREV_INSN (NEXT_INSN (tem)) = PREV_INSN (tem);
                   5466:              if (first_use)
                   5467:                {
                   5468:                  NEXT_INSN (tem) = first_use;
                   5469:                  PREV_INSN (first_use) = tem;
                   5470:                }
                   5471:              first_use = tem;
                   5472:              if (!last_use)
                   5473:                last_use = tem;
1.1.1.4   root     5474:            }
                   5475: 
1.1.1.6   root     5476:          emit_barrier_after (insn);
                   5477: 
1.1.1.4   root     5478:          seq = gen_epilogue ();
                   5479:          tail = emit_jump_insn_after (seq, insn);
1.1.1.6   root     5480: 
                   5481:          /* Insert the USE insns immediately before the return insn, which
                   5482:             must be the first instruction before the final barrier.  */
                   5483:          if (first_use)
                   5484:            {
                   5485:              tem = prev_nonnote_insn (get_last_insn ());
                   5486:              NEXT_INSN (PREV_INSN (tem)) = first_use;
                   5487:              PREV_INSN (first_use) = PREV_INSN (tem);
                   5488:              PREV_INSN (tem) = last_use;
                   5489:              NEXT_INSN (last_use) = tem;
                   5490:            }
                   5491: 
1.1.1.4   root     5492:          emit_note_after (NOTE_INSN_EPILOGUE_BEG, insn);
                   5493: 
                   5494:          /* Include the new epilogue insns in the last block.  Ignore
                   5495:             them if they form a basic block unto themselves.  */
                   5496:          if (basic_block_end && n_basic_blocks
                   5497:              && GET_CODE (basic_block_end[n_basic_blocks - 1]) != JUMP_INSN)
                   5498:            basic_block_end[n_basic_blocks - 1] = tail;
                   5499: 
                   5500:          /* Retain a map of the epilogue insns.  */
                   5501:          epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
                   5502:          return;
                   5503:        }
                   5504:     }
                   5505: #endif
                   5506:   epilogue = 0;
                   5507: }
                   5508: 
                   5509: /* Reposition the prologue-end and epilogue-begin notes after instruction
                   5510:    scheduling and delayed branch scheduling.  */
                   5511: 
                   5512: void
                   5513: reposition_prologue_and_epilogue_notes (f)
                   5514:      rtx f;
                   5515: {
                   5516: #if defined (HAVE_prologue) || defined (HAVE_epilogue)
                   5517:   /* Reposition the prologue and epilogue notes.  */
                   5518:   if (n_basic_blocks)
                   5519:     {
                   5520:       rtx next, prev;
                   5521:       int len;
                   5522: 
                   5523:       if (prologue)
                   5524:        {
                   5525:          register rtx insn, note = 0;
                   5526: 
                   5527:          /* Scan from the beginning until we reach the last prologue insn.
                   5528:             We apparently can't depend on basic_block_{head,end} after
                   5529:             reorg has run.  */
                   5530:          for (len = 0; prologue[len]; len++)
                   5531:            ;
1.1.1.5   root     5532:          for (insn = f; len && insn; insn = NEXT_INSN (insn))
                   5533:            {
                   5534:              if (GET_CODE (insn) == NOTE)
                   5535:                {
                   5536:                  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
                   5537:                    note = insn;
                   5538:                }
                   5539:              else if ((len -= contains (insn, prologue)) == 0)
                   5540:                {
                   5541:                  /* Find the prologue-end note if we haven't already, and
                   5542:                     move it to just after the last prologue insn.  */
                   5543:                  if (note == 0)
                   5544:                    {
                   5545:                      for (note = insn; note = NEXT_INSN (note);)
                   5546:                        if (GET_CODE (note) == NOTE
                   5547:                            && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
                   5548:                          break;
                   5549:                    }
                   5550:                  next = NEXT_INSN (note);
                   5551:                  prev = PREV_INSN (note);
                   5552:                  if (prev)
                   5553:                    NEXT_INSN (prev) = next;
                   5554:                  if (next)
                   5555:                    PREV_INSN (next) = prev;
                   5556:                  add_insn_after (note, insn);
                   5557:                }
                   5558:            }
1.1.1.4   root     5559:        }
                   5560: 
                   5561:       if (epilogue)
                   5562:        {
                   5563:          register rtx insn, note = 0;
                   5564: 
                   5565:          /* Scan from the end until we reach the first epilogue insn.
                   5566:             We apparently can't depend on basic_block_{head,end} after
                   5567:             reorg has run.  */
                   5568:          for (len = 0; epilogue[len]; len++)
                   5569:            ;
1.1.1.5   root     5570:          for (insn = get_last_insn (); len && insn; insn = PREV_INSN (insn))
                   5571:            {
                   5572:              if (GET_CODE (insn) == NOTE)
                   5573:                {
                   5574:                  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
                   5575:                    note = insn;
                   5576:                }
                   5577:              else if ((len -= contains (insn, epilogue)) == 0)
                   5578:                {
                   5579:                  /* Find the epilogue-begin note if we haven't already, and
                   5580:                     move it to just before the first epilogue insn.  */
                   5581:                  if (note == 0)
                   5582:                    {
                   5583:                      for (note = insn; note = PREV_INSN (note);)
                   5584:                        if (GET_CODE (note) == NOTE
                   5585:                            && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
                   5586:                          break;
                   5587:                    }
                   5588:                  next = NEXT_INSN (note);
                   5589:                  prev = PREV_INSN (note);
                   5590:                  if (prev)
                   5591:                    NEXT_INSN (prev) = next;
                   5592:                  if (next)
                   5593:                    PREV_INSN (next) = prev;
                   5594:                  add_insn_after (note, PREV_INSN (insn));
                   5595:                }
                   5596:            }
1.1.1.4   root     5597:        }
                   5598:     }
                   5599: #endif /* HAVE_prologue or HAVE_epilogue */
1.1       root     5600: }

unix.superglobalmegacorp.com

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