From patchwork Fri Mar 25 17:01:52 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 88399 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 6438FB6F9D for ; Sat, 26 Mar 2011 04:02:17 +1100 (EST) Received: (qmail 4529 invoked by alias); 25 Mar 2011 17:02:11 -0000 Received: (qmail 4485 invoked by uid 22791); 25 Mar 2011 17:02:04 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 25 Mar 2011 17:01:55 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2PH1sa4018029 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 25 Mar 2011 13:01:54 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p2PH1rDR009939 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 25 Mar 2011 13:01:54 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p2PH1q88013024; Fri, 25 Mar 2011 18:01:52 +0100 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p2PH1qVZ013023; Fri, 25 Mar 2011 18:01:52 +0100 Date: Fri, 25 Mar 2011 18:01:52 +0100 From: Jakub Jelinek To: Jason Merrill Cc: Richard Henderson , gcc-patches@gcc.gnu.org Subject: [PATCH] Better .debug_aranges fix (PR debug/48253, take 3) Message-ID: <20110325170152.GB18914@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek References: <20110323200829.GS18914@tyan-ft48-01.lab.bos.redhat.com> <4D8B7A71.7030504@redhat.com> <20110325161707.GA18914@tyan-ft48-01.lab.bos.redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20110325161707.GA18914@tyan-ft48-01.lab.bos.redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes 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 On Fri, Mar 25, 2011 at 05:17:07PM +0100, Jakub Jelinek wrote: > On Thu, Mar 24, 2011 at 06:08:01PM +0100, Jason Merrill wrote: > > This ought to cut down on the number of cases we have to handle in > > all the different places in dwarf2out that deal with this stuff. > > > > Does that make sense to you? > > Here is updated patch, it is quite larger than the last one, because Actually, I now realize I've missed the request to also remove dw_fde_switched_sections bitfield, which can be replaced with dw_fde_second_begin != NULL test. Done below: 2011-03-25 Jakub Jelinek PR debug/48253 * dwarf2out.c (struct dw_fde_struct): Remove dw_fde_hot_section_label, dw_fde_hot_section_end_label, dw_fde_unlikely_section_label, dw_fde_unlikely_section_end_label, cold_in_std_section, dw_fde_switched_sections and dw_fde_switched_cold_to_hot fields. Add dw_fde_second_begin, dw_fde_second_end and second_in_std_section fields. (output_fde): Use dw_fde_second_{begin,end} if second is true, otherwise dw_fde_{begin,end}. (output_call_frame_info): Test dw_fde_second_begin != NULL instead of dw_fde_switched_sections. (dwarf2out_begin_prologue): Stop initializing removed dw_fde_struct fields, initialize new fields. Initialize in_std_section unconditionally from the first partition. (dwarf2out_end_epilogue): Don't override dw_fde_end when dw_fde_second_begin is non-NULL. (dwarf2out_switch_text_section): Stop initializing removed dw_fde_struct fields, initialize new fields, initialize also dw_fde_end here. Set dw_fde_switch_cfi even when dwarf2out_do_cfi_asm (). Call var_location_switch_text_section. (struct var_loc_list_def): Add last_before_switch field. (arange_table, arange_table_allocated, arange_table_in_use, ARANGE_TABLE_INCREMENT, add_arange): Removed. (size_of_aranges): Count !in_std_section and !second_in_std_section hunks in fdes, instead of looking at arange_table_in_use. (output_aranges): Add aranges_length argument, don't call size_of_aranges here. Instead of using aranges_table* emit ranges for fdes when !in_std_section resp. !second_in_std_section. (dw_loc_list): Break ranges crossing section switch. (convert_cfa_to_fb_loc_list): Likewise. If switched sections, use dw_fde_second_end instead of dw_fde_end as end of last range. (gen_subprogram_die): Don't call add_arange. Use dw_fde_{begin,end} for first partition and if switched section dw_fde_second_{begin,end} for the second. (var_location_switch_text_section_1, var_location_switch_text_section): New functions. (dwarf2out_begin_function): Initialize cold_text_section even when function_section () isn't text_section. (prune_unused_types): Don't walk arange_table. (dwarf2out_finish): Don't needlessly test flag_reorder_blocks_and_partition when testing cold_text_section_used. If info_section_emitted, call size_of_aranges and if it indicates non-empty .debug_aranges, call output_aranges with the computed size. Stop using removed dw_fde_struct fields, use dw_fde_{begin,end} for first partition and dw_fde_second_{begin,end} for second. Jakub --- gcc/dwarf2out.c.jj 2011-03-25 11:24:06.000000000 +0100 +++ gcc/dwarf2out.c 2011-03-25 17:45:05.000000000 +0100 @@ -302,10 +302,8 @@ typedef struct GTY(()) dw_fde_struct { const char *dw_fde_end; const char *dw_fde_vms_end_prologue; const char *dw_fde_vms_begin_epilogue; - const char *dw_fde_hot_section_label; - const char *dw_fde_hot_section_end_label; - const char *dw_fde_unlikely_section_label; - const char *dw_fde_unlikely_section_end_label; + const char *dw_fde_second_begin; + const char *dw_fde_second_end; dw_cfi_ref dw_fde_cfi; dw_cfi_ref dw_fde_switch_cfi; /* Last CFI before switching sections. */ HOST_WIDE_INT stack_realignment; @@ -324,13 +322,9 @@ typedef struct GTY(()) dw_fde_struct { unsigned drap_reg_saved: 1; /* True iff dw_fde_begin label is in text_section or cold_text_section. */ unsigned in_std_section : 1; - /* True iff dw_fde_unlikely_section_label is in text_section or + /* True iff dw_fde_second_begin label is in text_section or cold_text_section. */ - unsigned cold_in_std_section : 1; - /* True iff switched sections. */ - unsigned dw_fde_switched_sections : 1; - /* True iff switching from cold to hot section. */ - unsigned dw_fde_switched_cold_to_hot : 1; + unsigned second_in_std_section : 1; } dw_fde_node; @@ -3628,28 +3622,8 @@ output_fde (dw_fde_ref fde, bool for_eh, dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label, debug_frame_section, "FDE CIE offset"); - if (!fde->dw_fde_switched_sections) - { - begin = fde->dw_fde_begin; - end = fde->dw_fde_end; - } - else - { - /* For the first section, prefer dw_fde_begin over - dw_fde_{hot,cold}_section_label, as the latter - might be separated from the real start of the - function by alignment padding. */ - if (!second) - begin = fde->dw_fde_begin; - else if (fde->dw_fde_switched_cold_to_hot) - begin = fde->dw_fde_hot_section_label; - else - begin = fde->dw_fde_unlikely_section_label; - if (second ^ fde->dw_fde_switched_cold_to_hot) - end = fde->dw_fde_unlikely_section_end_label; - else - end = fde->dw_fde_hot_section_end_label; - } + begin = second ? fde->dw_fde_second_begin : fde->dw_fde_begin; + end = second ? fde->dw_fde_second_end : fde->dw_fde_end; if (for_eh) { @@ -3710,7 +3684,7 @@ output_fde (dw_fde_ref fde, bool for_eh, /* Loop through the Call Frame Instructions associated with this FDE. */ fde->dw_fde_current_label = begin; - if (!fde->dw_fde_switched_sections) + if (fde->dw_fde_second_begin == NULL) for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) output_cfi (cfi, fde, for_eh); else if (!second) @@ -3989,7 +3963,7 @@ output_call_frame_info (int for_eh) if (for_eh && !fde_needed_for_eh_p (fde)) continue; - for (k = 0; k < (fde->dw_fde_switched_sections ? 2 : 1); k++) + for (k = 0; k < (fde->dw_fde_second_begin ? 2 : 1); k++) output_fde (fde, for_eh, k, section_start_label, fde_encoding, augmentation, any_lsda_needed, lsda_encoding); } @@ -4107,14 +4081,10 @@ dwarf2out_begin_prologue (unsigned int l fde = &fde_table[fde_table_in_use++]; fde->decl = current_function_decl; fde->dw_fde_begin = dup_label; - fde->dw_fde_current_label = dup_label; - fde->dw_fde_hot_section_label = NULL; - fde->dw_fde_hot_section_end_label = NULL; - fde->dw_fde_unlikely_section_label = NULL; - fde->dw_fde_unlikely_section_end_label = NULL; - fde->dw_fde_switched_sections = 0; - fde->dw_fde_switched_cold_to_hot = 0; fde->dw_fde_end = NULL; + fde->dw_fde_current_label = dup_label; + fde->dw_fde_second_begin = NULL; + fde->dw_fde_second_end = NULL; fde->dw_fde_vms_end_prologue = NULL; fde->dw_fde_vms_begin_epilogue = NULL; fde->dw_fde_cfi = NULL; @@ -4125,27 +4095,9 @@ dwarf2out_begin_prologue (unsigned int l fde->nothrow = crtl->nothrow; fde->drap_reg = INVALID_REGNUM; fde->vdrap_reg = INVALID_REGNUM; - if (flag_reorder_blocks_and_partition) - { - section *unlikelysec; - if (first_function_block_is_cold) - fde->in_std_section = 1; - else - fde->in_std_section - = (fnsec == text_section - || (cold_text_section && fnsec == cold_text_section)); - unlikelysec = unlikely_text_section (); - fde->cold_in_std_section - = (unlikelysec == text_section - || (cold_text_section && unlikelysec == cold_text_section)); - } - else - { - fde->in_std_section - = (fnsec == text_section - || (cold_text_section && fnsec == cold_text_section)); - fde->cold_in_std_section = 0; - } + fde->in_std_section = (fnsec == text_section + || (cold_text_section && fnsec == cold_text_section)); + fde->second_in_std_section = 0; args_size = old_args_size = 0; @@ -4241,7 +4193,8 @@ dwarf2out_end_epilogue (unsigned int lin ASM_OUTPUT_LABEL (asm_out_file, label); fde = current_fde (); gcc_assert (fde != NULL); - fde->dw_fde_end = xstrdup (label); + if (fde->dw_fde_second_begin == NULL) + fde->dw_fde_end = xstrdup (label); } void @@ -4288,20 +4241,29 @@ dwarf2out_note_section_used (void) cold_text_section_used = true; } +static void var_location_switch_text_section (void); + void dwarf2out_switch_text_section (void) { + section *sect; dw_fde_ref fde = current_fde (); + dw_cfi_ref cfi; - gcc_assert (cfun && fde && !fde->dw_fde_switched_sections); - - fde->dw_fde_switched_sections = 1; - fde->dw_fde_switched_cold_to_hot = !in_cold_section_p; + gcc_assert (cfun && fde && fde->dw_fde_second_begin == NULL); - fde->dw_fde_hot_section_label = crtl->subsections.hot_section_label; - fde->dw_fde_hot_section_end_label = crtl->subsections.hot_section_end_label; - fde->dw_fde_unlikely_section_label = crtl->subsections.cold_section_label; - fde->dw_fde_unlikely_section_end_label = crtl->subsections.cold_section_end_label; + if (!in_cold_section_p) + { + fde->dw_fde_end = crtl->subsections.cold_section_end_label; + fde->dw_fde_second_begin = crtl->subsections.hot_section_label; + fde->dw_fde_second_end = crtl->subsections.hot_section_end_label; + } + else + { + fde->dw_fde_end = crtl->subsections.hot_section_end_label; + fde->dw_fde_second_begin = crtl->subsections.cold_section_label; + fde->dw_fde_second_end = crtl->subsections.cold_section_end_label; + } have_multiple_function_sections = true; /* Reset the current label on switching text sections, so that we @@ -4316,7 +4278,12 @@ dwarf2out_switch_text_section (void) fprintf (asm_out_file, "\t.cfi_endproc\n"); /* Now do the real section switch. */ - switch_to_section (current_function_section ()); + sect = current_function_section (); + switch_to_section (sect); + + fde->second_in_std_section + = (sect == text_section + || (cold_text_section && sect == cold_text_section)); if (dwarf2out_do_cfi_asm ()) { @@ -4325,16 +4292,12 @@ dwarf2out_switch_text_section (void) again. */ output_cfis (fde->dw_fde_cfi, true, fde, true); } - else - { - dw_cfi_ref cfi = fde->dw_fde_cfi; - - cfi = fde->dw_fde_cfi; - if (cfi) - while (cfi->dw_cfi_next != NULL) - cfi = cfi->dw_cfi_next; - fde->dw_fde_switch_cfi = cfi; - } + cfi = fde->dw_fde_cfi; + if (cfi) + while (cfi->dw_cfi_next != NULL) + cfi = cfi->dw_cfi_next; + fde->dw_fde_switch_cfi = cfi; + var_location_switch_text_section (); } /* And now, the subset of the debugging information support code necessary @@ -6122,6 +6085,11 @@ struct GTY (()) var_loc_list_def { Do not mark it for GC because it is marked through the chain. */ struct var_loc_node * GTY ((skip ("%h"))) last; + /* Pointer to the last element before section switch, + if NULL, either sections weren't switched or first + is after section switch. */ + struct var_loc_node * GTY ((skip ("%h"))) last_before_switch; + /* DECL_UID of the variable decl. */ unsigned int decl_id; }; @@ -6212,19 +6180,6 @@ static GTY (()) VEC (pubname_entry, gc) defines/undefines (and file start/end markers). */ static GTY (()) VEC (macinfo_entry, gc) * macinfo_table; -/* Array of dies for which we should generate .debug_arange info. */ -static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table; - -/* Number of elements currently allocated for arange_table. */ -static GTY(()) unsigned arange_table_allocated; - -/* Number of elements in arange_table currently in use. */ -static GTY(()) unsigned arange_table_in_use; - -/* Size (in elements) of increments by which we may expand the - arange_table. */ -#define ARANGE_TABLE_INCREMENT 64 - /* Array of dies for which we should generate .debug_ranges info. */ static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table; @@ -6432,8 +6387,7 @@ static void add_pubname (tree, dw_die_re static void add_pubname_string (const char *, dw_die_ref); static void add_pubtype (tree, dw_die_ref); static void output_pubnames (VEC (pubname_entry,gc) *); -static void add_arange (tree, dw_die_ref); -static void output_aranges (void); +static void output_aranges (unsigned long); static unsigned int add_ranges_num (int); static unsigned int add_ranges (const_tree); static void add_ranges_by_labels (dw_die_ref, const char *, const char *, @@ -10881,7 +10835,20 @@ size_of_aranges (void) size += 2 * DWARF2_ADDR_SIZE; if (cold_text_section_used) size += 2 * DWARF2_ADDR_SIZE; - size += 2 * DWARF2_ADDR_SIZE * arange_table_in_use; + if (have_multiple_function_sections) + { + unsigned fde_idx = 0; + + for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++) + { + dw_fde_ref fde = &fde_table[fde_idx]; + + if (!fde->in_std_section) + size += 2 * DWARF2_ADDR_SIZE; + if (fde->dw_fde_second_begin && !fde->second_in_std_section) + size += 2 * DWARF2_ADDR_SIZE; + } + } /* Count the two zero words used to terminated the address range table. */ size += 2 * DWARF2_ADDR_SIZE; @@ -11712,35 +11679,14 @@ output_pubnames (VEC (pubname_entry, gc) dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL); } -/* Add a new entry to .debug_aranges if appropriate. */ - -static void -add_arange (tree decl, dw_die_ref die) -{ - if (! DECL_SECTION_NAME (decl)) - return; - - if (arange_table_in_use == arange_table_allocated) - { - arange_table_allocated += ARANGE_TABLE_INCREMENT; - arange_table = GGC_RESIZEVEC (dw_die_ref, arange_table, - arange_table_allocated); - memset (arange_table + arange_table_in_use, 0, - ARANGE_TABLE_INCREMENT * sizeof (dw_die_ref)); - } - - arange_table[arange_table_in_use++] = die; -} - /* Output the information that goes into the .debug_aranges table. Namely, define the beginning and ending address range of the text section generated for this compilation unit. */ static void -output_aranges (void) +output_aranges (unsigned long aranges_length) { unsigned i; - unsigned long aranges_length = size_of_aranges (); if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) dw2_asm_output_data (4, 0xffffffff, @@ -11785,38 +11731,28 @@ output_aranges (void) cold_text_section_label, "Length"); } - for (i = 0; i < arange_table_in_use; i++) + if (have_multiple_function_sections) { - dw_die_ref die = arange_table[i]; - - /* We shouldn't see aranges for DIEs outside of the main CU. */ - gcc_assert (die->die_mark); + unsigned fde_idx = 0; - if (die->die_tag == DW_TAG_subprogram) - { - dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die), - "Address"); - dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die), - get_AT_low_pc (die), "Length"); - } - else + for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++) { - /* A static variable; extract the symbol from DW_AT_location. - Note that this code isn't currently hit, as we only emit - aranges for functions (jason 9/23/99). */ - dw_attr_ref a = get_AT (die, DW_AT_location); - dw_loc_descr_ref loc; - - gcc_assert (a && AT_class (a) == dw_val_class_loc); - - loc = AT_loc (a); - gcc_assert (loc->dw_loc_opc == DW_OP_addr); + dw_fde_ref fde = &fde_table[fde_idx]; - dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, - loc->dw_loc_oprnd1.v.val_addr, "Address"); - dw2_asm_output_data (DWARF2_ADDR_SIZE, - get_AT_unsigned (die, DW_AT_byte_size), - "Length"); + if (!fde->in_std_section) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, + "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, fde->dw_fde_end, + fde->dw_fde_begin, "Length"); + } + if (fde->dw_fde_second_begin && !fde->second_in_std_section) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_second_begin, + "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, fde->dw_fde_second_end, + fde->dw_fde_second_begin, "Length"); + } } } @@ -15132,9 +15068,19 @@ dw_loc_list (var_loc_list *loc_list, tre } if (descr) { + /* If section switch happens in between node->label + and node->next->label (or end of function) and + we can't emit it as a single entry list, + emit two ranges, first one ending at the end + of first partition and second one starting at the + beginning of second partition. */ + if (node == loc_list->last_before_switch + && (node != loc_list->first || loc_list->first->next) + && current_function_decl) + endname = current_fde ()->dw_fde_end; /* The variable has a location between NODE->LABEL and NODE->NEXT->LABEL. */ - if (node->next) + else if (node->next) endname = node->next->label; /* If the variable has a location at the last label it keeps its location until the end of function. */ @@ -15149,6 +15095,32 @@ dw_loc_list (var_loc_list *loc_list, tre *listp = new_loc_list (descr, node->label, endname, secname); listp = &(*listp)->dw_loc_next; + + if (node == loc_list->last_before_switch + && (node != loc_list->first || loc_list->first->next) + && current_function_decl) + { + if (GET_CODE (node->loc) == EXPR_LIST) + descr = dw_sra_loc_expr (decl, node->loc); + else + { + initialized = NOTE_VAR_LOCATION_STATUS (node->loc); + varloc = NOTE_VAR_LOCATION (node->loc); + descr = dw_loc_list_1 (decl, varloc, want_address, + initialized); + } + gcc_assert (descr); + /* The variable has a location between NODE->LABEL and + NODE->NEXT->LABEL. */ + if (node->next) + endname = node->next->label; + else + endname = current_fde ()->dw_fde_second_end; + *listp = new_loc_list (descr, + current_fde ()->dw_fde_second_begin, + endname, secname); + listp = &(*listp)->dw_loc_next; + } } } @@ -17225,6 +17197,8 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_IN remember = next_cfa; start_label = fde->dw_fde_begin; + if (fde->dw_fde_second_begin && fde->dw_fde_switch_cfi == NULL) + start_label = fde->dw_fde_second_begin; /* ??? Bald assumption that the CIE opcode list does not contain advance opcodes. */ @@ -17235,32 +17209,50 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_IN last_label = start_label; for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next) - switch (cfi->dw_cfi_opc) - { - case DW_CFA_set_loc: - case DW_CFA_advance_loc1: - case DW_CFA_advance_loc2: - case DW_CFA_advance_loc4: - if (!cfa_equal_p (&last_cfa, &next_cfa)) - { - *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section); + { + switch (cfi->dw_cfi_opc) + { + case DW_CFA_set_loc: + case DW_CFA_advance_loc1: + case DW_CFA_advance_loc2: + case DW_CFA_advance_loc4: + if (!cfa_equal_p (&last_cfa, &next_cfa)) + { + *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), + start_label, last_label, section); - list_tail = &(*list_tail)->dw_loc_next; - last_cfa = next_cfa; - start_label = last_label; - } - last_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; - break; + list_tail = &(*list_tail)->dw_loc_next; + last_cfa = next_cfa; + start_label = last_label; + } + last_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; + break; - case DW_CFA_advance_loc: - /* The encoding is complex enough that we should never emit this. */ - gcc_unreachable (); + case DW_CFA_advance_loc: + /* The encoding is complex enough that we should never emit this. */ + gcc_unreachable (); - default: - lookup_cfa_1 (cfi, &next_cfa, &remember); - break; - } + default: + lookup_cfa_1 (cfi, &next_cfa, &remember); + break; + } + if (cfi == fde->dw_fde_switch_cfi) + { + if (!cfa_equal_p (&last_cfa, &next_cfa)) + { + *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), + start_label, last_label, section); + + list_tail = &(*list_tail)->dw_loc_next; + last_cfa = next_cfa; + start_label = last_label; + } + *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), + start_label, fde->dw_fde_end, section); + list_tail = &(*list_tail)->dw_loc_next; + start_label = last_label = fde->dw_fde_second_begin; + } + } if (!cfa_equal_p (&last_cfa, &next_cfa)) { @@ -17271,7 +17263,10 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_IN } *list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset), - start_label, fde->dw_fde_end, section); + start_label, + fde->dw_fde_second_begin + ? fde->dw_fde_second_end : fde->dw_fde_end, + section); if (list && list->dw_loc_next) gen_llsym (list); @@ -19196,14 +19191,13 @@ gen_subprogram_die (tree decl, dw_die_re #endif add_pubname (decl, subr_die); - add_arange (decl, subr_die); } else { /* Generate pubnames entries for the split function code ranges. */ dw_fde_ref fde = &fde_table[current_funcdef_fde]; - if (fde->dw_fde_switched_sections) + if (fde->dw_fde_second_begin) { if (dwarf_version >= 3 || !dwarf_strict) { @@ -19212,28 +19206,11 @@ gen_subprogram_die (tree decl, dw_die_re section, since the HOT/COLD labels might precede an alignment offset. */ bool range_list_added = false; - if (fde->in_std_section) - { - add_ranges_by_labels (subr_die, - fde->dw_fde_begin, - fde->dw_fde_end, - &range_list_added); - add_ranges_by_labels (subr_die, - fde->dw_fde_unlikely_section_label, - fde->dw_fde_unlikely_section_end_label, - &range_list_added); - } - else - { - add_ranges_by_labels (subr_die, - fde->dw_fde_begin, - fde->dw_fde_end, - &range_list_added); - add_ranges_by_labels (subr_die, - fde->dw_fde_hot_section_label, - fde->dw_fde_hot_section_end_label, - &range_list_added); - } + add_ranges_by_labels (subr_die, fde->dw_fde_begin, + fde->dw_fde_end, &range_list_added); + add_ranges_by_labels (subr_die, fde->dw_fde_second_begin, + fde->dw_fde_second_end, + &range_list_added); add_pubname (decl, subr_die); if (range_list_added) add_ranges (NULL); @@ -19258,7 +19235,6 @@ gen_subprogram_die (tree decl, dw_die_re fde->dw_fde_end); /* Add it. */ add_pubname (decl, subr_die); - add_arange (decl, subr_die); /* Build a minimal DIE for the secondary section. */ seg_die = new_die (DW_TAG_subprogram, @@ -19276,30 +19252,18 @@ gen_subprogram_die (tree decl, dw_die_re add_linkage_name (seg_die, decl); } - gcc_assert (name!=NULL); + gcc_assert (name != NULL); add_pure_or_virtual_attribute (seg_die, decl); if (DECL_ARTIFICIAL (decl)) add_AT_flag (seg_die, DW_AT_artificial, 1); - if (fde->in_std_section) - { - name = concat ("__cold_sect_of_", name, NULL); - add_AT_lbl_id (seg_die, DW_AT_low_pc, - fde->dw_fde_unlikely_section_label); - add_AT_lbl_id (seg_die, DW_AT_high_pc, - fde->dw_fde_unlikely_section_end_label); - } - else - { - name = concat ("__hot_sect_of_", name, NULL); - add_AT_lbl_id (seg_die, DW_AT_low_pc, - fde->dw_fde_hot_section_label); - add_AT_lbl_id (seg_die, DW_AT_high_pc, - fde->dw_fde_hot_section_end_label); - } + name = concat ("__second_sect_of_", name, NULL); + add_AT_lbl_id (seg_die, DW_AT_low_pc, + fde->dw_fde_second_begin); + add_AT_lbl_id (seg_die, DW_AT_high_pc, + fde->dw_fde_second_end); add_name_attribute (seg_die, name); add_pubname_string (name, seg_die); - add_arange (decl, seg_die); } } else @@ -19307,7 +19271,6 @@ gen_subprogram_die (tree decl, dw_die_re add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin); add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end); add_pubname (decl, subr_die); - add_arange (decl, subr_die); } } @@ -22034,6 +21997,29 @@ dwarf2out_var_location (rtx loc_note) last_in_cold_section_p = in_cold_section_p; } +/* Note in one location list that text section has changed. */ + +static int +var_location_switch_text_section_1 (void **slot, void *data ATTRIBUTE_UNUSED) +{ + var_loc_list *list = (var_loc_list *) *slot; + if (list->first) + list->last_before_switch + = list->last->next ? list->last->next : list->last; + return 1; +} + +/* Note in all location lists that text section has changed. */ + +static void +var_location_switch_text_section (void) +{ + if (decl_loc_table == NULL) + return; + + htab_traverse (decl_loc_table, var_location_switch_text_section_1, NULL); +} + /* We need to reset the locations at the beginning of each function. We can't do this in the end_function hook, because the declarations that use the locations won't have been output when @@ -22044,7 +22030,7 @@ dwarf2out_begin_function (tree fun) { if (function_section (fun) != text_section) have_multiple_function_sections = true; - else if (flag_reorder_blocks_and_partition && !cold_text_section) + if (flag_reorder_blocks_and_partition && !cold_text_section) { gcc_assert (current_function_decl == fun); cold_text_section = unlikely_text_section (); @@ -22754,11 +22740,9 @@ prune_unused_types (void) } /* Also set the mark on nodes referenced from the - pubname_table or arange_table. */ + pubname_table. */ FOR_EACH_VEC_ELT (pubname_entry, pubname_table, i, pub) prune_unused_types_mark (pub->die, 1); - for (i = 0; i < arange_table_in_use; i++) - prune_unused_types_mark (arange_table[i], 1); /* Get rid of nodes that aren't marked; and update the string counts. */ if (debug_str_hash && debug_str_hash_forced) @@ -23556,7 +23540,7 @@ dwarf2out_finish (const char *filename) if (text_section_used) add_ranges_by_labels (comp_unit_die (), text_section_label, text_end_label, &range_list_added); - if (flag_reorder_blocks_and_partition && cold_text_section_used) + if (cold_text_section_used) add_ranges_by_labels (comp_unit_die (), cold_text_section_label, cold_end_label, &range_list_added); @@ -23564,22 +23548,12 @@ dwarf2out_finish (const char *filename) { dw_fde_ref fde = &fde_table[fde_idx]; - if (fde->dw_fde_switched_sections) - { - if (!fde->in_std_section) - add_ranges_by_labels (comp_unit_die (), - fde->dw_fde_hot_section_label, - fde->dw_fde_hot_section_end_label, - &range_list_added); - if (!fde->cold_in_std_section) - add_ranges_by_labels (comp_unit_die (), - fde->dw_fde_unlikely_section_label, - fde->dw_fde_unlikely_section_end_label, - &range_list_added); - } - else if (!fde->in_std_section) + if (!fde->in_std_section) add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin, fde->dw_fde_end, &range_list_added); + if (fde->dw_fde_second_begin && !fde->second_in_std_section) + add_ranges_by_labels (comp_unit_die (), fde->dw_fde_second_begin, + fde->dw_fde_second_end, &range_list_added); } if (range_list_added) @@ -23679,13 +23653,21 @@ dwarf2out_finish (const char *filename) } } - /* Output the address range information. We only put functions in the arange - table, so don't write it out if we don't have any. */ - if ((text_section_used || cold_text_section_used || arange_table_in_use) - && info_section_emitted) - { - switch_to_section (debug_aranges_section); - output_aranges (); + /* Output the address range information. We only put functions in the + arange table, so don't write it out if we don't have any. */ + if (info_section_emitted) + { + unsigned long aranges_length = size_of_aranges (); + + /* Empty .debug_aranges would contain just header and + terminating 0,0. */ + if (aranges_length + != (unsigned long) (DWARF_ARANGES_HEADER_SIZE + + 2 * DWARF2_ADDR_SIZE)) + { + switch_to_section (debug_aranges_section); + output_aranges (aranges_length); + } } /* Output ranges section if necessary. */