From patchwork Sat Oct 2 21:16:38 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andi Kleen X-Patchwork-Id: 66583 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A8B21B70A8 for ; Sun, 3 Oct 2010 08:17:14 +1100 (EST) Received: (qmail 12551 invoked by alias); 2 Oct 2010 21:17:12 -0000 Received: (qmail 12525 invoked by uid 22791); 2 Oct 2010 21:17:11 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, TW_SV, TW_XF, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from one.firstfloor.org (HELO one.firstfloor.org) (213.235.205.2) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 02 Oct 2010 21:17:03 +0000 Received: from basil.firstfloor.org (p5B3C8AA2.dip0.t-ipconnect.de [91.60.138.162]) by one.firstfloor.org (Postfix) with ESMTP id 7EADC1A9804F; Sat, 2 Oct 2010 23:17:00 +0200 (CEST) Received: by basil.firstfloor.org (Postfix, from userid 1000) id 0FEFFB2532; Sat, 2 Oct 2010 23:17:00 +0200 (CEST) From: Andi Kleen To: gcc-patches@gcc.gnu.org Cc: Andi Kleen Subject: [PATCH] Save checksum of compiler options in LTO files Date: Sat, 2 Oct 2010 23:16:38 +0200 Message-Id: <1286054198-19617-1-git-send-email-andi@firstfloor.org> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org From: Andi Kleen I was finally tired of constant ICEs when I updated to a newer svn version because there were some stale LTO files lying around somewhere. The usual reason were added gcc options, which then change the option offsets and confuse the LTO options save/restore code. There is already a version check, but it only checks major/minor and does not handle smaller scale changes. This patch computes an checksum over all supported options at build time and then saves/compares that in the LTO object file. I used a simple 8bit fletcher checksum implemented in awk. This is not very strong, but should be good enough for this purpose. This fixes PR lto/44965 Passes bootstrap and full testsuite on x86_64-linux. Ok to commit? 2010-10-02 Andi Kleen PR lto/44965 * lto-opts.c (lto_opts_header): Add. (lto_write_options): Write out options checksum. (lto_read_file_options): Read and check options checksum. * opt-functions.awk (csum, csum_combine): Add. * optc-gen.awk (END): Compute and dump options checksum. * opth-gen.awk (END): Print declaration for opts_checksum. --- gcc/lto-opts.c | 35 ++++++++++++++++++++++------------- gcc/opt-functions.awk | 27 +++++++++++++++++++++++++++ gcc/optc-gen.awk | 4 ++++ gcc/opth-gen.awk | 3 +++ 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c index bbe2138..4c73c07 100644 --- a/gcc/lto-opts.c +++ b/gcc/lto-opts.c @@ -79,6 +79,11 @@ typedef struct GTY(()) opt_d DEF_VEC_O (opt_t); DEF_VEC_ALLOC_O (opt_t, heap); +struct lto_opts_header +{ + struct lto_simple_header simple; + unsigned checksum; +}; /* Options are held in two vectors, one for those registered by command line handling code, and the other for those read in from @@ -296,7 +301,7 @@ lto_write_options (void) { char *const section_name = lto_get_section_name (LTO_section_opts, NULL, NULL); struct lto_output_stream stream; - struct lto_simple_header header; + struct lto_opts_header header; struct lto_output_stream *header_stream; lto_begin_section (section_name, !flag_wpa); @@ -306,12 +311,13 @@ lto_write_options (void) output_options (&stream); memset (&header, 0, sizeof (header)); - header.lto_header.major_version = LTO_major_version; - header.lto_header.minor_version = LTO_minor_version; - header.lto_header.section_type = LTO_section_opts; + header.simple.lto_header.major_version = LTO_major_version; + header.simple.lto_header.minor_version = LTO_minor_version; + header.simple.lto_header.section_type = LTO_section_opts; - header.compressed_size = 0; - header.main_size = stream.total_size; + header.simple.compressed_size = 0; + header.simple.main_size = stream.total_size; + header.checksum = opts_checksum; header_stream = ((struct lto_output_stream *) xcalloc (1, sizeof (*header_stream))); @@ -351,7 +357,7 @@ lto_read_file_options (struct lto_file_decl_data *file_data) { size_t len, l, skip; const char *data, *p; - const struct lto_simple_header *header; + const struct lto_opts_header *header; int32_t opts_offset; struct lto_input_block ib; @@ -368,16 +374,19 @@ lto_read_file_options (struct lto_file_decl_data *file_data) p = data; do { - header = (const struct lto_simple_header *) p; + header = (const struct lto_opts_header *) p; opts_offset = sizeof (*header); - lto_check_version (header->lto_header.major_version, - header->lto_header.minor_version); - - LTO_INIT_INPUT_BLOCK (ib, p + opts_offset, 0, header->main_size); + lto_check_version (header->simple.lto_header.major_version, + header->simple.lto_header.minor_version); + + if (header->checksum != opts_checksum) + fatal_error ("LTO input file options checksum does not match mine"); + + LTO_INIT_INPUT_BLOCK (ib, p + opts_offset, 0, header->simple.main_size); input_options (&ib); - skip = header->main_size + opts_offset; + skip = header->simple.main_size + opts_offset; l -= skip; p += skip; } diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk index 863c478..75a7f33 100644 --- a/gcc/opt-functions.awk +++ b/gcc/opt-functions.awk @@ -215,3 +215,30 @@ function opt_enum(name) { return "OPT_" opt_sanitized_name(name) } + +# 8bit fletcher checksum. dumb, but simple version +function csum(array) +{ + # yes this is the official recommended GNU awk method :-( + for (i = 0; i < 255; i++) { + t = sprintf("%c", i) + ord[t] = i + } + + a = 0 + b = 0 + for (s in array) { + for (k = 0; k < length("" s); k++) { + a = a + ord[substr(s, k, 1)] + b = b + a + } + a = a % 0xff + b = b % 0xff + } + return or(lshift(a,8),b) +} + +function csum_combine(a,b) +{ + return a + lshift(b, 16) +} diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk index bad055f..86e0c96 100644 --- a/gcc/optc-gen.awk +++ b/gcc/optc-gen.awk @@ -596,6 +596,10 @@ print " if (targetm.target_option.print)"; print " targetm.target_option.print (file, indent, ptr);"; print "}"; + +sum = csum_combine(csum(opts), csum(indices)); +printf("const unsigned opts_checksum = 0x%x;\n", sum); + print "#endif"; } diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk index d27dfc0..dc3b6d8 100644 --- a/gcc/opth-gen.awk +++ b/gcc/opth-gen.awk @@ -283,6 +283,9 @@ print "extern void cl_target_option_restore (struct gcc_options *, struct cl_tar print ""; print "/* Print target option variables from a structure. */"; print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);"; +print ""; +print "/* Checksum of all options */"; +print "extern const unsigned opts_checksum;"; print "#endif"; print "";