⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 toplev.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
  else    {      register char *dumpname = (char *) xmalloc (dump_base_name_length + 6);      int len = strlen (dump_base_name);      strcpy (dumpname, dump_base_name);      if (len > 2 && ! strcmp (".c", dumpname + len - 2))	dumpname[len - 2] = 0;      else if (len > 2 && ! strcmp (".i", dumpname + len - 2))	dumpname[len - 2] = 0;      else if (len > 3 && ! strcmp (".co", dumpname + len - 3))	dumpname[len - 3] = 0;      strcat (dumpname, ".s");      if (asm_file_name == 0)	{	  asm_file_name = (char *) malloc (strlen (dumpname) + 1);	  strcpy (asm_file_name, dumpname);	}      if (!strcmp (asm_file_name, "-"))	asm_out_file = stdout;      else	asm_out_file = fopen (asm_file_name, "w");      if (asm_out_file == 0)	pfatal_with_name (asm_file_name);    }  input_filename = name;  /* the beginning of the file is a new line; check for # */  /* With luck, we discover the real source file's name from that     and put it in input_filename.  */  ungetc (check_newline (), finput);  /* If the input doesn't start with a #line, use the input name     as the official input file name.  */  if (main_input_filename == 0)    main_input_filename = name;  /* Put an entry on the input file stack for the main input file.  */  input_file_stack    = (struct file_stack *) xmalloc (sizeof (struct file_stack));  input_file_stack->next = 0;  input_file_stack->name = input_filename;  ASM_FILE_START (asm_out_file);  /* Output something to inform GDB that this compilation was by GCC.  */#ifndef ASM_IDENTIFY_GCC  fprintf (asm_out_file, "gcc_compiled.:\n");#else  ASM_IDENTIFY_GCC (asm_out_file);#endif  /* If GDB symbol table desired, open the GDB symbol output file.  */  if (write_symbols == GDB_DEBUG)    {      register char *dumpname = (char *) xmalloc (dump_base_name_length + 6);      int len = strlen (dump_base_name);      strcpy (dumpname, dump_base_name);      if (len > 2 && ! strcmp (".c", dumpname + len - 2))	dumpname[len - 2] = 0;      else if (len > 2 && ! strcmp (".i", dumpname + len - 2))	dumpname[len - 2] = 0;      else if (len > 3 && ! strcmp (".co", dumpname + len - 3))	dumpname[len - 3] = 0;      strcat (dumpname, ".sym");      if (sym_file_name == 0)	sym_file_name = dumpname;      symout_init (sym_file_name, asm_out_file, main_input_filename);    }  /* If dbx symbol table desired, initialize writing it     and output the predefined types.  */#ifdef DBX_DEBUGGING_INFO  if (write_symbols == DBX_DEBUG)    dbxout_init (asm_out_file, main_input_filename);#endif#ifdef SDB_DEBUGGING_INFO  if (write_symbols == SDB_DEBUG)    sdbout_init (asm_out_file, main_input_filename);#endif  /* Initialize yet another pass.  */  init_final (main_input_filename);  start_time = gettime ();  /* Call the parser, which parses the entire file     (calling rest_of_compilation for each function).  */  yyparse ();  /* Compilation is now finished except for writing     what's left of the symbol table output.  */  parse_time += gettime () - start_time;  parse_time -= integration_time;  parse_time -= varconst_time;  globals = getdecls ();  /* Really define vars that have had only a tentative definition.     Really output inline functions that must actually be callable     and have not been output so far.  */  {    tree decl;    for (decl = globals; decl; decl = TREE_CHAIN (decl))      {	if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)	    && ! TREE_ASM_WRITTEN (decl))	  {	    /* Don't write out static consts, unless we used them.	       (This used to write them out only if the address was	       taken, but that was wrong; if the variable was simply	       referred to, it still needs to exist or else it will	       be undefined in the linker.)  */	    if (! TREE_READONLY (decl)		|| TREE_USED (decl)		|| TREE_PUBLIC (decl)		|| TREE_ADDRESSABLE (decl))	      rest_of_decl_compilation (decl, 0, 1, 1);	    /* Otherwise maybe mention them just for the debugger.  */#ifdef DBX_DEBUGGING_INFO	    else if (DECL_INITIAL (decl) && write_symbols == DBX_DEBUG)	      TIMEVAR (varconst_time, dbxout_symbol (decl, 0));#endif#ifdef SDB_DEBUGGING_INFO	    else if (DECL_INITIAL (decl) && write_symbols == SDB_DEBUG)	      TIMEVAR (varconst_time, sdbout_symbol (decl, 0));#endif	  }	if (TREE_CODE (decl) == FUNCTION_DECL	    && ! TREE_ASM_WRITTEN (decl)	    && DECL_INITIAL (decl) != 0	    && TREE_ADDRESSABLE (decl)	    && ! TREE_EXTERNAL (decl))	  output_inline_function (decl);	/* Warn about any function declared static but not defined.  */	if (warn_unused	    && TREE_CODE (decl) == FUNCTION_DECL	    && DECL_INITIAL (decl) == 0	    && TREE_EXTERNAL (decl)	    && ! TREE_PUBLIC (decl))	  warning_with_decl (decl, "`%s' declared but never defined");	/* Warn about statics fns or vars defined but not used,	   but not about inline functions	   since unused inline statics is normal practice.  */	if (warn_unused	    && (TREE_CODE (decl) == FUNCTION_DECL		|| TREE_CODE (decl) == VAR_DECL)	    && ! TREE_EXTERNAL (decl)	    && ! TREE_PUBLIC (decl)	    && ! TREE_USED (decl)	    && ! TREE_INLINE (decl)	    /* The TREE_USED bit for file-scope decls	       is kept in the identifier, to handle multiple	       external decls in different scopes.  */	    && ! TREE_USED (DECL_NAME (decl)))	  warning_with_decl (decl, "`%s' defined but not used");      }  }  /* Do dbx symbols */#ifdef DBX_DEBUGGING_INFO  if (write_symbols == DBX_DEBUG)    TIMEVAR (symout_time,	     {	       dbxout_tags (gettags ());	       dbxout_types (get_permanent_types ());	     });#endif#ifdef SDB_DEBUGGING_INFO  if (write_symbols == SDB_DEBUG)    TIMEVAR (symout_time,	     {	       tree decl;	       sdbout_tags (gettags ());	       sdbout_types (get_permanent_types ());	       /* Output first static file-scope vars, then global ones.  */	       for (decl = globals; decl; decl = TREE_CHAIN (decl))		 if (TREE_CODE (decl) == VAR_DECL && !TREE_PUBLIC (decl))		   sdbout_symbol (decl, 1);	       for (decl = globals; decl; decl = TREE_CHAIN (decl))		 if (TREE_CODE (decl) == VAR_DECL && TREE_PUBLIC (decl))		   sdbout_symbol (decl, 1);	     });#endif  /* Do gdb symbols */  if (write_symbols == GDB_DEBUG)    TIMEVAR (symout_time,	     {	       struct stat statbuf;	       fstat (fileno (finput), &statbuf);	       symout_types (get_permanent_types ());	       symout_top_blocks (globals, gettags ());	       symout_finish (name, statbuf.st_ctime);	     });  /* Output some stuff at end of file if nec.  */  end_final (main_input_filename);#ifdef ASM_FILE_END  ASM_FILE_END (asm_out_file);#endif  /* Close the dump files.  */  if (rtl_dump)    fclose (rtl_dump_file);  if (jump_opt_dump)    fclose (jump_opt_dump_file);  if (cse_dump)    fclose (cse_dump_file);  if (loop_dump)    fclose (loop_dump_file);  if (flow_dump)    fclose (flow_dump_file);  if (combine_dump)    {      dump_combine_total_stats (combine_dump_file);      fclose (combine_dump_file);    }  if (local_reg_dump)    fclose (local_reg_dump_file);  if (global_reg_dump)    fclose (global_reg_dump_file);  if (jump2_opt_dump)    fclose (jump2_opt_dump_file);  if (dbr_sched_dump)    fclose (dbr_sched_dump_file);  /* Close non-debugging input and output files.  Take special care to note     whether fclose returns an error, since the pages might still be on the     buffer chain while the file is open.  */  fclose (finput);  if (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0)    fatal_io_error (asm_file_name);  /* Print the times.  */  if (! quiet_flag)    {      fprintf (stderr,"\n");      print_time ("parse", parse_time);      print_time ("integration", integration_time);      print_time ("jump", jump_time);      print_time ("cse", cse_time);      print_time ("loop", loop_time);      print_time ("flow", flow_time);      print_time ("combine", combine_time);      print_time ("local-alloc", local_alloc_time);      print_time ("global-alloc", global_alloc_time);      print_time ("dbranch", dbr_sched_time);      print_time ("final", final_time);      print_time ("varconst", varconst_time);      print_time ("symout", symout_time);      print_time ("dump", dump_time);    }}/* This is called from finish_decl (within yyparse)   for each declaration of a function or variable.   This does nothing for automatic variables.   Otherwise, it sets up the RTL and outputs any assembler code   (label definition, storage allocation and initialization).   DECL is the declaration.  If ASMSPEC is nonzero, it specifies   the assembler symbol name to be used.  TOP_LEVEL is nonzero   if this declaration is not within a function.  */voidrest_of_decl_compilation (decl, asmspec, top_level, at_end)     tree decl;     char *asmspec;     int top_level;     int at_end;{  /* Declarations of variables, and of functions defined elsewhere.  */  if (TREE_STATIC (decl) || TREE_EXTERNAL (decl))    TIMEVAR (varconst_time,	     {	       make_decl_rtl (decl, asmspec, top_level);	       /* Don't output anything		  when a tentative file-scope definition is seen.		  But at end of compilation, do output code for them.  */	       if (! (! at_end && top_level		      && (DECL_INITIAL (decl) == 0			  || DECL_INITIAL (decl) == error_mark_node)))		 assemble_variable (decl, top_level, write_symbols, at_end);	     });  else if (TREE_REGDECL (decl) && asmspec != 0)    {      if (decode_reg_name (asmspec) >= 0)	{	  DECL_RTL (decl) = 0;	  make_decl_rtl (decl, asmspec, top_level);	}      else	error ("invalid register name `%s' for register variable", asmspec);    }#ifdef DBX_DEBUGGING_INFO  else if (write_symbols == DBX_DEBUG && TREE_CODE (decl) == TYPE_DECL)    TIMEVAR (varconst_time, dbxout_symbol (decl, 0));#endif#ifdef SDB_DEBUGGING_INFO  else if (write_symbols == SDB_DEBUG && top_level	   && TREE_CODE (decl) == TYPE_DECL)    TIMEVAR (varconst_time, sdbout_symbol (decl, 0));#endif  if (top_level)    {      if (write_symbols == GDB_DEBUG)	{	  TIMEVAR (symout_time,		   {		     /* The initizations make types when they contain			string constants.  The types are on the temporary			obstack, so output them now before they go away.  */		     symout_types (get_temporary_types ());		   });	}      else	/* Clean out the temporary type list, since the types will go away.  */	get_temporary_types ();    }}/* This is called from finish_function (within yyparse)   after each top-level definition is parsed.   It is supposed to compile that function or variable   and output the assembler code for it.   After we return, the tree storage is freed.  */voidrest_of_compilation (decl)     tree decl;{  register rtx insns;  int start_time = gettime ();  int tem;  /* If we are reconsidering an inline function     at the end of compilation, skip the stuff for making it inline.  */  if (DECL_SAVED_INSNS (decl) == 0)    {      /* If requested, consider whether to make this function inline.  */      if (flag_inline_functions || TREE_INLINE (decl))	{	  TIMEVAR (integration_time,		   {		     int specd = TREE_INLINE (decl);		     char *lose = function_cannot_inline_p (decl);		     if (lose != 0 && specd)		       warning_with_decl (decl, lose);		     if (lose == 0)		       save_for_inline (decl);		     else		       TREE_INLINE (decl) = 0;		   });	}      insns = get_insns ();      /* Dump the rtl code if we are dumping rtl.  */      if (rtl_dump)	TIMEVAR (dump_time,		 {		   fprintf (rtl_dump_file, "\n;; Function %s\n\n",			    IDENTIFIER_POINTER (DECL_NAME (decl)));		   if (DECL_SAVED_INSNS (decl))		     fprintf (rtl_dump_file, ";; (integrable)\n\n");		   print_rtl (rtl_dump_file, insns);		   fflush (rtl_dump_file);		 });      /* If function is inline, and we don't yet know whether to	 compile it by itself, defer decision till end of compilation.	 finish_compilation will call rest_of_compilation again	 for those functions that need to be output.  */      if (((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)	    && ! flag_keep_inline_functions)	   || TREE_EXTERNAL (decl))	  && TREE_INLINE (decl))	goto exit_rest_of_compilation;    }  if (rtl_dump_and_exit || flag_syntax_only)    {      get_temporary_types ();      goto exit_rest_of_compilation;    }  TREE_ASM_WRITTEN (decl) = 1;  insns = get_insns ();  /* Copy any shared structure that should not be shared.  */  unshare_all_rtl (insns);  /* See if we have allocated stack slots that are not directly addressable.     If so, scan all the insns and create explicit address computation     for all references to such slots.  *//*   fixup_stack_slots (); */  /* Do jump optimization the first time, if -opt.     Also do it if -W, but in that case it doesn't change the rtl code,     it only computes whether control can drop off the end of the function.  */  if (optimize || extra_warnings || warn_return_type      /* If function is `volatile', we should warn if it tries to return.  */      || TREE_THIS_VOLATILE (decl))    TIMEVAR (jump_time, jump_optimize (insns, 0, 0));  /* Dump rtl code after jump, if we are doing that.  */  if (jump_opt_dump)    TIMEVAR (dump_time,	     {	       fprintf (jump_opt_dump_file, "\n;; Function %s\n\n",			IDENTIFIER_POINTER (DECL_NAME (decl)));	       print_rtl (jump_opt_dump_file, insns);	       fflush (jump_opt_dump_file);	     });  /* Perform common subexpression elimination.     Nonzero value from `cse_main' means that jumps were simplified     and some code may now be unreachable, so do     jump optimization again.  */  if (optimize)    {      TIMEVAR (cse_time, reg_scan (insns, max_reg_num (), 0));      TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num ()));      if (tem)	TIMEVAR (jump_time, jump_optimize (insns, 0, 0));    }  /* Dump rtl code after cse, if we are doing that.  */  if (cse_dump)    TIMEVAR (dump_time,	     {	       fprintf (cse_dump_file, "\n;; Function %s\n\n",			IDENTIFIER_POINTER (DECL_NAME (decl)));	       print_rtl (cse_dump_file, insns);	       fflush (cse_dump_file);	     });  if (loop_dump)    TIMEVAR (dump_time,	     {	       fprintf (loop_dump_file, "\n;; Function %s\n\n",			IDENTIFIER_POINTER (DECL_NAME (decl)));	     });  /* Move constant computations out of loops.  */  if (optimize)    {      TIMEVAR (loop_time,	       {		 reg_scan (insns, max_reg_num (), 1);		 loop_optimize (insns, loop_dump ? loop_dump_file : 0);	       });    }  /* Dump rtl code after loop opt, if we are doing that.  */  if (loop_dump)    TIMEVAR (dump_time,	     {	       print_rtl (loop_dump_file, insns);	       fflush (loop_dump_file);	     });  /* Now we choose between stupid (pcc-like) register allocation     (if we got the -noreg switch and not -opt)     and smart register allocation.  */  if (optimize)		/* Stupid allocation probably won't work */    obey_regdecls = 0;	/* if optimizations being done.  */  regclass_init ();  /* Print function header into flow dump now     because doing the flow analysis makes some of the dump.  */  if (flow_dump)    TIMEVAR (dump_time,	     {	       fprintf (flow_dump_file, "\n;; Function %s\n\n",			IDENTIFIER_POINTER (DECL_NAME (decl)));	     });  if (obey_regdecls)    {      TIMEVAR (flow_time,	       {		 regclass (insns, max_reg_num ());		 stupid_life_analysis (insns, max_reg_num (),				       flow_dump_file);	       });    }  else    {      /* Do control and data flow analysis,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -