From b8cb3096f78581c16d87469706e49b1a4ec345f0 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 27 Nov 2017 09:48:56 +0100 Subject: [PATCH] re PR debug/81307 (g++.dg/debug/debug9.C -gstabs FAILs) PR debug/81307 * dbxout.c (lastlineno): New variable. (dbx_debug_hooks): Use dbxout_switch_text_section as switch_text_section debug hook. (dbxout_function_end): Switch to current_function_section rather than function_section. If crtl->has_bb_partition, output just one N_FUN, depending on in_cold_section_p. (dbxout_source_line): Remember last lineno in lastlineno. (dbxout_switch_text_section): New function. (dbxout_function_decl): Adjust dbxout_block caller. (dbx_block_with_cold_children): New function. (dbxout_block): Return true if any LBRAC/RBRAC have been emitted. Use dbx_block_with_cold_children at depth == 0 in second partition. Add PARENT_BLOCKNUM argument, pass it optionally adjusted to children. Output LBRAC/RBRAC around recursive call only if the block is in the current partition, if not and anything was output, emit empty range LBRAC/RBRAC. * final.c (final_scan_insn): Compute cold_function_name before calling switch_text_section debug hook. Call that hook even if dwarf2out_do_frame if not emitting dwarf debug info. * g++.dg/debug/debug9.C: Remove -fno-reorder-blocks-and-partition workaround. From-SVN: r255161 --- gcc/ChangeLog | 23 +++++ gcc/dbxout.c | 150 ++++++++++++++++++++++++---- gcc/final.c | 13 ++- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/g++.dg/debug/debug9.C | 5 - 5 files changed, 170 insertions(+), 25 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7189a66ed83..75a860e3f81 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,28 @@ 2017-11-27 Jakub Jelinek + PR debug/81307 + * dbxout.c (lastlineno): New variable. + (dbx_debug_hooks): Use dbxout_switch_text_section as + switch_text_section debug hook. + (dbxout_function_end): Switch to current_function_section + rather than function_section. If crtl->has_bb_partition, + output just one N_FUN, depending on in_cold_section_p. + (dbxout_source_line): Remember last lineno in lastlineno. + (dbxout_switch_text_section): New function. + (dbxout_function_decl): Adjust dbxout_block caller. + (dbx_block_with_cold_children): New function. + (dbxout_block): Return true if any LBRAC/RBRAC have been + emitted. Use dbx_block_with_cold_children at depth == 0 + in second partition. Add PARENT_BLOCKNUM argument, pass + it optionally adjusted to children. Output LBRAC/RBRAC + around recursive call only if the block is in the current + partition, if not and anything was output, emit empty + range LBRAC/RBRAC. + * final.c (final_scan_insn): Compute cold_function_name + before calling switch_text_section debug hook. Call + that hook even if dwarf2out_do_frame if not emitting + dwarf debug info. + PR target/83100 * varasm.c (bss_initializer_p): Return true for DECL_COMMON TREE_READONLY decls. diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 49a858339f8..89f2d1f0cd4 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -244,6 +244,10 @@ static GTY(()) int source_label_number = 1; static GTY(()) const char *lastfile; +/* Last line number mentioned in a NOTE insn. */ + +static GTY(()) unsigned int lastlineno; + /* Used by PCH machinery to detect if 'lastfile' should be reset to base_input_file. */ static GTY(()) int lastfile_is_base; @@ -334,6 +338,7 @@ static void debug_free_queue (void); static void dbxout_source_line (unsigned int, unsigned int, const char *, int, bool); +static void dbxout_switch_text_section (void); static void dbxout_begin_prologue (unsigned int, unsigned int, const char *); static void dbxout_source_file (const char *); static void dbxout_function_end (tree); @@ -380,7 +385,7 @@ const struct gcc_debug_hooks dbx_debug_hooks = dbxout_handle_pch, /* handle_pch */ debug_nothing_rtx_insn, /* var_location */ debug_nothing_tree, /* size_function */ - debug_nothing_void, /* switch_text_section */ + dbxout_switch_text_section, /* switch_text_section */ debug_nothing_tree_tree, /* set_name */ 0, /* start_end_main_source_file */ TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */ @@ -902,7 +907,7 @@ dbxout_function_end (tree decl ATTRIBUTE_UNUSED) /* The Lscope label must be emitted even if we aren't doing anything else; dbxout_block needs it. */ - switch_to_section (function_section (current_function_decl)); + switch_to_section (current_function_section ()); /* Convert Lscope into the appropriate format for local labels in case the system doesn't insert underscores in front of user generated @@ -923,11 +928,12 @@ dbxout_function_end (tree decl ATTRIBUTE_UNUSED) if (crtl->has_bb_partition) { dbxout_begin_empty_stabs (N_FUN); - dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label, - crtl->subsections.hot_section_label); - dbxout_begin_empty_stabs (N_FUN); - dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label, - crtl->subsections.cold_section_label); + if (in_cold_section_p) + dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label, + crtl->subsections.cold_section_label); + else + dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label, + crtl->subsections.hot_section_label); } else { @@ -1215,7 +1221,7 @@ dbxout_handle_pch (unsigned at_end) #if defined (DBX_DEBUGGING_INFO) -static void dbxout_block (tree, int, tree); +static bool dbxout_block (tree, int, tree, int); /* Output debugging info to FILE to switch to sourcefile FILENAME. */ @@ -1289,6 +1295,60 @@ dbxout_source_line (unsigned int lineno, unsigned int column ATTRIBUTE_UNUSED, else dbxout_stabd (N_SLINE, lineno); #endif + lastlineno = lineno; +} + +/* Unfortunately, at least when emitting relative addresses, STABS + has no way to express multiple partitions. Represent a function + as two functions in this case. */ + +static void +dbxout_switch_text_section (void) +{ + /* The N_FUN tag at the end of the function is a GNU extension, + which may be undesirable, and is unnecessary if we do not have + named sections. */ + in_cold_section_p = !in_cold_section_p; + switch_to_section (current_function_section ()); + dbxout_block (DECL_INITIAL (current_function_decl), 0, + DECL_ARGUMENTS (current_function_decl), -1); + dbxout_function_end (current_function_decl); + in_cold_section_p = !in_cold_section_p; + + switch_to_section (current_function_section ()); + + tree context = decl_function_context (current_function_decl); + extern tree cold_function_name; + + dbxout_begin_complex_stabs (); + stabstr_I (cold_function_name); + stabstr_S (":f"); + + tree type = TREE_TYPE (current_function_decl); + if (TREE_TYPE (type)) + dbxout_type (TREE_TYPE (type), 0); + else + dbxout_type (void_type_node, 0); + + if (context != 0) + { + stabstr_C (','); + stabstr_I (cold_function_name); + stabstr_C (','); + stabstr_I (DECL_NAME (context)); + } + + dbxout_finish_complex_stabs (current_function_decl, N_FUN, 0, + crtl->subsections.cold_section_label, 0); + + /* pre-increment the scope counter */ + scope_labelno++; + + dbxout_source_line (lastlineno, 0, lastfile, 0, true); + /* Output function begin block at function scope, referenced + by dbxout_block, dbxout_source_line and dbxout_function_end. */ + emit_pending_bincls_if_required (); + targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno); } /* Describe the beginning of an internal block within a function. */ @@ -1322,7 +1382,7 @@ dbxout_function_decl (tree decl) #ifndef DBX_FUNCTION_FIRST dbxout_begin_function (decl); #endif - dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl)); + dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl), -1); dbxout_function_end (decl); } @@ -3664,6 +3724,26 @@ dbx_output_rbrac (const char *label, dbxout_stab_value_label (label); } +/* Return true is at least one block among BLOCK, its children or siblings + which has TREE_USED, TREE_ASM_WRITTEN and BLOCK_IN_COLD_SECTION_P + set. If there is none, clear TREE_USED bit on such blocks. */ + +static bool +dbx_block_with_cold_children (tree block) +{ + bool ret = false; + for (; block; block = BLOCK_CHAIN (block)) + if (TREE_USED (block) && TREE_ASM_WRITTEN (block)) + { + bool children = dbx_block_with_cold_children (BLOCK_SUBBLOCKS (block)); + if (BLOCK_IN_COLD_SECTION_P (block) || children) + ret = true; + else + TREE_USED (block) = false; + } + return ret; +} + /* Output everything about a symbol block (a BLOCK node that represents a scope level), including recursive output of contained blocks. @@ -3679,22 +3759,31 @@ dbx_output_rbrac (const char *label, except for the outermost block. Actually, BLOCK may be several blocks chained together. - We handle them all in sequence. */ + We handle them all in sequence. -static void -dbxout_block (tree block, int depth, tree args) + Return true if we emitted any LBRAC/RBRAC. */ + +static bool +dbxout_block (tree block, int depth, tree args, int parent_blocknum) { + bool ret = false; char begin_label[20]; /* Reference current function start using LFBB. */ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); - while (block) + /* If called for the second partition, ignore blocks that don't have + any children in the second partition. */ + if (crtl->has_bb_partition && in_cold_section_p && depth == 0) + dbx_block_with_cold_children (block); + + for (; block; block = BLOCK_CHAIN (block)) { /* Ignore blocks never expanded or otherwise marked as real. */ if (TREE_USED (block) && TREE_ASM_WRITTEN (block)) { int did_output; int blocknum = BLOCK_NUMBER (block); + int this_parent = parent_blocknum; /* In dbx format, the syms of a block come before the N_LBRAC. If nothing is output, we don't need the N_LBRAC, either. */ @@ -3708,11 +3797,13 @@ dbxout_block (tree block, int depth, tree args) the block. Use the block's tree-walk order to generate the assembler symbols LBBn and LBEn that final will define around the code in this block. */ - if (did_output) + if (did_output + && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p) { char buf[20]; const char *scope_start; + ret = true; if (depth == 0) /* The outermost block doesn't get LBB labels; use the LFBB local symbol emitted by dbxout_begin_prologue. */ @@ -3721,16 +3812,21 @@ dbxout_block (tree block, int depth, tree args) { ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum); scope_start = buf; + this_parent = blocknum; } dbx_output_lbrac (scope_start, begin_label); } /* Output the subblocks. */ - dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE); + bool children + = dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE, + this_parent); + ret |= children; /* Refer to the marker for the end of the block. */ - if (did_output) + if (did_output + && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p) { char buf[100]; if (depth == 0) @@ -3743,9 +3839,29 @@ dbxout_block (tree block, int depth, tree args) dbx_output_rbrac (buf, begin_label); } + else if (did_output && !children) + { + /* If we emitted any vars and didn't output any LBRAC/RBRAC, + either at this level or any lower level, we need to emit + an empty LBRAC/RBRAC pair now. */ + char buf[20]; + const char *scope_start; + + ret = true; + if (parent_blocknum == -1) + scope_start = begin_label; + else + { + ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", parent_blocknum); + scope_start = buf; + } + + dbx_output_lbrac (scope_start, begin_label); + dbx_output_rbrac (scope_start, begin_label); + } } - block = BLOCK_CHAIN (block); } + return ret; } /* Output the information about a function and its arguments and result. diff --git a/gcc/final.c b/gcc/final.c index 672c5bbc49c..fdae241bc83 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2210,8 +2210,17 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, case NOTE_INSN_SWITCH_TEXT_SECTIONS: in_cold_section_p = !in_cold_section_p; + if (in_cold_section_p) + cold_function_name + = clone_function_name (current_function_decl, "cold"); + if (dwarf2out_do_frame ()) - dwarf2out_switch_text_section (); + { + dwarf2out_switch_text_section (); + if (!dwarf2_debug_info_emitted_p (current_function_decl) + && !DECL_IGNORED_P (current_function_decl)) + debug_hooks->switch_text_section (); + } else if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->switch_text_section (); @@ -2223,8 +2232,6 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, suffixing "cold" to the original function's name. */ if (in_cold_section_p) { - cold_function_name - = clone_function_name (current_function_decl, "cold"); #ifdef ASM_DECLARE_COLD_FUNCTION_NAME ASM_DECLARE_COLD_FUNCTION_NAME (asm_out_file, IDENTIFIER_POINTER diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ff40f3657e3..87e930a3a0a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2017-11-27 Jakub Jelinek + PR debug/81307 + * g++.dg/debug/debug9.C: Remove -fno-reorder-blocks-and-partition + workaround. + PR target/83100 * gcc.dg/pr83100-1.c: New test. * gcc.dg/pr83100-2.c: New test. diff --git a/gcc/testsuite/g++.dg/debug/debug9.C b/gcc/testsuite/g++.dg/debug/debug9.C index 8cf2327e069..aa328ee6f79 100644 --- a/gcc/testsuite/g++.dg/debug/debug9.C +++ b/gcc/testsuite/g++.dg/debug/debug9.C @@ -1,9 +1,4 @@ /* { dg-do assemble } */ -/* Partitioning causes hot/cold section emission and breaks stabs - debugging. */ -/* { dg-additional-options "-fno-reorder-blocks-and-partition" } */ - - /* This testcase requires entries in the debug_range section in DWARF which refer to a vague linkage function. */ -- 2.30.2