Mercurial > hg > CbC > CbC_gcc
diff gcc/lto-streamer.h @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/lto-streamer.h Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/lto-streamer.h Fri Oct 27 22:46:09 2017 +0900 @@ -1,7 +1,7 @@ /* Data structures and declarations used for reading and writing GIMPLE to a file stream. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009-2017 Free Software Foundation, Inc. Contributed by Doug Kwan <dougkwan@google.com> This file is part of GCC. @@ -24,22 +24,8 @@ #define GCC_LTO_STREAMER_H #include "plugin-api.h" -#include "tree.h" -#include "gimple.h" -#include "target.h" -#include "cgraph.h" -#include "vec.h" -#include "vecprim.h" -#include "alloc-pool.h" #include "gcov-io.h" - -/* Define when debugging the LTO streamer. This causes the writer - to output the numeric value for the memory address of the tree node - being emitted. When debugging a problem in the reader, check the - original address that the writer was emitting using lto_orig_address_get. - With this value, set a breakpoint in the writer (e.g., lto_output_tree) - to trace how the faulty node is being emitted. */ -/* #define LTO_STREAMER_DEBUG 1 */ +#include "diagnostic.h" /* The encoding for a function consists of the following sections: @@ -134,39 +120,12 @@ String are represented in the table as pairs, a length in ULEB128 form followed by the data for the string. */ -/* The string that is the prefix on the section names we make for lto. - For decls the DECL_ASSEMBLER_NAME is appended to make the section - name for the functions and static_initializers. For other types of - sections a '.' and the section type are appended. */ -#define LTO_SECTION_NAME_PREFIX ".gnu.lto_" - -#define LTO_major_version 2 +#define LTO_major_version 7 #define LTO_minor_version 0 typedef unsigned char lto_decl_flags_t; -/* Data structures used to pack values and bitflags into a vector of - words. Used to stream values of a fixed number of bits in a space - efficient way. */ -static unsigned const BITS_PER_BITPACK_WORD = HOST_BITS_PER_WIDE_INT; - -typedef unsigned HOST_WIDE_INT bitpack_word_t; -DEF_VEC_I(bitpack_word_t); -DEF_VEC_ALLOC_I(bitpack_word_t, heap); - -struct bitpack_d -{ - /* The position of the first unused or unconsumed bit in the word. */ - unsigned pos; - - /* The current word we are (un)packing. */ - bitpack_word_t word; - - /* The lto_output_stream or the lto_input_block we are streaming to/from. */ - void *stream; -}; - /* Tags representing the various IL objects written to the bytecode file (GIMPLE statements, basic blocks, EH regions, tree nodes, etc). @@ -175,6 +134,9 @@ { LTO_null = 0, + /* Special for streamer. Reference to previously-streamed node. */ + LTO_tree_pickle_reference, + /* Reserve enough entries to fit all the tree and gimple codes handled by the streamer. This guarantees that: @@ -186,14 +148,14 @@ Conversely, to map between LTO tags and tree/gimple codes, the reverse operation must be applied. */ - LTO_bb0 = 1 + NUM_TREE_CODES + LAST_AND_UNUSED_GIMPLE_CODE, + LTO_bb0 = 1 + MAX_TREE_CODES + LAST_AND_UNUSED_GIMPLE_CODE, LTO_bb1, /* EH region holding the previous statement. */ LTO_eh_region, - /* An MD or NORMAL builtin. Only the code and class are streamed out. */ - LTO_builtin_decl, + /* Shared INTEGER_CST node. */ + LTO_integer_cst, /* Function body. */ LTO_function, @@ -213,8 +175,8 @@ /* EH try/catch node. */ LTO_eh_catch, - /* Special for global streamer. Reference to previously-streamed node. */ - LTO_tree_pickle_reference, + /* Special for global streamer. A blob of unnamed tree nodes. */ + LTO_tree_scc, /* References to indexable tree nodes. These objects are stored in tables that are written separately from the function bodies that @@ -237,7 +199,8 @@ LTO_const_decl_ref, LTO_imported_decl_ref, LTO_translation_unit_decl_ref, - LTO_global_decl_ref, /* Do not change. */ + LTO_global_decl_ref, + LTO_namelist_decl_ref, /* Do not change. */ /* This tag must always be last. */ LTO_NUM_TAGS @@ -255,20 +218,27 @@ LTO_section_decls = 0, LTO_section_function_body, LTO_section_static_initializer, - LTO_section_cgraph, - LTO_section_varpool, + LTO_section_symtab, LTO_section_refs, + LTO_section_asm, LTO_section_jump_functions, LTO_section_ipa_pure_const, LTO_section_ipa_reference, - LTO_section_symtab, + LTO_section_ipa_profile, + LTO_section_symtab_nodes, LTO_section_opts, LTO_section_cgraph_opt_sum, + LTO_section_ipa_fn_summary, + LTO_section_ipcp_transform, + LTO_section_ipa_icf, + LTO_section_offload_table, + LTO_section_mode_table, + LTO_section_ipa_hsa, LTO_N_SECTION_TYPES /* Must be last. */ }; /* Indices to the various function, type and symbol streams. */ -typedef enum +enum lto_decl_stream_e_t { LTO_DECL_STREAM_TYPE = 0, /* Must be first. */ LTO_DECL_STREAM_FIELD_DECL, @@ -278,11 +248,9 @@ LTO_DECL_STREAM_NAMESPACE_DECL, LTO_DECL_STREAM_LABEL_DECL, LTO_N_DECL_STREAMS -} lto_decl_stream_e_t; +}; typedef enum ld_plugin_symbol_resolution ld_plugin_symbol_resolution_t; -DEF_VEC_I(ld_plugin_symbol_resolution_t); -DEF_VEC_ALLOC_I(ld_plugin_symbol_resolution_t, heap); /* Macro to define convenience functions for type and decl streams @@ -293,15 +261,14 @@ unsigned int idx) \ { \ struct lto_in_decl_state *state = data->current_decl_state; \ - gcc_assert (idx < state->streams[LTO_DECL_STREAM_## UPPER_NAME].size); \ - return state->streams[LTO_DECL_STREAM_## UPPER_NAME].trees[idx]; \ + return (*state->streams[LTO_DECL_STREAM_## UPPER_NAME])[idx]; \ } \ \ static inline unsigned int \ lto_file_decl_data_num_ ## name ## s (struct lto_file_decl_data *data) \ { \ struct lto_in_decl_state *state = data->current_decl_state; \ - return state->streams[LTO_DECL_STREAM_## UPPER_NAME].size; \ + return vec_safe_length (state->streams[LTO_DECL_STREAM_## UPPER_NAME]); \ } @@ -318,71 +285,99 @@ /* Return the data found from the above call. The first three parameters are the same as above. The fourth parameter is the data - itself and the fifth is the lenght of the data. */ + itself and the fifth is the length of the data. */ typedef void (lto_free_section_data_f) (struct lto_file_decl_data *, enum lto_section_type, const char *, const char *, size_t); -/* Cache of pickled nodes. Used to avoid writing the same node more - than once. The first time a tree node is streamed out, it is - entered in this cache. Subsequent references to the same node are - resolved by looking it up in this cache. +/* The location cache holds expanded locations for streamed in trees. + This is done to reduce memory usage of libcpp linemap that strongly preffers + locations to be inserted in the soruce order. */ - This is used in two ways: - - - On the writing side, the first time T is added to STREAMER_CACHE, - a new reference index is created for T and T is emitted on the - stream. If T needs to be emitted again to the stream, instead of - pickling it again, the reference index is emitted. +class lto_location_cache +{ +public: + /* Apply all changes in location cache. Add locations into linemap and patch + trees. */ + bool apply_location_cache (); + /* Tree merging did not suceed; mark all changes in the cache as accepted. */ + void accept_location_cache (); + /* Tree merging did suceed; throw away recent changes. */ + void revert_location_cache (); + void input_location (location_t *loc, struct bitpack_d *bp, + struct data_in *data_in); + lto_location_cache () + : loc_cache (), accepted_length (0), current_file (NULL), current_line (0), + current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION) + { + gcc_assert (!current_cache); + current_cache = this; + } + ~lto_location_cache () + { + apply_location_cache (); + gcc_assert (current_cache == this); + current_cache = NULL; + } - - On the reading side, the first time T is read from the stream, it - is reconstructed in memory and a new reference index created for - T. The reconstructed T is inserted in some array so that when - the reference index for T is found in the input stream, it can be - used to look up into the array to get the reconstructed T. */ -struct lto_streamer_cache_d -{ - /* The mapping between tree nodes and slots into the nodes array. */ - htab_t node_map; + /* There can be at most one instance of location cache (combining multiple + would bring it out of sync with libcpp linemap); point to current + one. */ + static lto_location_cache *current_cache; + +private: + static int cmp_loc (const void *pa, const void *pb); + + struct cached_location + { + const char *file; + location_t *loc; + int line, col; + bool sysp; + }; + + /* The location cache. */ - /* Node map to store entries into. */ - alloc_pool node_map_entries; + auto_vec<cached_location> loc_cache; - /* Next available slot in the nodes and offsets arrays. */ - unsigned next_slot; + /* Accepted entries are ones used by trees that are known to be not unified + by tree merging. */ + + int accepted_length; - /* The nodes pickled so far. */ - VEC(tree,heap) *nodes; + /* Bookkeeping to remember state in between calls to lto_apply_location_cache + When streaming gimple, the location cache is not used and thus + lto_apply_location_cache happens per location basis. It is then + useful to avoid redundant calls of linemap API. */ - /* Offset into the stream where the nodes have been written. */ - VEC(unsigned,heap) *offsets; + const char *current_file; + int current_line; + int current_col; + bool current_sysp; + location_t current_loc; }; +/* Structure used as buffer for reading an LTO file. */ +class lto_input_block +{ +public: + /* Special constructor for the string table, it abuses this to + do random access but use the uhwi decoder. */ + lto_input_block (const char *data_, unsigned int p_, unsigned int len_, + const unsigned char *mode_table_) + : data (data_), mode_table (mode_table_), p (p_), len (len_) {} + lto_input_block (const char *data_, unsigned int len_, + const unsigned char *mode_table_) + : data (data_), mode_table (mode_table_), p (0), len (len_) {} -/* Structure used as buffer for reading an LTO file. */ -struct lto_input_block -{ const char *data; + const unsigned char *mode_table; unsigned int p; unsigned int len; }; -#define LTO_INIT_INPUT_BLOCK(BASE,D,P,L) \ - do { \ - BASE.data = D; \ - BASE.p = P; \ - BASE.len = L; \ - } while (0) - -#define LTO_INIT_INPUT_BLOCK_PTR(BASE,D,P,L) \ - do { \ - BASE->data = D; \ - BASE->p = P; \ - BASE->len = L; \ - } while (0) - /* The is the first part of the record for a function or constructor in the .o file. */ @@ -390,55 +385,38 @@ { int16_t major_version; int16_t minor_version; - enum lto_section_type section_type; }; -/* The header for a function body. */ -struct lto_function_header +/* The is the first part of the record in an LTO file for many of the + IPA passes. */ +struct lto_simple_header : lto_header { - /* The header for all types of sections. */ - struct lto_header lto_header; - - /* Number of labels with names. */ - int32_t num_named_labels; - - /* Number of labels without names. */ - int32_t num_unnamed_labels; - - /* Size compressed or 0 if not compressed. */ - int32_t compressed_size; - - /* Size of names for named labels. */ - int32_t named_label_size; - - /* Size of the cfg. */ - int32_t cfg_size; - /* Size of main gimple body of function. */ int32_t main_size; +}; +struct lto_simple_header_with_strings : lto_simple_header +{ /* Size of the string table. */ int32_t string_size; }; +/* The header for a function body. */ +struct lto_function_header : lto_simple_header_with_strings +{ + /* Size of the cfg. */ + int32_t cfg_size; +}; + /* Structure describing a symbol section. */ -struct lto_decl_header +struct lto_decl_header : lto_simple_header_with_strings { - /* The header for all types of sections. */ - struct lto_header lto_header; - /* Size of region for decl state. */ int32_t decl_state_size; /* Number of nodes in globals stream. */ int32_t num_nodes; - - /* Size of region for expressions, decls, types, etc. */ - int32_t main_size; - - /* Size of the string table. */ - int32_t string_size; }; @@ -446,7 +424,7 @@ struct lto_stats_d { unsigned HOST_WIDE_INT num_input_cgraph_nodes; - unsigned HOST_WIDE_INT num_output_cgraph_nodes; + unsigned HOST_WIDE_INT num_output_symtab_nodes; unsigned HOST_WIDE_INT num_input_files; unsigned HOST_WIDE_INT num_output_files; unsigned HOST_WIDE_INT num_cgraph_partitions; @@ -457,96 +435,83 @@ unsigned HOST_WIDE_INT num_compressed_il_bytes; unsigned HOST_WIDE_INT num_input_il_bytes; unsigned HOST_WIDE_INT num_uncompressed_il_bytes; + unsigned HOST_WIDE_INT num_tree_bodies_output; + unsigned HOST_WIDE_INT num_pickle_refs_output; }; -/* Encoder data structure used to stream callgraph nodes. */ -struct lto_cgraph_encoder_d +/* Entry of LTO symtab encoder. */ +struct lto_encoder_entry { - /* Map nodes to reference number. */ - struct pointer_map_t *map; - - /* Map reference number to node. */ - VEC(cgraph_node_ptr,heap) *nodes; - - /* Map of nodes where we want to output body. */ - struct pointer_set_t *body; + symtab_node *node; + /* Is the node in this partition (i.e. ltrans of this partition will + be responsible for outputting it)? */ + unsigned int in_partition:1; + /* Do we encode body in this partition? */ + unsigned int body:1; + /* Do we encode initializer in this partition? + For example the readonly variable initializers are encoded to aid + constant folding even if they are not in the partition. */ + unsigned int initializer:1; }; -typedef struct lto_cgraph_encoder_d *lto_cgraph_encoder_t; - -/* Return number of encoded nodes in ENCODER. */ - -static inline int -lto_cgraph_encoder_size (lto_cgraph_encoder_t encoder) -{ - return VEC_length (cgraph_node_ptr, encoder->nodes); -} - /* Encoder data structure used to stream callgraph nodes. */ -struct lto_varpool_encoder_d +struct lto_symtab_encoder_d { - /* Map nodes to reference number. */ - struct pointer_map_t *map; - - /* Map reference number to node. */ - VEC(varpool_node_ptr,heap) *nodes; - - /* Map of nodes where we want to output initializer. */ - struct pointer_set_t *initializer; -}; -typedef struct lto_varpool_encoder_d *lto_varpool_encoder_t; - -/* Return number of encoded nodes in ENCODER. */ - -static inline int -lto_varpool_encoder_size (lto_varpool_encoder_t encoder) -{ - return VEC_length (varpool_node_ptr, encoder->nodes); -} - -/* Mapping from indices to trees. */ -struct GTY(()) lto_tree_ref_table -{ - /* Array of referenced trees . */ - tree * GTY((length ("%h.size"))) trees; - - /* Size of array. */ - unsigned int size; + vec<lto_encoder_entry> nodes; + hash_map<symtab_node *, size_t> *map; }; +typedef struct lto_symtab_encoder_d *lto_symtab_encoder_t; -/* Mapping between trees and slots in an array. */ -struct lto_decl_slot +/* Iterator structure for cgraph node sets. */ +struct lto_symtab_encoder_iterator { - tree t; - int slot_num; + lto_symtab_encoder_t encoder; + unsigned index; }; + /* The lto_tree_ref_encoder struct is used to encode trees into indices. */ struct lto_tree_ref_encoder { - htab_t tree_hash_table; /* Maps pointers to indices. */ - unsigned int next_index; /* Next available index. */ - VEC(tree,heap) *trees; /* Maps indices to pointers. */ + hash_map<tree, unsigned> *tree_hash_table; /* Maps pointers to indices. */ + vec<tree> trees; /* Maps indices to pointers. */ }; /* Structure to hold states of input scope. */ -struct GTY(()) lto_in_decl_state +struct GTY((for_user)) lto_in_decl_state { /* Array of lto_in_decl_buffers to store type and decls streams. */ - struct lto_tree_ref_table streams[LTO_N_DECL_STREAMS]; + vec<tree, va_gc> *streams[LTO_N_DECL_STREAMS]; /* If this in-decl state is associated with a function. FN_DECL point to the FUNCTION_DECL. */ tree fn_decl; + + /* True if decl state is compressed. */ + bool compressed; }; typedef struct lto_in_decl_state *lto_in_decl_state_ptr; +struct decl_state_hasher : ggc_ptr_hash<lto_in_decl_state> +{ + static hashval_t + hash (lto_in_decl_state *s) + { + return htab_hash_pointer (s->fn_decl); + } + + static bool + equal (lto_in_decl_state *a, lto_in_decl_state *b) + { + return a->fn_decl == b->fn_decl; + } +}; /* The structure that holds all of the vectors of global types, decls and cgraph nodes used in the serialization of this file. */ @@ -557,20 +522,27 @@ struct lto_tree_ref_encoder streams[LTO_N_DECL_STREAMS]; /* Encoder for cgraph nodes. */ - lto_cgraph_encoder_t cgraph_node_encoder; - - /* Encoder for varpool nodes. */ - lto_varpool_encoder_t varpool_node_encoder; + lto_symtab_encoder_t symtab_node_encoder; /* If this out-decl state belongs to a function, fn_decl points to that function. Otherwise, it is NULL. */ tree fn_decl; + + /* True if decl state is compressed. */ + bool compressed; }; typedef struct lto_out_decl_state *lto_out_decl_state_ptr; -DEF_VEC_P(lto_out_decl_state_ptr); -DEF_VEC_ALLOC_P(lto_out_decl_state_ptr, heap); + +/* Compact representation of a index <-> resolution pair. Unpacked to an + vector later. */ +struct res_pair +{ + ld_plugin_symbol_resolution_t res; + unsigned index; +}; + /* One of these is allocated for each object file that being compiled by lto. This structure contains the tables that are needed by the @@ -586,13 +558,10 @@ struct lto_in_decl_state *global_decl_state; /* Table of cgraph nodes present in this file. */ - lto_cgraph_encoder_t GTY((skip)) cgraph_node_encoder; - - /* Table of varpool nodes present in this file. */ - lto_varpool_encoder_t GTY((skip)) varpool_node_encoder; + lto_symtab_encoder_t GTY((skip)) symtab_node_encoder; /* Hash table maps lto-related section names to location in file. */ - htab_t GTY((param_is (struct lto_in_decl_state))) function_decl_states; + hash_table<decl_state_hasher> *function_decl_states; /* The .o file that these offsets relate to. */ const char *GTY((skip)) file_name; @@ -607,12 +576,19 @@ struct lto_file_decl_data *next; /* Sub ID for merged objects. */ - unsigned id; + unsigned HOST_WIDE_INT id; /* Symbol resolutions for this file */ - VEC(ld_plugin_symbol_resolution_t,heap) * GTY((skip)) resolutions; + vec<res_pair> GTY((skip)) respairs; + unsigned max_index; struct gcov_ctr_summary GTY((skip)) profile_info; + + /* Map assigning declarations their resolutions. */ + hash_map<tree, ld_plugin_symbol_resolution> * GTY((skip)) resolution_map; + + /* Mode translation table. */ + const unsigned char *mode_table; }; typedef struct lto_file_decl_data *lto_file_decl_data_ptr; @@ -647,20 +623,6 @@ unsigned int total_size; }; -/* The is the first part of the record in an LTO file for many of the - IPA passes. */ -struct lto_simple_header -{ - /* The header for all types of sections. */ - struct lto_header lto_header; - - /* Size of main gimple body of function. */ - int32_t main_size; - - /* Size of main stream when compressed. */ - int32_t compressed_size; -}; - /* A simple output block. This can be used for simple IPA passes that do not need more than one stream. */ struct lto_simple_output_block @@ -672,6 +634,48 @@ struct lto_output_stream *main_stream; }; +/* String hashing. */ + +struct string_slot +{ + const char *s; + int len; + unsigned int slot_num; +}; + +/* Hashtable helpers. */ + +struct string_slot_hasher : nofree_ptr_hash <string_slot> +{ + static inline hashval_t hash (const string_slot *); + static inline bool equal (const string_slot *, const string_slot *); +}; + +/* Returns a hash code for DS. Adapted from libiberty's htab_hash_string + to support strings that may not end in '\0'. */ + +inline hashval_t +string_slot_hasher::hash (const string_slot *ds) +{ + hashval_t r = ds->len; + int i; + + for (i = 0; i < ds->len; i++) + r = r * 67 + (unsigned)ds->s[i] - 113; + return r; +} + +/* Returns nonzero if DS1 and DS2 are equal. */ + +inline bool +string_slot_hasher::equal (const string_slot *ds1, const string_slot *ds2) +{ + if (ds1->len == ds2->len) + return memcmp (ds1->s, ds2->s, ds1->len) == 0; + + return 0; +} + /* Data structure holding all the data and descriptors used when writing an LTO file. */ struct output_block @@ -690,11 +694,11 @@ /* The hash table that contains the set of strings we have seen so far and the indexes assigned to them. */ - htab_t string_hash_table; + hash_table<string_slot_hasher> *string_hash_table; - /* The current cgraph_node that we are currently serializing. Null + /* The current symbol that we are currently serializing. Null if we are serializing something else. */ - struct cgraph_node *cgraph_node; + symtab_node *symbol; /* These are the last file and line that were seen in the stream. If the current node differs from these, it needs to insert @@ -702,12 +706,14 @@ const char *current_file; int current_line; int current_col; - - /* True if writing globals and types. */ - bool global; + bool current_sysp; /* Cache of nodes written in this section. */ - struct lto_streamer_cache_d *writer_cache; + struct streamer_tree_cache_d *writer_cache; + + /* All data persistent across whole duration of output block + can go here. */ + struct obstack obstack; }; @@ -717,31 +723,20 @@ /* The global decls and types. */ struct lto_file_decl_data *file_data; - /* All of the labels. */ - tree *labels; - /* The string table. */ const char *strings; /* The length of the string table. */ unsigned int strings_len; - /* Number of named labels. Used to find the index of unnamed labels - since they share space with the named labels. */ - unsigned int num_named_labels; - - /* Number of unnamed labels. */ - unsigned int num_unnamed_labels; - - const char *current_file; - int current_line; - int current_col; - /* Maps each reference number to the resolution done by the linker. */ - VEC(ld_plugin_symbol_resolution_t,heap) *globals_resolution; + vec<ld_plugin_symbol_resolution_t> globals_resolution; /* Cache of pickled nodes. */ - struct lto_streamer_cache_d *reader_cache; + struct streamer_tree_cache_d *reader_cache; + + /* Cache of source code location. */ + lto_location_cache location_cache; }; @@ -759,15 +754,18 @@ extern struct lto_file_decl_data **lto_get_file_decl_data (void); extern const char *lto_get_section_data (struct lto_file_decl_data *, enum lto_section_type, - const char *, size_t *); + const char *, size_t *, + bool decompress = false); +extern const char *lto_get_raw_section_data (struct lto_file_decl_data *, + enum lto_section_type, + const char *, size_t *); extern void lto_free_section_data (struct lto_file_decl_data *, - enum lto_section_type, - const char *, const char *, size_t); -extern unsigned char lto_input_1_unsigned (struct lto_input_block *); -extern unsigned HOST_WIDE_INT lto_input_uleb128 (struct lto_input_block *); -extern unsigned HOST_WIDEST_INT lto_input_widest_uint_uleb128 ( - struct lto_input_block *); -extern HOST_WIDE_INT lto_input_sleb128 (struct lto_input_block *); + enum lto_section_type, + const char *, const char *, size_t, + bool decompress = false); +extern void lto_free_raw_section_data (struct lto_file_decl_data *, + enum lto_section_type, + const char *, const char *, size_t); extern htab_t lto_create_renaming_table (void); extern void lto_record_renamed_decl (struct lto_file_decl_data *, const char *, const char *); @@ -775,28 +773,21 @@ const char *); extern struct lto_in_decl_state *lto_new_in_decl_state (void); extern void lto_delete_in_decl_state (struct lto_in_decl_state *); -extern hashval_t lto_hash_in_decl_state (const void *); -extern int lto_eq_in_decl_state (const void *, const void *); extern struct lto_in_decl_state *lto_get_function_in_decl_state ( struct lto_file_decl_data *, tree); +extern void lto_free_function_in_decl_state (struct lto_in_decl_state *); +extern void lto_free_function_in_decl_state_for_node (symtab_node *); +extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN; +extern void lto_value_range_error (const char *, + HOST_WIDE_INT, HOST_WIDE_INT, + HOST_WIDE_INT) ATTRIBUTE_NORETURN; /* In lto-section-out.c */ -extern hashval_t lto_hash_decl_slot_node (const void *); -extern int lto_eq_decl_slot_node (const void *, const void *); -extern hashval_t lto_hash_type_slot_node (const void *); -extern int lto_eq_type_slot_node (const void *, const void *); extern void lto_begin_section (const char *, bool); extern void lto_end_section (void); +extern void lto_write_data (const void *, unsigned int); +extern void lto_write_raw_data (const void *, unsigned int); extern void lto_write_stream (struct lto_output_stream *); -extern void lto_output_1_stream (struct lto_output_stream *, char); -extern void lto_output_data_stream (struct lto_output_stream *, const void *, - size_t); -extern void lto_output_uleb128_stream (struct lto_output_stream *, - unsigned HOST_WIDE_INT); -extern void lto_output_widest_uint_uleb128_stream (struct lto_output_stream *, - unsigned HOST_WIDEST_INT); -extern void lto_output_sleb128_stream (struct lto_output_stream *, - HOST_WIDE_INT); extern bool lto_output_decl_index (struct lto_output_stream *, struct lto_tree_ref_encoder *, tree, unsigned int *); @@ -822,113 +813,120 @@ extern struct lto_out_decl_state *lto_pop_out_decl_state (void); extern void lto_record_function_out_decl_state (tree, struct lto_out_decl_state *); +extern void lto_append_block (struct lto_output_stream *); /* In lto-streamer.c. */ + +/* Set when streaming LTO for offloading compiler. */ +extern bool lto_stream_offload_p; + extern const char *lto_tag_name (enum LTO_tags); extern bitmap lto_bitmap_alloc (void); extern void lto_bitmap_free (bitmap); extern char *lto_get_section_name (int, const char *, struct lto_file_decl_data *); -extern void print_lto_report (void); -extern bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree, - int *, unsigned *); -extern bool lto_streamer_cache_insert_at (struct lto_streamer_cache_d *, tree, - int); -extern bool lto_streamer_cache_lookup (struct lto_streamer_cache_d *, tree, - int *); -extern tree lto_streamer_cache_get (struct lto_streamer_cache_d *, int); -extern struct lto_streamer_cache_d *lto_streamer_cache_create (void); -extern void lto_streamer_cache_delete (struct lto_streamer_cache_d *); +extern void print_lto_report (const char *); extern void lto_streamer_init (void); extern bool gate_lto_out (void); -#ifdef LTO_STREAMER_DEBUG -extern void lto_orig_address_map (tree, intptr_t); -extern intptr_t lto_orig_address_get (tree); -extern void lto_orig_address_remove (tree); -#endif -extern void lto_check_version (int, int); - +extern void lto_check_version (int, int, const char *); +extern void lto_streamer_hooks_init (void); /* In lto-streamer-in.c */ extern void lto_input_cgraph (struct lto_file_decl_data *, const char *); -extern void lto_init_reader (void); -extern tree lto_input_tree (struct lto_input_block *, struct data_in *); -extern void lto_input_function_body (struct lto_file_decl_data *, tree, +extern void lto_reader_init (void); +extern void lto_input_function_body (struct lto_file_decl_data *, + struct cgraph_node *, const char *); +extern void lto_input_variable_constructor (struct lto_file_decl_data *, + struct varpool_node *, + const char *); extern void lto_input_constructors_and_inits (struct lto_file_decl_data *, const char *); -extern void lto_init_reader (void); +extern void lto_input_toplevel_asms (struct lto_file_decl_data *, int); +extern void lto_input_mode_table (struct lto_file_decl_data *); extern struct data_in *lto_data_in_create (struct lto_file_decl_data *, const char *, unsigned, - VEC(ld_plugin_symbol_resolution_t,heap) *); + vec<ld_plugin_symbol_resolution_t> ); extern void lto_data_in_delete (struct data_in *); +extern void lto_input_data_block (struct lto_input_block *, void *, size_t); +void lto_input_location (location_t *, struct bitpack_d *, struct data_in *); +location_t stream_input_location_now (struct bitpack_d *bp, + struct data_in *data); +tree lto_input_tree_ref (struct lto_input_block *, struct data_in *, + struct function *, enum LTO_tags); +void lto_tag_check_set (enum LTO_tags, int, ...); +void lto_init_eh (void); +hashval_t lto_input_scc (struct lto_input_block *, struct data_in *, + unsigned *, unsigned *); +tree lto_input_tree_1 (struct lto_input_block *, struct data_in *, + enum LTO_tags, hashval_t hash); +tree lto_input_tree (struct lto_input_block *, struct data_in *); /* In lto-streamer-out.c */ extern void lto_register_decl_definition (tree, struct lto_file_decl_data *); extern struct output_block *create_output_block (enum lto_section_type); extern void destroy_output_block (struct output_block *); -extern void lto_output_tree (struct output_block *, tree, bool); +extern void lto_output_tree (struct output_block *, tree, bool, bool); +extern void lto_output_toplevel_asms (void); extern void produce_asm (struct output_block *ob, tree fn); +extern void lto_output (); +extern void produce_asm_for_decls (); +void lto_output_decl_state_streams (struct output_block *, + struct lto_out_decl_state *); +void lto_output_decl_state_refs (struct output_block *, + struct lto_output_stream *, + struct lto_out_decl_state *); +void lto_output_location (struct output_block *, struct bitpack_d *, location_t); +void lto_output_init_mode_table (void); /* In lto-cgraph.c */ -struct cgraph_node *lto_cgraph_encoder_deref (lto_cgraph_encoder_t, int); -int lto_cgraph_encoder_lookup (lto_cgraph_encoder_t, struct cgraph_node *); -lto_cgraph_encoder_t lto_cgraph_encoder_new (void); -int lto_cgraph_encoder_encode (lto_cgraph_encoder_t, struct cgraph_node *); -void lto_cgraph_encoder_delete (lto_cgraph_encoder_t); -bool lto_cgraph_encoder_encode_body_p (lto_cgraph_encoder_t, +extern bool asm_nodes_output; +lto_symtab_encoder_t lto_symtab_encoder_new (bool); +int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node *); +void lto_symtab_encoder_delete (lto_symtab_encoder_t); +bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node *); +bool lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t, struct cgraph_node *); +bool lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t, + symtab_node *); +void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t, + symtab_node *); -bool lto_varpool_encoder_encode_body_p (lto_varpool_encoder_t, - struct varpool_node *); -struct varpool_node *lto_varpool_encoder_deref (lto_varpool_encoder_t, int); -int lto_varpool_encoder_lookup (lto_varpool_encoder_t, struct varpool_node *); -lto_varpool_encoder_t lto_varpool_encoder_new (void); -int lto_varpool_encoder_encode (lto_varpool_encoder_t, struct varpool_node *); -void lto_varpool_encoder_delete (lto_varpool_encoder_t); -bool lto_varpool_encoder_encode_initializer_p (lto_varpool_encoder_t, - struct varpool_node *); -void output_cgraph (cgraph_node_set, varpool_node_set); -void input_cgraph (void); +bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t, + varpool_node *); +void output_symtab (void); +void input_symtab (void); +void output_offload_tables (void); +void input_offload_tables (bool); bool referenced_from_other_partition_p (struct ipa_ref_list *, - cgraph_node_set, - varpool_node_set vset); + lto_symtab_encoder_t); bool reachable_from_other_partition_p (struct cgraph_node *, - cgraph_node_set); -bool referenced_from_this_partition_p (struct ipa_ref_list *, - cgraph_node_set, - varpool_node_set vset); + lto_symtab_encoder_t); +bool referenced_from_this_partition_p (symtab_node *, + lto_symtab_encoder_t); bool reachable_from_this_partition_p (struct cgraph_node *, - cgraph_node_set); -void compute_ltrans_boundary (struct lto_out_decl_state *state, - cgraph_node_set, varpool_node_set); + lto_symtab_encoder_t); +lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder); +void select_what_to_stream (void); +/* In options-save.c. */ +void cl_target_option_stream_out (struct output_block *, struct bitpack_d *, + struct cl_target_option *); -/* In lto-symtab.c. */ -extern void lto_symtab_register_decl (tree, ld_plugin_symbol_resolution_t, - struct lto_file_decl_data *); -extern void lto_symtab_merge_decls (void); -extern void lto_symtab_merge_cgraph_nodes (void); -extern tree lto_symtab_prevailing_decl (tree decl); -extern enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl); -extern void lto_symtab_free (void); -extern GTY(()) VEC(tree,gc) *lto_global_var_decls; +void cl_target_option_stream_in (struct data_in *, + struct bitpack_d *, + struct cl_target_option *); + +void cl_optimization_stream_out (struct bitpack_d *, struct cl_optimization *); + +void cl_optimization_stream_in (struct bitpack_d *, struct cl_optimization *); + /* In lto-opts.c. */ -extern void lto_register_user_option (size_t, const char *, int, int); -extern void lto_read_file_options (struct lto_file_decl_data *); extern void lto_write_options (void); -extern void lto_reissue_options (void); -void lto_clear_user_options (void); -void lto_clear_file_options (void); - - -/* In lto-wpa-fixup.c */ -void lto_mark_nothrow_fndecl (tree); -void lto_fixup_nothrow_decls (void); /* Statistics gathered during LTO, WPA and LTRANS. */ @@ -939,13 +937,13 @@ /* Holds all the out decl states of functions output so far in the current output file. */ -extern VEC(lto_out_decl_state_ptr, heap) *lto_function_decl_states; +extern vec<lto_out_decl_state_ptr> lto_function_decl_states; /* Return true if LTO tag TAG corresponds to a tree code. */ static inline bool lto_tag_is_tree_code_p (enum LTO_tags tag) { - return tag > LTO_null && (unsigned) tag <= NUM_TREE_CODES; + return tag > LTO_tree_pickle_reference && (unsigned) tag <= MAX_TREE_CODES; } @@ -953,8 +951,8 @@ static inline bool lto_tag_is_gimple_code_p (enum LTO_tags tag) { - return (unsigned) tag >= NUM_TREE_CODES + 1 - && (unsigned) tag < 1 + NUM_TREE_CODES + LAST_AND_UNUSED_GIMPLE_CODE; + return (unsigned) tag >= NUM_TREE_CODES + 2 + && (unsigned) tag < 2 + NUM_TREE_CODES + LAST_AND_UNUSED_GIMPLE_CODE; } @@ -963,7 +961,7 @@ static inline enum LTO_tags lto_gimple_code_to_tag (enum gimple_code code) { - return (enum LTO_tags) ((unsigned) code + NUM_TREE_CODES + 1); + return (enum LTO_tags) ((unsigned) code + NUM_TREE_CODES + 2); } @@ -973,7 +971,7 @@ lto_tag_to_gimple_code (enum LTO_tags tag) { gcc_assert (lto_tag_is_gimple_code_p (tag)); - return (enum gimple_code) ((unsigned) tag - NUM_TREE_CODES - 1); + return (enum gimple_code) ((unsigned) tag - NUM_TREE_CODES - 2); } @@ -982,7 +980,7 @@ static inline enum LTO_tags lto_tree_code_to_tag (enum tree_code code) { - return (enum LTO_tags) ((unsigned) code + 1); + return (enum LTO_tags) ((unsigned) code + 2); } @@ -992,36 +990,56 @@ lto_tag_to_tree_code (enum LTO_tags tag) { gcc_assert (lto_tag_is_tree_code_p (tag)); - return (enum tree_code) ((unsigned) tag - 1); + return (enum tree_code) ((unsigned) tag - 2); +} + +/* Check that tag ACTUAL == EXPECTED. */ +static inline void +lto_tag_check (enum LTO_tags actual, enum LTO_tags expected) +{ + if (actual != expected) + internal_error ("bytecode stream: expected tag %s instead of %s", + lto_tag_name (expected), lto_tag_name (actual)); +} + +/* Check that tag ACTUAL is in the range [TAG1, TAG2]. */ +static inline void +lto_tag_check_range (enum LTO_tags actual, enum LTO_tags tag1, + enum LTO_tags tag2) +{ + if (actual < tag1 || actual > tag2) + internal_error ("bytecode stream: tag %s is not in the expected range " + "[%s, %s]", + lto_tag_name (actual), + lto_tag_name (tag1), + lto_tag_name (tag2)); } /* Initialize an lto_out_decl_buffer ENCODER. */ static inline void -lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder, - htab_hash hash_fn, htab_eq eq_fn) +lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder) { - encoder->tree_hash_table = htab_create (37, hash_fn, eq_fn, free); - encoder->next_index = 0; - encoder->trees = NULL; + encoder->tree_hash_table = new hash_map<tree, unsigned> (251); + encoder->trees.create (0); } -/* Destory an lto_tree_ref_encoder ENCODER by freeing its contents. The +/* Destroy an lto_tree_ref_encoder ENCODER by freeing its contents. The memory used by ENCODER is not freed by this function. */ static inline void lto_destroy_tree_ref_encoder (struct lto_tree_ref_encoder *encoder) { /* Hash table may be delete already. */ - if (encoder->tree_hash_table) - htab_delete (encoder->tree_hash_table); - VEC_free (tree, heap, encoder->trees); + delete encoder->tree_hash_table; + encoder->tree_hash_table = NULL; + encoder->trees.release (); } /* Return the number of trees encoded in ENCODER. */ static inline unsigned int lto_tree_ref_encoder_size (struct lto_tree_ref_encoder *encoder) { - return VEC_length (tree, encoder->trees); + return encoder->trees.length (); } /* Return the IDX-th tree in ENCODER. */ @@ -1029,49 +1047,161 @@ lto_tree_ref_encoder_get_tree (struct lto_tree_ref_encoder *encoder, unsigned int idx) { - return VEC_index (tree, encoder->trees, idx); + return encoder->trees[idx]; +} + +/* Return number of encoded nodes in ENCODER. */ +static inline int +lto_symtab_encoder_size (lto_symtab_encoder_t encoder) +{ + return encoder->nodes.length (); +} + +/* Value used to represent failure of lto_symtab_encoder_lookup. */ +#define LCC_NOT_FOUND (-1) + +/* Look up NODE in encoder. Return NODE's reference if it has been encoded + or LCC_NOT_FOUND if it is not there. */ + +static inline int +lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder, + symtab_node *node) +{ + size_t *slot = encoder->map->get (node); + return (slot && *slot ? *(slot) - 1 : LCC_NOT_FOUND); +} + +/* Return true if iterator LSE points to nothing. */ +static inline bool +lsei_end_p (lto_symtab_encoder_iterator lsei) +{ + return lsei.index >= (unsigned)lto_symtab_encoder_size (lsei.encoder); } +/* Advance iterator LSE. */ +static inline void +lsei_next (lto_symtab_encoder_iterator *lsei) +{ + lsei->index++; +} -/* Return true if LABEL should be emitted in the global context. */ -static inline bool -emit_label_in_global_context_p (tree label) +/* Return the node pointed to by LSI. */ +static inline symtab_node * +lsei_node (lto_symtab_encoder_iterator lsei) { - return DECL_NONLOCAL (label) || FORCED_LABEL (label); + return lsei.encoder->nodes[lsei.index].node; } -/* Return true if tree node EXPR should be streamed as a builtin. For - these nodes, we just emit the class and function code. */ -static inline bool -lto_stream_as_builtin_p (tree expr) +/* Return the node pointed to by LSI. */ +static inline struct cgraph_node * +lsei_cgraph_node (lto_symtab_encoder_iterator lsei) +{ + return dyn_cast<cgraph_node *> (lsei.encoder->nodes[lsei.index].node); +} + +/* Return the node pointed to by LSI. */ +static inline varpool_node * +lsei_varpool_node (lto_symtab_encoder_iterator lsei) { - return (TREE_CODE (expr) == FUNCTION_DECL - && DECL_IS_BUILTIN (expr) - && (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_NORMAL - || DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD)); + return dyn_cast<varpool_node *> (lsei.encoder->nodes[lsei.index].node); +} + +/* Return the cgraph node corresponding to REF using ENCODER. */ + +static inline symtab_node * +lto_symtab_encoder_deref (lto_symtab_encoder_t encoder, int ref) +{ + if (ref == LCC_NOT_FOUND) + return NULL; + + return encoder->nodes[ref].node; } -/* Return true if EXPR is a tree node that can be written to disk. */ -static inline bool -lto_is_streamable (tree expr) +/* Return an iterator to the first node in LSI. */ +static inline lto_symtab_encoder_iterator +lsei_start (lto_symtab_encoder_t encoder) +{ + lto_symtab_encoder_iterator lsei; + + lsei.encoder = encoder; + lsei.index = 0; + return lsei; +} + +/* Advance iterator LSE. */ +static inline void +lsei_next_in_partition (lto_symtab_encoder_iterator *lsei) { - enum tree_code code = TREE_CODE (expr); + lsei_next (lsei); + while (!lsei_end_p (*lsei) + && !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei))) + lsei_next (lsei); +} + +/* Return an iterator to the first node in LSI. */ +static inline lto_symtab_encoder_iterator +lsei_start_in_partition (lto_symtab_encoder_t encoder) +{ + lto_symtab_encoder_iterator lsei = lsei_start (encoder); + + if (lsei_end_p (lsei)) + return lsei; + if (!lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei))) + lsei_next_in_partition (&lsei); + + return lsei; +} - /* Notice that we reject SSA_NAMEs as well. We only emit the SSA - name version in lto_output_tree_ref (see output_ssa_names). */ - return !is_lang_specific (expr) - && code != SSA_NAME - && code != CALL_EXPR - && code != LANG_TYPE - && code != MODIFY_EXPR - && code != INIT_EXPR - && code != TARGET_EXPR - && code != BIND_EXPR - && code != WITH_CLEANUP_EXPR - && code != STATEMENT_LIST - && (code == CASE_LABEL_EXPR - || code == DECL_EXPR - || TREE_CODE_CLASS (code) != tcc_statement); +/* Advance iterator LSE. */ +static inline void +lsei_next_function_in_partition (lto_symtab_encoder_iterator *lsei) +{ + lsei_next (lsei); + while (!lsei_end_p (*lsei) + && (!is_a <cgraph_node *> (lsei_node (*lsei)) + || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei)))) + lsei_next (lsei); +} + +/* Return an iterator to the first node in LSI. */ +static inline lto_symtab_encoder_iterator +lsei_start_function_in_partition (lto_symtab_encoder_t encoder) +{ + lto_symtab_encoder_iterator lsei = lsei_start (encoder); + + if (lsei_end_p (lsei)) + return lsei; + if (!is_a <cgraph_node *> (lsei_node (lsei)) + || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei))) + lsei_next_function_in_partition (&lsei); + + return lsei; +} + +/* Advance iterator LSE. */ +static inline void +lsei_next_variable_in_partition (lto_symtab_encoder_iterator *lsei) +{ + lsei_next (lsei); + while (!lsei_end_p (*lsei) + && (!is_a <varpool_node *> (lsei_node (*lsei)) + || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei)))) + lsei_next (lsei); +} + +/* Return an iterator to the first node in LSI. */ +static inline lto_symtab_encoder_iterator +lsei_start_variable_in_partition (lto_symtab_encoder_t encoder) +{ + lto_symtab_encoder_iterator lsei = lsei_start (encoder); + + if (lsei_end_p (lsei)) + return lsei; + if (!is_a <varpool_node *> (lsei_node (lsei)) + || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei))) + lsei_next_variable_in_partition (&lsei); + + return lsei; } DEFINE_DECL_STREAM_FUNCS (TYPE, type) @@ -1082,85 +1212,14 @@ DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl) DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl) -/* Returns a new bit-packing context for bit-packing into S. */ -static inline struct bitpack_d -bitpack_create (struct lto_output_stream *s) -{ - struct bitpack_d bp; - bp.pos = 0; - bp.word = 0; - bp.stream = (void *)s; - return bp; -} - -/* Pack the NBITS bit sized value VAL into the bit-packing context BP. */ -static inline void -bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits) -{ - bitpack_word_t word = bp->word; - int pos = bp->pos; - /* If val does not fit into the current bitpack word switch to the - next one. */ - if (pos + nbits > BITS_PER_BITPACK_WORD) - { - lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream, word); - word = val; - pos = nbits; - } - else - { - word |= val << pos; - pos += nbits; - } - bp->word = word; - bp->pos = pos; -} +/* Entry for the delayed registering of decl -> DIE references. */ +struct dref_entry { + tree decl; + const char *sym; + unsigned HOST_WIDE_INT off; +}; -/* Finishes bit-packing of BP. */ -static inline void -lto_output_bitpack (struct bitpack_d *bp) -{ - lto_output_uleb128_stream ((struct lto_output_stream *) bp->stream, - bp->word); - bp->word = 0; - bp->pos = 0; -} - -/* Returns a new bit-packing context for bit-unpacking from IB. */ -static inline struct bitpack_d -lto_input_bitpack (struct lto_input_block *ib) -{ - struct bitpack_d bp; - bp.word = lto_input_uleb128 (ib); - bp.pos = 0; - bp.stream = (void *)ib; - return bp; -} +extern vec<dref_entry> dref_queue; -/* Unpacks NBITS bits from the bit-packing context BP and returns them. */ -static inline bitpack_word_t -bp_unpack_value (struct bitpack_d *bp, unsigned nbits) -{ - bitpack_word_t mask, val; - int pos = bp->pos; - - mask = (nbits == BITS_PER_BITPACK_WORD - ? (bitpack_word_t) -1 - : ((bitpack_word_t) 1 << nbits) - 1); - - /* If there are not continuous nbits in the current bitpack word - switch to the next one. */ - if (pos + nbits > BITS_PER_BITPACK_WORD) - { - bp->word = val = lto_input_uleb128 ((struct lto_input_block *)bp->stream); - bp->pos = nbits; - return val & mask; - } - val = bp->word; - val >>= pos; - bp->pos = pos + nbits; - - return val & mask; -} #endif /* GCC_LTO_STREAMER_H */