From 66d62d9f2e6b059be6a018397fba555147133a9a Mon Sep 17 00:00:00 2001 From: Hrishikesh Kulkarni Date: Mon, 6 May 2019 07:23:25 +0000 Subject: [PATCH] Add lto-dump tool. 2019-05-06 Hrishikesh Kulkarni Martin Liska * Makefile.in: Add lto-dump.texi. * cgraph.h: Add new functions get_visibility_string and get_symtab_type_string. * doc/gcc.texi: Include lto-dump section. * doc/lto-dump.texi: New file. * dumpfile.c (dump_switch_p_1): Use parse_dump_option. (parse_dump_option): Factor out this function. * dumpfile.h (enum dump_flag): Add new value TDF_ERROR. (parse_dump_option): Export the function. * symtab.c (symtab_node::get_visibility_string): New function. (symtab_node::get_symtab_type_string): Likewise. 2019-05-06 Hrishikesh Kulkarni Martin Liska * Make-lang.in: Add lto_dump-related definition. * config-lang.in: Likewise. * lang.opt: Add new language LTODump and options related to LTO dump tool. * lto-common.c (lto_read_decls): Support type statistics dump. (lto_file_read): Likewise for object files. * lto-dump.c: New file. * lto-lang.c (lto_option_lang_mask): Move from .. * lto.c (lto_option_lang_mask): .. here. * lto.h (lto_option_lang_mask): New declaration. Co-Authored-By: Martin Liska From-SVN: r270897 --- gcc/ChangeLog | 15 ++ gcc/Makefile.in | 2 +- gcc/cgraph.h | 6 + gcc/doc/gcc.texi | 5 + gcc/doc/lto-dump.texi | 131 ++++++++++++++++ gcc/dumpfile.c | 85 ++++++---- gcc/dumpfile.h | 5 + gcc/lto/ChangeLog | 14 ++ gcc/lto/Make-lang.in | 20 ++- gcc/lto/config-lang.in | 4 +- gcc/lto/lang.opt | 62 ++++++++ gcc/lto/lto-common.c | 40 +++++ gcc/lto/lto-dump.c | 344 +++++++++++++++++++++++++++++++++++++++++ gcc/lto/lto-lang.c | 6 - gcc/lto/lto.c | 6 + gcc/lto/lto.h | 2 + gcc/symtab.c | 17 ++ 17 files changed, 721 insertions(+), 43 deletions(-) create mode 100644 gcc/doc/lto-dump.texi create mode 100644 gcc/lto/lto-dump.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4ca21620723..06ba752591d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2019-05-06 Hrishikesh Kulkarni + Martin Liska + + * Makefile.in: Add lto-dump.texi. + * cgraph.h: Add new functions get_visibility_string and + get_symtab_type_string. + * doc/gcc.texi: Include lto-dump section. + * doc/lto-dump.texi: New file. + * dumpfile.c (dump_switch_p_1): Use parse_dump_option. + (parse_dump_option): Factor out this function. + * dumpfile.h (enum dump_flag): Add new value TDF_ERROR. + (parse_dump_option): Export the function. + * symtab.c (symtab_node::get_visibility_string): New function. + (symtab_node::get_symtab_type_string): Likewise. + 2019-05-06 Martin Liska * config/i386/i386-builtins.c: New file. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 5f43d9de00e..6677f77c76f 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3157,7 +3157,7 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi \ gcov.texi trouble.texi bugreport.texi service.texi \ contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi \ fdl.texi contrib.texi cppenv.texi cppopts.texi avr-mmcu.texi \ - implement-c.texi implement-cxx.texi gcov-tool.texi gcov-dump.texi + implement-c.texi implement-cxx.texi gcov-tool.texi gcov-dump.texi lto-dump.texi # we explicitly use $(srcdir)/doc/tm.texi here to avoid confusion with # the generated tm.texi; the latter might have a more recent timestamp, diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 9a19d83fffb..18839a4a5ec 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -119,6 +119,12 @@ public: /* Return dump name with assembler name. */ const char *dump_asm_name () const; + /* Return visibility name. */ + const char *get_visibility_string () const; + + /* Return type_name name. */ + const char *get_symtab_type_string () const; + /* Add node into symbol table. This function is not used directly, but via cgraph/varpool node creation routines. */ void register_symbol (void); diff --git a/gcc/doc/gcc.texi b/gcc/doc/gcc.texi index 5297b9cb5d0..4d03e3a6d96 100644 --- a/gcc/doc/gcc.texi +++ b/gcc/doc/gcc.texi @@ -68,6 +68,8 @@ Texts being (a) (see below), and with the Back-Cover Texts being (b) * gcov: (gcc) Gcov. @command{gcov}---a test coverage program. * gcov-tool: (gcc) Gcov-tool. @command{gcov-tool}---an offline gcda profile processing program. * gcov-dump: (gcc) Gcov-dump. @command{gcov-dump}---an offline gcda and gcno profile dump tool. +* lto-dump: (gcc) lto-dump. @command{lto-dump}---Tool for +dumping LTO object files. @end direntry This file documents the use of the GNU compilers. @sp 1 @@ -142,6 +144,8 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}. * Gcov:: @command{gcov}---a test coverage program. * Gcov-tool:: @command{gcov-tool}---an offline gcda profile processing program. * Gcov-dump:: @command{gcov-dump}---an offline gcda and gcno profile dump tool. +* lto-dump:: @command{lto-dump}---Tool for dumping LTO +object files. * Trouble:: If you have trouble using GCC. * Bugs:: How, why and where to report bugs. * Service:: How To Get Help with GCC @@ -170,6 +174,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}. @include gcov.texi @include gcov-tool.texi @include gcov-dump.texi +@include lto-dump.texi @include trouble.texi @include bugreport.texi @include service.texi diff --git a/gcc/doc/lto-dump.texi b/gcc/doc/lto-dump.texi new file mode 100644 index 00000000000..d84397581c0 --- /dev/null +++ b/gcc/doc/lto-dump.texi @@ -0,0 +1,131 @@ +@c Copyright (C) 2018-2019 Free Software Foundation, Inc. +@c This is part of the GCC manual. +@c For copying conditions, see the file gcc.texi. + +@ignore +@c man begin COPYRIGHT +Copyright @copyright{} 2017-2018 Free Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with the +Invariant Sections being ``GNU General Public License'' and ``Funding +Free Software'', the Front-Cover texts being (a) (see below), and with +the Back-Cover Texts being (b) (see below). A copy of the license is +included in the gfdl(7) man page. + +(a) The FSF's Front-Cover Text is: + + A GNU Manual + +(b) The FSF's Back-Cover Text is: + + You have freedom to copy and modify this GNU Manual, like GNU + software. Copies published by the Free Software Foundation raise + funds for GNU development. +@c man end +@c Set file name and title for the man page. +@setfilename lto-dump +@settitle Tool for dumping LTO object files. +@end ignore + +@node lto-dump +@chapter @command{lto-dump}---Tool for dumping LTO object files. + +@menu +* lto-dump Intro:: Introduction to lto-dump. +* Invoking lto-dump:: How to use lto-dump. +@end menu + +@node lto-dump Intro +@section Introduction to @command{lto-dump} +@c man begin DESCRIPTION + +@command{lto-dump} is a tool you can use in conjunction with GCC to +dump link time optimization object files. + +@c man end + +@node Invoking lto-dump +@section Invoking @command{lto-dump} + +@smallexample +Usage: lto-dump @r{[}@var{OPTION}@r{]} ... @var{objfiles} +@end smallexample + +@command{lto-dump} accepts the following options: + +@ignore +@c man begin SYNOPSIS +lto-dump [@option{-list}] + [@option{-demangle}] + [@option{-defined-only}] + [@option{-print-value}] + [@option{-name-sort}] + [@option{-size-sort}] + [@option{-reverse-sort}] + [@option{-no-sort}] + [@option{-symbol=}] + [@option{-objects}] + [@option{-type-stats}] + [@option{-tree-stats}] + [@option{-gimple-stats}] + [@option{-dump-level=}] + [@option{-dump-body=}] + [@option{-help}] @var{lto-dump} +@c man end +@end ignore + +@c man begin OPTIONS +@table @gcctabopt +@item -list +Dumps list of details of functions and variables. + +@item -demangle +Dump the demangled output. + +@item -defined-only +Dump only the defined symbols. + +@item -print-value +Dump initial values of the variables. + +@item -name-sort +Sort the symbols alphabetically. + +@item -size-sort +Sort the symbols according to size. + +@item -reverse-sort +Dump the symbols in reverse order. + +@item -no-sort +Dump the symbols in order of occurrence. + +@item -symbol= +Dump the details of specific symbol. + +@item -objects +Dump the details of LTO objects. + +@item -type-stats +Dump the statistics of tree types. + +@item -tree-stats +Dump the statistics of trees. + +@item -gimple-stats +Dump the statistics of gimple statements. + +@item -dump-level= +For deciding the optimization level of body. + +@item -dump-body= +Dump the specific gimple body. + +@item -help +Display the dump tool help. + +@end table + +@c man end diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c index 14b6dfea75e..5263d3a2134 100644 --- a/gcc/dumpfile.c +++ b/gcc/dumpfile.c @@ -115,6 +115,7 @@ static struct dump_file_info dump_files[TDI_end] = in dumpfile.h and opt_info_options below. */ static const kv_pair dump_options[] = { + {"none", TDF_NONE}, {"address", TDF_ADDRESS}, {"asmname", TDF_ASMNAME}, {"slim", TDF_SLIM}, @@ -1770,28 +1771,19 @@ gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const return true; } -/* Parse ARG as a dump switch. Return nonzero if it is, and store the - relevant details in the dump_files array. */ +/* Helper routine to parse -[=filename] + and return the corresponding dump flag. If POS_P is non-NULL, + assign start of filename into *POS_P. */ -int -gcc::dump_manager:: -dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) +dump_flags_t +parse_dump_option (const char *option_value, const char **pos_p) { - const char *option_value; const char *ptr; dump_flags_t flags; - if (doglob && !dfi->glob) - return 0; - - option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch); - if (!option_value) - return 0; - - if (*option_value && *option_value != '-' && *option_value != '=') - return 0; - ptr = option_value; + if (pos_p) + *pos_p = NULL; /* Retain "user-facing" and "internals" messages, but filter out those from an opt_problem being re-emitted at the top level @@ -1805,14 +1797,13 @@ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) const char *end_ptr; const char *eq_ptr; unsigned length; - while (*ptr == '-') ptr++; end_ptr = strchr (ptr, '-'); eq_ptr = strchr (ptr, '='); if (eq_ptr && !end_ptr) - end_ptr = eq_ptr; + end_ptr = eq_ptr; if (!end_ptr) end_ptr = ptr + strlen (ptr); @@ -1821,25 +1812,59 @@ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) for (option_ptr = dump_options; option_ptr->name; option_ptr++) if (strlen (option_ptr->name) == length && !memcmp (option_ptr->name, ptr, length)) - { - flags |= option_ptr->value; + { + flags |= option_ptr->value; goto found; - } + } if (*ptr == '=') - { + { /* Interpret rest of the argument as a dump filename. This filename overrides other command line filenames. */ - if (dfi->pfilename) - free (CONST_CAST (char *, dfi->pfilename)); - dfi->pfilename = xstrdup (ptr + 1); - break; - } + if (pos_p) + *pos_p = ptr + 1; + break; + } else - warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>", - length, ptr, dfi->swtch); - found:; + { + warning (0, "ignoring unknown option %q.*s", + length, ptr); + flags = TDF_ERROR; + } + found: ptr = end_ptr; + } + + return flags; +} + +/* Parse ARG as a dump switch. Return nonzero if it is, and store the + relevant details in the dump_files array. */ + +int +gcc::dump_manager:: +dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob) +{ + const char *option_value; + dump_flags_t flags = TDF_NONE; + + if (doglob && !dfi->glob) + return 0; + + option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch); + if (!option_value) + return 0; + + if (*option_value && *option_value != '-' && *option_value != '=') + return 0; + + const char *filename; + flags = parse_dump_option (option_value, &filename); + if (filename) + { + if (dfi->pfilename) + free (CONST_CAST (char *, dfi->pfilename)); + dfi->pfilename = xstrdup (filename); } dfi->pstate = -1; diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h index 1f9ac427f75..9bcaa25b0a5 100644 --- a/gcc/dumpfile.h +++ b/gcc/dumpfile.h @@ -193,6 +193,9 @@ enum dump_flag /* Dumping for -fcompare-debug. */ TDF_COMPARE_DEBUG = (1 << 28), + /* For error. */ + TDF_ERROR = (1 << 26), + /* All values. */ TDF_ALL_VALUES = (1 << 29) - 1 }; @@ -501,6 +504,8 @@ extern void dump_end (int, FILE *); extern int opt_info_switch_p (const char *); extern const char *dump_flag_name (int); extern const kv_pair optgroup_options[]; +extern dump_flags_t +parse_dump_option (const char *, const char **); /* Global variables used to communicate with passes. */ extern FILE *dump_file; diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 527d856ef3d..b2bd6b46c39 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,17 @@ +2019-05-06 Hrishikesh Kulkarni + Martin Liska + + * Make-lang.in: Add lto_dump-related definition. + * config-lang.in: Likewise. + * lang.opt: Add new language LTODump and options related + to LTO dump tool. + * lto-common.c (lto_read_decls): Support type statistics dump. + (lto_file_read): Likewise for object files. + * lto-dump.c: New file. + * lto-lang.c (lto_option_lang_mask): Move from .. + * lto.c (lto_option_lang_mask): .. here. + * lto.h (lto_option_lang_mask): New declaration. + 2019-05-06 Martin Liska Hrishikesh Kulkarni diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in index b7ed96eac29..92487e1f53e 100644 --- a/gcc/lto/Make-lang.in +++ b/gcc/lto/Make-lang.in @@ -21,9 +21,12 @@ # The name of the LTO compiler. LTO_EXE = lto1$(exeext) +LTO_DUMP_EXE = lto-dump$(exeext) # The LTO-specific object files inclued in $(LTO_EXE). LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-common.o lto_OBJS = $(LTO_OBJS) +LTO_DUMP_OBJS = lto/lto-lang.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-dump.o lto/lto-common.o +lto_dump_OBJS = $(LTO_DUMP_OBJS) # this is only useful in a LTO bootstrap, but this does not work right # now. Should reenable after this is fixed, but only when LTO bootstrap @@ -39,11 +42,14 @@ lto_OBJS = $(LTO_OBJS) # These hooks are used by the main GCC Makefile. Consult that # Makefile for documentation. -lto.all.cross: $(LTO_EXE) -lto.start.encap: $(LTO_EXE) +lto.all.cross: $(LTO_EXE) $(LTO_DUMP_EXE) +lto.start.encap: $(LTO_EXE) $(LTO_DUMP_EXE) lto.rest.encap: lto.tags: -lto.install-common: +lto.install-common: installdirs + $(INSTALL_PROGRAM) $(LTO_DUMP_EXE) \ + $(DESTDIR)/$(bindir)/$(LTO_DUMP_EXE) + lto.install-man: lto.install-info: lto.dvi: @@ -60,7 +66,7 @@ lto.srcinfo: lto.install-plugin: lto.mostlyclean: - rm -f $(LTO_OBJS) $(LTO_EXE) lto1.fda + rm -f $(LTO_OBJS) $(LTO_EXE) lto1.fda $(LTO_DUMP_OBJS) $(LTO_DUMP_EXE) lto-dump.fda lto.clean: lto.distclean: @@ -81,6 +87,12 @@ $(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS) +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ $(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS) +$(LTO_DUMP_EXE): $(LTO_EXE) $(LTO_DUMP_OBJS) $(BACKEND) $(LIBDEPS) + +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + $(LTO_DUMP_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS) + +lto/lto-dump.o: $(LTO_EXE) + lto1.fda: ../prev-gcc/lto1$(exeext) ../prev-gcc/$(PERF_DATA) $(CREATE_GCOV) -binary ../prev-gcc/lto1$(exeext) -gcov lto1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1 diff --git a/gcc/lto/config-lang.in b/gcc/lto/config-lang.in index 07214365fd8..37c8f6e12b1 100644 --- a/gcc/lto/config-lang.in +++ b/gcc/lto/config-lang.in @@ -18,9 +18,9 @@ # . language="lto" -compilers="lto1\$(exeext)" +compilers="lto1\$(exeext) lto-dump\$(exeext)" -gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c \$(srcdir)/lto/lto.h \$(srcdir)/lto/lto-common.h \$(srcdir)/lto/lto-common.c" +gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c \$(srcdir)/lto/lto.h \$(srcdir)/lto/lto-common.h \$(srcdir)/lto/lto-common.c \$(srcdir)/lto/lto-dump.c" # LTO is a special front end. From a user's perspective it is not # really a language, but a middle end feature. However, the GIMPLE diff --git a/gcc/lto/lang.opt b/gcc/lto/lang.opt index 4c4c1ced38c..5bacef349e3 100644 --- a/gcc/lto/lang.opt +++ b/gcc/lto/lang.opt @@ -24,6 +24,9 @@ Language LTO +Language +LTODump + Enum Name(lto_linker_output) Type(enum lto_linker_output) UnknownError(unknown linker output %qs) @@ -66,6 +69,65 @@ fwpa= LTO Driver RejectNegative Joined Var(flag_wpa) Whole program analysis (WPA) mode with number of parallel jobs specified. + +list +LTODump Var(flag_lto_dump_list) +Call the dump function for variables and function in IL. + +demangle +LTODump Var(flag_lto_dump_demangle) +Dump the demangled output. + +defined-only +LTODump Var(flag_lto_dump_defined) +Dump only the defined symbols. + +print-value +LTODump Var(flag_lto_print_value) +Print the initial values of the variables. + +name-sort +LTODump Var(flag_lto_name_sort) +Sort the symbols alphabetically. + +size-sort +LTODump Var(flag_lto_size_sort) +Sort the symbols according to size. + +reverse-sort +LTODump Var(flag_lto_reverse_sort) +Display the symbols in reverse order. + +symbol= +LTODump RejectNegative Joined Var(flag_lto_dump_symbol) + +objects +LTODump Var(flag_lto_dump_objects) +Dump the details of LTO objects. + +type-stats +LTODump Var(flag_lto_dump_type_stats) +Dump the statistics of tree types. + +tree-stats +LTODump Var(flag_lto_tree_stats) +Dump the statistics of trees. + +gimple-stats +LTODump Var(flag_lto_gimple_stats) +Dump the statistics of gimple statements. + +dump-level= +LTODump RejectNegative Joined Var(flag_dump_level) + +dump-body= +LTODump RejectNegative Joined Var(flag_dump_body) + +help +LTODump Var(flag_lto_dump_tool_help) +Dump the dump tool command line options. + + fresolution= LTO Joined The resolution file. diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c index 9d5b034729e..01470c17080 100644 --- a/gcc/lto/lto-common.c +++ b/gcc/lto/lto-common.c @@ -1681,6 +1681,10 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, /* We do not uniquify the pre-loaded cache entries, those are middle-end internal types that should not be merged. */ + typedef int_hash code_id_hash; + hash_map hm; + unsigned total = 0; + /* Read the global declarations and types. */ while (ib_main.p < ib_main.len) { @@ -1730,6 +1734,15 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, chains. */ if (TYPE_P (t)) { + /* Map the tree types to their frequencies. */ + if (flag_lto_dump_type_stats) + { + unsigned key = (unsigned) TREE_CODE (t); + unsigned *countp = hm.get (key); + hm.put (key, countp ? (*countp) + 1 : 1); + total++; + } + seen_type = true; num_prevailing_types++; lto_fixup_prevailing_type (t); @@ -1775,6 +1788,22 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, gcc_assert (t && data_in->reader_cache->nodes.length () == from); } } + + /* Dump type statistics. */ + if (flag_lto_dump_type_stats) + { + fprintf (stdout, " Type Frequency Percentage\n\n"); + for (hash_map::iterator itr = hm.begin (); + itr != hm.end (); + ++itr) + { + std::pair p = *itr; + enum tree_code code = (enum tree_code) p.first; + fprintf (stdout, "%14s %6d %12.2f\n", get_tree_code_name (code), + p.second, float (p.second)/total*100); + } + } + data_in->location_cache.apply_location_cache (); /* Read in lto_in_decl_state objects. */ @@ -2074,6 +2103,17 @@ lto_file_read (lto_file *file, FILE *resolution_file, int *count) memset (§ion_list, 0, sizeof (struct lto_section_list)); section_hash_table = lto_obj_build_section_table (file, §ion_list); + /* Dump the details of LTO objects. */ + if (flag_lto_dump_objects) + { + int i=0; + fprintf (stdout, "\n LTO Object Name: %s\n", file->filename); + fprintf (stdout, "\nNo. Offset Size Section Name\n\n"); + for (section = section_list.first; section != NULL; section = section->next) + fprintf (stdout, "%2d %8ld %8ld %s\n", + ++i, section->start, section->len, section->name); + } + /* Find all sub modules in the object and put their sections into new hash tables in a splay tree. */ file_ids = lto_splay_tree_new (); diff --git a/gcc/lto/lto-dump.c b/gcc/lto/lto-dump.c new file mode 100644 index 00000000000..d23d346d0d6 --- /dev/null +++ b/gcc/lto/lto-dump.c @@ -0,0 +1,344 @@ +/* Functions for LTO dump tool. + Copyright (C) 2018-2019 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "function.h" +#include "basic-block.h" +#include "tree.h" +#include "gimple.h" +#include "cfg.h" +#include "tree-cfg.h" +#include "tree-pass.h" +#include "tree-streamer.h" +#include "cgraph.h" +#include "opts.h" +#include "debug.h" +#include "lto-partition.h" +#include "tree-pretty-print.h" +#include "lto-common.h" + +/* Stores details of symbols for dumping symbol list. */ + +struct symbol_entry +{ + symtab_node *node; + symbol_entry (symtab_node *node_): node (node_) + {} + + char* get_name () const + { + if (flag_lto_dump_demangle) + return xstrdup (node->name ()); + else + return xstrdup (node->asm_name ()); + } + + virtual size_t get_size () const = 0; + + virtual void dump () + { + const char *name = get_name (); + const char *type_name = node->get_symtab_type_string (); + const char *visibility = node->get_visibility_string (); + size_t sz = get_size (); + printf ("%s %s %4lu %s ", type_name, visibility, sz, name); + } +}; + +/* Stores variable specific details of symbols for dumping symbol list. */ + +struct variable_entry: public symbol_entry +{ + variable_entry (varpool_node *node_): symbol_entry (node_) + {} + + virtual size_t get_size () const + { + varpool_node *vnode = dyn_cast (node); + if (DECL_SIZE (vnode->decl) && tree_fits_shwi_p (DECL_SIZE (vnode->decl))) + return tree_to_shwi (DECL_SIZE (vnode->decl)); + return 0; + } + + virtual void dump () + { + symbol_entry :: dump (); + varpool_node *vnode = dyn_cast (node); + vnode->get_constructor (); + tree value_tree = DECL_INITIAL (vnode->decl); + if (flag_lto_print_value && value_tree) + print_generic_expr (stdout, value_tree, TDF_NONE); + printf ("\n"); + } +}; + +/* Stores function specific details of symbols for dumping symbol list. */ + +struct function_entry: public symbol_entry +{ + function_entry (cgraph_node *node_): symbol_entry (node_) + {} + + virtual void dump () + { + symbol_entry :: dump (); + printf ("\n"); + } + + virtual size_t get_size () const + { + cgraph_node *cnode = dyn_cast (node); + gcc_assert (cnode); + + return (cnode->definition) + ? n_basic_blocks_for_fn (DECL_STRUCT_FUNCTION (cnode->decl)) + : 0; + } +}; + +/* Comparing symbols based on size. */ + +int size_compare (const void *a, const void *b) +{ + const symbol_entry *e1 = *(const symbol_entry * const*) a; + const symbol_entry *e2 = *(const symbol_entry * const*) b; + + return e1->get_size () - e2->get_size (); +} + +/* Comparing symbols based on name. */ + +int name_compare (const void *a, const void *b) +{ + const symbol_entry *e1 = *(const symbol_entry * const*) a; + const symbol_entry *e2 = *(const symbol_entry * const*) b; + + return strcmp (e1->get_name (), e2->get_name ()); +} + +/* Dump list of functions and their details. */ + +void dump_list_functions (void) +{ + auto_vec v; + + cgraph_node *cnode; + FOR_EACH_FUNCTION (cnode) + { + if (cnode->definition) + cnode->get_untransformed_body (); + symbol_entry *e = new function_entry (cnode); + if (!flag_lto_dump_defined || cnode->definition) + v.safe_push (e); + } + + if (flag_lto_size_sort) + v.qsort (size_compare); + else if (flag_lto_name_sort) + v.qsort (name_compare); + if (flag_lto_reverse_sort) + v.reverse (); + + printf ("Type Visibility Size Name"); + if (flag_lto_print_value) + printf (" Value"); + printf ("\n"); + int i=0; + symbol_entry* e; + FOR_EACH_VEC_ELT (v, i, e) + e->dump (); +} + +/* Dump list of variables and their details. */ + +void dump_list_variables (void) +{ + auto_vec v; + + varpool_node *vnode; + FOR_EACH_VARIABLE (vnode) + { + symbol_entry *e = new variable_entry (vnode); + if (!flag_lto_dump_defined || vnode->definition) + v.safe_push (e); + } + + if (flag_lto_size_sort) + v.qsort (size_compare); + else if (flag_lto_name_sort) + v.qsort (name_compare); + if (flag_lto_reverse_sort) + v.reverse (); + + printf ("\n"); + int i=0; + symbol_entry* e; + FOR_EACH_VEC_ELT (v, i, e) + e->dump (); +} + +/* Dump symbol list. */ + +void dump_list (void) +{ + dump_list_functions (); + dump_list_variables (); + return; +} + +/* Dump specific variables and functions used in IL. */ +void dump_symbol () +{ + symtab_node *node; + printf ("Symbol: %s\n", flag_lto_dump_symbol); + FOR_EACH_SYMBOL (node) + { + if (!strcmp (flag_lto_dump_symbol, node->name ())) + { + node->debug (); + printf ("\n"); + } + } + return; +} + +/* Dump specific gimple body of specified function. */ +void dump_body () +{ + int flag = 0; + dump_flags_t flags = TDF_NONE; + if (flag_dump_level) + flags = parse_dump_option (flag_dump_level, NULL); + if (flags == TDF_ERROR) + { + error_at (input_location, "Level not found, use none, slim, blocks, vops."); + return; + } + cgraph_node *cnode; + FOR_EACH_FUNCTION (cnode) + if (cnode->definition && !strcmp (cnode->name (), flag_dump_body)) + { + printf ("Gimple Body of Function: %s\n", cnode->name ()); + cnode->get_untransformed_body (); + debug_function (cnode->decl, flags); + flag = 1; + } + if (!flag) + error_at (input_location, "Function not found."); + return; +} + +/* List of command line options for dumping. */ +void dump_tool_help () +{ + printf ("Usage: lto-dump [OPTION]... SUB_COMMAND [OPTION]...\n\n"); + printf ("LTO dump tool command line options.\n\n"); + printf (" -list [options] Dump the symbol list.\n"); + printf (" -demangle Dump the demangled output.\n"); + printf (" -defined-only Dump only the defined symbols.\n"); + printf (" -print-value Dump initial values of the " + "variables.\n"); + printf (" -name-sort Sort the symbols alphabetically.\n"); + printf (" -size-sort Sort the symbols according to size.\n"); + printf (" -reverse-sort Dump the symbols in reverse order.\n"); + printf (" -symbol= Dump the details of specific symbol.\n"); + printf (" -objects Dump the details of LTO objects.\n"); + printf (" -type-stats Dump statistics of tree types.\n"); + printf (" -tree-stats Dump statistics of trees.\n"); + printf (" -gimple-stats Dump statistics of gimple " + "statements.\n"); + printf (" -dump-body= Dump the specific gimple body.\n"); + printf (" -dump-level= Deciding the optimization level " + "of body.\n"); + printf (" -help Display the dump tool help.\n"); + return; +} + +unsigned int +lto_option_lang_mask (void) +{ + return CL_LTODump; +} + +/* Functions for dumping various details in LTO dump tool are called + in lto_main(). The purpose of this dump tool is to analyze the LTO + object files. */ + +void +lto_main (void) +{ + quiet_flag = true; + if (flag_lto_dump_tool_help) + dump_tool_help (); + + /* LTO is called as a front end, even though it is not a front end. + Because it is called as a front end, TV_PHASE_PARSING and + TV_PARSE_GLOBAL are active, and we need to turn them off while + doing LTO. Later we turn them back on so they are active up in + toplev.c. */ + + /* Initialize the LTO front end. */ + lto_fe_init (); + g_timer = NULL; + /* Read all the symbols and call graph from all the files in the + command line. */ + read_cgraph_and_symbols (num_in_fnames, in_fnames); + + /* Dump symbol list. */ + if (flag_lto_dump_list) + dump_list (); + else if (flag_lto_dump_symbol) + { + /* Dump specific variables and functions used in IL. */ + dump_symbol (); + } + else if (flag_lto_gimple_stats) + { + /* Dump gimple statement statistics. */ + cgraph_node *node; + FOR_EACH_DEFINED_FUNCTION (node) + node->get_untransformed_body (); + if (!GATHER_STATISTICS) + warning_at (input_location, 0, + "Not configured with --enable-gather-detailed-mem-stats."); + else + dump_gimple_statistics (); + } + else if (flag_lto_tree_stats) + { + /* Dump tree statistics. */ + if (!GATHER_STATISTICS) + warning_at (input_location, 0, + "Not configured with --enable-gather-detailed-mem-stats."); + else + { + printf ("Tree Statistics\n"); + dump_tree_statistics (); + } + } + else if (flag_dump_body) + { + /* Dump specific gimple body of specified function. */ + dump_body (); + return; + } +} diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index b88ca09d102..e155ea33d32 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -789,12 +789,6 @@ static GTY(()) tree registered_builtin_types; /* Language hooks. */ -static unsigned int -lto_option_lang_mask (void) -{ - return CL_LTO; -} - static bool lto_complain_wrong_lang_p (const struct cl_option *option ATTRIBUTE_UNUSED) { diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 20c2efffeda..d89f258bb5c 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -560,6 +560,12 @@ offload_handle_link_vars (void) #endif } +unsigned int +lto_option_lang_mask (void) +{ + return CL_LTO; +} + /* Main entry point for the GIMPLE front end. This front end has three main personalities: diff --git a/gcc/lto/lto.h b/gcc/lto/lto.h index a1b39ef8ff0..e67e1e76d40 100644 --- a/gcc/lto/lto.h +++ b/gcc/lto/lto.h @@ -69,4 +69,6 @@ struct lto_section_list struct lto_section_slot *first, *last; }; +extern unsigned int lto_option_lang_mask (void); + #endif /* LTO_H */ diff --git a/gcc/symtab.c b/gcc/symtab.c index d648d288e40..4bf37a18171 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -808,6 +808,23 @@ symtab_node::dump_referring (FILE *file) static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; +/* Dump the visibility of the symbol. */ + +const char * +symtab_node::get_visibility_string () const +{ + static const char * const visibility_types[] + = { "default", "protected", "hidden", "internal" }; + return visibility_types[DECL_VISIBILITY (decl)]; +} + +/* Dump the type_name of the symbol. */ +const char * +symtab_node::get_symtab_type_string () const +{ + return symtab_type_names[type]; +} + /* Dump base fields of symtab nodes to F. Not to be used directly. */ void -- 2.30.2