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

Reply via email to