|
|
1.1 root 1: /* Expands front end tree to back end RTL for GNU C-Compiler 1.1.1.2 ! root 2: Copyright (C) 1987,1988 Free Software Foundation, Inc. 1.1 root 3: 4: This file is part of GNU CC. 5: 6: GNU CC is distributed in the hope that it will be useful, 7: but WITHOUT ANY WARRANTY. No author or distributor 8: accepts responsibility to anyone for the consequences of using it 9: or for whether it serves any particular purpose or works at all, 10: unless he says so in writing. Refer to the GNU CC General Public 11: License for full details. 12: 13: Everyone is granted permission to copy, modify and redistribute 14: GNU CC, but only under the conditions described in the 15: GNU CC General Public License. A copy of this license is 16: supposed to have been given to you along with GNU CC so you 17: can know your rights and responsibilities. It should be in a 18: file named COPYING. Among other things, the copyright notice 19: and this notice must be preserved on all copies. */ 20: 21: 22: /* This file handles the generation of rtl code from tree structure 1.1.1.2 ! root 23: above the level of expressions, using subroutines in exp*.c and emit-rtl.c. 1.1 root 24: It also creates the rtl expressions for parameters and auto variables 25: and has full responsibility for allocating stack slots. 26: 1.1.1.2 ! root 27: The functions whose names start with `expand_' are called by the ! 28: parser to generate RTL instructions for various kinds of constructs. ! 29: ! 30: Some control and binding constructs require calling several such ! 31: functions at different times. For example, a simple if-then ! 32: is expanded by calling `expand_start_cond' (with the condition-expression ! 33: as argument) before parsing the then-clause and calling `expand_end_cond' ! 34: after parsing the then-clause. ! 35: ! 36: `expand_start_function' is called at the beginning of a function, ! 37: before the function body is parsed, and `expand_end_function' is ! 38: called after parsing the body. ! 39: ! 40: Call `assign_stack_local' to allocate a stack slot for a local variable. ! 41: This is usually done during the RTL generation for the function body, ! 42: but it can also be done in the reload pass when a pseudo-register does ! 43: not get a hard register. ! 44: ! 45: Call `put_var_into_stack' when you learn, belatedly, that a variable ! 46: previously given a pseudo-register must in fact go in the stack. ! 47: This function changes the DECL_RTL to be a stack slot instead of a reg ! 48: then scans all the RTL instructions so far generated to correct them. */ 1.1 root 49: 50: #include "config.h" 51: 52: #include <stdio.h> 53: 54: #include "rtl.h" 55: #include "tree.h" 1.1.1.2 ! root 56: #include "flags.h" 1.1 root 57: #include "insn-flags.h" 1.1.1.2 ! root 58: #include "insn-config.h" 1.1 root 59: #include "expr.h" 1.1.1.2 ! root 60: #include "regs.h" 1.1 root 61: 62: #define MAX(x,y) (((x) > (y)) ? (x) : (y)) 63: #define MIN(x,y) (((x) < (y)) ? (x) : (y)) 64: 1.1.1.2 ! root 65: /* Nonzero if function being compiled pops its args on return. ! 66: May affect compilation of return insn or of function epilogue. */ ! 67: ! 68: int current_function_pops_args; ! 69: ! 70: /* If function's args have a fixed size, this is that size, in bytes. ! 71: Otherwise, it is -1. ! 72: May affect compilation of return insn or of function epilogue. */ ! 73: ! 74: int current_function_args_size; ! 75: ! 76: /* # bytes the prologue should push and pretend that the caller pushed them. ! 77: The prologue must do this, but only if parms can be passed in registers. */ ! 78: ! 79: int current_function_pretend_args_size; ! 80: ! 81: /* Name of function now being compiled. */ ! 82: ! 83: char *current_function_name; ! 84: 1.1 root 85: /* Label that will go on function epilogue. 86: Jumping to this label serves as a "return" instruction 87: on machines which require execution of the epilogue on all returns. */ 88: 1.1.1.2 ! root 89: rtx return_label; 1.1 root 90: 91: /* The FUNCTION_DECL node for the function being compiled. */ 92: 93: static tree this_function; 94: 95: /* Offset to end of allocated area of stack frame. 96: If stack grows down, this is the address of the last stack slot allocated. 97: If stack grows up, this is the address for the next slot. */ 98: static int frame_offset; 99: 1.1.1.2 ! root 100: /* Nonzero if a stack slot has been generated whose address is not ! 101: actually valid. It means that the generated rtl must all be scanned ! 102: to detect and correct the invalid addresses where they occur. */ ! 103: static int invalid_stack_slot; 1.1 root 104: 105: /* Label to jump back to for tail recursion, or 0 if we have 106: not yet needed one for this function. */ 107: static rtx tail_recursion_label; 108: 109: /* Place after which to insert the tail_recursion_label if we need one. */ 110: static rtx tail_recursion_reentry; 111: 1.1.1.2 ! root 112: /* Each time we expand an expression-statement, ! 113: record the expr's type and its RTL value here. */ ! 114: ! 115: static tree last_expr_type; ! 116: static rtx last_expr_value; ! 117: ! 118: static void fixup_gotos (); 1.1 root 119: static int tail_recursion_args (); 1.1.1.2 ! root 120: void fixup_stack_slots (); ! 121: static rtx fixup_stack_1 (); ! 122: static rtx fixup_memory_subreg (); ! 123: static void fixup_var_refs (); ! 124: static rtx fixup_var_refs_1 (); ! 125: static rtx parm_stack_loc (); ! 126: static void optimize_bit_field (); ! 127: void do_jump_if_equal (); 1.1 root 128: 1.1.1.2 ! root 129: /* Stack of control and binding constructs we are currently inside. 1.1 root 130: 1.1.1.2 ! root 131: These constructs begin when you call `expand_start_WHATEVER' ! 132: and end when you call `expand_end_WHATEVER'. This stack records ! 133: info about how the construct began that tells the end-function ! 134: what to do. It also may provide information about the construct ! 135: to alter the behavior of other constructs within the body. ! 136: For example, they may affect the behavior of C `break' and `continue'. ! 137: ! 138: Each construct gets one `struct nesting' object. ! 139: All of these objects are chained through the `all' field. ! 140: `nesting_stack' points to the first object (innermost construct). ! 141: The position of an entry on `nesting_stack' is in its `depth' field. ! 142: ! 143: Each type of construct has its own individual stack. ! 144: For example, loops have `loop_stack'. Each object points to the ! 145: next object of the same type through the `next' field. ! 146: ! 147: Some constructs are visible to `break' exit-statements and others ! 148: are not. Which constructs are visible depends on the language. ! 149: Therefore, the data structure allows each construct to be visible ! 150: or not, according to the args given when the construct is started. ! 151: The construct is visible if the `exit_label' field is non-null. ! 152: In that case, the value should be a CODE_LABEL rtx. */ ! 153: ! 154: struct nesting 1.1 root 155: { 1.1.1.2 ! root 156: struct nesting *all; ! 157: struct nesting *next; ! 158: int depth; ! 159: rtx exit_label; ! 160: union ! 161: { ! 162: /* For conds (if-then and if-then-else statements). */ ! 163: struct ! 164: { ! 165: /* Label on the else-part, if any, else 0. */ ! 166: rtx else_label; ! 167: /* Label at the end of the whole construct. */ ! 168: rtx after_label; ! 169: } cond; ! 170: /* For loops. */ ! 171: struct ! 172: { ! 173: /* Label at the top of the loop; place to loop back to. */ ! 174: rtx start_label; ! 175: /* Label at the end of the whole construct. */ ! 176: rtx end_label; ! 177: /* Label for `continue' statement to jump to; ! 178: this is in front of the stepper of the loop. */ ! 179: rtx continue_label; ! 180: } loop; ! 181: /* For variable binding contours. */ ! 182: struct ! 183: { ! 184: /* Nonzero => value to restore stack to on exit. */ ! 185: rtx stack_level; ! 186: /* The NOTE that starts this contour. ! 187: Used by expand_goto to check whether the destination ! 188: is within each contour or not. */ ! 189: rtx first_insn; ! 190: /* Innermost containing binding contour that has a stack level. */ ! 191: struct nesting *innermost_stack_block; ! 192: /* Chain of labels defined inside this binding contour. ! 193: Only for contours that have stack levels. */ ! 194: struct label_chain *label_chain; ! 195: } block; ! 196: /* For switch (C) or case (Pascal) statements, ! 197: and also for dummies (see `expand_start_case_dummy'). */ ! 198: struct ! 199: { ! 200: /* The insn after which the case dispatch should finally ! 201: be emitted. Zero for a dummy. */ ! 202: rtx start; ! 203: /* A list of the case-values and their labels. ! 204: A chain of TREE_LIST nodes with the value to test for ! 205: (a constant node) in the TREE_PURPOSE and the ! 206: label (a LABEL_DECL) in the TREE_VALUE. */ ! 207: tree case_list; ! 208: /* The expression to be dispatched on. */ ! 209: tree index_expr; ! 210: /* Type that INDEX_EXPR should be converted to. */ ! 211: tree nominal_type; ! 212: } case_stmt; ! 213: } data; ! 214: }; 1.1 root 215: 1.1.1.2 ! root 216: /* Chain of all pending binding contours. */ ! 217: struct nesting *block_stack; 1.1 root 218: 1.1.1.2 ! root 219: /* Chain of all pending binding contours that restore stack levels. */ ! 220: struct nesting *stack_block_stack; 1.1 root 221: 1.1.1.2 ! root 222: /* Chain of all pending conditional statements. */ ! 223: struct nesting *cond_stack; 1.1 root 224: 1.1.1.2 ! root 225: /* Chain of all pending loops. */ ! 226: struct nesting *loop_stack; ! 227: ! 228: /* Chain of all pending case or switch statements. */ ! 229: struct nesting *case_stack; ! 230: ! 231: /* Separate chain including all of the above, ! 232: chained through the `all' field. */ ! 233: struct nesting *nesting_stack; ! 234: ! 235: /* Number of entries on nesting_stack now. */ ! 236: int nesting_depth; ! 237: ! 238: /* Pop one of the sub-stacks, such as `loop_stack' or `cond_stack'; ! 239: and pop off `nesting_stack' down to the same level. */ ! 240: ! 241: #define POPSTACK(STACK) \ ! 242: do { int initial_depth = nesting_stack->depth; \ ! 243: do { struct nesting *this = STACK; \ ! 244: STACK = this->next; \ ! 245: nesting_stack = this->all; \ ! 246: nesting_depth = this->depth; \ ! 247: free (this); } \ ! 248: while (nesting_depth > initial_depth); } while (0) ! 249: 1.1 root 250: /* Return the rtx-label that corresponds to a LABEL_DECL, 251: creating it if necessary. */ 252: 253: static rtx 254: label_rtx (label) 255: tree label; 256: { 1.1.1.2 ! root 257: if (TREE_CODE (label) != LABEL_DECL) ! 258: abort (); ! 259: 1.1 root 260: if (DECL_RTL (label)) 261: return DECL_RTL (label); 262: 263: return DECL_RTL (label) = gen_label_rtx (); 264: } 265: 266: /* Add an unconditional jump to LABEL as the next sequential instruction. */ 267: 268: void 269: emit_jump (label) 270: rtx label; 271: { 272: do_pending_stack_adjust (); 273: emit_jump_insn (gen_jump (label)); 274: emit_barrier (); 275: } 1.1.1.2 ! root 276: ! 277: /* Handle goto statements and the labels that they can go to. */ 1.1 root 278: 1.1.1.2 ! root 279: /* In some cases it is impossible to generate code for a forward goto ! 280: until the label definition is seen. This happens when it may be necessary ! 281: for the goto to reset the stack pointer: we don't yet know how to do that. ! 282: So expand_goto puts an entry on this fixup list. ! 283: Each time a binding contour that resets the stack is exited, ! 284: we check each fixup. ! 285: If the target label has now been defined, we can insert the proper code. */ 1.1 root 286: 1.1.1.2 ! root 287: struct goto_fixup 1.1 root 288: { 1.1.1.2 ! root 289: /* Points to following fixup. */ ! 290: struct goto_fixup *next; ! 291: /* Points to the insn before the jump insn. ! 292: If more code must be inserted, it goes after this insn. */ ! 293: rtx before_jump; ! 294: /* The LABEL_DECL that this jump is jumping to. */ ! 295: tree target; ! 296: /* The outermost stack level that should be restored for this jump. ! 297: Each time a binding contour that resets the stack is exited, ! 298: if the target label is *not* yet defined, this slot is updated. */ ! 299: rtx stack_level; ! 300: }; ! 301: ! 302: static struct goto_fixup *goto_fixup_chain; ! 303: ! 304: /* Within any binding contour that must restore a stack level, ! 305: all labels are recorded with a chain of these structures. */ ! 306: ! 307: struct label_chain ! 308: { ! 309: /* Points to following fixup. */ ! 310: struct label_chain *next; ! 311: tree label; ! 312: }; ! 313: ! 314: /* Specify the location in the RTL code of a label BODY, ! 315: which is a LABEL_DECL tree node. ! 316: ! 317: This is used for the kind of label that the user can jump to with a ! 318: goto statement, and for alternatives of a switch or case statement. ! 319: RTL labels generated for loops and conditionals don't go through here; ! 320: they are generated directly at the RTL level, by other functions below. ! 321: ! 322: Note that this has nothing to do with defining label *names*. ! 323: Languages vary in how they do that and what that even means. */ ! 324: ! 325: void ! 326: expand_label (body) ! 327: tree body; ! 328: { ! 329: struct label_chain *p; ! 330: ! 331: do_pending_stack_adjust (); ! 332: emit_label (label_rtx (body)); ! 333: ! 334: if (stack_block_stack) ! 335: { ! 336: p = (struct label_chain *) oballoc (sizeof (struct label_chain)); ! 337: p->next = stack_block_stack->data.block.label_chain; ! 338: stack_block_stack->data.block.label_chain = p; ! 339: p->label = body; ! 340: } 1.1 root 341: } 342: 1.1.1.2 ! root 343: /* Generate RTL code for a `goto' statement with target label BODY. ! 344: BODY should be a LABEL_DECL tree node that was or will later be ! 345: defined with `expand_label'. */ ! 346: ! 347: void ! 348: expand_goto (body) ! 349: tree body; 1.1 root 350: { 1.1.1.2 ! root 351: struct nesting *block; ! 352: rtx stack_level = 0; ! 353: rtx label = label_rtx (body); ! 354: ! 355: if (GET_CODE (label) != CODE_LABEL) ! 356: abort (); ! 357: ! 358: /* If label has already been defined, we can tell now ! 359: whether and how we must alter the stack level. */ ! 360: ! 361: if (DECL_SOURCE_LINE (body) != 0) ! 362: { ! 363: /* Find the outermost pending block that contains the label. ! 364: (Check containment by comparing insn-uids.) ! 365: Then restore the outermost stack level within that block. */ ! 366: for (block = block_stack; block; block = block->next) ! 367: { ! 368: if (INSN_UID (block->data.block.first_insn) < INSN_UID (label)) ! 369: break; ! 370: if (block->data.block.stack_level != 0) ! 371: stack_level = block->data.block.stack_level; ! 372: } ! 373: ! 374: if (stack_level) ! 375: emit_move_insn (stack_pointer_rtx, stack_level); ! 376: ! 377: if (TREE_PACKED (body)) ! 378: error ("goto \"%s\" invalidly jumps into binding contour", ! 379: IDENTIFIER_POINTER (DECL_NAME (body))); ! 380: } ! 381: /* Label not yet defined: may need to put this goto ! 382: on the fixup list. */ ! 383: else ! 384: { ! 385: /* Does any containing block have a stack level? ! 386: If not, no fixup is needed, and that is the normal case ! 387: (the only case, for standard C). */ ! 388: for (block = block_stack; block; block = block->next) ! 389: if (block->data.block.stack_level != 0) ! 390: break; ! 391: ! 392: if (block) ! 393: { ! 394: /* Ok, a fixup is needed. Add a fixup to the list of such. */ ! 395: struct goto_fixup *fixup ! 396: = (struct goto_fixup *) oballoc (sizeof (struct goto_fixup)); ! 397: /* In case an old stack level is restored, make sure that comes ! 398: after any pending stack adjust. */ ! 399: do_pending_stack_adjust (); ! 400: fixup->before_jump = get_last_insn (); ! 401: fixup->target = body; ! 402: fixup->stack_level = 0; ! 403: fixup->next = goto_fixup_chain; ! 404: goto_fixup_chain = fixup; ! 405: } ! 406: else ! 407: /* No fixup needed. Record that the label is the target ! 408: of at least one goto that has no fixup. */ ! 409: TREE_ADDRESSABLE (body) = 1; ! 410: } ! 411: ! 412: emit_jump (label); 1.1 root 413: } 414: 1.1.1.2 ! root 415: /* When exiting a binding contour, process all pending gotos requiring fixups. ! 416: STACK_LEVEL is the rtx for the stack level to restore on exit from ! 417: this contour. FIRST_INSN is the insn that begain this contour. ! 418: Gotos that jump out of this contour must restore the ! 419: stack level before actually jumping. 1.1 root 420: 1.1.1.2 ! root 421: Also print an error message if any fixup describes a jump into this ! 422: contour from before the beginning of the contour. */ 1.1 root 423: 1.1.1.2 ! root 424: static void ! 425: fixup_gotos (stack_level, first_insn) ! 426: rtx stack_level; ! 427: rtx first_insn; 1.1 root 428: { 1.1.1.2 ! root 429: register struct goto_fixup *f; 1.1 root 430: 1.1.1.2 ! root 431: for (f = goto_fixup_chain; f; f = f->next) ! 432: { ! 433: /* Test for a fixup that is inactive because it is already handled. */ ! 434: if (f->before_jump == 0) ! 435: ; ! 436: /* Has this fixup's target label been defined? ! 437: If so, we can finalize it. */ ! 438: else if (DECL_SOURCE_LINE (f->target) != 0) ! 439: { ! 440: /* If this fixup jumped into this contour from before the beginning ! 441: of this contour, report an error. */ ! 442: if (INSN_UID (first_insn) > INSN_UID (f->before_jump) ! 443: && ! TREE_ADDRESSABLE (f->target)) ! 444: { ! 445: error_with_file_and_line (DECL_SOURCE_FILE (f->target), ! 446: DECL_SOURCE_LINE (f->target), ! 447: "label \"%s\" was used \ ! 448: before containing binding contour", ! 449: IDENTIFIER_POINTER (DECL_NAME (f->target))); ! 450: /* Prevent multiple errors for one label. */ ! 451: TREE_ADDRESSABLE (f->target) = 1; ! 452: } 1.1 root 453: 1.1.1.2 ! root 454: /* Restore stack level for the biggest contour that this ! 455: jump jumps out of. */ ! 456: if (f->stack_level) ! 457: emit_insn_after (gen_move_insn (stack_pointer_rtx, f->stack_level), ! 458: f->before_jump); ! 459: f->before_jump = 0; ! 460: } ! 461: /* Label has still not appeared. If we are exiting a block with ! 462: a stack level to restore, mark this stack level as needing ! 463: restoration when the fixup is later finalized. */ ! 464: else if (stack_level) ! 465: f->stack_level = stack_level; ! 466: } ! 467: } ! 468: ! 469: /* Generate RTL for an asm statement (explicit assembler code). ! 470: BODY is a STRING_CST node containing the assembler code text. */ ! 471: ! 472: void ! 473: expand_asm (body) ! 474: tree body; 1.1 root 475: { 1.1.1.2 ! root 476: emit_insn (gen_rtx (ASM_INPUT, VOIDmode, ! 477: TREE_STRING_POINTER (body))); ! 478: last_expr_type = 0; ! 479: } ! 480: ! 481: /* Generate RTL for an asm statement with arguments. ! 482: STRING is the instruction template. ! 483: OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs. ! 484: Each output or input has an expression in the TREE_VALUE and ! 485: a constraint-string in the TREE_PURPOSE. ! 486: ! 487: Not all kinds of lvalue that may appear in OUTPUTS can be stored directly. ! 488: Some elements of OUTPUTS may be replaced with trees representing temporary ! 489: values. The caller should copy those temporary values to the originally ! 490: specified lvalues. 1.1 root 491: 1.1.1.2 ! root 492: VOL nonzero means the insn is volatile; don't optimize it. */ 1.1 root 493: 1.1.1.2 ! root 494: void ! 495: expand_asm_operands (string, outputs, inputs, vol) ! 496: tree string, outputs, inputs; ! 497: int vol; ! 498: { ! 499: rtvec argvec, constraints; ! 500: rtx body; ! 501: int ninputs = list_length (inputs); ! 502: int noutputs = list_length (outputs); ! 503: int numargs = 0; ! 504: tree tail; ! 505: int i; ! 506: ! 507: if (ninputs + noutputs > MAX_RECOG_OPERANDS) 1.1 root 508: { 1.1.1.2 ! root 509: error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS); ! 510: return; ! 511: } 1.1 root 512: 1.1.1.2 ! root 513: for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) ! 514: { ! 515: tree val = TREE_VALUE (tail); 1.1 root 516: 1.1.1.2 ! root 517: /* If an output operand is not a variable or indirect ref, ! 518: create a SAVE_EXPR which is a pseudo-reg ! 519: to act as an intermediate temporary. ! 520: Make the asm insn write into that, then copy it to ! 521: the real output operand. */ ! 522: ! 523: if (TREE_CODE (val) != VAR_DECL ! 524: && TREE_CODE (val) != PARM_DECL ! 525: && TREE_CODE (val) != INDIRECT_REF) ! 526: TREE_VALUE (tail) = build (SAVE_EXPR, TREE_TYPE (val), val, ! 527: gen_reg_rtx (TYPE_MODE (TREE_TYPE (val)))); ! 528: } 1.1 root 529: 1.1.1.2 ! root 530: /* Make vectors for the expression-rtx and constraint strings. */ 1.1 root 531: 1.1.1.2 ! root 532: argvec = rtvec_alloc (ninputs); ! 533: constraints = rtvec_alloc (ninputs); 1.1 root 534: 1.1.1.2 ! root 535: body = gen_rtx (ASM_OPERANDS, VOIDmode, ! 536: TREE_STRING_POINTER (string), "", 0, argvec, constraints); ! 537: body->volatil = vol; 1.1 root 538: 1.1.1.2 ! root 539: /* Eval the inputs and put them into ARGVEC. ! 540: Put their constraints into ASM_INPUTs and store in CONSTRAINTS. */ 1.1 root 541: 1.1.1.2 ! root 542: i = 0; ! 543: for (tail = inputs; tail; tail = TREE_CHAIN (tail)) ! 544: { ! 545: XVECEXP (body, 3, i) /* argvec */ ! 546: = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0); ! 547: XVECEXP (body, 4, i) /* constraints */ ! 548: = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), ! 549: TREE_STRING_POINTER (TREE_PURPOSE (tail))); ! 550: i++; ! 551: } 1.1 root 552: 1.1.1.2 ! root 553: /* Now, for each output, construct an rtx ! 554: (set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT ! 555: ARGVEC CONSTRAINTS)) ! 556: If there is more than one, put them inside a PARALLEL. */ 1.1 root 557: 1.1.1.2 ! root 558: if (noutputs == 1) ! 559: { ! 560: tree val = TREE_VALUE (outputs); 1.1 root 561: 1.1.1.2 ! root 562: XSTR (body, 1) = TREE_STRING_POINTER (TREE_PURPOSE (outputs)); ! 563: emit_insn (gen_rtx (SET, VOIDmode, ! 564: expand_expr (val, 0, VOIDmode, 0), ! 565: body)); ! 566: } ! 567: else ! 568: { ! 569: body = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (noutputs)); ! 570: ! 571: for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) 1.1 root 572: { 1.1.1.2 ! root 573: tree val = TREE_VALUE (tail); ! 574: ! 575: XVECEXP (body, 0, i) ! 576: = gen_rtx (SET, VOIDmode, ! 577: expand_expr (val, 0, VOIDmode, 0), ! 578: gen_rtx (ASM_OPERANDS, VOIDmode, ! 579: TREE_STRING_POINTER (string), ! 580: TREE_STRING_POINTER (TREE_PURPOSE (tail)), ! 581: i, argvec, constraints)); ! 582: SET_SRC (XVECEXP (body, 0, i))->volatil = vol; 1.1 root 583: } 584: 1.1.1.2 ! root 585: emit_insn (body); ! 586: } ! 587: last_expr_type = 0; ! 588: } 1.1 root 589: 1.1.1.2 ! root 590: /* Nonzero if within a ({...}) grouping, in which case we must ! 591: always compute a value for each expr-stmt in case it is the last one. */ 1.1 root 592: 1.1.1.2 ! root 593: int expr_stmts_for_value; 1.1 root 594: 1.1.1.2 ! root 595: /* Generate RTL to evaluate the expression EXP ! 596: and remember it in case this is the VALUE in a ({... VALUE; }) constr. */ 1.1 root 597: 1.1.1.2 ! root 598: void ! 599: expand_expr_stmt (exp) ! 600: tree exp; ! 601: { ! 602: last_expr_type = TREE_TYPE (exp); ! 603: last_expr_value = expand_expr (exp, expr_stmts_for_value ? 0 : const0_rtx, ! 604: VOIDmode, 0); ! 605: emit_queue (); ! 606: } 1.1 root 607: 1.1.1.2 ! root 608: /* Clear out the memory of the last expression evaluated. */ 1.1 root 609: 1.1.1.2 ! root 610: void ! 611: clear_last_expr () ! 612: { ! 613: last_expr_type = 0; ! 614: } 1.1 root 615: 1.1.1.2 ! root 616: /* Return a tree node that refers to the last expression evaluated. ! 617: The nodes of that expression have been freed by now, so we cannot use them. ! 618: But we don't want to do that anyway; the expression has already been ! 619: evaluated and now we just want to use the value. So generate a SAVE_EXPR ! 620: with the proper type and RTL value. 1.1 root 621: 1.1.1.2 ! root 622: If the last statement was not an expression, ! 623: return something with type `void'. */ 1.1 root 624: 1.1.1.2 ! root 625: tree ! 626: get_last_expr () ! 627: { ! 628: tree t; 1.1 root 629: 1.1.1.2 ! root 630: if (last_expr_type == 0) ! 631: { ! 632: last_expr_type = void_type_node; ! 633: last_expr_value = const0_rtx; ! 634: } ! 635: t = build (RTL_EXPR, last_expr_type, NULL, NULL); ! 636: RTL_EXPR_RTL (t) = last_expr_value; ! 637: RTL_EXPR_SEQUENCE (t) = gen_sequence (); ! 638: return t; ! 639: } 1.1 root 640: 1.1.1.2 ! root 641: void ! 642: expand_start_stmt_expr () ! 643: { ! 644: extern int emit_to_sequence; ! 645: expr_stmts_for_value++; ! 646: emit_to_sequence++; ! 647: } 1.1 root 648: 1.1.1.2 ! root 649: void ! 650: expand_end_stmt_expr () ! 651: { ! 652: extern int emit_to_sequence; ! 653: expr_stmts_for_value--; ! 654: emit_to_sequence--; ! 655: } ! 656: ! 657: /* Generate RTL for the start of an if-then. COND is the expression ! 658: whose truth should be tested. 1.1 root 659: 1.1.1.2 ! root 660: If EXITFLAG is nonzero, this conditional is visible to ! 661: `exit_something'. */ 1.1 root 662: 1.1.1.2 ! root 663: void ! 664: expand_start_cond (cond, exitflag) ! 665: tree cond; ! 666: int exitflag; ! 667: { ! 668: struct nesting *thiscond ! 669: = (struct nesting *) xmalloc (sizeof (struct nesting)); 1.1 root 670: 1.1.1.2 ! root 671: /* Make an entry on cond_stack for the cond we are entering. */ 1.1 root 672: 1.1.1.2 ! root 673: thiscond->next = cond_stack; ! 674: thiscond->all = nesting_stack; ! 675: thiscond->depth = ++nesting_depth; ! 676: thiscond->data.cond.after_label = 0; ! 677: thiscond->data.cond.else_label = gen_label_rtx (); ! 678: thiscond->exit_label = exitflag ? thiscond->data.cond.else_label : 0; ! 679: cond_stack = thiscond; ! 680: nesting_stack = thiscond; 1.1 root 681: 1.1.1.2 ! root 682: do_jump (cond, thiscond->data.cond.else_label, NULL); ! 683: } 1.1 root 684: 1.1.1.2 ! root 685: /* Generate RTL for the end of an if-then with no else-clause. ! 686: Pop the record for it off of cond_stack. */ 1.1 root 687: 1.1.1.2 ! root 688: void ! 689: expand_end_cond () ! 690: { ! 691: struct nesting *thiscond = cond_stack; 1.1 root 692: 1.1.1.2 ! root 693: do_pending_stack_adjust (); ! 694: emit_label (thiscond->data.cond.else_label); 1.1 root 695: 1.1.1.2 ! root 696: POPSTACK (cond_stack); ! 697: last_expr_type = 0; ! 698: } 1.1 root 699: 1.1.1.2 ! root 700: /* Generate RTL between the then-clause and the else-clause ! 701: of an if-then-else. */ 1.1 root 702: 1.1.1.2 ! root 703: void ! 704: expand_start_else () ! 705: { ! 706: cond_stack->data.cond.after_label = gen_label_rtx (); ! 707: if (cond_stack->exit_label != 0) ! 708: cond_stack->exit_label = cond_stack->data.cond.after_label; ! 709: emit_jump (cond_stack->data.cond.after_label); ! 710: if (cond_stack->data.cond.else_label) ! 711: emit_label (cond_stack->data.cond.else_label); ! 712: } 1.1 root 713: 1.1.1.2 ! root 714: /* Generate RTL for the end of an if-then-else. ! 715: Pop the record for it off of cond_stack. */ ! 716: ! 717: void ! 718: expand_end_else () ! 719: { ! 720: struct nesting *thiscond = cond_stack; ! 721: ! 722: do_pending_stack_adjust (); ! 723: /* Note: a syntax error can cause this to be called ! 724: without first calling `expand_start_else'. */ ! 725: if (thiscond->data.cond.after_label) ! 726: emit_label (thiscond->data.cond.after_label); ! 727: ! 728: POPSTACK (cond_stack); ! 729: last_expr_type = 0; ! 730: } ! 731: ! 732: /* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this ! 733: loop should be exited by `exit_something'. This is a loop for which ! 734: `expand_continue' will jump to the top of the loop. ! 735: ! 736: Make an entry on loop_stack to record the labels associated with ! 737: this loop. */ ! 738: ! 739: void ! 740: expand_start_loop (exit_flag) ! 741: int exit_flag; ! 742: { ! 743: register struct nesting *thisloop ! 744: = (struct nesting *) xmalloc (sizeof (struct nesting)); ! 745: ! 746: /* Make an entry on loop_stack for the loop we are entering. */ ! 747: ! 748: thisloop->next = loop_stack; ! 749: thisloop->all = nesting_stack; ! 750: thisloop->depth = ++nesting_depth; ! 751: thisloop->data.loop.start_label = gen_label_rtx (); ! 752: thisloop->data.loop.end_label = gen_label_rtx (); ! 753: thisloop->data.loop.continue_label = thisloop->data.loop.start_label; ! 754: thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0; ! 755: loop_stack = thisloop; ! 756: nesting_stack = thisloop; ! 757: ! 758: do_pending_stack_adjust (); ! 759: emit_queue (); ! 760: emit_note (0, NOTE_INSN_LOOP_BEG); ! 761: emit_label (thisloop->data.loop.start_label); ! 762: } ! 763: ! 764: /* Like expand_start_loop but for a loop where the continuation point ! 765: (for expand_continue_loop) will be specified explicitly. */ 1.1 root 766: 1.1.1.2 ! root 767: void ! 768: expand_start_loop_continue_elsewhere (exit_flag) ! 769: int exit_flag; ! 770: { ! 771: expand_start_loop (exit_flag); ! 772: loop_stack->data.loop.continue_label = gen_label_rtx (); ! 773: } ! 774: ! 775: /* Specify the continuation point for a loop started with ! 776: expand_start_loop_continue_elsewhere. ! 777: Use this at the point in the code to which a continue statement ! 778: should jump. */ ! 779: ! 780: void ! 781: expand_loop_continue_here () ! 782: { ! 783: do_pending_stack_adjust (); ! 784: emit_label (loop_stack->data.loop.continue_label); ! 785: } ! 786: ! 787: /* Finish a loop. Generate a jump back to the top and the loop-exit label. ! 788: Pop the block off of loop_stack. */ ! 789: ! 790: void ! 791: expand_end_loop () ! 792: { ! 793: register struct nesting *thisloop = loop_stack; ! 794: register rtx insn = get_last_insn (); ! 795: register rtx start_label = loop_stack->data.loop.start_label; ! 796: ! 797: do_pending_stack_adjust (); ! 798: ! 799: /* If optimizing, perhaps reorder the loop. If the loop ! 800: starts with a conditional exit, roll that to the end ! 801: where it will optimize together with the jump back. */ ! 802: if (optimize ! 803: && ! 804: ! (GET_CODE (insn) == JUMP_INSN ! 805: && GET_CODE (PATTERN (insn)) == SET ! 806: && SET_DEST (PATTERN (insn)) == pc_rtx ! 807: && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)) ! 808: { ! 809: /* Scan insns from the top of the loop looking for a qualified ! 810: conditional exit. */ ! 811: for (insn = loop_stack->data.loop.start_label; insn; insn= NEXT_INSN (insn)) ! 812: if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET ! 813: && SET_DEST (PATTERN (insn)) == pc_rtx ! 814: && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE ! 815: && ! 816: ((GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == LABEL_REF ! 817: && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0) ! 818: == loop_stack->data.loop.end_label)) ! 819: || ! 820: (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 2)) == LABEL_REF ! 821: && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 2), 0) ! 822: == loop_stack->data.loop.end_label)))) ! 823: break; ! 824: if (insn != 0) ! 825: { ! 826: /* We found one. Move everything from there up ! 827: to the end of the loop, and add a jump into the loop ! 828: to jump to there. */ ! 829: register rtx newstart_label = gen_label_rtx (); ! 830: ! 831: emit_label_after (newstart_label, PREV_INSN (start_label)); ! 832: reorder_insns (start_label, insn, get_last_insn ()); ! 833: emit_jump_insn_after (gen_jump (start_label), PREV_INSN (newstart_label)); ! 834: emit_barrier_after (PREV_INSN (newstart_label)); ! 835: start_label = newstart_label; ! 836: } ! 837: } ! 838: ! 839: emit_jump (start_label); ! 840: emit_note (0, NOTE_INSN_LOOP_END); ! 841: emit_label (loop_stack->data.loop.end_label); ! 842: ! 843: POPSTACK (loop_stack); ! 844: ! 845: last_expr_type = 0; ! 846: } ! 847: ! 848: /* Generate a jump to the current loop's continue-point. ! 849: This is usually the top of the loop, but may be specified ! 850: explicitly elsewhere. If not currently inside a loop, ! 851: return 0 and do nothing; caller will print an error message. */ ! 852: ! 853: int ! 854: expand_continue_loop () ! 855: { ! 856: last_expr_type = 0; ! 857: if (loop_stack == 0) ! 858: return 0; ! 859: emit_jump (loop_stack->data.loop.continue_label); ! 860: return 1; ! 861: } ! 862: ! 863: /* Generate a jump to exit the current loop. If not currently inside a loop, ! 864: return 0 and do nothing; caller will print an error message. */ ! 865: ! 866: int ! 867: expand_exit_loop () ! 868: { ! 869: last_expr_type = 0; ! 870: if (loop_stack == 0) ! 871: return 0; ! 872: emit_jump (loop_stack->data.loop.end_label); ! 873: return 1; ! 874: } ! 875: ! 876: /* Generate a conditional jump to exit the current loop if COND ! 877: evaluates to zero. If not currently inside a loop, ! 878: return 0 and do nothing; caller will print an error message. */ ! 879: ! 880: int ! 881: expand_exit_loop_if_false (cond) ! 882: tree cond; ! 883: { ! 884: last_expr_type = 0; ! 885: if (loop_stack == 0) ! 886: return 0; ! 887: do_jump (cond, loop_stack->data.loop.end_label, NULL); ! 888: return 1; ! 889: } ! 890: ! 891: /* Generate a jump to exit the current loop, conditional, binding contour ! 892: or case statement. Not all such constructs are visible to this function, ! 893: only those started with EXIT_FLAG nonzero. Individual languages use ! 894: the EXIT_FLAG parameter to control which kinds of constructs you can ! 895: exit this way. ! 896: ! 897: If not currently inside anything that can be exited, ! 898: return 0 and do nothing; caller will print an error message. */ ! 899: ! 900: int ! 901: expand_exit_something () ! 902: { ! 903: struct nesting *n; ! 904: last_expr_type = 0; ! 905: for (n = nesting_stack; n; n = n->all) ! 906: { ! 907: if (n->exit_label != 0) ! 908: { ! 909: emit_jump (n->exit_label); ! 910: return 1; ! 911: } 1.1 root 912: } 1.1.1.2 ! root 913: return 0; ! 914: } ! 915: ! 916: /* Generate RTL to return from the current function, with no value. ! 917: (That is, we do not do anything about returning any value.) */ ! 918: ! 919: void ! 920: expand_null_return () ! 921: { ! 922: clear_pending_stack_adjust (); ! 923: #ifdef FUNCTION_EPILOGUE ! 924: emit_jump (return_label); ! 925: #else ! 926: emit_jump_insn (gen_return ()); ! 927: emit_barrier (); ! 928: #endif ! 929: last_expr_type = 0; ! 930: } 1.1 root 931: 1.1.1.2 ! root 932: /* Generate RTL to evaluate the expression RETVAL and return it ! 933: from the current function. */ 1.1 root 934: 1.1.1.2 ! root 935: void ! 936: expand_return (retval) ! 937: tree retval; ! 938: { ! 939: register rtx val = 0; ! 940: register rtx op0; ! 941: int really_for_value = ! 942: (TREE_CODE (retval) == MODIFY_EXPR ! 943: && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL); ! 944: ! 945: /* For tail-recursive call to current function, ! 946: just jump back to the beginning. ! 947: It's unsafe if any auto variable in this function ! 948: has its address taken; for simplicity, ! 949: require stack frame to be empty. */ ! 950: if (optimize && really_for_value ! 951: && frame_offset == 0 ! 952: && TREE_CODE (TREE_OPERAND (retval, 1)) == CALL_EXPR ! 953: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (retval, 1), 0)) == ADDR_EXPR ! 954: && TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (retval, 1), 0), 0) == this_function ! 955: /* Finish checking validity, and if valid emit code ! 956: to set the argument variables for the new call. */ ! 957: && tail_recursion_args (TREE_OPERAND (TREE_OPERAND (retval, 1), 1), ! 958: DECL_ARGUMENTS (this_function))) ! 959: { ! 960: ; ! 961: if (tail_recursion_label == 0) ! 962: { ! 963: tail_recursion_label = gen_label_rtx (); ! 964: emit_label_after (tail_recursion_label, ! 965: tail_recursion_reentry); ! 966: } ! 967: emit_jump (tail_recursion_label); ! 968: emit_barrier (); ! 969: return; ! 970: } ! 971: #ifndef FUNCTION_EPILOGUE ! 972: /* If this is return x == y; then generate ! 973: if (x == y) return 1; else return 0; ! 974: if we can do it with explicit return insns. */ ! 975: if (really_for_value) ! 976: switch (TREE_CODE (TREE_OPERAND (retval, 1))) ! 977: { ! 978: case EQ_EXPR: ! 979: case NE_EXPR: ! 980: case GT_EXPR: ! 981: case GE_EXPR: ! 982: case LT_EXPR: ! 983: case LE_EXPR: ! 984: case TRUTH_ANDIF_EXPR: ! 985: case TRUTH_ORIF_EXPR: ! 986: case TRUTH_NOT_EXPR: ! 987: op0 = gen_label_rtx (); ! 988: val = DECL_RTL (DECL_RESULT (this_function)); ! 989: jumpifnot (TREE_OPERAND (retval, 1), op0); ! 990: emit_move_insn (val, const1_rtx); ! 991: emit_insn (gen_rtx (USE, VOIDmode, val)); ! 992: expand_null_return (); ! 993: emit_label (op0); ! 994: emit_move_insn (val, const0_rtx); ! 995: emit_insn (gen_rtx (USE, VOIDmode, val)); ! 996: expand_null_return (); ! 997: return; ! 998: } ! 999: #endif ! 1000: val = expand_expr (retval, 0, VOIDmode, 0); 1.1 root 1001: emit_queue (); 1.1.1.2 ! root 1002: ! 1003: if (really_for_value && GET_CODE (val) == REG) ! 1004: emit_insn (gen_rtx (USE, VOIDmode, val)); ! 1005: ! 1006: expand_null_return (); ! 1007: } ! 1008: ! 1009: /* Return 1 if the end of the generated RTX is not a barrier. ! 1010: This means code already compiled can drop through. */ ! 1011: ! 1012: int ! 1013: drop_through_at_end_p () ! 1014: { ! 1015: rtx insn = get_last_insn (); ! 1016: while (insn && GET_CODE (insn) == NOTE) ! 1017: insn = PREV_INSN (insn); ! 1018: return insn && GET_CODE (insn) != BARRIER; 1.1 root 1019: } 1020: 1021: /* Emit code to alter this function's formal parms for a tail-recursive call. 1022: ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs). 1023: FORMALS is the chain of decls of formals. 1024: Return 1 if this can be done; 1025: otherwise return 0 and do not emit any code. */ 1026: 1027: static int 1028: tail_recursion_args (actuals, formals) 1029: tree actuals, formals; 1030: { 1031: register tree a = actuals, f = formals; 1032: register int i; 1033: register rtx *argvec; 1034: 1035: /* Check that number and types of actuals are compatible 1036: with the formals. This is not always true in valid C code. 1037: Also check that no formal needs to be addressable 1038: and that all formals are scalars. */ 1039: 1040: /* Also count the args. */ 1041: 1042: for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++) 1043: { 1044: if (TREE_TYPE (TREE_VALUE (a)) != TREE_TYPE (f)) 1045: return 0; 1046: if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode) 1047: return 0; 1048: } 1049: if (a != 0 || f != 0) 1050: return 0; 1051: 1052: /* Compute all the actuals. */ 1053: 1054: argvec = (rtx *) alloca (i * sizeof (rtx)); 1055: 1056: for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++) 1057: argvec[i] = expand_expr (TREE_VALUE (a), 0, VOIDmode, 0); 1058: 1059: /* Find which actual values refer to current values of previous formals. 1060: Copy each of them now, before any formal is changed. */ 1061: 1062: for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++) 1063: { 1064: int copy = 0; 1065: register int j; 1066: for (f = formals, j = 0; j < i; f = TREE_CHAIN (f), j++) 1067: if (reg_mentioned_p (DECL_RTL (f), argvec[i])) 1068: { copy = 1; break; } 1069: if (copy) 1070: argvec[i] = copy_to_reg (argvec[i]); 1071: } 1072: 1073: /* Store the values of the actuals into the formals. */ 1074: 1.1.1.2 ! root 1075: for (f = formals, a = actuals, i = 0; f; ! 1076: f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++) 1.1 root 1077: { 1078: if (DECL_MODE (f) == GET_MODE (argvec[i])) 1079: emit_move_insn (DECL_RTL (f), argvec[i]); 1080: else 1.1.1.2 ! root 1081: convert_move (DECL_RTL (f), argvec[i], ! 1082: TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a)))); 1.1 root 1083: } 1084: 1085: return 1; 1086: } 1087: 1.1.1.2 ! root 1088: /* Generate the RTL code for entering a binding contour. ! 1089: The variables are declared one by one, by calls to `expand_decl'. 1.1 root 1090: 1.1.1.2 ! root 1091: EXIT_FLAG is nonzero if this construct should be visible to ! 1092: `exit_something'. */ ! 1093: ! 1094: void ! 1095: expand_start_bindings (exit_flag) ! 1096: int exit_flag; 1.1 root 1097: { 1.1.1.2 ! root 1098: struct nesting *thisblock ! 1099: = (struct nesting *) xmalloc (sizeof (struct nesting)); ! 1100: ! 1101: rtx note = emit_note (0, NOTE_INSN_BLOCK_BEG); ! 1102: ! 1103: /* Make an entry on block_stack for the block we are entering. */ ! 1104: ! 1105: thisblock->next = block_stack; ! 1106: thisblock->all = nesting_stack; ! 1107: thisblock->depth = ++nesting_depth; ! 1108: thisblock->data.block.stack_level = 0; ! 1109: thisblock->data.block.label_chain = 0; ! 1110: thisblock->data.block.innermost_stack_block = stack_block_stack; ! 1111: thisblock->data.block.first_insn = note; ! 1112: thisblock->exit_label = exit_flag ? gen_label_rtx () : 0; ! 1113: block_stack = thisblock; ! 1114: nesting_stack = thisblock; ! 1115: } ! 1116: ! 1117: /* Generate RTL code to terminate a binding contour. ! 1118: VARS is the chain of VAR_DECL nodes ! 1119: for the variables bound in this contour. ! 1120: MARK_ENDs is nonzero if we should put a note at the beginning ! 1121: and end of this binding contour. */ ! 1122: ! 1123: void ! 1124: expand_end_bindings (vars, mark_ends) ! 1125: tree vars; ! 1126: int mark_ends; ! 1127: { ! 1128: register struct nesting *thisblock = block_stack; ! 1129: register tree decl; ! 1130: ! 1131: /* Mark the beginning and end of the scope if requested. */ ! 1132: ! 1133: if (mark_ends) ! 1134: emit_note (0, NOTE_INSN_BLOCK_END); ! 1135: else ! 1136: /* Get rid of the beginning-mark if we don't make an end-mark. */ ! 1137: NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED; ! 1138: ! 1139: if (thisblock->exit_label) ! 1140: { ! 1141: do_pending_stack_adjust (); ! 1142: emit_label (thisblock->exit_label); ! 1143: } ! 1144: ! 1145: /* Restore stack level in effect before the block ! 1146: (only if variable-size objects allocated). */ ! 1147: ! 1148: if (thisblock->data.block.stack_level != 0) ! 1149: { ! 1150: struct label_chain *chain; ! 1151: ! 1152: do_pending_stack_adjust (); ! 1153: emit_move_insn (stack_pointer_rtx, ! 1154: thisblock->data.block.stack_level); ! 1155: ! 1156: /* Any labels in this block are no longer valid to go to. ! 1157: Mark them to cause an error message. */ ! 1158: for (chain = thisblock->data.block.label_chain; chain; chain = chain->next) ! 1159: { ! 1160: TREE_PACKED (chain->label) = 1; ! 1161: /* If any goto without a fixup came to this label, ! 1162: that must be an error, because gotos without fixups ! 1163: come from outside all saved stack-levels. */ ! 1164: if (TREE_ADDRESSABLE (chain->label)) ! 1165: error_with_file_and_line (DECL_SOURCE_FILE (chain->label), ! 1166: DECL_SOURCE_LINE (chain->label), ! 1167: "label \"%s\" was used \ ! 1168: before containing binding contour", ! 1169: IDENTIFIER_POINTER (DECL_NAME (chain->label))); ! 1170: } ! 1171: ! 1172: /* Any gotos out of this block must also restore the stack level. ! 1173: Also report any gotos with fixups that came to labels in this level. */ ! 1174: fixup_gotos (thisblock->data.block.stack_level, ! 1175: thisblock->data.block.first_insn); ! 1176: } ! 1177: ! 1178: /* If doing stupid register allocation, make sure lives of all ! 1179: register variables declared here extend thru end of scope. */ ! 1180: ! 1181: if (obey_regdecls) ! 1182: for (decl = vars; decl; decl = TREE_CHAIN (decl)) ! 1183: { ! 1184: if (TREE_CODE (decl) == VAR_DECL ! 1185: && DECL_RTL (decl) != 0 ! 1186: && GET_CODE (DECL_RTL (decl)) == REG) ! 1187: emit_insn (gen_rtx (USE, VOIDmode, DECL_RTL (decl))); ! 1188: } ! 1189: ! 1190: /* Restore block_stack level for containing block. */ ! 1191: ! 1192: stack_block_stack = thisblock->data.block.innermost_stack_block; ! 1193: POPSTACK (block_stack); ! 1194: } ! 1195: ! 1196: /* Generate RTL for the automatic variable declaration DECL. ! 1197: (Other kinds of declarations are simply ignored.) */ ! 1198: ! 1199: void ! 1200: expand_decl (decl) ! 1201: register tree decl; ! 1202: { ! 1203: struct nesting *thisblock = block_stack; ! 1204: tree type = TREE_TYPE (decl); ! 1205: ! 1206: /* External function declarations are supposed to have been ! 1207: handled in assemble_variable. Verify this. */ ! 1208: if (TREE_CODE (decl) == FUNCTION_DECL) ! 1209: { ! 1210: if (DECL_RTL (decl) == 0) ! 1211: abort (); ! 1212: return; ! 1213: } ! 1214: ! 1215: /* Aside from that, only automatic variables need any expansion done. ! 1216: Static and external variables were handled by `assemble_variable' ! 1217: (called from finish_decl). TYPE_DECL and CONST_DECL require nothing; ! 1218: PARM_DECLs are handled in `assign_parms'. */ ! 1219: ! 1220: if (TREE_CODE (decl) != VAR_DECL) ! 1221: return; ! 1222: if (TREE_STATIC (decl) || TREE_EXTERNAL (decl)) ! 1223: return; ! 1224: ! 1225: /* Create the RTL representation for the variable. */ ! 1226: ! 1227: if (type == error_mark_node) ! 1228: DECL_RTL (decl) = gen_rtx (MEM, BLKmode, const0_rtx); ! 1229: else if (DECL_MODE (decl) != BLKmode ! 1230: /* If -ffloat-store, don't put explicit float vars ! 1231: into regs. */ ! 1232: && !(flag_float_store ! 1233: && TREE_CODE (type) == REAL_TYPE) ! 1234: && ! TREE_VOLATILE (decl) ! 1235: && ! TREE_ADDRESSABLE (decl) ! 1236: && (TREE_REGDECL (decl) || ! obey_regdecls)) ! 1237: { ! 1238: /* Automatic variable that can go in a register. */ ! 1239: DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); ! 1240: if (TREE_CODE (type) == POINTER_TYPE) ! 1241: mark_reg_pointer (DECL_RTL (decl)); ! 1242: DECL_RTL (decl)->volatil = 1; ! 1243: } ! 1244: else if (DECL_SIZE (decl) == 0) ! 1245: /* Variable with incomplete type. */ ! 1246: /* Error message was already done; now avoid a crash. */ ! 1247: DECL_RTL (decl) = assign_stack_local (DECL_MODE (decl), 0); ! 1248: else if (TREE_LITERAL (DECL_SIZE (decl))) ! 1249: { ! 1250: /* Variable of fixed size that goes on the stack. */ ! 1251: DECL_RTL (decl) ! 1252: = assign_stack_local (DECL_MODE (decl), ! 1253: (TREE_INT_CST_LOW (DECL_SIZE (decl)) ! 1254: * DECL_SIZE_UNIT (decl) ! 1255: + BITS_PER_UNIT - 1) ! 1256: / BITS_PER_UNIT); ! 1257: /* If this is a memory ref that contains aggregate components, ! 1258: mark it as such for cse and loop optimize. */ ! 1259: DECL_RTL (decl)->in_struct ! 1260: = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE ! 1261: || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE ! 1262: || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE); ! 1263: } ! 1264: else ! 1265: /* Dynamic-size object: must push space on the stack. */ ! 1266: { ! 1267: rtx address, size; ! 1268: ! 1269: frame_pointer_needed = 1; ! 1270: ! 1271: /* Record the stack pointer on entry to block, if have ! 1272: not already done so. */ ! 1273: if (thisblock->data.block.stack_level == 0) ! 1274: { ! 1275: do_pending_stack_adjust (); ! 1276: thisblock->data.block.stack_level ! 1277: = copy_to_reg (stack_pointer_rtx); ! 1278: stack_block_stack = thisblock; ! 1279: } ! 1280: ! 1281: /* Compute the variable's size, in bytes. */ ! 1282: size = expand_expr (convert_units (DECL_SIZE (decl), ! 1283: DECL_SIZE_UNIT (decl), ! 1284: BITS_PER_UNIT), ! 1285: 0, VOIDmode, 0); ! 1286: ! 1287: /* Round it up to this machine's required stack boundary. */ ! 1288: #ifdef STACK_BOUNDARY ! 1289: /* Avoid extra code if we can prove it's a multiple already. */ ! 1290: if (DECL_SIZE_UNIT (decl) % STACK_BOUNDARY) ! 1291: size = round_push (size); ! 1292: #endif ! 1293: ! 1294: /* Make space on the stack, and get an rtx for the address of it. */ ! 1295: #ifdef STACK_GROWS_DOWNWARD ! 1296: anti_adjust_stack (size); ! 1297: #endif ! 1298: address = copy_to_reg (stack_pointer_rtx); ! 1299: #ifndef STACK_GROWS_DOWNWARD ! 1300: anti_adjust_stack (size); ! 1301: #endif ! 1302: ! 1303: /* Reference the variable indirect through that rtx. */ ! 1304: DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address); ! 1305: } ! 1306: ! 1307: if (TREE_VOLATILE (decl)) ! 1308: DECL_RTL (decl)->volatil = 1; ! 1309: if (TREE_READONLY (decl)) ! 1310: DECL_RTL (decl)->unchanging = 1; ! 1311: ! 1312: /* If doing stupid register allocation, make sure life of any ! 1313: register variable starts here, at the start of its scope. */ ! 1314: ! 1315: if (obey_regdecls ! 1316: && TREE_CODE (decl) == VAR_DECL ! 1317: && DECL_RTL (decl) != 0 ! 1318: && GET_CODE (DECL_RTL (decl)) == REG) ! 1319: emit_insn (gen_rtx (USE, VOIDmode, DECL_RTL (decl))); ! 1320: ! 1321: /* Compute and store the initial value now. */ ! 1322: ! 1323: if (DECL_INITIAL (decl)) ! 1324: { ! 1325: emit_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); ! 1326: expand_assignment (decl, DECL_INITIAL (decl), 0, 0); ! 1327: emit_queue (); ! 1328: } ! 1329: } ! 1330: ! 1331: /* Enter a case (Pascal) or switch (C) statement. ! 1332: Push a block onto case_stack and nesting_stack ! 1333: to accumulate the case-labels that are seen ! 1334: and to record the labels generated for the statement. ! 1335: ! 1336: EXIT_FLAG is nonzero if `exit_something' should exit this case stmt. ! 1337: Otherwise, this construct is transparent for `exit_something'. ! 1338: ! 1339: EXPR is the index-expression to be dispatched on. ! 1340: TYPE is its nominal type. We could simply convert EXPR to this type, ! 1341: but instead we take short cuts. */ ! 1342: ! 1343: void ! 1344: expand_start_case (exit_flag, expr, type) ! 1345: int exit_flag; ! 1346: tree expr; ! 1347: tree type; ! 1348: { ! 1349: register struct nesting *thiscase ! 1350: = (struct nesting *) xmalloc (sizeof (struct nesting)); ! 1351: ! 1352: /* Make an entry on case_stack for the case we are entering. */ ! 1353: ! 1354: thiscase->next = case_stack; ! 1355: thiscase->all = nesting_stack; ! 1356: thiscase->depth = ++nesting_depth; ! 1357: thiscase->exit_label = exit_flag ? gen_label_rtx () : 0; ! 1358: thiscase->data.case_stmt.case_list = 0; ! 1359: thiscase->data.case_stmt.index_expr = expr; ! 1360: thiscase->data.case_stmt.nominal_type = type; ! 1361: case_stack = thiscase; ! 1362: nesting_stack = thiscase; ! 1363: ! 1364: do_pending_stack_adjust (); ! 1365: ! 1366: thiscase->data.case_stmt.start = get_last_insn (); ! 1367: } ! 1368: ! 1369: /* Start a "dummy case statement" within which case labels are invalid ! 1370: and are not connected to any larger real case statement. ! 1371: This can be used if you don't want to let a case statement jump ! 1372: into the middle of certain kinds of constructs. */ ! 1373: ! 1374: void ! 1375: expand_start_case_dummy () ! 1376: { ! 1377: register struct nesting *thiscase ! 1378: = (struct nesting *) xmalloc (sizeof (struct nesting)); ! 1379: ! 1380: /* Make an entry on case_stack for the dummy. */ ! 1381: ! 1382: thiscase->next = case_stack; ! 1383: thiscase->all = nesting_stack; ! 1384: thiscase->depth = ++nesting_depth; ! 1385: thiscase->exit_label = 0; ! 1386: thiscase->data.case_stmt.case_list = 0; ! 1387: thiscase->data.case_stmt.start = 0; ! 1388: thiscase->data.case_stmt.nominal_type = 0; ! 1389: case_stack = thiscase; ! 1390: nesting_stack = thiscase; ! 1391: } ! 1392: ! 1393: /* End a dummy case statement. */ ! 1394: ! 1395: void ! 1396: expand_end_case_dummy () ! 1397: { ! 1398: POPSTACK (case_stack); ! 1399: } ! 1400: ! 1401: /* Accumulate one case or default label inside a case or switch statement. ! 1402: VALUE is the value of the case (a null pointer, for a default label). ! 1403: ! 1404: If not currently inside a case or switch statement, return 1 and do ! 1405: nothing. The caller will print a language-specific error message. ! 1406: If VALUE is a duplicate, return 2 and do nothing. ! 1407: If VALUE is out of range, return 3 and do nothing. ! 1408: Return 0 on success. */ ! 1409: ! 1410: int ! 1411: pushcase (value, label) ! 1412: register tree value; ! 1413: register tree label; ! 1414: { ! 1415: register tree l; ! 1416: tree index_type; ! 1417: tree nominal_type; ! 1418: ! 1419: /* Fail if not inside a real case statement. */ ! 1420: if (! (case_stack && case_stack->data.case_stmt.start)) ! 1421: return 1; ! 1422: ! 1423: index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr); ! 1424: nominal_type = case_stack->data.case_stmt.nominal_type; ! 1425: ! 1426: /* If the index is erroneous, avoid more problems: pretend to succeed. */ ! 1427: if (index_type == error_mark_node) ! 1428: return 0; ! 1429: ! 1430: /* Convert VALUE to the type in which the comparisons are nominally done. */ ! 1431: if (value != 0) ! 1432: value = convert (nominal_type, value); ! 1433: ! 1434: /* Fail if this is a duplicate entry. */ ! 1435: for (l = case_stack->data.case_stmt.case_list; l; l = TREE_CHAIN (l)) ! 1436: { ! 1437: if (value == 0 && TREE_PURPOSE (l) == 0) ! 1438: return 2; ! 1439: if (value != 0 && TREE_PURPOSE (l) ! 1440: && (TREE_INT_CST_LOW (value) ! 1441: == TREE_INT_CST_LOW (TREE_PURPOSE (l))) ! 1442: && (TREE_INT_CST_HIGH (value) ! 1443: == TREE_INT_CST_HIGH (TREE_PURPOSE (l)))) ! 1444: return 2; ! 1445: } ! 1446: ! 1447: /* Fail if this value is out of range for the actual type of the index ! 1448: (which may be narrower than NOMINAL_TYPE). */ ! 1449: if (value != 0 && ! int_fits_type_p (value, index_type)) ! 1450: return 3; ! 1451: ! 1452: /* Add this label to the list, and succeed. ! 1453: Copy VALUE so it is temporary rather than momentary. */ ! 1454: case_stack->data.case_stmt.case_list ! 1455: = tree_cons (value ? copy_node (value) : 0, label, ! 1456: case_stack->data.case_stmt.case_list); ! 1457: expand_label (label); ! 1458: return 0; ! 1459: } ! 1460: ! 1461: /* Terminate a case (Pascal) or switch (C) statement ! 1462: in which CASE_INDEX is the expression to be tested. ! 1463: Generate the code to test it and jump to the right place. */ ! 1464: ! 1465: void ! 1466: expand_end_case () ! 1467: { ! 1468: tree minval, maxval, range; ! 1469: rtx default_label = 0; ! 1470: register tree elt; ! 1471: register tree c; ! 1472: int count; ! 1473: rtx index; ! 1474: rtx table_label = gen_label_rtx (); ! 1475: int ncases; ! 1476: rtx *labelvec; ! 1477: register int i; ! 1478: rtx before_case; ! 1479: register struct nesting *thiscase = case_stack; ! 1480: tree index_expr = thiscase->data.case_stmt.index_expr; ! 1481: ! 1482: do_pending_stack_adjust (); ! 1483: ! 1484: /* This happens for various reasons including invalid data type. */ ! 1485: if (index_expr != error_mark_node) ! 1486: { ! 1487: /* If we don't have a default-label, create one here, ! 1488: after the body of the switch. */ ! 1489: for (c = thiscase->data.case_stmt.case_list; c; c = TREE_CHAIN (c)) ! 1490: if (TREE_PURPOSE (c) == 0) ! 1491: break; ! 1492: if (c == 0) ! 1493: pushcase (0, build_decl (LABEL_DECL, NULL_TREE, NULL_TREE)); ! 1494: ! 1495: before_case = get_last_insn (); ! 1496: ! 1497: /* Get upper and lower bounds of case values. ! 1498: Also convert all the case values to the index expr's data type. */ ! 1499: count = 0; ! 1500: for (c = thiscase->data.case_stmt.case_list; c; c = TREE_CHAIN (c)) ! 1501: if (elt = TREE_PURPOSE (c)) ! 1502: { ! 1503: /* Note that in Pascal it will be possible ! 1504: to have a RANGE_EXPR here as long as both ! 1505: ends of the range are constant. ! 1506: It will be necessary to extend this function ! 1507: to handle them. */ ! 1508: if (TREE_CODE (elt) != INTEGER_CST) ! 1509: abort (); ! 1510: ! 1511: TREE_PURPOSE (c) = elt = convert (TREE_TYPE (index_expr), elt); ! 1512: ! 1513: /* Count the elements and track the largest and ! 1514: smallest of them ! 1515: (treating them as signed even if they are not). */ ! 1516: if (count++ == 0) ! 1517: { ! 1518: minval = maxval = elt; ! 1519: } ! 1520: else ! 1521: { ! 1522: if (INT_CST_LT (elt, minval)) ! 1523: minval = elt; ! 1524: if (INT_CST_LT (maxval, elt)) ! 1525: maxval = elt; ! 1526: } ! 1527: } ! 1528: else ! 1529: default_label = label_rtx (TREE_VALUE (c)); ! 1530: ! 1531: if (default_label == 0) ! 1532: abort (); ! 1533: ! 1534: /* Compute span of values. */ ! 1535: if (count != 0) ! 1536: range = combine (MINUS_EXPR, maxval, minval); ! 1537: ! 1538: if (count == 0 || TREE_CODE (TREE_TYPE (index_expr)) == ERROR_MARK) ! 1539: { ! 1540: expand_expr (index_expr, const0_rtx, VOIDmode, 0); ! 1541: emit_queue (); ! 1542: emit_jump (default_label); ! 1543: } ! 1544: /* If range of values is much bigger than number of values, ! 1545: make a sequence of conditional branches instead of a dispatch. ! 1546: If the switch-index is a constant, do it this way ! 1547: because we can optimize it. */ ! 1548: else if (TREE_INT_CST_HIGH (range) != 0 1.1 root 1549: #ifdef HAVE_casesi 1.1.1.2 ! root 1550: || count < 4 1.1 root 1551: #else 1.1.1.2 ! root 1552: /* If machine does not have a case insn that compares the ! 1553: bounds, this means extra overhead for dispatch tables ! 1554: which raises the threshold for using them. */ ! 1555: || count < 5 1.1 root 1556: #endif 1.1.1.2 ! root 1557: || (unsigned) (TREE_INT_CST_LOW (range)) > 10 * count ! 1558: || TREE_CODE (index_expr) == INTEGER_CST) ! 1559: { ! 1560: index = expand_expr (index_expr, 0, VOIDmode, 0); ! 1561: emit_queue (); 1.1 root 1562: 1.1.1.2 ! root 1563: index = protect_from_queue (index, 0); ! 1564: if (GET_CODE (index) == MEM) ! 1565: index = copy_to_reg (index); ! 1566: do_pending_stack_adjust (); 1.1 root 1567: 1.1.1.2 ! root 1568: for (c = thiscase->data.case_stmt.case_list; c; c = TREE_CHAIN (c)) ! 1569: { ! 1570: elt = TREE_PURPOSE (c); ! 1571: if (elt && TREE_VALUE (c)) ! 1572: do_jump_if_equal (expand_expr (elt, 0, VOIDmode, 0), index, ! 1573: label_rtx (TREE_VALUE (c))); ! 1574: } ! 1575: ! 1576: emit_jump (default_label); ! 1577: } ! 1578: else ! 1579: { 1.1 root 1580: #ifdef HAVE_casesi 1.1.1.2 ! root 1581: if (TYPE_MODE (TREE_TYPE (index_expr)) == DImode) ! 1582: { ! 1583: index_expr = convert (integer_type_node, ! 1584: build (MINUS_EXPR, TREE_TYPE (index_expr), ! 1585: index_expr, minval)); ! 1586: minval = integer_zero_node; ! 1587: } ! 1588: else if (TYPE_MODE (TREE_TYPE (index_expr)) != SImode) ! 1589: index_expr = convert (integer_type_node, index_expr); ! 1590: index = expand_expr (index_expr, 0, VOIDmode, 0); ! 1591: emit_queue (); ! 1592: index = protect_from_queue (index, 0); ! 1593: do_pending_stack_adjust (); ! 1594: ! 1595: emit_jump_insn (gen_casesi (index, expand_expr (minval, 0, VOIDmode, 0), ! 1596: expand_expr (range, 0, VOIDmode, 0), ! 1597: table_label, default_label)); 1.1 root 1598: #else 1599: #ifdef HAVE_tablejump 1.1.1.2 ! root 1600: index_expr = convert (integer_type_node, ! 1601: build (MINUS_EXPR, TREE_TYPE (index_expr), ! 1602: index_expr, minval)); ! 1603: index = expand_expr (index_expr, 0, VOIDmode, 0); ! 1604: emit_queue (); ! 1605: index = protect_from_queue (index, 0); ! 1606: do_pending_stack_adjust (); ! 1607: ! 1608: do_tablejump (index, ! 1609: gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (range)), ! 1610: table_label, default_label); 1.1 root 1611: #else 1.1.1.2 ! root 1612: lossage; ! 1613: #endif /* not HAVE_tablejump */ ! 1614: #endif /* not HAVE_casesi */ ! 1615: ! 1616: /* Get table of labels to jump to, in order of case index. */ ! 1617: ! 1618: ncases = TREE_INT_CST_LOW (range) + 1; ! 1619: labelvec = (rtx *) alloca (ncases * sizeof (rtx)); ! 1620: bzero (labelvec, ncases * sizeof (rtx)); 1.1 root 1621: 1.1.1.2 ! root 1622: for (c = thiscase->data.case_stmt.case_list; c; c = TREE_CHAIN (c)) ! 1623: if (TREE_VALUE (c) && (elt = TREE_PURPOSE (c))) ! 1624: { ! 1625: register int i ! 1626: = TREE_INT_CST_LOW (elt) - TREE_INT_CST_LOW (minval); ! 1627: labelvec[i] ! 1628: = gen_rtx (LABEL_REF, Pmode, label_rtx (TREE_VALUE (c))); ! 1629: } ! 1630: ! 1631: /* Fill in the gaps with the default. */ ! 1632: for (i = 0; i < ncases; i++) ! 1633: if (labelvec[i] == 0) ! 1634: labelvec[i] = gen_rtx (LABEL_REF, Pmode, default_label); ! 1635: ! 1636: /* Output the table */ ! 1637: emit_label (table_label); 1.1 root 1638: 1639: #ifdef CASE_VECTOR_PC_RELATIVE 1.1.1.2 ! root 1640: emit_jump_insn (gen_rtx (ADDR_DIFF_VEC, CASE_VECTOR_MODE, ! 1641: gen_rtx (LABEL_REF, Pmode, table_label), ! 1642: gen_rtvec_v (ncases, labelvec))); 1.1 root 1643: #else 1.1.1.2 ! root 1644: emit_jump_insn (gen_rtx (ADDR_VEC, CASE_VECTOR_MODE, ! 1645: gen_rtvec_v (ncases, labelvec))); 1.1 root 1646: #endif 1.1.1.2 ! root 1647: /* If the case insn drops through the table, ! 1648: after the table we must jump to the default-label. ! 1649: Otherwise record no drop-through after the table. */ ! 1650: #ifdef CASE_DROPS_THROUGH ! 1651: emit_jump (default_label); ! 1652: #else ! 1653: emit_barrier (); ! 1654: #endif ! 1655: } ! 1656: ! 1657: reorder_insns (NEXT_INSN (before_case), get_last_insn (), ! 1658: thiscase->data.case_stmt.start); ! 1659: } ! 1660: if (thiscase->exit_label) ! 1661: emit_label (thiscase->exit_label); ! 1662: ! 1663: POPSTACK (case_stack); ! 1664: } ! 1665: ! 1666: /* Generate code to jump to LABEL if OP1 and OP2 are equal. */ ! 1667: /* ??? This may need an UNSIGNEDP argument to work properly ??? */ ! 1668: ! 1669: void ! 1670: do_jump_if_equal (op1, op2, label) ! 1671: rtx op1, op2, label; ! 1672: { ! 1673: if (GET_CODE (op1) == CONST_INT ! 1674: && GET_CODE (op2) == CONST_INT) ! 1675: { ! 1676: if (INTVAL (op1) == INTVAL (op2)) ! 1677: emit_jump (label); ! 1678: } ! 1679: else ! 1680: { ! 1681: emit_cmp_insn (op1, op2, 0, 0); ! 1682: emit_jump_insn (gen_beq (label)); ! 1683: } 1.1 root 1684: } 1685: 1.1.1.2 ! root 1686: /* Allocate fixed slots in the stack frame of the current function. */ 1.1 root 1687: 1688: /* Return size needed for stack frame based on slots so far allocated. */ 1689: 1690: int 1691: get_frame_size () 1692: { 1.1.1.2 ! root 1693: #ifdef FRAME_GROWS_DOWNWARD ! 1694: return -frame_offset; ! 1695: #else 1.1 root 1696: return frame_offset; 1.1.1.2 ! root 1697: #endif 1.1 root 1698: } 1699: 1700: /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it 1701: with machine mode MODE. */ 1702: 1703: rtx 1704: assign_stack_local (mode, size) 1705: enum machine_mode mode; 1706: int size; 1707: { 1.1.1.2 ! root 1708: register rtx x, addr; 1.1 root 1709: 1.1.1.2 ! root 1710: frame_pointer_needed = 1; 1.1 root 1711: 1712: /* Make each stack slot a multiple of the main allocation unit. */ 1713: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) 1714: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)) 1715: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); 1716: 1717: #ifdef FRAME_GROWS_DOWNWARD 1718: frame_offset -= size; 1719: #endif 1.1.1.2 ! root 1720: addr = gen_rtx (PLUS, Pmode, frame_pointer_rtx, ! 1721: gen_rtx (CONST_INT, VOIDmode, frame_offset)); 1.1 root 1722: #ifndef FRAME_GROWS_DOWNWARD 1723: frame_offset += size; 1724: #endif 1725: 1.1.1.2 ! root 1726: if (! memory_address_p (mode, addr)) ! 1727: invalid_stack_slot = 1; ! 1728: ! 1729: x = gen_rtx (MEM, mode, addr); ! 1730: ! 1731: return x; 1.1 root 1732: } 1733: 1.1.1.2 ! root 1734: /* Retroactively move an auto variable from a register to a stack slot. ! 1735: This is done when an address-reference to the variable is seen. */ 1.1 root 1736: 1.1.1.2 ! root 1737: void ! 1738: put_var_into_stack (decl) ! 1739: tree decl; ! 1740: { ! 1741: register rtx reg = DECL_RTL (decl); ! 1742: register rtx new; 1.1 root 1743: 1.1.1.2 ! root 1744: /* No need to do anything if decl has no rtx yet ! 1745: since in that case caller is setting TREE_ADDRESSABLE ! 1746: and a stack slot will be assigned when the rtl is made. */ ! 1747: if (reg == 0) ! 1748: return; ! 1749: if (GET_CODE (reg) != REG) ! 1750: return; ! 1751: ! 1752: new = parm_stack_loc (reg); ! 1753: if (new == 0) ! 1754: new = assign_stack_local (GET_MODE (reg), GET_MODE_SIZE (GET_MODE (reg))); ! 1755: ! 1756: /* If this is a memory ref that contains aggregate components, ! 1757: mark it as such for cse and loop optimize. */ ! 1758: reg->in_struct ! 1759: = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE ! 1760: || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE ! 1761: || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE); ! 1762: ! 1763: XEXP (reg, 0) = XEXP (new, 0); ! 1764: PUT_CODE (reg, MEM); ! 1765: /* `volatil' bit means one thing for MEMs, another entirely for REGs. */ ! 1766: reg->volatil = 0; 1.1 root 1767: 1.1.1.2 ! root 1768: fixup_var_refs (reg); ! 1769: } ! 1770: 1.1 root 1771: static void 1.1.1.2 ! root 1772: fixup_var_refs (var) ! 1773: rtx var; 1.1 root 1774: { 1.1.1.2 ! root 1775: register rtx insn; ! 1776: ! 1777: /* Yes. Must scan all insns for stack-refs that exceed the limit. */ ! 1778: for (insn = get_insns (); insn; ) ! 1779: { ! 1780: rtx next = NEXT_INSN (insn); ! 1781: if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN ! 1782: || GET_CODE (insn) == JUMP_INSN) ! 1783: { ! 1784: /* The insn to load VAR from a home in the arglist ! 1785: is now a no-op. When we see it, just delete it. */ ! 1786: if (GET_CODE (PATTERN (insn)) == SET ! 1787: && SET_DEST (PATTERN (insn)) == var ! 1788: && rtx_equal_p (SET_SRC (PATTERN (insn)), var)) ! 1789: next = delete_insn (insn); ! 1790: else ! 1791: fixup_var_refs_1 (var, PATTERN (insn), insn); ! 1792: } ! 1793: insn = next; ! 1794: } ! 1795: } ! 1796: ! 1797: static rtx ! 1798: fixup_var_refs_1 (var, x, insn) ! 1799: register rtx var; ! 1800: register rtx x; ! 1801: rtx insn; ! 1802: { ! 1803: register int i; ! 1804: RTX_CODE code = GET_CODE (x); ! 1805: register char *fmt; ! 1806: register rtx tem; ! 1807: ! 1808: switch (code) ! 1809: { ! 1810: case MEM: ! 1811: if (var == x) ! 1812: { ! 1813: x = fixup_stack_1 (x, insn); ! 1814: tem = gen_reg_rtx (GET_MODE (x)); ! 1815: emit_insn_before (gen_move_insn (tem, x), insn); ! 1816: return tem; ! 1817: } ! 1818: break; ! 1819: ! 1820: case REG: ! 1821: case CC0: ! 1822: case PC: ! 1823: case CONST_INT: ! 1824: case CONST: ! 1825: case SYMBOL_REF: ! 1826: case LABEL_REF: ! 1827: case CONST_DOUBLE: ! 1828: return x; ! 1829: ! 1830: case SIGN_EXTRACT: ! 1831: case ZERO_EXTRACT: ! 1832: /* Note that in some cases those types of expressions are altered ! 1833: by optimize_bit_field, and do not survive to get here. */ ! 1834: case SUBREG: ! 1835: tem = x; ! 1836: while (GET_CODE (tem) == SUBREG || GET_CODE (tem) == SIGN_EXTRACT ! 1837: || GET_CODE (tem) == ZERO_EXTRACT) ! 1838: tem = XEXP (tem, 0); ! 1839: if (tem == var) ! 1840: { ! 1841: x = fixup_stack_1 (x, insn); ! 1842: tem = gen_reg_rtx (GET_MODE (x)); ! 1843: emit_insn_before (gen_move_insn (tem, x), insn); ! 1844: return tem; ! 1845: } ! 1846: break; ! 1847: ! 1848: case SET: ! 1849: /* First do special simplification of bit-field references. */ ! 1850: if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT ! 1851: || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT) ! 1852: optimize_bit_field (x, insn, 0); ! 1853: if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT ! 1854: || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT) ! 1855: optimize_bit_field (x, insn, 0); ! 1856: ! 1857: { ! 1858: rtx dest = SET_DEST (x); ! 1859: rtx src = SET_SRC (x); ! 1860: rtx outerdest = dest; ! 1861: rtx outersrc = src; ! 1862: int strictflag = GET_CODE (dest) == STRICT_LOW_PART; ! 1863: ! 1864: while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART ! 1865: || GET_CODE (dest) == SIGN_EXTRACT ! 1866: || GET_CODE (dest) == ZERO_EXTRACT) ! 1867: dest = XEXP (dest, 0); ! 1868: while (GET_CODE (src) == SUBREG ! 1869: || GET_CODE (src) == SIGN_EXTRACT ! 1870: || GET_CODE (src) == ZERO_EXTRACT) ! 1871: src = XEXP (src, 0); ! 1872: ! 1873: /* If VAR does not appear at the top level of the SET ! 1874: just scan the lower levels of the tree. */ ! 1875: ! 1876: if (src != var && dest != var) ! 1877: break; ! 1878: ! 1879: /* Clean up (SUBREG:SI (MEM:mode ...) 0) ! 1880: that may appear inside a SIGN_EXTRACT or ZERO_EXTRACT. ! 1881: This was legitimate when the MEM was a REG. */ ! 1882: ! 1883: if ((GET_CODE (outerdest) == SIGN_EXTRACT ! 1884: || GET_CODE (outerdest) == ZERO_EXTRACT) ! 1885: && GET_CODE (XEXP (outerdest, 0)) == SUBREG ! 1886: && SUBREG_REG (XEXP (outerdest, 0)) == var) ! 1887: XEXP (outerdest, 0) = fixup_memory_subreg (XEXP (outerdest, 0)); ! 1888: ! 1889: if ((GET_CODE (outersrc) == SIGN_EXTRACT ! 1890: || GET_CODE (outersrc) == ZERO_EXTRACT) ! 1891: && GET_CODE (XEXP (outersrc, 0)) == SUBREG ! 1892: && SUBREG_REG (XEXP (outersrc, 0)) == var) ! 1893: XEXP (outersrc, 0) = fixup_memory_subreg (XEXP (outersrc, 0)); ! 1894: ! 1895: /* Make sure a MEM inside a SIGN_EXTRACT has QImode ! 1896: since that's what bit-field insns want. */ ! 1897: ! 1898: if ((GET_CODE (outerdest) == SIGN_EXTRACT ! 1899: || GET_CODE (outerdest) == ZERO_EXTRACT) ! 1900: && GET_CODE (XEXP (outerdest, 0)) == MEM ! 1901: && GET_MODE (XEXP (outerdest, 0)) != QImode) ! 1902: { ! 1903: XEXP (outerdest, 0) = copy_rtx (XEXP (outerdest, 0)); ! 1904: PUT_MODE (XEXP (outerdest, 0), QImode); ! 1905: } ! 1906: ! 1907: if ((GET_CODE (outersrc) == SIGN_EXTRACT ! 1908: || GET_CODE (outersrc) == ZERO_EXTRACT) ! 1909: && GET_CODE (XEXP (outersrc, 0)) == MEM ! 1910: && GET_MODE (XEXP (outersrc, 0)) != QImode) ! 1911: { ! 1912: XEXP (outersrc, 0) = copy_rtx (XEXP (outersrc, 0)); ! 1913: PUT_MODE (XEXP (outersrc, 0), QImode); ! 1914: } ! 1915: ! 1916: /* STRICT_LOW_PART is a no-op on memory references ! 1917: and it can cause combinations to be unrecognizable, ! 1918: so eliminate it. */ ! 1919: ! 1920: if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART) ! 1921: SET_DEST (x) = XEXP (SET_DEST (x), 0); ! 1922: ! 1923: /* An insn to copy VAR into or out of a register ! 1924: must be left alone, to avoid an infinite loop here. ! 1925: But do fix up the address of VAR's stack slot if nec. */ ! 1926: ! 1927: if (GET_CODE (SET_SRC (x)) == REG || GET_CODE (SET_DEST (x)) == REG) ! 1928: return fixup_stack_1 (x, insn); ! 1929: ! 1930: if ((GET_CODE (SET_SRC (x)) == SUBREG ! 1931: && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG) ! 1932: || (GET_CODE (SET_DEST (x)) == SUBREG ! 1933: && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG)) ! 1934: return fixup_stack_1 (x, insn); ! 1935: ! 1936: /* Otherwise, storing into VAR must be handled specially ! 1937: by storing into a temporary and copying that into VAR ! 1938: with a new insn after this one. */ ! 1939: ! 1940: if (dest == var) ! 1941: { ! 1942: rtx temp; ! 1943: rtx fixeddest; ! 1944: tem = SET_DEST (x); ! 1945: if (GET_CODE (tem) == STRICT_LOW_PART) ! 1946: tem = XEXP (tem, 0); ! 1947: temp = gen_reg_rtx (GET_MODE (tem)); ! 1948: fixeddest = fixup_stack_1 (SET_DEST (x), insn); ! 1949: emit_insn_after (gen_move_insn (fixeddest, temp), insn); ! 1950: SET_DEST (x) = temp; ! 1951: } ! 1952: } ! 1953: } ! 1954: ! 1955: /* Nothing special about this RTX; fix its operands. */ ! 1956: ! 1957: fmt = GET_RTX_FORMAT (code); ! 1958: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 1959: { ! 1960: if (fmt[i] == 'e') ! 1961: XEXP (x, i) = fixup_var_refs_1 (var, XEXP (x, i), insn); ! 1962: if (fmt[i] == 'E') ! 1963: { ! 1964: register int j; ! 1965: for (j = 0; j < XVECLEN (x, i); j++) ! 1966: XVECEXP (x, i, j) ! 1967: = fixup_var_refs_1 (var, XVECEXP (x, i, j), insn); ! 1968: } ! 1969: } ! 1970: return x; ! 1971: } ! 1972: ! 1973: /* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)), ! 1974: return an rtx (MEM:m1 newaddr) which is equivalent. */ ! 1975: ! 1976: static rtx ! 1977: fixup_memory_subreg (x) ! 1978: rtx x; ! 1979: { ! 1980: int offset = SUBREG_WORD (x) * UNITS_PER_WORD; ! 1981: rtx addr = XEXP (SUBREG_REG (x), 0); ! 1982: enum machine_mode mode = GET_MODE (SUBREG_REG (x)); ! 1983: ! 1984: #ifdef BYTES_BIG_ENDIAN ! 1985: offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) ! 1986: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); ! 1987: #endif ! 1988: return change_address (SUBREG_REG (x), mode, ! 1989: plus_constant (addr, offset)); ! 1990: } ! 1991: ! 1992: #if 0 ! 1993: /* Fix up any references to stack slots that are invalid memory addresses ! 1994: because they exceed the maximum range of a displacement. */ ! 1995: ! 1996: void ! 1997: fixup_stack_slots () ! 1998: { ! 1999: register rtx insn; ! 2000: ! 2001: /* Did we generate a stack slot that is out of range ! 2002: or otherwise has an invalid address? */ ! 2003: if (invalid_stack_slot) ! 2004: { ! 2005: /* Yes. Must scan all insns for stack-refs that exceed the limit. */ ! 2006: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 2007: if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN ! 2008: || GET_CODE (insn) == JUMP_INSN) ! 2009: fixup_stack_1 (PATTERN (insn), insn); ! 2010: } ! 2011: } ! 2012: #endif ! 2013: ! 2014: /* For each memory ref within X, if it refers to a stack slot ! 2015: with an out of range displacement, put the address in a temp register ! 2016: (emitting new insns before INSN to load these registers) ! 2017: and alter the memory ref to use that register. ! 2018: Replace each such MEM rtx with a copy, to avoid clobberage. */ ! 2019: ! 2020: static rtx ! 2021: fixup_stack_1 (x, insn) ! 2022: rtx x; ! 2023: rtx insn; ! 2024: { ! 2025: register int i; ! 2026: register RTX_CODE code = GET_CODE (x); ! 2027: register char *fmt; ! 2028: ! 2029: if (code == MEM) ! 2030: { ! 2031: register rtx ad = XEXP (x, 0); ! 2032: /* If we have address of a stack slot but it's not valid ! 2033: (displacement is too large), compute the sum in a register. */ ! 2034: if (GET_CODE (ad) == PLUS ! 2035: && XEXP (ad, 0) == frame_pointer_rtx ! 2036: && GET_CODE (XEXP (ad, 1)) == CONST_INT) ! 2037: { ! 2038: rtx temp; ! 2039: if (memory_address_p (GET_MODE (x), ad)) ! 2040: return x; ! 2041: temp = gen_reg_rtx (GET_MODE (ad)); ! 2042: emit_insn_before (gen_move_insn (temp, ad), insn); ! 2043: return change_address (x, VOIDmode, temp); ! 2044: } ! 2045: return x; ! 2046: } ! 2047: ! 2048: fmt = GET_RTX_FORMAT (code); ! 2049: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 2050: { ! 2051: if (fmt[i] == 'e') ! 2052: XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn); ! 2053: if (fmt[i] == 'E') ! 2054: { ! 2055: register int j; ! 2056: for (j = 0; j < XVECLEN (x, i); j++) ! 2057: XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn); ! 2058: } ! 2059: } ! 2060: return x; 1.1 root 2061: } 1.1.1.2 ! root 2062: ! 2063: /* Optimization: a bit-field instruction whose field ! 2064: happens to be a byte or halfword in memory ! 2065: can be changed to a move instruction. 1.1 root 2066: 1.1.1.2 ! root 2067: We call here when INSN is an insn to examine or store into a bit-field. ! 2068: BODY is the SET-rtx to be altered. ! 2069: ! 2070: EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0. ! 2071: (Currently this is called only from stmt.c, and EQUIV_MEM is always 0.) */ 1.1 root 2072: 2073: static void 1.1.1.2 ! root 2074: optimize_bit_field (body, insn, equiv_mem) ! 2075: rtx body; ! 2076: rtx insn; ! 2077: rtx *equiv_mem; 1.1 root 2078: { 1.1.1.2 ! root 2079: register rtx bitfield; ! 2080: int destflag; 1.1 root 2081: 1.1.1.2 ! root 2082: if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT ! 2083: || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT) ! 2084: bitfield = SET_DEST (body), destflag = 1; ! 2085: else ! 2086: bitfield = SET_SRC (body), destflag = 0; ! 2087: ! 2088: /* First check that the field being stored has constant size and position ! 2089: and is in fact a byte or halfword suitably aligned. */ ! 2090: ! 2091: if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT ! 2092: && GET_CODE (XEXP (bitfield, 2)) == CONST_INT ! 2093: && (INTVAL (XEXP (bitfield, 1)) == GET_MODE_BITSIZE (QImode) ! 2094: || INTVAL (XEXP (bitfield, 1)) == GET_MODE_BITSIZE (HImode)) ! 2095: && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0) 1.1 root 2096: { 1.1.1.2 ! root 2097: register rtx memref = 0; ! 2098: ! 2099: /* Now check that the contanting word is memory, not a register, ! 2100: and that it is safe to change the machine mode and to ! 2101: add something to the address. */ ! 2102: ! 2103: if (GET_CODE (XEXP (bitfield, 0)) == MEM) ! 2104: memref = XEXP (bitfield, 0); ! 2105: else if (GET_CODE (XEXP (bitfield, 0)) == REG ! 2106: && equiv_mem != 0 ! 2107: && (memref = equiv_mem[REGNO (XEXP (bitfield, 0))]) != 0) ! 2108: ; ! 2109: else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG ! 2110: && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM) ! 2111: memref = SUBREG_REG (XEXP (bitfield, 0)); ! 2112: else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG ! 2113: && equiv_mem != 0 ! 2114: && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG ! 2115: && (memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))]) != 0) ! 2116: ; ! 2117: ! 2118: if (memref ! 2119: && ! mode_dependent_address_p (XEXP (memref, 0)) ! 2120: && offsetable_address_p (GET_MODE (bitfield), XEXP (memref, 0))) 1.1 root 2121: { 1.1.1.2 ! root 2122: /* Now adjust the address, first for any subreg'ing ! 2123: that we are now getting rid of, ! 2124: and then for which byte of the word is wanted. */ ! 2125: ! 2126: register int offset ! 2127: = INTVAL (XEXP (bitfield, 2)) / GET_MODE_BITSIZE (QImode); ! 2128: if (GET_CODE (XEXP (bitfield, 0)) == SUBREG) ! 2129: { ! 2130: offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD; ! 2131: #ifdef BYTES_BIG_ENDIAN ! 2132: offset -= (MIN (UNITS_PER_WORD, ! 2133: GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0)))) ! 2134: - MIN (UNITS_PER_WORD, ! 2135: GET_MODE_SIZE (GET_MODE (memref)))); ! 2136: #endif ! 2137: } ! 2138: memref = gen_rtx (MEM, ! 2139: (INTVAL (XEXP (bitfield, 1)) == GET_MODE_BITSIZE (QImode) ! 2140: ? QImode : HImode), ! 2141: XEXP (memref, 0)); 1.1 root 2142: 1.1.1.2 ! root 2143: /* Store this memory reference where ! 2144: we found the bit field reference. */ 1.1 root 2145: 1.1.1.2 ! root 2146: if (destflag) 1.1 root 2147: { 1.1.1.2 ! root 2148: SET_DEST (body) ! 2149: = adj_offsetable_operand (memref, offset); ! 2150: if (! CONSTANT_ADDRESS_P (SET_SRC (body))) 1.1 root 2151: { 1.1.1.2 ! root 2152: rtx src = SET_SRC (body); ! 2153: while (GET_CODE (src) == SUBREG ! 2154: && SUBREG_WORD (src) == 0) ! 2155: src = SUBREG_REG (src); ! 2156: if (GET_MODE (src) != GET_MODE (memref)) ! 2157: src = gen_rtx (SUBREG, GET_MODE (memref), ! 2158: SET_SRC (body), 0); ! 2159: SET_SRC (body) = src; 1.1 root 2160: } 1.1.1.2 ! root 2161: else if (GET_MODE (SET_SRC (body)) != VOIDmode ! 2162: && GET_MODE (SET_SRC (body)) != GET_MODE (memref)) ! 2163: /* This shouldn't happen because anything that didn't have ! 2164: one of these modes should have got converted explicitly ! 2165: and then referenced through a subreg. ! 2166: This is so because the original bit-field was ! 2167: handled by agg_mode and so its tree structure had ! 2168: the same mode that memref now has. */ ! 2169: abort (); ! 2170: } ! 2171: else ! 2172: { ! 2173: rtx newreg = gen_reg_rtx (GET_MODE (SET_DEST (body))); ! 2174: emit_insn_before (gen_extend_insn (newreg, adj_offsetable_operand (memref, offset), ! 2175: GET_MODE (SET_DEST (body)), ! 2176: GET_MODE (memref), ! 2177: GET_CODE (SET_SRC (body)) == ZERO_EXTRACT), ! 2178: insn); ! 2179: SET_SRC (body) = newreg; 1.1 root 2180: } 1.1.1.2 ! root 2181: ! 2182: /* Cause the insn to be re-recognized. */ ! 2183: ! 2184: INSN_CODE (insn) = -1; 1.1 root 2185: } 2186: } 2187: } 2188: 2189: /* 1 + last pseudo register number used for loading a copy 2190: of a parameter of this function. */ 2191: 2192: static int max_parm_reg; 2193: 1.1.1.2 ! root 2194: /* Vector indexed by REGNO, containing location on stack in which ! 2195: to put the parm which is nominally in pseudo register REGNO, ! 2196: if we discover that that parm must go in the stack. */ ! 2197: static rtx *parm_reg_stack_loc; ! 2198: ! 2199: /* Last insn of those whose job was to put parms into their nominal homes. */ ! 2200: static rtx last_parm_insn; ! 2201: ! 2202: int ! 2203: max_parm_reg_num () ! 2204: { ! 2205: return max_parm_reg; ! 2206: } ! 2207: ! 2208: /* Return the first insn following those generated by `assign_parms'. */ ! 2209: ! 2210: rtx ! 2211: get_first_nonparm_insn () ! 2212: { ! 2213: if (last_parm_insn) ! 2214: return NEXT_INSN (last_parm_insn); ! 2215: return get_insns (); ! 2216: } ! 2217: ! 2218: /* Get the stack home of a REG rtx that is one of this function's parameters. ! 2219: This is called rather than assign a new stack slot as a local. ! 2220: Return 0 if there is no existing stack home suitable for such use. */ ! 2221: ! 2222: static rtx ! 2223: parm_stack_loc (reg) ! 2224: rtx reg; ! 2225: { ! 2226: if (REGNO (reg) < max_parm_reg) ! 2227: return parm_reg_stack_loc[REGNO (reg)]; ! 2228: return 0; ! 2229: } ! 2230: 1.1 root 2231: /* Assign RTL expressions to the function's parameters. 2232: This may involve copying them into registers and using 2233: those registers as the RTL for them. */ 2234: 2235: static void 2236: assign_parms (fndecl) 2237: tree fndecl; 2238: { 2239: register tree parm; 1.1.1.2 ! root 2240: register rtx entry_parm; ! 2241: register rtx stack_parm; ! 2242: register CUMULATIVE_ARGS args_so_far; ! 2243: enum machine_mode passed_mode, nominal_mode; ! 2244: /* Total space needed so far for args on the stack, ! 2245: given as a constant and a tree-expression. */ ! 2246: struct args_size stack_args_size; ! 2247: ! 2248: int nparmregs ! 2249: = list_length (DECL_ARGUMENTS (fndecl)) + FIRST_PSEUDO_REGISTER; ! 2250: ! 2251: /* Nonzero if function takes extra anonymous args. ! 2252: This means the last named arg must be on the stack ! 2253: right before the anonymous ones. */ ! 2254: int vararg ! 2255: = (TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0 ! 2256: && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))) ! 2257: != void_type_node)); ! 2258: ! 2259: stack_args_size.constant = 0; ! 2260: stack_args_size.var = 0; ! 2261: ! 2262: parm_reg_stack_loc = (rtx *) oballoc (nparmregs * sizeof (rtx)); ! 2263: bzero (parm_reg_stack_loc, nparmregs * sizeof (rtx)); ! 2264: ! 2265: INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fndecl)); 1.1 root 2266: 1.1.1.2 ! root 2267: for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) 1.1 root 2268: { 1.1.1.2 ! root 2269: int aggregate ! 2270: = (TREE_CODE (TREE_TYPE (parm)) == ARRAY_TYPE ! 2271: || TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE ! 2272: || TREE_CODE (TREE_TYPE (parm)) == UNION_TYPE); ! 2273: struct args_size stack_offset; ! 2274: rtx stack_offset_rtx; ! 2275: ! 2276: /* Get this parm's offset as an rtx. */ ! 2277: stack_offset = stack_args_size; ! 2278: stack_offset.constant += FIRST_PARM_OFFSET; ! 2279: stack_offset_rtx = ARGS_SIZE_RTX (stack_offset); ! 2280: ! 2281: DECL_OFFSET (parm) = -1; ! 2282: 1.1 root 2283: if (TREE_TYPE (parm) == error_mark_node) 1.1.1.2 ! root 2284: { ! 2285: DECL_RTL (parm) = gen_rtx (MEM, BLKmode, const0_rtx); ! 2286: continue; ! 2287: } ! 2288: ! 2289: /* Find mode of arg as it is passed, and mode of arg ! 2290: as it should be during execution of this function. */ ! 2291: passed_mode = TYPE_MODE (DECL_ARG_TYPE (parm)); ! 2292: nominal_mode = TYPE_MODE (TREE_TYPE (parm)); ! 2293: ! 2294: /* Determine parm's home in the stack, ! 2295: in case it arrives in the stack or we should pretend it did. */ ! 2296: stack_parm ! 2297: = gen_rtx (MEM, passed_mode, ! 2298: memory_address (passed_mode, ! 2299: gen_rtx (PLUS, Pmode, ! 2300: arg_pointer_rtx, stack_offset_rtx))); ! 2301: ! 2302: /* If this is a memory ref that contains aggregate components, ! 2303: mark it as such for cse and loop optimize. */ ! 2304: stack_parm->in_struct = aggregate; ! 2305: ! 2306: /* Let machine desc say which reg (if any) the parm arrives in. ! 2307: 0 means it arrives on the stack. */ ! 2308: entry_parm = 0; ! 2309: /* Variable-size args, and args following such, are never in regs. */ ! 2310: if (TREE_CODE (TYPE_SIZE (TREE_TYPE (parm))) == INTEGER_CST ! 2311: || stack_offset.var != 0) ! 2312: { ! 2313: #ifdef FUNCTION_INCOMING_ARG ! 2314: entry_parm ! 2315: = FUNCTION_INCOMING_ARG (args_so_far, passed_mode, ! 2316: DECL_ARG_TYPE (parm), 1); ! 2317: #else ! 2318: entry_parm ! 2319: = FUNCTION_ARG (args_so_far, passed_mode, DECL_ARG_TYPE (parm), 1); ! 2320: #endif ! 2321: } ! 2322: /* If this parm was passed part in regs and part in memory, ! 2323: pretend it arrived entirely in memory ! 2324: by pushing the register-part onto the stack. ! 2325: ! 2326: In the special case of a DImode or DFmode that is split, ! 2327: we could put it together in a pseudoreg directly, ! 2328: but for now that's not worth bothering with. */ ! 2329: ! 2330: /* If this is the last named arg and anonymous args follow, ! 2331: likewise pretend this arg arrived on the stack ! 2332: so varargs can find the anonymous args following it. */ ! 2333: { ! 2334: int nregs = 0; ! 2335: int i; ! 2336: #ifdef FUNCTION_ARG_PARTIAL_NREGS ! 2337: nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, passed_mode, ! 2338: DECL_ARG_TYPE (parm), 1); ! 2339: #endif ! 2340: if (TREE_CHAIN (parm) == 0 && vararg && entry_parm != 0) ! 2341: nregs = GET_MODE_SIZE (GET_MODE (entry_parm)) / UNITS_PER_WORD; ! 2342: ! 2343: if (nregs > 0) ! 2344: current_function_pretend_args_size ! 2345: = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1) ! 2346: / (PARM_BOUNDARY / BITS_PER_UNIT) ! 2347: * (PARM_BOUNDARY / BITS_PER_UNIT)); ! 2348: ! 2349: i = nregs; ! 2350: while (--i >= 0) ! 2351: emit_move_insn (gen_rtx (MEM, SImode, ! 2352: plus_constant (XEXP (stack_parm, 0), ! 2353: i * GET_MODE_SIZE (SImode))), ! 2354: gen_rtx (REG, SImode, REGNO (entry_parm) + i)); ! 2355: if (nregs > 0) ! 2356: entry_parm = stack_parm; ! 2357: } ! 2358: ! 2359: if (entry_parm == 0) ! 2360: entry_parm = stack_parm; ! 2361: ! 2362: /* Now ENTRY_PARM refers to the stack iff this parm uses stack space. ! 2363: In that case, count its size in STACK_ARGS_SIZE. */ ! 2364: ! 2365: if (entry_parm == stack_parm) ! 2366: { ! 2367: tree sizetree = size_in_bytes (DECL_ARG_TYPE (parm)); ! 2368: /* Round the size up to multiple of PARM_BOUNDARY bits. */ ! 2369: tree s1 = convert_units (sizetree, BITS_PER_UNIT, PARM_BOUNDARY); ! 2370: tree s2 = convert_units (s1, PARM_BOUNDARY, BITS_PER_UNIT); ! 2371: /* Add it in. */ ! 2372: ADD_PARM_SIZE (stack_args_size, s2); ! 2373: } ! 2374: ! 2375: /* Now set STACK_PARM to the place in the stack ! 2376: where this parameter should live during execution, ! 2377: if we discover that it must live in the stack during execution. ! 2378: To make debuggers happier on big-endian machines, we store ! 2379: the value in the last bytes of the space available. */ ! 2380: ! 2381: if (nominal_mode != BLKmode && nominal_mode != passed_mode) ! 2382: { ! 2383: #ifdef BYTES_BIG_ENDIAN ! 2384: stack_offset.constant ! 2385: += GET_MODE_SIZE (passed_mode) ! 2386: - GET_MODE_SIZE (nominal_mode); ! 2387: stack_offset_rtx = ARGS_SIZE_RTX (stack_offset); ! 2388: #endif ! 2389: ! 2390: stack_parm ! 2391: = gen_rtx (MEM, nominal_mode, ! 2392: memory_address (nominal_mode, ! 2393: gen_rtx (PLUS, Pmode, ! 2394: arg_pointer_rtx, ! 2395: stack_offset_rtx))); ! 2396: ! 2397: /* If this is a memory ref that contains aggregate components, ! 2398: mark it as such for cse and loop optimize. */ ! 2399: stack_parm->in_struct = aggregate; ! 2400: } ! 2401: ! 2402: /* If the parm arrived in a reg, we don't have an argument ! 2403: stack slot for it, so don't think that we do. ! 2404: If it needs to be addressable, it will get put into the stack ! 2405: like an ordinary automatic variable. */ ! 2406: ! 2407: if (GET_CODE (entry_parm) == REG) ! 2408: stack_parm = 0; 1.1 root 2409: else 1.1.1.2 ! root 2410: DECL_OFFSET (parm) = stack_offset.constant * BITS_PER_UNIT; ! 2411: ! 2412: #if 0 /* Not needed now that `memory_address' is used above. */ ! 2413: /* If either STACK_PARM or ENTRY_PARM is a MEM whose address ! 2414: is not really valid, arrange to correct all references later. */ ! 2415: ! 2416: if ((GET_CODE (entry_parm) == MEM ! 2417: && ! memory_address_p (passed_mode, XEXP (entry_parm, 0))) ! 2418: || (stack_parm != entry_parm && stack_parm != 0 ! 2419: && GET_CODE (stack_parm) == MEM ! 2420: && ! memory_address_p (nominal_mode, XEXP (stack_parm, 0)))) ! 2421: invalid_stack_slot = 1; ! 2422: #endif /* 0 */ ! 2423: ! 2424: /* ENTRY_PARM is an RTX for the parameter as it arrives, ! 2425: in the mode in which it arrives. 1.1 root 2426: 2427: Now output code if necessary to convert it to 2428: the type in which this function declares it, 2429: and store a reference to that value in DECL_RTL. 1.1.1.2 ! root 2430: This reference may be the same as STACK_PARM, ! 2431: or a similar stack reference in a different mode, ! 2432: or may be a pseudo register. */ ! 2433: ! 2434: if (nominal_mode == BLKmode) ! 2435: { ! 2436: /* If a BLKmode arrives in registers, copy it to a stack slot. */ ! 2437: if (stack_parm == 0) ! 2438: { ! 2439: stack_parm ! 2440: = assign_stack_local (GET_MODE (entry_parm), ! 2441: int_size_in_bytes (TREE_TYPE (parm))); ! 2442: ! 2443: move_block_from_reg (REGNO (entry_parm), stack_parm, ! 2444: int_size_in_bytes (TREE_TYPE (parm)) ! 2445: / UNITS_PER_WORD); ! 2446: } ! 2447: DECL_RTL (parm) = stack_parm; 1.1 root 2448: 1.1.1.2 ! root 2449: } ! 2450: else if (! ((obey_regdecls && ! TREE_REGDECL (parm)) ! 2451: /* If -ffloat-store specified, don't put explicit ! 2452: float variables into registers. */ ! 2453: || (flag_float_store ! 2454: && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))) 1.1 root 2455: { 1.1.1.2 ! root 2456: /* Store the parm in a pseudoregister during the function. */ ! 2457: register rtx parmreg = gen_reg_rtx (nominal_mode); 1.1 root 2458: 1.1.1.2 ! root 2459: parmreg->volatil = 1; 1.1 root 2460: DECL_RTL (parm) = parmreg; 2461: 2462: /* Copy the value into the register. */ 1.1.1.2 ! root 2463: if (GET_MODE (parmreg) != GET_MODE (entry_parm)) ! 2464: convert_move (parmreg, entry_parm, 0); 1.1 root 2465: else 1.1.1.2 ! root 2466: emit_move_insn (parmreg, entry_parm); ! 2467: ! 2468: /* In any case, record the parm's desired stack location ! 2469: in case we later discover it must live in the stack. */ ! 2470: if (REGNO (parmreg) >= nparmregs) ! 2471: { ! 2472: rtx *new; ! 2473: nparmregs = REGNO (parmreg) + 5; ! 2474: new = (rtx *) oballoc (nparmregs * sizeof (rtx)); ! 2475: bcopy (parm_reg_stack_loc, new, nparmregs * sizeof (rtx)); ! 2476: parm_reg_stack_loc = new; ! 2477: } ! 2478: parm_reg_stack_loc[REGNO (parmreg)] = stack_parm; 1.1 root 2479: 1.1.1.2 ! root 2480: /* Mark the register as eliminable if we did no conversion ! 2481: and it was copied from memory at a fixed offset. */ ! 2482: if (nominal_mode == passed_mode ! 2483: && GET_CODE (entry_parm) == MEM ! 2484: && stack_offset.var == 0) ! 2485: REG_NOTES (get_last_insn ()) = gen_rtx (EXPR_LIST, REG_EQUIV, ! 2486: entry_parm, 0); 1.1 root 2487: 2488: /* For pointer data type, suggest pointer register. */ 2489: if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE) 2490: mark_reg_pointer (parmreg); 2491: } 1.1.1.2 ! root 2492: else 1.1 root 2493: { 1.1.1.2 ! root 2494: /* Value must be stored in the stack slot STACK_PARM ! 2495: during function execution. */ ! 2496: ! 2497: if (passed_mode != nominal_mode) ! 2498: /* Conversion is required. */ ! 2499: entry_parm = convert_to_mode (nominal_mode, entry_parm, 0); ! 2500: ! 2501: if (entry_parm != stack_parm) ! 2502: { ! 2503: if (stack_parm == 0) ! 2504: stack_parm = assign_stack_local (GET_MODE (entry_parm), ! 2505: GET_MODE_SIZE (GET_MODE (entry_parm))); ! 2506: emit_move_insn (stack_parm, entry_parm); ! 2507: } ! 2508: ! 2509: DECL_RTL (parm) = stack_parm; ! 2510: frame_pointer_needed = 1; 1.1 root 2511: } 1.1.1.2 ! root 2512: ! 2513: if (TREE_VOLATILE (parm)) ! 2514: DECL_RTL (parm)->volatil = 1; ! 2515: if (TREE_READONLY (parm)) ! 2516: DECL_RTL (parm)->unchanging = 1; ! 2517: ! 2518: /* Update info on where next arg arrives in registers. */ ! 2519: ! 2520: FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, DECL_ARG_TYPE (parm), 1); 1.1 root 2521: } 2522: max_parm_reg = max_reg_num (); 1.1.1.2 ! root 2523: last_parm_insn = get_last_insn (); ! 2524: ! 2525: current_function_args_size = stack_args_size.constant; 1.1 root 2526: } 2527: 2528: /* Allocation of space for returned structure values. 2529: During the rtl generation pass, `get_structure_value_addr' 2530: is called from time to time to request the address of a block in our 2531: stack frame in which called functions will store the structures 2532: they are returning. The same space is used for all of these blocks. 2533: 1.1.1.2 ! root 2534: We allocate these blocks like stack locals. We keep reusing ! 2535: the same block until a bigger one is needed. */ ! 2536: ! 2537: /* Length in bytes of largest structure value returned by ! 2538: any function called so far in this function. */ ! 2539: static int max_structure_value_size; 1.1 root 2540: 1.1.1.2 ! root 2541: /* An rtx for the addr we are currently using for structure values. ! 2542: This is typically (PLUS (REG:SI stackptr) (CONST_INT...)). */ ! 2543: static rtx structure_value; 1.1 root 2544: 2545: rtx 2546: get_structure_value_addr (sizex) 2547: rtx sizex; 2548: { 2549: register int size; 2550: if (GET_CODE (sizex) != CONST_INT) 2551: abort (); 2552: size = INTVAL (sizex); 2553: 2554: /* Round up to a multiple of the main allocation unit. */ 2555: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) 2556: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)) 2557: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); 2558: 1.1.1.2 ! root 2559: /* If this size is bigger than space we know to use, ! 2560: get a bigger piece of space. */ 1.1 root 2561: if (size > max_structure_value_size) 2562: { 2563: max_structure_value_size = size; 1.1.1.2 ! root 2564: structure_value = assign_stack_local (BLKmode, size); ! 2565: if (GET_CODE (structure_value) == MEM) ! 2566: structure_value = XEXP (structure_value, 0); 1.1 root 2567: } 1.1.1.2 ! root 2568: ! 2569: return structure_value; 1.1 root 2570: } 1.1.1.2 ! root 2571: ! 2572: /* Walk the tree of LET_STMTs describing the binding levels within a function ! 2573: and warn about uninitialized variables. ! 2574: This is done after calling flow_analysis and before global_alloc ! 2575: clobbers the pseudo-regs to hard regs. */ 1.1 root 2576: 1.1.1.2 ! root 2577: void ! 2578: uninitialized_vars_warning (block) ! 2579: tree block; 1.1 root 2580: { 1.1.1.2 ! root 2581: register tree decl, sub; ! 2582: for (decl = STMT_VARS (block); decl; decl = TREE_CHAIN (decl)) ! 2583: { ! 2584: if (TREE_CODE (decl) == VAR_DECL ! 2585: /* These warnings are unreliable for and aggregates ! 2586: because assigning the fields one by one can fail to convince ! 2587: flow.c that the entire aggregate was initialized. ! 2588: Unions are troublesome because members may be shorter. */ ! 2589: && TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE ! 2590: && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE ! 2591: && TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE ! 2592: && GET_CODE (DECL_RTL (decl)) == REG ! 2593: && regno_uninitialized (REGNO (DECL_RTL (decl)))) ! 2594: warning_with_decl (decl, ! 2595: "variable `%s' used uninitialized in this function"); ! 2596: if (TREE_CODE (decl) == VAR_DECL ! 2597: && GET_CODE (DECL_RTL (decl)) == REG ! 2598: && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl)))) ! 2599: warning_with_decl (decl, ! 2600: "variable `%s' may be clobbered by `longjmp'"); ! 2601: } ! 2602: for (sub = STMT_BODY (block); sub; sub = TREE_CHAIN (sub)) ! 2603: uninitialized_vars_warning (sub); 1.1 root 2604: } 2605: 1.1.1.2 ! root 2606: /* Generate RTL for the start of the function FUNC (a FUNCTION_DECL tree node) ! 2607: and initialize static variables for generating RTL for the statements ! 2608: of the function. */ 1.1 root 2609: 1.1.1.2 ! root 2610: void ! 2611: expand_function_start (subr) 1.1 root 2612: tree subr; 2613: { 2614: register int i; 1.1.1.2 ! root 2615: tree tem; 1.1 root 2616: 2617: this_function = subr; 1.1.1.2 ! root 2618: cse_not_expected = ! optimize; ! 2619: ! 2620: /* We have not yet found a reason why a frame pointer cannot ! 2621: be omitted for this function in particular, but maybe we know ! 2622: a priori that it is required. ! 2623: `flag_omit_frame_pointer' has its main effect here. */ ! 2624: frame_pointer_needed = FRAME_POINTER_REQUIRED || ! flag_omit_frame_pointer; 1.1 root 2625: 1.1.1.2 ! root 2626: /* No gotos have been expanded yet. */ ! 2627: goto_fixup_chain = 0; 1.1 root 2628: 1.1.1.2 ! root 2629: /* No invalid stack slots have been made yet. */ ! 2630: invalid_stack_slot = 0; ! 2631: ! 2632: /* Initialize the RTL mechanism. */ ! 2633: init_emit (write_symbols); ! 2634: ! 2635: /* Initialize the queue of pending postincrement and postdecrements, ! 2636: and some other info in expr.c. */ ! 2637: init_expr (); ! 2638: ! 2639: init_const_rtx_hash_table (); ! 2640: ! 2641: /* Decide whether function should try to pop its args on return. */ ! 2642: ! 2643: current_function_pops_args = RETURN_POPS_ARGS (TREE_TYPE (subr)); ! 2644: ! 2645: current_function_name = IDENTIFIER_POINTER (DECL_NAME (subr)); ! 2646: ! 2647: /* Make the label for return statements to jump to, if this machine ! 2648: does not have a one-instruction return. */ 1.1 root 2649: #ifdef FUNCTION_EPILOGUE 2650: return_label = gen_label_rtx (); 1.1.1.2 ! root 2651: #else ! 2652: return_label = 0; 1.1 root 2653: #endif 2654: 1.1.1.2 ! root 2655: /* No space assigned yet for structure values. */ 1.1 root 2656: max_structure_value_size = 0; 1.1.1.2 ! root 2657: structure_value = 0; 1.1 root 2658: 1.1.1.2 ! root 2659: /* We are not currently within any block, conditional, loop or case. */ 1.1 root 2660: block_stack = 0; 1.1.1.2 ! root 2661: loop_stack = 0; ! 2662: case_stack = 0; ! 2663: cond_stack = 0; ! 2664: nesting_stack = 0; ! 2665: nesting_depth = 0; ! 2666: ! 2667: /* We have not yet needed to make a label to jump to for tail-recursion. */ 1.1 root 2668: tail_recursion_label = 0; 2669: 1.1.1.2 ! root 2670: /* No stack slots allocated yet. */ ! 2671: frame_offset = STARTING_FRAME_OFFSET; ! 2672: ! 2673: init_pending_stack_adjust (); 1.1 root 2674: clear_current_args_size (); 2675: 2676: /* Prevent ever trying to delete the first instruction of a function. 2677: Also tell final how to output a linenum before the function prologue. */ 2678: emit_note (DECL_SOURCE_FILE (subr), DECL_SOURCE_LINE (subr)); 2679: /* Make sure first insn is a note even if we don't want linenums. 2680: This makes sure the first insn will never be deleted. 2681: Also, final expects a note to appear there. */ 2682: emit_note (0, NOTE_INSN_DELETED); 2683: 2684: /* Initialize rtx for parameters and local variables. 2685: In some cases this requires emitting insns. */ 2686: 2687: assign_parms (subr); 1.1.1.2 ! root 2688: ! 2689: /* If doing stupid allocation, mark parms as born here. */ ! 2690: ! 2691: if (obey_regdecls) ! 2692: for (i = FIRST_PSEUDO_REGISTER; i < max_parm_reg; i++) ! 2693: emit_insn (gen_rtx (USE, VOIDmode, regno_reg_rtx[i])); ! 2694: 1.1 root 2695: /* After the parm initializations is where the tail-recursion label 2696: should go, if we end up needing one. */ 2697: tail_recursion_reentry = get_last_insn (); 2698: 2699: /* Initialize rtx used to return the value. */ 2700: 2701: if (DECL_MODE (DECL_RESULT (subr)) == BLKmode) 2702: { 2703: /* Returning something that won't go in a register. */ 2704: register rtx value_address; 2705: 1.1.1.2 ! root 2706: /* Expect to be passed the address of a place to store the value. */ 1.1 root 2707: value_address = gen_reg_rtx (Pmode); 1.1.1.2 ! root 2708: emit_move_insn (value_address, struct_value_incoming_rtx); 1.1 root 2709: DECL_RTL (DECL_RESULT (subr)) 2710: = gen_rtx (MEM, DECL_MODE (DECL_RESULT (subr)), 2711: value_address); 2712: } 2713: else 1.1.1.2 ! root 2714: #ifdef FUNCTION_OUTGOING_VALUE 1.1 root 2715: DECL_RTL (DECL_RESULT (subr)) 1.1.1.2 ! root 2716: = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr); ! 2717: #else ! 2718: DECL_RTL (DECL_RESULT (subr)) ! 2719: = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr); ! 2720: #endif ! 2721: } 1.1 root 2722: 1.1.1.2 ! root 2723: /* Generate RTL for the end of the current function. */ 1.1 root 2724: 1.1.1.2 ! root 2725: void ! 2726: expand_function_end () ! 2727: { ! 2728: register int i; 1.1 root 2729: 1.1.1.2 ! root 2730: /* Fix up any gotos that jumped out to the outermost ! 2731: binding level of the function. */ ! 2732: fixup_gotos (0, get_insns ()); 1.1 root 2733: 2734: /* If doing stupid register allocation, 1.1.1.2 ! root 2735: mark register parms as dying here. */ ! 2736: 1.1 root 2737: if (obey_regdecls) 1.1.1.2 ! root 2738: for (i = FIRST_PSEUDO_REGISTER; i < max_parm_reg; i++) ! 2739: emit_insn (gen_rtx (USE, VOIDmode, regno_reg_rtx[i])); 1.1 root 2740: 2741: clear_pending_stack_adjust (); 1.1.1.2 ! root 2742: do_pending_stack_adjust (); 1.1 root 2743: 1.1.1.2 ! root 2744: /* Mark the end of the function body. ! 2745: If control reaches this insn, the function can drop through ! 2746: without returning a value. */ ! 2747: emit_note (0, NOTE_INSN_FUNCTION_END); ! 2748: ! 2749: /* If we require a true epilogue, ! 2750: put here the label that return statements jump to. ! 2751: If there will be no epilogue, write a return instruction. */ 1.1 root 2752: #ifdef FUNCTION_EPILOGUE 2753: emit_label (return_label); 2754: #else 2755: emit_jump_insn (gen_return ()); 2756: #endif 2757: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.