|
|
1.1 ! root 1: /* Expands front end tree to back end RTL for GNU C-Compiler ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 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 ! 23: at the level of statements using subroutines in exp*.c and emit-rtl.c. ! 24: It also creates the rtl expressions for parameters and auto variables ! 25: and has full responsibility for allocating stack slots. ! 26: A few routines in this file are called during later passes ! 27: when stack frame management requires it. ! 28: ! 29: The main entry point is expand_function, which is at the end. */ ! 30: ! 31: #include "config.h" ! 32: ! 33: #include <stdio.h> ! 34: ! 35: #include "rtl.h" ! 36: #include "tree.h" ! 37: #include "insn-flags.h" ! 38: #include "stupid.h" ! 39: #include "expr.h" ! 40: ! 41: #define MAX(x,y) (((x) > (y)) ? (x) : (y)) ! 42: #define MIN(x,y) (((x) < (y)) ? (x) : (y)) ! 43: ! 44: /* Label that will go on function epilogue. ! 45: Jumping to this label serves as a "return" instruction ! 46: on machines which require execution of the epilogue on all returns. */ ! 47: ! 48: static rtx return_label; ! 49: ! 50: /* The FUNCTION_DECL node for the function being compiled. */ ! 51: ! 52: static tree this_function; ! 53: ! 54: /* Offset to end of allocated area of stack frame. ! 55: If stack grows down, this is the address of the last stack slot allocated. ! 56: If stack grows up, this is the address for the next slot. */ ! 57: static int frame_offset; ! 58: ! 59: /* Length in bytes of largest structure value returned by ! 60: any function called so far in this function. */ ! 61: static int max_structure_value_size; ! 62: ! 63: /* Label to jump back to for tail recursion, or 0 if we have ! 64: not yet needed one for this function. */ ! 65: static rtx tail_recursion_label; ! 66: ! 67: /* Place after which to insert the tail_recursion_label if we need one. */ ! 68: static rtx tail_recursion_reentry; ! 69: ! 70: static int tail_recursion_args (); ! 71: ! 72: /* Estimate the complexity of the compiled code for STMT. ! 73: This is a rough estimate and is used for purposes ! 74: of deciding which optimizations are worth applying. */ ! 75: ! 76: static int ! 77: stmt_complexity (stmt) ! 78: tree stmt; ! 79: { ! 80: register tree s; ! 81: register int c = 0; ! 82: for (s = stmt; s; s = TREE_CHAIN (s)) ! 83: switch (TREE_CODE (s)) ! 84: { ! 85: case LABEL_STMT: ! 86: break; ! 87: ! 88: case COMPOUND_STMT: ! 89: c += stmt_complexity (STMT_BODY (s)); ! 90: break; ! 91: ! 92: case LOOP_STMT: ! 93: c += 1 + stmt_complexity (STMT_BODY (s)); ! 94: break; ! 95: ! 96: case EXIT_STMT: ! 97: c += 2; ! 98: break; ! 99: ! 100: case GOTO_STMT: ! 101: case ASM_STMT: ! 102: c += 1; ! 103: break; ! 104: ! 105: case IF_STMT: ! 106: c += 2 + stmt_complexity (STMT_THEN (s)) ! 107: + stmt_complexity (STMT_ELSE (s)); ! 108: break; ! 109: ! 110: case EXPR_STMT: ! 111: case RETURN_STMT: ! 112: c += 3; ! 113: break; ! 114: ! 115: /* The body of the case statement is actually not included ! 116: in the CASE_STMT, so it will be counted separately. */ ! 117: case CASE_STMT: ! 118: c += 3; ! 119: break; ! 120: ! 121: case LET_STMT: ! 122: case WITH_STMT: ! 123: c += list_length (STMT_VARS (s)) + stmt_complexity (STMT_BODY (s)); ! 124: break; ! 125: ! 126: default: abort (); ! 127: } ! 128: return c; ! 129: } ! 130: ! 131: static void expand_stmt (); ! 132: static void expand_stmts (); ! 133: static void expand_case_stmt (); ! 134: ! 135: /* Set nonzero at beginning of function ! 136: to prevent output of the NOTE_INSN_BLOCK_BEG for the outermost block. ! 137: This is because `final' generates it specially, ! 138: before the function prologue. */ ! 139: ! 140: static int inhibit_block_beg; ! 141: ! 142: /* Return the rtx-label that corresponds to a LABEL_DECL, ! 143: creating it if necessary. */ ! 144: ! 145: static rtx ! 146: label_rtx (label) ! 147: tree label; ! 148: { ! 149: if (DECL_RTL (label)) ! 150: return DECL_RTL (label); ! 151: ! 152: return DECL_RTL (label) = gen_label_rtx (); ! 153: } ! 154: ! 155: /* Add an unconditional jump to LABEL as the next sequential instruction. */ ! 156: ! 157: void ! 158: emit_jump (label) ! 159: rtx label; ! 160: { ! 161: do_pending_stack_adjust (); ! 162: emit_jump_insn (gen_jump (label)); ! 163: emit_barrier (); ! 164: } ! 165: ! 166: /* Return nonzero if T is a "simple enough" expression ! 167: such that we prefer to duplicate it as a loop exit condition. ! 168: We accept only comparisons whose operands are constants or variables. */ ! 169: ! 170: static int ! 171: exit_simple_enough_p (t) ! 172: tree t; ! 173: { ! 174: register enum tree_code code = TREE_CODE (t); ! 175: register tree op; ! 176: if (!(code == EQ_EXPR || code == NE_EXPR ! 177: || code == LT_EXPR || code == LE_EXPR ! 178: || code == GT_EXPR || code == GE_EXPR)) ! 179: return 0; ! 180: op = TREE_OPERAND (t, 0); ! 181: if (TREE_CODE (op) != VAR_DECL ! 182: && TREE_CODE (op) != INTEGER_CST ! 183: && TREE_CODE (op) != REAL_CST) ! 184: return 0; ! 185: op = TREE_OPERAND (t, 1); ! 186: if (TREE_CODE (op) != VAR_DECL ! 187: && TREE_CODE (op) != INTEGER_CST ! 188: && TREE_CODE (op) != REAL_CST) ! 189: return 0; ! 190: return 1; ! 191: } ! 192: ! 193: /* Generate rtl code for a sequence of statements ! 194: chained through the TREE_CHAIN. ! 195: LOOP_EXIT says where an EXIT_STMT should jump to. */ ! 196: ! 197: static void ! 198: expand_stmts (stmts, loop_exit) ! 199: tree stmts; ! 200: rtx loop_exit; ! 201: { ! 202: register tree stmt; ! 203: for (stmt = stmts; stmt; stmt = TREE_CHAIN (stmt)) ! 204: expand_stmt (stmt, loop_exit); ! 205: } ! 206: ! 207: /* Generate rtl for one statement, STMT. ! 208: LOOP_EXIT is an rtl CODE_LABEL to jump to to exit a loop. */ ! 209: ! 210: /* Stack of LET_STMT blocks that we are currently within ! 211: during the rtl-generation tree walk. */ ! 212: ! 213: struct block_stack ! 214: { ! 215: tree block; /* the LET_STMT tree node */ ! 216: rtx stack_level; /* the saved-on-entry stack pointer */ ! 217: struct block_stack *next; /* data for the containing LET_STMT or 0 */ ! 218: }; ! 219: ! 220: struct block_stack *block_stack; ! 221: ! 222: static void ! 223: expand_stmt (stmt, loop_exit) ! 224: tree stmt; ! 225: rtx loop_exit; ! 226: { ! 227: struct block_stack thisblock; ! 228: ! 229: if (STMT_SOURCE_LINE (stmt) != 0) ! 230: emit_note (STMT_SOURCE_FILE (stmt), STMT_SOURCE_LINE (stmt)); ! 231: ! 232: switch (TREE_CODE (stmt)) ! 233: { ! 234: case LABEL_STMT: ! 235: do_pending_stack_adjust (); ! 236: emit_label (label_rtx (STMT_BODY (stmt))); ! 237: break; ! 238: ! 239: case GOTO_STMT: ! 240: if (GET_CODE (label_rtx (STMT_BODY (stmt))) != CODE_LABEL) ! 241: abort (); ! 242: /* Look at the binding contours (LET_STMTs) we are jumping out of ! 243: and if any of them allocates a variable size auto variable ! 244: reset the stack to the appropriate level. */ ! 245: { ! 246: tree context = DECL_CONTEXT (STMT_BODY (stmt)); ! 247: struct block_stack *block; ! 248: rtx stack_level = 0; ! 249: ! 250: /* Chase contexts up from the target label. */ ! 251: while (context) ! 252: { ! 253: /* Chase contexts up from where we are. ! 254: We want the innermost block containing both ! 255: the goto and the label. */ ! 256: for (block = block_stack; block; ! 257: block = block->next) ! 258: { ! 259: if (block->stack_level != 0) ! 260: stack_level = block->stack_level; ! 261: if (block->block == context) ! 262: { ! 263: if (stack_level != 0) ! 264: emit_move_insn (gen_rtx (REG, Pmode, ! 265: STACK_POINTER_REGNUM), ! 266: stack_level); ! 267: goto context_done; ! 268: } ! 269: } ! 270: context = STMT_SUPERCONTEXT (context); ! 271: } ! 272: context_done: ; ! 273: } ! 274: emit_jump (label_rtx (STMT_BODY (stmt))); ! 275: break; ! 276: ! 277: case EXPR_STMT: ! 278: expand_expr (STMT_BODY (stmt), 0, VOIDmode, 0); ! 279: break; ! 280: ! 281: case COMPOUND_STMT: ! 282: expand_stmts (STMT_BODY (stmt), loop_exit); ! 283: break; ! 284: ! 285: case ASM_STMT: ! 286: emit_insn (gen_rtx (ASM_INPUT, VOIDmode, ! 287: TREE_STRING_POINTER (STMT_BODY (stmt)))); ! 288: break; ! 289: ! 290: case IF_STMT: ! 291: { ! 292: register rtx afterlabel = gen_label_rtx (); ! 293: ! 294: /* Simpler handling if there is no else-part ! 295: or a null then-part. */ ! 296: if (STMT_THEN (stmt) == 0) ! 297: { ! 298: do_jump (STMT_COND (stmt), NULL, afterlabel); ! 299: expand_stmts (STMT_ELSE (stmt), loop_exit); ! 300: } ! 301: else if (STMT_ELSE (stmt) == 0) ! 302: { ! 303: do_jump (STMT_COND (stmt), afterlabel, NULL); ! 304: expand_stmts (STMT_THEN (stmt), loop_exit); ! 305: } ! 306: else ! 307: { ! 308: register rtx elselabel = gen_label_rtx (); ! 309: ! 310: do_jump (STMT_COND (stmt), elselabel, NULL); ! 311: expand_stmts (STMT_THEN (stmt), loop_exit); ! 312: emit_jump (afterlabel); ! 313: emit_label (elselabel); ! 314: expand_stmts (STMT_ELSE (stmt), loop_exit); ! 315: } ! 316: do_pending_stack_adjust (); ! 317: emit_label (afterlabel); ! 318: } ! 319: break; ! 320: ! 321: case EXIT_STMT: ! 322: /* Exit if the condition is false. */ ! 323: do_jump (STMT_BODY (stmt), loop_exit, NULL); ! 324: break; ! 325: ! 326: case RETURN_STMT: ! 327: if (STMT_BODY (stmt)) ! 328: { ! 329: register rtx val = 0; ! 330: register rtx op0; ! 331: /* For tail-recursive call to current function, ! 332: just jump back to the beginning. ! 333: It's unsafe if any auto variable in this function ! 334: has its address taken; for simplicity, ! 335: require stack frame to be empty. */ ! 336: if (! cse_not_expected ! 337: && frame_offset == 0 ! 338: && TREE_CODE (STMT_BODY (stmt)) == MODIFY_EXPR ! 339: && TREE_CODE (TREE_OPERAND (STMT_BODY (stmt), 1)) == CALL_EXPR ! 340: && TREE_CODE (TREE_OPERAND (TREE_OPERAND (STMT_BODY (stmt), 1), 0)) == ADDR_EXPR ! 341: && TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (STMT_BODY (stmt), 1), 0), 0) == this_function ! 342: /* Finish checking validity, and if valid emit code ! 343: to set the argument variables for the new call. */ ! 344: && tail_recursion_args (TREE_OPERAND (TREE_OPERAND (STMT_BODY (stmt), 1), 1), ! 345: DECL_ARGUMENTS (this_function))) ! 346: { ! 347: ; ! 348: if (tail_recursion_label == 0) ! 349: { ! 350: tail_recursion_label = gen_label_rtx (); ! 351: emit_label_after (tail_recursion_label, ! 352: tail_recursion_reentry); ! 353: } ! 354: emit_jump (tail_recursion_label); ! 355: emit_barrier (); ! 356: break; ! 357: } ! 358: #ifndef FUNCTION_EPILOGUE ! 359: /* If this is return x == y; then generate ! 360: if (x == y) return 1; else return 0; ! 361: if we can do it with explicit return insns. */ ! 362: if (TREE_CODE (STMT_BODY (stmt)) == MODIFY_EXPR) ! 363: switch (TREE_CODE (TREE_OPERAND (STMT_BODY (stmt), 1))) ! 364: { ! 365: case EQ_EXPR: ! 366: case NE_EXPR: ! 367: case GT_EXPR: ! 368: case GE_EXPR: ! 369: case LT_EXPR: ! 370: case LE_EXPR: ! 371: case TRUTH_ANDIF_EXPR: ! 372: case TRUTH_ORIF_EXPR: ! 373: case TRUTH_NOT_EXPR: ! 374: op0 = gen_label_rtx (); ! 375: val = DECL_RTL (DECL_RESULT (this_function)); ! 376: jumpifnot (TREE_OPERAND (STMT_BODY (stmt), 1), op0); ! 377: emit_move_insn (val, const1_rtx); ! 378: emit_insn (gen_rtx (USE, VOIDmode, val)); ! 379: emit_jump_insn (gen_return ()); ! 380: emit_barrier (); ! 381: emit_label (op0); ! 382: emit_move_insn (val, const0_rtx); ! 383: emit_insn (gen_rtx (USE, VOIDmode, val)); ! 384: emit_jump_insn (gen_return ()); ! 385: emit_barrier (); ! 386: } ! 387: if (val != 0) ! 388: break; ! 389: #endif ! 390: val = expand_expr (STMT_BODY (stmt), 0, VOIDmode, 0); ! 391: if (GET_CODE (val) == REG) ! 392: emit_insn (gen_rtx (USE, VOIDmode, val)); ! 393: emit_queue (); ! 394: } ! 395: /* Return insn or function epilogue ignore the stack pointer. */ ! 396: clear_pending_stack_adjust (); ! 397: #ifdef FUNCTION_EPILOGUE ! 398: emit_jump (return_label); ! 399: #else ! 400: emit_jump_insn (gen_return ()); ! 401: #endif ! 402: emit_barrier (); ! 403: break; ! 404: ! 405: case LET_STMT: ! 406: { ! 407: rtx oldstack = 0; ! 408: register tree decl; ! 409: ! 410: /* Make an entry on BLOCK_STACK for the block we are entering. */ ! 411: ! 412: thisblock.block = stmt; ! 413: thisblock.next = block_stack; ! 414: thisblock.stack_level = 0; ! 415: block_stack = &thisblock; ! 416: ! 417: /* Output a NOTE to mark the beginning of the scope, ! 418: except when inhibited (for a function's outermost block). */ ! 419: ! 420: if (inhibit_block_beg) ! 421: inhibit_block_beg = 0; ! 422: else ! 423: emit_note (0, NOTE_INSN_BLOCK_BEG); ! 424: ! 425: if (reg_birth_insn) ! 426: { ! 427: /* If doing stupid register allocation, ! 428: mark all register variables of this block ! 429: as beginning life here. */ ! 430: ! 431: register rtx last_insn = get_last_insn (); ! 432: ! 433: for (decl = STMT_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! 434: { ! 435: if (TREE_CODE (decl) == VAR_DECL ! 436: && DECL_RTL (decl) != 0 ! 437: && GET_CODE (DECL_RTL (decl)) == REG) ! 438: reg_birth_insn[REGNO (DECL_RTL (decl))] = last_insn; ! 439: } ! 440: } ! 441: ! 442: /* Allocate space for all variable-size variables, ! 443: and set OLDSTACK nonzero if there are any. */ ! 444: for (decl = STMT_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! 445: if (TREE_CODE (decl) == VAR_DECL ! 446: && !TREE_LITERAL (DECL_SIZE (decl))) ! 447: { ! 448: rtx address, size; ! 449: ! 450: if (oldstack == 0) ! 451: { ! 452: do_pending_stack_adjust (); ! 453: oldstack = copy_to_reg (gen_rtx (REG, Pmode, ! 454: STACK_POINTER_REGNUM)); ! 455: thisblock.stack_level = oldstack; ! 456: } ! 457: size = expand_expr (DECL_SIZE (decl), 0, VOIDmode, 0); ! 458: #ifdef STACK_GROWS_DOWNWARD ! 459: anti_adjust_stack (size); ! 460: #endif ! 461: address = copy_to_reg (gen_rtx (REG, Pmode, ! 462: STACK_POINTER_REGNUM)); ! 463: #ifndef STACK_GROWS_DOWNWARD ! 464: anti_adjust_stack (size); ! 465: #endif ! 466: DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address); ! 467: } ! 468: ! 469: /* Compute and store the initial values ! 470: of all nonstatic variables bound here. */ ! 471: for (decl = STMT_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! 472: if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl) ! 473: && ! TREE_STATIC (decl)) ! 474: { ! 475: if (DECL_VOFFSET (decl) ! 476: || !TREE_LITERAL (DECL_SIZE (decl))) ! 477: abort (); ! 478: emit_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); ! 479: expand_assignment (decl, DECL_INITIAL (decl)); ! 480: } ! 481: ! 482: /* Generate code for the body of the block. */ ! 483: ! 484: expand_stmts (STMT_BODY (stmt), 0); ! 485: ! 486: /* Mark the end of the scope. */ ! 487: ! 488: emit_note (0, NOTE_INSN_BLOCK_END); ! 489: ! 490: if (reg_death_insn) ! 491: { ! 492: /* If doing stupid register allocation, ! 493: mark all register variables of this block ! 494: as having just died. */ ! 495: register rtx last_insn = get_last_insn (); ! 496: ! 497: for (decl = STMT_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! 498: { ! 499: if (TREE_CODE (decl) == VAR_DECL ! 500: && DECL_RTL (decl) != 0 ! 501: && GET_CODE (DECL_RTL (decl)) == REG) ! 502: reg_death_insn[REGNO (DECL_RTL (decl))] = last_insn; ! 503: } ! 504: } ! 505: ! 506: /* Restore stack level in effect before the block ! 507: (only if variable-size objects allocated). */ ! 508: ! 509: if (oldstack != 0) ! 510: emit_move_insn (gen_rtx (REG, Pmode, ! 511: STACK_POINTER_REGNUM), ! 512: oldstack); ! 513: ! 514: /* Restore block_stack level for containing block. */ ! 515: ! 516: block_stack = thisblock.next; ! 517: } ! 518: break; ! 519: ! 520: case LOOP_STMT: ! 521: { ! 522: register rtx lab1, lab2; ! 523: register tree x1 = tree_last (STMT_BODY (stmt)); ! 524: ! 525: /* There are several ways to arrange the compilation of a loop. ! 526: We choose one depending on where the exits are and what kinds ! 527: of conditions they test. */ ! 528: ! 529: lab1 = gen_label_rtx (); ! 530: lab2 = gen_label_rtx (); ! 531: ! 532: /* If the body ends with a conditional exit or goto, ! 533: just compile it straight through. The conditional at the end ! 534: will combine with the branch back. */ ! 535: if (TREE_CODE (x1) == EXIT_STMT ! 536: || (TREE_CODE (x1) == IF_STMT ! 537: && (TREE_CODE (STMT_THEN (x1)) == GOTO_STMT ! 538: || (STMT_ELSE (x1) ! 539: && TREE_CODE (STMT_ELSE (x1)) == GOTO_STMT)))) ! 540: { ! 541: do_pending_stack_adjust (); ! 542: emit_note (0, NOTE_INSN_LOOP_BEG); ! 543: emit_label (lab1); ! 544: expand_stmts (STMT_BODY (stmt), lab2); ! 545: emit_jump (lab1); ! 546: } ! 547: #if 0 ! 548: /* If the loop starts with a conditional exit that tests ! 549: a very simple condition, duplicate the test, jumping around ! 550: the loop if we don't want to execute it even once. ! 551: Then put the test at the end of the loop. */ ! 552: else if (! cse_not_expected ! 553: && TREE_CODE (STMT_BODY (stmt)) == EXIT_STMT ! 554: && stmt_complexity (stmt) < 15 ! 555: && exit_simple_enough_p (STMT_BODY (STMT_BODY (stmt)))) ! 556: { ! 557: do_jump (STMT_BODY (STMT_BODY (stmt)), lab2, 0); ! 558: emit_note (0, NOTE_INSN_LOOP_BEG); ! 559: emit_label (lab1); ! 560: expand_stmts (TREE_CHAIN (STMT_BODY (stmt)), lab2); ! 561: do_jump (STMT_BODY (STMT_BODY (stmt)), 0, lab1); ! 562: } ! 563: #endif ! 564: /* If the loop starts with a conditional exit that tests ! 565: a very simple condition, put that exit at the end of the loop ! 566: and enter by jumping to that test. */ ! 567: else if (! cse_not_expected ! 568: && TREE_CODE (STMT_BODY (stmt)) == EXIT_STMT) ! 569: { ! 570: register rtx lab3 = gen_label_rtx (); ! 571: do_pending_stack_adjust (); ! 572: emit_note (0, NOTE_INSN_LOOP_BEG); ! 573: emit_jump (lab3); ! 574: emit_label (lab1); ! 575: expand_stmts (TREE_CHAIN (STMT_BODY (stmt)), lab2); ! 576: do_pending_stack_adjust (); ! 577: emit_label (lab3); ! 578: do_jump (STMT_BODY (STMT_BODY (stmt)), 0, lab1); ! 579: } ! 580: /* Neither starts nor ends with a conditional exit. Strange. ! 581: Do it the simplest possible way. */ ! 582: else ! 583: { ! 584: do_pending_stack_adjust (); ! 585: emit_note (0, NOTE_INSN_LOOP_BEG); ! 586: emit_label (lab1); ! 587: expand_stmts (STMT_BODY (stmt), lab2); ! 588: emit_jump (lab1); ! 589: } ! 590: ! 591: emit_note (0, NOTE_INSN_LOOP_END); ! 592: emit_label (lab2); ! 593: } ! 594: break; ! 595: ! 596: case CASE_STMT: ! 597: expand_case_stmt (stmt); ! 598: break; ! 599: ! 600: default: ! 601: abort (); ! 602: } ! 603: ! 604: /* Perform any postincrements or postdecrements. */ ! 605: ! 606: emit_queue (); ! 607: } ! 608: ! 609: /* Emit code to alter this function's formal parms for a tail-recursive call. ! 610: ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs). ! 611: FORMALS is the chain of decls of formals. ! 612: Return 1 if this can be done; ! 613: otherwise return 0 and do not emit any code. */ ! 614: ! 615: static int ! 616: tail_recursion_args (actuals, formals) ! 617: tree actuals, formals; ! 618: { ! 619: register tree a = actuals, f = formals; ! 620: register int i; ! 621: register rtx *argvec; ! 622: ! 623: /* Check that number and types of actuals are compatible ! 624: with the formals. This is not always true in valid C code. ! 625: Also check that no formal needs to be addressable ! 626: and that all formals are scalars. */ ! 627: ! 628: /* Also count the args. */ ! 629: ! 630: for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++) ! 631: { ! 632: if (TREE_TYPE (TREE_VALUE (a)) != TREE_TYPE (f)) ! 633: return 0; ! 634: if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode) ! 635: return 0; ! 636: } ! 637: if (a != 0 || f != 0) ! 638: return 0; ! 639: ! 640: /* Compute all the actuals. */ ! 641: ! 642: argvec = (rtx *) alloca (i * sizeof (rtx)); ! 643: ! 644: for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++) ! 645: argvec[i] = expand_expr (TREE_VALUE (a), 0, VOIDmode, 0); ! 646: ! 647: /* Find which actual values refer to current values of previous formals. ! 648: Copy each of them now, before any formal is changed. */ ! 649: ! 650: for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++) ! 651: { ! 652: int copy = 0; ! 653: register int j; ! 654: for (f = formals, j = 0; j < i; f = TREE_CHAIN (f), j++) ! 655: if (reg_mentioned_p (DECL_RTL (f), argvec[i])) ! 656: { copy = 1; break; } ! 657: if (copy) ! 658: argvec[i] = copy_to_reg (argvec[i]); ! 659: } ! 660: ! 661: /* Store the values of the actuals into the formals. */ ! 662: ! 663: for (f = formals, i = 0; f; f = TREE_CHAIN (f), i++) ! 664: { ! 665: if (DECL_MODE (f) == GET_MODE (argvec[i])) ! 666: emit_move_insn (DECL_RTL (f), argvec[i]); ! 667: else ! 668: convert_move (DECL_RTL (f), argvec[i]); ! 669: } ! 670: ! 671: return 1; ! 672: } ! 673: ! 674: /* Generate code for a CASE_STMT node, ! 675: which stands for a dispatch table. */ ! 676: ! 677: static void ! 678: expand_case_stmt (stmt) ! 679: tree stmt; ! 680: { ! 681: tree minval, maxval, range; ! 682: rtx default_label = 0; ! 683: register tree elt; ! 684: register tree c; ! 685: int count; ! 686: tree index_exp; ! 687: rtx index; ! 688: rtx table_label = gen_label_rtx (); ! 689: int ncases; ! 690: rtx *labelvec; ! 691: register int i; ! 692: ! 693: /* Get upper and lower bounds of case values. */ ! 694: count = 0; ! 695: for (c = STMT_CASE_LIST (stmt); c; c = TREE_CHAIN (c)) ! 696: if (elt = TREE_PURPOSE (c)) ! 697: { ! 698: /* Note that in Pascal it will be possible ! 699: to have a RANGE_EXPR here as long as both ! 700: ends of the range are constant. ! 701: It will be necessary to extend this function ! 702: to handle them. */ ! 703: if (TREE_CODE (elt) != INTEGER_CST) ! 704: abort (); ! 705: ! 706: if (count++ == 0) ! 707: { ! 708: minval = maxval = elt; ! 709: } ! 710: else ! 711: { ! 712: if (INT_CST_LT (elt, minval)) ! 713: minval = elt; ! 714: if (INT_CST_LT (maxval, elt)) ! 715: maxval = elt; ! 716: } ! 717: } ! 718: else ! 719: default_label = label_rtx (TREE_VALUE (c)); ! 720: ! 721: if (default_label == 0) ! 722: abort (); ! 723: ! 724: /* Compute span of values. */ ! 725: range = combine (MINUS_EXPR, maxval, minval); ! 726: ! 727: /* If range of values is much bigger than number of values, ! 728: make a sequence of conditional branches instead of a dispatch. */ ! 729: if (TREE_INT_CST_HIGH (range) != 0 ! 730: #ifdef HAVE_casesi ! 731: || count < 4 ! 732: #else ! 733: /* If machine does not have a case insn that compares the ! 734: bounds, this means extra overhead for dispatch tables ! 735: which raises the threshold for using them. */ ! 736: || count < 7 ! 737: #endif ! 738: || TREE_INT_CST_LOW (range) > 10 * count) ! 739: { ! 740: index_exp = get_unwidened (STMT_CASE_INDEX (stmt), 0); ! 741: index = expand_expr (index_exp, 0, VOIDmode, 0); ! 742: emit_queue (); ! 743: ! 744: index = protect_from_queue (index, 0); ! 745: if (GET_CODE (index) == MEM) ! 746: index = copy_to_reg (index); ! 747: do_pending_stack_adjust (); ! 748: ! 749: for (c = STMT_CASE_LIST (stmt); c; c = TREE_CHAIN (c)) ! 750: if ((elt = TREE_PURPOSE (c)) ! 751: && int_fits_type_p (elt, TREE_TYPE (index_exp))) ! 752: do_jump_if_equal (expand_expr (elt, 0, VOIDmode, 0), index, ! 753: label_rtx (TREE_VALUE (c))); ! 754: ! 755: emit_jump (default_label); ! 756: return; ! 757: } ! 758: ! 759: index_exp = STMT_CASE_INDEX (stmt); ! 760: ! 761: #ifdef HAVE_casesi ! 762: if (TYPE_MODE (TREE_TYPE (index_exp)) == DImode) ! 763: { ! 764: index_exp = build2 (MINUS_EXPR, index_exp, minval); ! 765: TREE_TYPE (index_exp) = TREE_TYPE (STMT_CASE_INDEX (stmt)); ! 766: index_exp = convert (integer_type_node, index_exp); ! 767: minval = integer_zero_node; ! 768: } ! 769: else if (TYPE_MODE (TREE_TYPE (index_exp)) != SImode) ! 770: index_exp = convert (integer_type_node, index_exp); ! 771: index = expand_expr (index_exp, 0, VOIDmode, 0); ! 772: emit_queue (); ! 773: index = protect_from_queue (index, 0); ! 774: do_pending_stack_adjust (); ! 775: ! 776: emit_jump_insn (gen_casesi (index, expand_expr (minval, 0, VOIDmode, 0), ! 777: expand_expr (range, 0, VOIDmode, 0), ! 778: table_label)); ! 779: #else ! 780: #ifdef HAVE_tablejump ! 781: index_exp = build2 (MINUS_EXPR, index_exp, minval); ! 782: TREE_TYPE (index_exp) = TREE_TYPE (STMT_CASE_INDEX (stmt)); ! 783: index_exp = convert (integer_type_node, index_exp); ! 784: index = expand_expr (index_exp, 0, VOIDmode, 0); ! 785: emit_queue (); ! 786: index = protect_from_queue (index, 0); ! 787: do_pending_stack_adjust (); ! 788: ! 789: do_tablejump (index, ! 790: gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (range)), ! 791: table_label, default_label); ! 792: #else ! 793: lossage; ! 794: #endif /* not HAVE_tablejump */ ! 795: #endif /* not HAVE_casesi */ ! 796: ! 797: /* Get table of labels to jump to, in order of case index. */ ! 798: ! 799: ncases = TREE_INT_CST_LOW (range) + 1; ! 800: labelvec = (rtx *) alloca (ncases * sizeof (rtx)); ! 801: bzero (labelvec, ncases * sizeof (rtx)); ! 802: ! 803: for (c = STMT_CASE_LIST (stmt); c; c = TREE_CHAIN (c)) ! 804: if (elt = TREE_PURPOSE (c)) ! 805: { ! 806: register int i = TREE_INT_CST_LOW (elt) - TREE_INT_CST_LOW (minval); ! 807: labelvec[i] = gen_rtx (LABEL_REF, Pmode, label_rtx (TREE_VALUE (c))); ! 808: } ! 809: ! 810: /* Fill in the gaps with the default. */ ! 811: for (i = 0; i < ncases; i++) ! 812: if (labelvec[i] == 0) ! 813: labelvec[i] = gen_rtx (LABEL_REF, Pmode, default_label); ! 814: ! 815: /* Output the table */ ! 816: emit_label (table_label); ! 817: ! 818: #ifdef CASE_VECTOR_PC_RELATIVE ! 819: emit_jump_insn (gen_rtx (ADDR_DIFF_VEC, CASE_VECTOR_MODE, ! 820: gen_rtx (LABEL_REF, Pmode, table_label), ! 821: gen_rtvec_v (ncases, labelvec))); ! 822: #else ! 823: emit_jump_insn (gen_rtx (ADDR_VEC, CASE_VECTOR_MODE, ! 824: gen_rtvec_v (ncases, labelvec))); ! 825: #endif ! 826: emit_jump (default_label); ! 827: } ! 828: ! 829: /* Find all the variables declared within a function ! 830: and give them rtl definitions. */ ! 831: ! 832: /* Return size needed for stack frame based on slots so far allocated. */ ! 833: ! 834: int ! 835: get_frame_size () ! 836: { ! 837: return frame_offset; ! 838: } ! 839: ! 840: /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it ! 841: with machine mode MODE. */ ! 842: ! 843: rtx ! 844: assign_stack_local (mode, size) ! 845: enum machine_mode mode; ! 846: int size; ! 847: { ! 848: register rtx value; ! 849: ! 850: /* This function may not be used during rtl generation ! 851: because at that time space is being allocated for ! 852: structure values returned by function calls, ! 853: but we don't know how big the space is until the end ! 854: of rtl generation. */ ! 855: if (max_structure_value_size > 0) ! 856: abort (); ! 857: ! 858: /* Make each stack slot a multiple of the main allocation unit. */ ! 859: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) ! 860: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)) ! 861: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 862: ! 863: #ifdef FRAME_GROWS_DOWNWARD ! 864: frame_offset -= size; ! 865: #endif ! 866: value = gen_rtx (MEM, mode, ! 867: gen_rtx (PLUS, Pmode, ! 868: gen_rtx (REG, SImode, FRAME_POINTER_REGNUM), ! 869: gen_rtx (CONST_INT, VOIDmode, frame_offset))); ! 870: #ifndef FRAME_GROWS_DOWNWARD ! 871: frame_offset += size; ! 872: #endif ! 873: ! 874: return value; ! 875: } ! 876: ! 877: /* 1 + last pseudo register number used for one of the user's variables ! 878: (as opposed to compiler-generated temporaries). */ ! 879: ! 880: int first_temp_reg_num; ! 881: ! 882: static void assign_vars_1 (); ! 883: ! 884: /* Assign stack slots or pseudo-registers to all the variables ! 885: local to the body of a function being compiled (STMT). */ ! 886: ! 887: static void ! 888: assign_all_vars (stmt) ! 889: tree stmt; ! 890: { ! 891: frame_offset = STARTING_FRAME_OFFSET; ! 892: assign_vars_1 (stmt); ! 893: first_temp_reg_num = max_reg_num (); ! 894: } ! 895: ! 896: /* Assign stack slots or pseudo-registers to all the identifiers ! 897: local within STMT, by recursive tree walk, except for variables ! 898: of varying size. */ ! 899: ! 900: static void ! 901: assign_vars_1 (stmt) ! 902: register tree stmt; ! 903: { ! 904: register tree decl; ! 905: ! 906: while (stmt) ! 907: { ! 908: switch (TREE_CODE (stmt)) ! 909: { ! 910: case COMPOUND_STMT: ! 911: case LOOP_STMT: ! 912: assign_vars_1 (STMT_BODY (stmt)); ! 913: break; ! 914: ! 915: case IF_STMT: ! 916: assign_vars_1 (STMT_THEN (stmt)); ! 917: assign_vars_1 (STMT_ELSE (stmt)); ! 918: break; ! 919: ! 920: case LET_STMT: ! 921: for (decl = STMT_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! 922: { ! 923: if (TREE_TYPE (decl) == error_mark_node) ! 924: DECL_RTL (decl) = gen_rtx (MEM, BLKmode, const0_rtx); ! 925: else if (TREE_CODE (decl) == FUNCTION_DECL) ! 926: /* External function */ ! 927: DECL_RTL (decl) ! 928: = gen_rtx (MEM, FUNCTION_MODE, ! 929: gen_rtx (SYMBOL_REF, Pmode, ! 930: IDENTIFIER_POINTER (DECL_NAME (decl)))); ! 931: else if (TREE_CODE (decl) != VAR_DECL) ! 932: ; ! 933: else if (TREE_STATIC (decl) || TREE_EXTERNAL (decl)) ! 934: ; /* These were done by assemble_variable. */ ! 935: else if (DECL_MODE (decl) != BLKmode ! 936: && ! TREE_VOLATILE (decl) ! 937: && ! TREE_ADDRESSABLE (decl) ! 938: && (TREE_REGDECL (decl) || ! obey_regdecls)) ! 939: { ! 940: /* Variable that can go in a register. */ ! 941: DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); ! 942: if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE) ! 943: mark_reg_pointer (DECL_RTL (decl)); ! 944: } ! 945: else if (TREE_LITERAL (DECL_SIZE (decl))) ! 946: /* Variable of fixed size that goes on the stack. */ ! 947: DECL_RTL (decl) ! 948: = assign_stack_local (DECL_MODE (decl), ! 949: (TREE_INT_CST_LOW (DECL_SIZE (decl)) ! 950: * DECL_SIZE_UNIT (decl) ! 951: + BITS_PER_UNIT - 1) ! 952: / BITS_PER_UNIT); ! 953: /* Rtl for a dynamic-size object is set up when ! 954: the storage for the object is pushed. */ ! 955: ! 956: } ! 957: assign_vars_1 (STMT_BODY (stmt)); ! 958: } ! 959: stmt = TREE_CHAIN (stmt); ! 960: } ! 961: } ! 962: ! 963: /* 1 + last pseudo register number used for loading a copy ! 964: of a parameter of this function. */ ! 965: ! 966: static int max_parm_reg; ! 967: ! 968: /* Assign RTL expressions to the function's parameters. ! 969: This may involve copying them into registers and using ! 970: those registers as the RTL for them. */ ! 971: ! 972: static void ! 973: assign_parms (fndecl) ! 974: tree fndecl; ! 975: { ! 976: register tree parm; ! 977: register rtx parmloc; ! 978: register int i; ! 979: ! 980: for (parm = DECL_ARGUMENTS (fndecl), i = 0; parm; parm = TREE_CHAIN (parm), i++) ! 981: { ! 982: if (DECL_VOFFSET (parm)) ! 983: abort (); ! 984: if (TREE_TYPE (parm) == error_mark_node) ! 985: parmloc = gen_rtx (MEM, BLKmode, const0_rtx); ! 986: else ! 987: parmloc ! 988: = gen_rtx (MEM, TYPE_MODE (DECL_ARG_TYPE (parm)), ! 989: gen_rtx (PLUS, SImode, ! 990: gen_rtx (REG, SImode, ARG_POINTER_REGNUM), ! 991: gen_rtx (CONST_INT, VOIDmode, ! 992: DECL_OFFSET (parm) / BITS_PER_UNIT))); ! 993: ! 994: /* PARMLOC now refers to the parameter in the arglist ! 995: in the form in which it is passed. ! 996: Now output code if necessary to convert it to ! 997: the type in which this function declares it, ! 998: and store a reference to that value in DECL_RTL. ! 999: This reference may be the same as PARMLOC ! 1000: if no conversion is required. */ ! 1001: ! 1002: if (GET_MODE (parmloc) == BLKmode) ! 1003: DECL_RTL (parm) = parmloc; ! 1004: else if (! (TREE_ADDRESSABLE (parm) ! 1005: || (obey_regdecls && ! TREE_REGDECL (parm)))) ! 1006: { ! 1007: /* Store the parm in a register during the function. */ ! 1008: register rtx parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm))); ! 1009: ! 1010: DECL_RTL (parm) = parmreg; ! 1011: ! 1012: /* Copy the value into the register. */ ! 1013: if (GET_MODE (parmreg) != GET_MODE (parmloc)) ! 1014: convert_move (parmreg, parmloc, 0); ! 1015: else ! 1016: emit_move_insn (parmreg, parmloc); ! 1017: ! 1018: /* Mark the register as eliminable if we did no conversion. */ ! 1019: if (GET_MODE (parmreg) == GET_MODE (parmloc)) ! 1020: REG_NOTES (get_last_insn ()) = gen_rtx (EXPR_LIST, REG_CONST, ! 1021: parmreg, 0); ! 1022: ! 1023: /* For pointer data type, suggest pointer register. */ ! 1024: if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE) ! 1025: mark_reg_pointer (parmreg); ! 1026: } ! 1027: else if (GET_MODE (parmloc) != TYPE_MODE (TREE_TYPE (parm))) ! 1028: { ! 1029: /* Don't store in a register, but conversion is required. ! 1030: Convert it via a register and store back in the parm list ! 1031: in the new format. The debugger will expect this anyway. */ ! 1032: ! 1033: register rtx parmlcl ! 1034: = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (parm)), ! 1035: copy_rtx (XEXP (parmloc, 0))); ! 1036: register rtx parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm))); ! 1037: ! 1038: convert_move (parmreg, parmloc, 0); ! 1039: emit_move_insn (parmlcl, parmreg); ! 1040: DECL_RTL (parm) = parmlcl; ! 1041: } ! 1042: else ! 1043: DECL_RTL (parm) = parmloc; ! 1044: } ! 1045: max_parm_reg = max_reg_num (); ! 1046: } ! 1047: ! 1048: /* Allocation of space for returned structure values. ! 1049: During the rtl generation pass, `get_structure_value_addr' ! 1050: is called from time to time to request the address of a block in our ! 1051: stack frame in which called functions will store the structures ! 1052: they are returning. The same space is used for all of these blocks. ! 1053: ! 1054: `get_structure_value_addr' records the maximum block size needed. ! 1055: ! 1056: At the end of generation `allocate_structure_value_space' is ! 1057: called to adjust `frame_offset' so that the needed space is allocated. */ ! 1058: ! 1059: rtx ! 1060: get_structure_value_addr (sizex) ! 1061: rtx sizex; ! 1062: { ! 1063: register int size; ! 1064: if (GET_CODE (sizex) != CONST_INT) ! 1065: abort (); ! 1066: size = INTVAL (sizex); ! 1067: ! 1068: /* Round up to a multiple of the main allocation unit. */ ! 1069: size = (((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) ! 1070: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)) ! 1071: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 1072: ! 1073: if (size > max_structure_value_size) ! 1074: { ! 1075: max_structure_value_size = size; ! 1076: } ! 1077: #ifdef FRAME_GROWS_DOWNWARD ! 1078: return gen_rtx (PLUS, Pmode, ! 1079: gen_rtx (REG, SImode, FRAME_POINTER_REGNUM), ! 1080: gen_rtx (CONST_INT, VOIDmode, frame_offset - size)); ! 1081: #else ! 1082: return gen_rtx (PLUS, Pmode, ! 1083: gen_rtx (REG, SImode, FRAME_POINTER_REGNUM), ! 1084: gen_rtx (CONST_INT, VOIDmode, frame_offset)); ! 1085: #endif ! 1086: } ! 1087: ! 1088: static void ! 1089: allocate_structure_value_space () ! 1090: { ! 1091: #ifdef FRAME_GROWS_DOWNWARD ! 1092: frame_offset -= max_structure_value_size; ! 1093: #else ! 1094: frame_offset += max_structure_value_size; ! 1095: #endif ! 1096: /* Allow `assign_stack_local' to be used once again. */ ! 1097: max_structure_value_size = 0; ! 1098: } ! 1099: ! 1100: /* Main entry point: generate the rtl code for a function SUBR ! 1101: represented as a tree. Returns the first insn. ! 1102: ! 1103: NO_CSE is 1 if cse is not going to be done; ! 1104: this is passed because when cse is to be done it is sometimes ! 1105: desirable to generate excess temporaries at this stage to give ! 1106: cse an opportunity to go to work. */ ! 1107: ! 1108: rtx ! 1109: expand_function (subr, no_cse) ! 1110: tree subr; ! 1111: int no_cse; ! 1112: { ! 1113: register int i; ! 1114: ! 1115: this_function = subr; ! 1116: cse_not_expected = no_cse; ! 1117: ! 1118: init_queue (); ! 1119: ! 1120: #ifdef FUNCTION_EPILOGUE ! 1121: return_label = gen_label_rtx (); ! 1122: #endif ! 1123: ! 1124: max_structure_value_size = 0; ! 1125: ! 1126: /* We are not currently within any block. */ ! 1127: block_stack = 0; ! 1128: tail_recursion_label = 0; ! 1129: ! 1130: clear_pending_stack_adjust (); ! 1131: clear_current_args_size (); ! 1132: ! 1133: /* Prevent ever trying to delete the first instruction of a function. ! 1134: Also tell final how to output a linenum before the function prologue. */ ! 1135: emit_note (DECL_SOURCE_FILE (subr), DECL_SOURCE_LINE (subr)); ! 1136: /* Make sure first insn is a note even if we don't want linenums. ! 1137: This makes sure the first insn will never be deleted. ! 1138: Also, final expects a note to appear there. */ ! 1139: emit_note (0, NOTE_INSN_DELETED); ! 1140: ! 1141: /* Initialize rtx for parameters and local variables. ! 1142: In some cases this requires emitting insns. */ ! 1143: ! 1144: assign_parms (subr); ! 1145: /* After the parm initializations is where the tail-recursion label ! 1146: should go, if we end up needing one. */ ! 1147: tail_recursion_reentry = get_last_insn (); ! 1148: ! 1149: assign_all_vars (DECL_INITIAL (subr)); ! 1150: ! 1151: /* Initialize rtx used to return the value. */ ! 1152: ! 1153: if (DECL_MODE (DECL_RESULT (subr)) == BLKmode) ! 1154: { ! 1155: /* Returning something that won't go in a register. */ ! 1156: register rtx value_address; ! 1157: ! 1158: /* Expect to be passed the address of a place to store the value, ! 1159: in the same register that is normally used to return values. */ ! 1160: value_address = gen_reg_rtx (Pmode); ! 1161: emit_move_insn (value_address, ! 1162: gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM)); ! 1163: DECL_RTL (DECL_RESULT (subr)) ! 1164: = gen_rtx (MEM, DECL_MODE (DECL_RESULT (subr)), ! 1165: value_address); ! 1166: } ! 1167: else ! 1168: DECL_RTL (DECL_RESULT (subr)) ! 1169: = gen_rtx (REG, DECL_MODE (DECL_RESULT (subr)), ! 1170: FUNCTION_VALUE_REGNUM); ! 1171: ! 1172: /* If doing stupid allocation, mark parms as born here. */ ! 1173: ! 1174: if (obey_regdecls) ! 1175: { ! 1176: rtx insn = get_last_insn (); ! 1177: ! 1178: reg_birth_insn = (rtx *) oballoc (first_temp_reg_num * sizeof (rtx)); ! 1179: reg_death_insn = (rtx *) oballoc (first_temp_reg_num * sizeof (rtx)); ! 1180: bzero (reg_birth_insn, first_temp_reg_num * sizeof (rtx)); ! 1181: bzero (reg_death_insn, first_temp_reg_num * sizeof (rtx)); ! 1182: ! 1183: for (i = 0; i < max_parm_reg; i++) ! 1184: reg_birth_insn[i] = insn; ! 1185: } ! 1186: ! 1187: /* Don't generate a NOTE_INSN_BLOCK_BEG for the function's topmost block. ! 1188: final will do it specially, in order to make it come before ! 1189: the function prologue, and we don't want to have two of them. */ ! 1190: inhibit_block_beg = 1; ! 1191: ! 1192: /* Generate the actual code for the function. ! 1193: `assign_stack_local' may not be called again ! 1194: until after `allocate_structure_value_space'. */ ! 1195: ! 1196: expand_stmt (DECL_INITIAL (subr), 0); ! 1197: ! 1198: /* If doing stupid register allocation, ! 1199: mark any argument variables as dying here in the last insn generated ! 1200: (which is always an end-of-block comment, so it is never deleted). */ ! 1201: if (obey_regdecls) ! 1202: { ! 1203: rtx insn = get_last_insn (); ! 1204: for (i = 0; i < max_parm_reg; i++) ! 1205: reg_death_insn[i] = insn; ! 1206: } ! 1207: ! 1208: /* Return insn or function epilogue ignore the stack pointer. */ ! 1209: clear_pending_stack_adjust (); ! 1210: ! 1211: /* If we require a true epilogue, ! 1212: put here the label that return statements jump to. ! 1213: If there will be no epilogue, write a return instruction. */ ! 1214: #ifdef FUNCTION_EPILOGUE ! 1215: emit_label (return_label); ! 1216: #else ! 1217: emit_jump_insn (gen_return ()); ! 1218: #endif ! 1219: ! 1220: allocate_structure_value_space (); ! 1221: ! 1222: return get_insns (); ! 1223: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.