#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "target.h"
+#include "function.h"
#include "rtl.h"
-#include "alias.h"
#include "tree.h"
-#include "fold-const.h"
+#include "tm_p.h"
#include "stringpool.h"
+#include "insn-config.h"
+#include "ira.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
#include "stor-layout.h"
#include "varasm.h"
-#include "function.h"
-#include "emit-rtl.h"
#include "version.h"
#include "flags.h"
-#include "regs.h"
#include "rtlhash.h"
-#include "insn-config.h"
#include "reload.h"
#include "output.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "stmt.h"
#include "expr.h"
-#include "except.h"
-#include "dwarf2.h"
#include "dwarf2out.h"
#include "dwarf2asm.h"
#include "toplev.h"
#include "md5.h"
-#include "tm_p.h"
-#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "debug.h"
-#include "target.h"
#include "common/common-target.h"
#include "langhooks.h"
-#include "cgraph.h"
-#include "ira.h"
#include "lra.h"
#include "dumpfile.h"
#include "opts.h"
static rtx_insn *cached_next_real_insn;
static void dwarf2out_decl (tree);
+#ifndef XCOFF_DEBUGGING_INFO
+#define XCOFF_DEBUGGING_INFO 0
+#endif
+
+#ifndef HAVE_XCOFF_DWARF_EXTRAS
+#define HAVE_XCOFF_DWARF_EXTRAS 0
+#endif
+
#ifdef VMS_DEBUGGING_INFO
int vms_file_stats_name (const char *, long long *, long *, char *, int *);
#endif
/* Get the number of HOST_WIDE_INTs needed to represent the precision
- of the number. */
+ of the number. Some constants have a large uniform precision, so
+ we get the precision needed for the actual value of the number. */
static unsigned int
get_full_len (const wide_int &op)
{
- return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
+ int prec = wi::min_precision (op, UNSIGNED);
+ return ((prec + HOST_BITS_PER_WIDE_INT - 1)
/ HOST_BITS_PER_WIDE_INT);
}
for collect2 the first time around. */
static void
-switch_to_eh_frame_section (bool back)
+switch_to_eh_frame_section (bool back ATTRIBUTE_UNUSED)
{
- tree label;
-
-#ifdef EH_FRAME_SECTION_NAME
if (eh_frame_section == 0)
{
int flags;
}
else
flags = SECTION_WRITE;
+
+#ifdef EH_FRAME_SECTION_NAME
eh_frame_section = get_section (EH_FRAME_SECTION_NAME, flags, NULL);
- }
+#else
+ eh_frame_section = ((flags == SECTION_WRITE)
+ ? data_section : readonly_data_section);
#endif /* EH_FRAME_SECTION_NAME */
+ }
- if (eh_frame_section)
- switch_to_section (eh_frame_section);
- else
- {
- /* We have no special eh_frame section. Put the information in
- the data section and emit special labels to guide collect2. */
- switch_to_section (data_section);
+ switch_to_section (eh_frame_section);
- if (!back)
- {
- label = get_file_function_name ("F");
- ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
- targetm.asm_out.globalize_label (asm_out_file,
- IDENTIFIER_POINTER (label));
- ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
- }
+#ifdef EH_FRAME_THROUGH_COLLECT2
+ /* We have no special eh_frame section. Emit special labels to guide
+ collect2. */
+ if (!back)
+ {
+ tree label = get_file_function_name ("F");
+ ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
+ targetm.asm_out.globalize_label (asm_out_file,
+ IDENTIFIER_POINTER (label));
+ ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
}
+#endif
}
/* Switch [BACK] to the eh or debug frame table section, depending on
for_eh + j);
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + j);
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
- dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
- " indicating 64-bit DWARF extension");
- dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
- "FDE Length");
+ if (!XCOFF_DEBUGGING_INFO || for_eh)
+ {
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+ dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
+ " indicating 64-bit DWARF extension");
+ dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+ "FDE Length");
+ }
ASM_OUTPUT_LABEL (asm_out_file, l1);
if (for_eh)
/* Output the CIE. */
ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
- dw2_asm_output_data (4, 0xffffffff,
- "Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
- "Length of Common Information Entry");
+ if (!XCOFF_DEBUGGING_INFO || for_eh)
+ {
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating 64-bit DWARF extension");
+ dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
+ "Length of Common Information Entry");
+ }
ASM_OUTPUT_LABEL (asm_out_file, l1);
/* Now that the CIE pointer is PC-relative for EH,
/* True if .debug_macinfo or .debug_macros section is going to be
emitted. */
#define have_macinfo \
- (debug_info_level >= DINFO_LEVEL_VERBOSE \
+ ((!XCOFF_DEBUGGING_INFO || HAVE_XCOFF_DWARF_EXTRAS) \
+ && debug_info_level >= DINFO_LEVEL_VERBOSE \
&& !macinfo_table->is_empty ())
/* Array of dies for which we should generate .debug_ranges info. */
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, va_gc> *);
-static void output_aranges (unsigned long);
+static void output_aranges (void);
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 *,
static void insert_wide_int (const wide_int &, unsigned char *, int);
static void insert_float (const_rtx, unsigned char *);
static rtx rtl_for_decl_location (tree);
-static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool,
- enum dwarf_attribute);
+static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool);
static bool tree_add_const_value_attribute (dw_die_ref, tree);
static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die)
{
dw_attr_node attr;
+ gcc_checking_assert (targ_die != NULL);
-#ifdef ENABLE_CHECKING
- gcc_assert (targ_die != NULL);
-#else
/* With LTO we can end up trying to reference something we didn't create
a DIE for. Avoid crashing later on a NULL referenced DIE. */
if (targ_die == NULL)
return;
-#endif
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_die_ref;
{
dw_attr_node attr;
+ if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS)
+ return;
+
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_loc_list;
attr.dw_attr_val.val_entry = NULL;
&& TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
{
HOST_WIDE_INT maxsize;
- tree innerdecl;
- innerdecl
- = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
+ bool reverse;
+ tree innerdecl
+ = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize,
+ &reverse);
if (!DECL_P (innerdecl)
|| DECL_IGNORED_P (innerdecl)
|| TREE_STATIC (innerdecl)
print_die (comp_unit_die (), stderr);
}
-#ifdef ENABLE_CHECKING
/* Sanity checks on DIEs. */
static void
&& a->dw_attr != DW_AT_GNU_all_call_sites);
}
}
-#endif
\f
/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU
for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL
{
dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
"%s", name);
- name = NULL;
+ name = "";
}
else
for (i = 0; i < len; ++i)
{
dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
"%s", name);
- name = NULL;
+ name = "";
}
}
break;
DWARFv5 draft DIE tags in DWARFv4 format. */
int ver = dwarf_version < 5 ? dwarf_version : 4;
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
- dw2_asm_output_data (4, 0xffffffff,
- "Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE,
- next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
- "Length of Compilation Unit Info");
+ if (!XCOFF_DEBUGGING_INFO)
+ {
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating 64-bit DWARF extension");
+ dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
+ "Length of Compilation Unit Info");
+ }
+
dw2_asm_output_data (2, ver, "DWARF version number");
dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
debug_abbrev_section,
unsigned long pubnames_length = size_of_pubnames (names);
pubname_entry *pub;
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
- dw2_asm_output_data (4, 0xffffffff,
- "Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Pub Info Length");
+ if (!XCOFF_DEBUGGING_INFO)
+ {
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating 64-bit DWARF extension");
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+ "Pub Info Length");
+ }
/* Version number for pubnames/pubtypes is independent of dwarf version. */
dw2_asm_output_data (2, 2, "DWARF Version");
text section generated for this compilation unit. */
static void
-output_aranges (unsigned long aranges_length)
+output_aranges (void)
{
unsigned i;
+ unsigned long aranges_length = size_of_aranges ();
+
+ if (!XCOFF_DEBUGGING_INFO)
+ {
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating 64-bit DWARF extension");
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
+ "Length of Address Ranges Info");
+ }
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
- dw2_asm_output_data (4, 0xffffffff,
- "Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
- "Length of Address Ranges Info");
/* Version number for aranges is still 2, even up to DWARF5. */
dw2_asm_output_data (2, 2, "DWARF Version");
if (dwarf_split_debug_info)
ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0);
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
- dw2_asm_output_data (4, 0xffffffff,
- "Initial length escape value indicating 64-bit DWARF extension");
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
- "Length of Source Line Info");
+ if (!XCOFF_DEBUGGING_INFO)
+ {
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating 64-bit DWARF extension");
+ dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ "Length of Source Line Info");
+ }
+
ASM_OUTPUT_LABEL (asm_out_file, l1);
dw2_asm_output_data (2, ver, "DWARF Version");
mod_type_die = d;
}
}
- else if (code == POINTER_TYPE)
- {
- mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type);
- add_AT_unsigned (mod_type_die, DW_AT_byte_size,
- simple_type_size_in_bits (type) / BITS_PER_UNIT);
- item_type = TREE_TYPE (type);
- if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
- add_AT_unsigned (mod_type_die, DW_AT_address_class,
- TYPE_ADDR_SPACE (item_type));
- }
- else if (code == REFERENCE_TYPE)
+ else if (code == POINTER_TYPE || code == REFERENCE_TYPE)
{
- if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
- mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope,
- type);
- else
- mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type);
+ dwarf_tag tag = DW_TAG_pointer_type;
+ if (code == REFERENCE_TYPE)
+ {
+ if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
+ tag = DW_TAG_rvalue_reference_type;
+ else
+ tag = DW_TAG_reference_type;
+ }
+ mod_type_die = new_die (tag, mod_scope, type);
+
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
simple_type_size_in_bits (type) / BITS_PER_UNIT);
item_type = TREE_TYPE (type);
- if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
- add_AT_unsigned (mod_type_die, DW_AT_address_class,
- TYPE_ADDR_SPACE (item_type));
+
+ addr_space_t as = TYPE_ADDR_SPACE (item_type);
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ int action = targetm.addr_space.debug (as);
+ if (action >= 0)
+ {
+ /* Positive values indicate an address_class. */
+ add_AT_unsigned (mod_type_die, DW_AT_address_class, action);
+ }
+ else
+ {
+ /* Negative values indicate an (inverted) segment base reg. */
+ dw_loc_descr_ref d
+ = one_reg_loc_descriptor (~action, VAR_INIT_STATUS_INITIALIZED);
+ add_AT_loc (mod_type_die, DW_AT_segment, d);
+ }
+ }
}
else if (code == INTEGER_TYPE
&& TREE_TYPE (type) != NULL_TREE
{
/* If delegitimize_address couldn't do anything with the UNSPEC, assume
we can't express it in the debug info. */
-#ifdef ENABLE_CHECKING
/* Don't complain about TLS UNSPECs, those are just too hard to
delegitimize. Note this could be a non-decl SYMBOL_REF such as
one in a constant pool entry, so testing SYMBOL_REF_TLS_MODEL
rather than DECL_THREAD_LOCAL_P is not just an optimization. */
- if (XVECLEN (rtl, 0) == 0
- || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
- || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE)
+ if (flag_checking
+ && (XVECLEN (rtl, 0) == 0
+ || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
+ || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE))
inform (current_function_decl
? DECL_SOURCE_LOCATION (current_function_decl)
: UNKNOWN_LOCATION,
#else
"non-delegitimized UNSPEC %d found in variable location",
XINT (rtl, 1));
-#endif
#endif
expansion_failed (NULL_TREE, rtl,
"UNSPEC hasn't been delegitimized.\n");
goto symref;
default:
-#ifdef ENABLE_CHECKING
- print_rtl (stderr, rtl);
- gcc_unreachable ();
-#else
+ if (flag_checking)
+ {
+ print_rtl (stderr, rtl);
+ gcc_unreachable ();
+ }
break;
-#endif
}
if (mem_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
machine_mode mode;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
obj = get_inner_reference (TREE_OPERAND (loc, 0),
&bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
STRIP_NOPS (obj);
if (bitpos % BITS_PER_UNIT)
{
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
machine_mode mode;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
gcc_assert (obj != loc);
return 0;
}
-#ifdef ENABLE_CHECKING
/* Otherwise this is a generic code; we should just lists all of
these explicitly. We forgot one. */
- gcc_unreachable ();
-#else
+ if (flag_checking)
+ gcc_unreachable ();
+
/* In a release build, we want to degrade gracefully: better to
generate incomplete debugging information than to crash. */
return NULL;
-#endif
}
if (!ret && !list_ret)
static void
insert_float (const_rtx rtl, unsigned char *array)
{
- REAL_VALUE_TYPE rv;
long val[4];
int i;
- REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
- real_to_target (val, &rv, GET_MODE (rtl));
+ real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), GET_MODE (rtl));
/* real_to_target puts 32-bit pieces in each long. Pack them. */
for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
return true;
case CONST_WIDE_INT:
- add_AT_wide (die, DW_AT_const_value,
- std::make_pair (rtl, GET_MODE (rtl)));
+ {
+ wide_int w1 = std::make_pair (rtl, MAX_MODE_INT);
+ unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED),
+ (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT);
+ wide_int w = wi::zext (w1, prec);
+ add_AT_wide (die, DW_AT_const_value, w);
+ }
return true;
case CONST_DOUBLE:
machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
/* If the decl isn't a VAR_DECL, or if it isn't static, or if
it does not have a value (the offset into the common area), or if it
if (TREE_CODE (val_expr) != COMPONENT_REF)
return NULL_TREE;
- cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, true);
+ cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep, true);
if (cvar == NULL_TREE
|| TREE_CODE (cvar) != VAR_DECL
since we will need to refer to them each time the function is inlined. */
static bool
-add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
- enum dwarf_attribute attr)
+add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p)
{
rtx rtl;
dw_loc_list_ref list;
var_loc_list *loc_list;
cached_dw_loc_list *cache;
+ if (early_dwarf)
+ return false;
+
if (TREE_CODE (decl) == ERROR_MARK)
return false;
- if (get_AT (die, attr))
+ if (get_AT (die, DW_AT_location)
+ || get_AT (die, DW_AT_const_value))
return true;
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
}
if (list)
{
- add_AT_location_description (die, attr, list);
+ add_AT_location_description (die, DW_AT_location, list);
return true;
}
/* None of that worked, so it must not really have a location;
equate_decl_number_to_die (node, parm_die);
if (! DECL_ABSTRACT_P (node_or_origin))
add_location_or_const_value_attribute (parm_die, node_or_origin,
- node == NULL, DW_AT_location);
+ node == NULL);
break;
compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
if (fun->static_chain_decl)
- add_AT_location_description
- (subr_die, DW_AT_static_link,
- loc_list_from_tree (fun->static_chain_decl, 2, NULL));
+ {
+ /* DWARF requires here a location expression that computes the
+ address of the enclosing subprogram's frame base. The machinery
+ in tree-nested.c is supposed to store this specific address in the
+ last field of the FRAME record. */
+ const tree frame_type
+ = TREE_TYPE (TREE_TYPE (fun->static_chain_decl));
+ const tree fb_decl = tree_last (TYPE_FIELDS (frame_type));
+
+ tree fb_expr
+ = build1 (INDIRECT_REF, frame_type, fun->static_chain_decl);
+ fb_expr = build3 (COMPONENT_REF, TREE_TYPE (fb_decl),
+ fb_expr, fb_decl, NULL_TREE);
+
+ add_AT_location_description (subr_die, DW_AT_static_link,
+ loc_list_from_tree (fb_expr, 0, NULL));
+ }
}
/* Generate child dies for template paramaters. */
rtx tloc = NULL_RTX, tlocc = NULL_RTX;
rtx arg, next_arg;
- for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note);
+ for (arg = (ca_loc->call_arg_loc_note != NULL_RTX
+ ? NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note)
+ : NULL_RTX);
arg; arg = next_arg)
{
dw_loc_descr_ref reg, val;
}
if (mode == VOIDmode || mode == BLKmode)
continue;
- if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
+ /* Get dynamic information about call target only if we
+ have no static information: we cannot generate both
+ DW_AT_abstract_origin and DW_AT_GNU_call_site_target
+ attributes. */
+ if (ca_loc->symbol_ref == NULL_RTX)
{
- gcc_assert (ca_loc->symbol_ref == NULL_RTX);
- tloc = XEXP (XEXP (arg, 0), 1);
- continue;
- }
- else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
- && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
- {
- gcc_assert (ca_loc->symbol_ref == NULL_RTX);
- tlocc = XEXP (XEXP (arg, 0), 1);
- continue;
+ if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
+ {
+ tloc = XEXP (XEXP (arg, 0), 1);
+ continue;
+ }
+ else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
+ && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+ {
+ tlocc = XEXP (XEXP (arg, 0), 1);
+ continue;
+ }
}
reg = NULL;
if (REG_P (XEXP (XEXP (arg, 0), 0)))
add_pubname (decl_or_origin, var_die);
else
add_location_or_const_value_attribute (var_die, decl_or_origin,
- decl == NULL, DW_AT_location);
+ decl == NULL);
}
else
tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
{
if (old_die)
{
-#ifdef ENABLE_CHECKING
/* This must have been generated early and it won't even
need location information since it's a DW_AT_inline
function. */
- for (dw_die_ref c = context_die; c; c = c->die_parent)
- if (c->die_tag == DW_TAG_inlined_subroutine
- || c->die_tag == DW_TAG_subprogram)
- {
- gcc_assert (get_AT (c, DW_AT_inline));
- break;
- }
-#endif
+ if (flag_checking)
+ for (dw_die_ref c = context_die; c; c = c->die_parent)
+ if (c->die_tag == DW_TAG_inlined_subroutine
+ || c->die_tag == DW_TAG_subprogram)
+ {
+ gcc_assert (get_AT (c, DW_AT_inline));
+ break;
+ }
return;
}
}
if (type == NULL_TREE || type == error_mark_node)
return;
-#ifdef ENABLE_CHECKING
- if (type)
+ if (flag_checking && type)
verify_type (type);
-#endif
if (TYPE_NAME (type) != NULL_TREE
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
/* We are going to output a DIE to represent the unqualified version
of this type (i.e. without any const or volatile qualifiers) so
get the main variant (i.e. the unqualified version) of this type
- now. (Vectors are special because the debugging info is in the
+ now. (Vectors and arrays are special because the debugging info is in the
cloned type itself). */
- if (TREE_CODE (type) != VECTOR_TYPE)
+ if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
type = type_main_variant (type);
/* If this is an array type with hidden descriptor, handle it first. */
if (type != error_mark_node)
{
gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
-#ifdef ENABLE_CHECKING
- dw_die_ref die = lookup_type_die (type);
- if (die)
- check_die (die);
-#endif
+ if (flag_checking)
+ {
+ dw_die_ref die = lookup_type_die (type);
+ if (die)
+ check_die (die);
+ }
}
}
context_die);
case NAMESPACE_DECL:
- case IMPORTED_DECL:
if (dwarf_version >= 3 || !dwarf_strict)
gen_namespace_die (decl, context_die);
break;
+ case IMPORTED_DECL:
+ dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl),
+ DECL_CONTEXT (decl), context_die);
+ break;
+
case NAMELIST_DECL:
gen_namelist_decl (DECL_NAME (decl), context_die,
NAMELIST_DECL_ASSOCIATED_DECL (decl));
static void
dwarf2out_late_global_decl (tree decl)
{
- /* Output any global decls we missed or fill-in any location
- information we were unable to determine on the first pass.
+ /* We have to generate early debug late for LTO. */
+ if (in_lto_p)
+ dwarf2out_early_global_decl (decl);
- Skip over functions because they were handled by the
- debug_hooks->function_decl() call in rest_of_handle_final. */
- if ((TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+ /* Fill-in any location information we were unable to determine
+ on the first pass. */
+ if (TREE_CODE (decl) == VAR_DECL
&& !POINTER_BOUNDS_P (decl))
- dwarf2out_decl (decl);
+ {
+ dw_die_ref die = lookup_decl_die (decl);
+ if (die)
+ add_location_or_const_value_attribute (die, decl, false);
+ }
}
/* Output debug information for type decl DECL. Called from toplev.c
gen_decl_die (decl, NULL, context_die);
-#ifdef ENABLE_CHECKING
- dw_die_ref die = lookup_decl_die (decl);
- if (die)
- check_die (die);
-#endif
+ if (flag_checking)
+ {
+ dw_die_ref die = lookup_decl_die (decl);
+ if (die)
+ check_die (die);
+ }
}
/* Write the debugging output for DECL. */
just a unique number which is associated with only that one filename. We
need such numbers for the sake of generating labels (in the .debug_sfnames
section) and references to those files numbers (in the .debug_srcinfo
- and.debug_macinfo sections). If the filename given as an argument is not
+ and .debug_macinfo sections). If the filename given as an argument is not
found in our current list, add it to the list and assign it the next
available unique index number. */
if (!die || !arg)
return;
+ gcc_assert (early_dwarf);
+
if (!tmpl_value_parm_die_table)
vec_alloc (tmpl_value_parm_die_table, 32);
if (!generic_type_p (t))
return;
+ gcc_assert (early_dwarf);
+
if (!generic_type_instances)
vec_alloc (generic_type_instances, 256);
{
if (tmpl_value_parm_die_table)
{
- unsigned i;
+ unsigned i, j;
die_arg_entry *e;
+ /* We do this in two phases - first get the cases we can
+ handle during early-finish, preserving those we cannot
+ (containing symbolic constants where we don't yet know
+ whether we are going to output the referenced symbols).
+ For those we try again at late-finish. */
+ j = 0;
FOR_EACH_VEC_ELT (*tmpl_value_parm_die_table, i, e)
- tree_add_const_value_attribute (e->die, e->arg);
+ {
+ if (!tree_add_const_value_attribute (e->die, e->arg))
+ (*tmpl_value_parm_die_table)[j++] = *e;
+ }
+ tmpl_value_parm_die_table->truncate (j);
}
}
if (!generic_type_instances)
return;
+ /* We end up "recursing" into schedule_generic_params_dies_gen, so
+ pretend this generation is part of "early dwarf" as well. */
+ set_early_dwarf s;
+
FOR_EACH_VEC_ELT (*generic_type_instances, i, t)
if (COMPLETE_TYPE_P (t))
gen_generic_params_dies (t);
+
+ generic_type_instances = NULL;
}
char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
struct var_loc_node *newloc;
rtx_insn *next_real, *next_note;
+ rtx_insn *call_insn = NULL;
static const char *last_label;
static const char *last_postcall_label;
static bool last_in_cold_section_p;
call_site_count++;
if (SIBLING_CALL_P (loc_note))
tail_call_site_count++;
+ if (optimize == 0 && !flag_var_tracking)
+ {
+ /* When the var-tracking pass is not running, there is no note
+ for indirect calls whose target is compile-time known. In this
+ case, process such calls specifically so that we generate call
+ sites for them anyway. */
+ rtx x = PATTERN (loc_note);
+ if (GET_CODE (x) == PARALLEL)
+ x = XVECEXP (x, 0, 0);
+ if (GET_CODE (x) == SET)
+ x = SET_SRC (x);
+ if (GET_CODE (x) == CALL)
+ x = XEXP (x, 0);
+ if (!MEM_P (x)
+ || GET_CODE (XEXP (x, 0)) != SYMBOL_REF
+ || !SYMBOL_REF_DECL (XEXP (x, 0))
+ || (TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0)))
+ != FUNCTION_DECL))
+ {
+ call_insn = loc_note;
+ loc_note = NULL;
+ var_loc_p = false;
+
+ next_real = next_real_insn (call_insn);
+ next_note = NULL;
+ cached_next_real_insn = NULL;
+ goto create_label;
+ }
+ }
}
return;
}
&& !NOTE_DURING_CALL_P (loc_note))
return;
+create_label:
+
if (next_real == NULL_RTX)
next_real = get_last_insn ();
}
}
+ gcc_assert ((loc_note == NULL_RTX && call_insn != NULL_RTX)
+ || (loc_note != NULL_RTX && call_insn == NULL_RTX));
+
if (!var_loc_p)
{
struct call_arg_loc_node *ca_loc
= ggc_cleared_alloc<call_arg_loc_node> ();
- rtx_insn *prev = prev_real_insn (loc_note);
- rtx x;
+ rtx_insn *prev
+ = loc_note != NULL_RTX ? prev_real_insn (loc_note) : call_insn;
+
ca_loc->call_arg_loc_note = loc_note;
ca_loc->next = NULL;
ca_loc->label = last_label;
if (!CALL_P (prev))
prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
ca_loc->tail_call_p = SIBLING_CALL_P (prev);
- x = get_call_rtx_from (PATTERN (prev));
+
+ /* Look for a SYMBOL_REF in the "prev" instruction. */
+ rtx x = get_call_rtx_from (PATTERN (prev));
if (x)
{
- x = XEXP (XEXP (x, 0), 0);
- if (GET_CODE (x) == SYMBOL_REF
- && SYMBOL_REF_DECL (x)
- && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL)
- ca_loc->symbol_ref = x;
+ /* Try to get the call symbol, if any. */
+ if (MEM_P (XEXP (x, 0)))
+ x = XEXP (x, 0);
+ /* First, look for a memory access to a symbol_ref. */
+ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && SYMBOL_REF_DECL (XEXP (x, 0))
+ && TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0))) == FUNCTION_DECL)
+ ca_loc->symbol_ref = XEXP (x, 0);
+ /* Otherwise, look at a compile-time known user-level function
+ declaration. */
+ else if (MEM_P (x)
+ && MEM_EXPR (x)
+ && TREE_CODE (MEM_EXPR (x)) == FUNCTION_DECL)
+ ca_loc->symbol_ref = XEXP (DECL_RTL (MEM_EXPR (x)), 0);
}
+
ca_loc->block = insn_scope (prev);
if (call_arg_locations)
call_arg_loc_last->next = ca_loc;
call_arg_locations = ca_loc;
call_arg_loc_last = ca_loc;
}
- else if (!NOTE_DURING_CALL_P (loc_note))
+ else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note))
newloc->label = last_label;
else
{
producer->dw_attr_val.v.val_str->refcount--;
producer->dw_attr_val.v.val_str = find_AT_string (producer_string);
- gen_scheduled_generic_parms_dies ();
gen_remaining_tmpl_value_param_die_attribute ();
/* Add the name for the main input file now. We delayed this from
generate a table that would have contained data. */
if (info_section_emitted)
{
- unsigned long aranges_length = size_of_aranges ();
-
switch_to_section (debug_aranges_section);
- output_aranges (aranges_length);
+ output_aranges ();
}
/* Output ranges section if necessary. */
/* The point here is to flush out the limbo list so that it is empty
and we don't need to stream it for LTO. */
flush_limbo_die_list ();
+
+ gen_scheduled_generic_parms_dies ();
+ gen_remaining_tmpl_value_param_die_attribute ();
}
/* Reset all state within dwarf2out.c so that we can rerun the compiler