From patchwork Mon Oct 17 21:45:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 683436 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 3syWwW1yqFz9s2Q for ; Tue, 18 Oct 2016 08:45: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=BI/Q+7AZ; 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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=PZ6y7LwGFkeuUjbKyC2oTM11q3LmV e+vBkDml9bnCN1MVzqfzOv0kXQXawzFJ/2pu1l5wpsmq24wbInAn9ruvcUeN0f74 WNBLdS+CVtD+7300T7PnsGQqzul1puCa1tHaMVoppTE0DdrBAIal7XxLtTs6YmeR 3MPU6bFVmN4//c= 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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=dBIDa+Mvz3K/FwnbDNvALwtdUQk=; b=BI/ Q+7AZdlHf9xoX5oEN/0fqLukpDt6wqvHSSkFfR6NETbORvhp44rxr5d4a5v2LpgW 5/U45vtXht0kTZPtOlyvyCdfOD7DjqyuXTLCgNOXcqrVed3D0BQiSyUbRJEI9J9o IrBFDb1v6mxDHNwLfqKRdNDnkosVv0CA1fqH2gh8= Received: (qmail 93791 invoked by alias); 17 Oct 2016 21:45:32 -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 92053 invoked by uid 89); 17 Oct 2016 21:45:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=BAYES_05, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=abbreviation, 198, 7, 153, 7, increments X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Oct 2016 21:45:08 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C388B8E3E3; Mon, 17 Oct 2016 21:45:06 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-44.ams2.redhat.com [10.36.116.44]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u9HLj4Bv028674 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 17 Oct 2016 17:45:06 -0400 Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id u9HLj2BY011330; Mon, 17 Oct 2016 23:45:02 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id u9HLj0tH011329; Mon, 17 Oct 2016 23:45:00 +0200 Date: Mon, 17 Oct 2016 23:45:00 +0200 From: Jakub Jelinek To: Jason Merrill , Cary Coutant Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] DWARF5 DW_FORM_implicit_const support Message-ID: <20161017214500.GE7282@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-IsSubscribed: yes Hi! This patch starts using DW_FORM_implicit_const (new in DWARF5), though only for cases where the constants are the same among all DIEs with the same abbreviation (and only for abbrevs used only in the main compilation unit, because right now we don't give all DIEs abbreviations first before outputing anything. I think more precise optimizations could be left to DWZ (when it sees the whole binary or library, it can better simulate different decisions like using two different abbreviations for different subsets of DIEs which have the same attributes and forms, but differ in some const values, etc. The patch also switches the abbrev table from GC registered array with used and allocated integers to normal va_gc vector. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-10-17 Jakub Jelinek * dwarf2out.h (enum dw_val_class): Add dw_val_class_const_implicit, dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit. (struct dw_val_node): Add val_file_implicit field. * dwarf2out.c (dw_val_equal_p, print_dw_val, attr_checksum, attr_checksum_ordered, same_dw_val_p, size_of_die, value_format, output_die): Handle dw_val_class_const_implicit, dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit. (abbrev_die_table): Change into va_gc vec. (abbrev_die_table_allocated, abbrev_die_table_in_use, ABBREV_DIE_TABLE_INCREMENT): Remove. (AT_int, AT_unsigned, AT_file): Allow dw_val_class_*_implicit. (abbrev_opt_start, abbrev_usage_count, abbrev_dies): New variables. (build_abbrev_table): Adjust for abbrev_die_table being a va_gc vec. If abbrev_opt_start, fill in abbrev_usage_count and abbrev_dies vectors. (die_abbrev_cmp, optimize_implicit_const, optimize_abbrev_table): New functions. (output_die_abbrevs): For DW_FORM_implicit_const emit sleb128 with the implicit value. (output_abbrev_section): Adjust for abbrev_die_table being a va_gc vec. (output_comp_unit): Initialize abbrev_opt_start if emitting the main unit. Call optimize_abbrev_table. (dwarf2out_init, dwarf2out_finish, dwarf2out_c_finalize): Adjust for abbrev_die_table being a va_gc vec. Jakub --- gcc/dwarf2out.h.jj 2016-04-28 17:26:05.000000000 +0200 +++ gcc/dwarf2out.h 2016-10-17 19:07:45.425312870 +0200 @@ -153,7 +153,10 @@ enum dw_val_class dw_val_class_vms_delta, dw_val_class_high_pc, dw_val_class_discr_value, - dw_val_class_discr_list + dw_val_class_discr_list, + dw_val_class_const_implicit, + dw_val_class_unsigned_const_implicit, + dw_val_class_file_implicit }; /* Describe a floating point constant value, or a vector constant value. */ @@ -198,7 +201,8 @@ struct GTY(()) dw_val_node { dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list; dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc; HOST_WIDE_INT GTY ((default)) val_int; - unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned; + unsigned HOST_WIDE_INT + GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned; double_int GTY ((tag ("dw_val_class_const_double"))) val_double; wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide; dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec; @@ -212,6 +216,8 @@ struct GTY(()) dw_val_node { char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id; unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag; struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file; + struct dwarf_file_data * + GTY ((tag ("dw_val_class_file_implicit"))) val_file_implicit; unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8]; tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref; struct dw_val_vms_delta_union --- gcc/dwarf2out.c.jj 2016-10-17 14:46:46.000000000 +0200 +++ gcc/dwarf2out.c 2016-10-17 19:17:54.350626382 +0200 @@ -1363,6 +1363,8 @@ dw_val_equal_p (dw_val_node *a, dw_val_n case dw_val_class_offset: case dw_val_class_unsigned_const: case dw_val_class_const: + case dw_val_class_unsigned_const_implicit: + case dw_val_class_const_implicit: case dw_val_class_range_list: case dw_val_class_lineptr: case dw_val_class_macptr: @@ -1385,6 +1387,7 @@ dw_val_equal_p (dw_val_node *a, dw_val_n case dw_val_class_flag: return a->v.val_flag == b->v.val_flag; case dw_val_class_file: + case dw_val_class_file_implicit: return a->v.val_file == b->v.val_file; case dw_val_class_decl_ref: return a->v.val_decl_ref == b->v.val_decl_ref; @@ -3006,17 +3009,9 @@ struct dw_loc_list_hasher : ggc_ptr_hash /* Table of cached location lists. */ static GTY (()) hash_table *cached_dw_loc_list_table; -/* A pointer to the base of a list of references to DIE's that - are uniquely identified by their tag, presence/absence of - children DIE's, and list of attribute/value pairs. */ -static GTY((length ("abbrev_die_table_allocated"))) - dw_die_ref *abbrev_die_table; - -/* Number of elements currently allocated for abbrev_die_table. */ -static GTY(()) unsigned abbrev_die_table_allocated; - -/* Number of elements in abbrev_die_table currently in use. */ -static GTY(()) unsigned abbrev_die_table_in_use; +/* A vector of references to DIE's that are uniquely identified by their tag, + presence/absence of children DIE's, and list of attribute/value pairs. */ +static GTY(()) vec *abbrev_die_table; /* A hash map to remember the stack usage for DWARF procedures. The value stored is the stack size difference between before the DWARF procedure @@ -3024,10 +3019,6 @@ static GTY(()) unsigned abbrev_die_table that consumes N stack slots and that pushes M ones, this stores M - N. */ static hash_map *dwarf_proc_stack_usage_map; -/* Size (in elements) of increments by which we may expand the - abbrev_die_table. */ -#define ABBREV_DIE_TABLE_INCREMENT 256 - /* A global counter for generating labels for line number data. */ static unsigned int line_info_label_num; @@ -3922,7 +3913,8 @@ add_AT_int (dw_die_ref die, enum dwarf_a static inline HOST_WIDE_INT AT_int (dw_attr_node *a) { - gcc_assert (a && AT_class (a) == dw_val_class_const); + gcc_assert (a && (AT_class (a) == dw_val_class_const + || AT_class (a) == dw_val_class_const_implicit)); return a->dw_attr_val.v.val_int; } @@ -3944,7 +3936,8 @@ add_AT_unsigned (dw_die_ref die, enum dw static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *a) { - gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const); + gcc_assert (a && (AT_class (a) == dw_val_class_unsigned_const + || AT_class (a) == dw_val_class_unsigned_const_implicit)); return a->dw_attr_val.v.val_unsigned; } @@ -4523,7 +4516,8 @@ add_AT_file (dw_die_ref die, enum dwarf_ static inline struct dwarf_file_data * AT_file (dw_attr_node *a) { - gcc_assert (a && AT_class (a) == dw_val_class_file); + gcc_assert (a && (AT_class (a) == dw_val_class_file + || AT_class (a) == dw_val_class_file_implicit)); return a->dw_attr_val.v.val_file; } @@ -5598,9 +5592,11 @@ print_dw_val (dw_val_node *val, bool rec fprintf (outfile, "range list"); break; case dw_val_class_const: + case dw_val_class_const_implicit: fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int); break; case dw_val_class_unsigned_const: + case dw_val_class_unsigned_const_implicit: fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned); break; case dw_val_class_const_double: @@ -5667,6 +5663,7 @@ print_dw_val (dw_val_node *val, bool rec fprintf (outfile, ""); break; case dw_val_class_file: + case dw_val_class_file_implicit: fprintf (outfile, "\"%s\" (%d)", val->v.val_file->filename, val->v.val_file->emitted_number); break; @@ -5996,9 +5993,11 @@ attr_checksum (dw_attr_node *at, struct switch (AT_class (at)) { case dw_val_class_const: + case dw_val_class_const_implicit: CHECKSUM (at->dw_attr_val.v.val_int); break; case dw_val_class_unsigned_const: + case dw_val_class_unsigned_const_implicit: CHECKSUM (at->dw_attr_val.v.val_unsigned); break; case dw_val_class_const_double: @@ -6049,6 +6048,7 @@ attr_checksum (dw_attr_node *at, struct break; case dw_val_class_file: + case dw_val_class_file_implicit: CHECKSUM_STRING (AT_file (at)->filename); break; @@ -6273,11 +6273,13 @@ attr_checksum_ordered (enum dwarf_tag ta switch (AT_class (at)) { case dw_val_class_const: + case dw_val_class_const_implicit: CHECKSUM_ULEB128 (DW_FORM_sdata); CHECKSUM_SLEB128 (at->dw_attr_val.v.val_int); break; case dw_val_class_unsigned_const: + case dw_val_class_unsigned_const_implicit: CHECKSUM_ULEB128 (DW_FORM_sdata); CHECKSUM_SLEB128 ((int) at->dw_attr_val.v.val_unsigned); break; @@ -6341,6 +6343,7 @@ attr_checksum_ordered (enum dwarf_tag ta break; case dw_val_class_file: + case dw_val_class_file_implicit: CHECKSUM_ULEB128 (DW_FORM_string); CHECKSUM_STRING (AT_file (at)->filename); break; @@ -6783,8 +6786,10 @@ same_dw_val_p (const dw_val_node *v1, co switch (v1->val_class) { case dw_val_class_const: + case dw_val_class_const_implicit: return v1->v.val_int == v2->v.val_int; case dw_val_class_unsigned_const: + case dw_val_class_unsigned_const_implicit: return v1->v.val_unsigned == v2->v.val_unsigned; case dw_val_class_const_double: return v1->v.val_double.high == v2->v.val_double.high @@ -6834,6 +6839,7 @@ same_dw_val_p (const dw_val_node *v1, co return 1; case dw_val_class_file: + case dw_val_class_file_implicit: return v1->v.val_file == v2->v.val_file; case dw_val_class_data8: @@ -8269,6 +8275,16 @@ optimize_external_refs (dw_die_ref die) return map; } +/* First abbrev_id that can be optimized based on usage. */ +static unsigned int abbrev_opt_start; + +/* Vector of usage counts during build_abbrev_table. Indexed by + abbrev_id - abbrev_opt_start. */ +static vec abbrev_usage_count; + +/* Vector of all DIEs added with die_abbrev >= abbrev_opt_start. */ +static vec abbrev_dies; + /* The format of each DIE (and its attribute value pairs) is encoded in an abbreviation table. This routine builds the abbreviation table and assigns a unique abbreviation id for each abbreviation entry. The children of each @@ -8277,11 +8293,11 @@ optimize_external_refs (dw_die_ref die) static void build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map) { - unsigned long abbrev_id; - unsigned int n_alloc; + unsigned int abbrev_id = 0; dw_die_ref c; dw_attr_node *a; unsigned ix; + dw_die_ref abbrev; /* Scan the DIE references, and replace any that refer to DIEs from other CUs (i.e. those which are not marked) with @@ -8301,13 +8317,14 @@ build_abbrev_table (dw_die_ref die, exte set_AT_ref_external (a, 1); } - for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) + FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev) { - dw_die_ref abbrev = abbrev_die_table[abbrev_id]; dw_attr_node *die_a, *abbrev_a; unsigned ix; bool ok = true; + if (abbrev_id == 0) + continue; if (abbrev->die_tag != die->die_tag) continue; if ((abbrev->die_child != NULL) != (die->die_child != NULL)) @@ -8330,26 +8347,178 @@ build_abbrev_table (dw_die_ref die, exte break; } - if (abbrev_id >= abbrev_die_table_in_use) + if (abbrev_id >= vec_safe_length (abbrev_die_table)) { - if (abbrev_die_table_in_use >= abbrev_die_table_allocated) - { - n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT; - abbrev_die_table = GGC_RESIZEVEC (dw_die_ref, abbrev_die_table, - n_alloc); - - memset (&abbrev_die_table[abbrev_die_table_allocated], 0, - (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref)); - abbrev_die_table_allocated = n_alloc; - } - - ++abbrev_die_table_in_use; - abbrev_die_table[abbrev_id] = die; + vec_safe_push (abbrev_die_table, die); + if (abbrev_opt_start) + abbrev_usage_count.safe_push (0); + } + if (abbrev_opt_start && abbrev_id >= abbrev_opt_start) + { + abbrev_usage_count[abbrev_id - abbrev_opt_start]++; + abbrev_dies.safe_push (die); } die->die_abbrev = abbrev_id; FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map)); } + +/* Callback function for abbrev_dies vector sorting. We sort + by die_abbrev's usage count, from the most commonly used + abbreviation to the least. */ + +static int +die_abbrev_cmp (const void *p1, const void *p2) +{ + dw_die_ref die1 = *(const dw_die_ref *) p1; + dw_die_ref die2 = *(const dw_die_ref *) p2; + + gcc_checking_assert (die1->die_abbrev >= abbrev_opt_start); + gcc_checking_assert (die2->die_abbrev >= abbrev_opt_start); + + if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start] + > abbrev_usage_count[die2->die_abbrev - abbrev_opt_start]) + return -1; + if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start] + < abbrev_usage_count[die2->die_abbrev - abbrev_opt_start]) + return 1; + + /* Stabilize the sort. */ + if (die1->die_abbrev < die2->die_abbrev) + return -1; + if (die1->die_abbrev > die2->die_abbrev) + return 1; + + return 0; +} + +/* Convert dw_val_class_const and dw_val_class_unsigned_const class attributes + of DIEs in between abbrev_dies[first_id] and abbrev_dies[end_id - 1] into + dw_val_class_const_implicit or dw_val_class_unsigned_const_implicit. */ + +static void +optimize_implicit_const (unsigned int first_id, unsigned int end, + vec &implicit_consts) +{ + /* It never makes sense if there is just one DIE using the abbreviation. */ + if (end < first_id + 2) + return; + + dw_attr_node *a; + unsigned ix, i; + dw_die_ref die = abbrev_dies[first_id]; + FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) + if (implicit_consts[ix]) + { + enum dw_val_class new_class = dw_val_class_none; + switch (AT_class (a)) + { + case dw_val_class_unsigned_const: + if ((HOST_WIDE_INT) AT_unsigned (a) < 0) + continue; + + /* The .debug_abbrev section will grow by + size_of_sleb128 (AT_unsigned (a)) and we avoid the constants + in all the DIEs using that abbreviation. */ + if (constant_size (AT_unsigned (a)) * (end - first_id) + <= (unsigned) size_of_sleb128 (AT_unsigned (a))) + continue; + + new_class = dw_val_class_unsigned_const_implicit; + break; + + case dw_val_class_const: + new_class = dw_val_class_const_implicit; + break; + + case dw_val_class_file: + new_class = dw_val_class_file_implicit; + break; + + default: + continue; + } + for (i = first_id; i < end; i++) + (*abbrev_dies[i]->die_attr)[ix].dw_attr_val.val_class = new_class; + } +} + +/* Attempt to optimize abbreviation table from abbrev_opt_start + abbreviation above. */ + +static void +optimize_abbrev_table (void) +{ + if (abbrev_opt_start + && vec_safe_length (abbrev_die_table) > abbrev_opt_start + && (dwarf_version >= 5 || vec_safe_length (abbrev_die_table) > 127)) + { + auto_vec implicit_consts; + abbrev_dies.qsort (die_abbrev_cmp); + + unsigned int abbrev_id = abbrev_opt_start - 1; + unsigned int first_id = 0; + unsigned int last_abbrev_id = 0; + unsigned int i; + dw_die_ref die; + /* Reassign abbreviation ids from abbrev_opt_start above, so that + most commonly used abbreviations come first. */ + FOR_EACH_VEC_ELT (abbrev_dies, i, die) + { + dw_attr_node *a; + unsigned ix; + + if (die->die_abbrev != last_abbrev_id) + { + last_abbrev_id = die->die_abbrev; + if (dwarf_version >= 5 && i) + optimize_implicit_const (first_id, i, implicit_consts); + abbrev_id++; + (*abbrev_die_table)[abbrev_id] = die; + if (dwarf_version >= 5) + { + first_id = i; + implicit_consts.truncate (0); + + FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) + switch (AT_class (a)) + { + case dw_val_class_const: + case dw_val_class_unsigned_const: + case dw_val_class_file: + implicit_consts.safe_push (true); + break; + default: + implicit_consts.safe_push (false); + break; + } + } + } + else if (dwarf_version >= 5) + { + FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) + if (!implicit_consts[ix]) + continue; + else + { + dw_attr_node *other_a + = &(*(*abbrev_die_table)[abbrev_id]->die_attr)[ix]; + if (!dw_val_equal_p (&a->dw_attr_val, + &other_a->dw_attr_val)) + implicit_consts[ix] = false; + } + } + die->die_abbrev = abbrev_id; + } + gcc_assert (abbrev_id == vec_safe_length (abbrev_die_table) - 1); + if (dwarf_version >= 5) + optimize_implicit_const (first_id, i, implicit_consts); + } + + abbrev_opt_start = 0; + abbrev_usage_count.release (); + abbrev_dies.release (); +} /* Return the power-of-two number of bytes necessary to represent VALUE. */ @@ -8435,6 +8604,12 @@ size_of_die (dw_die_ref die) size += csize; } break; + case dw_val_class_const_implicit: + case dw_val_class_unsigned_const_implicit: + case dw_val_class_file_implicit: + /* These occupy no size in the DIE, just an extra sleb128 in + .debug_abbrev. */ + break; case dw_val_class_const_double: size += HOST_BITS_PER_DOUBLE_INT / HOST_BITS_PER_CHAR; if (HOST_BITS_PER_WIDE_INT >= 64) @@ -8815,6 +8990,10 @@ value_format (dw_attr_node *a) default: gcc_unreachable (); } + case dw_val_class_const_implicit: + case dw_val_class_unsigned_const_implicit: + case dw_val_class_file_implicit: + return DW_FORM_implicit_const; case dw_val_class_const_double: switch (HOST_BITS_PER_WIDE_INT) { @@ -8968,6 +9147,17 @@ output_die_abbrevs (unsigned long abbrev dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)", dwarf_attr_name (a_attr->dw_attr)); output_value_format (a_attr); + if (value_format (a_attr) == DW_FORM_implicit_const) + { + if (AT_class (a_attr) == dw_val_class_file_implicit) + { + int f = maybe_emit_file (a_attr->dw_attr_val.v.val_file); + const char *filename = a_attr->dw_attr_val.v.val_file->filename; + dw2_asm_output_data_sleb128 (f, "(%s)", filename); + } + else + dw2_asm_output_data_sleb128 (a_attr->dw_attr_val.v.val_int, NULL); + } } dw2_asm_output_data (1, 0, NULL); @@ -8981,10 +9171,12 @@ output_die_abbrevs (unsigned long abbrev static void output_abbrev_section (void) { - unsigned long abbrev_id; + unsigned int abbrev_id; + dw_die_ref abbrev; - for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) - output_die_abbrevs (abbrev_id, abbrev_die_table[abbrev_id]); + FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev) + if (abbrev_id != 0) + output_die_abbrevs (abbrev_id, abbrev); /* Terminate the table. */ dw2_asm_output_data (1, 0, NULL); @@ -9281,6 +9473,20 @@ output_die (dw_die_ref die) } break; + case dw_val_class_const_implicit: + if (flag_debug_asm) + fprintf (asm_out_file, "\t\t\t%s %s (" + HOST_WIDE_INT_PRINT_DEC ")\n", + ASM_COMMENT_START, name, AT_int (a)); + break; + + case dw_val_class_unsigned_const_implicit: + if (flag_debug_asm) + fprintf (asm_out_file, "\t\t\t%s %s (" + HOST_WIDE_INT_PRINT_HEX ")\n", + ASM_COMMENT_START, name, AT_unsigned (a)); + break; + case dw_val_class_const_double: { unsigned HOST_WIDE_INT first, second; @@ -9474,6 +9680,14 @@ output_die (dw_die_ref die) break; } + case dw_val_class_file_implicit: + if (flag_debug_asm) + fprintf (asm_out_file, "\t\t\t%s %s (%d, %s)\n", + ASM_COMMENT_START, name, + maybe_emit_file (a->dw_attr_val.v.val_file), + a->dw_attr_val.v.val_file->filename); + break; + case dw_val_class_data8: { int i; @@ -9581,8 +9795,16 @@ output_comp_unit (dw_die_ref die, int ou external_ref_hash_type *extern_map = optimize_external_refs (die); + /* For now, optimize only the main CU, in order to optimize the rest + we'd need to see all of them earlier. Leave the rest for post-linking + tools like DWZ. */ + if (die == comp_unit_die ()) + abbrev_opt_start = vec_safe_length (abbrev_die_table); + build_abbrev_table (die, extern_map); + optimize_abbrev_table (); + delete extern_map; /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ @@ -25738,11 +25960,9 @@ dwarf2out_init (const char *filename ATT vec_alloc (decl_scope_table, 256); /* Allocate the initial hunk of the abbrev_die_table. */ - abbrev_die_table = ggc_cleared_vec_alloc - (ABBREV_DIE_TABLE_INCREMENT); - abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT; + vec_alloc (abbrev_die_table, 256); /* Zero-th entry is allocated, but unused. */ - abbrev_die_table_in_use = 1; + abbrev_die_table->quick_push (NULL); /* Allocate the dwarf_proc_stack_usage_map. */ dwarf_proc_stack_usage_map = new hash_map; @@ -28142,7 +28362,7 @@ dwarf2out_finish (const char *) output_skeleton_debug_sections (main_comp_unit_die); /* Output the abbreviation table. */ - if (abbrev_die_table_in_use != 1) + if (vec_safe_length (abbrev_die_table) != 1) { switch_to_section (debug_abbrev_section); ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); @@ -28373,8 +28593,6 @@ dwarf2out_c_finalize (void) tail_call_site_count = -1; cached_dw_loc_list_table = NULL; abbrev_die_table = NULL; - abbrev_die_table_allocated = 0; - abbrev_die_table_in_use = 0; delete dwarf_proc_stack_usage_map; dwarf_proc_stack_usage_map = NULL; line_info_label_num = 0;