/* Output Dwarf2 format symbol table information from the GNU C compiler.
- Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Contributed by Gary Funck (gary@intrepid.com).
Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
static void def_cfa_1 PARAMS ((const char *,
dw_cfa_location *));
-/* .debug_str support. */
-static hashnode indirect_string_alloc PARAMS ((hash_table *));
-static int output_indirect_string PARAMS ((struct cpp_reader *,
- hashnode, const PTR));
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+
+ /* DWARF 3 */
case DW_CFA_def_cfa_expression:
return "DW_CFA_def_cfa_expression";
+ case DW_CFA_expression:
+ return "DW_CFA_expression";
+ case DW_CFA_offset_extended_sf:
+ return "DW_CFA_offset_extended_sf";
+ case DW_CFA_def_cfa_sf:
+ return "DW_CFA_def_cfa_sf";
+ case DW_CFA_def_cfa_offset_sf:
+ return "DW_CFA_def_cfa_offset_sf";
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
#endif
offset /= DWARF_CIE_DATA_ALIGNMENT;
if (offset < 0)
- {
- cfi->dw_cfi_opc = DW_CFA_GNU_negative_offset_extended;
- offset = -offset;
- }
+ cfi->dw_cfi_opc = DW_CFA_offset_extended_sf;
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
}
static long
stack_adjust_offset (pattern)
- rtx pattern;
+ rtx pattern;
{
rtx src = SET_SRC (pattern);
rtx dest = SET_DEST (pattern);
/* We handle only adjustments by constant amount. */
if (GET_CODE (XEXP (src, 1)) != PLUS ||
GET_CODE (val) != CONST_INT)
- abort();
+ abort ();
offset = -INTVAL (val);
}
case PRE_MODIFY:
/* We can't handle variable size modifications. */
if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT)
- abort();
+ abort ();
offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
break;
case DW_CFA_offset_extended:
- case DW_CFA_GNU_negative_offset_extended:
case DW_CFA_def_cfa:
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
NULL);
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
break;
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
+ dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
+ NULL);
+ dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
+ break;
+
case DW_CFA_restore_extended:
case DW_CFA_undefined:
case DW_CFA_same_value:
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
break;
+ case DW_CFA_def_cfa_offset_sf:
+ dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
+ break;
+
case DW_CFA_GNU_window_save:
break;
case DW_CFA_def_cfa_expression:
+ case DW_CFA_expression:
output_cfa_loc (cfi);
break;
+ case DW_CFA_GNU_negative_offset_extended:
+ /* Obsoleted by DW_CFA_offset_extended_sf. */
+ abort ();
+
default:
break;
}
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output a label to mark the endpoint of the code generated for this
- function. */
+ function. */
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
fde = &fde_table[fde_table_in_use - 1];
/* And now, the support for symbolic debugging information. */
#ifdef DWARF2_DEBUGGING_INFO
+/* .debug_str support. */
+static hashnode indirect_string_alloc PARAMS ((hash_table *));
+static int output_indirect_string PARAMS ((struct cpp_reader *,
+ hashnode, const PTR));
+
+
static void dwarf2out_init PARAMS ((const char *));
static void dwarf2out_finish PARAMS ((const char *));
static void dwarf2out_define PARAMS ((unsigned int, const char *));
typedef struct limbo_die_struct
{
dw_die_ref die;
+ tree created_for;
struct limbo_die_struct *next;
}
limbo_die_node;
#endif
#endif
-/* Define the architecture-dependent minimum instruction length (in bytes).
- In this implementation of DWARF, this field is used for information
- purposes only. Since GCC generates assembly language, we have
- no a priori knowledge of how many instruction bytes are generated
- for each source line, and therefore can use only the DW_LNE_set_address
- and DW_LNS_fixed_advance_pc line information commands. */
-#ifndef DWARF_LINE_MIN_INSTR_LENGTH
-#define DWARF_LINE_MIN_INSTR_LENGTH 4
-#endif
-
/* Minimum line offset in a special line info. opcode.
This value was chosen to give a reasonable range of values. */
#define DWARF_LINE_BASE -10
static inline void free_die PARAMS ((dw_die_ref));
static void remove_children PARAMS ((dw_die_ref));
static void add_child_die PARAMS ((dw_die_ref, dw_die_ref));
-static dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref));
+static dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref,
+ tree));
static dw_die_ref lookup_type_die PARAMS ((tree));
static void equate_type_number_to_die PARAMS ((tree, dw_die_ref));
static dw_die_ref lookup_decl_die PARAMS ((tree));
const char *, const char *, const char *));
static void output_loc_list PARAMS ((dw_loc_list_ref));
static char *gen_internal_sym PARAMS ((const char *));
+static void mark_limbo_die_list PARAMS ((void *));
/* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION
/* Return a pointer to a newly created DIE node. */
static inline dw_die_ref
-new_die (tag_value, parent_die)
+new_die (tag_value, parent_die, t)
enum dwarf_tag tag_value;
dw_die_ref parent_die;
+ tree t;
{
dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node));
limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node));
limbo_node->die = die;
+ limbo_node->created_for = t;
limbo_node->next = limbo_die_list;
limbo_die_list = limbo_node;
}
tree decl;
dw_die_ref decl_die;
{
- unsigned decl_id = DECL_UID (decl);
- unsigned num_allocated;
+ unsigned int decl_id = DECL_UID (decl);
+ unsigned int num_allocated;
if (decl_id >= decl_die_table_allocated)
{
static char *
gen_internal_sym (prefix)
- const char *prefix;
+ const char *prefix;
{
char buf[256];
static int label_num;
if (strcmp (curr->section, ".text") == 0)
{
/* dw2_asm_output_data will mask off any extra bits in the ~0. */
- dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT)0,
+ dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT) 0,
"Location list base address specifier fake entry");
dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section,
"Location list base address specifier base");
char *sym = AT_loc_list (a)->ll_symbol;
if (sym == 0)
- abort();
+ abort ();
dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym,
loc_section_label, "%s", name);
}
if (die->die_tag == DW_TAG_subprogram)
{
dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die),
- "Address");
+ "Address");
dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die),
get_AT_low_pc (die), "Length");
}
dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
ASM_OUTPUT_LABEL (asm_out_file, p1);
- dw2_asm_output_data (1, DWARF_LINE_MIN_INSTR_LENGTH,
+ /* Define the architecture-dependent minimum instruction length (in
+ bytes). In this implementation of DWARF, this field is used for
+ information purposes only. Since GCC generates assembly language,
+ we have no a priori knowledge of how many instruction bytes are
+ generated for each source line, and therefore can use only the
+ DW_LNE_set_address and DW_LNS_fixed_advance_pc line information
+ commands. Accordingly, we fix this as `1', which is "correct
+ enough" for all architectures, and don't let the target override. */
+ dw2_asm_output_data (1, 1,
"Minimum Instruction Length");
+
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
"Default is_stmt_start flag");
dw2_asm_output_data (1, DWARF_LINE_BASE,
abort ();
}
- base_type_result = new_die (DW_TAG_base_type, comp_unit_die);
+ base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type);
if (demangle_name_func)
type_name = (*demangle_name_func) (type_name);
;
else if (is_const_type)
{
- mod_type_die = new_die (DW_TAG_const_type, comp_unit_die);
+ 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);
+ 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);
+ mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type);
add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
#if 0
add_AT_unsigned (mod_type_die, DW_AT_address_class, 0);
}
else if (code == REFERENCE_TYPE)
{
- mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die);
+ mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
#if 0
add_AT_unsigned (mod_type_die, DW_AT_address_class, 0);
is_based_loc (rtl)
rtx rtl;
{
- return (GET_CODE (rtl) == PLUS
- && ((GET_CODE (XEXP (rtl, 0)) == REG
- && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
+ return (GET_CODE (rtl) == PLUS
+ && ((GET_CODE (XEXP (rtl, 0)) == REG
+ && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
+ && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
}
/* The following routine converts the RTL for a variable or parameter
by a different symbol. */
if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl))
{
- rtx tmp = get_pool_constant (rtl);
+ bool marked;
+ rtx tmp = get_pool_constant_mark (rtl, &marked);
if (GET_CODE (tmp) == SYMBOL_REF)
- rtl = tmp;
+ {
+ rtl = tmp;
+ if (CONSTANT_POOL_ADDRESS_P (tmp))
+ get_pool_constant_mark (tmp, &marked);
+ else
+ marked = true;
+ }
+
+ /* If all references to this pool constant were optimized away,
+ it was not output and thus we can't represent it.
+ FIXME: might try to use DW_OP_const_value here, though
+ DW_OP_piece complicates it. */
+ if (!marked)
+ return 0;
}
mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
break;
+ case ADDRESSOF:
+ /* If this is a MEM, return its address. Otherwise, we can't
+ represent this. */
+ if (GET_CODE (XEXP (rtl, 0)) == MEM)
+ return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode);
+ else
+ return 0;
+
default:
abort ();
}
the names of types. */
return 0;
+ case CALL_EXPR:
+ return 0;
+
+ case ADDR_EXPR:
+ /* We can support this only if we can look through conversions and
+ find an INDIRECT_EXPR. */
+ for (loc = TREE_OPERAND (loc, 0);
+ TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR
+ || TREE_CODE (loc) == NON_LVALUE_EXPR
+ || TREE_CODE (loc) == VIEW_CONVERT_EXPR
+ || TREE_CODE (loc) == SAVE_EXPR;
+ loc = TREE_OPERAND (loc, 0))
+ ;
+
+ return (TREE_CODE (loc) == INDIRECT_REF
+ ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp)
+ : 0);
+
case VAR_DECL:
case PARM_DECL:
{
rtx rtl = rtl_for_decl_location (loc);
- enum machine_mode mode = GET_MODE (rtl);
if (rtl == NULL_RTX)
return 0;
}
else
{
+ enum machine_mode mode = GET_MODE (rtl);
+
if (GET_CODE (rtl) == MEM)
{
indirect_p = 1;
return 0;
break;
+ case TRUTH_AND_EXPR:
+ case TRUTH_ANDIF_EXPR:
case BIT_AND_EXPR:
op = DW_OP_and;
goto do_binop;
+ case TRUTH_XOR_EXPR:
case BIT_XOR_EXPR:
op = DW_OP_xor;
goto do_binop;
+ case TRUTH_OR_EXPR:
+ case TRUTH_ORIF_EXPR:
case BIT_IOR_EXPR:
op = DW_OP_or;
goto do_binop;
add_loc_descr (&ret, new_loc_descr (op, 0, 0));
break;
+ case TRUTH_NOT_EXPR:
case BIT_NOT_EXPR:
op = DW_OP_not;
goto do_unop;
TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
- /* ... fall through ... */
+ /* ... fall through ... */
case COND_EXPR:
{
/* Use DECL_RTL as the "location" unless we find something better. */
rtl = DECL_RTL_IF_SET (decl);
- if (TREE_CODE (decl) == PARM_DECL)
+ /* When generating abstract instances, ignore everything except
+ constants and symbols living in memory. */
+ if (! reload_completed)
+ {
+ if (rtl
+ && (CONSTANT_P (rtl)
+ || (GET_CODE (rtl) == MEM
+ && CONSTANT_P (XEXP (rtl, 0)))))
+ return rtl;
+ rtl = NULL_RTX;
+ }
+ else if (TREE_CODE (decl) == PARM_DECL)
{
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
/* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant,
and will have been substituted directly into all expressions that use it.
C does not have such a concept, but C++ and other languages do. */
- else if (DECL_INITIAL (decl))
+ else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
EXPAND_INITIALIZER);
case ERROR_MARK:
return;
- /* All fixed-bounds are represented by INTEGER_CST nodes. */
+ /* All fixed-bounds are represented by INTEGER_CST nodes. */
case INTEGER_CST:
if (! host_integerp (bound, 0)
|| (bound_attr == DW_AT_lower_bound
&& (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
{
dw_die_ref ctx = lookup_decl_die (current_function_decl);
- dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
+ dw_die_ref decl_die = new_die (DW_TAG_variable, ctx, bound);
rtx loc = SAVE_EXPR_RTL (bound);
/* If the RTL for the SAVE_EXPR is memory, handle the case where
else
ctx = lookup_decl_die (current_function_decl);
- decl_die = new_die (DW_TAG_variable, ctx);
+ /* If we weren't able to find a context, it's most likely the case
+ that we are processing the return type of the function. So
+ make a SAVE_EXPR to point to it and have the limbo DIE code
+ find the proper die. The save_expr function doesn't always
+ make a SAVE_EXPR, so do it ourselves. */
+ if (ctx == 0)
+ bound = build (SAVE_EXPR, TREE_TYPE (bound), bound,
+ current_function_decl, NULL_TREE);
+
+ decl_die = new_die (DW_TAG_variable, ctx, bound);
add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
add_AT_loc (decl_die, DW_AT_location, loc);
/* Arrays come in three flavors: Unspecified bounds, fixed bounds,
and (in GNU C only) variable bounds. Handle all three forms
here. */
- subrange_die = new_die (DW_TAG_subrange_type, type_die);
+ subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
if (domain)
{
/* We have an array type with specified bounds. */
gen_type_die (TREE_TYPE (type), context_die);
#endif
- array_die = new_die (DW_TAG_array_type, scope_die);
+ array_die = new_die (DW_TAG_array_type, scope_die, type);
#if 0
/* We default the array ordering. SDB will probably do
dw_die_ref context_die;
{
dw_die_ref type_die
- = new_die (DW_TAG_set_type, scope_die_for (type, context_die));
+ = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type);
equate_type_number_to_die (type, type_die);
add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die);
dw_die_ref context_die;
{
tree origin = decl_ultimate_origin (decl);
- dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die);
+ dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl);
if (origin != NULL)
add_abstract_origin_attribute (decl_die, origin);
tree type;
dw_die_ref context_die;
{
- dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die);
+ dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type);
/* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
be incomplete and such types are not marked. */
tree type;
dw_die_ref context_die;
{
- dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die);
+ dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type);
/* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
be incomplete and such types are not marked. */
tree type;
dw_die_ref context_die;
{
- dw_die_ref type_die = new_die (DW_TAG_union_type, context_die);
+ dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type);
/* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
be incomplete and such types are not marked. */
if (type_die == NULL)
{
type_die = new_die (DW_TAG_enumeration_type,
- scope_die_for (type, context_die));
+ scope_die_for (type, context_die), type);
equate_type_number_to_die (type, type_die);
add_name_attribute (type_die, type_tag (type));
}
for (link = TYPE_FIELDS (type);
link != NULL; link = TREE_CHAIN (link))
{
- dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die);
+ dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link);
add_name_attribute (enum_die,
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
dw_die_ref context_die;
{
dw_die_ref parm_die
- = new_die (DW_TAG_formal_parameter, context_die);
+ = new_die (DW_TAG_formal_parameter, context_die, node);
tree origin;
switch (TREE_CODE_CLASS (TREE_CODE (node)))
static void
gen_unspecified_parameters_die (decl_or_type, context_die)
- tree decl_or_type ATTRIBUTE_UNUSED;
+ tree decl_or_type;
dw_die_ref context_die;
{
- new_die (DW_TAG_unspecified_parameters, context_die);
+ new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type);
}
/* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a
if (old_die && old_die->die_parent == NULL)
add_child_die (context_die, old_die);
- subr_die = new_die (DW_TAG_subprogram, context_die);
+ subr_die = new_die (DW_TAG_subprogram, context_die, decl);
add_abstract_origin_attribute (subr_die, origin);
}
else if (old_die)
}
else
{
- subr_die = new_die (DW_TAG_subprogram, context_die);
+ subr_die = new_die (DW_TAG_subprogram, context_die, decl);
add_AT_die_ref (subr_die, DW_AT_specification, old_die);
if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index)
add_AT_unsigned (subr_die, DW_AT_decl_file, file_index);
}
else
{
- subr_die = new_die (DW_TAG_subprogram, context_die);
+ subr_die = new_die (DW_TAG_subprogram, context_die, decl);
if (TREE_PUBLIC (decl))
add_AT_flag (subr_die, DW_AT_external, 1);
dw_die_ref context_die;
{
tree origin = decl_ultimate_origin (decl);
- dw_die_ref var_die = new_die (DW_TAG_variable, context_die);
+ dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl);
dw_die_ref old_die = lookup_decl_die (decl);
int declaration = (DECL_EXTERNAL (decl)
dw_die_ref context_die;
{
tree origin = decl_ultimate_origin (decl);
- dw_die_ref lbl_die = new_die (DW_TAG_label, context_die);
+ dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
rtx insn;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
dw_die_ref context_die;
int depth;
{
- dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die);
+ dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (! BLOCK_ABSTRACT (stmt))
if (! BLOCK_ABSTRACT (stmt))
{
dw_die_ref subr_die
- = new_die (DW_TAG_inlined_subroutine, context_die);
+ = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
tree decl = block_ultimate_origin (stmt);
char label[MAX_ARTIFICIAL_LABEL_BYTES];
tree decl;
dw_die_ref context_die;
{
- dw_die_ref decl_die = new_die (DW_TAG_member, context_die);
+ dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl);
add_name_and_src_coords_attributes (decl_die, decl);
add_type_attribute (decl_die, member_declared_type (decl),
dw_die_ref context_die;
{
dw_die_ref ptr_die
- = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die));
+ = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
equate_type_number_to_die (type, ptr_die);
add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die);
dw_die_ref context_die;
{
dw_die_ref ref_die
- = new_die (DW_TAG_reference_type, scope_die_for (type, context_die));
+ = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type);
equate_type_number_to_die (type, ref_die);
add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die);
dw_die_ref context_die;
{
dw_die_ref ptr_die
- = new_die (DW_TAG_ptr_to_member_type, scope_die_for (type, context_die));
+ = new_die (DW_TAG_ptr_to_member_type,
+ scope_die_for (type, context_die), type);
equate_type_number_to_die (type, ptr_die);
add_AT_die_ref (ptr_die, DW_AT_containing_type,
const char *language_string = lang_hooks.name;
int language;
- die = new_die (DW_TAG_compile_unit, NULL);
+ die = new_die (DW_TAG_compile_unit, NULL, NULL);
add_name_attribute (die, filename);
if (wd != NULL && filename[0] != DIR_SEPARATOR)
dw_die_ref context_die;
{
dw_die_ref type_die
- = new_die (DW_TAG_string_type, scope_die_for (type, context_die));
+ = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type);
equate_type_number_to_die (type, type_die);
tree binfo;
dw_die_ref context_die;
{
- dw_die_ref die = new_die (DW_TAG_inheritance, context_die);
+ dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
add_data_member_location_attribute (die, binfo);
type_die = new_die (TREE_CODE (type) == RECORD_TYPE
? DW_TAG_structure_type : DW_TAG_union_type,
- scope_die);
+ scope_die, type);
equate_type_number_to_die (type, type_die);
if (old_die)
add_AT_die_ref (type_die, DW_AT_specification, old_die);
add_AT_flag (type_die, DW_AT_declaration, 1);
/* We don't need to do this for function-local types. */
- if (! decl_function_context (TYPE_STUB_DECL (type)))
+ if (TYPE_STUB_DECL (type)
+ && ! decl_function_context (TYPE_STUB_DECL (type)))
VARRAY_PUSH_TREE (incomplete_types, type);
}
}
{
tree return_type = TREE_TYPE (type);
dw_die_ref subr_die
- = new_die (DW_TAG_subroutine_type, scope_die_for (type, context_die));
+ = new_die (DW_TAG_subroutine_type,
+ scope_die_for (type, context_die), type);
equate_type_number_to_die (type, subr_die);
add_prototyped_attribute (subr_die, type);
return;
TREE_ASM_WRITTEN (decl) = 1;
- type_die = new_die (DW_TAG_typedef, context_die);
+ type_die = new_die (DW_TAG_typedef, context_die, decl);
origin = decl_ultimate_origin (decl);
if (origin != NULL)
add_abstract_origin_attribute (type_die, origin);
abort ();
}
}
+
+static void
+mark_limbo_die_list (ptr)
+ void *ptr ATTRIBUTE_UNUSED;
+{
+ limbo_die_node *node;
+ for (node = limbo_die_list; node ; node = node->next)
+ ggc_mark_tree (node->created_for);
+}
\f
/* Add Ada "use" clause information for SGI Workshop debugger. */
if (filename != NULL)
{
- dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die);
+ dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die, NULL);
tree context_list_decl
= build_decl (LABEL_DECL, get_identifier (context_list),
void_type_node);
if (flag_eliminate_dwarf2_dups)
{
/* Record the beginning of the file for break_out_includes. */
- dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die);
+ dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
add_AT_string (bincl_die, DW_AT_name, filename);
}
{
if (flag_eliminate_dwarf2_dups)
/* Record the end of the file for break_out_includes. */
- new_die (DW_TAG_GNU_EINCL, comp_unit_die);
+ new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL);
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
ggc_add_rtx_varray_root (&used_rtx_varray, 1);
+ ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list);
+
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
DEBUG_ABBREV_SECTION_LABEL, 0);
if (die->die_parent == NULL)
{
dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
+ tree context;
if (origin)
add_child_die (origin->die_parent, die);
else if (die == comp_unit_die)
;
+ /* If this was an expression for a bound involved in a function
+ return type, it may be a SAVE_EXPR for which we weren't able
+ to find a DIE previously. So try now. */
+ else if (node->created_for
+ && TREE_CODE (node->created_for) == SAVE_EXPR
+ && 0 != (origin = (lookup_decl_die
+ (SAVE_EXPR_CONTEXT
+ (node->created_for)))))
+ add_child_die (origin, die);
else if (errorcount > 0 || sorrycount > 0)
/* It's OK to be confused by errors in the input. */
add_child_die (comp_unit_die, die);
+ else if (node->created_for
+ && ((DECL_P (node->created_for)
+ && (context = DECL_CONTEXT (node->created_for)))
+ || (TYPE_P (node->created_for)
+ && (context = TYPE_CONTEXT (node->created_for))))
+ && TREE_CODE (context) == FUNCTION_DECL)
+ {
+ /* In certain situations, the lexical block containing a
+ nested function can be optimized away, which results
+ in the nested function die being orphaned. Likewise
+ with the return type of that nested function. Force
+ this to be a child of the containing function. */
+ origin = lookup_decl_die (context);
+ if (! origin)
+ abort ();
+ add_child_die (origin, die);
+ }
else
abort ();
}