/* Output Dwarf2 format symbol table information from GCC.
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Gary Funck (gary@intrepid.com).
Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
Extensively modified by Jason Merrill (jason@cygnus.com).
static GTY(()) section *debug_line_section;
static GTY(()) section *debug_loc_section;
static GTY(()) section *debug_pubnames_section;
+static GTY(()) section *debug_pubtypes_section;
static GTY(()) section *debug_str_section;
static GTY(()) section *debug_ranges_section;
static GTY(()) section *debug_frame_section;
return stripped;
}
+/* MEM is a memory reference for the register size table, each element of
+ which has mode MODE. Initialize column C as a return address column. */
+
+static void
+init_return_column_size (enum machine_mode mode, rtx mem, unsigned int c)
+{
+ HOST_WIDE_INT offset = c * GET_MODE_SIZE (mode);
+ HOST_WIDE_INT size = GET_MODE_SIZE (Pmode);
+ emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
+}
+
/* Generate code to initialize the register size table. */
void
}
}
+ if (!wrote_return_column)
+ init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
+
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
- gcc_assert (wrote_return_column);
- i = DWARF_ALT_FRAME_RETURN_COLUMN;
- wrote_return_column = false;
-#else
- i = DWARF_FRAME_RETURN_COLUMN;
+ init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
#endif
-
- if (! wrote_return_column)
- {
- enum machine_mode save_mode = Pmode;
- HOST_WIDE_INT offset = i * GET_MODE_SIZE (mode);
- HOST_WIDE_INT size = GET_MODE_SIZE (save_mode);
- emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
- }
}
/* Convert a DWARF call frame info. operation to its string name */
{
int par_index;
int limit = XVECLEN (expr, 0);
+ rtx elem;
+
+ /* PARALLELs have strict read-modify-write semantics, so we
+ ought to evaluate every rvalue before changing any lvalue.
+ It's cumbersome to do that in general, but there's an
+ easy approximation that is enough for all current users:
+ handle register saves before register assignments. */
+ if (GET_CODE (expr) == PARALLEL)
+ for (par_index = 0; par_index < limit; par_index++)
+ {
+ elem = XVECEXP (expr, 0, par_index);
+ if (GET_CODE (elem) == SET
+ && MEM_P (SET_DEST (elem))
+ && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
+ dwarf2out_frame_debug_expr (elem, label);
+ }
for (par_index = 0; par_index < limit; par_index++)
- if (GET_CODE (XVECEXP (expr, 0, par_index)) == SET
- && (RTX_FRAME_RELATED_P (XVECEXP (expr, 0, par_index))
- || par_index == 0))
- dwarf2out_frame_debug_expr (XVECEXP (expr, 0, par_index), label);
-
+ {
+ elem = XVECEXP (expr, 0, par_index);
+ if (GET_CODE (elem) == SET
+ && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
+ && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
+ dwarf2out_frame_debug_expr (elem, label);
+ }
return;
}
/* 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);
- label = get_file_function_name ('F');
+ 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));
fde = &fde_table[fde_table_in_use++];
fde->decl = current_function_decl;
fde->dw_fde_begin = dup_label;
- fde->dw_fde_current_label = NULL;
+ fde->dw_fde_current_label = dup_label;
fde->dw_fde_hot_section_label = NULL;
fde->dw_fde_hot_section_end_label = NULL;
fde->dw_fde_unlikely_section_label = NULL;
typedef struct pubname_struct GTY(())
{
dw_die_ref die;
- char *name;
+ const char *name;
}
pubname_entry;
+DEF_VEC_O(pubname_entry);
+DEF_VEC_ALLOC_O(pubname_entry, gc);
+
struct dw_ranges_struct GTY(())
{
int block_num;
/* A pointer to the base of a table that contains a list of publicly
accessible names. */
-static GTY ((length ("pubname_table_allocated"))) pubname_ref pubname_table;
-
-/* Number of elements currently allocated for pubname_table. */
-static GTY(()) unsigned pubname_table_allocated;
-
-/* Number of elements in pubname_table currently in use. */
-static GTY(()) unsigned pubname_table_in_use;
+static GTY (()) VEC (pubname_entry, gc) * pubname_table;
-/* Size (in elements) of increments by which we may expand the
- pubname_table. */
-#define PUBNAME_TABLE_INCREMENT 64
+/* A pointer to the base of a table that contains a list of publicly
+ accessible types. */
+static GTY (()) VEC (pubname_entry, gc) * pubtype_table;
/* Array of dies for which we should generate .debug_arange info. */
static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table;
/* Number of internal labels generated by gen_internal_sym(). */
static GTY(()) int label_num;
+/* Cached result of previous call to lookup_filename. */
+static GTY(()) struct dwarf_file_data * file_table_last_lookup;
+
#ifdef DWARF2_DEBUGGING_INFO
/* Offset from the "steady-state frame pointer" to the frame base,
static void mark_dies (dw_die_ref);
static void unmark_dies (dw_die_ref);
static void unmark_all_dies (dw_die_ref);
-static unsigned long size_of_pubnames (void);
+static unsigned long size_of_pubnames (VEC (pubname_entry,gc) *);
static unsigned long size_of_aranges (void);
static enum dwarf_form value_format (dw_attr_ref);
static void output_value_format (dw_attr_ref);
static void output_comp_unit (dw_die_ref, int);
static const char *dwarf2_name (tree, int);
static void add_pubname (tree, dw_die_ref);
-static void output_pubnames (void);
+static void add_pubtype (tree, dw_die_ref);
+static void output_pubnames (VEC (pubname_entry,gc) *);
static void add_arange (tree, dw_die_ref);
static void output_aranges (void);
static unsigned int add_ranges (tree);
static void output_line_info (void);
static void output_file_names (void);
static dw_die_ref base_type_die (tree);
-static tree root_type (tree);
static int is_base_type (tree);
static bool is_subrange_type (tree);
static dw_die_ref subrange_type_die (tree, dw_die_ref);
unmark_all_dies (AT_ref (a));
}
-/* Return the size of the .debug_pubnames table generated for the
- compilation unit. */
+/* Return the size of the .debug_pubnames or .debug_pubtypes table
+ generated for the compilation unit. */
static unsigned long
-size_of_pubnames (void)
+size_of_pubnames (VEC (pubname_entry, gc) * names)
{
unsigned long size;
unsigned i;
+ pubname_ref p;
size = DWARF_PUBNAMES_HEADER_SIZE;
- for (i = 0; i < pubname_table_in_use; i++)
- {
- pubname_ref p = &pubname_table[i];
- size += DWARF_OFFSET_SIZE + strlen (p->name) + 1;
- }
+ for (i = 0; VEC_iterate (pubname_entry, names, i, p); i++)
+ if (names != pubtype_table
+ || p->die->die_offset != 0
+ || !flag_eliminate_unused_debug_types)
+ size += strlen (p->name) + DWARF_OFFSET_SIZE + 1;
size += DWARF_OFFSET_SIZE;
return size;
static void
add_pubname (tree decl, dw_die_ref die)
{
- pubname_ref p;
+ pubname_entry e;
if (! TREE_PUBLIC (decl))
return;
- if (pubname_table_in_use == pubname_table_allocated)
+ e.die = die;
+ e.name = xstrdup (dwarf2_name (decl, 1));
+ VEC_safe_push (pubname_entry, gc, pubname_table, &e);
+}
+
+/* Add a new entry to .debug_pubtypes if appropriate. */
+
+static void
+add_pubtype (tree decl, dw_die_ref die)
+{
+ pubname_entry e;
+
+ e.name = NULL;
+ if ((TREE_PUBLIC (decl)
+ || die->die_parent == comp_unit_die)
+ && (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
{
- pubname_table_allocated += PUBNAME_TABLE_INCREMENT;
- pubname_table
- = ggc_realloc (pubname_table,
- (pubname_table_allocated * sizeof (pubname_entry)));
- memset (pubname_table + pubname_table_in_use, 0,
- PUBNAME_TABLE_INCREMENT * sizeof (pubname_entry));
- }
+ e.die = die;
+ if (TYPE_P (decl))
+ {
+ if (TYPE_NAME (decl))
+ {
+ if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE)
+ e.name = IDENTIFIER_POINTER (TYPE_NAME (decl));
+ else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (decl)))
+ e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
+ else
+ e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
+ }
+ }
+ else
+ e.name = xstrdup (dwarf2_name (decl, 1));
- p = &pubname_table[pubname_table_in_use++];
- p->die = die;
- p->name = xstrdup (dwarf2_name (decl, 1));
+ /* If we don't have a name for the type, there's no point in adding
+ it to the table. */
+ if (e.name && e.name[0] != '\0')
+ VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+ }
}
/* Output the public names table used to speed up access to externally
- visible names. For now, only generate entries for externally
- visible procedures. */
+ visible names; or the public types table used to find type definitions. */
static void
-output_pubnames (void)
+output_pubnames (VEC (pubname_entry, gc) * names)
{
unsigned i;
- unsigned long pubnames_length = size_of_pubnames ();
+ unsigned long pubnames_length = size_of_pubnames (names);
+ pubname_ref 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,
- "Length of Public Names Info");
+ if (names == pubname_table)
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+ "Length of Public Names Info");
+ else
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
+ "Length of Public Type Names Info");
dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version");
dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
debug_info_section,
dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
"Compilation Unit Length");
- for (i = 0; i < pubname_table_in_use; i++)
+ for (i = 0; VEC_iterate (pubname_entry, names, i, pub); i++)
{
- pubname_ref pub = &pubname_table[i];
-
- /* We shouldn't see pubnames for DIEs outside of the main CU. */
- gcc_assert (pub->die->die_mark);
+ /* We shouldn't see pubnames for DIEs outside of the main CU. */
+ if (names == pubname_table)
+ gcc_assert (pub->die->die_mark);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
- "DIE offset");
+ if (names != pubtype_table
+ || pub->die->die_offset != 0
+ || !flag_eliminate_unused_debug_types)
+ {
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
+ "DIE offset");
- dw2_asm_output_nstring (pub->name, -1, "external name");
+ dw2_asm_output_nstring (pub->name, -1, "external name");
+ }
}
dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
/* Skip all leading "./". */
f = d->filename;
- while (f[0] == '.' && f[1] == '/')
+ while (f[0] == '.' && IS_DIR_SEPARATOR (f[1]))
f += 2;
/* Create a new array entry. */
fi->file_idx = d;
/* Search for the file name part. */
- f = strrchr (f, '/');
+ f = strrchr (f, DIR_SEPARATOR);
+#if defined (DIR_SEPARATOR_2)
+ {
+ char *g = strrchr (fi->path, DIR_SEPARATOR_2);
+
+ if (g != NULL)
+ {
+ if (f == NULL || f < g)
+ f = g;
+ }
+ }
+#endif
+
fi->fname = f == NULL ? fi->path : f + 1;
return 1;
}
return base_type_result;
}
-/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to
- the Dwarf "root" type for the given input type. The Dwarf "root" type of
- a given type is generally the same as the given type, except that if the
- given type is a pointer or reference type, then the root type of the given
- type is the root type of the "basis" type for the pointer or reference
- type. (This definition of the "root" type is recursive.) Also, the root
- type of a `const' qualified type or a `volatile' qualified type is the
- root type of the given type without the qualifiers. */
-
-static tree
-root_type (tree type)
-{
- if (TREE_CODE (type) == ERROR_MARK)
- return error_mark_node;
-
- switch (TREE_CODE (type))
- {
- case ERROR_MARK:
- return error_mark_node;
-
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- return type_main_variant (root_type (TREE_TYPE (type)));
-
- default:
- return type_main_variant (type);
- }
-}
-
/* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
given input type is a Dwarf "fundamental" type. Otherwise return null. */
gen_type_die (qualified_type, context_die);
return lookup_type_die (qualified_type);
}
- else if (DECL_ORIGINAL_TYPE (name)
- && (is_const_type < TYPE_READONLY (dtype)
- || is_volatile_type < TYPE_VOLATILE (dtype)))
+ else if (is_const_type < TYPE_READONLY (dtype)
+ || is_volatile_type < TYPE_VOLATILE (dtype)
+ || (is_const_type <= TYPE_READONLY (dtype)
+ && is_volatile_type <= TYPE_VOLATILE (dtype)
+ && DECL_ORIGINAL_TYPE (name) != type))
/* cv-unqualified version of named type. Just use the unnamed
type to which it refers. */
return modified_type_die (DECL_ORIGINAL_TYPE (name),
gcc_assert (regno < FIRST_PSEUDO_REGISTER);
#ifdef LEAF_REG_REMAP
- {
- int leaf_reg;
-
- leaf_reg = LEAF_REG_REMAP (regno);
- if (leaf_reg != -1)
- regno = (unsigned) leaf_reg;
- }
+ if (current_function_uses_only_leaf_regs)
+ {
+ int leaf_reg = LEAF_REG_REMAP (regno);
+ if (leaf_reg != -1)
+ regno = (unsigned) leaf_reg;
+ }
#endif
return DBX_REGISTER_NUMBER (regno);
reg = REGNO (rtl);
#ifdef LEAF_REG_REMAP
- {
- int leaf_reg;
-
- leaf_reg = LEAF_REG_REMAP (reg);
- if (leaf_reg != -1)
- reg = (unsigned) leaf_reg;
- }
+ if (current_function_uses_only_leaf_regs)
+ {
+ int leaf_reg = LEAF_REG_REMAP (reg);
+ if (leaf_reg != -1)
+ reg = (unsigned) leaf_reg;
+ }
#endif
gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
&& GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
}
+/* Return a descriptor that describes the concatenation of N locations
+ used to form the address of a memory location. */
+
+static dw_loc_descr_ref
+concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
+{
+ unsigned int i;
+ dw_loc_descr_ref cc_loc_result = NULL;
+ unsigned int n = XVECLEN (concatn, 0);
+
+ for (i = 0; i < n; ++i)
+ {
+ dw_loc_descr_ref ref;
+ rtx x = XVECEXP (concatn, 0, i);
+
+ ref = mem_loc_descriptor (x, mode);
+ if (ref == NULL)
+ return NULL;
+
+ add_loc_descr (&cc_loc_result, ref);
+ add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
+ }
+
+ return cc_loc_result;
+}
+
/* The following routine converts the RTL for a variable or parameter
(resident in memory) into an equivalent Dwarf representation of a
mechanism for getting the address of that same variable onto the top of a
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
break;
+ case CONCATN:
+ mem_loc_result = concatn_mem_loc_descriptor (rtl, mode);
+ break;
+
default:
gcc_unreachable ();
}
return cc_loc_result;
}
+/* Return a descriptor that describes the concatenation of N
+ locations. */
+
+static dw_loc_descr_ref
+concatn_loc_descriptor (rtx concatn)
+{
+ unsigned int i;
+ dw_loc_descr_ref cc_loc_result = NULL;
+ unsigned int n = XVECLEN (concatn, 0);
+
+ for (i = 0; i < n; ++i)
+ {
+ dw_loc_descr_ref ref;
+ rtx x = XVECEXP (concatn, 0, i);
+
+ ref = loc_descriptor (x);
+ if (ref == NULL)
+ return NULL;
+
+ add_loc_descr (&cc_loc_result, ref);
+ add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
+ }
+
+ return cc_loc_result;
+}
+
/* 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
loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
break;
+ case CONCATN:
+ loc_result = concatn_loc_descriptor (rtl);
+ break;
+
case VAR_LOCATION:
/* Single part. */
if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
rtx rtl;
/* If this is not defined, we have no way to emit the data. */
- if (!targetm.asm_out.output_dwarf_dtprel)
+ if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel)
return 0;
/* The way DW_OP_GNU_push_tls_address is specified, we can only
/* FALLTHRU */
case RESULT_DECL:
+ case FUNCTION_DECL:
{
rtx rtl = rtl_for_decl_location (loc);
case NON_LVALUE_EXPR:
case VIEW_CONVERT_EXPR:
case SAVE_EXPR:
- case MODIFY_EXPR:
- return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
+ case GIMPLE_MODIFY_STMT:
+ return loc_descriptor_from_tree_1 (GENERIC_TREE_OPERAND (loc, 0),
+ want_address);
case COMPONENT_REF:
case BIT_FIELD_REF:
break;
case FIX_TRUNC_EXPR:
- case FIX_CEIL_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
return 0;
default:
return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
}
+/* Return the result of rounding T up to ALIGN. */
+
+static inline HOST_WIDE_INT
+round_up_to_align (HOST_WIDE_INT t, unsigned int align)
+{
+ /* We must be careful if T is negative because HOST_WIDE_INT can be
+ either "above" or "below" unsigned int as per the C promotion
+ rules, depending on the host, thus making the signedness of the
+ direct multiplication and division unpredictable. */
+ unsigned HOST_WIDE_INT u = (unsigned HOST_WIDE_INT) t;
+
+ u += align - 1;
+ u /= align;
+ u *= align;
+
+ return (HOST_WIDE_INT) u;
+}
+
/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
lowest addressed byte of the "containing object" for the given FIELD_DECL,
or return 0 if we are unable to determine what that offset is, either
object_offset_in_bits = deepest_bitpos - type_size_in_bits;
/* Round up to type_align by default. This works best for bitfields. */
- object_offset_in_bits += type_align_in_bits - 1;
- object_offset_in_bits /= type_align_in_bits;
- object_offset_in_bits *= type_align_in_bits;
+ object_offset_in_bits
+ = round_up_to_align (object_offset_in_bits, type_align_in_bits);
if (object_offset_in_bits > bitpos_int)
{
object_offset_in_bits = deepest_bitpos - type_size_in_bits;
/* Round up to decl_align instead. */
- object_offset_in_bits += decl_align_in_bits - 1;
- object_offset_in_bits /= decl_align_in_bits;
- object_offset_in_bits *= decl_align_in_bits;
+ object_offset_in_bits
+ = round_up_to_align (object_offset_in_bits, decl_align_in_bits);
}
return object_offset_in_bits / BITS_PER_UNIT;
reference_to_unused (tree * tp, int * walk_subtrees,
void * data ATTRIBUTE_UNUSED)
{
- if (! EXPR_P (*tp) && ! CONSTANT_CLASS_P (*tp))
+ if (! EXPR_P (*tp) && ! GIMPLE_STMT_P (*tp) && ! CONSTANT_CLASS_P (*tp))
*walk_subtrees = 0;
if (DECL_P (*tp) && ! TREE_PUBLIC (*tp) && ! TREE_USED (*tp)
&& ! TREE_ASM_WRITTEN (*tp))
return *tp;
- else
- return NULL_TREE;
+ else if (DECL_P (*tp) && TREE_CODE (*tp) != FUNCTION_DECL)
+ {
+ struct varpool_node *node = varpool_node (*tp);
+ if (!node->needed)
+ return *tp;
+ }
+
+ return NULL_TREE;
}
/* Generate an RTL constant from a decl initializer INIT with decl type TYPE,
#endif
add_type_attribute (array_die, element_type, 0, 0, context_die);
+
+ if (get_AT (array_die, DW_AT_name))
+ add_pubtype (type, array_die);
}
#if 0
else
add_AT_flag (type_die, DW_AT_declaration, 1);
+ if (get_AT (type_die, DW_AT_name))
+ add_pubtype (type, type_die);
+
return type_die;
}
add_AT_file (var_die, DW_AT_decl_file, file_index);
if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
-
add_AT_unsigned (var_die, DW_AT_decl_line, s.line);
}
}
{
add_name_attribute (die, filename);
/* Don't add cwd for <built-in>. */
- if (filename[0] != DIR_SEPARATOR && filename[0] != '<')
+ if (!IS_ABSOLUTE_PATH (filename) && filename[0] != '<')
add_comp_dir_attribute (die);
}
&& ! decl_function_context (TYPE_STUB_DECL (type)))
VEC_safe_push (tree, gc, incomplete_types, type);
}
+
+ if (get_AT (type_die, DW_AT_name))
+ add_pubtype (type, type_die);
}
/* Generate a DIE for a subroutine _type_. */
add_prototyped_attribute (subr_die, type);
add_type_attribute (subr_die, return_type, 0, 0, context_die);
gen_formal_types_die (type, subr_die);
+
+ if (get_AT (subr_die, DW_AT_name))
+ add_pubtype (type, subr_die);
}
/* Generate a DIE for a type definition. */
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die (decl, type_die);
+
+ if (get_AT (type_die, DW_AT_name))
+ add_pubtype (decl, type_die);
}
/* Generate a type description DIE. */
}
if (TREE_CODE (type) == ENUMERAL_TYPE)
- gen_enumeration_type_die (type, context_die);
+ {
+ /* This might have been written out by the call to
+ declare_in_namespace. */
+ if (!TREE_ASM_WRITTEN (type))
+ gen_enumeration_type_die (type, context_die);
+ }
else
gen_struct_or_union_type_die (type, context_die);
add_child_die (context_die, die);
/* Do not produce debug information for static variables since
these might be optimized out. We are called for these later
- in cgraph_varpool_analyze_pending_decls. */
+ in varpool_analyze_pending_decls. */
if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
;
else
the index of the filename was looked up last. This handles the majority of
all searches. */
-static GTY(()) struct dwarf_file_data * file_table_last_lookup;
-
static struct dwarf_file_data *
lookup_filename (const char *file_name)
{
/* Zero-th entry is allocated, but unused. */
line_info_table_in_use = 1;
+ /* Allocate the pubtypes and pubnames vectors. */
+ pubname_table = VEC_alloc (pubname_entry, gc, 32);
+ pubtype_table = VEC_alloc (pubname_entry, gc, 32);
+
/* 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
SECTION_DEBUG, NULL);
debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
SECTION_DEBUG, NULL);
+#ifdef DEBUG_PUBTYPES_SECTION
+ debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
+ SECTION_DEBUG, NULL);
+#endif
debug_str_section = get_section (DEBUG_STR_SECTION,
DEBUG_STR_SECTION_FLAGS, NULL);
debug_ranges_section = get_section (DEBUG_RANGES_SECTION,
if (die->die_mark)
return;
- switch (die->die_tag) {
- case DW_TAG_const_type:
- case DW_TAG_packed_type:
- case DW_TAG_pointer_type:
- case DW_TAG_reference_type:
- case DW_TAG_volatile_type:
- case DW_TAG_typedef:
- case DW_TAG_array_type:
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- case DW_TAG_friend:
- case DW_TAG_variant_part:
- case DW_TAG_enumeration_type:
- case DW_TAG_subroutine_type:
- case DW_TAG_string_type:
- case DW_TAG_set_type:
- case DW_TAG_subrange_type:
- case DW_TAG_ptr_to_member_type:
- case DW_TAG_file_type:
- if (die->die_perennial_p)
- break;
+ switch (die->die_tag)
+ {
+ case DW_TAG_const_type:
+ case DW_TAG_packed_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_typedef:
+ case DW_TAG_array_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ case DW_TAG_friend:
+ case DW_TAG_variant_part:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_string_type:
+ case DW_TAG_set_type:
+ case DW_TAG_subrange_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_file_type:
+ if (die->die_perennial_p)
+ break;
- /* It's a type node --- don't mark it. */
- return;
+ /* It's a type node --- don't mark it. */
+ return;
- default:
- /* Mark everything else. */
- break;
+ default:
+ /* Mark everything else. */
+ break;
}
die->die_mark = 1;
{
unsigned int i;
limbo_die_node *node;
+ pubname_ref pub;
#if ENABLE_ASSERT_CHECKING
/* All the marks should already be clear. */
/* Also set the mark on nodes referenced from the
pubname_table or arange_table. */
- for (i = 0; i < pubname_table_in_use; i++)
- prune_unused_types_mark (pubname_table[i].die, 1);
+ for (i = 0; VEC_iterate (pubname_entry, pubname_table, i, pub); i++)
+ prune_unused_types_mark (pub->die, 1);
for (i = 0; i < arange_table_in_use; i++)
prune_unused_types_mark (arange_table[i], 1);
{
bool *p = param;
struct dwarf_file_data *d = *slot;
- if (d->emitted_number && d->filename[0] != DIR_SEPARATOR)
+ if (d->emitted_number && !IS_ABSOLUTE_PATH (d->filename))
{
*p = true;
return 0;
/* 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, filename);
- if (filename[0] != DIR_SEPARATOR)
+ if (!IS_ABSOLUTE_PATH (filename))
add_comp_dir_attribute (comp_unit_die);
else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
{
else if (TYPE_P (node->created_for))
context = TYPE_CONTEXT (node->created_for);
- gcc_assert (context && TREE_CODE (context) == FUNCTION_DECL);
+ gcc_assert (context
+ && (TREE_CODE (context) == FUNCTION_DECL
+ || TREE_CODE (context) == NAMESPACE_DECL));
origin = lookup_decl_die (context);
if (origin)
output_abbrev_section ();
/* Output public names table if necessary. */
- if (pubname_table_in_use)
+ if (!VEC_empty (pubname_entry, pubname_table))
{
switch_to_section (debug_pubnames_section);
- output_pubnames ();
+ output_pubnames (pubname_table);
}
+#ifdef DEBUG_PUBTYPES_SECTION
+ /* Output public types table if necessary. */
+ if (!VEC_empty (pubname_entry, pubtype_table))
+ {
+ switch_to_section (debug_pubtypes_section);
+ output_pubnames (pubtype_table);
+ }
+#endif
+
/* Output the address range information. We only put functions in the arange
table, so don't write it out if we don't have any. */
if (fde_table_in_use)