From patchwork Tue Oct 6 18:40:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rong Xu X-Patchwork-Id: 526872 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2DCEC14012C for ; Wed, 7 Oct 2015 05:40:47 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=q1JSjFVy; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; q=dns; s=default; b=kR4ZiaXJoI0VfApbT3 GaYwlpgthCkhVC+QmncOzoRpcR/20nuHjZqDJ87qI0xrcQs9TWss5IeA12NYyTfI wok26Z6yBuxvMRcTqcSoUZuE9vSSFZXriS7BmU7DIc2SLTw//xlYN2riIADW0yBx dmlm/ND8V+1SlCkYND3wuLM4M= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; s=default; bh=wMizCFRdjJDT5/uXY6YjTEpe 4o8=; b=q1JSjFVyEawPd5nKgtyxuSZUeJe8b3CeeSOz5NeWQQY86a2C3Z4Q59mz XEAOVdk5xs6p+jt41GR2UC2d9agPbbBzavi6qquKxICWGSYyVWtTTJDsdZlMHruO /I8LG8PX9pKlU7T+ISoBEJoiUwbWL+8i49HlQ+CCUsj4rqakwFk= Received: (qmail 76262 invoked by alias); 6 Oct 2015 18:40:38 -0000 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 Received: (qmail 76249 invoked by uid 89); 6 Oct 2015 18:40:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mail-yk0-f179.google.com Received: from mail-yk0-f179.google.com (HELO mail-yk0-f179.google.com) (209.85.160.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 06 Oct 2015 18:40:32 +0000 Received: by ykft14 with SMTP id t14so212527828ykf.0 for ; Tue, 06 Oct 2015 11:40:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=kSPT3WxD0ZdNURAs8iCksyD/b0ge+MeEXDzncJAhHXM=; b=DG0+k1nwt2HPdwmZ7aU6XIA6dn6/Fb4m7gcpJkxYXi4PbKVuscxrsnxAyKnVpM3ZyE /uA76QZePcRTzEIw3dFB2uBeW3X7RzWnPGtfCyistJts/dr5MB9AOFIENE9/Irnqh84Q +SF0xH8n+PkQ6aDkf6ChtCXgjomml1Y0ltmm6K/aifpb3PvqqmXkO9jVLycjckhZby14 yjB8VHsXlOWHobk/mZwR0U5MwtKXpTjSHf4cUt9ErY9hQPebrttPfWd3XNTKpJw9vJiO 5uJ99YFw4dJ5ZexBhljHZrPr/tM6HQivJRHOeMcgVU7eExR2jQGr7B8zOAMfNWJ39LJj u6Rw== X-Gm-Message-State: ALoCoQk8PVml1uqgpUxQVUiwtB6pwhG/IBTvaPgiDIAL84CSbfBEzZ+fFaN9DcC2Pv5+GXt9Tstn MIME-Version: 1.0 X-Received: by 10.13.192.66 with SMTP id b63mr28267080ywd.80.1444156830327; Tue, 06 Oct 2015 11:40:30 -0700 (PDT) Received: by 10.37.22.130 with HTTP; Tue, 6 Oct 2015 11:40:30 -0700 (PDT) In-Reply-To: References: Date: Tue, 6 Oct 2015 11:40:30 -0700 Message-ID: Subject: Re: [google][gcc-4_9] encode and compress cc1 option strings in gcov_module_info From: Rong Xu To: Xinliang David Li Cc: GCC Patches X-IsSubscribed: yes Here is the patch set 2 that integrates David's comments. Note that this uses the combined strlen (i.e. encoding compressed and uncompressed strlen into one gcov_unsigned_t). Testing is ongoing. -Rong On Tue, Oct 6, 2015 at 11:30 AM, Rong Xu wrote: > It's 1:3 to 1:4 in the programs I tested. But it really depends on how > the options are used. I think your idea of using combined strlen works > better. > I just make the code a little clumsy but it does not cause any > performance issue. > > On Tue, Oct 6, 2015 at 10:21 AM, Xinliang David Li wrote: >> On Tue, Oct 6, 2015 at 9:26 AM, Rong Xu wrote: >>> On Mon, Oct 5, 2015 at 5:33 PM, Xinliang David Li wrote: >>>> unsigned ggc_memory = gcov_read_unsigned (); >>>> + unsigned marker = 0, len = 0, k; >>>> + char **string_array, *saved_cc1_strings; >>>> + >>>> for (unsigned j = 0; j < 7; j++) >>>> >>>> >>>> Do not use hard coded number. Use the enum defined in coverage.c. >>> >>> OK. >>> >>>> >>>> >>>> + string_array[j] = xstrdup (gcov_read_string ()); >>>> + >>>> + k = 0; >>>> + for (unsigned j = 1; j < 7; j++) >>>> >>>> Do not use hard coded number. >>> >>> OK. >>> >>>> >>>> >>>> + { >>>> + if (num_array[j] == 0) >>>> + continue; >>>> + marker += num_array[j]; >>>> >>>> It is better to read if the name of variable 'marker' is changed to >>>> 'j_end' or something similar >>>> >>>> For all the substrings of 'j' kind, there should be just one marker, >>>> right? It looks like here you introduce one marker per string, not one >>>> marker per string kind. >>> >>> I don't understand what you meant here. "marker" is fixed for each j >>> substring (one option kind) -- it the end index of the sub-string >>> array. k-loop is for each string. >>> >> >> That was a wrong comment from me. Discard it. >> >>>> >>>> + len += 3; /* [[ */ >>>> >>>> Same here for hard coded value. >>>> >>>> + for (; k < marker; k++) >>>> + len += strlen (string_array[k]) + 1; /* 1 for delimter of ']' */ >>>> >>>> Why do we need one ']' per string? >>> >>> This is because the options strings can contain space ' '. I cannot >>> use space as the delimiter, neither is \0 as it is the end of the >>> string of the encoded string. >> >> Ok -- this allows you to avoid string copy during parsing. >>> >>>> >>>> >>>> + } >>>> + saved_cc1_strings = (char *) xmalloc (len + 1); >>>> + saved_cc1_strings[0] = 0; >>>> + >>>> + marker = 0; >>>> + k = 0; >>>> + for (unsigned j = 1; j < 7; j++) >>>> >>>> Same here for 7. >>> >>> will fix in the new patch. >>> >>>> >>>> + { >>>> + static const char lipo_string_flags[6] = {'Q', 'B', 'S', >>>> 'D','I', 'C'}; >>>> + if (num_array[j] == 0) >>>> + continue; >>>> + marker += num_array[j]; >>>> >>>> Suggest changing marker to j_end >>> OK. >>> >>>> >>>> + sprintf (saved_cc1_strings, "%s[[%c", saved_cc1_strings, >>>> + lipo_string_flags[j - 1]); >>>> + for (; k < marker; k++) >>>> + { >>>> + sprintf (saved_cc1_strings, "%s%s]", saved_cc1_strings, >>>> + string_array[k]); >>>> >>>> +#define DELIMTER "[[" >>>> >>>> Why double '[' ? >>> I will change to single '['. >>> >>>> >>>> +#define DELIMTER2 "]" >>>> +#define QUOTE_PATH_FLAG 'Q' >>>> +#define BRACKET_PATH_FLAG 'B' >>>> +#define SYSTEM_PATH_FLAG 'S' >>>> +#define D_U_OPTION_FLAG 'D' >>>> +#define INCLUDE_OPTION_FLAG 'I' >>>> +#define COMMAND_ARG_FLAG 'C' >>>> + >>>> +enum lipo_cc1_string_kind { >>>> + k_quote_paths = 0, >>>> + k_bracket_paths, >>>> + k_system_paths, >>>> + k_cpp_defines, >>>> + k_cpp_includes, >>>> + k_lipo_cl_args, >>>> + num_lipo_cc1_string_kind >>>> +}; >>>> + >>>> +struct lipo_parsed_cc1_string { >>>> + const char* source_filename; >>>> + unsigned num[num_lipo_cc1_string_kind]; >>>> + char **strings[num_lipo_cc1_string_kind]; >>>> +}; >>>> + >>>> +struct lipo_parsed_cc1_string * >>>> +lipo_parse_saved_cc1_string (const char *src, char *str, >>>> + bool parse_cl_args_only); >>>> +void free_parsed_string (struct lipo_parsed_cc1_string *string); >>>> + >>>> >>>> Declare above in a header file. >>> >>> OK. >>> >>>> >>>> >>>> /* Returns true if the command-line arguments stored in the given module-infos >>>> are incompatible. */ >>>> bool >>>> -incompatible_cl_args (struct gcov_module_info* mod_info1, >>>> - struct gcov_module_info* mod_info2) >>>> +incompatible_cl_args (struct lipo_parsed_cc1_string* mod_info1, >>>> + struct lipo_parsed_cc1_string* mod_info2) >>>> >>>> Fix formating. >>> OK. >>>> >>>> { >>>> { >>>> @@ -1647,7 +1679,7 @@ build_var (tree fn_decl, tree type, int counter) >>>> /* Creates the gcov_fn_info RECORD_TYPE. */ >>>> >>>> NULL_TREE, get_gcov_unsigned_t ()); >>>> DECL_CHAIN (field) = fields; >>>> fields = field; >>>> >>>> - /* Num bracket paths */ >>>> + /* cc1_uncompressed_strlen field */ >>>> field = build_decl (BUILTINS_LOCATION, FIELD_DECL, >>>> NULL_TREE, get_gcov_unsigned_t ()); >>>> DECL_CHAIN (field) = fields; >>>> fields = field; >>>> >>>> >>>> Why do we need to store uncompressed string length? If there is need >>>> to do that, I suggest combine uncompressed length and compressed >>>> length into one 32bit integer. (16/16, or 17/15 split) >>> >>> In theory, I don't need the uncompressed length, But I would need to >>> guess the uncompressed length to allocate the buffer. If the >>> decompressing fails with insufficient space, I need to have another >>> guess and do it again. I think it's easier just save the uncompressed >>> size to the struct. I think combine the two sizes into one >>> gcov_unsigned_t is a good idea. We don't expect the string size are >>> very big. >> >> What is the usual compression ratio? If you guess it right most of the >> time, just get rid of the uncompressed length. >> >> David >> >>>> >>>> >>>> David >>>> >>>> On Mon, Oct 5, 2015 at 3:51 PM, Rong Xu wrote: >>>>> Hi, >>>>> >>>>> This patch is for google branch only. >>>>> >>>>> It encodes and compresses various cc1 option strings in >>>>> gcov_module_info to reduce the lipo instrumented object size. The >>>>> savings are from string compression and the reduced number of >>>>> relocations. >>>>> >>>>> More specifically, we replace the following fields in gcov_module_info >>>>> gcov_unsigned_t num_quote_paths; >>>>> gcov_unsigned_t num_bracket_paths; >>>>> gcov_unsigned_t num_system_paths; >>>>> gcov_unsigned_t num_cpp_defines; >>>>> gcov_unsigned_t num_cpp_includes; >>>>> gcov_unsigned_t num_cl_args; >>>>> char *string_array[1]; >>>>> with >>>>> gcov_unsigned_t cc1_strlen; >>>>> gcov_unsigned_t cc1_uncompressed_strlen; >>>>> char *saved_cc1_strings; >>>>> >>>>> The new saved_cc1_strings are zlib compressed string. >>>>> >>>>> Tested with google internal benchmarks. >>>>> >>>>> Thanks, >>>>> >>>>> -Rong 2015-10-06 Rong Xu * gcc/Makefile.in (gcov-dump): link with zlib (gcov-tool): Ditto. * gcc/auto-profile.c (autofdo_module_profile::read): convert old gcov_module_info to the new format. (read_aux_modules): using new incompatible_cl_args interface. * gcc/coverage.c (zlib.h): new include. (incompatible_cl_args): change the paramter. (read_counts_file): using new gcov_module_info. (build_fn_info_type): remove used parameter. (build_gcov_module_info_type): using new gcov_module_info. (free_parsed_string): new function. (find_substr): ditto. (lipo_parse_saved_cc1_string): ditto. (lipo_append_tag): ditto. (build_gcov_module_info_value): using new gcov_module_info. (coverage_obj_init): remove used parameter. (add_module_info): using new gcov_module_info. (process_include): ditto. (process_include_paths_1): ditto. (process_include_paths): ditto. (set_lipo_c_parsing_context): ditto. * gcc/coverage.h: add new decls. * gcc/gcov-io.c (zlib.h) new include. (gcov_read_module_info): using new gcov_module_info. * gcc/gcov-io.h (struct gcov_module_info): new gcov_module_info. (enum lipo_cc1_string_kind): new define. (struct lipo_parsed_cc1_string): new define. * libgcc/dyn-ipa.c: delete unused code. * libgcc/libgcov-driver.c (gcov_write_module_info): using new gcov_module_info. Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (revision 228354) +++ gcc/Makefile.in (working copy) @@ -2583,7 +2583,7 @@ gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS) GCOV_DUMP_OBJS = gcov-dump.o vec.o ggc-none.o gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) \ - $(LIBS) -o $@ + $(LIBS) $(ZLIB) -o $@ GCOV_TOOL_DEP_FILES = $(srcdir)/../libgcc/libgcov-util.c gcov-io.c $(GCOV_IO_H) \ $(srcdir)/../libgcc/libgcov-driver.c $(srcdir)/../libgcc/libgcov-driver-system.c \ @@ -2607,7 +2607,7 @@ gcov-tool-params.o: params.c $(CONFIG_H) $(SYSTEM_ GCOV_TOOL_OBJS = gcov-tool.o libgcov-util.o libgcov-driver-tool.o \ libgcov-merge-tool.o gcov-tool-dyn-ipa.o gcov-tool-params.o gcov-tool$(exeext): $(GCOV_TOOL_OBJS) $(LIBDEPS) - +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_TOOL_OBJS) $(LIBS) -o $@ + +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_TOOL_OBJS) $(LIBS) $(ZLIB) -o $@ # # Build the include directories. The stamp files are stmp-* rather than # s-* so that mostlyclean does not force the include directory to Index: gcc/auto-profile.c =================================================================== --- gcc/auto-profile.c (revision 228354) +++ gcc/auto-profile.c (working copy) @@ -947,7 +947,6 @@ autofdo_source_profile::get_function_instance_by_i return s; } - /* Member functions for autofdo_module_profile. */ bool @@ -968,11 +967,14 @@ autofdo_module_profile::read () { char *name = xstrdup (gcov_read_string ()); unsigned total_num = 0; - unsigned num_array[7]; + unsigned num_array[num_lipo_cc1_string_kind]; unsigned exported = gcov_read_unsigned (); unsigned lang = gcov_read_unsigned (); unsigned ggc_memory = gcov_read_unsigned (); - for (unsigned j = 0; j < 7; j++) + unsigned j_end = 0, len = 0, k; + char **string_array, *saved_cc1_strings; + + for (unsigned j = 0; j < (unsigned)num_lipo_cc1_string_kind; j++) { num_array[j] = gcov_read_unsigned (); total_num += num_array[j]; @@ -988,19 +990,55 @@ autofdo_module_profile::read () module->ident = i + 1; module->lang = lang; module->ggc_memory = ggc_memory; - module->num_quote_paths = num_array[1]; - module->num_bracket_paths = num_array[2]; - module->num_system_paths = num_array[3]; - module->num_cpp_defines = num_array[4]; - module->num_cpp_includes = num_array[5]; - module->num_cl_args = num_array[6]; module->source_filename = name; module->is_primary = strcmp (name, in_fnames[0]) == 0; module->flags = module->is_primary ? exported : 1; for (unsigned j = 0; j < num_array[0]; j++) ret.first->second.first.safe_push (xstrdup (gcov_read_string ())); + + string_array = (char **) alloca ((total_num - num_array[0]) + * sizeof (char*)); for (unsigned j = 0; j < total_num - num_array[0]; j++) - module->string_array[j] = xstrdup (gcov_read_string ()); + string_array[j] = xstrdup (gcov_read_string ()); + + k = 0; + for (unsigned j = 1; j < (unsigned)num_lipo_cc1_string_kind; j++) + { + if (num_array[j] == 0) + continue; + j_end += num_array[j]; + len += strlen (DELIMITER) + 1; /* [ */ + for (; k < j_end; k++) + len += strlen (string_array[k]) + 1; /* 1 for delimiter of ']' */ + } + saved_cc1_strings = (char *) xmalloc (len + 1); + saved_cc1_strings[0] = 0; + + j_end = 0; + k = 0; + for (unsigned j = 1; j < (unsigned)num_lipo_cc1_string_kind; j++) + { + static const char lipo_string_flags[] = { + QUOTE_PATH_FLAG, + BRACKET_PATH_FLAG, + SYSTEM_PATH_FLAG, + D_U_OPTION_FLAG, + INCLUDE_OPTION_FLAG, + COMMAND_ARG_FLAG }; + + if (num_array[j] == 0) + continue; + j_end += num_array[j]; + sprintf (saved_cc1_strings, "%s%s%c", saved_cc1_strings, + DELIMITER, lipo_string_flags[j - 1]); + for (; k < j_end; k++) + { + sprintf (saved_cc1_strings, "%s%s%s", saved_cc1_strings, + string_array[k], DELIMITER2); + free (string_array[k]); + } + } + module->saved_cc1_strings = saved_cc1_strings; } return true; } @@ -1071,6 +1109,10 @@ read_aux_modules (void) record_module_name (module->ident, lbasename (in_fnames[0])); if (aux_modules == NULL) return; + + struct lipo_parsed_cc1_string * module_cl_args = + lipo_parse_saved_cc1_string (module->source_filename, + module->saved_cc1_strings, true); unsigned curr_module = 1, max_group = PARAM_VALUE (PARAM_MAX_LIPO_GROUP); int i; char *str; @@ -1107,17 +1149,23 @@ read_aux_modules (void) inform (0, "Not importing %s: maximum group size reached", str); continue; } - if (incompatible_cl_args (module, aux_module)) + struct lipo_parsed_cc1_string * aux_module_cl_args = + lipo_parse_saved_cc1_string (aux_module->source_filename, + aux_module->saved_cc1_strings, true); + if (incompatible_cl_args (module_cl_args, aux_module_cl_args)) { if (flag_opt_info) inform (0, "Not importing %s: command-line" " arguments not compatible with primary module", str); + free_parsed_string (aux_module_cl_args); continue; } module_infos[curr_module++] = aux_module; add_input_filename (str); record_module_name (aux_module->ident, lbasename (str)); + free_parsed_string (aux_module_cl_args); } + free_parsed_string (module_cl_args); } /* From AutoFDO profiles, find values inside STMT for that we want to measure Index: gcc/coverage.c =================================================================== --- gcc/coverage.c (revision 228354) +++ gcc/coverage.c (working copy) @@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "pointer-set.h" #include "auto-profile.h" +#include "zlib.h" struct GTY((chain_next ("%h.next"))) coverage_data { @@ -187,7 +188,7 @@ static bool has_asm_statement; /* Forward declarations. */ static void read_counts_file (const char *, unsigned); static tree build_var (tree, tree, int); -static void build_fn_info_type (tree, unsigned, tree); +static void build_fn_info_type (tree, unsigned); static void build_info_type (tree, tree); static tree build_fn_info (const struct coverage_data *, tree); static tree build_info (tree, tree); @@ -345,13 +346,18 @@ has_incompatible_cg_opts (bool *cg_opts1, bool *cg /* Returns true if the command-line arguments stored in the given module-infos are incompatible. */ bool -incompatible_cl_args (struct gcov_module_info* mod_info1, - struct gcov_module_info* mod_info2) +incompatible_cl_args (struct lipo_parsed_cc1_string* mod_info1, + struct lipo_parsed_cc1_string* mod_info2) { - char **warning_opts1 = XNEWVEC (char *, mod_info1->num_cl_args); - char **warning_opts2 = XNEWVEC (char *, mod_info2->num_cl_args); - char **non_warning_opts1 = XNEWVEC (char *, mod_info1->num_cl_args); - char **non_warning_opts2 = XNEWVEC (char *, mod_info2->num_cl_args); + unsigned num_cl_args_1 = mod_info1->num[k_lipo_cl_args]; + unsigned num_cl_args_2 = mod_info2->num[k_lipo_cl_args]; + char **string_array_1 = mod_info1->strings[k_lipo_cl_args]; + char **string_array_2 = mod_info2->strings[k_lipo_cl_args]; + + char **warning_opts1 = XNEWVEC (char *, num_cl_args_1); + char **warning_opts2 = XNEWVEC (char *, num_cl_args_2); + char **non_warning_opts1 = XNEWVEC (char *, num_cl_args_1); + char **non_warning_opts2 = XNEWVEC (char *, num_cl_args_2); char *std_opts1 = NULL, *std_opts2 = NULL; unsigned arch_isa1 = 0, arch_isa2 = 0; unsigned int i, num_warning_opts1 = 0, num_warning_opts2 = 0; @@ -359,12 +365,6 @@ bool bool warning_mismatch = false; bool non_warning_mismatch = false; hash_table option_tab1, option_tab2; - unsigned int start_index1 = mod_info1->num_quote_paths - + mod_info1->num_bracket_paths + mod_info1->num_system_paths - + mod_info1->num_cpp_defines + mod_info1->num_cpp_includes; - unsigned int start_index2 = mod_info2->num_quote_paths - + mod_info2->num_bracket_paths + mod_info2->num_system_paths - + mod_info2->num_cpp_defines + mod_info2->num_cpp_includes; bool *cg_opts1, *cg_opts2, has_any_incompatible_cg_opts, has_incompatible_std; bool has_incompatible_arch_isa; @@ -387,14 +387,13 @@ bool option_tab2.create (10); /* First, separate the warning and non-warning options. */ - for (i = 0; i < mod_info1->num_cl_args; i++) - if (mod_info1->string_array[start_index1 + i][1] == 'W') - warning_opts1[num_warning_opts1++] = - mod_info1->string_array[start_index1 + i]; + for (i = 0; i < num_cl_args_1; i++) + if (string_array_1[i][1] == 'W') + warning_opts1[num_warning_opts1++] = string_array_1[i]; else { char **slot; - char *option_string = mod_info1->string_array[start_index1 + i]; + char *option_string = string_array_1[i]; check_cg_opts (cg_opts1, option_string); if (strstr (option_string, "-std=")) @@ -411,14 +410,13 @@ bool } } - for (i = 0; i < mod_info2->num_cl_args; i++) - if (mod_info2->string_array[start_index2 + i][1] == 'W') - warning_opts2[num_warning_opts2++] = - mod_info2->string_array[start_index2 + i]; + for (i = 0; i < num_cl_args_2; i++) + if (string_array_2[i][1] == 'W') + warning_opts2[num_warning_opts2++] = string_array_2[i]; else { char **slot; - char *option_string = mod_info2->string_array[start_index2 + i]; + char *option_string = string_array_2[i]; check_cg_opts (cg_opts2, option_string); if (strstr (option_string, "-std=")) @@ -710,6 +708,7 @@ read_counts_file (const char *da_file_name, unsign unsigned lineno_checksum = 0; unsigned cfg_checksum = 0; const char *imports_filename; + struct lipo_parsed_cc1_string *primary_mod_info_cl_args = NULL; if (max_group == 0) max_group = (unsigned) -1; @@ -891,6 +890,7 @@ read_counts_file (const char *da_file_name, unsign else if (tag == GCOV_TAG_MODULE_INFO && flag_dyn_ipa && !module_id) { struct gcov_module_info* mod_info; + struct lipo_parsed_cc1_string *mod_info_cl_args = NULL; size_t info_sz; /* each string has at least 8 bytes, so MOD_INFO's persistent length >= in core size. */ @@ -898,13 +898,7 @@ read_counts_file (const char *da_file_name, unsign = (struct gcov_module_info *) alloca ((length + 2) * sizeof (gcov_unsigned_t)); gcov_read_module_info (mod_info, length); - info_sz = (sizeof (struct gcov_module_info) + - sizeof (void *) * (mod_info->num_quote_paths + - mod_info->num_bracket_paths + - mod_info->num_system_paths + - mod_info->num_cpp_defines + - mod_info->num_cpp_includes + - mod_info->num_cl_args)); + info_sz = sizeof (struct gcov_module_info); /* The first MODULE_INFO record must be for the primary module. */ if (module_infos_read == 0) { @@ -917,6 +911,8 @@ read_counts_file (const char *da_file_name, unsign module_infos = XCNEWVEC (struct gcov_module_info *, 1); module_infos[0] = XCNEWVAR (struct gcov_module_info, info_sz); memcpy (module_infos[0], mod_info, info_sz); + primary_mod_info_cl_args = lipo_parse_saved_cc1_string ( + mod_info->source_filename, mod_info->saved_cc1_strings, true); } else { @@ -923,6 +919,8 @@ read_counts_file (const char *da_file_name, unsign int fd; char *aux_da_filename = get_da_file_name (mod_info->da_filename); gcc_assert (!mod_info->is_primary); + mod_info_cl_args = lipo_parse_saved_cc1_string ( + mod_info->source_filename, mod_info->saved_cc1_strings, true); if (pointer_set_insert (modset, (void *)(size_t)mod_info->ident)) { if (dump_enabled_p ()) @@ -950,7 +948,8 @@ read_counts_file (const char *da_file_name, unsign "Not importing %s: maximum group size" " reached", mod_info->source_filename); } - else if (incompatible_cl_args (module_infos[0], mod_info)) + else if (incompatible_cl_args (primary_mod_info_cl_args, + mod_info_cl_args)) { if (dump_enabled_p ()) dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, @@ -1012,6 +1011,7 @@ read_counts_file (const char *da_file_name, unsign mod_info->source_filename, mod_info->da_filename); } + free_parsed_string (mod_info_cl_args); } gcov_sync (offset, length); if ((is_error = gcov_is_error ())) @@ -1023,6 +1023,8 @@ read_counts_file (const char *da_file_name, unsign } } + free_parsed_string (primary_mod_info_cl_args); + if ((imports_filename = getenv ("LIPO_REORDER_GROUP")) && flag_dyn_ipa && !module_id) { @@ -1647,7 +1649,7 @@ build_var (tree fn_decl, tree type, int counter) /* Creates the gcov_fn_info RECORD_TYPE. */ static void -build_fn_info_type (tree type, unsigned counters, tree gcov_info_type) +build_fn_info_type (tree type, unsigned counters) { tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE); tree field, fields; @@ -1954,11 +1956,8 @@ static tree build_gcov_module_info_type (void) { tree type, field, fields = NULL_TREE; - tree string_type, index_type, string_array_type; + tree string_type; - cpp_dir *quote_paths, *bracket_paths, *system_paths, *pdir; - int num_quote_paths = 0, num_bracket_paths = 0, num_system_paths = 0; - type = lang_hooks.types.make_type (RECORD_TYPE); string_type = build_pointer_type ( build_qualified_type (char_type_node, @@ -2011,76 +2010,148 @@ build_gcov_module_info_type (void) DECL_CHAIN (field) = fields; fields = field; - /* Num quote paths */ + /* combined_strlen field */ field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ()); DECL_CHAIN (field) = fields; fields = field; - /* Num bracket paths */ + /* Saved cc1 strings */ field = build_decl (BUILTINS_LOCATION, FIELD_DECL, - NULL_TREE, get_gcov_unsigned_t ()); + NULL_TREE, string_type); DECL_CHAIN (field) = fields; fields = field; - /* Num system paths */ - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, - NULL_TREE, get_gcov_unsigned_t ()); - DECL_CHAIN (field) = fields; - fields = field; + finish_builtin_struct (type, "__gcov_module_info", fields, NULL_TREE); - /* Num -D/-U options. */ - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, - NULL_TREE, get_gcov_unsigned_t ()); - DECL_CHAIN (field) = fields; - fields = field; + return type; +} - /* Num -imacro/-include options. */ - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, - get_gcov_unsigned_t ()); - DECL_CHAIN (field) = fields; - fields = field; +/* Free the malloc memory for struct lipo_parsed_cc1_string. */ - /* Num command-line args. */ - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, - NULL_TREE, get_gcov_unsigned_t ()); - DECL_CHAIN (field) = fields; - fields = field; +void +free_parsed_string (struct lipo_parsed_cc1_string *string) +{ + unsigned k; - get_include_chains ("e_paths, &bracket_paths, &system_paths); - for (pdir = quote_paths; pdir; pdir = pdir->next) - { - if (pdir == bracket_paths) + if (string == NULL) + return; + for (k = 0; k < (int) num_lipo_cc1_string_kind; k++) + free (string->strings[k]); + free (string); +} + +/* Find the next encoded string. */ + +static inline char * +find_substr (char *str) +{ + char *substr = strstr(str, DELIMITER); + char ch; + size_t index = strlen (DELIMITER); + + if (substr == NULL || strlen(substr) < index + 1) + return str + strlen(str);; + ch = substr[index]; + if (ch == QUOTE_PATH_FLAG || + ch == BRACKET_PATH_FLAG || + ch == SYSTEM_PATH_FLAG || + ch == D_U_OPTION_FLAG || + ch == INCLUDE_OPTION_FLAG || + ch == COMMAND_ARG_FLAG) + return substr; + return str + strlen(str);; +} + +/* Parsing lipo cc1 strings in module info. Note that the STR is modified + after this function. The modification is to replace delimiter with \0. */ + +struct lipo_parsed_cc1_string * +lipo_parse_saved_cc1_string (const char *src, char *str, bool parse_cl_args_only) +{ + char *substr_begin; + unsigned size = sizeof (struct lipo_parsed_cc1_string); + + struct lipo_parsed_cc1_string *ret = (struct lipo_parsed_cc1_string *) + xmalloc (size); + memset (ret, 0, size); + ret->source_filename = src; + + substr_begin = find_substr (str); + if (substr_begin == str + strlen(str)) + return ret; + do { + char *p, *p1, *substr_end; + char **pp; + unsigned i; + enum lipo_cc1_string_kind k; + + switch (substr_begin[strlen (DELIMITER)]) { + case QUOTE_PATH_FLAG: + k = k_quote_paths; break; - num_quote_paths++; - } - for (pdir = bracket_paths; pdir; pdir = pdir->next) - { - if (pdir == system_paths) + case BRACKET_PATH_FLAG: + k = k_bracket_paths; break; - num_bracket_paths++; + case SYSTEM_PATH_FLAG: + k = k_system_paths; + break; + case D_U_OPTION_FLAG: + k = k_cpp_defines; + break; + case INCLUDE_OPTION_FLAG: + k = k_cpp_includes; + break; + case COMMAND_ARG_FLAG: + k = k_lipo_cl_args; + break; + default: + gcc_unreachable (); } - for (pdir = system_paths; pdir; pdir = pdir->next) - num_system_paths++; + substr_end = find_substr (substr_begin + 2); - /* string array */ - index_type = build_index_type (build_int_cst (NULL_TREE, - num_quote_paths + - num_bracket_paths + - num_system_paths + - num_cpp_defines + - num_cpp_includes + - num_lipo_cl_args)); + if (!parse_cl_args_only || k == k_lipo_cl_args) + { + /* Count number of space char b/w start and end. */ + i = 0; + p = substr_begin + strlen (DELIMITER) + 1; + p1 = p; + while (p != substr_end) { + if (*p == ']') + i++; + p++; + } + ret->num[k] = i; + pp = (char **) xmalloc ((i + 1) * sizeof (char *)); + ret->strings[k] = pp; + /* Replace the delimiter with \0. */ + *pp = p = p1; + while (p != substr_end) { + if (*p == ']') + { + *p = 0; + *(++pp) = p + 1; + } + p++; + } + } - string_array_type = build_array_type (string_type, index_type); - field = build_decl (BUILTINS_LOCATION, FIELD_DECL, - NULL_TREE, string_array_type); - DECL_CHAIN (field) = fields; - fields = field; + substr_begin = substr_end; + } while (*substr_begin); - finish_builtin_struct (type, "__gcov_module_info", fields, NULL_TREE); + return ret; +} - return type; +/* Append TAG to string STRINGS. */ +static inline void +lipo_append_tag (char *strings, char tag) +{ + int i; + + strcat (strings, DELIMITER); + i = strlen (strings); + strings[i] = tag; + strings[i + 1] = 0; } /* Returns the value of the module info associated with the @@ -2092,12 +2163,17 @@ build_gcov_module_info_value (tree mod_type) tree info_fields, mod_info; tree value = NULL_TREE; int file_name_len; - tree filename_string, string_array_type, string_type; + tree filename_string, string_type, saved_string; cpp_dir *quote_paths, *bracket_paths, *system_paths, *pdir; - int num_quote_paths = 0, num_bracket_paths = 0, num_system_paths = 0; + int num_quote_paths = 0, num_bracket_paths = 0, num_system_paths = 0, i; unsigned lang; char name_buf[50]; - vec *v = NULL, *path_v = NULL; + vec *v = NULL; + unsigned string_len; + char *compressed_strings; + unsigned long dest_len, src_len, total_length, ui; + struct str_list *head; + char *strings; info_fields = TYPE_FIELDS (mod_type); @@ -2181,57 +2257,127 @@ build_gcov_module_info_value (tree mod_type) for (pdir = system_paths; pdir; pdir = pdir->next) num_system_paths++; - /* Num quote paths */ - CONSTRUCTOR_APPEND_ELT (v, info_fields, - build_int_cstu (get_gcov_unsigned_t (), - num_quote_paths)); - info_fields = DECL_CHAIN (info_fields); + total_length = 1; /* space for \0. */ + /* quote paths */ + total_length += strlen (DELIMITER) + 1; /* 1 for tag flag. */ + for (i = 0, pdir = quote_paths; i < num_quote_paths; i++) + { + total_length += strlen (pdir->name) + 1; + pdir = pdir->next; + } - /* Num bracket paths */ - CONSTRUCTOR_APPEND_ELT (v, info_fields, - build_int_cstu (get_gcov_unsigned_t (), - num_bracket_paths)); - info_fields = DECL_CHAIN (info_fields); + /* bracket paths */ + total_length += strlen (DELIMITER) + 1; /* 1 for tag flag. */ + for (i = 0, pdir = bracket_paths; i < num_bracket_paths; i++) + { + total_length += strlen (pdir->name) + 1; + pdir = pdir->next; + } - /* Num system paths */ - CONSTRUCTOR_APPEND_ELT (v, info_fields, - build_int_cstu (get_gcov_unsigned_t (), - num_system_paths)); - info_fields = DECL_CHAIN (info_fields); + /* system paths */ + total_length += strlen (DELIMITER) + 1; /* 1 for tag flag. */ + for (i = 0, pdir = system_paths; i < num_system_paths; i++) + { + total_length += strlen (pdir->name) + 1; + pdir = pdir->next; + } - /* Num -D/-U options. */ - CONSTRUCTOR_APPEND_ELT (v, info_fields, - build_int_cstu (get_gcov_unsigned_t (), - num_cpp_defines)); - info_fields = DECL_CHAIN (info_fields); + /* -D/-U options */ + total_length += strlen (DELIMITER) + 1; /* 1 for tag flag. */ + head = cpp_defines_head; + while (head) + { + total_length += strlen (head->str) + 1; + head = head->next; + } - /* Num -imacro/-include options. */ - CONSTRUCTOR_APPEND_ELT (v, info_fields, - build_int_cstu (get_gcov_unsigned_t (), - num_cpp_includes)); - info_fields = DECL_CHAIN (info_fields); + /* -imacro/-include options */ + total_length += strlen (DELIMITER) + 1; /* 1 for tag flag. */ + head = cpp_includes_head; + while (head) + { + total_length += strlen (head->str) + 1; + head = head->next; + } - /* Num command-line args. */ + /* Num command-line args */ + total_length += strlen (DELIMITER) + 1; /* 1 for tag flag. */ + for (ui = 0; ui < num_lipo_cl_args; ui++) + total_length += strlen (lipo_cl_args[ui]) + 1; + + strings = (char*) xmalloc (total_length); + *strings = 0; + + lipo_append_tag (strings, QUOTE_PATH_FLAG); + for (i = 0, pdir = quote_paths; i < num_quote_paths; i++) + { + strcat(strings, pdir->name); + strcat(strings, DELIMITER2); + pdir = pdir->next; + } + + lipo_append_tag (strings, BRACKET_PATH_FLAG); + for (i = 0, pdir = bracket_paths; i < num_bracket_paths; i++) + { + strcat(strings, pdir->name); + strcat(strings, DELIMITER2); + pdir = pdir->next; + } + + lipo_append_tag (strings, SYSTEM_PATH_FLAG); + for (i = 0, pdir = system_paths; i < num_system_paths; i++) + { + strcat(strings, pdir->name); + strcat(strings, DELIMITER2); + pdir = pdir->next; + } + + lipo_append_tag (strings, D_U_OPTION_FLAG); + head = cpp_defines_head; + while (head) + { + strcat(strings, head->str); + strcat(strings, DELIMITER2); + head = head->next; + } + + lipo_append_tag (strings, INCLUDE_OPTION_FLAG); + head = cpp_includes_head; + while (head) + { + strcat(strings, head->str); + strcat(strings, DELIMITER2); + head = head->next; + } + + lipo_append_tag (strings, COMMAND_ARG_FLAG); + for (ui = 0; ui < num_lipo_cl_args; ui++) + { + strcat(strings, lipo_cl_args[ui]); + strcat(strings, DELIMITER2); + } + string_len = strlen (strings) + 1; + compressed_strings = (char*) xmalloc (string_len); + dest_len = string_len; + src_len = string_len; + compress ((Bytef *)compressed_strings, &dest_len, (const Bytef *)strings, src_len); + + gcc_assert (dest_len < 0xFFFF); + gcc_assert (src_len < 0xFFFF); + /* combined_strlen field */ CONSTRUCTOR_APPEND_ELT (v, info_fields, build_int_cstu (get_gcov_unsigned_t (), - num_lipo_cl_args)); + (src_len << 16 | dest_len))); info_fields = DECL_CHAIN (info_fields); - /* string array */ - string_array_type = TREE_TYPE (info_fields); - build_inc_path_array_value (string_type, &path_v, - quote_paths, num_quote_paths); - build_inc_path_array_value (string_type, &path_v, - bracket_paths, num_bracket_paths); - build_inc_path_array_value (string_type, &path_v, - system_paths, num_system_paths); - build_str_array_value (string_type, &path_v, - cpp_defines_head); - build_str_array_value (string_type, &path_v, - cpp_includes_head); - build_cl_args_array_value (string_type, &path_v); + strings = compressed_strings; + string_len = dest_len; + saved_string = build_string (string_len, strings); + TREE_TYPE (saved_string) = build_array_type + (char_type_node, build_index_type + (build_int_cst (NULL_TREE, string_len))); CONSTRUCTOR_APPEND_ELT (v, info_fields, - build_constructor (string_array_type, path_v)); + build1 (ADDR_EXPR, string_type, saved_string)); info_fields = DECL_CHAIN (info_fields); gcc_assert (!info_fields); @@ -2523,7 +2669,7 @@ coverage_obj_init (void) gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE); gcov_fn_info_ptr_type = build_pointer_type (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST)); - build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type); + build_fn_info_type (gcov_fn_info_type, n_counters); build_info_type (gcov_info_type, gcov_fn_info_ptr_type); /* Build the gcov info var, this is referred to in its own @@ -2703,8 +2849,6 @@ add_module_info (unsigned module_id, bool is_prima cur_info = module_infos[index]; cur_info->ident = module_id; SET_MODULE_EXPORTED (cur_info); - cur_info->num_quote_paths = 0; - cur_info->num_bracket_paths = 0; cur_info->da_filename = NULL; cur_info->source_filename = NULL; if (is_primary) @@ -2748,21 +2892,20 @@ process_include (char **orig_inc_path, char* old_s -fripa-inc-path-sub=OLD_SUB:NEW_SUB */ static void -process_include_paths_1 (struct gcov_module_info *mod_info, +process_include_paths_1 (struct lipo_parsed_cc1_string *mod_info_str, char* old_sub, char *new_sub) { - unsigned i, j; + unsigned i; + enum lipo_cc1_string_kind k; - for (i = 0; i < mod_info->num_quote_paths; i++) - process_include (&mod_info->string_array[i], old_sub, new_sub); + for (i = 0, k = k_quote_paths; i < mod_info_str->num[k]; i++) + process_include (&mod_info_str->strings[k][i], old_sub, new_sub); - for (i = 0, j = mod_info->num_quote_paths; - i < mod_info->num_bracket_paths; i++, j++) - process_include (&mod_info->string_array[j], old_sub, new_sub); + for (i = 0, k = k_bracket_paths; i < mod_info_str->num[k]; i++) + process_include (&mod_info_str->strings[k][i], old_sub, new_sub); - for (i = 0, j = mod_info->num_quote_paths + mod_info->num_bracket_paths + - mod_info->num_cpp_defines; i < mod_info->num_cpp_includes; i++, j++) - process_include (&mod_info->string_array[j], old_sub, new_sub); + for (i = 0, k = k_cpp_includes; i < mod_info_str->num[k]; i++) + process_include (&mod_info_str->strings[k][i], old_sub, new_sub); } @@ -2770,7 +2913,7 @@ static void -fripa-inc-path-sub=old_sub1:new_sub1[,old_sub2:new_sub2] */ static void -process_include_paths (struct gcov_module_info *mod_info) +process_include_paths (struct lipo_parsed_cc1_string *mod_info_str) { char *sub_pattern, *cur, *next, *new_sub; @@ -2793,7 +2936,7 @@ static void return; } *new_sub++ = '\0'; - process_include_paths_1 (mod_info, cur, new_sub); + process_include_paths_1 (mod_info_str, cur, new_sub); cur = next; } while (cur); free (sub_pattern); @@ -2818,34 +2961,36 @@ set_lipo_c_parsing_context (struct cpp_reader *par if (current_module_id != primary_module_id) { - unsigned i, j; + unsigned i; + enum lipo_cc1_string_kind k; + struct lipo_parsed_cc1_string *mod_info_str = + lipo_parse_saved_cc1_string (mod_info->source_filename, + mod_info->saved_cc1_strings, false); - process_include_paths (mod_info); + process_include_paths (mod_info_str); /* Setup include paths. */ clear_include_chains (); - for (i = 0; i < mod_info->num_quote_paths; i++) - add_path (xstrdup (mod_info->string_array[i]), - QUOTE, 0, 1); - for (i = 0, j = mod_info->num_quote_paths; - i < mod_info->num_bracket_paths; i++, j++) - add_path (xstrdup (mod_info->string_array[j]), - BRACKET, 0, 1); - for (i = 0; i < mod_info->num_system_paths; i++, j++) - add_path (xstrdup (mod_info->string_array[j]), - SYSTEM, 0, 1); - register_include_chains (parse_in, NULL, NULL, NULL, - 0, 0, verbose); + for (i = 0, k = k_quote_paths; i < mod_info_str->num[k]; i++) + add_path (xstrdup (mod_info_str->strings[k][i]), QUOTE, 0, 1); + for (i = 0, k = k_bracket_paths; i < mod_info_str->num[k]; i++) + add_path (xstrdup (mod_info_str->strings[k][i]), BRACKET, 0, 1); + for (i = 0, k = k_system_paths; i < mod_info_str->num[k]; i++) + add_path (xstrdup (mod_info_str->strings[k][i]), SYSTEM, 0, 1); + register_include_chains (parse_in, NULL, NULL, NULL, 0, 0, verbose); /* Setup defines/undefs. */ - for (i = 0; i < mod_info->num_cpp_defines; i++, j++) - if (mod_info->string_array[j][0] == 'D') - cpp_define (parse_in, mod_info->string_array[j] + 1); - else - cpp_undef (parse_in, mod_info->string_array[j] + 1); + for (i = 0, k = k_cpp_defines; i < mod_info_str->num[k]; i++) + if (mod_info_str->strings[k][i][0] == 'D') + cpp_define (parse_in, mod_info_str->strings[k][i] + 1); + else + cpp_undef (parse_in, mod_info_str->strings[k][i] + 1); /* Setup -imacro/-include. */ - for (i = 0; i < mod_info->num_cpp_includes; i++, j++) - cpp_push_include (parse_in, mod_info->string_array[j]); + for (i = 0, k = k_cpp_includes; i < mod_info_str->num[k]; i++) + cpp_push_include (parse_in, mod_info_str->strings[k][i]); + + /* free mode_info_str */ + free_parsed_string (mod_info_str); } } Index: gcc/coverage.h =================================================================== --- gcc/coverage.h (revision 228354) +++ gcc/coverage.h (working copy) @@ -86,8 +86,12 @@ extern tree get_const_string_type (void); /* Mark this module as containing asm statements. */ extern void coverage_has_asm_stmt (void); -extern bool incompatible_cl_args (struct gcov_module_info *, - struct gcov_module_info *); +struct lipo_parsed_cc1_string; +struct lipo_parsed_cc1_string * lipo_parse_saved_cc1_string (const char *src, + char *str, bool parse_cl_args_only); +void free_parsed_string (struct lipo_parsed_cc1_string *string); +extern bool incompatible_cl_args (struct lipo_parsed_cc1_string *, + struct lipo_parsed_cc1_string *); /* Defined in tree-profile.c. */ extern void tree_init_instrumentation_sampling (void); Index: gcc/gcov-io.c =================================================================== --- gcc/gcov-io.c (revision 228354) +++ gcc/gcov-io.c (working copy) @@ -803,23 +803,22 @@ gcov_read_build_info (gcov_unsigned_t length, gcov #if (!IN_LIBGCOV && IN_GCOV != 1) || defined (IN_GCOV_TOOL) /* Read LEN words (unsigned type) and construct MOD_INFO. */ +#include "zlib.h" + GCOV_LINKAGE void gcov_read_module_info (struct gcov_module_info *mod_info, gcov_unsigned_t len) { - gcov_unsigned_t src_filename_len, filename_len, i, num_strings; + gcov_unsigned_t src_filename_len, filename_len, i; + char *compressed_array, *uncompressed_array; + gcov_unsigned_t tag_len; + unsigned long saved_compressed_len, saved_uncompressed_len, result_len; mod_info->ident = gcov_read_unsigned (); mod_info->is_primary = gcov_read_unsigned (); mod_info->flags = gcov_read_unsigned (); mod_info->lang = gcov_read_unsigned (); mod_info->ggc_memory = gcov_read_unsigned (); - mod_info->num_quote_paths = gcov_read_unsigned (); - mod_info->num_bracket_paths = gcov_read_unsigned (); - mod_info->num_system_paths = gcov_read_unsigned (); - mod_info->num_cpp_defines = gcov_read_unsigned (); - mod_info->num_cpp_includes = gcov_read_unsigned (); - mod_info->num_cl_args = gcov_read_unsigned (); - len -= 11; + len -= 5; filename_len = gcov_read_unsigned (); mod_info->da_filename = (char *) xmalloc (filename_len * @@ -830,17 +829,28 @@ gcov_read_module_info (struct gcov_module_info *mo src_filename_len = gcov_read_unsigned (); mod_info->source_filename = (char *) xmalloc (src_filename_len * - sizeof (gcov_unsigned_t)); + sizeof (gcov_unsigned_t)); for (i = 0; i < src_filename_len; i++) ((gcov_unsigned_t *) mod_info->source_filename)[i] = gcov_read_unsigned (); len -= (src_filename_len + 1); - num_strings = mod_info->num_quote_paths + mod_info->num_bracket_paths - + mod_info->num_system_paths - + mod_info->num_cpp_defines + mod_info->num_cpp_includes - + mod_info->num_cl_args; - len -= gcov_read_string_array (mod_info->string_array, num_strings); + saved_compressed_len = (unsigned long) gcov_read_unsigned (); + saved_uncompressed_len = saved_compressed_len >> 16; + saved_compressed_len &= 0xFFFF; + tag_len = gcov_read_unsigned (); + len -= (tag_len + 2); gcc_assert (!len); + compressed_array = (char *) xmalloc (tag_len * sizeof (gcov_unsigned_t)); + uncompressed_array = (char *) xmalloc (saved_uncompressed_len); + for (i = 0; i < tag_len; i++) + ((gcov_unsigned_t *) compressed_array)[i] = gcov_read_unsigned (); + + result_len = saved_uncompressed_len; + uncompress ((Bytef *)uncompressed_array, &result_len, + (const Bytef *)compressed_array, saved_compressed_len); + gcc_assert (result_len == saved_uncompressed_len); + mod_info->saved_cc1_strings = uncompressed_array; + free (compressed_array); } #endif Index: gcc/gcov-io.h =================================================================== --- gcc/gcov-io.h (revision 228354) +++ gcc/gcov-io.h (working copy) @@ -402,6 +402,35 @@ struct gcov_summary #define GCOV_MODULE_ASM_STMTS (1 << 16) #define GCOV_MODULE_LANG_MASK 0xffff +/* The following defines are for the saved_cc1_strings encoding. */ + +#define DELIMITER "[" +#define DELIMITER2 "]" +#define QUOTE_PATH_FLAG 'Q' +#define BRACKET_PATH_FLAG 'B' +#define SYSTEM_PATH_FLAG 'S' +#define D_U_OPTION_FLAG 'D' +#define INCLUDE_OPTION_FLAG 'I' +#define COMMAND_ARG_FLAG 'C' + +/* Define various kind of option for saved_cc1_strings. */ +enum lipo_cc1_string_kind { + k_quote_paths = 0, + k_bracket_paths, + k_system_paths, + k_cpp_defines, + k_cpp_includes, + k_lipo_cl_args, + num_lipo_cc1_string_kind +}; + +/* The struct for parsed (decoding) string for saved_cc1_strings. */ +struct lipo_parsed_cc1_string { + const char* source_filename; + unsigned num[num_lipo_cc1_string_kind]; + char **strings[num_lipo_cc1_string_kind]; +}; + /* Source module info. The data structure is used in both runtime and profile-use phase. Make sure to allocate enough space for the variable length member. */ @@ -421,13 +450,18 @@ struct gcov_module_info gcov_unsigned_t ggc_memory; /* memory needed for parsing in kb */ char *da_filename; char *source_filename; - gcov_unsigned_t num_quote_paths; - gcov_unsigned_t num_bracket_paths; - gcov_unsigned_t num_system_paths; - gcov_unsigned_t num_cpp_defines; - gcov_unsigned_t num_cpp_includes; - gcov_unsigned_t num_cl_args; - char *string_array[1]; + /* we encode and compress various cc1 options to one string + to SAVED_CC1_STRINGS field. + For the encoding, all the string options are separated by ']'. + (as the original string can contain ' '. Quoted_paths start with + "[[Q". Bracket_paths start with "[[B". System_paths start with + "[[S". Cpp_defines start with "[[D". Cpp_includes start with + "[[I". Command line arguments (cl_args) start with "[[C". + COMBINED_STRLEN contains the compressed size and the original + (uncompressed) string length. Bit[0..15] is the compressed size and + bit [16,31] is the uncompressed string length. */ + gcov_unsigned_t combined_strlen; + char *saved_cc1_strings; }; extern struct gcov_module_info **module_infos; Index: libgcc/dyn-ipa.c =================================================================== --- libgcc/dyn-ipa.c (revision 228272) +++ libgcc/dyn-ipa.c (working copy) @@ -2257,67 +2257,6 @@ gcov_compute_random_module_groups (unsigned max_gr } } -#if 0 -/* Write out MOD_INFO into the gcda file. IS_PRIMARY is a flag - indicating if the module is the primary module in the group. */ - -static void -gcov_write_module_info (const struct gcov_info *mod_info, - unsigned is_primary) -{ - gcov_unsigned_t len = 0, filename_len = 0, src_filename_len = 0, i; - gcov_unsigned_t num_strings; - gcov_unsigned_t *aligned_fname; - struct gcov_module_info *module_info = mod_info->mod_info; - filename_len = (strlen (module_info->da_filename) + - sizeof (gcov_unsigned_t)) / sizeof (gcov_unsigned_t); - src_filename_len = (strlen (module_info->source_filename) + - sizeof (gcov_unsigned_t)) / sizeof (gcov_unsigned_t); - len = filename_len + src_filename_len; - len += 2; /* each name string is led by a length. */ - - num_strings = module_info->num_quote_paths + module_info->num_bracket_paths - + module_info->num_system_paths - + module_info->num_cpp_defines + module_info->num_cpp_includes - + module_info->num_cl_args; - len += gcov_compute_string_array_len (module_info->string_array, - num_strings); - - len += 11; /* 11 more fields */ - - gcov_write_tag_length (GCOV_TAG_MODULE_INFO, len); - gcov_write_unsigned (module_info->ident); - gcov_write_unsigned (is_primary); - if (flag_alg_mode == INCLUSION_BASED_PRIORITY_ALGORITHM && is_primary) - SET_MODULE_INCLUDE_ALL_AUX (module_info); - gcov_write_unsigned (module_info->flags); - gcov_write_unsigned (module_info->lang); - gcov_write_unsigned (module_info->ggc_memory); - gcov_write_unsigned (module_info->num_quote_paths); - gcov_write_unsigned (module_info->num_bracket_paths); - gcov_write_unsigned (module_info->num_system_paths); - gcov_write_unsigned (module_info->num_cpp_defines); - gcov_write_unsigned (module_info->num_cpp_includes); - gcov_write_unsigned (module_info->num_cl_args); - - /* Now write the filenames */ - aligned_fname = (gcov_unsigned_t *) alloca ((filename_len + src_filename_len + 2) * - sizeof (gcov_unsigned_t)); - memset (aligned_fname, 0, - (filename_len + src_filename_len + 2) * sizeof (gcov_unsigned_t)); - aligned_fname[0] = filename_len; - strcpy ((char*) (aligned_fname + 1), module_info->da_filename); - aligned_fname[filename_len + 1] = src_filename_len; - strcpy ((char*) (aligned_fname + filename_len + 2), module_info->source_filename); - - for (i = 0; i < (filename_len + src_filename_len + 2); i++) - gcov_write_unsigned (aligned_fname[i]); - - /* Now write the string array. */ - gcov_write_string_array (module_info->string_array, num_strings); -} -#endif - /* Write out MOD_INFO and its imported modules into gcda file. */ void @@ -2880,21 +2819,6 @@ static gcov_dyn_ipa_merge_fn ctr_merge_functions[G }; #undef DEF_GCOV_COUNTER -#if 0 -static gcov_dyn_ipa_merge_fn ctr_merge_functions[GCOV_COUNTERS] = { - __gcov_dyn_ipa_merge_add, - __gcov_dyn_ipa_merge_add, - __gcov_dyn_ipa_merge_add, - __gcov_dyn_ipa_merge_single, - __gcov_dyn_ipa_merge_delta, - __gcov_dyn_ipa_merge_single, - __gcov_dyn_ipa_merge_add, - __gcov_dyn_ipa_merge_ior, - __gcov_dyn_ipa_merge_icall_topn, - __gcov_dyn_ipa_merge_dc, -}; -#endif - /* Copy counters from SRC_CTRS array to DEST_CTRS array, where SRC_CTRS is indexed by the GCOV_COUNTER type, and DEST_CTRS is an array holding only the mergable counters to emit to the gcda file for DEST_GUID. */ Index: libgcc/libgcov-driver.c =================================================================== --- libgcc/libgcov-driver.c (revision 228272) +++ libgcc/libgcov-driver.c (working copy) @@ -1494,8 +1494,8 @@ gcov_write_module_info (const struct gcov_info *mo unsigned is_primary) { gcov_unsigned_t len = 0, filename_len = 0, src_filename_len = 0, i; - gcov_unsigned_t num_strings; - gcov_unsigned_t *aligned_fname; + gcov_unsigned_t num_strings, cc1_strlen; + gcov_unsigned_t *aligned_fname, *aligned_string, saved_cc1_strings_len; struct gcov_module_info *module_info = mod_info->mod_info; filename_len = (strlen (module_info->da_filename) + sizeof (gcov_unsigned_t)) / sizeof (gcov_unsigned_t); @@ -1504,14 +1504,12 @@ gcov_write_module_info (const struct gcov_info *mo len = filename_len + src_filename_len; len += 2; /* each name string is led by a length. */ - num_strings = module_info->num_quote_paths + module_info->num_bracket_paths - + module_info->num_system_paths - + module_info->num_cpp_defines + module_info->num_cpp_includes - + module_info->num_cl_args; - len += gcov_compute_string_array_len (module_info->string_array, - num_strings); + cc1_strlen = module_info->combined_strlen & 0xFFFF; + saved_cc1_strings_len = (cc1_strlen + sizeof (gcov_unsigned_t)) + / sizeof (gcov_unsigned_t); + len += saved_cc1_strings_len + 1; /* prepend the length. */ - len += 11; /* 11 more fields */ + len += 6; /* 6 more fields */ gcov_write_tag_length (GCOV_TAG_MODULE_INFO, len); gcov_write_unsigned (module_info->ident); @@ -1519,12 +1517,6 @@ gcov_write_module_info (const struct gcov_info *mo gcov_write_unsigned (module_info->flags); gcov_write_unsigned (module_info->lang); gcov_write_unsigned (module_info->ggc_memory); - gcov_write_unsigned (module_info->num_quote_paths); - gcov_write_unsigned (module_info->num_bracket_paths); - gcov_write_unsigned (module_info->num_system_paths); - gcov_write_unsigned (module_info->num_cpp_defines); - gcov_write_unsigned (module_info->num_cpp_includes); - gcov_write_unsigned (module_info->num_cl_args); /* Now write the filenames */ aligned_fname = (gcov_unsigned_t *) alloca ((filename_len + src_filename_len + 2) * @@ -1539,8 +1531,15 @@ gcov_write_module_info (const struct gcov_info *mo for (i = 0; i < (filename_len + src_filename_len + 2); i++) gcov_write_unsigned (aligned_fname[i]); - /* Now write the string array. */ - gcov_write_string_array (module_info->string_array, num_strings); + gcov_write_unsigned (module_info->combined_strlen); + /* Now write the saved cc1 strings. */ + aligned_string = (gcov_unsigned_t *) alloca ((saved_cc1_strings_len + 1) * + sizeof (gcov_unsigned_t)); + memset (aligned_string, 0, (saved_cc1_strings_len + 1) * sizeof (gcov_unsigned_t)); + aligned_string[0] = saved_cc1_strings_len; + memcpy (aligned_string + 1, module_info->saved_cc1_strings, cc1_strlen); + for (i = 0; i < saved_cc1_strings_len + 1; i++) + gcov_write_unsigned (aligned_string[i]); } #endif /* L_gcov */