#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "line-map.h"
-#include "input.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "varasm.h"
#include "tree-inline.h"
#include "realmpfr.h" /* For GMP/MPFR/MPC versions, in print_version. */
#include "recog.h"
#include "output.h"
#include "except.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
#include "function.h"
#include "toplev.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "intl.h"
#include "regs.h"
#include "hosthooks.h"
#include "predict.h"
#include "basic-block.h"
-#include "hash-map.h"
-#include "is-a.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
#include "cgraph.h"
#include "opts.h"
#include "opts-diagnostic.h"
declarations for e.g. AIX 4.x. */
#endif
+#ifndef HAVE_prologue
+#define HAVE_prologue 0
+#endif
+
#include <new>
-static void general_init (const char *);
+static void general_init (const char *, bool);
static void do_compile ();
static void process_options (void);
static void backend_init (void);
int fd = open ("/dev/urandom", O_RDONLY);
if (fd >= 0)
{
- read (fd, &random_seed, sizeof (random_seed));
+ if (read (fd, &random_seed, sizeof (random_seed))
+ != sizeof (random_seed))
+ random_seed = 0;
close (fd);
}
return output_something;
}
-/* A subroutine of check_global_declarations. Issue appropriate warnings
- for the global declaration DECL. */
+/* Issue appropriate warnings for the global declaration DECL. */
void
-check_global_declaration_1 (tree decl)
+check_global_declaration (tree decl)
{
/* Warn about any function declared static but not defined. We don't
warn about variables, because many programs have static variables
that exist only to get some text into the object file. */
+ symtab_node *snode = symtab_node::get (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) == 0
&& DECL_EXTERNAL (decl)
&& ! TREE_NO_WARNING (decl)
&& ! TREE_PUBLIC (decl)
&& (warn_unused_function
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ || snode->referred_to_p (/*include_self=*/false)))
{
- if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ if (snode->referred_to_p (/*include_self=*/false))
pedwarn (input_location, 0, "%q+F used but never defined", decl);
else
warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl);
|| (warn_unused_variable
&& TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl)
+ && ! snode->referred_to_p (/*include_self=*/false)
+ /* This TREE_USED check is needed in addition to referred_to_p
+ above, because the `__unused__' attribute is not being
+ considered for referred_to_p. */
&& ! TREE_USED (decl)
/* The TREE_USED bit for file-scope decls is kept in the identifier,
to handle multiple external decls in different scopes. */
&& ! (DECL_NAME (decl) && TREE_USED (DECL_NAME (decl)))
&& ! DECL_EXTERNAL (decl)
+ && ! DECL_ARTIFICIAL (decl)
+ && ! DECL_ABSTRACT_ORIGIN (decl)
&& ! TREE_PUBLIC (decl)
/* A volatile variable might be used in some non-obvious way. */
&& ! TREE_THIS_VOLATILE (decl)
/* Global register variables must be declared to reserve them. */
&& ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ /* Global ctors and dtors are called by the runtime. */
+ && (TREE_CODE (decl) != FUNCTION_DECL
+ || (!DECL_STATIC_CONSTRUCTOR (decl)
+ && !DECL_STATIC_DESTRUCTOR (decl)))
/* Otherwise, ask the language. */
&& lang_hooks.decls.warn_unused_global (decl))
warning ((TREE_CODE (decl) == FUNCTION_DECL)
"%q+D defined but not used", decl);
}
-/* Issue appropriate warnings for the global declarations in V (of
- which there are LEN). */
-
-void
-check_global_declarations (tree *v, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- check_global_declaration_1 (v[i]);
-}
-
-/* Emit debugging information for all global declarations in VEC. */
-
-void
-emit_debug_global_declarations (tree *vec, int len)
-{
- int i;
-
- /* Avoid confusing the debug information machinery when there are errors. */
- if (seen_error ())
- return;
-
- timevar_push (TV_SYMOUT);
- for (i = 0; i < len; i++)
- debug_hooks->global_decl (vec[i]);
- timevar_pop (TV_SYMOUT);
-}
-
/* Compile an entire translation unit. Write a file of assembly
output and various debugging dumps. */
timevar_start (TV_PHASE_PARSING);
timevar_push (TV_PARSE_GLOBAL);
- /* Call the parser, which parses the entire file (calling
- rest_of_compilation for each function). */
+ /* Parse entire file and generate initial debug information. */
lang_hooks.parse_file ();
timevar_pop (TV_PARSE_GLOBAL);
timevar_stop (TV_PHASE_PARSING);
+ if (flag_dump_locations)
+ dump_location_info (stderr);
+
/* Compilation is now finished except for writing
what's left of the symbol table output. */
ggc_protect_identifiers = false;
- /* This must also call finalize_compilation_unit. */
- lang_hooks.decls.final_write_globals ();
+ /* Run the actual compilation process. */
+ if (!in_lto_p)
+ {
+ timevar_start (TV_PHASE_OPT_GEN);
+ symtab->finalize_compilation_unit ();
+ timevar_stop (TV_PHASE_OPT_GEN);
+ }
+
+ /* Perform any post compilation-proper parser cleanups and
+ processing. This is currently only needed for the C++ parser,
+ which can be hopefully cleaned up so this hook is no longer
+ necessary. */
+ if (lang_hooks.decls.post_compilation_parsing_cleanups)
+ lang_hooks.decls.post_compilation_parsing_cleanups ();
if (seen_error ())
return;
+ /* After the parser has generated debugging information, augment
+ this information with any new location/etc information that may
+ have become available after the compilation proper. */
+ timevar_start (TV_PHASE_DBGINFO);
+ symtab_node *node;
+ FOR_EACH_DEFINED_SYMBOL (node)
+ debug_hooks->late_global_decl (node->decl);
+ timevar_stop (TV_PHASE_DBGINFO);
+
timevar_start (TV_PHASE_LATE_ASM);
/* Compilation unit is finalized. When producing non-fat LTO object, we are
/* Print version information to FILE.
Each line begins with INDENT (for the case where FILE is the
- assembler output file). */
+ assembler output file).
+
+ If SHOW_GLOBAL_STATE is true (for cc1 etc), we are within the compiler
+ proper and can print pertinent state (e.g. params and plugins).
+
+ If SHOW_GLOBAL_STATE is false (for use by libgccjit), we are outside the
+ compiler, and we don't hold the mutex on the compiler's global state:
+ we can't print params and plugins, since they might not be initialized,
+ or might be being manipulated by a compile running in another
+ thread. */
void
-print_version (FILE *file, const char *indent)
+print_version (FILE *file, const char *indent, bool show_global_state)
{
static const char fmt1[] =
#ifdef __GNUC__
file == stderr ? _(fmt3) : fmt3,
indent, *indent != 0 ? " " : "",
"MPC", MPC_VERSION_STRING, mpc_get_version ());
- fprintf (file,
- file == stderr ? _(fmt4) : fmt4,
- indent, *indent != 0 ? " " : "",
- PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
- print_plugins_versions (file, indent);
+ if (show_global_state)
+ {
+ fprintf (file,
+ file == stderr ? _(fmt4) : fmt4,
+ indent, *indent != 0 ? " " : "",
+ PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
+
+ print_plugins_versions (file, indent);
+ }
}
static int
|| !strcmp (asm_file_name, HOST_BIT_BUCKET))
asm_out_file = fopen (asm_file_name, "w");
else
- /* Use fatal_error (UNKOWN_LOCATION) instead of just fatal_error to
- prevent gcc from printing the first line in the current file. */
+ /* Use UNKOWN_LOCATION to prevent gcc from printing the first
+ line in the current file. */
fatal_error (UNKNOWN_LOCATION,
"input file %qs is the same as output file",
asm_file_name);
{
/* Print the list of switches in effect
into the assembler file as comments. */
- print_version (asm_out_file, ASM_COMMENT_START);
+ print_version (asm_out_file, ASM_COMMENT_START, true);
print_switch_values (print_to_asm_out_file);
putc ('\n', asm_out_file);
}
}
fprintf (stack_usage_file,
- "%s:%d:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n",
+ "%s:%d:%d:%s\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
lbasename (loc.file),
loc.line,
loc.column,
filename = concat (aux_base_name, ".", ext, NULL);
file = fopen (filename, "w");
if (!file)
- fatal_error ("can%'t open %s for writing: %m", filename);
+ fatal_error (input_location, "can%'t open %s for writing: %m", filename);
free (filename);
return file;
}
options are parsed. Signal handlers, internationalization etc.
ARGV0 is main's argv[0]. */
static void
-general_init (const char *argv0)
+general_init (const char *argv0, bool init_signals)
{
const char *p;
global_dc->option_state = &global_options;
global_dc->option_name = option_name;
- /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
+ if (init_signals)
+ {
+ /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
#ifdef SIGSEGV
- signal (SIGSEGV, crash_signal);
+ signal (SIGSEGV, crash_signal);
#endif
#ifdef SIGILL
- signal (SIGILL, crash_signal);
+ signal (SIGILL, crash_signal);
#endif
#ifdef SIGBUS
- signal (SIGBUS, crash_signal);
+ signal (SIGBUS, crash_signal);
#endif
#ifdef SIGABRT
- signal (SIGABRT, crash_signal);
+ signal (SIGABRT, crash_signal);
#endif
#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
- signal (SIGIOT, crash_signal);
+ signal (SIGIOT, crash_signal);
#endif
#ifdef SIGFPE
- signal (SIGFPE, crash_signal);
+ signal (SIGFPE, crash_signal);
#endif
- /* Other host-specific signal setup. */
- (*host_hooks.extra_signals)();
+ /* Other host-specific signal setup. */
+ (*host_hooks.extra_signals)();
+ }
/* Initialize the garbage-collector, string pools and tree type hash
table. */
if (flag_check_pointer_bounds)
{
if (targetm.chkp_bound_mode () == VOIDmode)
- error ("-fcheck-pointer-bounds is not supported for this target");
+ {
+ error ("-fcheck-pointer-bounds is not supported for this target");
+ flag_check_pointer_bounds = 0;
+ }
+
+ if (flag_sanitize & SANITIZE_ADDRESS)
+ {
+ error ("-fcheck-pointer-bounds is not supported with "
+ "Address Sanitizer");
+ flag_check_pointer_bounds = 0;
+ }
}
/* One region RA really helps to decrease the code size. */
option flags in use. */
if (version_flag)
{
- print_version (stderr, "");
+ print_version (stderr, "", true);
if (! quiet_flag)
print_switch_values (print_to_stderr);
}
warning (0, "var-tracking-assignments changes selective scheduling");
if (flag_tree_cselim == AUTODETECT_VALUE)
-#ifdef HAVE_conditional_move
- flag_tree_cselim = 1;
-#else
- flag_tree_cselim = 0;
-#endif
+ {
+ if (HAVE_conditional_move)
+ flag_tree_cselim = 1;
+ else
+ flag_tree_cselim = 0;
+ }
/* If auxiliary info generation is desired, open the output file.
This goes in the same directory as the source file--unlike
{
aux_info_file = fopen (aux_info_file_name, "w");
if (aux_info_file == 0)
- fatal_error ("can%'t open %s: %m", aux_info_file_name);
+ fatal_error (input_location, "can%'t open %s: %m", aux_info_file_name);
}
if (!targetm_common.have_named_sections)
flag_sanitize &= ~SANITIZE_ADDRESS;
}
+ /* Do not use IPA optimizations for register allocation if profiler is active
+ or port does not emit prologue and epilogue as RTL. */
+ if (profile_flag || !HAVE_prologue || !HAVE_epilogue)
+ flag_ipa_ra = 0;
+
/* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
have not been set. */
if (!global_options_set.x_warnings_are_errors
/* Save the current optimization options. */
optimization_default_node = build_optimization_node (&global_options);
optimization_current_node = optimization_default_node;
+
+ /* Please don't change global_options after this point, those changes won't
+ be reflected in optimization_{default,current}_node. */
}
/* This function can be called multiple times to reinitialize the compiler
void
initialize_rtl (void)
{
+ auto_timevar tv (TV_INITIALIZE_RTL);
+
/* Initialization done just once per compilation, but delayed
till code generation. */
if (!rtl_initialized)
dump_rtx_statistics ();
dump_alloc_pool_statistics ();
dump_bitmap_statistics ();
+ dump_hash_table_loc_statistics ();
dump_vec_loc_statistics ();
dump_ggc_loc_statistics (final);
dump_alias_stats (stderr);
if (asm_out_file)
{
if (ferror (asm_out_file) != 0)
- fatal_error ("error writing to %s: %m", asm_file_name);
+ fatal_error (input_location, "error writing to %s: %m", asm_file_name);
if (fclose (asm_out_file) != 0)
- fatal_error ("error closing %s: %m", asm_file_name);
+ fatal_error (input_location, "error closing %s: %m", asm_file_name);
}
if (stack_usage_file)
}
}
-toplev::toplev (bool use_TV_TOTAL)
- : m_use_TV_TOTAL (use_TV_TOTAL)
+toplev::toplev (bool use_TV_TOTAL, bool init_signals)
+ : m_use_TV_TOTAL (use_TV_TOTAL),
+ m_init_signals (init_signals)
{
if (!m_use_TV_TOTAL)
start_timevars ();
toplev::~toplev ()
{
- timevar_stop (TV_TOTAL);
- timevar_print (stderr);
+ if (g_timer)
+ {
+ g_timer->stop (TV_TOTAL);
+ g_timer->print (stderr);
+ }
}
void
expandargv (&argc, &argv);
/* Initialization of GCC's environment, and diagnostics. */
- general_init (argv[0]);
+ general_init (argv[0], m_init_signals);
/* One-off initialization of options that does not need to be
repeated when options are added for particular functions. */
initialize_plugins ();
if (version_flag)
- print_version (stderr, "");
+ print_version (stderr, "", true);
if (help_flag)
print_plugins_help (stderr, "");