Annotation of gcc/function.c, revision 1.1

1.1     ! root        1: /* Expands front end tree to back end RTL for GNU C-Compiler
        !             2:    Copyright (C) 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
        !             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"
        !            56: 
        !            57: /* Round a value to the lowest integer less than it that is a multiple of
        !            58:    the required alignment.  Avoid using division in case the value is
        !            59:    negative.  Assume the alignment is a power of two.  */
        !            60: #define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
        !            61: 
        !            62: /* Similar, but round to the next highest integer that meets the
        !            63:    alignment.  */
        !            64: #define CEIL_ROUND(VALUE,ALIGN)        (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
        !            65: 
        !            66: /* NEED_SEPARATE_AP means that we cannot derive ap from the value of fp
        !            67:    during rtl generation.  If they are different register numbers, this is
        !            68:    always true.  It may also be true if
        !            69:    FIRST_PARM_OFFSET - STARTING_FRAME_OFFSET is not a constant during rtl
        !            70:    generation.  See fix_lexical_addr for details.  */
        !            71: 
        !            72: #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
        !            73: #define NEED_SEPARATE_AP
        !            74: #endif
        !            75: 
        !            76: /* Number of bytes of args popped by function being compiled on its return.
        !            77:    Zero if no bytes are to be popped.
        !            78:    May affect compilation of return insn or of function epilogue.  */
        !            79: 
        !            80: int current_function_pops_args;
        !            81: 
        !            82: /* Nonzero if function being compiled needs to be given an address
        !            83:    where the value should be stored.  */
        !            84: 
        !            85: int current_function_returns_struct;
        !            86: 
        !            87: /* Nonzero if function being compiled needs to
        !            88:    return the address of where it has put a structure value.  */
        !            89: 
        !            90: int current_function_returns_pcc_struct;
        !            91: 
        !            92: /* Nonzero if function being compiled needs to be passed a static chain.  */
        !            93: 
        !            94: int current_function_needs_context;
        !            95: 
        !            96: /* Nonzero if function being compiled can call setjmp.  */
        !            97: 
        !            98: int current_function_calls_setjmp;
        !            99: 
        !           100: /* Nonzero if function being compiled can call longjmp.  */
        !           101: 
        !           102: int current_function_calls_longjmp;
        !           103: 
        !           104: /* Nonzero if function being compiled receives nonlocal gotos
        !           105:    from nested functions.  */
        !           106: 
        !           107: int current_function_has_nonlocal_label;
        !           108: 
        !           109: /* Nonzero if function being compiled contains nested functions.  */
        !           110: 
        !           111: int current_function_contains_functions;
        !           112: 
        !           113: /* Nonzero if function being compiled can call alloca,
        !           114:    either as a subroutine or builtin.  */
        !           115: 
        !           116: int current_function_calls_alloca;
        !           117: 
        !           118: /* Nonzero if the current function returns a pointer type */
        !           119: 
        !           120: int current_function_returns_pointer;
        !           121: 
        !           122: /* If some insns can be deferred to the delay slots of the epilogue, the
        !           123:    delay list for them is recorded here.  */
        !           124: 
        !           125: rtx current_function_epilogue_delay_list;
        !           126: 
        !           127: /* If function's args have a fixed size, this is that size, in bytes.
        !           128:    Otherwise, it is -1.
        !           129:    May affect compilation of return insn or of function epilogue.  */
        !           130: 
        !           131: int current_function_args_size;
        !           132: 
        !           133: /* # bytes the prologue should push and pretend that the caller pushed them.
        !           134:    The prologue must do this, but only if parms can be passed in registers.  */
        !           135: 
        !           136: int current_function_pretend_args_size;
        !           137: 
        !           138: /* # of bytes of outgoing arguments required to be pushed by the prologue.
        !           139:    If this is non-zero, it means that ACCUMULATE_OUTGOING_ARGS was defined
        !           140:    and no stack adjusts will be done on function calls.  */
        !           141: 
        !           142: int current_function_outgoing_args_size;
        !           143: 
        !           144: /* This is the offset from the arg pointer to the place where the first
        !           145:    anonymous arg can be found, if there is one.  */
        !           146: 
        !           147: rtx current_function_arg_offset_rtx;
        !           148: 
        !           149: /* Nonzero if current function uses varargs.h or equivalent.
        !           150:    Zero for functions that use stdarg.h.  */
        !           151: 
        !           152: int current_function_varargs;
        !           153: 
        !           154: /* Quantities of various kinds of registers
        !           155:    used for the current function's args.  */
        !           156: 
        !           157: CUMULATIVE_ARGS current_function_args_info;
        !           158: 
        !           159: /* Name of function now being compiled.  */
        !           160: 
        !           161: char *current_function_name;
        !           162: 
        !           163: /* If non-zero, an RTL expression for that location at which the current
        !           164:    function returns its result.  Always equal to
        !           165:    DECL_RTL (DECL_RESULT (current_function_decl)), but provided
        !           166:    independently of the tree structures.  */
        !           167: 
        !           168: rtx current_function_return_rtx;
        !           169: 
        !           170: /* Nonzero if the current function uses the constant pool.  */
        !           171: 
        !           172: int current_function_uses_const_pool;
        !           173: 
        !           174: /* Nonzero if the current function uses pic_offset_table_rtx.  */
        !           175: int current_function_uses_pic_offset_table;
        !           176: 
        !           177: /* The arg pointer hard register, or the pseudo into which it was copied.  */
        !           178: rtx current_function_internal_arg_pointer;
        !           179: 
        !           180: /* The FUNCTION_DECL for an inline function currently being expanded.  */
        !           181: tree inline_function_decl;
        !           182: 
        !           183: /* Number of function calls seen so far in current function.  */
        !           184: 
        !           185: int function_call_count;
        !           186: 
        !           187: /* List (chain of TREE_LIST) of LABEL_DECLs for all nonlocal labels
        !           188:    (labels to which there can be nonlocal gotos from nested functions)
        !           189:    in this function.  */
        !           190: 
        !           191: tree nonlocal_labels;
        !           192: 
        !           193: /* RTX for stack slot that holds the current handler for nonlocal gotos.
        !           194:    Zero when function does not have nonlocal labels.  */
        !           195: 
        !           196: rtx nonlocal_goto_handler_slot;
        !           197: 
        !           198: /* RTX for stack slot that holds the stack pointer value to restore
        !           199:    for a nonlocal goto.
        !           200:    Zero when function does not have nonlocal labels.  */
        !           201: 
        !           202: rtx nonlocal_goto_stack_level;
        !           203: 
        !           204: /* Label that will go on parm cleanup code, if any.
        !           205:    Jumping to this label runs cleanup code for parameters, if
        !           206:    such code must be run.  Following this code is the logical return label.  */
        !           207: 
        !           208: rtx cleanup_label;
        !           209: 
        !           210: /* Label that will go on function epilogue.
        !           211:    Jumping to this label serves as a "return" instruction
        !           212:    on machines which require execution of the epilogue on all returns.  */
        !           213: 
        !           214: rtx return_label;
        !           215: 
        !           216: /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
        !           217:    So we can mark them all live at the end of the function, if nonopt.  */
        !           218: rtx save_expr_regs;
        !           219: 
        !           220: /* List (chain of EXPR_LISTs) of all stack slots in this function.
        !           221:    Made for the sake of unshare_all_rtl.  */
        !           222: rtx stack_slot_list;
        !           223: 
        !           224: /* Chain of all RTL_EXPRs that have insns in them.  */
        !           225: tree rtl_expr_chain;
        !           226: 
        !           227: /* Label to jump back to for tail recursion, or 0 if we have
        !           228:    not yet needed one for this function.  */
        !           229: rtx tail_recursion_label;
        !           230: 
        !           231: /* Place after which to insert the tail_recursion_label if we need one.  */
        !           232: rtx tail_recursion_reentry;
        !           233: 
        !           234: /* Location at which to save the argument pointer if it will need to be
        !           235:    referenced.  There are two cases where this is done: if nonlocal gotos
        !           236:    exist, or if vars stored at an offset from the argument pointer will be
        !           237:    needed by inner routines.  */
        !           238: 
        !           239: rtx arg_pointer_save_area;
        !           240: 
        !           241: /* Offset to end of allocated area of stack frame.
        !           242:    If stack grows down, this is the address of the last stack slot allocated.
        !           243:    If stack grows up, this is the address for the next slot.  */
        !           244: int frame_offset;
        !           245: 
        !           246: /* List (chain of TREE_LISTs) of static chains for containing functions.
        !           247:    Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
        !           248:    in an RTL_EXPR in the TREE_VALUE.  */
        !           249: static tree context_display;
        !           250: 
        !           251: /* List (chain of TREE_LISTs) of trampolines for nested functions.
        !           252:    The trampoline sets up the static chain and jumps to the function.
        !           253:    We supply the trampoline's address when the function's address is requested.
        !           254: 
        !           255:    Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
        !           256:    in an RTL_EXPR in the TREE_VALUE.  */
        !           257: static tree trampoline_list;
        !           258: 
        !           259: /* Insn after which register parms and SAVE_EXPRs are born, if nonopt.  */
        !           260: static rtx parm_birth_insn;
        !           261: 
        !           262: #if 0
        !           263: /* Nonzero if a stack slot has been generated whose address is not
        !           264:    actually valid.  It means that the generated rtl must all be scanned
        !           265:    to detect and correct the invalid addresses where they occur.  */
        !           266: static int invalid_stack_slot;
        !           267: #endif
        !           268: 
        !           269: /* Last insn of those whose job was to put parms into their nominal homes.  */
        !           270: static rtx last_parm_insn;
        !           271: 
        !           272: /* 1 + last pseudo register number used for loading a copy
        !           273:    of a parameter of this function.  */
        !           274: static int max_parm_reg;
        !           275: 
        !           276: /* Vector indexed by REGNO, containing location on stack in which
        !           277:    to put the parm which is nominally in pseudo register REGNO,
        !           278:    if we discover that that parm must go in the stack.  */
        !           279: static rtx *parm_reg_stack_loc;
        !           280: 
        !           281: #if 0  /* Turned off because 0 seems to work just as well.  */
        !           282: /* Cleanup lists are required for binding levels regardless of whether
        !           283:    that binding level has cleanups or not.  This node serves as the
        !           284:    cleanup list whenever an empty list is required.  */
        !           285: static tree empty_cleanup_list;
        !           286: #endif
        !           287: 
        !           288: /* Nonzero once virtual register instantiation has been done.
        !           289:    assign_stack_local uses frame_pointer_rtx when this is nonzero.  */
        !           290: static int virtuals_instantiated;
        !           291: 
        !           292: /* Nonzero if we need to distinguish between the return value of this function
        !           293:    and the return value of a function called by this function.  This helps
        !           294:    integrate.c  */
        !           295: 
        !           296: extern int rtx_equal_function_value_matters;
        !           297: 
        !           298: void fixup_gotos ();
        !           299: 
        !           300: static tree round_down ();
        !           301: static rtx round_trampoline_addr ();
        !           302: static rtx fixup_stack_1 ();
        !           303: static void fixup_var_refs ();
        !           304: static void fixup_var_refs_insns ();
        !           305: static void fixup_var_refs_1 ();
        !           306: static void optimize_bit_field ();
        !           307: static void instantiate_decls ();
        !           308: static void instantiate_decls_1 ();
        !           309: static int instantiate_virtual_regs_1 ();
        !           310: static rtx fixup_memory_subreg ();
        !           311: static rtx walk_fixup_memory_subreg ();
        !           312: 
        !           313: /* In order to evaluate some expressions, such as function calls returning
        !           314:    structures in memory, we need to temporarily allocate stack locations.
        !           315:    We record each allocated temporary in the following structure.
        !           316: 
        !           317:    Associated with each temporary slot is a nesting level.  When we pop up
        !           318:    one level, all temporaries associated with the previous level are freed.
        !           319:    Normally, all temporaries are freed after the execution of the statement
        !           320:    in which they were created.  However, if we are inside a ({...}) grouping,
        !           321:    the result may be in a temporary and hence must be preserved.  If the
        !           322:    result could be in a temporary, we preserve it if we can determine which
        !           323:    one it is in.  If we cannot determine which temporary may contain the
        !           324:    result, all temporaries are preserved.  A temporary is preserved by
        !           325:    pretending it was allocated at the previous nesting level.
        !           326: 
        !           327:    Automatic variables are also assigned temporary slots, at the nesting
        !           328:    level where they are defined.  They are marked a "kept" so that
        !           329:    free_temp_slots will not free them.  */
        !           330: 
        !           331: struct temp_slot
        !           332: {
        !           333:   /* Points to next temporary slot.  */
        !           334:   struct temp_slot *next;
        !           335:   /* The rtx to used to reference the slot. */
        !           336:   rtx slot;
        !           337:   /* The size, in units, of the slot.  */
        !           338:   int size;
        !           339:   /* Non-zero if this temporary is currently in use.  */
        !           340:   char in_use;
        !           341:   /* Nesting level at which this slot is being used.  */
        !           342:   int level;
        !           343:   /* Non-zero if this should survive a call to free_temp_slots.  */
        !           344:   int keep;
        !           345: };
        !           346: 
        !           347: /* List of all temporaries allocated, both available and in use.  */
        !           348: 
        !           349: struct temp_slot *temp_slots;
        !           350: 
        !           351: /* Current nesting level for temporaries.  */
        !           352: 
        !           353: int temp_slot_level;
        !           354: 
        !           355: /* Pointer to chain of `struct function' for containing functions.  */
        !           356: struct function *outer_function_chain;
        !           357: 
        !           358: /* Given a function decl for a containing function,
        !           359:    return the `struct function' for it.  */
        !           360: 
        !           361: struct function *
        !           362: find_function_data (decl)
        !           363:      tree decl;
        !           364: {
        !           365:   struct function *p;
        !           366:   for (p = outer_function_chain; p; p = p->next)
        !           367:     if (p->decl == decl)
        !           368:       return p;
        !           369:   abort ();
        !           370: }
        !           371: 
        !           372: /* Save the current context for compilation of a nested function.
        !           373:    This is called from language-specific code.
        !           374:    The caller is responsible for saving any language-specific status,
        !           375:    since this function knows only about language-indepedent variables.  */
        !           376: 
        !           377: void
        !           378: push_function_context ()
        !           379: {
        !           380:   struct function *p = (struct function *) xmalloc (sizeof (struct function));
        !           381: 
        !           382:   p->next = outer_function_chain;
        !           383:   outer_function_chain = p;
        !           384: 
        !           385:   p->name = current_function_name;
        !           386:   p->decl = current_function_decl;
        !           387:   p->pops_args = current_function_pops_args;
        !           388:   p->returns_struct = current_function_returns_struct;
        !           389:   p->returns_pcc_struct = current_function_returns_pcc_struct;
        !           390:   p->needs_context = current_function_needs_context;
        !           391:   p->calls_setjmp = current_function_calls_setjmp;
        !           392:   p->calls_longjmp = current_function_calls_longjmp;
        !           393:   p->calls_alloca = current_function_calls_alloca;
        !           394:   p->has_nonlocal_label = current_function_has_nonlocal_label;
        !           395:   p->args_size = current_function_args_size;
        !           396:   p->pretend_args_size = current_function_pretend_args_size;
        !           397:   p->arg_offset_rtx = current_function_arg_offset_rtx;
        !           398:   p->uses_const_pool = current_function_uses_const_pool;
        !           399:   p->uses_pic_offset_table = current_function_uses_pic_offset_table;
        !           400:   p->internal_arg_pointer = current_function_internal_arg_pointer;
        !           401:   p->max_parm_reg = max_parm_reg;
        !           402:   p->parm_reg_stack_loc = parm_reg_stack_loc;
        !           403:   p->outgoing_args_size = current_function_outgoing_args_size;
        !           404:   p->return_rtx = current_function_return_rtx;
        !           405:   p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;
        !           406:   p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
        !           407:   p->nonlocal_labels = nonlocal_labels;
        !           408:   p->cleanup_label = cleanup_label;
        !           409:   p->return_label = return_label;
        !           410:   p->save_expr_regs = save_expr_regs;
        !           411:   p->stack_slot_list = stack_slot_list;
        !           412:   p->parm_birth_insn = parm_birth_insn;
        !           413:   p->frame_offset = frame_offset;
        !           414:   p->tail_recursion_label = tail_recursion_label;
        !           415:   p->tail_recursion_reentry = tail_recursion_reentry;
        !           416:   p->arg_pointer_save_area = arg_pointer_save_area;
        !           417:   p->rtl_expr_chain = rtl_expr_chain;
        !           418:   p->last_parm_insn = last_parm_insn;
        !           419:   p->context_display = context_display;
        !           420:   p->trampoline_list = trampoline_list;
        !           421:   p->function_call_count = function_call_count;
        !           422:   p->temp_slots = temp_slots;
        !           423:   p->temp_slot_level = temp_slot_level;
        !           424:   p->fixup_var_refs_queue = 0;
        !           425: 
        !           426:   save_tree_status (p);
        !           427:   save_storage_status (p);
        !           428:   save_emit_status (p);
        !           429:   init_emit ();
        !           430:   save_expr_status (p);
        !           431:   save_stmt_status (p);
        !           432: }
        !           433: 
        !           434: /* Restore the last saved context, at the end of a nested function.
        !           435:    This function is called from language-specific code.  */
        !           436: 
        !           437: void
        !           438: pop_function_context ()
        !           439: {
        !           440:   struct function *p = outer_function_chain;
        !           441: 
        !           442:   outer_function_chain = p->next;
        !           443: 
        !           444:   current_function_name = p->name;
        !           445:   current_function_decl = p->decl;
        !           446:   current_function_pops_args = p->pops_args;
        !           447:   current_function_returns_struct = p->returns_struct;
        !           448:   current_function_returns_pcc_struct = p->returns_pcc_struct;
        !           449:   current_function_needs_context = p->needs_context;
        !           450:   current_function_calls_setjmp = p->calls_setjmp;
        !           451:   current_function_calls_longjmp = p->calls_longjmp;
        !           452:   current_function_calls_alloca = p->calls_alloca;
        !           453:   current_function_has_nonlocal_label = p->has_nonlocal_label;
        !           454:   current_function_contains_functions = 1;
        !           455:   current_function_args_size = p->args_size;
        !           456:   current_function_pretend_args_size = p->pretend_args_size;
        !           457:   current_function_arg_offset_rtx = p->arg_offset_rtx;
        !           458:   current_function_uses_const_pool = p->uses_const_pool;
        !           459:   current_function_uses_pic_offset_table = p->uses_pic_offset_table;
        !           460:   current_function_internal_arg_pointer = p->internal_arg_pointer;
        !           461:   max_parm_reg = p->max_parm_reg;
        !           462:   parm_reg_stack_loc = p->parm_reg_stack_loc;
        !           463:   current_function_outgoing_args_size = p->outgoing_args_size;
        !           464:   current_function_return_rtx = p->return_rtx;
        !           465:   nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;
        !           466:   nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
        !           467:   nonlocal_labels = p->nonlocal_labels;
        !           468:   cleanup_label = p->cleanup_label;
        !           469:   return_label = p->return_label;
        !           470:   save_expr_regs = p->save_expr_regs;
        !           471:   stack_slot_list = p->stack_slot_list;
        !           472:   parm_birth_insn = p->parm_birth_insn;
        !           473:   frame_offset = p->frame_offset;
        !           474:   tail_recursion_label = p->tail_recursion_label;
        !           475:   tail_recursion_reentry = p->tail_recursion_reentry;
        !           476:   arg_pointer_save_area = p->arg_pointer_save_area;
        !           477:   rtl_expr_chain = p->rtl_expr_chain;
        !           478:   last_parm_insn = p->last_parm_insn;
        !           479:   context_display = p->context_display;
        !           480:   trampoline_list = p->trampoline_list;
        !           481:   function_call_count = p->function_call_count;
        !           482:   temp_slots = p->temp_slots;
        !           483:   temp_slot_level = p->temp_slot_level;
        !           484: 
        !           485:   restore_tree_status (p);
        !           486:   restore_storage_status (p);
        !           487:   restore_expr_status (p);
        !           488:   restore_emit_status (p);
        !           489:   restore_stmt_status (p);
        !           490: 
        !           491:   /* Finish doing put_var_into_stack for any of our variables
        !           492:      which became addressable during the nested function.  */
        !           493:   {
        !           494:     struct var_refs_queue *queue = p->fixup_var_refs_queue;
        !           495:     for (; queue; queue = queue->next)
        !           496:       fixup_var_refs (queue->modified);
        !           497:   }
        !           498: 
        !           499:   free (p);
        !           500: 
        !           501:   /* Reset variables that have known state during rtx generation.  */
        !           502:   rtx_equal_function_value_matters = 1;
        !           503:   virtuals_instantiated = 0;
        !           504: }
        !           505: 
        !           506: /* Allocate fixed slots in the stack frame of the current function.  */
        !           507: 
        !           508: /* Return size needed for stack frame based on slots so far allocated.
        !           509:    This size counts from zero.  It is not rounded to STACK_BOUNDARY;
        !           510:    the caller may have to do that.  */
        !           511: 
        !           512: int
        !           513: get_frame_size ()
        !           514: {
        !           515: #ifdef FRAME_GROWS_DOWNWARD
        !           516:   return -frame_offset;
        !           517: #else
        !           518:   return frame_offset;
        !           519: #endif
        !           520: }
        !           521: 
        !           522: /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
        !           523:    with machine mode MODE.
        !           524:    
        !           525:    ALIGN controls the amount of alignment for the address of the slot:
        !           526:    0 means according to MODE,
        !           527:    -1 means use BIGGEST_ALIGNMENT and round size to multiple of that,
        !           528:    positive specifies alignment boundary in bits.
        !           529: 
        !           530:    We do not round to stack_boundary here.  */
        !           531: 
        !           532: rtx
        !           533: assign_stack_local (mode, size, align)
        !           534:      enum machine_mode mode;
        !           535:      int size;
        !           536:      int align;
        !           537: {
        !           538:   register rtx x, addr;
        !           539:   int bigend_correction = 0;
        !           540:   int alignment;
        !           541: 
        !           542:   if (align == 0)
        !           543:     {
        !           544:       alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
        !           545:       if (mode == BLKmode)
        !           546:        alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
        !           547:     }
        !           548:   else if (align == -1)
        !           549:     {
        !           550:       alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
        !           551:       size = CEIL_ROUND (size, alignment);
        !           552:     }
        !           553:   else
        !           554:     alignment = align / BITS_PER_UNIT;
        !           555: 
        !           556: #if 0 /* Let's see if this is really needed--rms.  */
        !           557: #ifdef STRICT_ALIGNMENT
        !           558:   /* Supposedly sub-word sized units may later be accessed
        !           559:      with word intructions.  It's not certain this is really true.  */
        !           560:   if (mode != BLKmode && align == 0 && alignment < UNITS_PER_WORD)
        !           561:     alignment = UNITS_PER_WORD;
        !           562: 
        !           563:   /* This is in case we just made the alignment bigger than the size.  */
        !           564:   size = CEIL_ROUND (size, alignment);
        !           565: #endif
        !           566: #endif
        !           567: 
        !           568:   /* Round frame offset to that alignment.
        !           569:      We must be careful here, since FRAME_OFFSET might be negative and
        !           570:      division with a negative dividend isn't as well defined as we might
        !           571:      like.  So we instead assume that ALIGNMENT is a power of two and
        !           572:      use logical operations which are unambiguous.  */
        !           573: #ifdef FRAME_GROWS_DOWNWARD
        !           574:   frame_offset = FLOOR_ROUND (frame_offset, alignment);
        !           575: #else
        !           576:   frame_offset = CEIL_ROUND (frame_offset, alignment);
        !           577: #endif
        !           578: 
        !           579:   /* On a big-endian machine, if we are allocating more space than we will use,
        !           580:      use the least significant bytes of those that are allocated.  */
        !           581: #if BYTES_BIG_ENDIAN
        !           582:   if (mode != BLKmode)
        !           583:     bigend_correction = size - GET_MODE_SIZE (mode);
        !           584: #endif
        !           585: 
        !           586: #ifdef FRAME_GROWS_DOWNWARD
        !           587:   frame_offset -= size;
        !           588: #endif
        !           589: 
        !           590:   /* If we have already instantiated virtual registers, return the actual
        !           591:      address relative to the frame pointer.  */
        !           592:   if (virtuals_instantiated)
        !           593:     addr = plus_constant (frame_pointer_rtx,
        !           594:                          (frame_offset + bigend_correction
        !           595:                           + STARTING_FRAME_OFFSET));
        !           596:   else
        !           597:     addr = plus_constant (virtual_stack_vars_rtx,
        !           598:                          frame_offset + bigend_correction);
        !           599: 
        !           600: #ifndef FRAME_GROWS_DOWNWARD
        !           601:   frame_offset += size;
        !           602: #endif
        !           603: 
        !           604:   x = gen_rtx (MEM, mode, addr);
        !           605: 
        !           606:   stack_slot_list = gen_rtx (EXPR_LIST, VOIDmode, x, stack_slot_list);
        !           607: 
        !           608:   return x;
        !           609: }
        !           610: 
        !           611: /* Assign a stack slot in a containing function.
        !           612:    First three arguments are same as in preceding function.
        !           613:    The last argument specifies the function to allocate in.  */
        !           614: 
        !           615: rtx
        !           616: assign_outer_stack_local (mode, size, align, function)
        !           617:      enum machine_mode mode;
        !           618:      int size;
        !           619:      int align;
        !           620:      struct function *function;
        !           621: {
        !           622:   register rtx x, addr;
        !           623:   int bigend_correction = 0;
        !           624:   int alignment;
        !           625: 
        !           626:   /* Allocate in the memory associated with the function in whose frame
        !           627:      we are assigning.  */
        !           628:   push_obstacks (function->function_obstack,
        !           629:                 function->function_maybepermanent_obstack);
        !           630: 
        !           631:   if (align == 0)
        !           632:     {
        !           633:       alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
        !           634:       if (mode == BLKmode)
        !           635:        alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
        !           636:     }
        !           637:   else if (align == -1)
        !           638:     {
        !           639:       alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
        !           640:       size = CEIL_ROUND (size, alignment);
        !           641:     }
        !           642:   else
        !           643:     alignment = align / BITS_PER_UNIT;
        !           644: 
        !           645: #if 0 /* Let's see if this is really needed--rms.  */
        !           646: #ifdef STRICT_ALIGNMENT
        !           647:   /* Sub-word sized units may later be accessed with word intructions.
        !           648:      This results from (SUBREG (MEM ...) ...).  */
        !           649:   if (mode != BLKmode && align == 0 && alignment < UNITS_PER_WORD)
        !           650:     alignment = UNITS_PER_WORD;
        !           651: 
        !           652:   /* This is in case we just made the alignment bigger than the size.  */
        !           653:   size = CEIL_ROUND (size, alignment);
        !           654: #endif
        !           655: #endif
        !           656: 
        !           657:   /* Round frame offset to that alignment.  */
        !           658: #ifdef FRAME_GROWS_DOWNWARD
        !           659:   frame_offset = FLOOR_ROUND (frame_offset, alignment);
        !           660: #else
        !           661:   frame_offset = CEIL_ROUND (frame_offset, alignment);
        !           662: #endif
        !           663: 
        !           664:   /* On a big-endian machine, if we are allocating more space than we will use,
        !           665:      use the least significant bytes of those that are allocated.  */
        !           666: #if BYTES_BIG_ENDIAN
        !           667:   if (mode != BLKmode)
        !           668:     bigend_correction = size - GET_MODE_SIZE (mode);
        !           669: #endif
        !           670: 
        !           671: #ifdef FRAME_GROWS_DOWNWARD
        !           672:   function->frame_offset -= size;
        !           673: #endif
        !           674:   addr = plus_constant (virtual_stack_vars_rtx,
        !           675:                        function->frame_offset + bigend_correction);
        !           676: #ifndef FRAME_GROWS_DOWNWARD
        !           677:   function->frame_offset += size;
        !           678: #endif
        !           679: 
        !           680:   x = gen_rtx (MEM, mode, addr);
        !           681: 
        !           682:   function->stack_slot_list
        !           683:     = gen_rtx (EXPR_LIST, VOIDmode, x, function->stack_slot_list);
        !           684: 
        !           685:   pop_obstacks ();
        !           686: 
        !           687:   return x;
        !           688: }
        !           689: 
        !           690: /* Allocate a temporary stack slot and record it for possible later
        !           691:    reuse.
        !           692: 
        !           693:    MODE is the machine mode to be given to the returned rtx.
        !           694: 
        !           695:    SIZE is the size in units of the space required.  We do no rounding here
        !           696:    since assign_stack_local will do any required rounding.
        !           697: 
        !           698:    KEEP is non-zero if this slot is to be retained after a call to
        !           699:    free_temp_slots.  Automatic variables for a block are allocated with this
        !           700:    flag.  */
        !           701: 
        !           702: rtx
        !           703: assign_stack_temp (mode, size, keep)
        !           704:      enum machine_mode mode;
        !           705:      int size;
        !           706:      int keep;
        !           707: {
        !           708:   struct temp_slot *p, *best_p = 0;
        !           709: 
        !           710:   /* First try to find an available, already-allocated temporary that is the
        !           711:      exact size we require.  */
        !           712:   for (p = temp_slots; p; p = p->next)
        !           713:     if (p->size == size && GET_MODE (p->slot) == mode && ! p->in_use)
        !           714:       break;
        !           715: 
        !           716:   /* If we didn't find, one, try one that is larger than what we want.  We
        !           717:      find the smallest such.  */
        !           718:   if (p == 0)
        !           719:     for (p = temp_slots; p; p = p->next)
        !           720:       if (p->size > size && GET_MODE (p->slot) == mode && ! p->in_use
        !           721:          && (best_p == 0 || best_p->size > p->size))
        !           722:        best_p = p;
        !           723: 
        !           724:   /* Make our best, if any, the one to use.  */
        !           725:   if (best_p)
        !           726:     p = best_p;
        !           727: 
        !           728:   /* If we still didn't find one, make a new temporary.  */
        !           729:   if (p == 0)
        !           730:     {
        !           731:       p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
        !           732:       p->size = size;
        !           733:       /* If the temp slot mode doesn't indicate the alignment,
        !           734:         use the largest possible, so no one will be disappointed.  */
        !           735:       p->slot = assign_stack_local (mode, size, mode == BLKmode ? -1 : 0); 
        !           736:       p->next = temp_slots;
        !           737:       temp_slots = p;
        !           738:     }
        !           739: 
        !           740:   p->in_use = 1;
        !           741:   p->level = temp_slot_level;
        !           742:   p->keep = keep;
        !           743:   return p->slot;
        !           744: }
        !           745: 
        !           746: /* If X could be a reference to a temporary slot, mark that slot as belonging
        !           747:    to the to one level higher.  If X matched one of our slots, just mark that
        !           748:    one.  Otherwise, we can't easily predict which it is, so upgrade all of
        !           749:    them.  Kept slots need not be touched.
        !           750: 
        !           751:    This is called when an ({...}) construct occurs and a statement
        !           752:    returns a value in memory.  */
        !           753: 
        !           754: void
        !           755: preserve_temp_slots (x)
        !           756:      rtx x;
        !           757: {
        !           758:   struct temp_slot *p;
        !           759: 
        !           760:   /* If X is not in memory or is at a constant address, it cannot be in
        !           761:      a temporary slot.  */
        !           762:   if (x == 0 || GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
        !           763:     return;
        !           764: 
        !           765:   /* First see if we can find a match.  */
        !           766:   for (p = temp_slots; p; p = p->next)
        !           767:     if (p->in_use && x == p->slot)
        !           768:       {
        !           769:        p->level--;
        !           770:        return;
        !           771:       }
        !           772: 
        !           773:   /* Otherwise, preserve all non-kept slots at this level.  */
        !           774:   for (p = temp_slots; p; p = p->next)
        !           775:     if (p->in_use && p->level == temp_slot_level && ! p->keep)
        !           776:       p->level--;
        !           777: }
        !           778: 
        !           779: /* Free all temporaries used so far.  This is normally called at the end
        !           780:    of generating code for a statement.  */
        !           781: 
        !           782: void
        !           783: free_temp_slots ()
        !           784: {
        !           785:   struct temp_slot *p;
        !           786: 
        !           787:   for (p = temp_slots; p; p = p->next)
        !           788:     if (p->in_use && p->level == temp_slot_level && ! p->keep)
        !           789:       p->in_use = 0;
        !           790: }
        !           791: 
        !           792: /* Push deeper into the nesting level for stack temporaries.  */
        !           793: 
        !           794: void
        !           795: push_temp_slots ()
        !           796: {
        !           797:   /* For GNU C++, we must allow a sequence to be emitted anywhere in
        !           798:      the level where the sequence was started.  By not changing levels
        !           799:      when the compiler is inside a sequence, the temporaries for the
        !           800:      sequence and the temporaries will not unwittingly conflict with
        !           801:      the temporaries for other sequences and/or code at that level.  */
        !           802:   if (in_sequence_p ())
        !           803:     return;
        !           804: 
        !           805:   temp_slot_level++;
        !           806: }
        !           807: 
        !           808: /* Pop a temporary nesting level.  All slots in use in the current level
        !           809:    are freed.  */
        !           810: 
        !           811: void
        !           812: pop_temp_slots ()
        !           813: {
        !           814:   struct temp_slot *p;
        !           815: 
        !           816:   /* See comment in push_temp_slots about why we don't change levels
        !           817:      in sequences.  */
        !           818:   if (in_sequence_p ())
        !           819:     return;
        !           820: 
        !           821:   for (p = temp_slots; p; p = p->next)
        !           822:     if (p->in_use && p->level == temp_slot_level)
        !           823:       p->in_use = 0;
        !           824: 
        !           825:   temp_slot_level--;
        !           826: }
        !           827: 
        !           828: /* Retroactively move an auto variable from a register to a stack slot.
        !           829:    This is done when an address-reference to the variable is seen.  */
        !           830: 
        !           831: void
        !           832: put_var_into_stack (decl)
        !           833:      tree decl;
        !           834: {
        !           835:   register rtx reg;
        !           836:   register rtx new = 0;
        !           837:   struct function *function = 0;
        !           838:   tree context = decl_function_context (decl);
        !           839: 
        !           840:   /* Get the current rtl used for this object.  */
        !           841:   reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl);
        !           842: 
        !           843:   /* If this variable comes from an outer function,
        !           844:      find that function's saved context.  */
        !           845:   if (context != current_function_decl)
        !           846:     for (function = outer_function_chain; function; function = function->next)
        !           847:       if (function->decl == context)
        !           848:        break;
        !           849: 
        !           850:   /* No need to do anything if decl has no rtx yet
        !           851:      since in that case caller is setting TREE_ADDRESSABLE
        !           852:      and a stack slot will be assigned when the rtl is made.  */
        !           853:   if (reg == 0)
        !           854:     return;
        !           855: 
        !           856:   /* If this is a variable-size object with a pseudo to address it,
        !           857:      put that pseudo into the stack, if the var is nonlocal.  */
        !           858:   if (TREE_NONLOCAL (decl)
        !           859:       && GET_CODE (reg) == MEM
        !           860:       && GET_CODE (XEXP (reg, 0)) == REG
        !           861:       && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)
        !           862:     reg = XEXP (reg, 0);
        !           863:   if (GET_CODE (reg) != REG)
        !           864:     return;
        !           865: 
        !           866:   if (function)
        !           867:     {
        !           868:       if (REGNO (reg) < function->max_parm_reg)
        !           869:        new = function->parm_reg_stack_loc[REGNO (reg)];
        !           870:       if (new == 0)
        !           871:        new = assign_outer_stack_local (GET_MODE (reg),
        !           872:                                        GET_MODE_SIZE (GET_MODE (reg)),
        !           873:                                        0, function);
        !           874:     }
        !           875:   else
        !           876:     {
        !           877:       if (REGNO (reg) < max_parm_reg)
        !           878:        new = parm_reg_stack_loc[REGNO (reg)];
        !           879:       if (new == 0)
        !           880:        new = assign_stack_local (GET_MODE (reg),
        !           881:                                  GET_MODE_SIZE (GET_MODE (reg)),
        !           882:                                  0);
        !           883:     }
        !           884: 
        !           885:   XEXP (reg, 0) = XEXP (new, 0);
        !           886:   /* `volatil' bit means one thing for MEMs, another entirely for REGs.  */
        !           887:   REG_USERVAR_P (reg) = 0;
        !           888:   PUT_CODE (reg, MEM);
        !           889: 
        !           890:   /* If this is a memory ref that contains aggregate components,
        !           891:      mark it as such for cse and loop optimize.  */
        !           892:   MEM_IN_STRUCT_P (reg)
        !           893:     = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
        !           894:        || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
        !           895:        || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
        !           896: 
        !           897:   /* Now make sure that all refs to the variable, previously made
        !           898:      when it was a register, are fixed up to be valid again.  */
        !           899:   if (function)
        !           900:     {
        !           901:       struct var_refs_queue *temp;
        !           902: 
        !           903:       /* Variable is inherited; fix it up when we get back to its function.  */
        !           904:       push_obstacks (function->function_obstack,
        !           905:                     function->function_maybepermanent_obstack);
        !           906:       temp
        !           907:        = (struct var_refs_queue *) oballoc (sizeof (struct var_refs_queue));
        !           908:       temp->modified = reg;
        !           909:       temp->next = function->fixup_var_refs_queue;
        !           910:       function->fixup_var_refs_queue = temp;
        !           911:       pop_obstacks ();
        !           912:     }
        !           913:   else
        !           914:     /* Variable is local; fix it up now.  */
        !           915:     fixup_var_refs (reg);
        !           916: }
        !           917: 
        !           918: static void
        !           919: fixup_var_refs (var)
        !           920:      rtx var;
        !           921: {
        !           922:   tree pending;
        !           923:   rtx first_insn = get_insns ();
        !           924:   struct sequence_stack *stack = sequence_stack;
        !           925:   tree rtl_exps = rtl_expr_chain;
        !           926: 
        !           927:   /* Must scan all insns for stack-refs that exceed the limit.  */
        !           928:   fixup_var_refs_insns (var, first_insn, stack == 0);
        !           929: 
        !           930:   /* Scan all pending sequences too.  */
        !           931:   for (; stack; stack = stack->next)
        !           932:     {
        !           933:       push_to_sequence (stack->first);
        !           934:       fixup_var_refs_insns (var, stack->first, stack->next != 0);
        !           935:       /* Update remembered end of sequence
        !           936:         in case we added an insn at the end.  */
        !           937:       stack->last = get_last_insn ();
        !           938:       end_sequence ();
        !           939:     }
        !           940: 
        !           941:   /* Scan all waiting RTL_EXPRs too.  */
        !           942:   for (pending = rtl_exps; pending; pending = TREE_CHAIN (pending))
        !           943:     {
        !           944:       rtx seq = RTL_EXPR_SEQUENCE (TREE_VALUE (pending));
        !           945:       if (seq != const0_rtx && seq != 0)
        !           946:        {
        !           947:          push_to_sequence (seq);
        !           948:          fixup_var_refs_insns (var, seq, 0);
        !           949:          end_sequence ();
        !           950:        }
        !           951:     }
        !           952: }
        !           953: 
        !           954: /* This structure is used by the following two functions to record MEMs or
        !           955:    pseudos used to replace VAR, any SUBREGs of VAR, and any MEMs containing
        !           956:    VAR as an address.  We need to maintain this list in case two operands of
        !           957:    an insn were required to match; in that case we must ensure we use the
        !           958:    same replacement.  */
        !           959: 
        !           960: struct fixup_replacement
        !           961: {
        !           962:   rtx old;
        !           963:   rtx new;
        !           964:   struct fixup_replacement *next;
        !           965: };
        !           966:    
        !           967: /* REPLACEMENTS is a pointer to a list of the above structures and X is
        !           968:    some part of an insn.  Return a struct fixup_replacement whose OLD
        !           969:    value is equal to X.  Allocate a new structure if no such entry exists. */
        !           970: 
        !           971: static struct fixup_replacement *
        !           972: find_replacement (replacements, x)
        !           973:      struct fixup_replacement **replacements;
        !           974:      rtx x;
        !           975: {
        !           976:   struct fixup_replacement *p;
        !           977: 
        !           978:   /* See if we have already replaced this.  */
        !           979:   for (p = *replacements; p && p->old != x; p = p->next)
        !           980:     ;
        !           981: 
        !           982:   if (p == 0)
        !           983:     {
        !           984:       p = (struct fixup_replacement *) oballoc (sizeof (struct fixup_replacement));
        !           985:       p->old = x;
        !           986:       p->new = 0;
        !           987:       p->next = *replacements;
        !           988:       *replacements = p;
        !           989:     }
        !           990: 
        !           991:   return p;
        !           992: }
        !           993: 
        !           994: /* Scan the insn-chain starting with INSN for refs to VAR
        !           995:    and fix them up.  TOPLEVEL is nonzero if this chain is the
        !           996:    main chain of insns for the current function.  */
        !           997: 
        !           998: static void
        !           999: fixup_var_refs_insns (var, insn, toplevel)
        !          1000:      rtx var;
        !          1001:      rtx insn;
        !          1002:      int toplevel;
        !          1003: {
        !          1004:   while (insn)
        !          1005:     {
        !          1006:       rtx next = NEXT_INSN (insn);
        !          1007:       rtx note;
        !          1008:       if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
        !          1009:          || GET_CODE (insn) == JUMP_INSN)
        !          1010:        {
        !          1011:          /* The insn to load VAR from a home in the arglist
        !          1012:             is now a no-op.  When we see it, just delete it.  */
        !          1013:          if (toplevel
        !          1014:              && GET_CODE (PATTERN (insn)) == SET
        !          1015:              && SET_DEST (PATTERN (insn)) == var
        !          1016:              && rtx_equal_p (SET_SRC (PATTERN (insn)), var))
        !          1017:            {
        !          1018:              next = delete_insn (insn);
        !          1019:              if (insn == last_parm_insn)
        !          1020:                last_parm_insn = PREV_INSN (next);
        !          1021:            }
        !          1022:          else
        !          1023:            {
        !          1024:              /* See if we have to do anything to INSN now that VAR is in
        !          1025:                 memory.  If it needs to be loaded into a pseudo, use a single
        !          1026:                 pseudo for the entire insn in case there is a MATCH_DUP
        !          1027:                 between two operands.  We pass a pointer to the head of
        !          1028:                 a list of struct fixup_replacements.  If fixup_var_refs_1
        !          1029:                 needs to allocate pseudos or replacement MEMs (for SUBREGs),
        !          1030:                 it will record them in this list.
        !          1031:                 
        !          1032:                 If it allocated a pseudo for any replacement, we copy into
        !          1033:                 it here.  */
        !          1034: 
        !          1035:              struct fixup_replacement *replacements = 0;
        !          1036: 
        !          1037:              fixup_var_refs_1 (var, &PATTERN (insn), insn, &replacements);
        !          1038: 
        !          1039:              while (replacements)
        !          1040:                {
        !          1041:                  if (GET_CODE (replacements->new) == REG)
        !          1042:                    {
        !          1043:                      rtx insert_before;
        !          1044: 
        !          1045:                      /* OLD might be a (subreg (mem)).  */
        !          1046:                      if (GET_CODE (replacements->old) == SUBREG)
        !          1047:                        replacements->old
        !          1048:                          = fixup_memory_subreg (replacements->old, insn, 0);
        !          1049:                      else
        !          1050:                        replacements->old
        !          1051:                          = fixup_stack_1 (replacements->old, insn);
        !          1052: 
        !          1053:                      /* We can not separate USE insns from the CALL_INSN
        !          1054:                         that they belong to.  If this is a CALL_INSN, insert
        !          1055:                         the move insn before the USE insns preceeding it
        !          1056:                         instead of immediately before the insn.  */
        !          1057:                      if (GET_CODE (insn) == CALL_INSN)
        !          1058:                        {
        !          1059:                          insert_before = insn;
        !          1060:                          while (GET_CODE (PREV_INSN (insert_before)) == INSN
        !          1061:                                 && GET_CODE (PATTERN (PREV_INSN (insert_before))) == USE)
        !          1062:                            insert_before = PREV_INSN (insert_before);
        !          1063:                        }
        !          1064:                      else
        !          1065:                        insert_before = insn;
        !          1066: 
        !          1067:                      emit_insn_before (gen_move_insn (replacements->new,
        !          1068:                                                       replacements->old),
        !          1069:                                        insert_before);
        !          1070:                    }
        !          1071: 
        !          1072:                  replacements = replacements->next;
        !          1073:                }
        !          1074:            }
        !          1075: 
        !          1076:          /* Also fix up any invalid exprs in the REG_NOTES of this insn.
        !          1077:             But don't touch other insns referred to by reg-notes;
        !          1078:             we will get them elsewhere.  */
        !          1079:          for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
        !          1080:            if (GET_CODE (note) != INSN_LIST)
        !          1081:              XEXP (note, 0) = walk_fixup_memory_subreg (XEXP (note, 0), insn);
        !          1082:        }
        !          1083:       insn = next;
        !          1084:     }
        !          1085: }
        !          1086: 
        !          1087: /* VAR is a MEM that used to be a pseudo register.  See if the rtx expression
        !          1088:    at *LOC in INSN needs to be changed.
        !          1089: 
        !          1090:    REPLACEMENTS is a pointer to a list head that starts out zero, but may
        !          1091:    contain a list of original rtx's and replacements. If we find that we need
        !          1092:    to modify this insn by replacing a memory reference with a pseudo or by
        !          1093:    making a new MEM to implement a SUBREG, we consult that list to see if
        !          1094:    we have already chosen a replacement. If none has already been allocated,
        !          1095:    we allocate it and update the list.  fixup_var_refs_insns will copy VAR
        !          1096:    or the SUBREG, as appropriate, to the pseudo.  */
        !          1097: 
        !          1098: static void
        !          1099: fixup_var_refs_1 (var, loc, insn, replacements)
        !          1100:      register rtx var;
        !          1101:      register rtx *loc;
        !          1102:      rtx insn;
        !          1103:      struct fixup_replacement **replacements;
        !          1104: {
        !          1105:   register int i;
        !          1106:   register rtx x = *loc;
        !          1107:   RTX_CODE code = GET_CODE (x);
        !          1108:   register char *fmt;
        !          1109:   register rtx tem, tem1;
        !          1110:   struct fixup_replacement *replacement;
        !          1111: 
        !          1112:   switch (code)
        !          1113:     {
        !          1114:     case MEM:
        !          1115:       if (var == x)
        !          1116:        {
        !          1117:          /* If we already have a replacement, use it.  Otherwise, 
        !          1118:             try to fix up this address in case it is invalid.  */
        !          1119: 
        !          1120:          replacement = find_replacement (replacements, var);
        !          1121:          if (replacement->new)
        !          1122:            {
        !          1123:              *loc = replacement->new;
        !          1124:              return;
        !          1125:            }
        !          1126: 
        !          1127:          *loc = replacement->new = x = fixup_stack_1 (x, insn);
        !          1128: 
        !          1129:          /* Unless we are forcing memory to register, we can leave things
        !          1130:             the way they are if the insn is valid.  */
        !          1131:             
        !          1132:          INSN_CODE (insn) = -1;
        !          1133:          if (! flag_force_mem && recog_memoized (insn) >= 0)
        !          1134:            return;
        !          1135: 
        !          1136:          *loc = replacement->new = gen_reg_rtx (GET_MODE (x));
        !          1137:          return;
        !          1138:        }
        !          1139: 
        !          1140:       /* If X contains VAR, we need to unshare it here so that we update
        !          1141:         each occurrence separately.  But all identical MEMs in one insn
        !          1142:         must be replaced with the same rtx because of the possibility of
        !          1143:         MATCH_DUPs.  */
        !          1144: 
        !          1145:       if (reg_mentioned_p (var, x))
        !          1146:        {
        !          1147:          replacement = find_replacement (replacements, x);
        !          1148:          if (replacement->new == 0)
        !          1149:            replacement->new = copy_most_rtx (x, var);
        !          1150: 
        !          1151:          *loc = x = replacement->new;
        !          1152:        }
        !          1153:       break;
        !          1154: 
        !          1155:     case REG:
        !          1156:     case CC0:
        !          1157:     case PC:
        !          1158:     case CONST_INT:
        !          1159:     case CONST:
        !          1160:     case SYMBOL_REF:
        !          1161:     case LABEL_REF:
        !          1162:     case CONST_DOUBLE:
        !          1163:       return;
        !          1164: 
        !          1165:     case SIGN_EXTRACT:
        !          1166:     case ZERO_EXTRACT:
        !          1167:       /* Note that in some cases those types of expressions are altered
        !          1168:         by optimize_bit_field, and do not survive to get here.  */
        !          1169:       if (XEXP (x, 0) == var
        !          1170:          || (GET_CODE (XEXP (x, 0)) == SUBREG
        !          1171:              && SUBREG_REG (XEXP (x, 0)) == var))
        !          1172:        {
        !          1173:          /* Get TEM as a valid MEM in the mode presently in the insn.
        !          1174: 
        !          1175:             We don't worry about the possibility of MATCH_DUP here; it
        !          1176:             is highly unlikely and would be tricky to handle.  */
        !          1177: 
        !          1178:          tem = XEXP (x, 0);
        !          1179:          if (GET_CODE (tem) == SUBREG)
        !          1180:            tem = fixup_memory_subreg (tem, insn, 1);
        !          1181:          tem = fixup_stack_1 (tem, insn);
        !          1182: 
        !          1183:          /* Unless we want to load from memory, get TEM into the proper mode
        !          1184:             for an extract from memory.  This can only be done if the
        !          1185:             extract is at a constant position and length.  */
        !          1186: 
        !          1187:          if (! flag_force_mem && GET_CODE (XEXP (x, 1)) == CONST_INT
        !          1188:              && GET_CODE (XEXP (x, 2)) == CONST_INT
        !          1189:              && ! mode_dependent_address_p (XEXP (tem, 0))
        !          1190:              && ! MEM_VOLATILE_P (tem))
        !          1191:            {
        !          1192:              enum machine_mode wanted_mode = VOIDmode;
        !          1193:              enum machine_mode is_mode = GET_MODE (tem);
        !          1194:              int width = INTVAL (XEXP (x, 1));
        !          1195:              int pos = INTVAL (XEXP (x, 2));
        !          1196: 
        !          1197: #ifdef HAVE_extzv
        !          1198:              if (GET_CODE (x) == ZERO_EXTRACT)
        !          1199:                wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
        !          1200: #endif
        !          1201: #ifdef HAVE_extv
        !          1202:              if (GET_CODE (x) == SIGN_EXTRACT)
        !          1203:                wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
        !          1204: #endif
        !          1205:              /* If we have a narrower mode, we can do someting.  */
        !          1206:              if (wanted_mode != VOIDmode
        !          1207:                  && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
        !          1208:                {
        !          1209:                  int offset = pos / BITS_PER_UNIT;
        !          1210:                  rtx old_pos = XEXP (x, 2);
        !          1211:                  rtx newmem;
        !          1212: 
        !          1213:                  /* If the bytes and bits are counted differently, we
        !          1214:                     must adjust the offset.  */
        !          1215: #if BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
        !          1216:                  offset = (GET_MODE_SIZE (is_mode)
        !          1217:                            - GET_MODE_SIZE (wanted_mode) - offset);
        !          1218: #endif
        !          1219: 
        !          1220:                  pos %= GET_MODE_BITSIZE (wanted_mode);
        !          1221: 
        !          1222:                  newmem = gen_rtx (MEM, wanted_mode,
        !          1223:                                    plus_constant (XEXP (tem, 0), offset));
        !          1224:                  RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
        !          1225:                  MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
        !          1226:                  MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
        !          1227: 
        !          1228:                  /* Make the change and see if the insn remains valid.  */
        !          1229:                  INSN_CODE (insn) = -1;
        !          1230:                  XEXP (x, 0) = newmem;
        !          1231:                  XEXP (x, 2) = gen_rtx (CONST_INT, VOIDmode, pos);
        !          1232: 
        !          1233:                  if (recog_memoized (insn) >= 0)
        !          1234:                    return;
        !          1235: 
        !          1236:                  /* Otherwise, restore old position.  XEXP (x, 0) will be
        !          1237:                     restored later.  */
        !          1238:                  XEXP (x, 2) = old_pos;
        !          1239:                }
        !          1240:            }
        !          1241: 
        !          1242:          /* If we get here, the bitfield extract insn can't accept a memory
        !          1243:             reference.  Copy the input into a register.  */
        !          1244: 
        !          1245:          tem1 = gen_reg_rtx (GET_MODE (tem));
        !          1246:          emit_insn_before (gen_move_insn (tem1, tem), insn);
        !          1247:          XEXP (x, 0) = tem1;
        !          1248:          return;
        !          1249:        }
        !          1250:       break;
        !          1251:              
        !          1252:     case SUBREG:
        !          1253:       if (SUBREG_REG (x) == var)
        !          1254:        {
        !          1255:          /* If this SUBREG makes VAR wider, it has become a paradoxical
        !          1256:             SUBREG with VAR in memory, but these aren't allowed at this 
        !          1257:             stage of the compilation.  So load VAR into a pseudo and take
        !          1258:             a SUBREG of that pseudo.  */
        !          1259:          if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var)))
        !          1260:            {
        !          1261:              replacement = find_replacement (replacements, var);
        !          1262:              if (replacement->new == 0)
        !          1263:                replacement->new = gen_reg_rtx (GET_MODE (var));
        !          1264:              SUBREG_REG (x) = replacement->new;
        !          1265:              return;
        !          1266:            }
        !          1267: 
        !          1268:          /* See if we have already found a replacement for this SUBREG.
        !          1269:             If so, use it.  Otherwise, make a MEM and see if the insn
        !          1270:             is recognized.  If not, or if we should force MEM into a register,
        !          1271:             make a pseudo for this SUBREG.  */
        !          1272:          replacement = find_replacement (replacements, x);
        !          1273:          if (replacement->new)
        !          1274:            {
        !          1275:              *loc = replacement->new;
        !          1276:              return;
        !          1277:            }
        !          1278:          
        !          1279:          replacement->new = *loc = fixup_memory_subreg (x, insn, 0);
        !          1280: 
        !          1281:          if (! flag_force_mem && recog_memoized (insn) >= 0)
        !          1282:            return;
        !          1283: 
        !          1284:          *loc = replacement->new = gen_reg_rtx (GET_MODE (x));
        !          1285:          return;
        !          1286:        }
        !          1287:       break;
        !          1288: 
        !          1289:     case SET:
        !          1290:       /* First do special simplification of bit-field references.  */
        !          1291:       if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT
        !          1292:          || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
        !          1293:        optimize_bit_field (x, insn, 0);
        !          1294:       if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT
        !          1295:          || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
        !          1296:        optimize_bit_field (x, insn, 0);
        !          1297: 
        !          1298:       /* If SET_DEST is now a paradoxical SUBREG, put the result of this
        !          1299:         insn into a pseudo and store the low part of the pseudo into VAR. */
        !          1300:       if (GET_CODE (SET_DEST (x)) == SUBREG
        !          1301:          && SUBREG_REG (SET_DEST (x)) == var
        !          1302:          && (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
        !          1303:              > GET_MODE_SIZE (GET_MODE (var))))
        !          1304:        {
        !          1305:          SET_DEST (x) = tem = gen_reg_rtx (GET_MODE (SET_DEST (x)));
        !          1306:          emit_insn_after (gen_move_insn (var, gen_lowpart (GET_MODE (var),
        !          1307:                                                            tem)),
        !          1308:                           insn);
        !          1309:          break;
        !          1310:        }
        !          1311:          
        !          1312:       {
        !          1313:        rtx dest = SET_DEST (x);
        !          1314:        rtx src = SET_SRC (x);
        !          1315:        rtx outerdest = dest;
        !          1316: 
        !          1317:        while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
        !          1318:               || GET_CODE (dest) == SIGN_EXTRACT
        !          1319:               || GET_CODE (dest) == ZERO_EXTRACT)
        !          1320:          dest = XEXP (dest, 0);
        !          1321: 
        !          1322:        if (GET_CODE (src) == SUBREG)
        !          1323:          src = XEXP (src, 0);
        !          1324: 
        !          1325:        /* If VAR does not appear at the top level of the SET
        !          1326:           just scan the lower levels of the tree.  */
        !          1327: 
        !          1328:         if (src != var && dest != var)
        !          1329:          break;
        !          1330: 
        !          1331:        /* We will need to rerecognize this insn.  */
        !          1332:        INSN_CODE (insn) = -1;
        !          1333: 
        !          1334: #ifdef HAVE_insv
        !          1335:        if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var)
        !          1336:          {
        !          1337:            /* Since this case will return, ensure we fixup all the
        !          1338:               operands here.  */
        !          1339:            fixup_var_refs_1 (var, &XEXP (outerdest, 1), insn, replacements);
        !          1340:            fixup_var_refs_1 (var, &XEXP (outerdest, 2), insn, replacements);
        !          1341:            fixup_var_refs_1 (var, &SET_SRC (x), insn, replacements);
        !          1342: 
        !          1343:            tem = XEXP (outerdest, 0);
        !          1344: 
        !          1345:            /* Clean up (SUBREG:SI (MEM:mode ...) 0)
        !          1346:               that may appear inside a ZERO_EXTRACT.
        !          1347:               This was legitimate when the MEM was a REG.  */
        !          1348:            if (GET_CODE (tem) == SUBREG
        !          1349:                && SUBREG_REG (tem) == var)
        !          1350:              tem = fixup_memory_subreg (tem, insn, 1);
        !          1351:            else
        !          1352:              tem = fixup_stack_1 (tem, insn);
        !          1353: 
        !          1354:            if (GET_CODE (XEXP (outerdest, 1)) == CONST_INT
        !          1355:                && GET_CODE (XEXP (outerdest, 2)) == CONST_INT
        !          1356:                && ! mode_dependent_address_p (XEXP (tem, 0))
        !          1357:                && ! MEM_VOLATILE_P (tem))
        !          1358:              {
        !          1359:                enum machine_mode wanted_mode
        !          1360:                  = insn_operand_mode[(int) CODE_FOR_insv][0];
        !          1361:                enum machine_mode is_mode = GET_MODE (tem);
        !          1362:                int width = INTVAL (XEXP (outerdest, 1));
        !          1363:                int pos = INTVAL (XEXP (outerdest, 2));
        !          1364: 
        !          1365:                /* If we have a narrower mode, we can do someting.  */
        !          1366:                if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
        !          1367:                  {
        !          1368:                    int offset = pos / BITS_PER_UNIT;
        !          1369:                    rtx old_pos = XEXP (outerdest, 2);
        !          1370:                    rtx newmem;
        !          1371: 
        !          1372: #if BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
        !          1373:                    offset = (GET_MODE_SIZE (is_mode)
        !          1374:                              - GET_MODE_SIZE (wanted_mode) - offset);
        !          1375: #endif
        !          1376: 
        !          1377:                    pos %= GET_MODE_BITSIZE (wanted_mode);
        !          1378: 
        !          1379:                    newmem = gen_rtx (MEM, wanted_mode,
        !          1380:                                      plus_constant (XEXP (tem, 0), offset));
        !          1381:                    RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
        !          1382:                    MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
        !          1383:                    MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
        !          1384: 
        !          1385:                    /* Make the change and see if the insn remains valid.  */
        !          1386:                    INSN_CODE (insn) = -1;
        !          1387:                    XEXP (outerdest, 0) = newmem;
        !          1388:                    XEXP (outerdest, 2) = gen_rtx (CONST_INT, VOIDmode, pos);
        !          1389:                    
        !          1390:                    if (recog_memoized (insn) >= 0)
        !          1391:                      return;
        !          1392:                    
        !          1393:                    /* Otherwise, restore old position.  XEXP (x, 0) will be
        !          1394:                       restored later.  */
        !          1395:                    XEXP (outerdest, 2) = old_pos;
        !          1396:                  }
        !          1397:              }
        !          1398: 
        !          1399:            /* If we get here, the bit-field store doesn't allow memory
        !          1400:               or isn't located at a constant position.  Load the value into
        !          1401:               a register, do the store, and put it back into memory.  */
        !          1402: 
        !          1403:            tem1 = gen_reg_rtx (GET_MODE (tem));
        !          1404:            emit_insn_before (gen_move_insn (tem1, tem), insn);
        !          1405:            emit_insn_after (gen_move_insn (tem, tem1), insn);
        !          1406:            XEXP (outerdest, 0) = tem1;
        !          1407:            return;
        !          1408:          }
        !          1409: #endif
        !          1410: 
        !          1411:        /* STRICT_LOW_PART is a no-op on memory references
        !          1412:           and it can cause combinations to be unrecognizable,
        !          1413:           so eliminate it.  */
        !          1414: 
        !          1415:        if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
        !          1416:          SET_DEST (x) = XEXP (SET_DEST (x), 0);
        !          1417: 
        !          1418:        /* A valid insn to copy VAR into or out of a register
        !          1419:           must be left alone, to avoid an infinite loop here.
        !          1420:           If the reference to VAR is by a subreg, fix that up,
        !          1421:           since SUBREG is not valid for a memref.
        !          1422:           Also fix up the address of the stack slot.  */
        !          1423: 
        !          1424:        if ((SET_SRC (x) == var
        !          1425:             || (GET_CODE (SET_SRC (x)) == SUBREG
        !          1426:                 && SUBREG_REG (SET_SRC (x)) == var))
        !          1427:            && (GET_CODE (SET_DEST (x)) == REG
        !          1428:                || (GET_CODE (SET_DEST (x)) == SUBREG
        !          1429:                    && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))
        !          1430:            && recog_memoized (insn) >= 0)
        !          1431:          {
        !          1432:            replacement = find_replacement (replacements, SET_SRC (x));
        !          1433:            if (replacement->new)
        !          1434:              {
        !          1435:              SET_SRC (x) = replacement->new;
        !          1436:              return;
        !          1437:            }
        !          1438:            else if (GET_CODE (SET_SRC (x)) == SUBREG)
        !          1439:              SET_SRC (x) = replacement->new
        !          1440:                = fixup_memory_subreg (SET_SRC (x), insn, 0);
        !          1441:            else
        !          1442:              SET_SRC (x) = replacement->new
        !          1443:                = fixup_stack_1 (SET_SRC (x), insn);
        !          1444:            return;
        !          1445:          }
        !          1446: 
        !          1447:        if ((SET_DEST (x) == var
        !          1448:             || (GET_CODE (SET_DEST (x)) == SUBREG
        !          1449:                 && SUBREG_REG (SET_DEST (x)) == var))
        !          1450:            && (GET_CODE (SET_SRC (x)) == REG
        !          1451:                || (GET_CODE (SET_SRC (x)) == SUBREG
        !          1452:                    && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG))
        !          1453:            && recog_memoized (insn) >= 0)
        !          1454:          {
        !          1455:            if (GET_CODE (SET_DEST (x)) == SUBREG)
        !          1456:              SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);
        !          1457:            else
        !          1458:              SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
        !          1459:            return;
        !          1460:          }
        !          1461: 
        !          1462:        /* Otherwise, storing into VAR must be handled specially
        !          1463:           by storing into a temporary and copying that into VAR
        !          1464:           with a new insn after this one.  */
        !          1465: 
        !          1466:        if (dest == var)
        !          1467:          {
        !          1468:            rtx temp;
        !          1469:            rtx fixeddest;
        !          1470:            tem = SET_DEST (x);
        !          1471:            /* STRICT_LOW_PART can be discarded, around a MEM.  */
        !          1472:            if (GET_CODE (tem) == STRICT_LOW_PART)
        !          1473:              tem = XEXP (tem, 0);
        !          1474:            /* Convert (SUBREG (MEM)) to a MEM in a changed mode.  */
        !          1475:            if (GET_CODE (tem) == SUBREG)
        !          1476:              fixeddest = fixup_memory_subreg (tem, insn, 0);
        !          1477:            else
        !          1478:              fixeddest = fixup_stack_1 (tem, insn);
        !          1479: 
        !          1480:            temp = gen_reg_rtx (GET_MODE (tem));
        !          1481:            emit_insn_after (gen_move_insn (fixeddest, temp), insn);
        !          1482:            SET_DEST (x) = temp;
        !          1483:          }
        !          1484:       }
        !          1485:     }
        !          1486: 
        !          1487:   /* Nothing special about this RTX; fix its operands.  */
        !          1488: 
        !          1489:   fmt = GET_RTX_FORMAT (code);
        !          1490:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          1491:     {
        !          1492:       if (fmt[i] == 'e')
        !          1493:        fixup_var_refs_1 (var, &XEXP (x, i), insn, replacements);
        !          1494:       if (fmt[i] == 'E')
        !          1495:        {
        !          1496:          register int j;
        !          1497:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1498:            fixup_var_refs_1 (var, &XVECEXP (x, i, j), insn, replacements);
        !          1499:        }
        !          1500:     }
        !          1501: }
        !          1502: 
        !          1503: /* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
        !          1504:    return an rtx (MEM:m1 newaddr) which is equivalent.
        !          1505:    If any insns must be emitted to compute NEWADDR, put them before INSN.
        !          1506: 
        !          1507:    UNCRITICAL nonzero means accept paradoxical subregs.
        !          1508:    This is used for subregs found inside of ZERO_EXTRACTs.  */
        !          1509: 
        !          1510: static rtx
        !          1511: fixup_memory_subreg (x, insn, uncritical)
        !          1512:      rtx x;
        !          1513:      rtx insn;
        !          1514:      int uncritical;
        !          1515: {
        !          1516:   int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
        !          1517:   rtx addr = XEXP (SUBREG_REG (x), 0);
        !          1518:   enum machine_mode mode = GET_MODE (x);
        !          1519:   rtx saved, result;
        !          1520: 
        !          1521:   /* Paradoxical SUBREGs are usually invalid during RTL generation.  */
        !          1522:   if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
        !          1523:       && ! uncritical)
        !          1524:     abort ();
        !          1525: 
        !          1526: #if BYTES_BIG_ENDIAN
        !          1527:   offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
        !          1528:             - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
        !          1529: #endif
        !          1530:   addr = plus_constant (addr, offset);
        !          1531:   if (!flag_force_addr && memory_address_p (mode, addr))
        !          1532:     /* Shortcut if no insns need be emitted.  */
        !          1533:     return change_address (SUBREG_REG (x), mode, addr);
        !          1534:   start_sequence ();
        !          1535:   result = change_address (SUBREG_REG (x), mode, addr);
        !          1536:   emit_insn_before (gen_sequence (), insn);
        !          1537:   end_sequence ();
        !          1538:   return result;
        !          1539: }
        !          1540: 
        !          1541: /* Do fixup_memory_subreg on all (SUBREG (MEM ...) ...) contained in X.
        !          1542:    Replace subexpressions of X in place.
        !          1543:    If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
        !          1544:    Otherwise return X, with its contents possibly altered.
        !          1545: 
        !          1546:    If any insns must be emitted to compute NEWADDR, put them before INSN.  */
        !          1547: 
        !          1548: static rtx
        !          1549: walk_fixup_memory_subreg (x, insn)
        !          1550:      register rtx x;
        !          1551:      rtx insn;
        !          1552: {
        !          1553:   register enum rtx_code code;
        !          1554:   register char *fmt;
        !          1555:   register int i;
        !          1556: 
        !          1557:   if (x == 0)
        !          1558:     return 0;
        !          1559: 
        !          1560:   code = GET_CODE (x);
        !          1561: 
        !          1562:   if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
        !          1563:     return fixup_memory_subreg (x, insn, 0);
        !          1564: 
        !          1565:   /* Nothing special about this RTX; fix its operands.  */
        !          1566: 
        !          1567:   fmt = GET_RTX_FORMAT (code);
        !          1568:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          1569:     {
        !          1570:       if (fmt[i] == 'e')
        !          1571:        XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn);
        !          1572:       if (fmt[i] == 'E')
        !          1573:        {
        !          1574:          register int j;
        !          1575:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1576:            XVECEXP (x, i, j)
        !          1577:              = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn);
        !          1578:        }
        !          1579:     }
        !          1580:   return x;
        !          1581: }
        !          1582: 
        !          1583: #if 0
        !          1584: /* Fix up any references to stack slots that are invalid memory addresses
        !          1585:    because they exceed the maximum range of a displacement.  */
        !          1586: 
        !          1587: void
        !          1588: fixup_stack_slots ()
        !          1589: {
        !          1590:   register rtx insn;
        !          1591: 
        !          1592:   /* Did we generate a stack slot that is out of range
        !          1593:      or otherwise has an invalid address?  */
        !          1594:   if (invalid_stack_slot)
        !          1595:     {
        !          1596:       /* Yes.  Must scan all insns for stack-refs that exceed the limit.  */
        !          1597:       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
        !          1598:        if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
        !          1599:            || GET_CODE (insn) == JUMP_INSN)
        !          1600:          fixup_stack_1 (PATTERN (insn), insn);
        !          1601:     }
        !          1602: }
        !          1603: #endif
        !          1604: 
        !          1605: /* For each memory ref within X, if it refers to a stack slot
        !          1606:    with an out of range displacement, put the address in a temp register
        !          1607:    (emitting new insns before INSN to load these registers)
        !          1608:    and alter the memory ref to use that register.
        !          1609:    Replace each such MEM rtx with a copy, to avoid clobberage.  */
        !          1610: 
        !          1611: static rtx
        !          1612: fixup_stack_1 (x, insn)
        !          1613:      rtx x;
        !          1614:      rtx insn;
        !          1615: {
        !          1616:   register int i;
        !          1617:   register RTX_CODE code = GET_CODE (x);
        !          1618:   register char *fmt;
        !          1619: 
        !          1620:   if (code == MEM)
        !          1621:     {
        !          1622:       register rtx ad = XEXP (x, 0);
        !          1623:       /* If we have address of a stack slot but it's not valid
        !          1624:         (displacement is too large), compute the sum in a register.  */
        !          1625:       if (GET_CODE (ad) == PLUS
        !          1626:          && GET_CODE (XEXP (ad, 0)) == REG
        !          1627:          && REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER
        !          1628:          && REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER
        !          1629:          && GET_CODE (XEXP (ad, 1)) == CONST_INT)
        !          1630:        {
        !          1631:          rtx temp, seq;
        !          1632:          if (memory_address_p (GET_MODE (x), ad))
        !          1633:            return x;
        !          1634: 
        !          1635:          start_sequence ();
        !          1636:          temp = copy_to_reg (ad);
        !          1637:          seq = gen_sequence ();
        !          1638:          end_sequence ();
        !          1639:          emit_insn_before (seq, insn);
        !          1640:          return change_address (x, VOIDmode, temp);
        !          1641:        }
        !          1642:       return x;
        !          1643:     }
        !          1644: 
        !          1645:   fmt = GET_RTX_FORMAT (code);
        !          1646:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          1647:     {
        !          1648:       if (fmt[i] == 'e')
        !          1649:        XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);
        !          1650:       if (fmt[i] == 'E')
        !          1651:        {
        !          1652:          register int j;
        !          1653:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1654:            XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);
        !          1655:        }
        !          1656:     }
        !          1657:   return x;
        !          1658: }
        !          1659: 
        !          1660: /* Optimization: a bit-field instruction whose field
        !          1661:    happens to be a byte or halfword in memory
        !          1662:    can be changed to a move instruction.
        !          1663: 
        !          1664:    We call here when INSN is an insn to examine or store into a bit-field.
        !          1665:    BODY is the SET-rtx to be altered.
        !          1666: 
        !          1667:    EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0.
        !          1668:    (Currently this is called only from function.c, and EQUIV_MEM
        !          1669:    is always 0.)  */
        !          1670: 
        !          1671: static void
        !          1672: optimize_bit_field (body, insn, equiv_mem)
        !          1673:      rtx body;
        !          1674:      rtx insn;
        !          1675:      rtx *equiv_mem;
        !          1676: {
        !          1677:   register rtx bitfield;
        !          1678:   int destflag;
        !          1679:   rtx seq = 0;
        !          1680:   enum machine_mode mode;
        !          1681: 
        !          1682:   if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT
        !          1683:       || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)
        !          1684:     bitfield = SET_DEST (body), destflag = 1;
        !          1685:   else
        !          1686:     bitfield = SET_SRC (body), destflag = 0;
        !          1687: 
        !          1688:   /* First check that the field being stored has constant size and position
        !          1689:      and is in fact a byte or halfword suitably aligned.  */
        !          1690: 
        !          1691:   if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT
        !          1692:       && GET_CODE (XEXP (bitfield, 2)) == CONST_INT
        !          1693:       && ((mode = mode_for_size (INTVAL (XEXP (bitfield, 1)), MODE_INT, 1))
        !          1694:          != BLKmode)
        !          1695:       && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)
        !          1696:     {
        !          1697:       register rtx memref = 0;
        !          1698: 
        !          1699:       /* Now check that the containing word is memory, not a register,
        !          1700:         and that it is safe to change the machine mode.  */
        !          1701: 
        !          1702:       if (GET_CODE (XEXP (bitfield, 0)) == MEM)
        !          1703:        memref = XEXP (bitfield, 0);
        !          1704:       else if (GET_CODE (XEXP (bitfield, 0)) == REG
        !          1705:               && equiv_mem != 0)
        !          1706:        memref = equiv_mem[REGNO (XEXP (bitfield, 0))];
        !          1707:       else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
        !          1708:               && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM)
        !          1709:        memref = SUBREG_REG (XEXP (bitfield, 0));
        !          1710:       else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
        !          1711:               && equiv_mem != 0
        !          1712:               && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG)
        !          1713:        memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];
        !          1714: 
        !          1715:       if (memref
        !          1716:          && ! mode_dependent_address_p (XEXP (memref, 0))
        !          1717:          && ! MEM_VOLATILE_P (memref))
        !          1718:        {
        !          1719:          /* Now adjust the address, first for any subreg'ing
        !          1720:             that we are now getting rid of,
        !          1721:             and then for which byte of the word is wanted.  */
        !          1722: 
        !          1723:          register int offset = INTVAL (XEXP (bitfield, 2));
        !          1724:          /* Adjust OFFSET to count bits from low-address byte.  */
        !          1725: #if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN
        !          1726:          offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))
        !          1727:                    - offset - INTVAL (XEXP (bitfield, 1)));
        !          1728: #endif
        !          1729:          /* Adjust OFFSET to count bytes from low-address byte.  */
        !          1730:          offset /= BITS_PER_UNIT;
        !          1731:          if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
        !          1732:            {
        !          1733:              offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
        !          1734: #if BYTES_BIG_ENDIAN
        !          1735:              offset -= (MIN (UNITS_PER_WORD,
        !          1736:                              GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
        !          1737:                         - MIN (UNITS_PER_WORD,
        !          1738:                                GET_MODE_SIZE (GET_MODE (memref))));
        !          1739: #endif
        !          1740:            }
        !          1741: 
        !          1742:          memref = change_address (memref, mode, 
        !          1743:                                   plus_constant (XEXP (memref, 0), offset));
        !          1744: 
        !          1745:          /* Store this memory reference where
        !          1746:             we found the bit field reference.  */
        !          1747: 
        !          1748:          if (destflag)
        !          1749:            {
        !          1750:              validate_change (insn, &SET_DEST (body), memref, 1);
        !          1751:              if (! CONSTANT_ADDRESS_P (SET_SRC (body)))
        !          1752:                {
        !          1753:                  rtx src = SET_SRC (body);
        !          1754:                  while (GET_CODE (src) == SUBREG
        !          1755:                         && SUBREG_WORD (src) == 0)
        !          1756:                    src = SUBREG_REG (src);
        !          1757:                  if (GET_MODE (src) != GET_MODE (memref))
        !          1758:                    src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
        !          1759:                  validate_change (insn, &SET_SRC (body), src, 1);
        !          1760:                }
        !          1761:              else if (GET_MODE (SET_SRC (body)) != VOIDmode
        !          1762:                       && GET_MODE (SET_SRC (body)) != GET_MODE (memref))
        !          1763:                /* This shouldn't happen because anything that didn't have
        !          1764:                   one of these modes should have got converted explicitly
        !          1765:                   and then referenced through a subreg.
        !          1766:                   This is so because the original bit-field was
        !          1767:                   handled by agg_mode and so its tree structure had
        !          1768:                   the same mode that memref now has.  */
        !          1769:                abort ();
        !          1770:            }
        !          1771:          else
        !          1772:            {
        !          1773:              rtx dest = SET_DEST (body);
        !          1774: 
        !          1775:              while (GET_CODE (dest) == SUBREG
        !          1776:                     && SUBREG_WORD (dest) == 0)
        !          1777:                dest = SUBREG_REG (dest);
        !          1778: 
        !          1779:              validate_change (insn, &SET_DEST (body), dest, 1);
        !          1780: 
        !          1781:              if (GET_MODE (dest) == GET_MODE (memref))
        !          1782:                validate_change (insn, &SET_SRC (body), memref, 1);
        !          1783:              else
        !          1784:                {
        !          1785:                  /* Convert the mem ref to the destination mode.  */
        !          1786:                  rtx newreg = gen_reg_rtx (GET_MODE (dest));
        !          1787: 
        !          1788:                  start_sequence ();
        !          1789:                  convert_move (newreg, memref,
        !          1790:                                GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);
        !          1791:                  seq = get_insns ();
        !          1792:                  end_sequence ();
        !          1793: 
        !          1794:                  validate_change (insn, &SET_SRC (body), newreg, 1);
        !          1795:                }
        !          1796:            }
        !          1797: 
        !          1798:          /* See if we can convert this extraction or insertion into
        !          1799:             a simple move insn.  We might not be able to do so if this
        !          1800:             was, for example, part of a PARALLEL.
        !          1801: 
        !          1802:             If we succeed, write out any needed conversions.  If we fail,
        !          1803:             it is hard to guess why we failed, so don't do anything
        !          1804:             special; just let the optimization be suppressed.  */
        !          1805: 
        !          1806:          if (apply_change_group () && seq)
        !          1807:            emit_insns_before (seq, insn);
        !          1808:        }
        !          1809:     }
        !          1810: }
        !          1811: 
        !          1812: /* These routines are responsible for converting virtual register references
        !          1813:    to the actual hard register references once RTL generation is complete.
        !          1814: 
        !          1815:    The following four variables are used for communication between the
        !          1816:    routines.  They contain the offsets of the virtual registers from their
        !          1817:    respective hard registers.  */
        !          1818: 
        !          1819: static int in_arg_offset;
        !          1820: static int var_offset;
        !          1821: static int dynamic_offset;
        !          1822: static int out_arg_offset;
        !          1823: 
        !          1824: /* In most machines, the stack pointer register is equivalent to the bottom
        !          1825:    of the stack.  */
        !          1826: 
        !          1827: #ifndef STACK_POINTER_OFFSET
        !          1828: #define STACK_POINTER_OFFSET   0
        !          1829: #endif
        !          1830: 
        !          1831: /* If not defined, pick an appropriate default for the offset of dynamically
        !          1832:    allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,
        !          1833:    REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */
        !          1834: 
        !          1835: #ifndef STACK_DYNAMIC_OFFSET
        !          1836: 
        !          1837: #ifdef ACCUMULATE_OUTGOING_ARGS
        !          1838: /* The bottom of the stack points to the actual arguments.  If
        !          1839:    REG_PARM_STACK_SPACE is defined, this includes the space for the register
        !          1840:    parameters.  However, if OUTGOING_REG_PARM_STACK space is not defined,
        !          1841:    stack space for register parameters is not pushed by the caller, but 
        !          1842:    rather part of the fixed stack areas and hence not included in
        !          1843:    `current_function_outgoing_args_size'.  Nevertheless, we must allow
        !          1844:    for it when allocating stack dynamic objects.  */
        !          1845: 
        !          1846: #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
        !          1847: #define STACK_DYNAMIC_OFFSET(FNDECL)   \
        !          1848: (current_function_outgoing_args_size   \
        !          1849:  + REG_PARM_STACK_SPACE (FNDECL) + (STACK_POINTER_OFFSET))
        !          1850: 
        !          1851: #else
        !          1852: #define STACK_DYNAMIC_OFFSET(FNDECL)   \
        !          1853: (current_function_outgoing_args_size + (STACK_POINTER_OFFSET))
        !          1854: #endif
        !          1855: 
        !          1856: #else
        !          1857: #define STACK_DYNAMIC_OFFSET(FNDECL) STACK_POINTER_OFFSET
        !          1858: #endif
        !          1859: #endif
        !          1860: 
        !          1861: /* Pass through the INSNS of function FNDECL and convert virtual register
        !          1862:    references to hard register references.  */
        !          1863: 
        !          1864: void
        !          1865: instantiate_virtual_regs (fndecl, insns)
        !          1866:      tree fndecl;
        !          1867:      rtx insns;
        !          1868: {
        !          1869:   rtx insn;
        !          1870: 
        !          1871:   /* Compute the offsets to use for this function.  */
        !          1872:   in_arg_offset = FIRST_PARM_OFFSET (fndecl);
        !          1873:   var_offset = STARTING_FRAME_OFFSET;
        !          1874:   dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
        !          1875:   out_arg_offset = STACK_POINTER_OFFSET;
        !          1876: 
        !          1877:   /* Scan all variables and parameters of this function.  For each that is
        !          1878:      in memory, instantiate all virtual registers if the result is a valid
        !          1879:      address.  If not, we do it later.  That will handle most uses of virtual
        !          1880:      regs on many machines.  */
        !          1881:   instantiate_decls (fndecl, 1);
        !          1882: 
        !          1883:   /* Initialize recognition, indicating that volatile is OK.  */
        !          1884:   init_recog ();
        !          1885: 
        !          1886:   /* Scan through all the insns, instantiating every virtual register still
        !          1887:      present.  */
        !          1888:   for (insn = insns; insn; insn = NEXT_INSN (insn))
        !          1889:     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
        !          1890:        || GET_CODE (insn) == CALL_INSN)
        !          1891:       {
        !          1892:        instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1);
        !          1893:        instantiate_virtual_regs_1 (&REG_NOTES (insn), 0, 0);
        !          1894:       }
        !          1895: 
        !          1896:   /* Now instantiate the remaining register equivalences for debugging info.
        !          1897:      These will not be valid addresses.  */
        !          1898:   instantiate_decls (fndecl, 0);
        !          1899: 
        !          1900:   /* Indicate that, from now on, assign_stack_local should use
        !          1901:      frame_pointer_rtx.  */
        !          1902:   virtuals_instantiated = 1;
        !          1903: }
        !          1904: 
        !          1905: /* Scan all decls in FNDECL (both variables and parameters) and instantiate
        !          1906:    all virtual registers in their DECL_RTL's.
        !          1907: 
        !          1908:    If VALID_ONLY, do this only if the resulting address is still valid.
        !          1909:    Otherwise, always do it.  */
        !          1910: 
        !          1911: static void
        !          1912: instantiate_decls (fndecl, valid_only)
        !          1913:      tree fndecl;
        !          1914:      int valid_only;
        !          1915: {
        !          1916:   tree decl;
        !          1917: 
        !          1918:   if (TREE_INLINE (fndecl))
        !          1919:     /* When compiling an inline function, the obstack used for
        !          1920:        rtl allocation is the maybepermanent_obstack.  Calling
        !          1921:        `resume_temporary_allocation' switches us back to that
        !          1922:        obstack while we process this function's parameters.  */
        !          1923:     resume_temporary_allocation ();
        !          1924: 
        !          1925:   /* Process all parameters of the function.  */
        !          1926:   for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
        !          1927:     {
        !          1928:       if (DECL_RTL (decl) && GET_CODE (DECL_RTL (decl)) == MEM)
        !          1929:        instantiate_virtual_regs_1 (&XEXP (DECL_RTL (decl), 0),
        !          1930:                                    valid_only ? DECL_RTL (decl) : 0, 0);
        !          1931: #if 0 /* This is probably correct, but it seems to require fixes
        !          1932:         elsewhere in order to work.  Let's fix them in 2.1.  */
        !          1933:       if (DECL_INCOMING_RTL (decl)
        !          1934:          && GET_CODE (DECL_INCOMING_RTL (decl)) == MEM)
        !          1935:        instantiate_virtual_regs_1 (&XEXP (DECL_INCOMING_RTL (decl), 0),
        !          1936:                                    valid_only ? DECL_INCOMING_RTL (decl) : 0,
        !          1937:                                    0);
        !          1938: #endif
        !          1939:     }
        !          1940: 
        !          1941:   /* Now process all variables defined in the function or its subblocks. */
        !          1942:   instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only);
        !          1943: 
        !          1944:   if (TREE_INLINE (fndecl))
        !          1945:     {
        !          1946:       /* Save all rtl allocated for this function by raising the
        !          1947:         high-water mark on the maybepermanent_obstack.  */
        !          1948:       preserve_data ();
        !          1949:       /* All further rtl allocation is now done in the current_obstack.  */
        !          1950:       rtl_in_current_obstack ();
        !          1951:     }
        !          1952: }
        !          1953: 
        !          1954: /* Subroutine of instantiate_decls: Process all decls in the given
        !          1955:    BLOCK node and all its subblocks.  */
        !          1956: 
        !          1957: static void
        !          1958: instantiate_decls_1 (let, valid_only)
        !          1959:      tree let;
        !          1960:      int valid_only;
        !          1961: {
        !          1962:   tree t;
        !          1963: 
        !          1964:   for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
        !          1965:     if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)
        !          1966:       instantiate_virtual_regs_1 (& XEXP (DECL_RTL (t), 0),
        !          1967:                                  valid_only ? DECL_RTL (t) : 0, 0);
        !          1968: 
        !          1969:   /* Process all subblocks.  */
        !          1970:   for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
        !          1971:     instantiate_decls_1 (t, valid_only);
        !          1972: }
        !          1973: 
        !          1974: /* Given a pointer to a piece of rtx and an optional pointer to the
        !          1975:    containing object, instantiate any virtual registers present in it.
        !          1976: 
        !          1977:    If EXTRA_INSNS, we always do the replacement and generate
        !          1978:    any extra insns before OBJECT.  If it zero, we do nothing if replacement
        !          1979:    is not valid.
        !          1980: 
        !          1981:    Return 1 if we either had nothing to do or if we were able to do the
        !          1982:    needed replacement.  Return 0 otherwise; we only return zero if 
        !          1983:    EXTRA_INSNS is zero.
        !          1984: 
        !          1985:    We first try some simple transformations to avoid the creation of extra
        !          1986:    pseudos.  */
        !          1987: 
        !          1988: static int
        !          1989: instantiate_virtual_regs_1 (loc, object, extra_insns)
        !          1990:      rtx *loc;
        !          1991:      rtx object;
        !          1992:      int extra_insns;
        !          1993: {
        !          1994:   rtx x;
        !          1995:   RTX_CODE code;
        !          1996:   rtx new = 0;
        !          1997:   int offset;
        !          1998:   rtx temp;
        !          1999:   rtx seq;
        !          2000:   int i, j;
        !          2001:   char *fmt;
        !          2002: 
        !          2003:   /* Re-start here to avoid recursion in common cases.  */
        !          2004:  restart:
        !          2005: 
        !          2006:   x = *loc;
        !          2007:   if (x == 0)
        !          2008:     return 1;
        !          2009: 
        !          2010:   code = GET_CODE (x);
        !          2011: 
        !          2012:   /* Check for some special cases.  */
        !          2013:   switch (code)
        !          2014:     {
        !          2015:     case CONST_INT:
        !          2016:     case CONST_DOUBLE:
        !          2017:     case CONST:
        !          2018:     case SYMBOL_REF:
        !          2019:     case CODE_LABEL:
        !          2020:     case PC:
        !          2021:     case CC0:
        !          2022:     case ASM_INPUT:
        !          2023:     case ADDR_VEC:
        !          2024:     case ADDR_DIFF_VEC:
        !          2025:     case RETURN:
        !          2026:       return 1;
        !          2027: 
        !          2028:     case SET:
        !          2029:       /* We are allowed to set the virtual registers.  This means that
        !          2030:         that the actual register should receive the source minus the
        !          2031:         appropriate offset.  This is used, for example, in the handling
        !          2032:         of non-local gotos.  */
        !          2033:       if (SET_DEST (x) == virtual_incoming_args_rtx)
        !          2034:        new = arg_pointer_rtx, offset = - in_arg_offset;
        !          2035:       else if (SET_DEST (x) == virtual_stack_vars_rtx)
        !          2036:        new = frame_pointer_rtx, offset = - var_offset;
        !          2037:       else if (SET_DEST (x) == virtual_stack_dynamic_rtx)
        !          2038:        new = stack_pointer_rtx, offset = - dynamic_offset;
        !          2039:       else if (SET_DEST (x) == virtual_outgoing_args_rtx)
        !          2040:        new = stack_pointer_rtx, offset = - out_arg_offset;
        !          2041: 
        !          2042:       if (new)
        !          2043:        {
        !          2044:          /* The only valid sources here are PLUS or REG.  Just do
        !          2045:             the simplest possible thing to handle them.  */
        !          2046:          if (GET_CODE (SET_SRC (x)) != REG
        !          2047:              && GET_CODE (SET_SRC (x)) != PLUS)
        !          2048:            abort ();
        !          2049: 
        !          2050:          start_sequence ();
        !          2051:          if (GET_CODE (SET_SRC (x)) != REG)
        !          2052:            temp = force_operand (SET_SRC (x), 0);
        !          2053:          else
        !          2054:            temp = SET_SRC (x);
        !          2055:          temp = force_operand (plus_constant (temp, offset), 0);
        !          2056:          seq = get_insns ();
        !          2057:          end_sequence ();
        !          2058: 
        !          2059:          emit_insns_before (seq, object);
        !          2060:          SET_DEST (x) = new;
        !          2061: 
        !          2062:          if (!validate_change (object, &SET_SRC (x), temp, 0)
        !          2063:              || ! extra_insns)
        !          2064:            abort ();
        !          2065: 
        !          2066:          return 1;
        !          2067:        }
        !          2068: 
        !          2069:       instantiate_virtual_regs_1 (&SET_DEST (x), object, extra_insns);
        !          2070:       loc = &SET_SRC (x);
        !          2071:       goto restart;
        !          2072: 
        !          2073:     case PLUS:
        !          2074:       /* Handle special case of virtual register plus constant.  */
        !          2075:       if (CONSTANT_P (XEXP (x, 1)))
        !          2076:        {
        !          2077:          rtx old;
        !          2078: 
        !          2079:          /* Check for (plus (plus VIRT foo) (const_int)) first.  */
        !          2080:          if (GET_CODE (XEXP (x, 0)) == PLUS)
        !          2081:            {
        !          2082:              rtx inner = XEXP (XEXP (x, 0), 0);
        !          2083: 
        !          2084:              if (inner == virtual_incoming_args_rtx)
        !          2085:                new = arg_pointer_rtx, offset = in_arg_offset;
        !          2086:              else if (inner == virtual_stack_vars_rtx)
        !          2087:                new = frame_pointer_rtx, offset = var_offset;
        !          2088:              else if (inner == virtual_stack_dynamic_rtx)
        !          2089:                new = stack_pointer_rtx, offset = dynamic_offset;
        !          2090:              else if (inner == virtual_outgoing_args_rtx)
        !          2091:                new = stack_pointer_rtx, offset = out_arg_offset;
        !          2092:              else
        !          2093:                {
        !          2094:                  loc = &XEXP (x, 0);
        !          2095:                  goto restart;
        !          2096:                }
        !          2097: 
        !          2098:              instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
        !          2099:                                          extra_insns);
        !          2100:              new = gen_rtx (PLUS, Pmode, new, XEXP (XEXP (x, 0), 1));
        !          2101:            }
        !          2102: 
        !          2103:          else if (XEXP (x, 0) == virtual_incoming_args_rtx)
        !          2104:            new = arg_pointer_rtx, offset = in_arg_offset;
        !          2105:          else if (XEXP (x, 0) == virtual_stack_vars_rtx)
        !          2106:            new = frame_pointer_rtx, offset = var_offset;
        !          2107:          else if (XEXP (x, 0) == virtual_stack_dynamic_rtx)
        !          2108:            new = stack_pointer_rtx, offset = dynamic_offset;
        !          2109:          else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
        !          2110:            new = stack_pointer_rtx, offset = out_arg_offset;
        !          2111:          else
        !          2112:            {
        !          2113:              /* We know the second operand is a constant.  Unless the
        !          2114:                 first operand is a REG (which has been already checked),
        !          2115:                 it needs to be checked.  */
        !          2116:              if (GET_CODE (XEXP (x, 0)) != REG)
        !          2117:                {
        !          2118:                  loc = &XEXP (x, 0);
        !          2119:                  goto restart;
        !          2120:                }
        !          2121:              return 1;
        !          2122:            }
        !          2123: 
        !          2124:          old = XEXP (x, 0);
        !          2125:          XEXP (x, 0) = new;
        !          2126:          new = plus_constant (XEXP (x, 1), offset);
        !          2127: 
        !          2128:          /* If the new constant is zero, try to replace the sum with its
        !          2129:             first operand.  */
        !          2130:          if (new == const0_rtx
        !          2131:              && validate_change (object, loc, XEXP (x, 0), 0))
        !          2132:            return 1;
        !          2133: 
        !          2134:          /* Next try to replace constant with new one.  */
        !          2135:          if (!validate_change (object, &XEXP (x, 1), new, 0))
        !          2136:            {
        !          2137:              if (! extra_insns)
        !          2138:                {
        !          2139:                  XEXP (x, 0) = old;
        !          2140:                  return 0;
        !          2141:                }
        !          2142: 
        !          2143:              /* Otherwise copy the new constant into a register and replace
        !          2144:                 constant with that register.  */
        !          2145:              temp = gen_reg_rtx (Pmode);
        !          2146:              if (validate_change (object, &XEXP (x, 1), temp, 0))
        !          2147:                emit_insn_before (gen_move_insn (temp, new), object);
        !          2148:              else
        !          2149:                {
        !          2150:                  /* If that didn't work, replace this expression with a
        !          2151:                     register containing the sum.  */
        !          2152: 
        !          2153:                  new = gen_rtx (PLUS, Pmode, XEXP (x, 0), new);
        !          2154:                  XEXP (x, 0) = old;
        !          2155: 
        !          2156:                  start_sequence ();
        !          2157:                  temp = force_operand (new, 0);
        !          2158:                  seq = get_insns ();
        !          2159:                  end_sequence ();
        !          2160: 
        !          2161:                  emit_insns_before (seq, object);
        !          2162:                  if (! validate_change (object, loc, temp, 0)
        !          2163:                      && ! validate_replace_rtx (x, temp, object))
        !          2164:                    abort ();
        !          2165:                }
        !          2166:            }
        !          2167: 
        !          2168:          return 1;
        !          2169:        }
        !          2170: 
        !          2171:       /* Fall through to generic two-operand expression case.  */
        !          2172:     case EXPR_LIST:
        !          2173:     case CALL:
        !          2174:     case COMPARE:
        !          2175:     case MINUS:
        !          2176:     case MULT:
        !          2177:     case DIV:      case UDIV:
        !          2178:     case MOD:      case UMOD:
        !          2179:     case AND:      case IOR:      case XOR:
        !          2180:     case LSHIFT:   case ASHIFT:   case ROTATE:
        !          2181:     case ASHIFTRT: case LSHIFTRT: case ROTATERT:
        !          2182:     case NE:       case EQ:
        !          2183:     case GE:       case GT:       case GEU:    case GTU:
        !          2184:     case LE:       case LT:       case LEU:    case LTU:
        !          2185:       if (XEXP (x, 1) && ! CONSTANT_P (XEXP (x, 1)))
        !          2186:        instantiate_virtual_regs_1 (&XEXP (x, 1), object, extra_insns);
        !          2187:       loc = &XEXP (x, 0);
        !          2188:       goto restart;
        !          2189: 
        !          2190:     case MEM:
        !          2191:       /* Most cases of MEM that convert to valid addresses have already been
        !          2192:         handled by our scan of regno_reg_rtx.  The only special handling we
        !          2193:         need here is to make a copy of the rtx to ensure it isn't being
        !          2194:         shared if we have to change it to a psuedo. 
        !          2195: 
        !          2196:         If the rtx is a simple reference to an address via a virtual register,
        !          2197:         it can potentially be shared.  In such cases, first try to make it
        !          2198:         a valid address, which can also be shared.  Otherwise, copy it and
        !          2199:         proceed normally. 
        !          2200: 
        !          2201:         First check for common cases that need no processing.  These are
        !          2202:         usually due to instantiation already being done on a previous instance
        !          2203:         of a shared rtx.  */
        !          2204: 
        !          2205:       temp = XEXP (x, 0);
        !          2206:       if (CONSTANT_ADDRESS_P (temp)
        !          2207: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !          2208:          || temp == arg_pointer_rtx
        !          2209: #endif
        !          2210:          || temp == frame_pointer_rtx)
        !          2211:        return 1;
        !          2212: 
        !          2213:       if (GET_CODE (temp) == PLUS
        !          2214:          && CONSTANT_ADDRESS_P (XEXP (temp, 1))
        !          2215:          && (XEXP (temp, 0) == frame_pointer_rtx
        !          2216: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !          2217:              || XEXP (temp, 0) == arg_pointer_rtx
        !          2218: #endif
        !          2219:              ))
        !          2220:        return 1;
        !          2221: 
        !          2222:       if (temp == virtual_stack_vars_rtx
        !          2223:          || temp == virtual_incoming_args_rtx
        !          2224:          || (GET_CODE (temp) == PLUS
        !          2225:              && CONSTANT_ADDRESS_P (XEXP (temp, 1))
        !          2226:              && (XEXP (temp, 0) == virtual_stack_vars_rtx
        !          2227:                  || XEXP (temp, 0) == virtual_incoming_args_rtx)))
        !          2228:        {
        !          2229:          /* This MEM may be shared.  If the substitution can be done without
        !          2230:             the need to generate new pseudos, we want to do it in place
        !          2231:             so all copies of the shared rtx benefit.  The call below will
        !          2232:             only make substitutions if the resulting address is still
        !          2233:             valid.
        !          2234: 
        !          2235:             Note that we cannot pass X as the object in the recursive call
        !          2236:             since the insn being processed may not allow all valid
        !          2237:             addresses.  */
        !          2238: 
        !          2239:          if (instantiate_virtual_regs_1 (&XEXP (x, 0), object, 0))
        !          2240:            return 1;
        !          2241: 
        !          2242:          /* Otherwise make a copy and process that copy.  We copy the entire
        !          2243:             RTL expression since it might be a PLUS which could also be
        !          2244:             shared.  */
        !          2245:          *loc = x = copy_rtx (x);
        !          2246:        }
        !          2247: 
        !          2248:       /* Fall through to generic unary operation case.  */
        !          2249:     case USE:
        !          2250:     case CLOBBER:
        !          2251:     case SUBREG:
        !          2252:     case STRICT_LOW_PART:
        !          2253:     case NEG:          case NOT:
        !          2254:     case PRE_DEC:      case PRE_INC:      case POST_DEC:    case POST_INC:
        !          2255:     case SIGN_EXTEND:  case ZERO_EXTEND:
        !          2256:     case TRUNCATE:     case FLOAT_EXTEND: case FLOAT_TRUNCATE:
        !          2257:     case FLOAT:        case FIX:
        !          2258:     case UNSIGNED_FIX: case UNSIGNED_FLOAT:
        !          2259:     case ABS:
        !          2260:     case SQRT:
        !          2261:     case FFS:
        !          2262:       /* These case either have just one operand or we know that we need not
        !          2263:         check the rest of the operands.  */
        !          2264:       loc = &XEXP (x, 0);
        !          2265:       goto restart;
        !          2266: 
        !          2267:     case REG:
        !          2268:       /* Try to replace with a PLUS.  If that doesn't work, compute the sum
        !          2269:         in front of this insn and substitute the temporary.  */
        !          2270:       if (x == virtual_incoming_args_rtx)
        !          2271:        new = arg_pointer_rtx, offset = in_arg_offset;
        !          2272:       else if (x == virtual_stack_vars_rtx)
        !          2273:        new = frame_pointer_rtx, offset = var_offset;
        !          2274:       else if (x == virtual_stack_dynamic_rtx)
        !          2275:        new = stack_pointer_rtx, offset = dynamic_offset;
        !          2276:       else if (x == virtual_outgoing_args_rtx)
        !          2277:        new = stack_pointer_rtx, offset = out_arg_offset;
        !          2278: 
        !          2279:       if (new)
        !          2280:        {
        !          2281:          temp = plus_constant (new, offset);
        !          2282:          if (!validate_change (object, loc, temp, 0))
        !          2283:            {
        !          2284:              if (! extra_insns)
        !          2285:                return 0;
        !          2286: 
        !          2287:              start_sequence ();
        !          2288:              temp = force_operand (temp, 0);
        !          2289:              seq = get_insns ();
        !          2290:              end_sequence ();
        !          2291: 
        !          2292:              emit_insns_before (seq, object);
        !          2293:              if (! validate_change (object, loc, temp, 0)
        !          2294:                  && ! validate_replace_rtx (x, temp, object))
        !          2295:                abort ();
        !          2296:            }
        !          2297:        }
        !          2298: 
        !          2299:       return 1;
        !          2300:     }
        !          2301: 
        !          2302:   /* Scan all subexpressions.  */
        !          2303:   fmt = GET_RTX_FORMAT (code);
        !          2304:   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
        !          2305:     if (*fmt == 'e')
        !          2306:       {
        !          2307:        if (!instantiate_virtual_regs_1 (&XEXP (x, i), object, extra_insns))
        !          2308:          return 0;
        !          2309:       }
        !          2310:     else if (*fmt == 'E')
        !          2311:       for (j = 0; j < XVECLEN (x, i); j++)
        !          2312:        if (! instantiate_virtual_regs_1 (&XVECEXP (x, i, j), object,
        !          2313:                                          extra_insns))
        !          2314:          return 0;
        !          2315: 
        !          2316:   return 1;
        !          2317: }
        !          2318: 
        !          2319: /* Optimization: assuming this function does not receive nonlocal gotos,
        !          2320:    delete the handlers for such, as well as the insns to establish
        !          2321:    and disestablish them.  */
        !          2322: 
        !          2323: static void
        !          2324: delete_handlers ()
        !          2325: {
        !          2326:   rtx insn;
        !          2327:   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
        !          2328:     {
        !          2329:       /* Delete the handler by turning off the flag that would
        !          2330:         prevent jump_optimize from deleting it.
        !          2331:         Also permit deletion of the nonlocal labels themselves
        !          2332:         if nothing local refers to them.  */
        !          2333:       if (GET_CODE (insn) == CODE_LABEL)
        !          2334:        LABEL_PRESERVE_P (insn) = 0;
        !          2335:       if (GET_CODE (insn) == INSN
        !          2336:          && GET_CODE (PATTERN (insn)) == SET
        !          2337:          && (SET_DEST (PATTERN (insn)) == nonlocal_goto_handler_slot
        !          2338:              || SET_SRC (PATTERN (insn)) == nonlocal_goto_handler_slot
        !          2339:              || SET_DEST (PATTERN (insn)) == nonlocal_goto_stack_level
        !          2340:              || SET_SRC (PATTERN (insn)) == nonlocal_goto_stack_level))
        !          2341:        delete_insn (insn);
        !          2342:     }
        !          2343: }
        !          2344: 
        !          2345: /* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels
        !          2346:    of the current function.  */
        !          2347: 
        !          2348: rtx
        !          2349: nonlocal_label_rtx_list ()
        !          2350: {
        !          2351:   tree t;
        !          2352:   rtx x = 0;
        !          2353: 
        !          2354:   for (t = nonlocal_labels; t; t = TREE_CHAIN (t))
        !          2355:     x = gen_rtx (EXPR_LIST, VOIDmode, label_rtx (TREE_VALUE (t)), x);
        !          2356: 
        !          2357:   return x;
        !          2358: }
        !          2359: 
        !          2360: /* Output a USE for any register use in RTL.
        !          2361:    This is used with -noreg to mark the extent of lifespan
        !          2362:    of any registers used in a user-visible variable's DECL_RTL.  */
        !          2363: 
        !          2364: void
        !          2365: use_variable (rtl)
        !          2366:      rtx rtl;
        !          2367: {
        !          2368:   if (GET_CODE (rtl) == REG)
        !          2369:     /* This is a register variable.  */
        !          2370:     emit_insn (gen_rtx (USE, VOIDmode, rtl));
        !          2371:   else if (GET_CODE (rtl) == MEM
        !          2372:           && GET_CODE (XEXP (rtl, 0)) == REG
        !          2373:           && (REGNO (XEXP (rtl, 0)) < FIRST_VIRTUAL_REGISTER
        !          2374:               || REGNO (XEXP (rtl, 0)) > LAST_VIRTUAL_REGISTER)
        !          2375:           && XEXP (rtl, 0) != current_function_internal_arg_pointer)
        !          2376:     /* This is a variable-sized structure.  */
        !          2377:     emit_insn (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)));
        !          2378: }
        !          2379: 
        !          2380: /* Like use_variable except that it outputs the USEs after INSN
        !          2381:    instead of at the end of the insn-chain.  */
        !          2382: 
        !          2383: void
        !          2384: use_variable_after (rtl, insn)
        !          2385:      rtx rtl, insn;
        !          2386: {
        !          2387:   if (GET_CODE (rtl) == REG)
        !          2388:     /* This is a register variable.  */
        !          2389:     emit_insn_after (gen_rtx (USE, VOIDmode, rtl), insn);
        !          2390:   else if (GET_CODE (rtl) == MEM
        !          2391:           && GET_CODE (XEXP (rtl, 0)) == REG
        !          2392:           && (REGNO (XEXP (rtl, 0)) < FIRST_VIRTUAL_REGISTER
        !          2393:               || REGNO (XEXP (rtl, 0)) > LAST_VIRTUAL_REGISTER)
        !          2394:           && XEXP (rtl, 0) != current_function_internal_arg_pointer)
        !          2395:     /* This is a variable-sized structure.  */
        !          2396:     emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (rtl, 0)), insn);
        !          2397: }
        !          2398: 
        !          2399: int
        !          2400: max_parm_reg_num ()
        !          2401: {
        !          2402:   return max_parm_reg;
        !          2403: }
        !          2404: 
        !          2405: /* Return the first insn following those generated by `assign_parms'.  */
        !          2406: 
        !          2407: rtx
        !          2408: get_first_nonparm_insn ()
        !          2409: {
        !          2410:   if (last_parm_insn)
        !          2411:     return NEXT_INSN (last_parm_insn);
        !          2412:   return get_insns ();
        !          2413: }
        !          2414: 
        !          2415: /* Return 1 if EXP returns an aggregate value, for which an address
        !          2416:    must be passed to the function or returned by the function.  */
        !          2417: 
        !          2418: int
        !          2419: aggregate_value_p (exp)
        !          2420:      tree exp;
        !          2421: {
        !          2422:   if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
        !          2423:     return 1;
        !          2424:   if (RETURN_IN_MEMORY (TREE_TYPE (exp)))
        !          2425:     return 1;
        !          2426:   if (flag_pcc_struct_return
        !          2427:       && (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
        !          2428:          || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE))
        !          2429:     return 1;
        !          2430:   return 0;
        !          2431: }
        !          2432: 
        !          2433: /* Assign RTL expressions to the function's parameters.
        !          2434:    This may involve copying them into registers and using
        !          2435:    those registers as the RTL for them.
        !          2436: 
        !          2437:    If SECOND_TIME is non-zero it means that this function is being
        !          2438:    called a second time.  This is done by integrate.c when a function's
        !          2439:    compilation is deferred.  We need to come back here in case the
        !          2440:    FUNCTION_ARG macro computes items needed for the rest of the compilation
        !          2441:    (such as changing which registers are fixed or caller-saved).  But suppress
        !          2442:    writing any insns or setting DECL_RTL of anything in this case.  */
        !          2443: 
        !          2444: void
        !          2445: assign_parms (fndecl, second_time)
        !          2446:      tree fndecl;
        !          2447:      int second_time;
        !          2448: {
        !          2449:   register tree parm;
        !          2450:   register rtx entry_parm = 0;
        !          2451:   register rtx stack_parm = 0;
        !          2452:   CUMULATIVE_ARGS args_so_far;
        !          2453:   enum machine_mode passed_mode, nominal_mode;
        !          2454:   /* Total space needed so far for args on the stack,
        !          2455:      given as a constant and a tree-expression.  */
        !          2456:   struct args_size stack_args_size;
        !          2457:   tree fntype = TREE_TYPE (fndecl);
        !          2458:   tree fnargs = DECL_ARGUMENTS (fndecl);
        !          2459:   /* This is used for the arg pointer when referring to stack args.  */
        !          2460:   rtx internal_arg_pointer;
        !          2461:   /* This is a dummy PARM_DECL that we used for the function result if 
        !          2462:      the function returns a structure.  */
        !          2463:   tree function_result_decl = 0;
        !          2464:   int nparmregs = list_length (fnargs) + LAST_VIRTUAL_REGISTER + 1;
        !          2465:   int varargs_setup = 0;
        !          2466: 
        !          2467:   /* Nonzero if the last arg is named `__builtin_va_alist',
        !          2468:      which is used on some machines for old-fashioned non-ANSI varargs.h;
        !          2469:      this should be stuck onto the stack as if it had arrived there.  */
        !          2470:   int vararg
        !          2471:     = (fnargs
        !          2472:        && (parm = tree_last (fnargs)) != 0
        !          2473:        && DECL_NAME (parm)
        !          2474:        && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)),
        !          2475:                     "__builtin_va_alist")));
        !          2476: 
        !          2477:   /* Nonzero if function takes extra anonymous args.
        !          2478:      This means the last named arg must be on the stack
        !          2479:      right before the anonymous ones. */
        !          2480:   int stdarg
        !          2481:     = (TYPE_ARG_TYPES (fntype) != 0
        !          2482:        && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
        !          2483:           != void_type_node));
        !          2484: 
        !          2485:   /* If the reg that the virtual arg pointer will be translated into is
        !          2486:      not a fixed reg or is the stack pointer, make a copy of the virtual
        !          2487:      arg pointer, and address parms via the copy.  The frame pointer is
        !          2488:      considered fixed even though it is not marked as such.
        !          2489: 
        !          2490:      The second time through, simply use ap to avoid generating rtx.  */
        !          2491: 
        !          2492:   if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
        !          2493:        || ! (fixed_regs[ARG_POINTER_REGNUM]
        !          2494:             || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM))
        !          2495:       && ! second_time)
        !          2496:     internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
        !          2497:   else
        !          2498:     internal_arg_pointer = virtual_incoming_args_rtx;
        !          2499:   current_function_internal_arg_pointer = internal_arg_pointer;
        !          2500: 
        !          2501:   stack_args_size.constant = 0;
        !          2502:   stack_args_size.var = 0;
        !          2503: 
        !          2504:   /* If struct value address is treated as the first argument, make it so.  */
        !          2505:   if (aggregate_value_p (DECL_RESULT (fndecl))
        !          2506:       && ! current_function_returns_pcc_struct
        !          2507:       && struct_value_incoming_rtx == 0)
        !          2508:     {
        !          2509:       tree type = build_pointer_type (fntype);
        !          2510: 
        !          2511:       function_result_decl = build_decl (PARM_DECL, 0, type);
        !          2512: 
        !          2513:       DECL_ARG_TYPE (function_result_decl) = type;
        !          2514:       TREE_CHAIN (function_result_decl) = fnargs;
        !          2515:       fnargs = function_result_decl;
        !          2516:     }
        !          2517:                               
        !          2518:   parm_reg_stack_loc = (rtx *) oballoc (nparmregs * sizeof (rtx));
        !          2519:   bzero (parm_reg_stack_loc, nparmregs * sizeof (rtx));
        !          2520: 
        !          2521: #ifdef INIT_CUMULATIVE_INCOMING_ARGS
        !          2522:   INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, 0);
        !          2523: #else
        !          2524:   INIT_CUMULATIVE_ARGS (args_so_far, fntype, 0);
        !          2525: #endif
        !          2526: 
        !          2527:   /* We haven't yet found an argument that we must push and pretend the
        !          2528:      caller did.  */
        !          2529:   current_function_pretend_args_size = 0;
        !          2530: 
        !          2531:   for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
        !          2532:     {
        !          2533:       int aggregate
        !          2534:        = (TREE_CODE (TREE_TYPE (parm)) == ARRAY_TYPE
        !          2535:           || TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE
        !          2536:           || TREE_CODE (TREE_TYPE (parm)) == UNION_TYPE);
        !          2537:       struct args_size stack_offset;
        !          2538:       struct args_size arg_size;
        !          2539:       int passed_pointer = 0;
        !          2540:       tree passed_type = DECL_ARG_TYPE (parm);
        !          2541: 
        !          2542:       /* Set LAST_NAMED if this is last named arg before some
        !          2543:         anonymous args.  We treat it as if it were anonymous too.  */
        !          2544:       int last_named = ((TREE_CHAIN (parm) == 0
        !          2545:                         || DECL_NAME (TREE_CHAIN (parm)) == 0)
        !          2546:                        && (vararg || stdarg));
        !          2547: 
        !          2548:       if (TREE_TYPE (parm) == error_mark_node
        !          2549:          /* This can happen after weird syntax errors
        !          2550:             or if an enum type is defined among the parms.  */
        !          2551:          || TREE_CODE (parm) != PARM_DECL
        !          2552:          || passed_type == NULL)
        !          2553:        {
        !          2554:          DECL_RTL (parm) = gen_rtx (MEM, BLKmode, const0_rtx);
        !          2555:          TREE_USED (parm) = 1;
        !          2556:          continue;
        !          2557:        }
        !          2558: 
        !          2559:       /* For varargs.h function, save info about regs and stack space
        !          2560:         used by the individual args, not including the va_alist arg.  */
        !          2561:       if (vararg && last_named)
        !          2562:        current_function_args_info = args_so_far;
        !          2563: 
        !          2564:       /* Find mode of arg as it is passed, and mode of arg
        !          2565:         as it should be during execution of this function.  */
        !          2566:       passed_mode = TYPE_MODE (passed_type);
        !          2567:       nominal_mode = TYPE_MODE (TREE_TYPE (parm));
        !          2568: 
        !          2569: #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
        !          2570:       /* See if this arg was passed by invisible reference.  */
        !          2571:       if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
        !          2572:                                          passed_type, ! last_named))
        !          2573:        {
        !          2574:          passed_type = build_pointer_type (passed_type);
        !          2575:          passed_pointer = 1;
        !          2576:          passed_mode = nominal_mode = Pmode;
        !          2577:        }
        !          2578: #endif
        !          2579: 
        !          2580:       /* Let machine desc say which reg (if any) the parm arrives in.
        !          2581:         0 means it arrives on the stack.  */
        !          2582: #ifdef FUNCTION_INCOMING_ARG
        !          2583:       entry_parm = FUNCTION_INCOMING_ARG (args_so_far, passed_mode,
        !          2584:                                          passed_type, ! last_named);
        !          2585: #else
        !          2586:       entry_parm = FUNCTION_ARG (args_so_far, passed_mode,
        !          2587:                                 passed_type, ! last_named);
        !          2588: #endif
        !          2589: 
        !          2590: #ifdef SETUP_INCOMING_VARARGS
        !          2591:       /* If this is the last named parameter, do any required setup for
        !          2592:         varargs or stdargs.  We need to know about the case of this being an
        !          2593:         addressable type, in which case we skip the registers it
        !          2594:         would have arrived in.
        !          2595: 
        !          2596:         For stdargs, LAST_NAMED will be set for two parameters, the one that
        !          2597:         is actually the last named, and the dummy parameter.  We only
        !          2598:         want to do this action once.
        !          2599: 
        !          2600:         Also, indicate when RTL generation is to be suppressed.  */
        !          2601:       if (last_named && !varargs_setup)
        !          2602:        {
        !          2603:          SETUP_INCOMING_VARARGS (args_so_far, passed_mode, passed_type,
        !          2604:                                  current_function_pretend_args_size,
        !          2605:                                  second_time);
        !          2606:          varargs_setup = 1;
        !          2607:        }
        !          2608: #endif
        !          2609: 
        !          2610:       /* Determine parm's home in the stack,
        !          2611:         in case it arrives in the stack or we should pretend it did.
        !          2612: 
        !          2613:         Compute the stack position and rtx where the argument arrives
        !          2614:         and its size.
        !          2615: 
        !          2616:         There is one complexity here:  If this was a parameter that would
        !          2617:         have been passed in registers, but wasn't only because it is
        !          2618:         __builtin_va_alist, we want locate_and_pad_parm to treat it as if
        !          2619:         it came in a register so that REG_PARM_STACK_SPACE isn't skipped.
        !          2620:         In this case, we call FUNCTION_ARG with NAMED set to 1 instead of
        !          2621:         0 as it was the previous time.  */
        !          2622: 
        !          2623:       locate_and_pad_parm (passed_mode, passed_type,
        !          2624: #ifdef STACK_PARMS_IN_REG_PARM_AREA
        !          2625:                           1,
        !          2626: #else
        !          2627: #ifdef FUNCTION_INCOMING_ARG
        !          2628:                           FUNCTION_INCOMING_ARG (args_so_far, passed_mode,
        !          2629:                                                  passed_type,
        !          2630:                                                  (! last_named
        !          2631:                                                   || varargs_setup)) != 0,
        !          2632: #else
        !          2633:                           FUNCTION_ARG (args_so_far, passed_mode,
        !          2634:                                         passed_type,
        !          2635:                                         ! last_named || varargs_setup) != 0,
        !          2636: #endif
        !          2637: #endif
        !          2638:                           fndecl, &stack_args_size, &stack_offset, &arg_size);
        !          2639: 
        !          2640:       if (! second_time)
        !          2641:        {
        !          2642:          rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
        !          2643: 
        !          2644:          if (offset_rtx == const0_rtx)
        !          2645:            stack_parm = gen_rtx (MEM, passed_mode, internal_arg_pointer);
        !          2646:          else
        !          2647:            stack_parm = gen_rtx (MEM, passed_mode,
        !          2648:                                  gen_rtx (PLUS, Pmode,
        !          2649:                                           internal_arg_pointer, offset_rtx));
        !          2650: 
        !          2651:          /* If this is a memory ref that contains aggregate components,
        !          2652:             mark it as such for cse and loop optimize.  */
        !          2653:          MEM_IN_STRUCT_P (stack_parm) = aggregate;
        !          2654:        }
        !          2655: 
        !          2656:       /* If this parameter was passed both in registers and in the stack,
        !          2657:         use the copy on the stack.  */
        !          2658:       if (MUST_PASS_IN_STACK (passed_mode, passed_type))
        !          2659:        entry_parm = 0;
        !          2660: 
        !          2661:       /* If this parm was passed part in regs and part in memory,
        !          2662:         pretend it arrived entirely in memory
        !          2663:         by pushing the register-part onto the stack.
        !          2664: 
        !          2665:         In the special case of a DImode or DFmode that is split,
        !          2666:         we could put it together in a pseudoreg directly,
        !          2667:         but for now that's not worth bothering with.  */
        !          2668: 
        !          2669:       if (entry_parm)
        !          2670:        {
        !          2671:          int nregs = 0;
        !          2672: #ifdef FUNCTION_ARG_PARTIAL_NREGS
        !          2673:          nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, passed_mode,
        !          2674:                                              passed_type, ! last_named);
        !          2675: #endif
        !          2676: 
        !          2677:          if (nregs > 0)
        !          2678:            {
        !          2679:              current_function_pretend_args_size
        !          2680:                = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
        !          2681:                   / (PARM_BOUNDARY / BITS_PER_UNIT)
        !          2682:                   * (PARM_BOUNDARY / BITS_PER_UNIT));
        !          2683: 
        !          2684:              if (! second_time)
        !          2685:                move_block_from_reg (REGNO (entry_parm),
        !          2686:                                     validize_mem (stack_parm), nregs);
        !          2687:              entry_parm = stack_parm;
        !          2688:            }
        !          2689:        }
        !          2690: 
        !          2691:       /* If we didn't decide this parm came in a register,
        !          2692:         by default it came on the stack.  */
        !          2693:       if (entry_parm == 0)
        !          2694:        entry_parm = stack_parm;
        !          2695: 
        !          2696:       /* Record permanently how this parm was passed.  */
        !          2697:       if (! second_time)
        !          2698:        DECL_INCOMING_RTL (parm) = entry_parm;
        !          2699: 
        !          2700:       /* If there is actually space on the stack for this parm,
        !          2701:         count it in stack_args_size; otherwise set stack_parm to 0
        !          2702:         to indicate there is no preallocated stack slot for the parm.  */
        !          2703: 
        !          2704:       if (entry_parm == stack_parm
        !          2705: #ifdef REG_PARM_STACK_SPACE
        !          2706:          /* On some machines, even if a parm value arrives in a register
        !          2707:             there is still an (uninitialized) stack slot allocated for it.  */
        !          2708:          || REG_PARM_STACK_SPACE (fndecl) > 0
        !          2709: #endif
        !          2710:          )
        !          2711:        {
        !          2712:          stack_args_size.constant += arg_size.constant;
        !          2713:          if (arg_size.var)
        !          2714:            ADD_PARM_SIZE (stack_args_size, arg_size.var);
        !          2715:        }
        !          2716:       else
        !          2717:        /* No stack slot was pushed for this parm.  */
        !          2718:        stack_parm = 0;
        !          2719: 
        !          2720:       /* Update info on where next arg arrives in registers.  */
        !          2721: 
        !          2722:       FUNCTION_ARG_ADVANCE (args_so_far, passed_mode,
        !          2723:                            passed_type, ! last_named);
        !          2724: 
        !          2725:       /* If this is our second time through, we are done with this parm. */
        !          2726:       if (second_time)
        !          2727:        continue;
        !          2728: 
        !          2729:       /* Now adjust STACK_PARM to the mode and precise location
        !          2730:         where this parameter should live during execution,
        !          2731:         if we discover that it must live in the stack during execution.
        !          2732:         To make debuggers happier on big-endian machines, we store
        !          2733:         the value in the last bytes of the space available.  */
        !          2734: 
        !          2735:       if (nominal_mode != BLKmode && nominal_mode != passed_mode
        !          2736:          && stack_parm != 0)
        !          2737:        {
        !          2738:          rtx offset_rtx;
        !          2739: 
        !          2740: #if BYTES_BIG_ENDIAN
        !          2741:          if (GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD)
        !          2742:            stack_offset.constant += (GET_MODE_SIZE (passed_mode)
        !          2743:                                      - GET_MODE_SIZE (nominal_mode));
        !          2744: #endif
        !          2745: 
        !          2746:          offset_rtx = ARGS_SIZE_RTX (stack_offset);
        !          2747:          if (offset_rtx == const0_rtx)
        !          2748:            stack_parm = gen_rtx (MEM, nominal_mode, internal_arg_pointer);
        !          2749:          else
        !          2750:            stack_parm = gen_rtx (MEM, nominal_mode,
        !          2751:                                  gen_rtx (PLUS, Pmode,
        !          2752:                                           internal_arg_pointer, offset_rtx));
        !          2753: 
        !          2754:          /* If this is a memory ref that contains aggregate components,
        !          2755:             mark it as such for cse and loop optimize.  */
        !          2756:          MEM_IN_STRUCT_P (stack_parm) = aggregate;
        !          2757:        }
        !          2758: 
        !          2759:       /* ENTRY_PARM is an RTX for the parameter as it arrives,
        !          2760:         in the mode in which it arrives.
        !          2761:         STACK_PARM is an RTX for a stack slot where the parameter can live
        !          2762:         during the function (in case we want to put it there).
        !          2763:         STACK_PARM is 0 if no stack slot was pushed for it.
        !          2764: 
        !          2765:         Now output code if necessary to convert ENTRY_PARM to
        !          2766:         the type in which this function declares it,
        !          2767:         and store that result in an appropriate place,
        !          2768:         which may be a pseudo reg, may be STACK_PARM,
        !          2769:         or may be a local stack slot if STACK_PARM is 0.
        !          2770: 
        !          2771:         Set DECL_RTL to that place.  */
        !          2772: 
        !          2773:       if (nominal_mode == BLKmode)
        !          2774:        {
        !          2775:          /* If a BLKmode arrives in registers, copy it to a stack slot.  */
        !          2776:          if (GET_CODE (entry_parm) == REG)
        !          2777:            {
        !          2778:              int size_stored = CEIL_ROUND (int_size_in_bytes (TREE_TYPE (parm)),
        !          2779:                                            UNITS_PER_WORD);
        !          2780: 
        !          2781:              /* Note that we will be storing an integral number of words.
        !          2782:                 So we have to be careful to ensure that we allocate an
        !          2783:                 integral number of words.  We do this below in the
        !          2784:                 assign_stack_local if space was not allocated in the argument
        !          2785:                 list.  If it was, this will not work if PARM_BOUNDARY is not
        !          2786:                 a multiple of BITS_PER_WORD.  It isn't clear how to fix this
        !          2787:                 if it becomes a problem.  */
        !          2788: 
        !          2789:              if (stack_parm == 0)
        !          2790:                stack_parm
        !          2791:                  = assign_stack_local (GET_MODE (entry_parm), size_stored, 0);
        !          2792:              else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
        !          2793:                abort ();
        !          2794: 
        !          2795:              move_block_from_reg (REGNO (entry_parm),
        !          2796:                                   validize_mem (stack_parm),
        !          2797:                                   size_stored / UNITS_PER_WORD);
        !          2798:            }
        !          2799:          DECL_RTL (parm) = stack_parm;
        !          2800:        }
        !          2801:       else if (! (
        !          2802: #if 0 /* This change was turned off because it makes compilation bigger.  */
        !          2803:                  !optimize
        !          2804: #else /* It's not clear why the following was replaced.  */
        !          2805:                  /* Obsoleted by preceeding line. */
        !          2806:                  (obey_regdecls && ! TREE_REGDECL (parm)
        !          2807:                   && ! TREE_INLINE (fndecl))
        !          2808: #endif
        !          2809:                  /* layout_decl may set this.  */
        !          2810:                  || TREE_ADDRESSABLE (parm)
        !          2811:                  || TREE_SIDE_EFFECTS (parm)
        !          2812:                  /* If -ffloat-store specified, don't put explicit
        !          2813:                     float variables into registers.  */
        !          2814:                  || (flag_float_store
        !          2815:                      && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))
        !          2816:               /* Always assign pseudo to structure return or item passed
        !          2817:                  by invisible reference.  */
        !          2818:               || passed_pointer || parm == function_result_decl)
        !          2819:        {
        !          2820:          /* Store the parm in a pseudoregister during the function.  */
        !          2821:          register rtx parmreg = gen_reg_rtx (nominal_mode);
        !          2822: 
        !          2823:          REG_USERVAR_P (parmreg) = 1;
        !          2824: 
        !          2825:          /* If this was an item that we received a pointer to, set DECL_RTL
        !          2826:             appropriately.  */
        !          2827:          if (passed_pointer)
        !          2828:            {
        !          2829:              DECL_RTL (parm) = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
        !          2830:              MEM_IN_STRUCT_P (DECL_RTL (parm)) = aggregate;
        !          2831:            }
        !          2832:          else
        !          2833:            DECL_RTL (parm) = parmreg;
        !          2834: 
        !          2835:          /* Copy the value into the register.  */
        !          2836:          if (GET_MODE (parmreg) != GET_MODE (entry_parm))
        !          2837:            convert_move (parmreg, validize_mem (entry_parm), 0);
        !          2838:          else
        !          2839:            emit_move_insn (parmreg, validize_mem (entry_parm));
        !          2840: 
        !          2841:          /* In any case, record the parm's desired stack location
        !          2842:             in case we later discover it must live in the stack.  */
        !          2843:          if (REGNO (parmreg) >= nparmregs)
        !          2844:            {
        !          2845:              rtx *new;
        !          2846:              nparmregs = REGNO (parmreg) + 5;
        !          2847:              new = (rtx *) oballoc (nparmregs * sizeof (rtx));
        !          2848:              bcopy (parm_reg_stack_loc, new, nparmregs * sizeof (rtx));
        !          2849:              parm_reg_stack_loc = new;
        !          2850:            }
        !          2851:          parm_reg_stack_loc[REGNO (parmreg)] = stack_parm;
        !          2852: 
        !          2853:          /* Mark the register as eliminable if we did no conversion
        !          2854:             and it was copied from memory at a fixed offset,
        !          2855:             and the arg pointer was not copied to a pseudo-reg.
        !          2856:             If the arg pointer is a pseudo reg or the offset formed
        !          2857:             an invalid address, such memory-equivalences
        !          2858:             as we make here would screw up life analysis for it.  */
        !          2859:          if (nominal_mode == passed_mode
        !          2860:              && GET_CODE (entry_parm) == MEM
        !          2861:              && stack_offset.var == 0
        !          2862:              && reg_mentioned_p (virtual_incoming_args_rtx,
        !          2863:                                  XEXP (entry_parm, 0)))
        !          2864:            REG_NOTES (get_last_insn ())
        !          2865:              = gen_rtx (EXPR_LIST, REG_EQUIV,
        !          2866:                         entry_parm, REG_NOTES (get_last_insn ()));
        !          2867: 
        !          2868:          /* For pointer data type, suggest pointer register.  */
        !          2869:          if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
        !          2870:            mark_reg_pointer (parmreg);
        !          2871:        }
        !          2872:       else
        !          2873:        {
        !          2874:          /* Value must be stored in the stack slot STACK_PARM
        !          2875:             during function execution.  */
        !          2876: 
        !          2877:          if (passed_mode != nominal_mode)
        !          2878:            /* Conversion is required.  */
        !          2879:            entry_parm = convert_to_mode (nominal_mode, entry_parm, 0);
        !          2880: 
        !          2881:          if (entry_parm != stack_parm)
        !          2882:            {
        !          2883:              if (stack_parm == 0)
        !          2884:                stack_parm = assign_stack_local (GET_MODE (entry_parm),
        !          2885:                                                 GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
        !          2886:              emit_move_insn (validize_mem (stack_parm),
        !          2887:                              validize_mem (entry_parm));
        !          2888:            }
        !          2889: 
        !          2890:          DECL_RTL (parm) = stack_parm;
        !          2891:        }
        !          2892:       
        !          2893:       /* If this "parameter" was the place where we are receiving the
        !          2894:         function's incoming structure pointer, set up the result.  */
        !          2895:       if (parm == function_result_decl)
        !          2896:        DECL_RTL (DECL_RESULT (fndecl))
        !          2897:          = gen_rtx (MEM, DECL_MODE (DECL_RESULT (fndecl)), DECL_RTL (parm));
        !          2898: 
        !          2899:       if (TREE_THIS_VOLATILE (parm))
        !          2900:        MEM_VOLATILE_P (DECL_RTL (parm)) = 1;
        !          2901:       if (TREE_READONLY (parm))
        !          2902:        RTX_UNCHANGING_P (DECL_RTL (parm)) = 1;
        !          2903:     }
        !          2904: 
        !          2905:   max_parm_reg = max_reg_num ();
        !          2906:   last_parm_insn = get_last_insn ();
        !          2907: 
        !          2908:   current_function_args_size = stack_args_size.constant;
        !          2909: 
        !          2910:   /* Adjust function incoming argument size for alignment and
        !          2911:      minimum length.  */
        !          2912: 
        !          2913: #ifdef REG_PARM_STACK_SPACE
        !          2914:   current_function_args_size = MAX (current_function_args_size,
        !          2915:                                    REG_PARM_STACK_SPACE (fndecl));
        !          2916: #endif
        !          2917: 
        !          2918: #ifdef STACK_BOUNDARY
        !          2919: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
        !          2920: 
        !          2921:   current_function_args_size
        !          2922:     = ((current_function_args_size + STACK_BYTES - 1)
        !          2923:        / STACK_BYTES) * STACK_BYTES;
        !          2924: #endif  
        !          2925: 
        !          2926: #ifdef ARGS_GROW_DOWNWARD
        !          2927:   current_function_arg_offset_rtx
        !          2928:     = (stack_args_size.var == 0 ? gen_rtx (CONST_INT, VOIDmode,
        !          2929:                                           -stack_args_size.constant)
        !          2930:        : expand_expr (size_binop (MINUS_EXPR, stack_args_size.var,     
        !          2931:                                  size_int (-stack_args_size.constant)),   
        !          2932:                      0, VOIDmode, 0));
        !          2933: #else
        !          2934:   current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size);
        !          2935: #endif
        !          2936: 
        !          2937:   /* See how many bytes, if any, of its args a function should try to pop
        !          2938:      on return.  */
        !          2939: 
        !          2940:   current_function_pops_args = RETURN_POPS_ARGS (TREE_TYPE (fndecl),
        !          2941:                                                 current_function_args_size);
        !          2942: 
        !          2943:   /* For stdarg.h function, save info about regs and stack space
        !          2944:      used by the named args.  */
        !          2945: 
        !          2946:   if (stdarg)
        !          2947:     current_function_args_info = args_so_far;
        !          2948: 
        !          2949:   /* Set the rtx used for the function return value.  Put this in its
        !          2950:      own variable so any optimizers that need this information don't have
        !          2951:      to include tree.h.  Do this here so it gets done when an inlined
        !          2952:      function gets output.  */
        !          2953: 
        !          2954:   current_function_return_rtx = DECL_RTL (DECL_RESULT (fndecl));
        !          2955: }
        !          2956: 
        !          2957: /* Compute the size and offset from the start of the stacked arguments for a
        !          2958:    parm passed in mode PASSED_MODE and with type TYPE.
        !          2959: 
        !          2960:    INITIAL_OFFSET_PTR points to the current offset into the stacked
        !          2961:    arguments.
        !          2962: 
        !          2963:    The starting offset and size for this parm are returned in *OFFSET_PTR
        !          2964:    and *ARG_SIZE_PTR, respectively.
        !          2965: 
        !          2966:    IN_REGS is non-zero if the argument will be passed in registers.  It will
        !          2967:    never be set if REG_PARM_STACK_SPACE is not defined.
        !          2968: 
        !          2969:    FNDECL is the function in which the argument was defined.
        !          2970: 
        !          2971:    There are two types of rounding that are done.  The first, controlled by
        !          2972:    FUNCTION_ARG_BOUNDARY, forces the offset from the start of the argument
        !          2973:    list to be aligned to the specific boundary (in bits).  This rounding
        !          2974:    affects the initial and starting offsets, but not the argument size.
        !          2975: 
        !          2976:    The second, controlled by FUNCTION_ARG_PADDING and PARM_BOUNDARY,
        !          2977:    optionally rounds the size of the parm to PARM_BOUNDARY.  The
        !          2978:    initial offset is not affected by this rounding, while the size always
        !          2979:    is and the starting offset may be.  */
        !          2980: 
        !          2981: /*  offset_ptr will be negative for ARGS_GROW_DOWNWARD case; 
        !          2982:     initial_offset_ptr is positive because locate_and_pad_parm's
        !          2983:     callers pass in the total size of args so far as
        !          2984:     initial_offset_ptr. arg_size_ptr is always positive.*/
        !          2985: 
        !          2986: static void pad_to_arg_alignment (), pad_below ();
        !          2987: 
        !          2988: void
        !          2989: locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
        !          2990:                     initial_offset_ptr, offset_ptr, arg_size_ptr)
        !          2991:      enum machine_mode passed_mode;
        !          2992:      tree type;
        !          2993:      int in_regs;
        !          2994:      tree fndecl;
        !          2995:      struct args_size *initial_offset_ptr;
        !          2996:      struct args_size *offset_ptr;
        !          2997:      struct args_size *arg_size_ptr;
        !          2998: {
        !          2999:   tree sizetree
        !          3000:     = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
        !          3001:   enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
        !          3002:   int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
        !          3003:   int boundary_in_bytes = boundary / BITS_PER_UNIT;
        !          3004:   int reg_parm_stack_space = 0;
        !          3005: 
        !          3006: #ifdef REG_PARM_STACK_SPACE
        !          3007:   /* If we have found a stack parm before we reach the end of the
        !          3008:      area reserved for registers, skip that area.  */
        !          3009:   if (! in_regs)
        !          3010:     {
        !          3011:       reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
        !          3012:       if (reg_parm_stack_space > 0)
        !          3013:        {
        !          3014:          if (initial_offset_ptr->var)
        !          3015:            {
        !          3016:              initial_offset_ptr->var
        !          3017:                = size_binop (MAX_EXPR, ARGS_SIZE_TREE (*initial_offset_ptr),
        !          3018:                              size_int (reg_parm_stack_space));
        !          3019:              initial_offset_ptr->constant = 0;
        !          3020:            }
        !          3021:          else if (initial_offset_ptr->constant < reg_parm_stack_space)
        !          3022:            initial_offset_ptr->constant = reg_parm_stack_space;
        !          3023:        }
        !          3024:     }
        !          3025: #endif /* REG_PARM_STACK_SPACE */
        !          3026: 
        !          3027:   arg_size_ptr->var = 0;
        !          3028:   arg_size_ptr->constant = 0;
        !          3029: 
        !          3030: #ifdef ARGS_GROW_DOWNWARD
        !          3031:   if (initial_offset_ptr->var)
        !          3032:     {
        !          3033:       offset_ptr->constant = 0;
        !          3034:       offset_ptr->var = size_binop (MINUS_EXPR, integer_zero_node,
        !          3035:                                    initial_offset_ptr->var);
        !          3036:     }
        !          3037:   else
        !          3038:     {
        !          3039:       offset_ptr->constant = - initial_offset_ptr->constant;
        !          3040:       offset_ptr->var = 0;
        !          3041:     }
        !          3042:   if (where_pad == upward
        !          3043:       && (TREE_CODE (sizetree) != INTEGER_CST
        !          3044:          || ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
        !          3045:     sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
        !          3046:   SUB_PARM_SIZE (*offset_ptr, sizetree);
        !          3047:   pad_to_arg_alignment (offset_ptr, boundary);
        !          3048:   if (initial_offset_ptr->var)
        !          3049:     {
        !          3050:       arg_size_ptr->var = size_binop (MINUS_EXPR,
        !          3051:                                      size_binop (MINUS_EXPR,
        !          3052:                                                  integer_zero_node,
        !          3053:                                                  initial_offset_ptr->var),
        !          3054:                                      offset_ptr->var);
        !          3055:     }
        !          3056:   else
        !          3057:     {
        !          3058:       arg_size_ptr->constant = (- initial_offset_ptr->constant -
        !          3059:                                offset_ptr->constant); 
        !          3060:     }
        !          3061: /*  ADD_PARM_SIZE (*arg_size_ptr, sizetree); */
        !          3062:   if (where_pad == downward)
        !          3063:     pad_below (arg_size_ptr, passed_mode, sizetree);
        !          3064: #else /* !ARGS_GROW_DOWNWARD */
        !          3065:   pad_to_arg_alignment (initial_offset_ptr, boundary);
        !          3066:   *offset_ptr = *initial_offset_ptr;
        !          3067:   if (where_pad == downward)
        !          3068:     pad_below (offset_ptr, passed_mode, sizetree);
        !          3069: 
        !          3070: #ifdef PUSH_ROUNDING
        !          3071:   if (passed_mode != BLKmode)
        !          3072:     sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
        !          3073: #endif
        !          3074: 
        !          3075:   if (where_pad != none
        !          3076:       && (TREE_CODE (sizetree) != INTEGER_CST
        !          3077:          || ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
        !          3078:     sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
        !          3079: 
        !          3080:   ADD_PARM_SIZE (*arg_size_ptr, sizetree);
        !          3081: #endif /* ARGS_GROW_DOWNWARD */
        !          3082: }
        !          3083: 
        !          3084: static void
        !          3085: pad_to_arg_alignment (offset_ptr, boundary)
        !          3086:      struct args_size *offset_ptr;
        !          3087:      int boundary;
        !          3088: {
        !          3089:   int boundary_in_bytes = boundary / BITS_PER_UNIT;
        !          3090:   
        !          3091:   if (boundary > BITS_PER_UNIT)
        !          3092:     {
        !          3093:       if (offset_ptr->var)
        !          3094:        {
        !          3095:          offset_ptr->var  =
        !          3096: #ifdef ARGS_GROW_DOWNWARD
        !          3097:            round_down 
        !          3098: #else
        !          3099:            round_up
        !          3100: #endif
        !          3101:              (ARGS_SIZE_TREE (*offset_ptr),
        !          3102:               boundary / BITS_PER_UNIT);
        !          3103:          offset_ptr->constant = 0; /*?*/
        !          3104:        }
        !          3105:       else
        !          3106:        offset_ptr->constant =
        !          3107: #ifdef ARGS_GROW_DOWNWARD
        !          3108:          FLOOR_ROUND (offset_ptr->constant, boundary_in_bytes);
        !          3109: #else
        !          3110:          CEIL_ROUND (offset_ptr->constant, boundary_in_bytes);
        !          3111: #endif
        !          3112:     }
        !          3113: }
        !          3114: 
        !          3115: static void
        !          3116: pad_below (offset_ptr, passed_mode, sizetree)
        !          3117:      struct args_size *offset_ptr;
        !          3118:      enum machine_mode passed_mode;
        !          3119:      tree sizetree;
        !          3120: {
        !          3121:   if (passed_mode != BLKmode)
        !          3122:     {
        !          3123:       if (GET_MODE_BITSIZE (passed_mode) % PARM_BOUNDARY)
        !          3124:        offset_ptr->constant
        !          3125:          += (((GET_MODE_BITSIZE (passed_mode) + PARM_BOUNDARY - 1)
        !          3126:               / PARM_BOUNDARY * PARM_BOUNDARY / BITS_PER_UNIT)
        !          3127:              - GET_MODE_SIZE (passed_mode));
        !          3128:     }
        !          3129:   else
        !          3130:     {
        !          3131:       if (TREE_CODE (sizetree) != INTEGER_CST
        !          3132:          || (TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
        !          3133:        {
        !          3134:          /* Round the size up to multiple of PARM_BOUNDARY bits.  */
        !          3135:          tree s2 = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
        !          3136:          /* Add it in.  */
        !          3137:          ADD_PARM_SIZE (*offset_ptr, s2);
        !          3138:          SUB_PARM_SIZE (*offset_ptr, sizetree);
        !          3139:        }
        !          3140:     }
        !          3141: }
        !          3142: 
        !          3143: static tree
        !          3144: round_down (value, divisor)
        !          3145:      tree value;
        !          3146:      int divisor;
        !          3147: {
        !          3148:   return size_binop (MULT_EXPR,
        !          3149:                     size_binop (FLOOR_DIV_EXPR, value, size_int (divisor)),
        !          3150:                     size_int (divisor));
        !          3151: }
        !          3152: 
        !          3153: /* Walk the tree of blocks describing the binding levels within a function
        !          3154:    and warn about uninitialized variables.
        !          3155:    This is done after calling flow_analysis and before global_alloc
        !          3156:    clobbers the pseudo-regs to hard regs.  */
        !          3157: 
        !          3158: void
        !          3159: uninitialized_vars_warning (block)
        !          3160:      tree block;
        !          3161: {
        !          3162:   register tree decl, sub;
        !          3163:   for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
        !          3164:     {
        !          3165:       if (TREE_CODE (decl) == VAR_DECL
        !          3166:          /* These warnings are unreliable for and aggregates
        !          3167:             because assigning the fields one by one can fail to convince
        !          3168:             flow.c that the entire aggregate was initialized.
        !          3169:             Unions are troublesome because members may be shorter.  */
        !          3170:          && TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
        !          3171:          && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE
        !          3172:          && TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE
        !          3173:          && DECL_RTL (decl) != 0
        !          3174:          && GET_CODE (DECL_RTL (decl)) == REG
        !          3175:          && regno_uninitialized (REGNO (DECL_RTL (decl))))
        !          3176:        warning_with_decl (decl,
        !          3177:                           "`%s' may be used uninitialized in this function");
        !          3178:       if (TREE_CODE (decl) == VAR_DECL
        !          3179:          && DECL_RTL (decl) != 0
        !          3180:          && GET_CODE (DECL_RTL (decl)) == REG
        !          3181:          && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
        !          3182:        warning_with_decl (decl,
        !          3183:                           "variable `%s' may be clobbered by `longjmp'");
        !          3184:     }
        !          3185:   for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
        !          3186:     uninitialized_vars_warning (sub);
        !          3187: }
        !          3188: 
        !          3189: /* Do the appropriate part of uninitialized_vars_warning
        !          3190:    but for arguments instead of local variables.  */
        !          3191: 
        !          3192: void
        !          3193: setjmp_args_warning (block)
        !          3194:      tree block;
        !          3195: {
        !          3196:   register tree decl;
        !          3197:   for (decl = DECL_ARGUMENTS (current_function_decl);
        !          3198:        decl; decl = TREE_CHAIN (decl))
        !          3199:     if (DECL_RTL (decl) != 0
        !          3200:        && GET_CODE (DECL_RTL (decl)) == REG
        !          3201:        && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
        !          3202:       warning_with_decl (decl, "argument `%s' may be clobbered by `longjmp'");
        !          3203: }
        !          3204: 
        !          3205: /* If this function call setjmp, put all vars into the stack
        !          3206:    unless they were declared `register'.  */
        !          3207: 
        !          3208: void
        !          3209: setjmp_protect (block)
        !          3210:      tree block;
        !          3211: {
        !          3212:   register tree decl, sub;
        !          3213:   for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
        !          3214:     if ((TREE_CODE (decl) == VAR_DECL
        !          3215:         || TREE_CODE (decl) == PARM_DECL)
        !          3216:        && DECL_RTL (decl) != 0
        !          3217:        && GET_CODE (DECL_RTL (decl)) == REG
        !          3218:        && (
        !          3219: #ifdef NON_SAVING_SETJMP
        !          3220:            /* If longjmp doesn't restore the registers,
        !          3221:               don't put anything in them.  */
        !          3222:            NON_SAVING_SETJMP
        !          3223:            ||
        !          3224: #endif
        !          3225:            ! TREE_REGDECL (decl)))
        !          3226:       put_var_into_stack (decl);
        !          3227:   for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
        !          3228:     setjmp_protect (sub);
        !          3229: }
        !          3230: 
        !          3231: /* Like the previous function, but for args instead of local variables.  */
        !          3232: 
        !          3233: void
        !          3234: setjmp_protect_args ()
        !          3235: {
        !          3236:   register tree decl, sub;
        !          3237:   for (decl = DECL_ARGUMENTS (current_function_decl);
        !          3238:        decl; decl = TREE_CHAIN (decl))
        !          3239:     if ((TREE_CODE (decl) == VAR_DECL
        !          3240:         || TREE_CODE (decl) == PARM_DECL)
        !          3241:        && DECL_RTL (decl) != 0
        !          3242:        && GET_CODE (DECL_RTL (decl)) == REG
        !          3243:        && (
        !          3244:            /* If longjmp doesn't restore the registers,
        !          3245:               don't put anything in them.  */
        !          3246: #ifdef NON_SAVING_SETJMP
        !          3247:            NON_SAVING_SETJMP
        !          3248:            ||
        !          3249: #endif
        !          3250:            ! TREE_REGDECL (decl)))
        !          3251:       put_var_into_stack (decl);
        !          3252: }
        !          3253: 
        !          3254: /* Return the context-pointer register corresponding to DECL,
        !          3255:    or 0 if it does not need one.  */
        !          3256: 
        !          3257: rtx
        !          3258: lookup_static_chain (decl)
        !          3259:      tree decl;
        !          3260: {
        !          3261:   tree context = decl_function_context (decl);
        !          3262:   tree link;
        !          3263: 
        !          3264:   if (context == 0)
        !          3265:     return 0;
        !          3266:   
        !          3267:   /* We treat inline_function_decl as an alias for the current function
        !          3268:      because that is the inline function whose vars, types, etc.
        !          3269:      are being merged into the current function.
        !          3270:      See expand_inline_function.  */
        !          3271:   if (context == current_function_decl || context == inline_function_decl)
        !          3272:     return virtual_stack_vars_rtx;
        !          3273: 
        !          3274:   for (link = context_display; link; link = TREE_CHAIN (link))
        !          3275:     if (TREE_PURPOSE (link) == context)
        !          3276:       return RTL_EXPR_RTL (TREE_VALUE (link));
        !          3277: 
        !          3278:   abort ();
        !          3279: }
        !          3280: 
        !          3281: /* Convert a stack slot address ADDR for variable VAR
        !          3282:    (from a containing function)
        !          3283:    into an address valid in this function (using a static chain).  */
        !          3284: 
        !          3285: rtx
        !          3286: fix_lexical_addr (addr, var)
        !          3287:      rtx addr;
        !          3288:      tree var;
        !          3289: {
        !          3290:   rtx basereg;
        !          3291:   int displacement;
        !          3292:   tree context = decl_function_context (var);
        !          3293:   struct function *fp;
        !          3294:   rtx base = 0;
        !          3295: 
        !          3296:   /* If this is the present function, we need not do anything.  */
        !          3297:   if (context == current_function_decl || context == inline_function_decl)
        !          3298:     return addr;
        !          3299: 
        !          3300:   for (fp = outer_function_chain; fp; fp = fp->next)
        !          3301:     if (fp->decl == context)
        !          3302:       break;
        !          3303: 
        !          3304:   if (fp == 0)
        !          3305:     abort ();
        !          3306: 
        !          3307:   /* Decode given address as base reg plus displacement.  */
        !          3308:   if (GET_CODE (addr) == REG)
        !          3309:     basereg = addr, displacement = 0;
        !          3310:   else if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT)
        !          3311:     basereg = XEXP (addr, 0), displacement = INTVAL (XEXP (addr, 1));
        !          3312:   else
        !          3313:     abort ();
        !          3314: 
        !          3315:   /* We accept vars reached via the containing function's
        !          3316:      incoming arg pointer and via its stack variables pointer.  */
        !          3317:   if (basereg == fp->internal_arg_pointer)
        !          3318:     {
        !          3319:       /* If reached via arg pointer, get the arg pointer value
        !          3320:         out of that function's stack frame.
        !          3321: 
        !          3322:         There are two cases:  If a separate ap is needed, allocate a
        !          3323:         slot in the outer function for it and dereference it that way.
        !          3324:         This is correct even if the real ap is actually a pseudo.
        !          3325:         Otherwise, just adjust the offset from the frame pointer to
        !          3326:         compensate.  */
        !          3327: 
        !          3328: #ifdef NEED_SEPARATE_AP
        !          3329:       rtx addr;
        !          3330: 
        !          3331:       if (fp->arg_pointer_save_area == 0)
        !          3332:        fp->arg_pointer_save_area
        !          3333:          = assign_outer_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0, fp);
        !          3334: 
        !          3335:       addr = fix_lexical_addr (XEXP (fp->arg_pointer_save_area, 0), var);
        !          3336:       addr = memory_address (Pmode, addr);
        !          3337: 
        !          3338:       base = copy_to_reg (gen_rtx (MEM, Pmode, addr));
        !          3339: #else
        !          3340:       displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET);
        !          3341: #endif
        !          3342:     }
        !          3343: 
        !          3344:   else if (basereg == virtual_stack_vars_rtx)
        !          3345:     {
        !          3346:       /* This is the same code as lookup_static_chain, duplicated here to
        !          3347:         avoid an extra call to decl_function_context.  */
        !          3348:       tree link;
        !          3349: 
        !          3350:       for (link = context_display; link; link = TREE_CHAIN (link))
        !          3351:        if (TREE_PURPOSE (link) == context)
        !          3352:          {
        !          3353:            base = RTL_EXPR_RTL (TREE_VALUE (link));
        !          3354:            break;
        !          3355:          }
        !          3356:     }
        !          3357: 
        !          3358:   if (base == 0)
        !          3359:     abort ();
        !          3360: 
        !          3361:   /* Use same offset, relative to appropriate static chain or argument
        !          3362:      pointer.  */
        !          3363:   return plus_constant (base, displacement);
        !          3364: }
        !          3365: 
        !          3366: /* Return the address of the trampoline for entering nested fn FUNCTION.
        !          3367:    If necessary, allocate a trampoline (in the stack frame)
        !          3368:    and emit rtl to initialize its contents (at entry to this function).  */
        !          3369: 
        !          3370: rtx
        !          3371: trampoline_address (function)
        !          3372:      tree function;
        !          3373: {
        !          3374:   tree link;
        !          3375:   tree rtlexp;
        !          3376:   rtx tramp;
        !          3377:   struct function *fp;
        !          3378:   tree fn_context;
        !          3379: 
        !          3380:   /* Find an existing trampoline and return it.  */
        !          3381:   for (link = trampoline_list; link; link = TREE_CHAIN (link))
        !          3382:     if (TREE_PURPOSE (link) == function)
        !          3383:       return XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0);
        !          3384:   for (fp = outer_function_chain; fp; fp = fp->next)
        !          3385:     for (link = fp->trampoline_list; link; link = TREE_CHAIN (link))
        !          3386:       if (TREE_PURPOSE (link) == function)
        !          3387:        {
        !          3388:          tramp = fix_lexical_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0),
        !          3389:                                    function);
        !          3390:          return round_trampoline_addr (tramp);
        !          3391:        }
        !          3392: 
        !          3393:   /* None exists; we must make one.  */
        !          3394: 
        !          3395:   /* Find the `struct function' for the function containing FUNCTION.  */
        !          3396:   fp = 0;
        !          3397:   fn_context = decl_function_context (function);
        !          3398:   if (fn_context != current_function_decl)
        !          3399:     for (fp = outer_function_chain; fp; fp = fp->next)
        !          3400:       if (fp->decl == fn_context)
        !          3401:        break;
        !          3402: 
        !          3403:   /* Allocate run-time space for this trampoline
        !          3404:      (usually in the defining function's stack frame).  */
        !          3405: #ifdef ALLOCATE_TRAMPOLINE
        !          3406:   tramp = ALLOCATE_TRAMPOLINE (fp);
        !          3407: #else
        !          3408:   /* If rounding needed, allocate extra space
        !          3409:      to ensure we have TRAMPOLINE_SIZE bytes left after rounding up.  */
        !          3410: #ifdef TRAMPOLINE_ALIGNMENT
        !          3411: #define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE + TRAMPOLINE_ALIGNMENT - 1)
        !          3412: #else
        !          3413: #define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
        !          3414: #endif
        !          3415:   if (fp != 0)
        !          3416:     tramp = assign_outer_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0, fp);
        !          3417:   else
        !          3418:     tramp = assign_stack_local (BLKmode, TRAMPOLINE_REAL_SIZE, 0);
        !          3419: #endif
        !          3420: 
        !          3421:   /* Record the trampoline for reuse and note it for later initialization
        !          3422:      by expand_function_end.  */
        !          3423:   if (fp != 0)
        !          3424:     {
        !          3425:       push_obstacks (fp->current_obstack, fp->function_maybepermanent_obstack);
        !          3426:       rtlexp = make_node (RTL_EXPR);
        !          3427:       RTL_EXPR_RTL (rtlexp) = tramp;
        !          3428:       fp->trampoline_list = tree_cons (function, rtlexp, fp->trampoline_list);
        !          3429:       pop_obstacks ();
        !          3430:     }
        !          3431:   else
        !          3432:     {
        !          3433:       /* Make the RTL_EXPR node temporary, not momentary, so that the
        !          3434:         trampoline_list doesn't become garbage.  */
        !          3435:       int momentary = suspend_momentary ();
        !          3436:       rtlexp = make_node (RTL_EXPR);
        !          3437:       resume_momentary (momentary);
        !          3438: 
        !          3439:       RTL_EXPR_RTL (rtlexp) = tramp;
        !          3440:       trampoline_list = tree_cons (function, rtlexp, trampoline_list);
        !          3441:     }
        !          3442: 
        !          3443:   tramp = fix_lexical_addr (XEXP (tramp, 0), function);
        !          3444:   return round_trampoline_addr (tramp);
        !          3445: }
        !          3446: 
        !          3447: /* Given a trampoline address,
        !          3448:    round it to multiple of TRAMPOLINE_ALIGNMENT.  */
        !          3449: 
        !          3450: static rtx
        !          3451: round_trampoline_addr (tramp)
        !          3452:      rtx tramp;
        !          3453: {
        !          3454: #ifdef TRAMPOLINE_ALIGNMENT
        !          3455:   /* Round address up to desired boundary.  */
        !          3456:   rtx temp = gen_reg_rtx (Pmode);
        !          3457:   temp = expand_binop (Pmode, add_optab, tramp,
        !          3458:                       gen_rtx (CONST_INT, VOIDmode, TRAMPOLINE_ALIGNMENT - 1),
        !          3459:                       temp, 0, OPTAB_LIB_WIDEN);
        !          3460:   tramp = expand_binop (Pmode, and_optab, temp,
        !          3461:                        gen_rtx (CONST_INT, VOIDmode, - TRAMPOLINE_ALIGNMENT),
        !          3462:                        temp, 0, OPTAB_LIB_WIDEN);
        !          3463: #endif
        !          3464:   return tramp;
        !          3465: }
        !          3466: 
        !          3467: /* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node)
        !          3468:    and initialize static variables for generating RTL for the statements
        !          3469:    of the function.  */
        !          3470: 
        !          3471: void
        !          3472: init_function_start (subr, filename, line)
        !          3473:      tree subr;
        !          3474:      char *filename;
        !          3475:      int line;
        !          3476: {
        !          3477:   char *junk;
        !          3478: 
        !          3479:   init_stmt_for_function ();
        !          3480: 
        !          3481:   cse_not_expected = ! optimize;
        !          3482: 
        !          3483:   /* Caller save not needed yet.  */
        !          3484:   caller_save_needed = 0;
        !          3485: 
        !          3486:   /* No stack slots have been made yet.  */
        !          3487:   stack_slot_list = 0;
        !          3488: 
        !          3489:   /* There is no stack slot for handling nonlocal gotos.  */
        !          3490:   nonlocal_goto_handler_slot = 0;
        !          3491:   nonlocal_goto_stack_level = 0;
        !          3492: 
        !          3493:   /* No labels have been declared for nonlocal use.  */
        !          3494:   nonlocal_labels = 0;
        !          3495: 
        !          3496:   /* No function calls so far in this function.  */
        !          3497:   function_call_count = 0;
        !          3498: 
        !          3499:   /* No parm regs have been allocated.
        !          3500:      (This is important for output_inline_function.)  */
        !          3501:   max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
        !          3502: 
        !          3503:   /* Initialize the RTL mechanism.  */
        !          3504:   init_emit ();
        !          3505: 
        !          3506:   /* Initialize the queue of pending postincrement and postdecrements,
        !          3507:      and some other info in expr.c.  */
        !          3508:   init_expr ();
        !          3509: 
        !          3510:   /* We haven't done register allocation yet.  */
        !          3511:   reg_renumber = 0;
        !          3512: 
        !          3513:   init_const_rtx_hash_table ();
        !          3514: 
        !          3515:   current_function_name = (*decl_printable_name) (subr, &junk);
        !          3516: 
        !          3517:   /* Nonzero if this is a nested function that uses a static chain.  */
        !          3518: 
        !          3519:   current_function_needs_context
        !          3520:     = (decl_function_context (current_function_decl) != 0);
        !          3521: 
        !          3522:   /* Set if a call to setjmp is seen.  */
        !          3523:   current_function_calls_setjmp = 0;
        !          3524: 
        !          3525:   /* Set if a call to longjmp is seen.  */
        !          3526:   current_function_calls_longjmp = 0;
        !          3527: 
        !          3528:   current_function_calls_alloca = 0;
        !          3529:   current_function_has_nonlocal_label = 0;
        !          3530:   current_function_contains_functions = 0;
        !          3531: 
        !          3532:   current_function_returns_pcc_struct = 0;
        !          3533:   current_function_returns_struct = 0;
        !          3534:   current_function_epilogue_delay_list = 0;
        !          3535:   current_function_uses_const_pool = 0;
        !          3536:   current_function_uses_pic_offset_table = 0;
        !          3537: 
        !          3538:   /* We have not yet needed to make a label to jump to for tail-recursion.  */
        !          3539:   tail_recursion_label = 0;
        !          3540: 
        !          3541:   /* We haven't had a need to make a save area for ap yet.  */
        !          3542: 
        !          3543:   arg_pointer_save_area = 0;
        !          3544: 
        !          3545:   /* No stack slots allocated yet.  */
        !          3546:   frame_offset = 0;
        !          3547: 
        !          3548:   /* No SAVE_EXPRs in this function yet.  */
        !          3549:   save_expr_regs = 0;
        !          3550: 
        !          3551:   /* No RTL_EXPRs in this function yet.  */
        !          3552:   rtl_expr_chain = 0;
        !          3553: 
        !          3554:   /* We have not allocated any temporaries yet.  */
        !          3555:   temp_slots = 0;
        !          3556:   temp_slot_level = 0;
        !          3557: 
        !          3558:   /* Within function body, compute a type's size as soon it is laid out.  */
        !          3559:   immediate_size_expand++;
        !          3560: 
        !          3561:   init_pending_stack_adjust ();
        !          3562:   inhibit_defer_pop = 0;
        !          3563: 
        !          3564:   current_function_outgoing_args_size = 0;
        !          3565: 
        !          3566:   /* Initialize the insn lengths.  */
        !          3567:   init_insn_lengths ();
        !          3568: 
        !          3569:   /* Prevent ever trying to delete the first instruction of a function.
        !          3570:      Also tell final how to output a linenum before the function prologue.  */
        !          3571:   emit_line_note (filename, line);
        !          3572: 
        !          3573:   /* Make sure first insn is a note even if we don't want linenums.
        !          3574:      This makes sure the first insn will never be deleted.
        !          3575:      Also, final expects a note to appear there.  */
        !          3576:   emit_note (0, NOTE_INSN_DELETED);
        !          3577: 
        !          3578:   /* Set flags used by final.c.  */
        !          3579:   if (aggregate_value_p (DECL_RESULT (subr)))
        !          3580:     {
        !          3581: #ifdef PCC_STATIC_STRUCT_RETURN
        !          3582:       if (flag_pcc_struct_return)
        !          3583:        current_function_returns_pcc_struct = 1;
        !          3584:       else
        !          3585: #endif
        !          3586:        current_function_returns_struct = 1;
        !          3587:     }
        !          3588: 
        !          3589:   /* Warn if this value is an aggregate type,
        !          3590:      regardless of which calling convention we are using for it.  */
        !          3591:   if (warn_aggregate_return
        !          3592:       && (TREE_CODE (TREE_TYPE (DECL_RESULT (subr))) == RECORD_TYPE
        !          3593:          || TREE_CODE (TREE_TYPE (DECL_RESULT (subr))) == UNION_TYPE
        !          3594:          || TREE_CODE (TREE_TYPE (DECL_RESULT (subr))) == ARRAY_TYPE))
        !          3595:     warning ("function returns an aggregate");
        !          3596: 
        !          3597:   current_function_returns_pointer
        !          3598:     = (TREE_CODE (TREE_TYPE (DECL_RESULT (subr))) == POINTER_TYPE);
        !          3599: 
        !          3600:   /* Indicate that we need to distinguish between the return value of the
        !          3601:      present function and the return value of a function being called.  */
        !          3602:   rtx_equal_function_value_matters = 1;
        !          3603: 
        !          3604:   /* Indicate that we have not instantiated virtual registers yet.  */
        !          3605:   virtuals_instantiated = 0;
        !          3606: 
        !          3607:   /* Indicate we have no need of a frame pointer yet.  */
        !          3608:   frame_pointer_needed = 0;
        !          3609: 
        !          3610:   /* By default assume not varargs.  */
        !          3611:   current_function_varargs = 0;
        !          3612: }
        !          3613: 
        !          3614: /* Indicate that the current function uses extra args
        !          3615:    not explicitly mentioned in the argument list in any fashion.  */
        !          3616: 
        !          3617: void
        !          3618: mark_varargs ()
        !          3619: {
        !          3620:   current_function_varargs = 1;
        !          3621: }
        !          3622: 
        !          3623: /* Expand a call to __main at the beginning of a possible main function.  */
        !          3624: 
        !          3625: void
        !          3626: expand_main_function ()
        !          3627: {
        !          3628: #ifndef INIT_SECTION_ASM_OP
        !          3629:   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__main"), 0,
        !          3630:                     VOIDmode, 0);
        !          3631: #endif /* not INIT_SECTION_ASM_OP */
        !          3632: }
        !          3633: 
        !          3634: /* Start the RTL for a new function, and set variables used for
        !          3635:    emitting RTL.
        !          3636:    SUBR is the FUNCTION_DECL node.
        !          3637:    PARMS_HAVE_CLEANUPS is nonzero if there are cleanups associated with
        !          3638:    the function's parameters, which must be run at any return statement.  */
        !          3639: 
        !          3640: void
        !          3641: expand_function_start (subr, parms_have_cleanups)
        !          3642:      tree subr;
        !          3643:      int parms_have_cleanups;
        !          3644: {
        !          3645:   register int i;
        !          3646:   tree tem;
        !          3647:   rtx last_ptr;
        !          3648: 
        !          3649:   /* Make sure volatile mem refs aren't considered
        !          3650:      valid operands of arithmetic insns.  */
        !          3651:   init_recog_no_volatile ();
        !          3652: 
        !          3653:   /* If function gets a static chain arg, store it in the stack frame.
        !          3654:      Do this first, so it gets the first stack slot offset.  */
        !          3655:   if (current_function_needs_context)
        !          3656:     emit_move_insn (assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0),
        !          3657:                    static_chain_incoming_rtx);
        !          3658: 
        !          3659:   /* If the parameters of this function need cleaning up, get a label
        !          3660:      for the beginning of the code which executes those cleanups.  This must
        !          3661:      be done before doing anything with return_label.  */
        !          3662:   if (parms_have_cleanups)
        !          3663:     cleanup_label = gen_label_rtx ();
        !          3664:   else
        !          3665:     cleanup_label = 0;
        !          3666: 
        !          3667:   /* Make the label for return statements to jump to, if this machine
        !          3668:      does not have a one-instruction return and uses an epilogue,
        !          3669:      or if it returns a structure, or if it has parm cleanups.  */
        !          3670: #ifdef HAVE_return
        !          3671:   if (cleanup_label == 0 && HAVE_return
        !          3672:       && ! current_function_returns_pcc_struct
        !          3673:       && ! (current_function_returns_struct && ! optimize))
        !          3674:     return_label = 0;
        !          3675:   else
        !          3676:     return_label = gen_label_rtx ();
        !          3677: #else
        !          3678:   return_label = gen_label_rtx ();
        !          3679: #endif
        !          3680: 
        !          3681:   /* Initialize rtx used to return the value.  */
        !          3682:   /* Do this before assign_parms so that we copy the struct value address
        !          3683:      before any library calls that assign parms might generate.  */
        !          3684: 
        !          3685:   /* Decide whether to return the value in memory or in a register.  */
        !          3686:   if (aggregate_value_p (DECL_RESULT (subr)))
        !          3687:     {
        !          3688:       /* Returning something that won't go in a register.  */
        !          3689:       register rtx value_address;
        !          3690: 
        !          3691: #ifdef PCC_STATIC_STRUCT_RETURN
        !          3692:       if (current_function_returns_pcc_struct)
        !          3693:        {
        !          3694:          int size = int_size_in_bytes (TREE_TYPE (DECL_RESULT (subr)));
        !          3695:          value_address = assemble_static_space (size);
        !          3696:        }
        !          3697:       else
        !          3698: #endif
        !          3699:        {
        !          3700:          /* Expect to be passed the address of a place to store the value.
        !          3701:             If it is passed as an argument, assign_parms will take care of
        !          3702:             it.  */
        !          3703:          if (struct_value_incoming_rtx)
        !          3704:            {
        !          3705:              value_address = gen_reg_rtx (Pmode);
        !          3706:              emit_move_insn (value_address, struct_value_incoming_rtx);
        !          3707:            }
        !          3708:        }
        !          3709:       if (value_address)
        !          3710:        DECL_RTL (DECL_RESULT (subr))
        !          3711:          = gen_rtx (MEM, DECL_MODE (DECL_RESULT (subr)),
        !          3712:                     value_address);
        !          3713:     }
        !          3714:   else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
        !          3715:     /* If return mode is void, this decl rtl should not be used.  */
        !          3716:     DECL_RTL (DECL_RESULT (subr)) = 0;
        !          3717:   else if (parms_have_cleanups)
        !          3718:     /* If function will end with cleanup code for parms,
        !          3719:        compute the return values into a pseudo reg,
        !          3720:        which we will copy into the true return register
        !          3721:        after the cleanups are done.  */
        !          3722:     DECL_RTL (DECL_RESULT (subr))
        !          3723:       = gen_reg_rtx (DECL_MODE (DECL_RESULT (subr)));
        !          3724:   else
        !          3725:     /* Scalar, returned in a register.  */
        !          3726:     {
        !          3727: #ifdef FUNCTION_OUTGOING_VALUE
        !          3728:       DECL_RTL (DECL_RESULT (subr))
        !          3729:        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
        !          3730: #else
        !          3731:       DECL_RTL (DECL_RESULT (subr))
        !          3732:        = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
        !          3733: #endif
        !          3734: 
        !          3735:       /* Mark this reg as the function's return value.  */
        !          3736:       if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
        !          3737:        {
        !          3738:          REG_FUNCTION_VALUE_P (DECL_RTL (DECL_RESULT (subr))) = 1;
        !          3739:          /* Needed because we may need to move this to memory
        !          3740:             in case it's a named return value whose address is taken.  */
        !          3741:          TREE_REGDECL (DECL_RESULT (subr)) = 1;
        !          3742:        }
        !          3743:     }
        !          3744: 
        !          3745:   /* Initialize rtx for parameters and local variables.
        !          3746:      In some cases this requires emitting insns.  */
        !          3747: 
        !          3748:   assign_parms (subr, 0);
        !          3749: 
        !          3750:   /* The following was moved from init_function_start.
        !          3751:      The move is supposed to make sdb output more accurate.  */
        !          3752:   /* Indicate the beginning of the function body,
        !          3753:      as opposed to parm setup.  */
        !          3754:   emit_note (0, NOTE_INSN_FUNCTION_BEG);
        !          3755: 
        !          3756:   /* If doing stupid allocation, mark parms as born here.  */
        !          3757: 
        !          3758:   if (GET_CODE (get_last_insn ()) != NOTE)
        !          3759:     emit_note (0, NOTE_INSN_DELETED);
        !          3760:   parm_birth_insn = get_last_insn ();
        !          3761: 
        !          3762:   if (obey_regdecls)
        !          3763:     {
        !          3764:       for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; i++)
        !          3765:        use_variable (regno_reg_rtx[i]);
        !          3766: 
        !          3767:       if (current_function_internal_arg_pointer != virtual_incoming_args_rtx)
        !          3768:        use_variable (current_function_internal_arg_pointer);
        !          3769:     }
        !          3770: 
        !          3771:   /* Fetch static chain values for containing functions.  */
        !          3772:   tem = decl_function_context (current_function_decl);
        !          3773:   if (tem)
        !          3774:     last_ptr = copy_to_reg (static_chain_incoming_rtx);
        !          3775:   context_display = 0;
        !          3776:   while (tem)
        !          3777:     {
        !          3778:       tree rtlexp = make_node (RTL_EXPR);
        !          3779: 
        !          3780:       RTL_EXPR_RTL (rtlexp) = last_ptr;
        !          3781:       context_display = tree_cons (tem, rtlexp, context_display);
        !          3782:       tem = decl_function_context (tem);
        !          3783:       if (tem == 0)
        !          3784:        break;
        !          3785:       /* Chain thru stack frames, assuming pointer to next lexical frame
        !          3786:         is found at the place we always store it.  */
        !          3787: #ifdef FRAME_GROWS_DOWNWARD
        !          3788:       last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
        !          3789: #endif
        !          3790:       last_ptr = copy_to_reg (gen_rtx (MEM, Pmode,
        !          3791:                                       memory_address (Pmode, last_ptr)));
        !          3792:     }
        !          3793: 
        !          3794:   /* After the display initializations is where the tail-recursion label
        !          3795:      should go, if we end up needing one.   Ensure we have a NOTE here
        !          3796:      since some things (like trampolines) get placed before this.  */
        !          3797:   tail_recursion_reentry = emit_note (0, NOTE_INSN_DELETED);
        !          3798: 
        !          3799:   /* Evaluate now the sizes of any types declared among the arguments.  */
        !          3800:   for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
        !          3801:     expand_expr (TREE_VALUE (tem), 0, VOIDmode, 0);
        !          3802: 
        !          3803:   /* Make sure there is a line number after the function entry setup code.  */
        !          3804:   force_next_line_note ();
        !          3805: }
        !          3806: 
        !          3807: /* Generate RTL for the end of the current function.
        !          3808:    FILENAME and LINE are the current position in the source file.  */
        !          3809: 
        !          3810: /* It is up to language-specific callers to do cleanups for parameters.  */
        !          3811: 
        !          3812: void
        !          3813: expand_function_end (filename, line)
        !          3814:      char *filename;
        !          3815:      int line;
        !          3816: {
        !          3817:   register int i;
        !          3818:   tree link;
        !          3819: 
        !          3820:   static rtx initial_trampoline;
        !          3821: 
        !          3822: #ifdef NON_SAVING_SETJMP
        !          3823:   /* Don't put any variables in registers if we call setjmp
        !          3824:      on a machine that fails to restore the registers.  */
        !          3825:   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
        !          3826:     {
        !          3827:       setjmp_protect (DECL_INITIAL (current_function_decl));
        !          3828:       setjmp_protect_args ();
        !          3829:     }
        !          3830: #endif
        !          3831: 
        !          3832:   /* Save the argument pointer if a save area was made for it.  */
        !          3833:   if (arg_pointer_save_area)
        !          3834:     {
        !          3835:       rtx x = gen_move_insn (arg_pointer_save_area, virtual_incoming_args_rtx);
        !          3836:       emit_insn_before (x, tail_recursion_reentry);
        !          3837:     }
        !          3838: 
        !          3839:   /* Initialize any trampolines required by this function.  */
        !          3840:   for (link = trampoline_list; link; link = TREE_CHAIN (link))
        !          3841:     {
        !          3842:       tree function = TREE_PURPOSE (link);
        !          3843:       rtx context = lookup_static_chain (function);
        !          3844:       rtx tramp = RTL_EXPR_RTL (TREE_VALUE (link));
        !          3845:       rtx seq;
        !          3846: 
        !          3847:       /* First make sure this compilation has a template for
        !          3848:         initializing trampolines.  */
        !          3849:       if (initial_trampoline == 0)
        !          3850:        initial_trampoline
        !          3851:          = gen_rtx (MEM, BLKmode, assemble_trampoline_template ());
        !          3852: 
        !          3853:       /* Generate insns to initialize the trampoline.  */
        !          3854:       start_sequence ();
        !          3855:       tramp = change_address (initial_trampoline, BLKmode,
        !          3856:                              round_trampoline_addr (XEXP (tramp, 0)));
        !          3857:       emit_block_move (tramp, initial_trampoline,
        !          3858:                       gen_rtx (CONST_INT, VOIDmode, TRAMPOLINE_SIZE),
        !          3859:                       FUNCTION_BOUNDARY / BITS_PER_UNIT);
        !          3860:       INITIALIZE_TRAMPOLINE (XEXP (tramp, 0),
        !          3861:                             XEXP (DECL_RTL (function), 0), context);
        !          3862:       seq = get_insns ();
        !          3863:       end_sequence ();
        !          3864: 
        !          3865:       /* Put those insns at entry to the containing function (this one).  */
        !          3866:       emit_insns_before (seq, tail_recursion_reentry);
        !          3867:     }
        !          3868:   /* Clear the trampoline_list for the next function.  */
        !          3869:   trampoline_list = 0;
        !          3870: 
        !          3871: #if 0  /* I think unused parms are legitimate enough.  */
        !          3872:   /* Warn about unused parms.  */
        !          3873:   if (warn_unused)
        !          3874:     {
        !          3875:       rtx decl;
        !          3876: 
        !          3877:       for (decl = DECL_ARGUMENTS (current_function_decl);
        !          3878:           decl; decl = TREE_CHAIN (decl))
        !          3879:        if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL)
        !          3880:          warning_with_decl (decl, "unused parameter `%s'");
        !          3881:     }
        !          3882: #endif
        !          3883: 
        !          3884:   /* Delete handlers for nonlocal gotos if nothing uses them.  */
        !          3885:   if (nonlocal_goto_handler_slot != 0 && !current_function_has_nonlocal_label)
        !          3886:     delete_handlers ();
        !          3887: 
        !          3888:   /* End any sequences that failed to be closed due to syntax errors.  */
        !          3889:   while (in_sequence_p ())
        !          3890:     end_sequence (0);
        !          3891: 
        !          3892:   /* Outside function body, can't compute type's actual size
        !          3893:      until next function's body starts.  */
        !          3894:   immediate_size_expand--;
        !          3895: 
        !          3896:   /* If doing stupid register allocation,
        !          3897:      mark register parms as dying here.  */
        !          3898: 
        !          3899:   if (obey_regdecls)
        !          3900:     {
        !          3901:       rtx tem;
        !          3902:       for (i = LAST_VIRTUAL_REGISTER + 1; i < max_parm_reg; i++)
        !          3903:        use_variable (regno_reg_rtx[i]);
        !          3904: 
        !          3905:       /* Likewise for the regs of all the SAVE_EXPRs in the function.  */
        !          3906: 
        !          3907:       for (tem = save_expr_regs; tem; tem = XEXP (tem, 1))
        !          3908:        {
        !          3909:          use_variable (XEXP (tem, 0));
        !          3910:          use_variable_after (XEXP (tem, 0), parm_birth_insn);
        !          3911:        }
        !          3912: 
        !          3913:       if (current_function_internal_arg_pointer != virtual_incoming_args_rtx)
        !          3914:        use_variable (current_function_internal_arg_pointer);
        !          3915:     }
        !          3916: 
        !          3917:   clear_pending_stack_adjust ();
        !          3918:   do_pending_stack_adjust ();
        !          3919: 
        !          3920:   /* Mark the end of the function body.
        !          3921:      If control reaches this insn, the function can drop through
        !          3922:      without returning a value.  */
        !          3923:   emit_note (0, NOTE_INSN_FUNCTION_END);
        !          3924: 
        !          3925:   /* Output a linenumber for the end of the function.
        !          3926:      SDB depends on this.  */
        !          3927:   emit_line_note_force (filename, line);
        !          3928: 
        !          3929:   /* Output the label for the actual return from the function,
        !          3930:      if one is expected.  This happens either because a function epilogue
        !          3931:      is used instead of a return instruction, or because a return was done
        !          3932:      with a goto in order to run local cleanups, or because of pcc-style
        !          3933:      structure returning.  */
        !          3934: 
        !          3935:   if (return_label)
        !          3936:     emit_label (return_label);
        !          3937: 
        !          3938:   /* If we had calls to alloca, and this machine needs
        !          3939:      an accurate stack pointer to exit the function,
        !          3940:      insert some code to save and restore the stack pointer.  */
        !          3941: #ifdef EXIT_IGNORE_STACK
        !          3942:   if (! EXIT_IGNORE_STACK)
        !          3943: #endif
        !          3944:     if (current_function_calls_alloca)
        !          3945:       {
        !          3946:        rtx tem = gen_reg_rtx (Pmode);
        !          3947:        emit_insn_after (gen_rtx (SET, VOIDmode, tem, stack_pointer_rtx),
        !          3948:                         parm_birth_insn);
        !          3949:        emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx, tem));
        !          3950:       }
        !          3951: 
        !          3952:   /* If scalar return value was computed in a pseudo-reg,
        !          3953:      copy that to the hard return register.  */
        !          3954:   if (DECL_RTL (DECL_RESULT (current_function_decl)) != 0
        !          3955:       && GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG
        !          3956:       && (REGNO (DECL_RTL (DECL_RESULT (current_function_decl)))
        !          3957:          >= FIRST_PSEUDO_REGISTER))
        !          3958:     {
        !          3959:       rtx real_decl_result;
        !          3960: 
        !          3961: #ifdef FUNCTION_OUTGOING_VALUE
        !          3962:       real_decl_result
        !          3963:        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
        !          3964:                                   current_function_decl);
        !          3965: #else
        !          3966:       real_decl_result
        !          3967:        = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (current_function_decl)),
        !          3968:                          current_function_decl);
        !          3969: #endif
        !          3970:       REG_FUNCTION_VALUE_P (real_decl_result) = 1;
        !          3971:       emit_move_insn (real_decl_result,
        !          3972:                      DECL_RTL (DECL_RESULT (current_function_decl)));
        !          3973:       emit_insn (gen_rtx (USE, VOIDmode, real_decl_result));
        !          3974:     }
        !          3975: 
        !          3976:   /* If returning a structure, arrange to return the address of the value
        !          3977:      in a place where debuggers expect to find it.
        !          3978: 
        !          3979:      If returning a structure PCC style,
        !          3980:      the caller also depends on this value.
        !          3981:      And current_function_returns_pcc_struct is not necessarily set.  */
        !          3982:   if (current_function_returns_struct
        !          3983:       || current_function_returns_pcc_struct)
        !          3984:     {
        !          3985:       rtx value_address = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
        !          3986:       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
        !          3987: #ifdef FUNCTION_OUTGOING_VALUE
        !          3988:       rtx outgoing
        !          3989:        = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
        !          3990:                                   current_function_decl);
        !          3991: #else
        !          3992:       rtx outgoing
        !          3993:        = FUNCTION_VALUE (build_pointer_type (type),
        !          3994:                          current_function_decl);
        !          3995: #endif
        !          3996: 
        !          3997:       /* Mark this as a function return value so integrate will delete the
        !          3998:         assignment and USE below when inlining this function.  */
        !          3999:       REG_FUNCTION_VALUE_P (outgoing) = 1;
        !          4000: 
        !          4001:       emit_move_insn (outgoing, value_address);
        !          4002:       use_variable (outgoing);
        !          4003:     }
        !          4004: 
        !          4005:   /* Output a return insn if we are using one.
        !          4006:      Otherwise, let the rtl chain end here, to drop through
        !          4007:      into the epilogue.  */
        !          4008: 
        !          4009: #ifdef HAVE_return
        !          4010:   if (HAVE_return)
        !          4011:     {
        !          4012:       emit_jump_insn (gen_return ());
        !          4013:       emit_barrier ();
        !          4014:     }
        !          4015: #endif
        !          4016: 
        !          4017:   /* Fix up any gotos that jumped out to the outermost
        !          4018:      binding level of the function.
        !          4019:      Must follow emitting RETURN_LABEL.  */
        !          4020: 
        !          4021:   /* If you have any cleanups to do at this point,
        !          4022:      and they need to create temporary variables,
        !          4023:      then you will lose.  */
        !          4024:   fixup_gotos (0, 0, 0, get_insns (), 0);
        !          4025: }

unix.superglobalmegacorp.com

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