#define DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET 0
#endif
-#ifndef DWARF2_FRAME_INFO
-# ifdef DWARF2_DEBUGGING_INFO
-# define DWARF2_FRAME_INFO \
- (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
-# else
-# define DWARF2_FRAME_INFO 0
-# endif
+/* ??? Poison these here until it can be done generically. They've been
+ totally replaced in this file; make sure it stays that way. */
+#undef DWARF2_UNWIND_INFO
+#undef DWARF2_FRAME_INFO
+#if (GCC_VERSION >= 3000)
+ #pragma GCC poison DWARF2_UNWIND_INFO DWARF2_FRAME_INFO
+#endif
+
+#ifndef INCOMING_RETURN_ADDR_RTX
+#define INCOMING_RETURN_ADDR_RTX (gcc_unreachable (), NULL_RTX)
#endif
/* Map register numbers held in the call frame info that gcc has
/* We want to emit correct CFA location expressions or lists, so we
have to return true if we're going to output debug info, even if
we're not going to output frame or unwind info. */
- return (write_symbols == DWARF2_DEBUG
- || write_symbols == VMS_AND_DWARF2_DEBUG
- || DWARF2_FRAME_INFO || saved_do_cfi_asm
-#ifdef DWARF2_UNWIND_INFO
- || (DWARF2_UNWIND_INFO
- && (flag_unwind_tables
- || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)))
-#endif
- );
+ if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+ return true;
+
+ if (saved_do_cfi_asm)
+ return true;
+
+ if (targetm.debug_unwind_info () == UI_DWARF2)
+ return true;
+
+ if ((flag_unwind_tables || flag_exceptions)
+ && targetm.except_unwind_info () == UI_DWARF2)
+ return true;
+
+ return false;
}
/* Decide whether to emit frame unwind via assembler directives. */
#ifdef MIPS_DEBUGGING_INFO
return false;
#endif
- if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
- return false;
if (saved_do_cfi_asm)
return true;
+ if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
+ return false;
if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
return false;
if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
return false;
- if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE)
- {
-#ifdef TARGET_UNWIND_INFO
- return false;
-#else
- if (USING_SJLJ_EXCEPTIONS || (!flag_unwind_tables && !flag_exceptions))
- return false;
-#endif
- }
+ /* If we can't get the assembler to emit only .debug_frame, and we don't need
+ dwarf2 unwind info for exceptions, then emit .debug_frame by hand. */
+ if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE
+ && !flag_unwind_tables && !flag_exceptions
+ && targetm.except_unwind_info () != UI_DWARF2)
+ return false;
saved_do_cfi_asm = true;
return true;
static void output_cfi_directive (dw_cfi_ref);
static void output_call_frame_info (int);
static void dwarf2out_note_section_used (void);
-static void flush_queued_reg_saves (void);
static bool clobbers_queued_reg_save (const_rtx);
static void dwarf2out_frame_debug_expr (rtx, const char *);
static struct dw_loc_descr_struct *build_cfa_aligned_loc
(HOST_WIDE_INT, HOST_WIDE_INT);
static void def_cfa_1 (const char *, dw_cfa_location *);
+static struct dw_loc_descr_struct *mem_loc_descriptor
+ (rtx, enum machine_mode mode, enum var_init_status);
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
}
else
{
- ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", dwarf2out_cfi_label_num++);
- ASM_OUTPUT_LABEL (asm_out_file, label);
+ int num = dwarf2out_cfi_label_num++;
+ ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num);
+ ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", num);
}
return label;
/* True if remember_state should be emitted before following CFI directive. */
static bool emit_cfa_remember;
+/* True if any CFI directives were emitted at the current insn. */
+static bool any_cfis_emitted;
+
/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
or to the CIE if LABEL is NULL. */
output_cfi_directive (cfi);
list_head = &fde->dw_fde_cfi;
+ any_cfis_emitted = true;
}
/* ??? If this is a CFI for the CIE, we don't emit. This
assumes that the standard CIE contents that the assembler
}
list_head = &fde->dw_fde_cfi;
+ any_cfis_emitted = true;
}
add_cfi (list_head, cfi);
/* Output all the entries in QUEUED_REG_SAVES. */
-static void
-flush_queued_reg_saves (void)
+void
+dwarf2out_flush_queued_reg_saves (void)
{
struct queued_reg_save *q;
cfa.reg = REGNO (pat);
break;
+ case MEM:
+ cfa.indirect = 1;
+ pat = XEXP (pat, 0);
+ if (GET_CODE (pat) == PLUS)
+ {
+ cfa.base_offset = INTVAL (XEXP (pat, 1));
+ pat = XEXP (pat, 0);
+ }
+ cfa.reg = REGNO (pat);
+ break;
+
default:
/* Recurse and define an expression. */
gcc_unreachable ();
reg_save (label, sregno, dregno, 0);
}
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */
+
+static void
+dwarf2out_frame_debug_cfa_expression (rtx set, const char *label)
+{
+ rtx src, dest, span;
+ dw_cfi_ref cfi = new_cfi ();
+
+ dest = SET_DEST (set);
+ src = SET_SRC (set);
+
+ gcc_assert (REG_P (src));
+ gcc_assert (MEM_P (dest));
+
+ span = targetm.dwarf_register_span (src);
+ gcc_assert (!span);
+
+ cfi->dw_cfi_opc = DW_CFA_expression;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = DWARF_FRAME_REGNUM (REGNO (src));
+ cfi->dw_cfi_oprnd2.dw_cfi_loc
+ = mem_loc_descriptor (XEXP (dest, 0), GET_MODE (dest),
+ VAR_INIT_STATUS_INITIALIZED);
+
+ /* ??? We'd like to use queue_reg_save, were the interface different,
+ and, as above, we could manage flushing for epilogues. */
+ add_fde_cfi (label, cfi);
+}
+
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
static void
alignment. */
if (fde && XEXP (src, 0) == stack_pointer_rtx)
{
+ /* We interpret reg_save differently with stack_realign set.
+ Thus we must flush whatever we have queued first. */
+ dwarf2out_flush_queued_reg_saves ();
+
gcc_assert (cfa_store.reg == REGNO (XEXP (src, 0)));
fde->stack_realign = 1;
fde->stack_realignment = INTVAL (XEXP (src, 1));
size_t i;
/* Flush any queued register saves. */
- flush_queued_reg_saves ();
+ dwarf2out_flush_queued_reg_saves ();
/* Set up state for generating call frame debug info. */
lookup_cfa (&cfa);
}
if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn))
- flush_queued_reg_saves ();
+ dwarf2out_flush_queued_reg_saves ();
if (!RTX_FRAME_RELATED_P (insn))
{
}
label = dwarf2out_cfi_label (false);
+ any_cfis_emitted = false;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
switch (REG_NOTE_KIND (note))
handled_one = true;
break;
+ case REG_CFA_EXPRESSION:
+ n = XEXP (note, 0);
+ if (n == NULL)
+ n = single_set (insn);
+ dwarf2out_frame_debug_cfa_expression (n, label);
+ handled_one = true;
+ break;
+
case REG_CFA_RESTORE:
n = XEXP (note, 0);
if (n == NULL)
break;
}
if (handled_one)
- return;
+ {
+ if (any_cfis_emitted)
+ dwarf2out_flush_queued_reg_saves ();
+ return;
+ }
insn = PATTERN (insn);
found:
/* Check again. A parallel can save and update the same register.
We could probably check just once, here, but this is safer than
removing the check above. */
- if (clobbers_queued_reg_save (insn))
- flush_queued_reg_saves ();
+ if (any_cfis_emitted || clobbers_queued_reg_save (insn))
+ dwarf2out_flush_queued_reg_saves ();
}
/* Determine if we need to save and restore CFI information around this
char * dup_label;
dw_fde_ref fde;
section *fnsec;
+ bool do_frame;
current_function_func_begin_label = NULL;
-#ifdef TARGET_UNWIND_INFO
- /* ??? current_function_func_begin_label is also used by except.c
- for call-site information. We must emit this label if it might
- be used. */
- if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS)
- && ! dwarf2out_do_frame ())
- return;
-#else
- if (! dwarf2out_do_frame ())
+ do_frame = dwarf2out_do_frame ();
+
+ /* ??? current_function_func_begin_label is also used by except.c for
+ call-site information. We must emit this label if it might be used. */
+ if (!do_frame
+ && (!flag_exceptions
+ || targetm.except_unwind_info () != UI_TARGET))
return;
-#endif
fnsec = function_section (current_function_decl);
switch_to_section (fnsec);
dup_label = xstrdup (label);
current_function_func_begin_label = dup_label;
-#ifdef TARGET_UNWIND_INFO
/* We can elide the fde allocation if we're not emitting debug info. */
- if (! dwarf2out_do_frame ())
+ if (!do_frame)
return;
-#endif
/* Expand the fde table if necessary. */
if (fde_table_in_use == fde_table_allocated)
/* On entry, the Canonical Frame Address is at SP. */
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
-#ifdef DWARF2_UNWIND_INFO
- if (DWARF2_UNWIND_INFO || DWARF2_FRAME_INFO)
+ if (targetm.debug_unwind_info () == UI_DWARF2
+ || targetm.except_unwind_info () == UI_DWARF2)
initial_return_save (INCOMING_RETURN_ADDR_RTX);
-#endif
}
void
dwarf2out_frame_finish (void)
{
/* Output call frame information. */
- if (DWARF2_FRAME_INFO)
+ if (targetm.debug_unwind_info () == UI_DWARF2)
output_call_frame_info (0);
-#ifndef TARGET_UNWIND_INFO
/* Output another copy for the unwinder. */
- if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
+ if ((flag_unwind_tables || flag_exceptions)
+ && targetm.except_unwind_info () == UI_DWARF2)
output_call_frame_info (1);
-#endif
}
/* Note that the current function section is being used for code. */
dw_val_class_macptr,
dw_val_class_file,
dw_val_class_data8,
+ dw_val_class_decl_ref,
dw_val_class_vms_delta
};
unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file;
unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8];
+ tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref;
struct dw_val_vms_delta_union
{
char * lbl1;
return "DW_OP_GNU_uninit";
case DW_OP_GNU_encoded_addr:
return "DW_OP_GNU_encoded_addr";
+ case DW_OP_GNU_implicit_pointer:
+ return "DW_OP_GNU_implicit_pointer";
default:
return "OP_<unknown>";
loc_descr_plus_const (&d->expr, offset);
}
+#define DWARF_REF_SIZE \
+ (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
+
/* Return the size of a location descriptor. */
static unsigned long
size += 4;
break;
case DW_OP_call_ref:
- size += DWARF2_ADDR_SIZE;
+ size += DWARF_REF_SIZE;
break;
case DW_OP_implicit_value:
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned)
+ loc->dw_loc_oprnd1.v.val_unsigned;
break;
+ case DW_OP_GNU_implicit_pointer:
+ size += DWARF_REF_SIZE + size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
+ break;
default:
break;
}
}
static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
+static void get_ref_die_offset_label (char *, dw_die_ref);
/* Output location description stack opcode's operands (if any). */
}
break;
+ case DW_OP_GNU_implicit_pointer:
+ {
+ char label[MAX_ARTIFICIAL_LABEL_BYTES
+ + HOST_BITS_PER_WIDE_INT / 2 + 2];
+ gcc_assert (val1->val_class == dw_val_class_die_ref);
+ get_ref_die_offset_label (label, val1->v.val_die_ref.die);
+ dw2_asm_output_offset (DWARF_REF_SIZE, label, debug_info_section, NULL);
+ dw2_asm_output_data_sleb128 (val2->v.val_int, NULL);
+ }
+ break;
+
default:
/* Other codes have no operands. */
break;
dw2_asm_output_data_sleb128_raw (val2->v.val_int);
break;
+ case DW_OP_GNU_implicit_pointer:
+ gcc_unreachable ();
+ break;
+
default:
/* Other codes have no operands. */
break;
die_sib. die_child points to the node *before* the "first" child node. */
typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
- enum dwarf_tag die_tag;
union die_symbol_or_type_node
{
char * GTY ((tag ("0"))) die_symbol;
/* Die is used and must not be pruned as unused. */
int die_perennial_p;
unsigned int decl_id;
+ enum dwarf_tag die_tag;
}
die_node;
static unsigned long next_die_offset;
/* Record the root of the DIE's built for the current compilation unit. */
-static GTY(()) dw_die_ref comp_unit_die;
+static GTY(()) dw_die_ref single_comp_unit_die;
/* A list of type DIEs that have been separated into comdat sections. */
static GTY(()) comdat_type_node *comdat_type_list;
/* Record whether the function being analyzed contains inlined functions. */
static int current_function_has_inlines;
-#if 0 && defined (MIPS_DEBUGGING_INFO)
-static int comp_unit_has_inlines;
-#endif
/* The last file entry emitted by maybe_emit_file(). */
static GTY(()) struct dwarf_file_data * last_emitted_file;
enum var_init_status);
static int is_based_loc (const_rtx);
static int resolve_one_addr (rtx *, void *);
-static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode,
- enum var_init_status);
static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
enum var_init_status);
static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
#endif
\f
+/* Return the root of the DIE's built for the current compilation unit. */
+static dw_die_ref
+comp_unit_die (void)
+{
+ if (!single_comp_unit_die)
+ single_comp_unit_die = gen_compile_unit_die (NULL);
+ return single_comp_unit_die;
+}
+
/* We allow a language front-end to designate a function that is to be
called to "demangle" any name before it is put into a DIE. */
|| code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
}
+/* Set label to debug_info_section_label + die_offset of a DIE reference. */
+
+static void
+get_ref_die_offset_label (char *label, dw_die_ref ref)
+{
+ sprintf (label, "%s+%ld", debug_info_section_label, ref->die_offset);
+}
+
/* Convert a DIE tag into its string name. */
static const char *
if (! die)
return NULL;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (a->dw_attr == attr_kind)
return a;
else if (a->dw_attr == DW_AT_specification
static inline bool
is_cxx (void)
{
- unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+ unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus;
}
static inline bool
is_fortran (void)
{
- unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+ unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
return (lang == DW_LANG_Fortran77
|| lang == DW_LANG_Fortran90
static inline bool
is_ada (void)
{
- unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+ unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
}
if (! die)
return;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (a->dw_attr == attr_kind)
{
if (AT_class (a) == dw_val_class_str)
fprintf (outfile, "\n");
}
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
print_spaces (outfile);
fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr));
debug_dwarf (void)
{
print_indent = 0;
- print_die (comp_unit_die, stderr);
+ print_die (comp_unit_die (), stderr);
if (! DWARF2_ASM_LINE_DEBUG_INFO)
print_dwarf_line_table (stderr);
}
CHECKSUM (die->die_tag);
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
attr_checksum (a, ctx, mark);
FOR_EACH_CHILD (die, c, die_checksum (c, ctx, mark));
dw_attr_ref a;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
switch (a->dw_attr)
{
!= VEC_length (dw_attr_node, die2->die_attr))
return 0;
- for (ix = 0; VEC_iterate (dw_attr_node, die1->die_attr, ix, a1); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die1->die_attr, ix, a1)
if (!same_attr_p (a1, VEC_index (dw_attr_node, die2->die_attr, ix), mark))
return 0;
|| c->die_tag == DW_TAG_module);
}
+/* Returns true iff C is a compile-unit DIE. */
+
+static inline bool
+is_cu_die (dw_die_ref c)
+{
+ return c && c->die_tag == DW_TAG_compile_unit;
+}
+
static char *
gen_internal_sym (const char *prefix)
{
dw_attr_ref a;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (a->dw_attr == DW_AT_declaration)
return 1;
clone = ggc_alloc_cleared_die_node ();
clone->die_tag = die->die_tag;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
add_dwarf_attr (clone, a);
return clone;
clone = ggc_alloc_cleared_die_node ();
clone->die_tag = die->die_tag;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
/* We don't want to copy over all attributes.
For example we don't want DW_AT_byte_size because otherwise we will no
remove_AT (die, DW_AT_specification);
- for (ix = 0; VEC_iterate (dw_attr_node, decl->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, decl->die_attr, ix, a)
{
if (a->dw_attr != DW_AT_name
&& a->dw_attr != DW_AT_declaration
add it to the list of comdat types. */
unit = new_die (DW_TAG_type_unit, NULL, NULL);
add_AT_unsigned (unit, DW_AT_language,
- get_AT_unsigned (comp_unit_die, DW_AT_language));
+ get_AT_unsigned (comp_unit_die (), DW_AT_language));
type_node = ggc_alloc_cleared_comdat_type_node ();
type_node->root_die = unit;
type_node->next = comdat_type_list;
dw_attr_ref a;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
if (AT_class (a) == dw_val_class_die_ref)
{
dw_attr_ref a;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (AT_class (a) == dw_val_class_loc_list)
output_loc_list (AT_loc_list (a));
/* Scan the DIE references, and mark as external any that refer to
DIEs from other CUs (i.e. those which are not marked). */
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (AT_class (a) == dw_val_class_die_ref
&& AT_ref (a)->die_mark == 0)
{
!= VEC_length (dw_attr_node, die->die_attr))
continue;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, die_a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, die_a)
{
abbrev_a = VEC_index (dw_attr_node, abbrev->die_attr, ix);
if ((abbrev_a->dw_attr != die_a->dw_attr)
unsigned ix;
size += size_of_uleb128 (die->die_abbrev);
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
switch (AT_class (a))
{
FOR_EACH_CHILD (die, c, unmark_all_dies (c));
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (AT_class (a) == dw_val_class_die_ref)
unmark_all_dies (AT_ref (a));
}
pubname_ref p;
size = DWARF_PUBNAMES_HEADER_SIZE;
- for (i = 0; VEC_iterate (pubname_entry, names, i, p); i++)
+ FOR_EACH_VEC_ELT (pubname_entry, names, i, p)
if (names != pubtype_table
|| p->die->die_offset != 0
|| !flag_eliminate_unused_debug_types)
(unsigned long)die->die_offset,
dwarf_tag_name (die->die_tag));
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
const char *name = dwarf_attr_name (a->dw_attr);
e.name = NULL;
if ((TREE_PUBLIC (decl)
- || die->die_parent == comp_unit_die)
+ || is_cu_die (die->die_parent))
&& (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
{
e.die = die;
dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
"Compilation Unit Length");
- for (i = 0; VEC_iterate (pubname_entry, names, i, pub); i++)
+ FOR_EACH_VEC_ELT (pubname_entry, names, i, pub)
{
/* We shouldn't see pubnames for DIEs outside of the main CU. */
if (names == pubname_table)
size = 2 + DWARF_OFFSET_SIZE + 1;
/* Each entry: code label + DIE offset. */
- for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, p); i++)
+ FOR_EACH_VEC_ELT (dcall_entry, dcall_table, i, p)
{
gcc_assert (p->targ_die != NULL);
/* Insert a "from" entry when the point-of-call DIE offset changes. */
"Offset of Compilation Unit Info");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
- for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, p); i++)
+ FOR_EACH_VEC_ELT (dcall_entry, dcall_table, i, p)
{
/* Insert a "from" entry when the point-of-call DIE offset changes. */
if (p->poc_decl != last_poc_decl)
size = 2 + 1;
/* Each entry: code label + vtable slot index. */
- for (i = 0; VEC_iterate (vcall_entry, vcall_table, i, p); i++)
+ FOR_EACH_VEC_ELT (vcall_entry, vcall_table, i, p)
size += DWARF_OFFSET_SIZE + size_of_uleb128 (p->vtable_slot);
return size;
dw2_asm_output_data (2, 4, "Version number");
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
- for (i = 0; VEC_iterate (vcall_entry, vcall_table, i, p); i++)
+ FOR_EACH_VEC_ELT (vcall_entry, vcall_table, i, p)
{
ASM_GENERATE_INTERNAL_LABEL (poc_label, "LPOC", p->poc_label_num);
dw2_asm_output_addr (DWARF_OFFSET_SIZE, poc_label, "Point of call");
gcc_unreachable ();
}
- base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type);
+ base_type_result = new_die (DW_TAG_base_type, comp_unit_die (), type);
add_AT_unsigned (base_type_result, DW_AT_byte_size,
int_size_in_bytes (type));
const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
if (context_die == NULL)
- context_die = comp_unit_die;
+ context_die = comp_unit_die ();
subrange_die = new_die (DW_TAG_subrange_type, context_die, type);
if (is_const_type)
{
- mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type);
+ mod_type_die = new_die (DW_TAG_const_type, comp_unit_die (), type);
sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
}
else if (is_volatile_type)
{
- mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type);
+ mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die (), type);
sub_die = modified_type_die (type, 0, 0, context_die);
}
else if (code == POINTER_TYPE)
{
- mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type);
+ mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die (), 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);
else if (code == REFERENCE_TYPE)
{
if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
- mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die,
+ mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die (),
type);
else
- mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
+ mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die (), 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);
case CONCAT:
case CONCATN:
case VAR_LOCATION:
+ case DEBUG_IMPLICIT_PTR:
expansion_failed (NULL_TREE, rtl,
"CONCAT/CONCATN/VAR_LOCATION is handled only by loc_descriptor");
return 0;
return cc_loc_result;
}
+/* Helper function for loc_descriptor. Return DW_OP_GNU_implicit_pointer
+ for DEBUG_IMPLICIT_PTR RTL. */
+
+static dw_loc_descr_ref
+implicit_ptr_descriptor (rtx rtl, HOST_WIDE_INT offset)
+{
+ dw_loc_descr_ref ret;
+ dw_die_ref ref;
+
+ if (dwarf_strict)
+ return NULL;
+ gcc_assert (TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == VAR_DECL
+ || TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == PARM_DECL
+ || TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == RESULT_DECL);
+ ref = lookup_decl_die (DEBUG_IMPLICIT_PTR_DECL (rtl));
+ ret = new_loc_descr (DW_OP_GNU_implicit_pointer, 0, offset);
+ ret->dw_loc_oprnd2.val_class = dw_val_class_const;
+ if (ref)
+ {
+ ret->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+ ret->dw_loc_oprnd1.v.val_die_ref.die = ref;
+ ret->dw_loc_oprnd1.v.val_die_ref.external = 0;
+ }
+ else
+ {
+ ret->dw_loc_oprnd1.val_class = dw_val_class_decl_ref;
+ ret->dw_loc_oprnd1.v.val_decl_ref = DEBUG_IMPLICIT_PTR_DECL (rtl);
+ }
+ return ret;
+}
+
/* Output a proper Dwarf location descriptor for a variable or parameter
which is either allocated in a register or in a memory location. For a
register, we just generate an OP_REG and the register number. For a
}
break;
+ case DEBUG_IMPLICIT_PTR:
+ loc_result = implicit_ptr_descriptor (rtl, 0);
+ break;
+
+ case PLUS:
+ if (GET_CODE (XEXP (rtl, 0)) == DEBUG_IMPLICIT_PTR
+ && CONST_INT_P (XEXP (rtl, 1)))
+ {
+ loc_result
+ = implicit_ptr_descriptor (XEXP (rtl, 0), INTVAL (XEXP (rtl, 1)));
+ break;
+ }
+ /* FALLTHRU */
default:
if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (rtl) == mode
&& GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
return 0;
/* Fallthru. */
case INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
have_address = 1;
break;
static void
add_accessibility_attribute (dw_die_ref die, tree decl)
{
+ /* In DWARF3+ the default is DW_ACCESS_private only in DW_TAG_class_type
+ children, otherwise the default is DW_ACCESS_public. In DWARF2
+ the default has always been DW_ACCESS_public. */
if (TREE_PROTECTED (decl))
add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
else if (TREE_PRIVATE (decl))
- add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private);
+ {
+ if (dwarf_version == 2
+ || die->die_parent == NULL
+ || die->die_parent->die_tag != DW_TAG_class_type)
+ add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private);
+ }
+ else if (dwarf_version > 2
+ && die->die_parent
+ && die->die_parent->die_tag == DW_TAG_class_type)
+ add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
}
/* Attach the specialized form of location attribute used for data members of
;
/* Vectors only work if their mode is supported by the target.
FIXME: generic vectors ought to work too. */
- else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_MODE (type) == BLKmode)
+ else if (TREE_CODE (type) == VECTOR_TYPE
+ && !VECTOR_MODE_P (TYPE_MODE (type)))
;
/* If the initializer is something that we know will expand into an
immediate RTL constant, expand it now. We must be careful not to
&& (!REG_P (XEXP (rtl, 0))
|| REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM
|| REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM
-#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_ARG_POINTER
|| REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM
#endif
)
min_index = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0);
memset (array, '\0', size);
- for (cnt = 0;
- VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce);
- cnt++)
+ FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce)
{
tree val = ce->value;
tree index = ce->index;
if (TREE_CODE (type) == RECORD_TYPE)
field = TYPE_FIELDS (type);
- for (cnt = 0;
- VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce);
- cnt++, field = field ? DECL_CHAIN (field) : 0)
+ FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce)
{
tree val = ce->value;
int pos, fieldsize;
static int
lower_bound_default (void)
{
- switch (get_AT_unsigned (comp_unit_die, DW_AT_language))
+ switch (get_AT_unsigned (comp_unit_die (), DW_AT_language))
{
case DW_LANG_C:
case DW_LANG_C89:
break;
if (current_function_decl == 0)
- ctx = comp_unit_die;
+ ctx = comp_unit_die ();
else
ctx = lookup_decl_die (current_function_decl);
static inline void
add_prototyped_attribute (dw_die_ref die, tree func_type)
{
- if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89
+ if (get_AT_unsigned (comp_unit_die (), DW_AT_language) == DW_LANG_C89
&& TYPE_ARG_TYPES (func_type) != NULL)
add_AT_flag (die, DW_AT_prototyped, 1);
}
current_function_funcdef_no);
add_AT_lbl_id (die, DW_AT_entry_pc, label);
- /* Make it the first child of comp_unit_die. */
- die->die_parent = comp_unit_die;
- if (comp_unit_die->die_child)
+ /* Make it the first child of comp_unit_die (). */
+ die->die_parent = comp_unit_die ();
+ if (comp_unit_die ()->die_child)
{
- die->die_sib = comp_unit_die->die_child->die_sib;
- comp_unit_die->die_child->die_sib = die;
+ die->die_sib = comp_unit_die ()->die_child->die_sib;
+ comp_unit_die ()->die_child->die_sib = die;
}
else
{
die->die_sib = die;
- comp_unit_die->die_child = die;
+ comp_unit_die ()->die_child = die;
}
}
#endif /* VMS_DEBUGGING_INFO */
containing_scope = NULL_TREE;
if (containing_scope == NULL_TREE)
- scope_die = comp_unit_die;
+ scope_die = comp_unit_die ();
else if (TYPE_P (containing_scope))
{
/* For types, we can just look up the appropriate DIE. But
/* If none of the current dies are suitable, we get file scope. */
if (scope_die == NULL)
- scope_die = comp_unit_die;
+ scope_die = comp_unit_die ();
}
else
scope_die = lookup_type_die (containing_scope);
equate_type_number_to_die (type, array_die);
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)));
- add_AT_flag (array_die, DW_AT_GNU_vector, 1);
- }
+ add_AT_flag (array_die, DW_AT_GNU_vector, 1);
/* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */
if (is_fortran ()
#ifdef MIPS_DEBUGGING_INFO
/* The SGI compilers handle arrays of unknown bound by setting
AT_declaration and not emitting any subrange DIEs. */
- if (! TYPE_DOMAIN (type))
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && ! TYPE_DOMAIN (type))
add_AT_flag (array_die, DW_AT_declaration, 1);
else
#endif
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ /* For VECTOR_TYPEs we use an array die with appropriate bounds. */
+ dw_die_ref subrange_die = new_die (DW_TAG_subrange_type, array_die, NULL);
+ add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node);
+ add_bound_info (subrange_die, DW_AT_upper_bound,
+ size_int (TYPE_VECTOR_SUBPARTS (type) - 1));
+ }
+ else
add_subscript_info (array_die, type, collapse_nested_arrays);
/* Add representation of the type of the elements of this array type and
for (i = VEC_length (tree, incomplete_types) - 1; i >= 0; i--)
if (should_emit_struct_debug (VEC_index (tree, incomplete_types, i),
DINFO_USAGE_DIR_USE))
- gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die);
+ gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die ());
}
/* Determine what tag to use for a record type. */
context = decl_class_context (decl);
if (context)
gen_type_die_for_member
- (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+ (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ());
}
/* Pretend we've just finished compiling this function. */
instances of inlines, since the spec requires the out-of-line copy
to have the same parent. For local class methods, this doesn't
apply; we just use the old DIE. */
- if ((old_die->die_parent == comp_unit_die || context_die == NULL)
+ if ((is_cu_die (old_die->die_parent) || context_die == NULL)
&& (DECL_ARTIFICIAL (decl)
|| (get_AT_file (old_die, DW_AT_decl_file) == file_index
&& (get_AT_unsigned (old_die, DW_AT_decl_line)
if (fn_arg_types != NULL)
{
/* This is the prototyped case, check for.... */
- if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
+ if (stdarg_p (TREE_TYPE (decl)))
gen_unspecified_parameters_die (decl, subr_die);
}
else if (DECL_INITIAL (decl) == NULL_TREE)
current_function_has_inlines = 0;
decls_for_scope (outer_scope, subr_die, 0);
-
-#if 0 && defined (MIPS_DEBUGGING_INFO)
- if (current_function_has_inlines)
- {
- add_AT_flag (subr_die, DW_AT_MIPS_has_inlines, 1);
- if (! comp_unit_has_inlines)
- {
- add_AT_flag (comp_unit_die, DW_AT_MIPS_has_inlines, 1);
- comp_unit_has_inlines = 1;
- }
- }
-#endif
}
/* Add the calling convention attribute if requested. */
add_calling_convention_attribute (subr_die, decl);
if (declaration)
add_AT_flag (var_die, DW_AT_declaration, 1);
- if (decl && (DECL_ABSTRACT (decl) || declaration))
+ if (decl && (DECL_ABSTRACT (decl) || declaration || old_die == NULL))
equate_decl_number_to_die (decl, var_die);
if (! declaration
add_AT_string (die, DW_AT_producer, producer);
+ /* If our producer is LTO try to figure out a common language to use
+ from the global list of translation units. */
+ if (strcmp (language_string, "GNU GIMPLE") == 0)
+ {
+ unsigned i;
+ tree t;
+ const char *common_lang = NULL;
+
+ FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+ {
+ if (!TRANSLATION_UNIT_LANGUAGE (t))
+ continue;
+ if (!common_lang)
+ common_lang = TRANSLATION_UNIT_LANGUAGE (t);
+ else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0)
+ ;
+ else if (strncmp (common_lang, "GNU C", 5) == 0
+ && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
+ /* Mixing C and C++ is ok, use C++ in that case. */
+ common_lang = "GNU C++";
+ else
+ {
+ /* Fall back to C. */
+ common_lang = NULL;
+ break;
+ }
+ }
+
+ if (common_lang)
+ language_string = common_lang;
+ }
+
language = DW_LANG_C89;
if (strcmp (language_string, "GNU C++") == 0)
language = DW_LANG_C_plus_plus;
if (BINFO_VIRTUAL_P (binfo))
add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
+ /* In DWARF3+ the default is DW_ACCESS_private only in DW_TAG_class_type
+ children, otherwise the default is DW_ACCESS_public. In DWARF2
+ the default has always been DW_ACCESS_private. */
if (access == access_public_node)
- add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
+ {
+ if (dwarf_version == 2
+ || context_die->die_tag == DW_TAG_class_type)
+ add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
+ }
else if (access == access_protected_node)
add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
+ else if (dwarf_version > 2
+ && context_die->die_tag != DW_TAG_class_type)
+ add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private);
}
/* Generate a DIE for a class member. */
scope_die = scope_die_for (type, context_die);
- if (! type_die || (nested && scope_die == comp_unit_die))
+ if (! type_die || (nested && is_cu_die (scope_die)))
/* First occurrence of type or toplevel definition of nested class. */
{
dw_die_ref old_die = type_die;
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
- type_die = new_die (DW_TAG_unspecified_type, comp_unit_die, type);
+ type_die = new_die (DW_TAG_unspecified_type, comp_unit_die (), type);
add_name_attribute (type_die, IDENTIFIER_POINTER (name));
equate_type_number_to_die (type, type_die);
}
else
return force_decl_die (context);
}
- return comp_unit_die;
+ return comp_unit_die ();
}
/* Returns the DIE for decl. A DIE will always be returned. */
dwarf2out_decl (decl);
else
/* DWARF2 has neither DW_TAG_module, nor DW_TAG_namespace. */
- decl_die = comp_unit_die;
+ decl_die = comp_unit_die ();
+ break;
+
+ case TRANSLATION_UNIT_DECL:
+ decl_die = comp_unit_die ();
break;
default:
if (DECL_ABSTRACT_ORIGIN (decl) == NULL)
{
/* Output a real namespace or module. */
- context_die = setup_namespace_context (decl, comp_unit_die);
+ context_die = setup_namespace_context (decl, comp_unit_die ());
namespace_die = new_die (is_fortran ()
? DW_TAG_module : DW_TAG_namespace,
context_die, decl);
if (DECL_CONTEXT (decl) == NULL_TREE
|| TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
- context_die = setup_namespace_context (decl, comp_unit_die);
+ context_die = setup_namespace_context (decl, comp_unit_die ());
/* Now create the namespace alias DIE. */
namespace_die = new_die (DW_TAG_imported_declaration, context_die, decl);
add_name_and_src_coords_attributes (namespace_die, decl);
break;
case CONST_DECL:
- if (!is_fortran ())
+ if (!is_fortran () && !is_ada ())
{
/* The individual enumerators of an enum type get output when we output
the Dwarf representation of the relevant enum type itself. */
else if (debug_info_level > DINFO_LEVEL_TERSE)
{
/* Before we describe the FUNCTION_DECL itself, make sure that we
- have described its return type. */
+ have its containing type. */
+ if (!origin)
+ origin = decl_class_context (decl);
+ if (origin != NULL_TREE)
+ gen_type_die (origin, context_die);
+
+ /* And its return type. */
gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
/* And its virtual context. */
if (DECL_VINDEX (decl) != NULL_TREE)
gen_type_die (DECL_CONTEXT (decl), context_die);
- /* And its containing type. */
- if (!origin)
- origin = decl_class_context (decl);
+ /* Make sure we have a member DIE for decl. */
if (origin != NULL_TREE)
gen_type_die_for_member (origin, decl, context_die);
void
dwarf2out_decl (tree decl)
{
- dw_die_ref context_die = comp_unit_die;
+ dw_die_ref context_die = comp_unit_die ();
switch (TREE_CODE (decl))
{
case CONST_DECL:
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
- if (!is_fortran ())
+ if (!is_fortran () && !is_ada ())
return;
if (TREE_STATIC (decl) && decl_function_context (decl))
context_die = lookup_decl_die (DECL_CONTEXT (decl));
/* Don't bother trying to generate any DIEs to represent any of the
normal built-in types for the language we are compiling. */
if (DECL_IS_BUILTIN (decl))
- {
- /* OK, we need to generate one for `bool' so GDB knows what type
- comparisons have. */
- if (is_cxx ()
- && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE
- && ! DECL_IGNORED_P (decl))
- modified_type_die (TREE_TYPE (decl), 0, 0, NULL);
-
- return;
- }
+ return;
/* If we are in terse mode, don't generate any DIEs for types. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
unsigned i;
die_arg_entry *e;
- for (i = 0;
- VEC_iterate (die_arg_entry, tmpl_value_parm_die_table, i, e);
- i++)
+ FOR_EACH_VEC_ELT (die_arg_entry, tmpl_value_parm_die_table, i, e)
tree_add_const_value_attribute (e->die, e->arg);
}
}
/* Record the beginning of the file for break_out_includes. */
dw_die_ref bincl_die;
- bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
+ bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die (), NULL);
add_AT_string (bincl_die, DW_AT_name, remap_debug_filename (filename));
}
{
if (flag_eliminate_dwarf2_dups && dwarf_version < 4)
/* Record the end of the file for break_out_includes. */
- new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL);
+ new_die (DW_TAG_GNU_EINCL, comp_unit_die (), NULL);
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
vcall_insn_table = htab_create_ggc (10, vcall_insn_table_hash,
vcall_insn_table_eq, NULL);
- /* Generate the initial DIE for the .debug section. Note that the (string)
- value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE
- will (typically) be a relative pathname and that this pathname should be
- taken as being relative to the directory from which the compiler was
- invoked when the given (base) source file was compiled. We will fill
- in this value in dwarf2out_finish. */
- comp_unit_die = gen_compile_unit_die (NULL);
-
incomplete_types = VEC_alloc (tree, gc, 64);
used_rtx_array = VEC_alloc (rtx, gc, 32);
static void
dwarf2out_assembly_start (void)
{
- if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE && dwarf2out_do_cfi_asm ())
- {
-#ifndef TARGET_UNWIND_INFO
- if (USING_SJLJ_EXCEPTIONS || (!flag_unwind_tables && !flag_exceptions))
-#endif
- fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
- }
+ if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE
+ && dwarf2out_do_cfi_asm ()
+ && (!(flag_unwind_tables || flag_exceptions)
+ || targetm.except_unwind_info () != UI_DWARF2))
+ fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
}
/* A helper function for dwarf2out_finish called through
dw_attr_ref a;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
{
if (a->dw_attr_val.val_class == dw_val_class_die_ref)
{
dw_attr_ref a;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
if (AT_class (a) == dw_val_class_str)
{
struct indirect_string_node *s = a->dw_attr_val.v.val_str;
#if ENABLE_ASSERT_CHECKING
/* All the marks should already be clear. */
- verify_marks_clear (comp_unit_die);
+ verify_marks_clear (comp_unit_die ());
for (node = limbo_die_list; node; node = node->next)
verify_marks_clear (node->die);
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
premark_types_used_by_global_vars ();
/* Set the mark on nodes that are actually used. */
- prune_unused_types_walk (comp_unit_die);
+ prune_unused_types_walk (comp_unit_die ());
for (node = limbo_die_list; node; node = node->next)
prune_unused_types_walk (node->die);
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
/* Also set the mark on nodes referenced from the
pubname_table or arange_table. */
- for (i = 0; VEC_iterate (pubname_entry, pubname_table, i, pub); i++)
+ FOR_EACH_VEC_ELT (pubname_entry, pubname_table, i, pub)
prune_unused_types_mark (pub->die, 1);
for (i = 0; i < arange_table_in_use; i++)
prune_unused_types_mark (arange_table[i], 1);
/* Mark nodes referenced from the direct call table. */
- for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, dcall); i++)
+ FOR_EACH_VEC_ELT (dcall_entry, dcall_table, i, dcall)
prune_unused_types_mark (dcall->targ_die, 1);
/* Get rid of nodes that aren't marked; and update the string counts. */
htab_traverse (debug_str_hash, prune_indirect_string, NULL);
else if (debug_str_hash)
htab_empty (debug_str_hash);
- prune_unused_types_prune (comp_unit_die);
+ prune_unused_types_prune (comp_unit_die ());
for (node = limbo_die_list; node; node = node->next)
prune_unused_types_prune (node->die);
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
prune_unused_types_prune (ctnode->root_die);
/* Leave the marks clear. */
- prune_unmark_dies (comp_unit_die);
+ prune_unmark_dies (comp_unit_die ());
for (node = limbo_die_list; node; node = node->next)
prune_unmark_dies (node->die);
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
&& loc->dw_loc_oprnd2.val_class == dw_val_class_addr
&& resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL)))
return false;
+ else if (loc->dw_loc_opc == DW_OP_GNU_implicit_pointer
+ && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref)
+ {
+ dw_die_ref ref
+ = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref);
+ if (ref == NULL)
+ return false;
+ loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+ loc->dw_loc_oprnd1.v.val_die_ref.die = ref;
+ loc->dw_loc_oprnd1.v.val_die_ref.external = 0;
+ }
return true;
}
dw_loc_list_ref *curr;
unsigned ix;
- for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
+ FOR_EACH_VEC_ELT (dw_attr_node, die->die_attr, ix, a)
switch (AT_class (a))
{
case dw_val_class_loc_list:
/* Add the name for the main input file now. We delayed this from
dwarf2out_init to avoid complications with PCH. */
- add_name_attribute (comp_unit_die, remap_debug_filename (filename));
+ add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
if (!IS_ABSOLUTE_PATH (filename))
- add_comp_dir_attribute (comp_unit_die);
- else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
+ add_comp_dir_attribute (comp_unit_die ());
+ else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
{
bool p = false;
htab_traverse (file_table, file_table_relative_p, &p);
if (p)
- add_comp_dir_attribute (comp_unit_die);
+ add_comp_dir_attribute (comp_unit_die ());
}
for (i = 0; i < VEC_length (deferred_locations, deferred_locations_list); i++)
if (origin)
add_child_die (origin->die_parent, die);
- else if (die == comp_unit_die)
+ else if (is_cu_die (die))
;
else if (seen_error ())
/* It's OK to be confused by errors in the input. */
- add_child_die (comp_unit_die, die);
+ add_child_die (comp_unit_die (), die);
else
{
/* In certain situations, the lexical block containing a
if (origin)
add_child_die (origin, die);
else
- add_child_die (comp_unit_die, die);
+ add_child_die (comp_unit_die (), die);
}
}
}
limbo_die_list = NULL;
- resolve_addr (comp_unit_die);
+ resolve_addr (comp_unit_die ());
for (node = deferred_asm_name; node; node = node->next)
{
/* Generate separate CUs for each of the include files we've seen.
They will go into limbo_die_list. */
if (flag_eliminate_dwarf2_dups && dwarf_version < 4)
- break_out_includes (comp_unit_die);
+ break_out_includes (comp_unit_die ());
/* Generate separate COMDAT sections for type DIEs. */
if (dwarf_version >= 4)
{
- break_out_comdat_types (comp_unit_die);
+ break_out_comdat_types (comp_unit_die ());
/* Each new type_unit DIE was added to the limbo die list when created.
Since these have all been added to comdat_type_list, clear the
references to the main compile unit). */
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
copy_decls_for_unworthy_types (ctnode->root_die);
- copy_decls_for_unworthy_types (comp_unit_die);
+ copy_decls_for_unworthy_types (comp_unit_die ());
/* In the process of copying declarations from one unit to another,
we may have left some declarations behind that are no longer
/* Traverse the DIE's and add add sibling attributes to those DIE's
that have children. */
- add_sibling_attributes (comp_unit_die);
+ add_sibling_attributes (comp_unit_die ());
for (node = limbo_die_list; node; node = node->next)
add_sibling_attributes (node->die);
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
if (!have_multiple_function_sections
|| !(dwarf_version >= 3 || !dwarf_strict))
{
- add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
- add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
+ add_AT_lbl_id (comp_unit_die (), DW_AT_low_pc, text_section_label);
+ add_AT_lbl_id (comp_unit_die (), DW_AT_high_pc, text_end_label);
}
else
absolute. Historically, we've emitted the unexpected
DW_AT_entry_pc instead of DW_AT_low_pc for this purpose.
Emit both to give time for other tools to adapt. */
- add_AT_addr (comp_unit_die, DW_AT_low_pc, const0_rtx);
- add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx);
+ add_AT_addr (comp_unit_die (), DW_AT_low_pc, const0_rtx);
+ add_AT_addr (comp_unit_die (), DW_AT_entry_pc, const0_rtx);
if (text_section_used)
- add_ranges_by_labels (comp_unit_die, text_section_label,
+ add_ranges_by_labels (comp_unit_die (), text_section_label,
text_end_label, &range_list_added);
if (flag_reorder_blocks_and_partition && cold_text_section_used)
- add_ranges_by_labels (comp_unit_die, cold_text_section_label,
+ add_ranges_by_labels (comp_unit_die (), cold_text_section_label,
cold_end_label, &range_list_added);
for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++)
if (fde->dw_fde_switched_sections)
{
if (!fde->in_std_section)
- add_ranges_by_labels (comp_unit_die,
+ add_ranges_by_labels (comp_unit_die (),
fde->dw_fde_hot_section_label,
fde->dw_fde_hot_section_end_label,
&range_list_added);
if (!fde->cold_in_std_section)
- add_ranges_by_labels (comp_unit_die,
+ add_ranges_by_labels (comp_unit_die (),
fde->dw_fde_unlikely_section_label,
fde->dw_fde_unlikely_section_end_label,
&range_list_added);
}
else if (!fde->in_std_section)
- add_ranges_by_labels (comp_unit_die, fde->dw_fde_begin,
+ add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin,
fde->dw_fde_end, &range_list_added);
}
add_ranges (NULL);
}
- /* Output location list section if necessary. */
- if (have_location_lists)
- {
- /* Output the location lists info. */
- switch_to_section (debug_loc_section);
- ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
- DEBUG_LOC_SECTION_LABEL, 0);
- ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
- output_location_lists (die);
- }
-
if (debug_info_level >= DINFO_LEVEL_NORMAL)
- add_AT_lineptr (comp_unit_die, DW_AT_stmt_list,
+ add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list,
debug_line_section_label);
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
- add_AT_macptr (comp_unit_die, DW_AT_macro_info, macinfo_section_label);
+ add_AT_macptr (comp_unit_die (), DW_AT_macro_info, macinfo_section_label);
/* Output all of the compilation units. We put the main one last so that
the offsets are available to output_pubnames. */
/* Output the main compilation unit if non-empty or if .debug_macinfo
has been emitted. */
- output_comp_unit (comp_unit_die, debug_info_level >= DINFO_LEVEL_VERBOSE);
+ output_comp_unit (comp_unit_die (), debug_info_level >= DINFO_LEVEL_VERBOSE);
/* Output the abbreviation table. */
switch_to_section (debug_abbrev_section);
output_abbrev_section ();
+ /* Output location list section if necessary. */
+ if (have_location_lists)
+ {
+ /* Output the location lists info. */
+ switch_to_section (debug_loc_section);
+ ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
+ DEBUG_LOC_SECTION_LABEL, 0);
+ ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
+ output_location_lists (die);
+ }
+
/* Output public names table if necessary. */
if (!VEC_empty (pubname_entry, pubname_table))
{