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