|
|
1.1 ! root 1: /* Top level of 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 is the top level of cc1. ! 23: It parses command args, opens files, invokes the various passes ! 24: in the proper order, and counts the time used by each. ! 25: Error messages and low-level interface to malloc also handled here. */ ! 26: ! 27: #include "config.h" ! 28: #include <stdio.h> ! 29: #include <signal.h> ! 30: #include <strings.h> ! 31: #include <sys/time.h> ! 32: #include <sys/resource.h> ! 33: #ifndef _TYPES_ ! 34: #include <sys/types.h> ! 35: #endif ! 36: #include <sys/stat.h> ! 37: #include "tree.h" ! 38: #include "c-tree.h" ! 39: #include "rtl.h" ! 40: ! 41: extern void dump_tree (); ! 42: extern int yydebug; ! 43: ! 44: extern FILE *finput; ! 45: ! 46: extern void init_lex (); ! 47: extern void init_decl_processing (); ! 48: extern void init_tree (); ! 49: extern void init_rtl (); ! 50: extern rtx expand_function (); ! 51: extern void init_optabs (); ! 52: extern void dump_flow_info (); ! 53: extern void dump_local_alloc (); ! 54: ! 55: /* Bit flags that specify the machine subtype we are compiling for. ! 56: Bits are tested using macros TARGET_... defined in the tm-...h file ! 57: and set by `-m...' switches. */ ! 58: ! 59: int target_flags; ! 60: ! 61: /* Name of current real source file (what was input to cpp). ! 62: # commands in the input that specify file names ! 63: change this value. */ ! 64: ! 65: extern char *input_filename; ! 66: ! 67: /* Current line number in real source file. */ ! 68: ! 69: extern int lineno; ! 70: ! 71: /* FUNCTION_DECL for function now being parsed or compiled. */ ! 72: ! 73: extern tree current_function_decl; ! 74: ! 75: /* Name to use as base of names for dump output files. */ ! 76: ! 77: char *dump_base_name; ! 78: ! 79: /* Flags saying which kinds of debugging dump have been requested. */ ! 80: ! 81: int tree_dump = 0; ! 82: int rtl_dump = 0; ! 83: int rtl_dump_and_exit = 0; ! 84: int jump_opt_dump = 0; ! 85: int cse_dump = 0; ! 86: int loop_dump = 0; ! 87: int flow_dump = 0; ! 88: int combine_dump = 0; ! 89: int local_reg_dump = 0; ! 90: int global_reg_dump = 0; ! 91: ! 92: /* 1 => write gdb debugging output (using symout.c). -g ! 93: 2 => write dbx debugging output (using dbxout.c). -G */ ! 94: ! 95: int write_symbols = 0; ! 96: ! 97: /* Nonzero means do optimizations. -opt. */ ! 98: ! 99: int optimize = 0; ! 100: ! 101: /* Nonzero for -optforcemem: load memory value into a register ! 102: before arithmetic on it. This makes better cse but slower compilation. */ ! 103: ! 104: int force_mem = 0; ! 105: ! 106: /* Nonzero for -optforcemem: load memory address into a register before ! 107: reference to memory. This makes better cse but slower compilation. */ ! 108: ! 109: int force_addr = 0; ! 110: ! 111: /* Nonzero means do stupid register allocation. -noreg. ! 112: This an OPTIMIZE are controlled by different switches in cc1, ! 113: but normally cc controls them both with the -O switch. */ ! 114: ! 115: int obey_regdecls = 0; ! 116: ! 117: /* Don't print functions as they are compiled and don't print ! 118: times taken by the various passes. -quiet. */ ! 119: ! 120: int quiet_flag = 0; ! 121: ! 122: /* Don't print warning messages. -w. */ ! 123: ! 124: int inhibit_warnings = 0; ! 125: ! 126: /* Number of error messages and warning messages so far. */ ! 127: ! 128: int errorcount = 0; ! 129: int warningcount = 0; ! 130: ! 131: /* Nonzero for -pedantic switch: warn about anything ! 132: that standard C forbids. */ ! 133: ! 134: int pedantic = 0; ! 135: ! 136: /* Name for output file of assembly code, specified with -o. */ ! 137: ! 138: char *asm_file_name; ! 139: ! 140: /* Name for output file of GDB symbol segment, specified with -symout. */ ! 141: ! 142: char *sym_file_name; ! 143: ! 144: /* Output files for assembler code (real compiler output) ! 145: and debugging dumps. */ ! 146: ! 147: FILE *asm_out_file; ! 148: FILE *tree_dump_file; ! 149: FILE *rtl_dump_file; ! 150: FILE *jump_opt_dump_file; ! 151: FILE *cse_dump_file; ! 152: FILE *loop_dump_file; ! 153: FILE *flow_dump_file; ! 154: FILE *combine_dump_file; ! 155: FILE *local_reg_dump_file; ! 156: FILE *global_reg_dump_file; ! 157: ! 158: /* Time accumulators, to count the total time spent in various passes. */ ! 159: ! 160: int parse_time; ! 161: int varconst_time; ! 162: int expand_time; ! 163: int jump_time; ! 164: int cse_time; ! 165: int loop_time; ! 166: int flow_time; ! 167: int combine_time; ! 168: int local_alloc_time; ! 169: int global_alloc_time; ! 170: int final_time; ! 171: int symout_time; ! 172: int dump_time; ! 173: ! 174: /* Return time used so far, in microseconds. */ ! 175: ! 176: gettime () ! 177: { ! 178: struct rusage rusage; ! 179: if (quiet_flag) ! 180: return 0; ! 181: getrusage (0, &rusage); ! 182: return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec ! 183: + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec); ! 184: } ! 185: ! 186: #define TIMEVAR(VAR, BODY) \ ! 187: { int otime = gettime (); BODY; VAR += gettime () - otime; } ! 188: ! 189: print_time (str, total) ! 190: char *str; ! 191: int total; ! 192: { ! 193: printf ("time in %s: %d.%06d\n", str, total / 1000000, total % 1000000); ! 194: } ! 195: ! 196: /* Count an error or warning. Return 1 if the message should be printed. */ ! 197: ! 198: int ! 199: count_error (warningp) ! 200: int warningp; ! 201: { ! 202: if (warningp && inhibit_warnings) ! 203: return 0; ! 204: ! 205: if (warningp) ! 206: warningcount++; ! 207: else ! 208: errorcount++; ! 209: ! 210: /* If we are printing function names, make sure error message ! 211: starts at beginning of line. */ ! 212: if (!quiet_flag) ! 213: fprintf (stderr, "\n"); ! 214: ! 215: return 1; ! 216: } ! 217: ! 218: /* Print a fatal error message. NAME is the text. ! 219: Also include a system error message based on `errno'. */ ! 220: ! 221: int ! 222: pfatal_with_name (name) ! 223: { ! 224: fprintf (stderr, "cc1: "); ! 225: perror (name); ! 226: exit (35); ! 227: } ! 228: ! 229: void ! 230: fatal (s) ! 231: char *s; ! 232: { ! 233: yyerror (s, 0); ! 234: exit (34); ! 235: } ! 236: ! 237: /* Called when the start of a function definition is parsed, ! 238: this function prints on stderr the name of the function. */ ! 239: ! 240: void ! 241: announce_function (decl) ! 242: tree decl; ! 243: { ! 244: if (! quiet_flag) ! 245: { ! 246: fprintf (stderr, " %s", IDENTIFIER_POINTER (DECL_NAME (decl))); ! 247: fflush (stderr); ! 248: } ! 249: } ! 250: ! 251: static tree last_error_function; ! 252: ! 253: /* Report an error at the current line number. ! 254: S and V are a string and an arg for `printf'. */ ! 255: ! 256: void ! 257: yyerror (s, v) ! 258: char *s; ! 259: int v; /* @@also used as pointer */ ! 260: { ! 261: yylineerror (lineno, s, v); ! 262: } ! 263: ! 264: /* Report an error at line LINE. ! 265: S and V are a string and an arg for `printf'. */ ! 266: ! 267: yylineerror (line, s, v) ! 268: int line; ! 269: char *s; ! 270: int v; ! 271: { ! 272: count_error (0); ! 273: ! 274: if (last_error_function != current_function_decl) ! 275: { ! 276: fprintf (stderr, "In function %s:\n", ! 277: IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); ! 278: last_error_function = current_function_decl; ! 279: } ! 280: fprintf (stderr, "%s:%d: ", input_filename, line); ! 281: fprintf (stderr, s, v); ! 282: fprintf (stderr, "\n"); ! 283: } ! 284: ! 285: /* Report a warning at the current line number. ! 286: S and V are a string and an arg for `printf'. */ ! 287: ! 288: void ! 289: warning (s, v) ! 290: char *s; ! 291: int v; /* @@also used as pointer */ ! 292: { ! 293: warning_with_line (lineno, s, v); ! 294: } ! 295: ! 296: /* Report a warning at line LINE. ! 297: S and V are a string and an arg for `printf'. */ ! 298: ! 299: warning_with_line (line, s, v) ! 300: int line; ! 301: char *s; ! 302: int v; ! 303: { ! 304: if (count_error (1) == 0) ! 305: return; ! 306: ! 307: if (last_error_function != current_function_decl) ! 308: { ! 309: fprintf (stderr, "In function %s:\n", ! 310: IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); ! 311: last_error_function = current_function_decl; ! 312: } ! 313: fprintf (stderr, "%s:%d: ", input_filename, line); ! 314: ! 315: fprintf (stderr, "warning: "); ! 316: fprintf (stderr, s, v); ! 317: fprintf (stderr, "\n"); ! 318: } ! 319: ! 320: /* When `malloc.c' is compiled with `rcheck' defined, ! 321: it calls this function to report clobberage. */ ! 322: ! 323: botch (s) ! 324: { ! 325: abort (); ! 326: } ! 327: ! 328: /* Same as `malloc' but report error if no memory available. */ ! 329: ! 330: xmalloc (size) ! 331: unsigned size; ! 332: { ! 333: register int value = (int) malloc (size); ! 334: if (value == 0) ! 335: fatal ("Virtual memory exhausted."); ! 336: return value; ! 337: } ! 338: ! 339: /* Same as `realloc' but report error if no memory available. */ ! 340: ! 341: int ! 342: xrealloc (ptr, size) ! 343: char *ptr; ! 344: int size; ! 345: { ! 346: int result = realloc (ptr, size); ! 347: if (!result) ! 348: abort (); ! 349: return result; ! 350: } ! 351: ! 352: /* Return the logarithm of X, base 2, considering X unsigned, ! 353: if X is a power of 2. Otherwise, returns -1. */ ! 354: ! 355: int ! 356: exact_log2 (x) ! 357: register unsigned int x; ! 358: { ! 359: register int log = 0; ! 360: for (log = 0; log < HOST_BITS_PER_INT; log++) ! 361: if (x == (1 << log)) ! 362: return log; ! 363: return -1; ! 364: } ! 365: ! 366: /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X. ! 367: If X is 0, return -1. */ ! 368: ! 369: int ! 370: floor_log2 (x) ! 371: register unsigned int x; ! 372: { ! 373: register int log = 0; ! 374: for (log = 0; log < HOST_BITS_PER_INT; log++) ! 375: if ((x & ((-1) << log)) == 0) ! 376: return log - 1; ! 377: return HOST_BITS_PER_INT - 1; ! 378: } ! 379: ! 380: /* Compile an entire file of output from cpp, named NAME. ! 381: Write a file of assembly output and various debugging dumps. */ ! 382: ! 383: static void ! 384: compile_file (name) ! 385: char *name; ! 386: { ! 387: tree globals; ! 388: int start_time; ! 389: int dump_base_name_length = strlen (dump_base_name); ! 390: ! 391: parse_time = 0; ! 392: varconst_time = 0; ! 393: expand_time = 0; ! 394: jump_time = 0; ! 395: cse_time = 0; ! 396: loop_time = 0; ! 397: flow_time = 0; ! 398: combine_time = 0; ! 399: local_alloc_time = 0; ! 400: global_alloc_time = 0; ! 401: final_time = 0; ! 402: symout_time = 0; ! 403: dump_time; ! 404: ! 405: /* Open input file. */ ! 406: ! 407: finput = fopen (name, "r"); ! 408: if (finput == 0) ! 409: pfatal_with_name (name); ! 410: ! 411: /* Initialize data in various passes. */ ! 412: ! 413: init_tree (); ! 414: init_lex (); ! 415: init_rtl (); ! 416: init_decl_processing (); ! 417: init_optabs (); ! 418: ! 419: /* If tree dump desired, open the output file. */ ! 420: if (tree_dump) ! 421: { ! 422: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 423: strcpy (dumpname, dump_base_name); ! 424: strcat (dumpname, ".tree"); ! 425: tree_dump_file = fopen (dumpname, "w"); ! 426: if (tree_dump_file == 0) ! 427: pfatal_with_name (dumpname); ! 428: } ! 429: ! 430: /* If rtl dump desired, open the output file. */ ! 431: if (rtl_dump) ! 432: { ! 433: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 434: strcpy (dumpname, dump_base_name); ! 435: strcat (dumpname, ".rtl"); ! 436: rtl_dump_file = fopen (dumpname, "w"); ! 437: if (rtl_dump_file == 0) ! 438: pfatal_with_name (dumpname); ! 439: } ! 440: ! 441: /* If jump_opt dump desired, open the output file. */ ! 442: if (jump_opt_dump) ! 443: { ! 444: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 445: strcpy (dumpname, dump_base_name); ! 446: strcat (dumpname, ".jump"); ! 447: jump_opt_dump_file = fopen (dumpname, "w"); ! 448: if (jump_opt_dump_file == 0) ! 449: pfatal_with_name (dumpname); ! 450: } ! 451: ! 452: /* If cse dump desired, open the output file. */ ! 453: if (cse_dump) ! 454: { ! 455: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 456: strcpy (dumpname, dump_base_name); ! 457: strcat (dumpname, ".cse"); ! 458: cse_dump_file = fopen (dumpname, "w"); ! 459: if (cse_dump_file == 0) ! 460: pfatal_with_name (dumpname); ! 461: } ! 462: ! 463: /* If loop dump desired, open the output file. */ ! 464: if (loop_dump) ! 465: { ! 466: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 467: strcpy (dumpname, dump_base_name); ! 468: strcat (dumpname, ".loop"); ! 469: loop_dump_file = fopen (dumpname, "w"); ! 470: if (loop_dump_file == 0) ! 471: pfatal_with_name (dumpname); ! 472: } ! 473: ! 474: /* If flow dump desired, open the output file. */ ! 475: if (flow_dump) ! 476: { ! 477: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 478: strcpy (dumpname, dump_base_name); ! 479: strcat (dumpname, ".flow"); ! 480: flow_dump_file = fopen (dumpname, "w"); ! 481: if (flow_dump_file == 0) ! 482: pfatal_with_name (dumpname); ! 483: } ! 484: ! 485: /* If combine dump desired, open the output file. */ ! 486: if (combine_dump) ! 487: { ! 488: register char *dumpname = (char *) xmalloc (dump_base_name_length + 10); ! 489: strcpy (dumpname, dump_base_name); ! 490: strcat (dumpname, ".combine"); ! 491: combine_dump_file = fopen (dumpname, "w"); ! 492: if (combine_dump_file == 0) ! 493: pfatal_with_name (dumpname); ! 494: } ! 495: ! 496: /* If local_reg dump desired, open the output file. */ ! 497: if (local_reg_dump) ! 498: { ! 499: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 500: strcpy (dumpname, dump_base_name); ! 501: strcat (dumpname, ".lreg"); ! 502: local_reg_dump_file = fopen (dumpname, "w"); ! 503: if (local_reg_dump_file == 0) ! 504: pfatal_with_name (dumpname); ! 505: } ! 506: ! 507: /* If global_reg dump desired, open the output file. */ ! 508: if (global_reg_dump) ! 509: { ! 510: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 511: strcpy (dumpname, dump_base_name); ! 512: strcat (dumpname, ".greg"); ! 513: global_reg_dump_file = fopen (dumpname, "w"); ! 514: if (global_reg_dump_file == 0) ! 515: pfatal_with_name (dumpname); ! 516: } ! 517: ! 518: /* Open assembler code output file. */ ! 519: ! 520: { ! 521: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 522: strcpy (dumpname, dump_base_name); ! 523: strcat (dumpname, ".s"); ! 524: asm_out_file = fopen (asm_file_name ? asm_file_name : dumpname, "w"); ! 525: if (asm_out_file == 0) ! 526: pfatal_with_name (asm_file_name ? asm_file_name : dumpname); ! 527: } ! 528: ! 529: input_filename = name; ! 530: ! 531: /* the beginning of the file is a new line; check for # */ ! 532: /* With luck, we discover the real source file's name from that ! 533: and put it in input_filename. */ ! 534: check_newline (); ! 535: ! 536: /* If GDB symbol table desired, open the GDB symbol output file. */ ! 537: if (write_symbols == 1) ! 538: { ! 539: register char *dumpname = (char *) xmalloc (dump_base_name_length + 6); ! 540: strcpy (dumpname, dump_base_name); ! 541: strcat (dumpname, ".sym"); ! 542: if (sym_file_name == 0) ! 543: sym_file_name = dumpname; ! 544: symout_init (sym_file_name, asm_out_file, input_filename); ! 545: } ! 546: ! 547: /* If dbx symbol table desired, initialize writing it ! 548: and output the predefined types. */ ! 549: if (write_symbols == 2) ! 550: dbxout_init (asm_out_file, input_filename); ! 551: ! 552: /* Initialize yet another pass. */ ! 553: ! 554: init_final (input_filename); ! 555: ! 556: start_time = gettime (); ! 557: ! 558: /* Call the parser, which parses the entire file ! 559: (calling rest_of_compilation for each function). */ ! 560: ! 561: yyparse (); ! 562: ! 563: /* Compilation is now finished except for writing ! 564: what's left of the symbol table output. */ ! 565: ! 566: parse_time += gettime () - start_time; ! 567: ! 568: globals = getdecls (); ! 569: ! 570: /* Do dbx symbols */ ! 571: if (write_symbols == 2) ! 572: TIMEVAR (symout_time, ! 573: { ! 574: dbxout_tags (gettags ()); ! 575: dbxout_types (get_permanent_types ()); ! 576: }); ! 577: ! 578: /* Do gdb symbols */ ! 579: if (write_symbols == 1) ! 580: TIMEVAR (symout_time, ! 581: { ! 582: struct stat statbuf; ! 583: fstat (fileno (finput), &statbuf); ! 584: symout_types (get_permanent_types ()); ! 585: symout_top_blocks (globals, gettags ()); ! 586: symout_finish (name, statbuf.st_ctime); ! 587: }); ! 588: ! 589: /* Close non-debugging input and output files. */ ! 590: ! 591: fclose (finput); ! 592: fclose (asm_out_file); ! 593: ! 594: if (!quiet_flag) ! 595: fprintf (stderr,"\n"); ! 596: ! 597: /* Dump the global nodes and close the tree dump file. */ ! 598: if (tree_dump) ! 599: { ! 600: dump_tree (tree_dump_file, globals); ! 601: fclose (tree_dump_file); ! 602: } ! 603: ! 604: /* Close all other dump files. */ ! 605: ! 606: if (rtl_dump) ! 607: fclose (rtl_dump_file); ! 608: ! 609: if (jump_opt_dump) ! 610: fclose (jump_opt_dump_file); ! 611: ! 612: if (cse_dump) ! 613: fclose (cse_dump_file); ! 614: ! 615: if (loop_dump) ! 616: fclose (loop_dump_file); ! 617: ! 618: if (flow_dump) ! 619: fclose (flow_dump_file); ! 620: ! 621: if (combine_dump) ! 622: { ! 623: dump_combine_total_stats (combine_dump_file); ! 624: fclose (combine_dump_file); ! 625: } ! 626: ! 627: if (local_reg_dump) ! 628: fclose (local_reg_dump_file); ! 629: ! 630: if (global_reg_dump) ! 631: fclose (global_reg_dump_file); ! 632: ! 633: /* Print the times. */ ! 634: ! 635: if (! quiet_flag) ! 636: { ! 637: print_time ("parse", parse_time); ! 638: print_time ("expand", expand_time); ! 639: print_time ("jump", jump_time); ! 640: print_time ("cse", cse_time); ! 641: print_time ("loop", loop_time); ! 642: print_time ("flow", flow_time); ! 643: print_time ("combine", combine_time); ! 644: print_time ("local-alloc", local_alloc_time); ! 645: print_time ("global-alloc", global_alloc_time); ! 646: print_time ("final", final_time); ! 647: print_time ("varconst", varconst_time); ! 648: print_time ("symout", symout_time); ! 649: print_time ("dump", dump_time); ! 650: } ! 651: } ! 652: ! 653: /* This is called from finish_function (within yyparse) ! 654: after each top-level definition is parsed, and from ! 655: finish_decl (also within yyparse) for each other top-level declaration. ! 656: It is supposed to compile that function or variable ! 657: and output the assembler code for it. ! 658: After we return, the tree storage is freed. */ ! 659: ! 660: void ! 661: rest_of_compilation (decl, top_level) ! 662: tree decl; ! 663: int top_level; ! 664: { ! 665: register rtx insns; ! 666: int start_time = gettime (); ! 667: int tem; ! 668: ! 669: /* Declarations of variables, and of functions defined elsewhere. */ ! 670: ! 671: if ((TREE_CODE (decl) == VAR_DECL ! 672: || (TREE_CODE (decl) == FUNCTION_DECL ! 673: && DECL_INITIAL (decl) == 0)) ! 674: && (TREE_STATIC (decl) || TREE_EXTERNAL (decl))) ! 675: { ! 676: TIMEVAR (varconst_time, ! 677: { ! 678: assemble_variable (decl, top_level); ! 679: if (write_symbols == 2) ! 680: dbxout_symbol (decl, 0); ! 681: }); ! 682: } ! 683: ! 684: /* Function definitions are the real work ! 685: (all the rest of this function). */ ! 686: ! 687: else if (TREE_CODE (decl) == FUNCTION_DECL ! 688: && DECL_INITIAL (decl)) ! 689: { ! 690: /* Dump the function's tree if we are dumping trees. */ ! 691: ! 692: if (tree_dump) ! 693: TIMEVAR (dump_time, ! 694: dump_tree (tree_dump_file, decl)); ! 695: ! 696: /* Output some preliminaries for assembler. */ ! 697: ! 698: TIMEVAR (varconst_time, assemble_function (decl)); ! 699: ! 700: /* Generate rtl code for this function (see stmt.c, expr.c). */ ! 701: ! 702: TIMEVAR (expand_time, ! 703: { ! 704: init_emit (write_symbols); ! 705: insns = expand_function (decl, !optimize); ! 706: }); ! 707: ! 708: /* Dump the rtl code if we are dumping rtl. */ ! 709: ! 710: if (rtl_dump) ! 711: TIMEVAR (dump_time, ! 712: { ! 713: fprintf (rtl_dump_file, "\n;; Function %s\n\n", ! 714: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 715: print_rtl (rtl_dump_file, insns); ! 716: fflush (rtl_dump_file); ! 717: }); ! 718: ! 719: if (rtl_dump_and_exit) ! 720: goto exit_rest_of_compilation; ! 721: ! 722: /* Do jump optimization the first time, if -opt. */ ! 723: ! 724: if (optimize) ! 725: TIMEVAR (jump_time, jump_optimize (insns, 0)); ! 726: ! 727: /* Dump rtl code after jump, if we are doing that. */ ! 728: ! 729: if (jump_opt_dump) ! 730: TIMEVAR (dump_time, ! 731: { ! 732: fprintf (jump_opt_dump_file, "\n;; Function %s\n\n", ! 733: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 734: print_rtl (jump_opt_dump_file, insns); ! 735: fflush (jump_opt_dump_file); ! 736: }); ! 737: ! 738: /* Perform common subexpression elimination. ! 739: Nonzero value from `cse_main' means that jumps were simplified ! 740: and some code may now be unreachable, so do ! 741: jump optimization again. */ ! 742: ! 743: if (optimize) ! 744: { ! 745: TIMEVAR (cse_time, reg_scan (insns, max_reg_num ())); ! 746: ! 747: TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num ())); ! 748: ! 749: if (tem) ! 750: TIMEVAR (jump_time, jump_optimize (insns, 0)); ! 751: } ! 752: ! 753: /* Dump rtl code after cse, if we are doing that. */ ! 754: ! 755: if (cse_dump) ! 756: TIMEVAR (dump_time, ! 757: { ! 758: fprintf (cse_dump_file, "\n;; Function %s\n\n", ! 759: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 760: print_rtl (cse_dump_file, insns); ! 761: fflush (cse_dump_file); ! 762: }); ! 763: ! 764: /* Move constant computations out of loops. */ ! 765: ! 766: if (optimize) ! 767: { ! 768: TIMEVAR (loop_time, loop_optimize (insns, max_reg_num ())); ! 769: } ! 770: ! 771: /* Dump rtl code after loop opt, if we are doing that. */ ! 772: ! 773: if (loop_dump) ! 774: TIMEVAR (dump_time, ! 775: { ! 776: fprintf (loop_dump_file, "\n;; Function %s\n\n", ! 777: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 778: print_rtl (loop_dump_file, insns); ! 779: fflush (loop_dump_file); ! 780: }); ! 781: ! 782: /* Now we choose between stupid (pcc-like) register allocation ! 783: (if we got the -noreg switch and not -opt) ! 784: and smart register allocation. */ ! 785: ! 786: if (optimize) /* Stupid allocation probably won't work */ ! 787: obey_regdecls = 0; /* if optimizations being done. */ ! 788: ! 789: /* Print function header into flow dump now ! 790: because doing the flow analysis makes some of the dump. */ ! 791: ! 792: if (flow_dump) ! 793: TIMEVAR (dump_time, ! 794: { ! 795: fprintf (flow_dump_file, "\n;; Function %s\n\n", ! 796: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 797: }); ! 798: ! 799: if (obey_regdecls) ! 800: { ! 801: TIMEVAR (flow_time, ! 802: { ! 803: regclass (insns, max_reg_num ()); ! 804: stupid_life_analysis (insns, max_reg_num (), ! 805: flow_dump_file); ! 806: }); ! 807: } ! 808: else ! 809: { ! 810: /* Do control and data flow analysis, ! 811: and write some of the results to dump file. */ ! 812: ! 813: TIMEVAR (flow_time, flow_analysis (insns, max_reg_num (), ! 814: flow_dump_file)); ! 815: } ! 816: ! 817: /* Dump rtl after flow analysis. */ ! 818: ! 819: if (flow_dump) ! 820: TIMEVAR (dump_time, ! 821: { ! 822: print_rtl (flow_dump_file, insns); ! 823: fflush (flow_dump_file); ! 824: }); ! 825: ! 826: /* If -opt, try combining insns through substitution. */ ! 827: ! 828: if (optimize) ! 829: TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ())); ! 830: ! 831: /* Dump rtl code after insn combination. */ ! 832: ! 833: if (combine_dump) ! 834: TIMEVAR (dump_time, ! 835: { ! 836: fprintf (combine_dump_file, "\n;; Function %s\n\n", ! 837: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 838: dump_combine_stats (combine_dump_file); ! 839: print_rtl (combine_dump_file, insns); ! 840: fflush (combine_dump_file); ! 841: }); ! 842: ! 843: /* Unless we did stupid register allocation, ! 844: allocate pseudo-regs that are used only within 1 basic block. */ ! 845: ! 846: if (!obey_regdecls) ! 847: TIMEVAR (local_alloc_time, ! 848: { ! 849: regclass (insns, max_reg_num ()); ! 850: local_alloc (); ! 851: }); ! 852: ! 853: /* Dump rtl code after allocating regs within basic blocks. */ ! 854: ! 855: if (local_reg_dump) ! 856: TIMEVAR (dump_time, ! 857: { ! 858: fprintf (local_reg_dump_file, "\n;; Function %s\n\n", ! 859: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 860: dump_flow_info (local_reg_dump_file); ! 861: dump_local_alloc (local_reg_dump_file); ! 862: print_rtl (local_reg_dump_file, insns); ! 863: fflush (local_reg_dump_file); ! 864: }); ! 865: ! 866: if (global_reg_dump) ! 867: TIMEVAR (dump_time, ! 868: fprintf (global_reg_dump_file, "\n;; Function %s\n\n", ! 869: IDENTIFIER_POINTER (DECL_NAME (decl)))); ! 870: ! 871: /* Unless we did stupid register allocation, ! 872: allocate remaining pseudo-regs, then do the reload pass ! 873: fixing up any insns that are invalid. */ ! 874: ! 875: TIMEVAR (global_alloc_time, ! 876: { ! 877: if (!obey_regdecls) ! 878: global_alloc (global_reg_dump ? global_reg_dump_file : 0); ! 879: else ! 880: reload (insns, 0, ! 881: global_reg_dump ? global_reg_dump_file : 0); ! 882: }); ! 883: ! 884: if (global_reg_dump) ! 885: TIMEVAR (dump_time, ! 886: { ! 887: dump_global_regs (global_reg_dump_file); ! 888: print_rtl (global_reg_dump_file, insns); ! 889: fflush (global_reg_dump_file); ! 890: }); ! 891: ! 892: /* One more attempt to remove jumps to .+1 ! 893: left by dead-store-elimination. ! 894: Also do cross-jumping this time. */ ! 895: ! 896: if (optimize) ! 897: TIMEVAR (jump_time, jump_optimize (insns, 1)); ! 898: ! 899: /* Now turn the rtl into assembler code. */ ! 900: ! 901: TIMEVAR (final_time, ! 902: { ! 903: final (insns, asm_out_file, ! 904: IDENTIFIER_POINTER (DECL_NAME (decl)), ! 905: write_symbols, optimize); ! 906: fflush (asm_out_file); ! 907: }); ! 908: ! 909: /* Write GDB symbols if requested */ ! 910: ! 911: if (write_symbols == 1) ! 912: TIMEVAR (symout_time, ! 913: { ! 914: symout_types (get_permanent_types ()); ! 915: symout_types (get_temporary_types ()); ! 916: ! 917: DECL_BLOCK_SYMTAB_ADDRESS (decl) ! 918: = symout_function (DECL_INITIAL (decl), ! 919: DECL_ARGUMENTS (decl), 0); ! 920: }); ! 921: ! 922: /* Write DBX symbols if requested */ ! 923: ! 924: if (write_symbols == 2) ! 925: TIMEVAR (symout_time, dbxout_function (decl)); ! 926: } ! 927: ! 928: exit_rest_of_compilation: ! 929: ! 930: /* The parsing time is all the time spent in yyparse ! 931: *except* what is spent in this function. */ ! 932: ! 933: parse_time -= gettime () - start_time; ! 934: } ! 935: ! 936: /* Entry point of cc1. Decode command args, then call compile_file. ! 937: Exit code is 34 if fatal error, else 33 if have error messages, ! 938: else 1 if have warnings, else 0. */ ! 939: ! 940: int ! 941: main (argc, argv, envp) ! 942: int argc; ! 943: char **argv; ! 944: char **envp; ! 945: { ! 946: register int i; ! 947: char *filename; ! 948: ! 949: target_flags = 0; ! 950: set_target_switch (""); ! 951: ! 952: for (i = 1; i < argc; i++) ! 953: if (argv[i][0] == '-') ! 954: { ! 955: register char *str = argv[i] + 1; ! 956: if (str[0] == 'Y') ! 957: str++; ! 958: ! 959: if (str[0] == 'm') ! 960: set_target_switch (&str[1]); ! 961: else if (!strcmp (str, "dumpbase")) ! 962: { ! 963: dump_base_name = argv[++i]; ! 964: } ! 965: else if (str[0] == 'd') ! 966: { ! 967: register char *p = &str[1]; ! 968: while (*p) ! 969: switch (*p++) ! 970: { ! 971: case 'c': ! 972: combine_dump = 1; ! 973: break; ! 974: case 'f': ! 975: flow_dump = 1; ! 976: break; ! 977: case 'g': ! 978: global_reg_dump = 1; ! 979: break; ! 980: case 'j': ! 981: jump_opt_dump = 1; ! 982: break; ! 983: case 'l': ! 984: local_reg_dump = 1; ! 985: break; ! 986: case 'L': ! 987: loop_dump = 1; ! 988: break; ! 989: case 'r': ! 990: rtl_dump = 1; ! 991: break; ! 992: case 's': ! 993: cse_dump = 1; ! 994: break; ! 995: case 't': ! 996: tree_dump = 1; ! 997: break; ! 998: case 'y': ! 999: yydebug = 1; ! 1000: break; ! 1001: } ! 1002: } ! 1003: else if (!strcmp (str, "quiet")) ! 1004: quiet_flag = 1; ! 1005: else if (!strcmp (str, "opt")) ! 1006: optimize = 1; ! 1007: else if (!strcmp (str, "optforcemem")) ! 1008: force_mem = 1; ! 1009: else if (!strcmp (str, "optforceaddr")) ! 1010: force_addr = 1; ! 1011: else if (!strcmp (str, "noreg")) ! 1012: obey_regdecls = 1; ! 1013: else if (!strcmp (str, "w")) ! 1014: inhibit_warnings = 1; ! 1015: else if (!strcmp (str, "g")) ! 1016: write_symbols = 1; ! 1017: else if (!strcmp (str, "G")) ! 1018: write_symbols = 2; ! 1019: else if (!strcmp (str, "symout")) ! 1020: { ! 1021: if (write_symbols == 0) ! 1022: write_symbols = 1; ! 1023: sym_file_name = argv[++i]; ! 1024: } ! 1025: else if (!strcmp (str, "o")) ! 1026: { ! 1027: asm_file_name = argv[++i]; ! 1028: } ! 1029: else ! 1030: yylineerror (0, "Invalid switch, %s.", argv[i]); ! 1031: } ! 1032: else ! 1033: filename = argv[i]; ! 1034: ! 1035: if (filename == 0) ! 1036: fatal ("no input file specified"); ! 1037: ! 1038: if (dump_base_name == 0) ! 1039: dump_base_name = filename; ! 1040: compile_file (filename); ! 1041: ! 1042: if (errorcount) ! 1043: return 33; ! 1044: else ! 1045: return (warningcount > 0); ! 1046: } ! 1047: ! 1048: /* Decode -m switches. */ ! 1049: ! 1050: /* Here is a table, controlled by the tm-...h file, listing each -m switch ! 1051: and which bits in `target_switches' it should set or clear. ! 1052: If VALUE is positive, it is bits to set. ! 1053: If VALUE is negative, -VALUE is bits to clear. ! 1054: (The sign bit is not used so there is no confusion.) */ ! 1055: ! 1056: struct {char *name; int value;} target_switches [] ! 1057: = TARGET_SWITCHES; ! 1058: ! 1059: /* Decode the switch -mNAME. */ ! 1060: ! 1061: set_target_switch (name) ! 1062: char *name; ! 1063: { ! 1064: register int j = 0; ! 1065: for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++) ! 1066: if (!strcmp (target_switches[j].name, name)) ! 1067: { ! 1068: if (target_switches[j].value < 0) ! 1069: target_flags &= ~-target_switches[j].value; ! 1070: else ! 1071: target_flags |= target_switches[j].value; ! 1072: break; ! 1073: } ! 1074: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.