return true;
if ((flag_unwind_tables || flag_exceptions)
- && targetm.except_unwind_info () == UI_DWARF2)
+ && targetm.except_unwind_info (&global_options) == UI_DWARF2)
return true;
return false;
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)
+ && targetm.except_unwind_info (&global_options) != UI_DWARF2)
return false;
saved_do_cfi_asm = true;
It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
Instead of passing around REG and OFFSET, we pass a copy
of this structure. */
-typedef struct GTY(()) cfa_loc {
+typedef struct cfa_loc {
HOST_WIDE_INT offset;
HOST_WIDE_INT base_offset;
unsigned int reg;
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif
\f
+/* Match the base name of a file to the base name of a compilation unit. */
+
+static int
+matches_main_base (const char *path)
+{
+ /* Cache the last query. */
+ static const char *last_path = NULL;
+ static int last_match = 0;
+ if (path != last_path)
+ {
+ const char *base;
+ int length = base_of_path (path, &base);
+ last_path = path;
+ last_match = (length == main_input_baselength
+ && memcmp (base, main_input_basename, length) == 0);
+ }
+ return last_match;
+}
+
+#ifdef DEBUG_DEBUG_STRUCT
+
+static int
+dump_struct_debug (tree type, enum debug_info_usage usage,
+ enum debug_struct_file criterion, int generic,
+ int matches, int result)
+{
+ /* Find the type name. */
+ tree type_decl = TYPE_STUB_DECL (type);
+ tree t = type_decl;
+ const char *name = 0;
+ if (TREE_CODE (t) == TYPE_DECL)
+ t = DECL_NAME (t);
+ if (t)
+ name = IDENTIFIER_POINTER (t);
+
+ fprintf (stderr, " struct %d %s %s %s %s %d %p %s\n",
+ criterion,
+ DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr",
+ matches ? "bas" : "hdr",
+ generic ? "gen" : "ord",
+ usage == DINFO_USAGE_DFN ? ";" :
+ usage == DINFO_USAGE_DIR_USE ? "." : "*",
+ result,
+ (void*) type_decl, name);
+ return result;
+}
+#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \
+ dump_struct_debug (type, usage, criterion, generic, matches, result)
+
+#else
+
+#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \
+ (result)
+
+#endif
+
+static bool
+should_emit_struct_debug (tree type, enum debug_info_usage usage)
+{
+ enum debug_struct_file criterion;
+ tree type_decl;
+ bool generic = lang_hooks.types.generic_p (type);
+
+ if (generic)
+ criterion = debug_struct_generic[usage];
+ else
+ criterion = debug_struct_ordinary[usage];
+
+ if (criterion == DINFO_STRUCT_FILE_NONE)
+ return DUMP_GSTRUCT (type, usage, criterion, generic, false, false);
+ if (criterion == DINFO_STRUCT_FILE_ANY)
+ return DUMP_GSTRUCT (type, usage, criterion, generic, false, true);
+
+ type_decl = TYPE_STUB_DECL (type);
+
+ if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl))
+ return DUMP_GSTRUCT (type, usage, criterion, generic, false, true);
+
+ if (matches_main_base (DECL_SOURCE_FILE (type_decl)))
+ return DUMP_GSTRUCT (type, usage, criterion, generic, true, true);
+ return DUMP_GSTRUCT (type, usage, criterion, generic, false, false);
+}
+\f
/* Hook used by __throw. */
rtx
call-site information. We must emit this label if it might be used. */
if (!do_frame
&& (!flag_exceptions
- || targetm.except_unwind_info () != UI_TARGET))
+ || targetm.except_unwind_info (&global_options) != UI_TARGET))
return;
fnsec = function_section (current_function_decl);
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
if (targetm.debug_unwind_info () == UI_DWARF2
- || targetm.except_unwind_info () == UI_DWARF2)
+ || targetm.except_unwind_info (&global_options) == UI_DWARF2)
initial_return_save (INCOMING_RETURN_ADDR_RTX);
}
/* Output another copy for the unwinder. */
if ((flag_unwind_tables || flag_exceptions)
- && targetm.except_unwind_info () == UI_DWARF2)
+ && targetm.except_unwind_info (&global_options) == UI_DWARF2)
output_call_frame_info (1);
}
}
limbo_die_node;
-typedef struct GTY(()) skeleton_chain_struct
+typedef struct skeleton_chain_struct
{
dw_die_ref old_die;
dw_die_ref new_die;
static void add_child_die (dw_die_ref, dw_die_ref);
static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
static dw_die_ref lookup_type_die (tree);
+static dw_die_ref lookup_type_die_strip_naming_typedef (tree);
static void equate_type_number_to_die (tree, dw_die_ref);
static hashval_t decl_die_table_hash (const void *);
static int decl_die_table_eq (const void *, const void *);
{
dw_attr_node attr;
+#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;
attr.dw_attr_val.v.val_die_ref.die = targ_die;
return TYPE_SYMTAB_DIE (type);
}
+/* Like lookup_type_die, but if type is an anonymous type named by a
+ typedef[1], return the DIE of the anonymous type instead the one of
+ the naming typedef. This is because in gen_typedef_die, we did
+ equate the anonymous struct named by the typedef with the DIE of
+ the naming typedef. So by default, lookup_type_die on an anonymous
+ struct yields the DIE of the naming typedef.
+
+ [1]: Read the comment of is_naming_typedef_decl to learn about what
+ a naming typedef is. */
+
+static inline dw_die_ref
+lookup_type_die_strip_naming_typedef (tree type)
+{
+ dw_die_ref die = lookup_type_die (type);
+ if (TREE_CODE (type) == RECORD_TYPE
+ && die->die_tag == DW_TAG_typedef
+ && is_naming_typedef_decl (TYPE_NAME (type)))
+ die = get_AT_ref (die, DW_AT_type);
+ return die;
+}
+
/* Equate a DIE to a given type specifier. */
static inline void
unsigned ix;
print_spaces (outfile);
- fprintf (outfile, "DIE %4ld: %s\n",
- die->die_offset, dwarf_tag_name (die->die_tag));
+ fprintf (outfile, "DIE %4ld: %s (%p)\n",
+ die->die_offset, dwarf_tag_name (die->die_tag),
+ (void*) die);
print_spaces (outfile);
fprintf (outfile, " abbrev id: %lu", die->die_abbrev);
- fprintf (outfile, " offset: %ld\n", die->die_offset);
+ fprintf (outfile, " offset: %ld", die->die_offset);
+ fprintf (outfile, " mark: %d\n", die->die_mark);
+
if (dwarf_version >= 4 && die->die_id.die_type_node)
{
print_spaces (outfile);
AT_ref (a)->die_id.die_symbol);
else
fprintf (outfile, "die -> %ld", AT_ref (a)->die_offset);
+ fprintf (outfile, " (%p)", (void *) AT_ref (a));
}
else
fprintf (outfile, "die -> <null>");
/* Else cv-qualified version of named type; fall through. */
}
- if (is_const_type)
+ if (is_const_type
+ /* If both is_const_type and is_volatile_type, prefer the path
+ which leads to a qualified type. */
+ && (!is_volatile_type
+ || get_qualified_type (type, TYPE_QUAL_CONST) == NULL_TREE
+ || get_qualified_type (type, TYPE_QUAL_VOLATILE) != NULL_TREE))
{
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);
- sub_die = modified_type_die (type, 0, 0, context_die);
+ sub_die = modified_type_die (type, is_const_type, 0, context_die);
}
else if (code == POINTER_TYPE)
{
/* If delegitimize_address couldn't do anything with the UNSPEC, assume
we can't express it in the debug info. */
#ifdef ENABLE_CHECKING
- inform (current_function_decl
- ? DECL_SOURCE_LOCATION (current_function_decl)
- : UNKNOWN_LOCATION,
- "non-delegitimized UNSPEC %d found in variable location",
- XINT (rtl, 1));
+ /* Don't complain about TLS UNSPECs, those are just too hard to
+ delegitimize. */
+ if (XVECLEN (rtl, 0) != 1
+ || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
+ || SYMBOL_REF_DECL (XVECEXP (rtl, 0, 0)) == NULL
+ || TREE_CODE (SYMBOL_REF_DECL (XVECEXP (rtl, 0, 0))) != VAR_DECL
+ || !DECL_THREAD_LOCAL_P (SYMBOL_REF_DECL (XVECEXP (rtl, 0, 0))))
+ inform (current_function_decl
+ ? DECL_SOURCE_LOCATION (current_function_decl)
+ : UNKNOWN_LOCATION,
+ "non-delegitimized UNSPEC %d found in variable location",
+ XINT (rtl, 1));
#endif
expansion_failed (NULL_TREE, rtl,
"UNSPEC hasn't been delegitimized.\n");
/* FALLTHRU */
case PARM_DECL:
+ case RESULT_DECL:
if (DECL_HAS_VALUE_EXPR_P (loc))
return loc_list_from_tree (DECL_VALUE_EXPR (loc),
want_address);
/* FALLTHRU */
- case RESULT_DECL:
case FUNCTION_DECL:
{
rtx rtl;
add_prototyped_attribute (dw_die_ref die, tree func_type)
{
if (get_AT_unsigned (comp_unit_die (), DW_AT_language) == DW_LANG_C89
- && TYPE_ARG_TYPES (func_type) != NULL)
+ && prototype_p (func_type))
add_AT_flag (die, DW_AT_prototyped, 1);
}
scope_die = comp_unit_die ();
}
else
- scope_die = lookup_type_die (containing_scope);
+ scope_die = lookup_type_die_strip_naming_typedef (containing_scope);
}
else
scope_die = context_die;
gcc_assert (!decl_ultimate_origin (member));
push_decl_scope (type);
- type_die = lookup_type_die (type);
+ type_die = lookup_type_die_strip_naming_typedef (type);
if (TREE_CODE (member) == FUNCTION_DECL)
gen_subprogram_die (member, type_die);
else if (TREE_CODE (member) == FIELD_DECL)
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
tree origin = decl_ultimate_origin (decl);
dw_die_ref subr_die;
- tree fn_arg_types;
tree outer_scope;
dw_die_ref old_die = lookup_decl_die (decl);
int declaration = (current_function_decl != decl
void_type_node 2) an unprototyped function declaration (not a
definition). This just means that we have no info about the
parameters at all. */
- fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- if (fn_arg_types != NULL)
+ if (prototype_p (TREE_TYPE (decl)))
{
/* This is the prototyped case, check for.... */
if (stdarg_p (TREE_TYPE (decl)))
out yet, use a NULL context for now; it will be fixed up in
decls_for_scope. */
context_die = lookup_decl_die (TYPE_CONTEXT (type));
+ /* A declaration DIE doesn't count; nested types need to go in the
+ specification. */
+ if (context_die && is_declaration_die (context_die))
+ context_die = NULL;
need_pop = 0;
}
else
static void
gen_type_die_with_usage (tree type, dw_die_ref context_die,
- enum debug_info_usage usage)
+ enum debug_info_usage usage)
{
struct array_descr_info info;
if (type == NULL_TREE || type == error_mark_node)
return;
+ if (TYPE_NAME (type) != NULL_TREE
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && is_redundant_typedef (TYPE_NAME (type))
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+ /* The DECL of this type is a typedef we don't want to emit debug
+ info for but we want debug info for its underlying typedef.
+ This can happen for e.g, the injected-class-name of a C++
+ type. */
+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
/* If TYPE is a typedef type variant, let's generate debug info
for the parent typedef which TYPE is a type of. */
if (typedef_variant_p (type))
{
if (function_section (fun) != text_section)
have_multiple_function_sections = true;
+ else if (flag_reorder_blocks_and_partition && !cold_text_section)
+ {
+ gcc_assert (current_function_decl == fun);
+ cold_text_section = unlikely_text_section ();
+ switch_to_section (cold_text_section);
+ ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
+ switch_to_section (current_function_section ());
+ }
dwarf2out_note_section_used ();
}
switch_to_section (text_section);
ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
- if (flag_reorder_blocks_and_partition)
- {
- cold_text_section = unlikely_text_section ();
- switch_to_section (cold_text_section);
- ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
- }
-
}
/* Called before cgraph_optimize starts outputtting functions, variables
if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE
&& dwarf2out_do_cfi_asm ()
&& (!(flag_unwind_tables || flag_exceptions)
- || targetm.except_unwind_info () != UI_DWARF2))
+ || targetm.except_unwind_info (&global_options) != UI_DWARF2))
fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
}
limbo_die_node *node, *next_node;
comdat_type_node *ctnode;
htab_t comdat_type_table;
- dw_die_ref die = 0;
unsigned int i;
gen_remaining_tmpl_value_param_die_attribute ();
instance. */
for (node = limbo_die_list; node; node = next_node)
{
+ dw_die_ref die = node->die;
next_node = node->next;
- die = node->die;
if (die->die_parent == NULL)
{
/* Output a terminator label for the .text section. */
switch_to_section (text_section);
targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
- if (flag_reorder_blocks_and_partition)
+ if (cold_text_section)
{
- switch_to_section (unlikely_text_section ());
+ switch_to_section (cold_text_section);
targetm.asm_out.internal_label (asm_out_file, COLD_END_LABEL, 0);
}
add_AT_macptr (comp_unit_die (), DW_AT_macro_info, macinfo_section_label);
if (have_location_lists)
- optimize_location_lists (die);
+ optimize_location_lists (comp_unit_die ());
/* Output all of the compilation units. We put the main one last so that
the offsets are available to output_pubnames. */
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_location_lists (comp_unit_die ());
}
/* Output public names table if necessary. */