Hi. The patch is about a new ELF section that will contain information about LTO version. And for the future, used compression will be stored here. The patch removes streaming of the version into each section.
Disadvantage is a format change that will lead to following errors when LTO bytecode is used from a different version: $ gcc x.o lto1: fatal error: bytecode stream in file ‘x.o’ generated with GCC compiler older than 10.0 $ gcc-9 main.o lto1: fatal error: bytecode stream in file ‘main.o’ generated with LTO version 850.0 instead of the expected 8.0 I've been testing the patch. Thoughts? Martin
>From a694d3244812bb8c0ae79d3ef5aecc6f5a2bd9ca Mon Sep 17 00:00:00 2001 From: Martin Liska <mli...@suse.cz> Date: Fri, 21 Jun 2019 12:14:04 +0200 Subject: [PATCH] Add .gnu.lto_.meta section. gcc/ChangeLog: 2019-06-21 Martin Liska <mli...@suse.cz> * lto-section-in.c (lto_get_section_data): Do not decompress LTO_section_meta section. * lto-section-out.c (lto_destroy_simple_output_block): Do not set major and minor version. * lto-streamer-out.c (produce_asm): Likewise. (lto_output_toplevel_asms): Likewise here. (produce_lto_meta): New. (lto_output): Produce LTO meta section. (lto_write_mode_table): Do not set major and minor version. (produce_asm_for_decls): Likewise. * lto-streamer.h (enum lto_section_type): Add LTO_section_meta. (struct lto_simple_header): Do not inherit from lto_simple_header. gcc/lto/ChangeLog: 2019-06-21 Martin Liska <mli...@suse.cz> * lto-common.c: Check for LTO bytecode version. --- gcc/lto-section-in.c | 9 +++------ gcc/lto-section-out.c | 2 -- gcc/lto-streamer-out.c | 36 +++++++++++++++++++++--------------- gcc/lto-streamer.h | 3 ++- gcc/lto/lto-common.c | 14 ++++++++++++++ 5 files changed, 40 insertions(+), 24 deletions(-) diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c index 4cfc0cad4be..96962f2f2c4 100644 --- a/gcc/lto-section-in.c +++ b/gcc/lto-section-in.c @@ -52,10 +52,10 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] = "icf", "offload_table", "mode_table", - "hsa" + "hsa", + "meta" }; - /* Hooks so that the ipa passes can call into the lto front end to get sections. */ @@ -146,7 +146,7 @@ lto_get_section_data (struct lto_file_decl_data *file_data, /* WPA->ltrans streams are not compressed with exception of function bodies and variable initializers that has been verbatim copied from earlier compilations. */ - if (!flag_ltrans || decompress) + if ((!flag_ltrans || decompress) && section_type != LTO_section_meta) { /* Create a mapping header containing the underlying data and length, and prepend this to the uncompression buffer. The uncompressed data @@ -167,9 +167,6 @@ lto_get_section_data (struct lto_file_decl_data *file_data, data = buffer.data + header_length; } - lto_check_version (((const lto_header *)data)->major_version, - ((const lto_header *)data)->minor_version, - file_data->file_name); return data; } diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c index c91e58f0465..7ae102164ef 100644 --- a/gcc/lto-section-out.c +++ b/gcc/lto-section-out.c @@ -285,8 +285,6 @@ lto_destroy_simple_output_block (struct lto_simple_output_block *ob) /* Write the header which says how to decode the pieces of the t. */ memset (&header, 0, sizeof (struct lto_simple_header)); - header.major_version = LTO_major_version; - header.minor_version = LTO_minor_version; header.main_size = ob->main_stream->total_size; lto_write_data (&header, sizeof header); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index b1084f4d3c5..bd259097dc4 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1972,10 +1972,6 @@ produce_asm (struct output_block *ob, tree fn) /* The entire header is stream computed here. */ memset (&header, 0, sizeof (struct lto_function_header)); - /* Write the header. */ - header.major_version = LTO_major_version; - header.minor_version = LTO_minor_version; - if (section_type == LTO_section_function_body) header.cfg_size = ob->cfg_stream->total_size; header.main_size = ob->main_stream->total_size; @@ -2268,10 +2264,6 @@ lto_output_toplevel_asms (void) /* The entire header stream is computed here. */ memset (&header, 0, sizeof (header)); - /* Write the header. */ - header.major_version = LTO_major_version; - header.minor_version = LTO_minor_version; - header.main_size = ob->main_stream->total_size; header.string_size = ob->string_stream->total_size; lto_write_data (&header, sizeof header); @@ -2388,6 +2380,25 @@ prune_offload_funcs (void) DECL_PRESERVE_P (fn_decl) = 1; } +/* Produce LTO meta section that contains global information + about LTO bytecode. */ + +static void +produce_lto_meta () +{ + /* Stream LTO meta section. */ + output_block *ob = create_output_block (LTO_section_meta); + + char * section_name = lto_get_section_name (LTO_section_meta, NULL, NULL); + lto_begin_section (section_name, false); + free (section_name); + + lto_header header = { LTO_major_version, LTO_minor_version }; + lto_write_data (&header, sizeof header); + lto_end_section (); + destroy_output_block (ob); +} + /* Main entry point from the pass manager. */ void @@ -2406,6 +2417,8 @@ lto_output (void) /* Initialize the streamer. */ lto_streamer_init (); + produce_lto_meta (); + n_nodes = lto_symtab_encoder_size (encoder); /* Process only the functions with bodies. */ for (i = 0; i < n_nodes; i++) @@ -2825,10 +2838,6 @@ lto_write_mode_table (void) struct lto_simple_header_with_strings header; memset (&header, 0, sizeof (header)); - /* Write the header. */ - header.major_version = LTO_major_version; - header.minor_version = LTO_minor_version; - header.main_size = ob->main_stream->total_size; header.string_size = ob->string_stream->total_size; lto_write_data (&header, sizeof header); @@ -2899,9 +2908,6 @@ produce_asm_for_decls (void) lto_output_decl_state_streams (ob, fn_out_state); } - header.major_version = LTO_major_version; - header.minor_version = LTO_minor_version; - /* Currently not used. This field would allow us to preallocate the globals vector, so that it need not be resized as it is extended. */ header.num_nodes = -1; diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index d087cba9bf0..1b20161d193 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -234,6 +234,7 @@ enum lto_section_type LTO_section_offload_table, LTO_section_mode_table, LTO_section_ipa_hsa, + LTO_section_meta, LTO_N_SECTION_TYPES /* Must be last. */ }; @@ -389,7 +390,7 @@ struct lto_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 +struct lto_simple_header { /* Size of main gimple body of function. */ int32_t main_size; diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c index 9d2f9c57780..6e64a5e4110 100644 --- a/gcc/lto/lto-common.c +++ b/gcc/lto/lto-common.c @@ -2058,6 +2058,20 @@ lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file) #else file_data->mode_table = lto_mode_identity_table; #endif + + /* Read and verify LTO meta header. */ + data = lto_get_section_data (file_data, LTO_section_meta, NULL, &len, false); + if (data == NULL) + { + fatal_error (input_location, "bytecode stream in file %qs generated " + "with GCC compiler older than 10.0", file_data->file_name); + return; + } + + lto_check_version (((const lto_header *)data)->major_version, + ((const lto_header *)data)->minor_version, + file_data->file_name); + data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len); if (data == NULL) { -- 2.21.0