/* Output dbx-format symbol table information from GNU compiler.
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "common/common-target.h"
#include "langhooks.h"
#include "expr.h"
+#include "file-prefix-map.h" /* remap_debug_filename() */
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
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;
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);
debug_nothing_rtx_code_label, /* label */
dbxout_handle_pch, /* handle_pch */
debug_nothing_rtx_insn, /* var_location */
+ debug_nothing_tree, /* inline_entry */
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 */
debug_nothing_rtx_code_label, /* label */
dbxout_handle_pch, /* handle_pch */
debug_nothing_rtx_insn, /* var_location */
+ debug_nothing_tree, /* inline_entry */
debug_nothing_tree, /* size_function */
debug_nothing_void, /* switch_text_section */
debug_nothing_tree_tree, /* set_name */
if (num < 0)
{
putc ('-', asm_out_file);
- unum = -num;
+ unum = -(unsigned int) num;
}
else
unum = num;
{
char buf[64];
char *p = buf + sizeof buf;
- unsigned int unum;
+ unsigned HOST_WIDE_INT unum;
if (num == 0)
{
if (num < 0)
{
stabstr_C ('-');
- unum = -num;
+ unum = -(unsigned HOST_WIDE_INT) num;
}
else
unum = num;
/* 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
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
{
#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. */
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. */
#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);
}
if (TREE_TYPE (type))
dbxout_type (TREE_TYPE (type), 0);
else if (TREE_CODE (type) != INTEGER_TYPE)
- dbxout_type (type, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
+ dbxout_type (type, 0);
else
{
/* Traditionally, we made sure 'int' was type 1, and builtin types
dbxout_type (TREE_TYPE (type), 0);
break;
- case POINTER_BOUNDS_TYPE:
- /* No debug info for pointer bounds type supported yet. */
- break;
-
default:
/* A C++ function with deduced return type can have a TEMPLATE_TYPE_PARM
named 'auto' in its type.
case BIT_FIELD_REF:
{
machine_mode mode;
- HOST_WIDE_INT bitsize, bitpos;
+ poly_int64 bitsize, bitpos;
tree offset, tem;
int unsignedp, reversep, volatilep = 0;
rtx x;
return NULL;
x = adjust_address_nv (x, mode, tree_to_shwi (offset));
}
- if (bitpos != 0)
- x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT);
+ if (maybe_ne (bitpos, 0))
+ x = adjust_address_nv (x, mode, bits_to_bytes_round_down (bitpos));
return x;
}
/* Do not generate a tag for incomplete records. */
&& COMPLETE_TYPE_P (type)
/* Do not generate a tag for records of variable size,
- since this type can not be properly described in the
+ since this type cannot be properly described in the
DBX format, and it confuses some tools such as objdump. */
&& tree_fits_uhwi_p (TYPE_SIZE (type)))
{
int offs;
letter = 'G';
code = N_GSYM;
- if (NULL != dbxout_common_check (decl, &offs))
+ if (dbxout_common_check (decl, &offs) != NULL)
{
letter = 'V';
addr = 0;
{
int offs;
code = N_LCSYM;
- if (NULL != dbxout_common_check (decl, &offs))
+ if (dbxout_common_check (decl, &offs) != NULL)
{
addr = 0;
number = offs;
int offs;
code = N_LCSYM;
letter = 'V';
- if (NULL == dbxout_common_check (decl, &offs))
+ if (dbxout_common_check (decl, &offs) == NULL)
addr = XEXP (XEXP (home, 0), 0);
else
{
dbxout_stab_value_label (label);
}
+/* Return true if at least one block among BLOCK, its children or siblings
+ 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.
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. */
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. */
{
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)
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[30];
+ 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.