/* Output dbx-format symbol table information from GNU compiler.
- Copyright (C) 1987-2013 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-
-#include "tree.h"
+#include "target.h"
+#include "function.h"
#include "rtl.h"
-#include "flags.h"
-#include "regs.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
#include "insn-config.h"
+#include "emit-rtl.h"
+#include "cgraph.h"
+#include "diagnostic-core.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "stor-layout.h"
#include "reload.h"
#include "output.h"
#include "dbxout.h"
-#include "diagnostic-core.h"
#include "toplev.h"
-#include "tm_p.h"
-#include "ggc.h"
#include "debug.h"
-#include "function.h"
-#include "target.h"
#include "common/common-target.h"
#include "langhooks.h"
-#include "obstack.h"
#include "expr.h"
-#include "cgraph.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_symbol_name (tree, const char *, int);
static void dbxout_common_name (tree, const char *, stab_code_type);
static const char *dbxout_common_check (tree, int *);
-static void dbxout_global_decl (tree);
+static void dbxout_early_global_decl (tree);
+static void dbxout_late_global_decl (tree);
static void dbxout_type_decl (tree, int);
static void dbxout_handle_pch (unsigned);
static void debug_free_queue (void);
/* The debug hooks structure. */
#if defined (DBX_DEBUGGING_INFO)
-static void dbxout_source_line (unsigned int, const char *, int, bool);
-static void dbxout_begin_prologue (unsigned int, const char *);
+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);
static void dbxout_begin_function (tree);
{
dbxout_init,
dbxout_finish,
+ debug_nothing_charstar,
debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
debug_nothing_tree, /* begin_function */
#endif
debug_nothing_int, /* end_function */
+ debug_nothing_tree, /* register_main_translation_unit */
dbxout_function_decl,
- dbxout_global_decl, /* global_decl */
+ dbxout_early_global_decl, /* early_global_decl */
+ dbxout_late_global_decl, /* late_global_decl */
dbxout_type_decl, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+ debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+ debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
- debug_nothing_rtx, /* label */
+ debug_nothing_rtx_code_label, /* label */
dbxout_handle_pch, /* handle_pch */
- debug_nothing_rtx, /* var_location */
- debug_nothing_void, /* switch_text_section */
+ debug_nothing_rtx_insn, /* var_location */
+ debug_nothing_tree, /* inline_entry */
+ debug_nothing_tree, /* size_function */
+ 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 */
{
dbxout_init,
dbxout_finish,
+ debug_nothing_charstar,
debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
xcoffout_end_epilogue,
debug_nothing_tree, /* begin_function */
xcoffout_end_function,
+ debug_nothing_tree, /* register_main_translation_unit */
debug_nothing_tree, /* function_decl */
- dbxout_global_decl, /* global_decl */
+ dbxout_early_global_decl, /* early_global_decl */
+ dbxout_late_global_decl, /* late_global_decl */
dbxout_type_decl, /* type_decl */
- debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+ debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+ debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
- debug_nothing_rtx, /* label */
+ debug_nothing_rtx_code_label, /* label */
dbxout_handle_pch, /* handle_pch */
- debug_nothing_rtx, /* var_location */
+ 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 */
0, /* start_end_main_source_file */
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;
static void
stabstr_O (tree cst)
{
- unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (cst);
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
-
- char buf[128];
- char *p = buf + sizeof buf;
-
- /* GDB wants constants with no extra leading "1" bits, so
- we need to remove any sign-extension that might be
- present. */
- {
- const unsigned int width = TYPE_PRECISION (TREE_TYPE (cst));
- if (width == HOST_BITS_PER_DOUBLE_INT)
- ;
- else if (width > HOST_BITS_PER_WIDE_INT)
- high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
- else if (width == HOST_BITS_PER_WIDE_INT)
- high = 0;
- else
- high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
- }
+ int prec = TYPE_PRECISION (TREE_TYPE (cst));
+ int res_pres = prec % 3;
+ int i;
+ unsigned int digit;
/* Leading zero for base indicator. */
stabstr_C ('0');
/* If the value is zero, the base indicator will serve as the value
all by itself. */
- if (high == 0 && low == 0)
+ if (wi::to_wide (cst) == 0)
return;
- /* If the high half is zero, we need only print the low half normally. */
- if (high == 0)
- NUMBER_FMT_LOOP (p, low, 8);
- else
+ /* GDB wants constants with no extra leading "1" bits, so
+ we need to remove any sign-extension that might be
+ present. */
+ if (res_pres == 1)
{
- /* When high != 0, we need to print enough zeroes from low to
- give the digits from high their proper place-values. Hence
- NUMBER_FMT_LOOP cannot be used. */
- const int n_digits = HOST_BITS_PER_WIDE_INT / 3;
- int i;
-
- for (i = 1; i <= n_digits; i++)
- {
- unsigned int digit = low % 8;
- low /= 8;
- *--p = '0' + digit;
- }
-
- /* Octal digits carry exactly three bits of information. The
- width of a HOST_WIDE_INT is not normally a multiple of three.
- Therefore, the next digit printed probably needs to carry
- information from both low and high. */
- if (HOST_BITS_PER_WIDE_INT % 3 != 0)
- {
- const int n_leftover_bits = HOST_BITS_PER_WIDE_INT % 3;
- const int n_bits_from_high = 3 - n_leftover_bits;
-
- const unsigned HOST_WIDE_INT
- low_mask = (((unsigned HOST_WIDE_INT)1) << n_leftover_bits) - 1;
- const unsigned HOST_WIDE_INT
- high_mask = (((unsigned HOST_WIDE_INT)1) << n_bits_from_high) - 1;
-
- unsigned int digit;
-
- /* At this point, only the bottom n_leftover_bits bits of low
- should be set. */
- gcc_assert (!(low & ~low_mask));
-
- digit = (low | ((high & high_mask) << n_leftover_bits));
- high >>= n_bits_from_high;
-
- *--p = '0' + digit;
- }
-
- /* Now we can format high in the normal manner. However, if
- the only bits of high that were set were handled by the
- digit split between low and high, high will now be zero, and
- we don't want to print extra digits in that case. */
- if (high)
- NUMBER_FMT_LOOP (p, high, 8);
+ digit = wi::extract_uhwi (wi::to_wide (cst), prec - 1, 1);
+ stabstr_C ('0' + digit);
+ }
+ else if (res_pres == 2)
+ {
+ digit = wi::extract_uhwi (wi::to_wide (cst), prec - 2, 2);
+ stabstr_C ('0' + digit);
}
- obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+ prec -= res_pres;
+ for (i = prec - 3; i >= 0; i = i - 3)
+ {
+ digit = wi::extract_uhwi (wi::to_wide (cst), i, 3);
+ stabstr_C ('0' + digit);
+ }
}
/* Called whenever it is safe to break a stabs string into multiple
/* 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
/* By convention, GCC will mark the end of a function with an N_FUN
symbol and an empty string. */
- if (flag_reorder_blocks_and_partition)
+ 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
{
get_lang_number (void)
{
const char *language_string = lang_hooks.name;
-
- if (strcmp (language_string, "GNU C") == 0)
+ if (lang_GNU_C ())
return N_SO_C;
- else if (strcmp (language_string, "GNU C++") == 0)
+ else if (lang_GNU_CXX ())
return N_SO_CC;
else if (strcmp (language_string, "GNU F77") == 0)
return N_SO_FORTRAN;
- else if (strcmp (language_string, "GNU Fortran") == 0)
+ else if (lang_GNU_Fortran ())
return N_SO_FORTRAN90; /* CHECKME */
- else if (strcmp (language_string, "GNU Pascal") == 0)
- return N_SO_PASCAL;
else if (strcmp (language_string, "GNU Objective-C") == 0)
return N_SO_OBJC;
else if (strcmp (language_string, "GNU Objective-C++") == 0)
const char *mapped_name;
typevec_len = 100;
- typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
+ typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
/* stabstr_ob contains one string, which will be just fine with
1-byte alignment. */
#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. */
function scope */
static void
-dbxout_begin_prologue (unsigned int lineno, const char *filename)
+dbxout_begin_prologue (unsigned int lineno,
+ unsigned int column ATTRIBUTE_UNUSED,
+ const char *filename)
{
if (use_gnu_debug_info_extensions
&& !NO_DBX_FUNCTION_END
/* pre-increment the scope counter */
scope_labelno++;
- dbxout_source_line (lineno, filename, 0, true);
+ dbxout_source_line (lineno, 0, filename, 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 ();
number LINENO. */
static void
-dbxout_source_line (unsigned int lineno, const char *filename,
- int discriminator ATTRIBUTE_UNUSED,
+dbxout_source_line (unsigned int lineno, unsigned int column ATTRIBUTE_UNUSED,
+ const char *filename, int discriminator ATTRIBUTE_UNUSED,
bool is_stmt ATTRIBUTE_UNUSED)
{
dbxout_source_file (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);
}
#endif /* DBX_DEBUGGING_INFO */
+static void
+dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+{
+ /* NYI for non-dwarf. */
+}
+
/* Debug information for a global DECL. Called from toplev.c after
compilation proper has finished. */
static void
-dbxout_global_decl (tree decl)
+dbxout_late_global_decl (tree decl)
{
- if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
+ if (VAR_P (decl) && !DECL_EXTERNAL (decl))
{
int saved_tree_used = TREE_USED (decl);
TREE_USED (decl) = 1;
/* Omit here local type decls until we know how to support them. */
if (TREE_CODE (tem) == TYPE_DECL
+ || TREE_CODE (tem) == TEMPLATE_DECL
+ /* Member functions emitted after fields. */
+ || TREE_CODE (tem) == FUNCTION_DECL
/* Omit here the nameless fields that are used to skip bits. */
|| DECL_IGNORED_P (tem)
/* Omit fields whose position or size are variable or too large to
&& DECL_BIT_FIELD_TYPE (tem))
? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0);
- if (TREE_CODE (tem) == VAR_DECL)
+ if (VAR_P (tem))
{
if (TREE_STATIC (tem) && use_gnu_debug_info_extensions)
{
stabstr_C (',');
stabstr_D (int_bit_position (tem));
stabstr_C (',');
- stabstr_D (tree_low_cst (DECL_SIZE (tem), 1));
+ stabstr_D (tree_to_uhwi (DECL_SIZE (tem)));
stabstr_C (';');
}
}
if (DECL_VINDEX (decl) && tree_fits_shwi_p (DECL_VINDEX (decl)))
{
- stabstr_D (tree_low_cst (DECL_VINDEX (decl), 0));
+ stabstr_D (tree_to_shwi (DECL_VINDEX (decl)));
stabstr_C (';');
dbxout_type (DECL_CONTEXT (decl), 0);
stabstr_C (';');
}
}
\f
-/* Subroutine of `dbxout_type'. Output debug info about the methods defined
- in TYPE. */
+/* Subroutine of `dbxout_type'. Output debug info about the member
+ functions defined in TYPE. */
static void
dbxout_type_methods (tree type)
{
- /* C++: put out the method names and their parameter lists */
- tree methods = TYPE_METHODS (type);
- tree fndecl;
- tree last;
-
- if (methods == NULL_TREE)
- return;
-
- if (TREE_CODE (methods) != TREE_VEC)
- fndecl = methods;
- else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
- fndecl = TREE_VEC_ELT (methods, 0);
- else
- fndecl = TREE_VEC_ELT (methods, 1);
-
- while (fndecl)
+ for (tree fndecl = TYPE_FIELDS (type); fndecl;)
{
int need_prefix = 1;
/* Group together all the methods for the same operation.
These differ in the types of the arguments. */
- for (last = NULL_TREE;
+ for (tree last = NULL_TREE;
fndecl && (last == NULL_TREE || DECL_NAME (fndecl) == DECL_NAME (last));
fndecl = DECL_CHAIN (fndecl))
/* Output the name of the field (after overloading), as
well as the name of the field before overloading, along
with its parameter list */
{
- /* Skip methods that aren't FUNCTION_DECLs. (In C++, these
- include TEMPLATE_DECLs.) The debugger doesn't know what
- to do with such entities anyhow. */
+ /* Skip non-functions. */
if (TREE_CODE (fndecl) != FUNCTION_DECL)
continue;
- CONTIN;
-
- last = fndecl;
-
/* Also ignore abstract methods; those are only interesting to
the DWARF backends. */
- if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl))
+ if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT_P (fndecl))
continue;
+ CONTIN;
+
+ last = fndecl;
+
/* Redundantly output the plain name, since that's what gdb
expects. */
if (need_prefix)
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
if (print_int_cst_bounds_in_octal_p (type, low, high))
stabstr_O (low);
else
- stabstr_D (tree_low_cst (low, 0));
+ stabstr_D (tree_to_shwi (low));
}
else
stabstr_C ('0');
if (print_int_cst_bounds_in_octal_p (type, low, high))
stabstr_O (high);
else
- stabstr_D (tree_low_cst (high, 0));
+ stabstr_D (tree_to_shwi (high));
stabstr_C (';');
}
else
another type's definition; instead, output an xref
and let the definition come when the name is defined. */
stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
- if (TYPE_NAME (type) != 0
- /* The C frontend creates for anonymous variable length
- records/unions TYPE_NAME with DECL_NAME NULL. */
- && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
- || DECL_NAME (TYPE_NAME (type))))
- dbxout_type_name (type);
+ if (TYPE_IDENTIFIER (type))
+ {
+ /* Note that the C frontend creates for anonymous variable
+ length records/unions TYPE_NAME with DECL_NAME NULL. */
+ dbxout_type_name (type);
+ }
else
{
stabstr_S ("$$");
access == access_protected_node
? '1' :'0');
if (BINFO_VIRTUAL_P (child)
- && (strcmp (lang_hooks.name, "GNU C++") == 0
+ && (lang_GNU_CXX ()
|| strcmp (lang_hooks.name, "GNU Objective-C++") == 0))
/* For a virtual base, print the (negative)
offset within the vtable where we must look
to find the necessary adjustment. */
stabstr_D
- (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
+ (tree_to_shwi (BINFO_VPTR_FIELD (child))
* BITS_PER_UNIT);
else
- stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
+ stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
* BITS_PER_UNIT);
stabstr_C (',');
dbxout_type (BINFO_TYPE (child), 0);
stabstr_C (':');
dbxout_type (BINFO_TYPE (child), full);
stabstr_C (',');
- stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
+ stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
* BITS_PER_UNIT);
stabstr_C (',');
stabstr_D
- (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)), 0)
+ (tree_to_shwi (TYPE_SIZE (BINFO_TYPE (child)))
* BITS_PER_UNIT);
stabstr_C (';');
}
/* Write out the field declarations. */
dbxout_type_fields (type);
- if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
- {
- dbxout_type_methods (type);
- }
+ if (use_gnu_debug_info_extensions)
+ dbxout_type_methods (type);
stabstr_C (';');
if (TREE_CODE (value) == CONST_DECL)
value = DECL_INITIAL (value);
- if (TREE_INT_CST_HIGH (value) == 0)
- stabstr_D (TREE_INT_CST_LOW (value));
- else if (TREE_INT_CST_HIGH (value) == -1
- && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
+ if (cst_and_fits_in_hwi (value))
stabstr_D (TREE_INT_CST_LOW (value));
else
stabstr_O (value);
break;
default:
+ /* A C++ function with deduced return type can have a TEMPLATE_TYPE_PARM
+ named 'auto' in its type.
+ No debug info for TEMPLATE_TYPE_PARM type supported yet. */
+ if (lang_GNU_CXX ())
+ {
+ tree name = TYPE_IDENTIFIER (type);
+ if (name == get_identifier ("auto")
+ || name == get_identifier ("decltype(auto)"))
+ break;
+ }
+
gcc_unreachable ();
}
}
stabstr_I (t);
}
-/* Output leading leading struct or class names needed for qualifying
- type whose scope is limited to a struct or class. */
+/* Output leading struct or class names needed for qualifying type
+ whose scope is limited to a struct or class. */
static void
dbxout_class_name_qualifiers (tree decl)
/* If this is a var that might not be actually output,
return NULL, otherwise stabs might reference an undefined
symbol. */
- struct varpool_node *node = varpool_get_node (expr);
+ varpool_node *node = varpool_node::get (expr);
if (!node || !node->definition)
return NULL;
}
case ARRAY_RANGE_REF:
case BIT_FIELD_REF:
{
- enum machine_mode mode;
- HOST_WIDE_INT bitsize, bitpos;
+ machine_mode mode;
+ poly_int64 bitsize, bitpos;
tree offset, tem;
- int volatilep = 0, unsignedp = 0;
+ int unsignedp, reversep, volatilep = 0;
rtx x;
- tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, true);
+ tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep);
x = dbxout_expand_expr (tem);
if (x == NULL || !MEM_P (x))
{
if (!tree_fits_shwi_p (offset))
return NULL;
- x = adjust_address_nv (x, mode, tree_low_cst (offset, 0));
+ 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;
}
/* Helper function for output_used_types. Queue one entry from the
used types hash to be output. */
-static int
-output_used_types_helper (void **slot, void *data)
+bool
+output_used_types_helper (tree const &type, vec<tree> *types_p)
{
- tree type = (tree) *slot;
- vec<tree> *types_p = (vec<tree> *) data;
-
if ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
types_p->quick_push (TYPE_NAME (type));
- return 1;
+ return true;
}
/* This is a qsort callback which sorts types and declarations into a
int i;
tree type;
- types.create (htab_elements (cfun->used_types_hash));
- htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
+ types.create (cfun->used_types_hash->elements ());
+ cfun->used_types_hash->traverse<vec<tree> *, output_used_types_helper>
+ (&types);
/* Sort by UID to prevent dependence on hash table ordering. */
types.qsort (output_types_sort);
if (flag_debug_only_used_symbols
&& (!TREE_USED (decl)
- && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl))))
+ && (!VAR_P (decl) || !DECL_INITIAL (decl))))
DBXOUT_DECR_NESTING_AND_RETURN (0);
/* If dbxout_init has not yet run, queue this symbol for later. */
/* 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)))
{
- tree name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
+ tree name = TYPE_IDENTIFIER (type);
dbxout_begin_complex_stabs ();
stabstr_I (name);
This is what represents `struct foo' with no typedef. */
/* In C++, the name of a type is the corresponding typedef.
In C, it is an IDENTIFIER_NODE. */
- tree name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
+ tree name = TYPE_IDENTIFIER (type);
dbxout_begin_complex_stabs ();
stabstr_I (name);
/* PARM_DECLs go in their own separate chain and are output by
dbxout_reg_parms and dbxout_parms, except for those that are
disguised VAR_DECLs like Out parameters in Ada. */
- gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ gcc_assert (VAR_P (decl));
- /* ... fall through ... */
+ /* fall through */
case RESULT_DECL:
case VAR_DECL:
if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
{
- HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
+ HOST_WIDE_INT ival = tree_to_shwi (DECL_INITIAL (decl));
dbxout_begin_complex_stabs ();
dbxout_symbol_name (decl, NULL, 'c');
if (!decl_rtl)
DBXOUT_DECR_NESTING_AND_RETURN (0);
- decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX);
+ if (!is_global_var (decl))
+ decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX);
#ifdef LEAF_REG_REMAP
if (crtl->uses_only_leaf_regs)
leaf_renumber_regs_insn (decl_rtl);
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;
we rely on the fact that error_mark_node initializers always
end up in bss for C++ and never end up in bss for C. */
if (DECL_INITIAL (decl) == 0
- || (!strcmp (lang_hooks.name, "GNU C++")
+ || (lang_GNU_CXX ()
&& DECL_INITIAL (decl) == error_mark_node))
{
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
{
??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs
for thread-local symbols. Can be handled via same mechanism as used
in dwarf2out.c. */
- if (TREE_CODE (decl) != VAR_DECL
+ if (!VAR_P (decl)
|| !TREE_STATIC (decl)
|| !DECL_HAS_VALUE_EXPR_P (decl)
|| DECL_THREAD_LOCAL_P (decl)
{
++debug_nesting;
emit_pending_bincls_if_required ();
+ fixed_size_mode rtl_mode, type_mode;
for (; parms; parms = DECL_CHAIN (parms))
if (DECL_NAME (parms)
&& TREE_TYPE (parms) != error_mark_node
&& DECL_RTL_SET_P (parms)
- && DECL_INCOMING_RTL (parms))
+ && DECL_INCOMING_RTL (parms)
+ /* We can't represent variable-sized types in this format. */
+ && is_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (parms)), &type_mode)
+ && is_a <fixed_size_mode> (GET_MODE (DECL_RTL (parms)), &rtl_mode))
{
tree eff_type;
char letter;
/* Make a big endian correction if the mode of the type of the
parameter is not the same as the mode of the rtl. */
if (BYTES_BIG_ENDIAN
- && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
- && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
- number += (GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
- - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))));
+ && type_mode != rtl_mode
+ && GET_MODE_SIZE (type_mode) < UNITS_PER_WORD)
+ number += GET_MODE_SIZE (rtl_mode) - GET_MODE_SIZE (type_mode);
}
else
/* ??? We don't know how to represent this argument. */
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.