/* Output dbx-format symbol table information from GNU compiler.
- Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-
+#include "alias.h"
#include "tree.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "stor-layout.h"
#include "rtl.h"
#include "flags.h"
#include "regs.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 "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
+#include "cgraph.h"
+#include "stringpool.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
#endif
-#define DBXOUT_DECR_NESTING \
- if (--debug_nesting == 0 && symbol_queue_index > 0) \
- { emit_pending_bincls_if_required (); debug_flush_symbol_queue (); }
-
-#define DBXOUT_DECR_NESTING_AND_RETURN(x) \
- do {--debug_nesting; return (x);} while (0)
-
#ifndef ASM_STABS_OP
# ifdef XCOFF_DEBUGGING_INFO
# define ASM_STABS_OP "\t.stabx\t"
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);
\f
/* The debug hooks structure. */
#if defined (DBX_DEBUGGING_INFO)
dbxout_init,
dbxout_finish,
debug_nothing_void,
+ debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
dbxout_start_source_file,
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, /* 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_void, /* switch_text_section */
- debug_nothing_tree, /* direct_call */
- debug_nothing_tree_int, /* virtual_call_token */
- debug_nothing_rtx_rtx, /* copy_call_info */
- debug_nothing_uid, /* virtual_call */
debug_nothing_tree_tree, /* set_name */
- 0 /* start_end_main_source_file */
+ 0, /* start_end_main_source_file */
+ TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */
};
#endif /* DBX_DEBUGGING_INFO */
dbxout_init,
dbxout_finish,
debug_nothing_void,
+ debug_nothing_void,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
dbxout_start_source_file,
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, /* 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_void, /* switch_text_section */
- debug_nothing_tree, /* direct_call */
- debug_nothing_tree_int, /* virtual_call_token */
- debug_nothing_rtx_rtx, /* copy_call_info */
- debug_nothing_uid, /* virtual_call */
debug_nothing_tree_tree, /* set_name */
- 0 /* start_end_main_source_file */
+ 0, /* start_end_main_source_file */
+ TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */
};
#endif /* XCOFF_DEBUGGING_INFO */
\f
#define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr)
/* Add STR, a normal C string, to the string being built. */
-#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen(str))
+#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen (str))
/* Add the text of ID, an IDENTIFIER_NODE, to the string being built. */
#define stabstr_I(id) obstack_grow (&stabstr_ob, \
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_WIDE_INT * 2)
- ;
- 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::eq_p (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 (cst, prec - 1, 1);
+ stabstr_C ('0' + digit);
+ }
+ else if (res_pres == 2)
+ {
+ digit = wi::extract_uhwi (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 (cst, i, 3);
+ stabstr_C ('0' + digit);
+ }
}
/* Called whenever it is safe to break a stabs string into multiple
obstack_free (&stabstr_ob, str);
}
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+
+/* When -gused is used, emit debug info for only used symbols. But in
+ addition to the standard intercepted debug_hooks there are some
+ direct calls into this file, i.e., dbxout_symbol, dbxout_parms, and
+ dbxout_reg_params. Those routines may also be called from a higher
+ level intercepted routine. So to prevent recording data for an inner
+ call to one of these for an intercept, we maintain an intercept
+ nesting counter (debug_nesting). We only save the intercepted
+ arguments if the nesting is 1. */
+static int debug_nesting = 0;
+
+static tree *symbol_queue;
+static int symbol_queue_index = 0;
+static int symbol_queue_size = 0;
+
+#define DBXOUT_DECR_NESTING \
+ if (--debug_nesting == 0 && symbol_queue_index > 0) \
+ { emit_pending_bincls_if_required (); debug_flush_symbol_queue (); }
+
+#define DBXOUT_DECR_NESTING_AND_RETURN(x) \
+ do {--debug_nesting; return (x);} while (0)
+
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+
#if defined (DBX_DEBUGGING_INFO)
static void
named sections. */
if (!use_gnu_debug_info_extensions
|| NO_DBX_FUNCTION_END
- || !targetm.have_named_sections)
+ || !targetm_common.have_named_sections)
return;
/* By convention, GCC will mark the end of a function with an N_FUN
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;
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. */
#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))
{
}
\f
+/* Generate the symbols for any queued up type symbols we encountered
+ while generating the type info for some originally used symbol.
+ This might generate additional entries in the queue. Only when
+ the nesting depth goes to 0 is this routine called. */
+
+static void
+debug_flush_symbol_queue (void)
+{
+ int i;
+
+ /* Make sure that additionally queued items are not flushed
+ prematurely. */
+
+ ++debug_nesting;
+
+ for (i = 0; i < symbol_queue_index; ++i)
+ {
+ /* If we pushed queued symbols then such symbols must be
+ output no matter what anyone else says. Specifically,
+ we need to make sure dbxout_symbol() thinks the symbol was
+ used and also we need to override TYPE_DECL_SUPPRESS_DEBUG
+ which may be set for outside reasons. */
+ int saved_tree_used = TREE_USED (symbol_queue[i]);
+ int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]);
+ TREE_USED (symbol_queue[i]) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0;
+#ifdef DBX_DEBUGGING_INFO
+ dbxout_symbol (symbol_queue[i], 0);
+#endif
+
+ TREE_USED (symbol_queue[i]) = saved_tree_used;
+ TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug;
+ }
+
+ symbol_queue_index = 0;
+ --debug_nesting;
+}
+
+/* Queue a type symbol needed as part of the definition of a decl
+ symbol. These symbols are generated when debug_flush_symbol_queue()
+ is called. */
+
+static void
+debug_queue_symbol (tree decl)
+{
+ if (symbol_queue_index >= symbol_queue_size)
+ {
+ symbol_queue_size += 10;
+ symbol_queue = XRESIZEVEC (tree, symbol_queue, symbol_queue_size);
+ }
+
+ symbol_queue[symbol_queue_index++] = decl;
+}
+
+/* Free symbol queue. */
+static void
+debug_free_queue (void)
+{
+ if (symbol_queue)
+ {
+ free (symbol_queue);
+ symbol_queue = NULL;
+ symbol_queue_size = 0;
+ }
+}
+\f
/* Used in several places: evaluates to '0' for a private decl,
'1' for a protected decl, '2' for a public decl. */
#define DECL_ACCESSIBILITY_CHAR(DECL) \
{
/* If one of the nodes is an error_mark or its type is then
return early. */
- if (tem == error_mark_node || TREE_TYPE (tem) == error_mark_node)
+ if (error_operand_p (tem))
return;
/* Omit here local type decls until we know how to support them. */
/* Omit fields whose position or size are variable or too large to
represent. */
|| (TREE_CODE (tem) == FIELD_DECL
- && (! host_integerp (bit_position (tem), 0)
+ && (! tree_fits_shwi_p (bit_position (tem))
|| ! DECL_SIZE (tem)
- || ! host_integerp (DECL_SIZE (tem), 1))))
+ || ! tree_fits_uhwi_p (DECL_SIZE (tem)))))
continue;
else if (TREE_CODE (tem) != CONST_DECL)
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 (';');
}
}
stabstr_C (c1);
stabstr_C (c2);
- if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0))
+ 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 (';');
/* 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;
/* Redundantly output the plain name, since that's what gdb
}
stabstr_C (';');
- if (low && host_integerp (low, 0))
+ if (low && tree_fits_shwi_p (low))
{
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');
stabstr_C (';');
- if (high && host_integerp (high, 0))
+ if (high && tree_fits_shwi_p (high))
{
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
dbxout_type (tree type, int full)
{
static int anonymous_type_number = 0;
- bool vector_type = false;
tree tem, main_variant, low, high;
- if (TREE_CODE (type) == VECTOR_TYPE)
- {
- /* The frontend feeds us a representation for the vector as a struct
- containing an array. Pull out the array type. */
- type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
- vector_type = true;
- }
-
if (TREE_CODE (type) == INTEGER_TYPE)
{
if (TREE_TYPE (type) == 0)
Sun dbx crashes if we do. */
if (! full || !COMPLETE_TYPE_P (type)
/* No way in DBX fmt to describe a variable size. */
- || ! host_integerp (TYPE_SIZE (type), 1))
+ || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
return;
break;
case TYPE_DEFINED:
&& !full)
|| !COMPLETE_TYPE_P (type)
/* No way in DBX fmt to describe a variable size. */
- || ! host_integerp (TYPE_SIZE (type), 1))
+ || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
{
typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
return;
switch (TREE_CODE (type))
{
case VOID_TYPE:
+ case NULLPTR_TYPE:
case LANG_TYPE:
/* For a void type, just define it as itself; i.e., "5=5".
This makes us consider it defined
break;
}
- if (use_gnu_debug_info_extensions && vector_type)
- stabstr_S ("@V;");
-
/* Output "a" followed by a range type definition
for the index type of the array
followed by a reference to the target-type.
dbxout_type (TREE_TYPE (type), 0);
break;
+ case VECTOR_TYPE:
+ /* Make vectors look like an array. */
+ if (use_gnu_debug_info_extensions)
+ stabstr_S ("@V;");
+
+ /* Output "a" followed by a range type definition
+ for the index type of the array
+ followed by a reference to the target-type.
+ ar1;0;N;M for a C array of type M and size N+1. */
+ stabstr_C ('a');
+ dbxout_range_type (integer_type_node, size_zero_node,
+ size_int (TYPE_VECTOR_SUBPARTS (type) - 1));
+
+ dbxout_type (TREE_TYPE (type), 0);
+ break;
+
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
&& !full)
|| !COMPLETE_TYPE_P (type)
/* No way in DBX fmt to describe a variable size. */
- || ! host_integerp (TYPE_SIZE (type), 1))
+ || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
{
/* If the type is just a cross reference, output one
and mark the type as partially described.
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 ("$$");
{
int i;
tree child;
- VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
+ vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (binfo);
if (use_gnu_debug_info_extensions)
{
}
for (i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++)
{
- tree access = (accesses ? VEC_index (tree, accesses, i)
- : access_public_node);
+ tree access = (accesses ? (*accesses)[i] : access_public_node);
if (use_gnu_debug_info_extensions)
{
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 (';');
}
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);
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.
+ 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)
tree context = decl_type_context (decl);
if (context != NULL_TREE
- && TREE_CODE(context) == RECORD_TYPE
+ && TREE_CODE (context) == RECORD_TYPE
&& TYPE_NAME (context) != 0
&& (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
|| (DECL_NAME (TYPE_NAME (context)) != 0)))
disable debug info for these variables. */
if (!targetm.have_tls && DECL_THREAD_LOCAL_P (expr))
return NULL;
+ if (TREE_STATIC (expr)
+ && !TREE_ASM_WRITTEN (expr)
+ && !DECL_HAS_VALUE_EXPR_P (expr)
+ && !TREE_PUBLIC (expr)
+ && DECL_RTL_SET_P (expr)
+ && MEM_P (DECL_RTL (expr)))
+ {
+ /* If this is a var that might not be actually output,
+ return NULL, otherwise stabs might reference an undefined
+ symbol. */
+ varpool_node *node = varpool_node::get (expr);
+ if (!node || !node->definition)
+ return NULL;
+ }
/* FALLTHRU */
case PARM_DECL:
+ case RESULT_DECL:
if (DECL_HAS_VALUE_EXPR_P (expr))
return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
/* FALLTHRU */
case CONST_DECL:
- case RESULT_DECL:
return DECL_RTL_IF_SET (expr);
case INTEGER_CST:
case ARRAY_RANGE_REF:
case BIT_FIELD_REF:
{
- enum machine_mode mode;
+ machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
tree offset, tem;
int volatilep = 0, unsignedp = 0;
return NULL;
if (offset != NULL)
{
- if (!host_integerp (offset, 0))
+ 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);
/* 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, heap) **types_p = (VEC(tree, heap) **) data;
-
if ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE
&& TYPE_STUB_DECL (type)
&& DECL_P (TYPE_STUB_DECL (type))
&& ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
- VEC_quick_push (tree, *types_p, TYPE_STUB_DECL (type));
+ types_p->quick_push (TYPE_STUB_DECL (type));
else if (TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
- VEC_quick_push (tree, *types_p, TYPE_NAME (type));
+ types_p->quick_push (TYPE_NAME (type));
- return 1;
+ return true;
}
/* This is a qsort callback which sorts types and declarations into a
{
if (cfun && cfun->used_types_hash)
{
- VEC(tree, heap) *types;
+ vec<tree> types;
int i;
tree type;
- types = VEC_alloc (tree, heap, 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. */
- qsort (VEC_address (tree, types), VEC_length (tree, types),
- sizeof (tree), output_types_sort);
+ types.qsort (output_types_sort);
- for (i = 0; VEC_iterate (tree, types, i, type); i++)
+ FOR_EACH_VEC_ELT (types, i, type)
debug_queue_symbol (type);
- VEC_free (tree, heap, types);
+ types.release ();
}
}
/* Do not generate a tag for records of variable size,
since this type can not be properly described in the
DBX format, and it confuses some tools such as objdump. */
- && host_integerp (TYPE_SIZE (type), 1))
+ && 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);
??? Why do we skip emitting the type and location in this case? */
if (TREE_STATIC (decl) && TREE_READONLY (decl)
&& DECL_INITIAL (decl) != 0
- && host_integerp (DECL_INITIAL (decl), 0)
+ && tree_fits_shwi_p (DECL_INITIAL (decl))
&& ! TREE_ASM_WRITTEN (decl)
- && (DECL_CONTEXT (decl) == NULL_TREE
+ && (DECL_FILE_SCOPE_P (decl)
|| TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
|| TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
&& TREE_PUBLIC (decl) == 0)
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 (current_function_uses_only_leaf_regs)
+ if (crtl->uses_only_leaf_regs)
leaf_renumber_regs_insn (decl_rtl);
#endif
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return 0;
}
- home = alter_subreg (&home);
+ home = alter_subreg (&home, true);
}
if (REG_P (home))
{
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;
|| (REG_P (XEXP (home, 0))
&& REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
&& REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
-#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_ARG_POINTER
&& REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
#endif
)))
for thread-local symbols. Can be handled via same mechanism as used
in dwarf2out.c. */
if (TREE_CODE (decl) != VAR_DECL
- || !TREE_STATIC(decl)
- || !DECL_HAS_VALUE_EXPR_P(decl)
+ || !TREE_STATIC (decl)
+ || !DECL_HAS_VALUE_EXPR_P (decl)
|| DECL_THREAD_LOCAL_P (decl)
|| !is_fortran ())
return NULL;
if (CONST_INT_P (XEXP (sym_addr, 0)))
{
name =
- targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 1), 0));
+ targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 1), 0));
*value = INTVAL (XEXP (sym_addr, 0));
cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1));
}
else
{
name =
- targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 0), 0));
+ targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 0), 0));
*value = INTVAL (XEXP (sym_addr, 1));
cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0));
}
break;
case SYMBOL_REF:
- name = targetm.strip_name_encoding(XSTR (sym_addr, 0));
+ name = targetm.strip_name_encoding (XSTR (sym_addr, 0));
*value = 0;
cdecl = SYMBOL_REF_DECL (sym_addr);
break;
/* Check area common symbol is offset into. If this is not public, then
it is not a symbol in a common block. It must be a .lcomm symbol, not
a .comm symbol. */
- if (cdecl == NULL || !TREE_PUBLIC(cdecl))
+ if (cdecl == NULL || !TREE_PUBLIC (cdecl))
name = NULL;
}
else
SET_DECL_RTL (parms,
eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX));
#ifdef LEAF_REG_REMAP
- if (current_function_uses_only_leaf_regs)
+ if (crtl->uses_only_leaf_regs)
{
leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
leaf_renumber_regs_insn (DECL_RTL (parms));
&& REG_P (XEXP (DECL_RTL (parms), 0))
&& REGNO (XEXP (DECL_RTL (parms), 0)) != HARD_FRAME_POINTER_REGNUM
&& REGNO (XEXP (DECL_RTL (parms), 0)) != STACK_POINTER_REGNUM
-#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_ARG_POINTER
&& REGNO (XEXP (DECL_RTL (parms), 0)) != ARG_POINTER_REGNUM
#endif
)
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+/* Record an element in the table of global destructors. SYMBOL is
+ a SYMBOL_REF of the function to be called; PRIORITY is a number
+ between 0 and MAX_INIT_PRIORITY. */
+
+void
+default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED,
+ int priority ATTRIBUTE_UNUSED)
+{
+#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
+ /* Tell GNU LD that this is part of the static destructor set.
+ This will work for any system that uses stabs, most usefully
+ aout systems. */
+ dbxout_begin_simple_stabs ("___DTOR_LIST__", 22 /* N_SETT */);
+ dbxout_stab_value_label (XSTR (symbol, 0));
+#else
+ sorry ("global destructors not supported on this target");
+#endif
+}
+
+/* Likewise for global constructors. */
+
+void
+default_stabs_asm_out_constructor (rtx symbol ATTRIBUTE_UNUSED,
+ int priority ATTRIBUTE_UNUSED)
+{
+#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
+ /* Tell GNU LD that this is part of the static destructor set.
+ This will work for any system that uses stabs, most usefully
+ aout systems. */
+ dbxout_begin_simple_stabs ("___CTOR_LIST__", 22 /* N_SETT */);
+ dbxout_stab_value_label (XSTR (symbol, 0));
+#else
+ sorry ("global constructors not supported on this target");
+#endif
+}
+
#include "gt-dbxout.h"