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