for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
int rnum = DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), 1);
-
+
if (rnum < DWARF_FRAME_REGISTERS)
{
HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (mode);
enum machine_mode save_mode = reg_raw_mode[i];
HOST_WIDE_INT size;
-
+
if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode))
save_mode = choose_hard_reg_mode (i, 1, true);
if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
size = GET_MODE_SIZE (save_mode);
if (offset < 0)
continue;
-
+
emit_move_insn (adjust_address (mem, mode, offset),
gen_int_mode (size, mode));
}
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
#endif
+
+ targetm.init_dwarf_reg_sizes_extra (address);
}
/* Convert a DWARF call frame info. operation to its string name */
&& for_eh)
for (i = 0; i < fde_table_in_use; i++)
if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
- && !fde_table[i].uses_eh_lsda
+ && !fde_table[i].uses_eh_lsda
&& ! DECL_WEAK (fde_table[i].decl))
targetm.asm_out.unwind_label (asm_out_file, fde_table[i].decl,
for_eh, /* empty */ 1);
for (i = 0; i < fde_table_in_use; i++)
if (fde_table[i].uses_eh_lsda)
any_eh_needed = any_lsda_needed = true;
- else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
+ else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
any_eh_needed = true;
else if (! fde_table[i].nothrow
&& ! fde_table[i].all_throwers_are_sibcalls)
{
*p++ = 'P';
augmentation_size += 1 + size_of_encoded_value (per_encoding);
+ assemble_external_libcall (eh_personality_libfunc);
}
if (any_lsda_needed)
{
"FDE initial location");
if (fde->dw_fde_switched_sections)
{
- rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode,
+ rtx sym_ref2 = gen_rtx_SYMBOL_REF (Pmode,
fde->dw_fde_unlikely_section_label);
- rtx sym_ref3= gen_rtx_SYMBOL_REF (Pmode,
+ rtx sym_ref3= gen_rtx_SYMBOL_REF (Pmode,
fde->dw_fde_hot_section_label);
SYMBOL_REF_FLAGS (sym_ref2) |= SYMBOL_FLAG_LOCAL;
SYMBOL_REF_FLAGS (sym_ref3) |= SYMBOL_FLAG_LOCAL;
dw2_asm_output_addr (DWARF2_ADDR_SIZE,
fde->dw_fde_unlikely_section_label,
"FDE initial location");
- dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+ dw2_asm_output_delta (DWARF2_ADDR_SIZE,
fde->dw_fde_unlikely_section_end_label,
fde->dw_fde_unlikely_section_label,
"FDE address range");
/* Fixed size portion of the address range info. */
#define DWARF_ARANGES_HEADER_SIZE \
(DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
- DWARF2_ADDR_SIZE * 2) \
+ DWARF2_ADDR_SIZE * 2) \
- DWARF_INITIAL_LENGTH_SIZE)
/* Size of padding portion in the address range info. It must be
aligned to twice the pointer size. */
#define DWARF_ARANGES_PAD_SIZE \
(DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
- DWARF2_ADDR_SIZE * 2) \
+ DWARF2_ADDR_SIZE * 2) \
- (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4))
/* Use assembler line directives if available. */
static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char cold_text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL);
}
while (lookahead != NULL && lookahead != ret_val);
-
+
/* The block's abstract origin chain may not be the *ultimate* origin of
the block. It could lead to a DECL that has an abstract origin set.
If so, we want that DECL's abstract origin (which is what DECL_ORIGIN
/* Maybe this should be an assert? */
if (die == NULL)
return;
-
+
if (die->die_attr == NULL)
die->die_attr = VEC_alloc (dw_attr_node, gc, 1);
VEC_safe_push (dw_attr_node, gc, die->die_attr, attr);
slot = htab_find_slot_with_hash (debug_str_hash, str,
htab_hash_string (str), INSERT);
if (*slot == NULL)
- *slot = ggc_alloc_cleared (sizeof (struct indirect_string_node));
- node = (struct indirect_string_node *) *slot;
- node->str = ggc_strdup (str);
+ {
+ node = (struct indirect_string_node *)
+ ggc_alloc_cleared (sizeof (struct indirect_string_node));
+ node->str = ggc_strdup (str);
+ *slot = node;
+ }
+ else
+ node = (struct indirect_string_node *) *slot;
+
node->refcount++;
attr.dw_attr = attr_kind;
else if (a->dw_attr == DW_AT_specification
|| a->dw_attr == DW_AT_abstract_origin)
spec = AT_ref (a);
-
+
if (spec)
return get_AT (spec, attr_kind);
is_cxx (void)
{
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;
}
remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
{
dw_die_ref c;
-
+
c = die->die_child;
if (c) do {
dw_die_ref prev = c;
}
/* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
- is the specification, to the end of PARENT's list of children.
+ is the specification, to the end of PARENT's list of children.
This is done by removing and re-adding it. */
static void
gcc_assert (child->die_parent == parent
|| (child->die_parent
== get_AT_ref (parent, DW_AT_specification)));
-
+
for (p = child->die_parent->die_child; ; p = p->die_sib)
if (p->die_sib == child)
{
if (VEC_length (dw_attr_node, die1->die_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++)
if (!same_attr_p (a1, VEC_index (dw_attr_node, die2->die_attr, ix), mark))
return 0;
/* This DIE is for a secondary CU; remove it from the main one. */
remove_child_with_prev (c, prev);
-
+
if (c->die_tag == DW_TAG_GNU_BINCL)
unit = push_new_compile_unit (unit, c);
else if (c->die_tag == DW_TAG_GNU_EINCL)
dw_attr_ref die_a, abbrev_a;
unsigned ix;
bool ok = true;
-
+
if (abbrev->die_tag != die->die_tag)
continue;
if ((abbrev->die_child != NULL) != (die->die_child != NULL))
continue;
-
+
if (VEC_length (dw_attr_node, abbrev->die_attr)
!= VEC_length (dw_attr_node, die->die_attr))
continue;
-
+
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, die_a); ix++)
{
abbrev_a = VEC_index (dw_attr_node, abbrev->die_attr, ix);
unmark_all_dies (AT_ref (a));
}
-/* Return the size of the .debug_pubnames or .debug_pubtypes table
+/* Return the size of the .debug_pubnames or .debug_pubtypes table
generated for the compilation unit. */
static unsigned long
case dw_val_class_file:
{
int f = maybe_emit_file (a->dw_attr_val.v.val_file);
-
+
dw2_asm_output_data (constant_size (f), f, "%s (%s)", name,
a->dw_attr_val.v.val_file->filename);
break;
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
dw2_asm_output_data (DWARF_OFFSET_SIZE,
- next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
+ next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
"Length of Compilation Unit Info");
dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number");
dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
&& DECL_NAME (TYPE_NAME (decl)))
e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
- else
+ else
e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
}
}
- else
+ else
e.name = xstrdup (dwarf2_name (decl, 1));
/* If we don't have a name for the type, there's no point in adding
for (i = 0; VEC_iterate (pubname_entry, names, i, pub); i++)
{
- /* We shouldn't see pubnames for DIEs outside of the main CU. */
+ /* We shouldn't see pubnames for DIEs outside of the main CU. */
if (names == pubname_table)
gcc_assert (pub->die->die_mark);
text_section_label, "Length");
if (flag_reorder_blocks_and_partition)
{
- dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label,
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label,
"Address");
dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label,
cold_text_section_label, "Length");
}
}
-struct file_name_acquire_data
+struct file_name_acquire_data
{
struct file_info *files;
int used_files;
f = d->filename;
while (f[0] == '.' && IS_DIR_SEPARATOR (f[1]))
f += 2;
-
+
/* Create a new array entry. */
fi->path = f;
fi->length = strlen (f);
fi->file_idx = d;
-
+
/* Search for the file name part. */
f = strrchr (f, DIR_SEPARATOR);
#if defined (DIR_SEPARATOR_2)
&& tree_int_cst_equal (TYPE_MAX_VALUE (type), TYPE_MAX_VALUE (subtype)))
{
/* The type and its subtype have the same representation. If in
- addition the two types also have the same name, then the given
- type is not a subrange type, but rather a plain base type. */
+ addition the two types also have the same name, then the given
+ type is not a subrange type, but rather a plain base type. */
/* FIXME: brobecker/2004-03-22:
- Sizetype INTEGER_CSTs nodes are canonicalized. It should
- therefore be sufficient to check the TYPE_SIZE node pointers
- rather than checking the actual size. Unfortunately, we have
- found some cases, such as in the Ada "integer" type, where
- this is not the case. Until this problem is solved, we need to
- keep checking the actual size. */
+ Sizetype INTEGER_CSTs nodes are canonicalized. It should
+ therefore be sufficient to check the TYPE_SIZE node pointers
+ rather than checking the actual size. Unfortunately, we have
+ found some cases, such as in the Ada "integer" type, where
+ this is not the case. Until this problem is solved, we need to
+ keep checking the actual size. */
tree type_name = TYPE_NAME (type);
tree subtype_name = TYPE_NAME (subtype);
if (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
- type_name = DECL_NAME (type_name);
+ type_name = DECL_NAME (type_name);
if (subtype_name != NULL && TREE_CODE (subtype_name) == TYPE_DECL)
- subtype_name = DECL_NAME (subtype_name);
+ subtype_name = DECL_NAME (subtype_name);
if (type_name == subtype_name)
- return false;
+ return false;
}
return true;
if (int_size_in_bytes (TREE_TYPE (type)) != size_in_bytes)
{
/* The size of the subrange type and its base type do not match,
- so we need to generate a size attribute for the subrange type. */
+ so we need to generate a size attribute for the subrange type. */
add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes);
}
if (TYPE_MIN_VALUE (type) != NULL)
add_bound_info (subrange_die, DW_AT_lower_bound,
- TYPE_MIN_VALUE (type));
+ TYPE_MIN_VALUE (type));
if (TYPE_MAX_VALUE (type) != NULL)
add_bound_info (subrange_die, DW_AT_upper_bound,
- TYPE_MAX_VALUE (type));
+ TYPE_MAX_VALUE (type));
return subrange_die;
}
= get_qualified_type (type,
((is_const_type ? TYPE_QUAL_CONST : 0)
| (is_volatile_type ? TYPE_QUAL_VOLATILE : 0)));
-
+
/* If we do, then we can just use its DIE, if it exists. */
if (qualified_type)
{
if (mod_type_die)
return mod_type_die;
}
-
+
name = qualified_type ? TYPE_NAME (qualified_type) : NULL;
-
+
/* Handle C typedef types. */
if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name))
{
tree dtype = TREE_TYPE (name);
-
+
if (qualified_type == dtype)
{
/* For a named type, use the typedef. */
context_die);
/* Else cv-qualified version of named type; fall through. */
}
-
+
if (is_const_type)
{
mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type);
else
{
gen_type_die (type, context_die);
-
+
/* We have to get the type_main_variant here (and pass that to the
`lookup_type_die' routine) because the ..._TYPE node we have
might simply be a *copy* of some original type node (where the
not the main variant. */
return lookup_type_die (type);
}
-
+
/* Builtin types don't have a DECL_ORIGINAL_TYPE. For those,
don't output a DW_TAG_typedef, since there isn't one in the
user's program; just attach a DW_AT_name to the type. */
name = DECL_NAME (name);
add_name_attribute (mod_type_die, IDENTIFIER_POINTER (name));
}
-
+
if (qualified_type)
equate_type_number_to_die (qualified_type, mod_type_die);
}
gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
: stack_pointer_rtx));
- offset += frame_pointer_fb_offset;
+ offset += frame_pointer_fb_offset;
- return new_loc_descr (DW_OP_fbreg, offset, 0);
+ return new_loc_descr (DW_OP_fbreg, offset, 0);
}
}
&& 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 ();
}
if (rtl == NULL_RTX)
return 0;
- else if (GET_CODE (rtl) == CONST_INT)
+ else if (GET_CODE (rtl) == CONST_INT)
{
HOST_WIDE_INT val = INTVAL (rtl);
if (TYPE_UNSIGNED (TREE_TYPE (loc)))
case MIN_EXPR:
case MAX_EXPR:
{
- const enum tree_code code =
- TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
+ const enum tree_code code =
+ TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
- loc = build3 (COND_EXPR, TREE_TYPE (loc),
+ loc = build3 (COND_EXPR, TREE_TYPE (loc),
build2 (code, integer_type_node,
TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
- TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+ TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
}
/* ... fall through ... */
/* Leave front-end specific codes as simply unknown. This comes
up, for instance, with the C STMT_EXPR. */
if ((unsigned int) TREE_CODE (loc)
- >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
+ >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
return 0;
#ifdef ENABLE_CHECKING
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;
{
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 if (DECL_P (*tp) && TREE_CODE (*tp) != FUNCTION_DECL)
+ else if (!flag_unit_at_a_time)
+ return NULL_TREE;
+ else if (!cgraph_global_info_ready
+ && (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
+ gcc_unreachable ();
+ else if (DECL_P (*tp) && TREE_CODE (*tp) == VAR_DECL)
{
struct varpool_node *node = varpool_node (*tp);
if (!node->needed)
return *tp;
}
+ else if (DECL_P (*tp) && TREE_CODE (*tp) == FUNCTION_DECL
+ && (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp)))
+ {
+ struct cgraph_node *node = cgraph_node (*tp);
+ if (!node->output)
+ return *tp;
+ }
return NULL_TREE;
}
CONCAT: FIXME! */
else if (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
;
- /* Vectors only work if their mode is supported by the target.
+ /* 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)
;
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL);
-
+
/* See if we possibly have multiple locations for this variable. */
loc_list = lookup_decl_loc (decl);
rtx varloc;
/* Now that we know what section we are using for a base,
- actually construct the list of locations.
+ actually construct the list of locations.
The first location information is what is passed to the
function that creates the location list, and the remaining
locations just get added on to that list.
/* Try to get some constant RTL for this decl, and use that as the value of
the location. */
-
+
rtl = rtl_for_decl_location (decl);
if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
{
add_const_value_attribute (die, rtl);
return;
}
-
+
/* If we have tried to generate the location otherwise, and it
didn't work out (we wouldn't be here if we did), and we have a one entry
location list, try generating a location from that. */
if (TYPE_P (fn))
fn = TYPE_STUB_DECL (fn);
-
+
fn = decl_function_context (fn);
if (fn)
dwarf2out_abstract_function (fn);
involved. */
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ! DECL_IGNORED_P (TYPE_NAME (type)))
- t = DECL_NAME (TYPE_NAME (type));
+ {
+ /* We want to be extra verbose. Don't call dwarf_name if
+ DECL_NAME isn't set. The default hook for decl_printable_name
+ doesn't like that, and in this context it's correct to return
+ 0, instead of "<anonymous>" or the like. */
+ if (DECL_NAME (TYPE_NAME (type)))
+ name = lang_hooks.dwarf_name (TYPE_NAME (type), 2);
+ }
/* Now get the name as a string, or invent one. */
- if (t != 0)
+ if (!name && t != 0)
name = IDENTIFIER_POINTER (t);
}
{
if (DECL_DECLARED_INLINE_P (decl))
{
- if (cgraph_function_possibly_inlined_p (decl))
+ if (cgraph_function_possibly_inlined_p (decl))
add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined);
else
add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined);
else
{
if (cgraph_function_possibly_inlined_p (decl))
- add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined);
+ add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined);
else
- add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined);
+ add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined);
}
equate_decl_number_to_die (decl, subr_die);
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
current_function_funcdef_no);
add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
-
+
add_pubname (decl, subr_die);
add_arange (decl, subr_die);
}
/* Compute a displacement from the "steady-state frame pointer" to
the CFA. The former is what all stack slots and argument slots
- will reference in the rtl; the later is what we've told the
+ will reference in the rtl; the later is what we've told the
debugger about. We'll need to adjust all frame_base references
by this displacement. */
compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
the program. For example, consider the C++
test case:
- template <class T>
- struct S { static const int i = 7; };
+ template <class T>
+ struct S { static const int i = 7; };
+
+ template <class T>
+ const int S<T>::i;
- template <class T>
- const int S<T>::i;
+ int f() { return S<int>::i; }
- int f() { return S<int>::i; }
-
Here, S<int>::i is not DECL_EXTERNAL, but no
definition is required, so the compiler will
- not emit a definition. */
+ not emit a definition. */
|| (TREE_CODE (decl) == VAR_DECL
&& DECL_COMDAT (decl) && !TREE_ASM_WRITTEN (decl))
|| class_or_namespace_scope_p (context_die));
add_AT_unsigned (die, DW_AT_call_line, s.line);
}
+
+/* If STMT's abstract origin is a function declaration and STMT's
+ first subblock's abstract origin is the function's outermost block,
+ then we're looking at the main entry point. */
+static bool
+is_inlined_entry_point (tree stmt)
+{
+ tree decl, block;
+
+ if (!stmt || TREE_CODE (stmt) != BLOCK)
+ return false;
+
+ decl = block_ultimate_origin (stmt);
+
+ if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
+
+ block = BLOCK_SUBBLOCKS (stmt);
+
+ if (block)
+ {
+ if (TREE_CODE (block) != BLOCK)
+ return false;
+
+ block = block_ultimate_origin (block);
+ }
+
+ return block == DECL_INITIAL (decl);
+}
+
/* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
Add low_pc and high_pc attributes to the DIE for a block STMT. */
{
tree chain;
+ if (is_inlined_entry_point (stmt))
+ {
+ ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
+ BLOCK_NUMBER (stmt));
+ add_AT_lbl_id (die, DW_AT_entry_pc, label);
+ }
+
add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
chain = BLOCK_FRAGMENT_CHAIN (stmt);
if (debug_info_level > DINFO_LEVEL_TERSE)
/* We are not in terse mode so *any* local declaration counts
as being a "significant" one. */
- must_output_die = (BLOCK_VARS (stmt) != NULL
- && (TREE_USED (stmt)
+ must_output_die = (BLOCK_VARS (stmt) != NULL
+ && (TREE_USED (stmt)
|| TREE_ASM_WRITTEN (stmt)
|| BLOCK_ABSTRACT (stmt)));
else
for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
{
dw_die_ref die;
-
+
if (TREE_CODE (decl) == FUNCTION_DECL)
die = lookup_decl_die (decl);
else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
die = lookup_type_die (TREE_TYPE (decl));
else
die = NULL;
-
+
if (die != NULL && die->die_parent == NULL)
add_child_die (context_die, die);
/* Do not produce debug information for static variables since
return decl_die;
}
-/* Returns the DIE for TYPE. A DIE is always returned. */
+/* Returns the DIE for TYPE, that must not be a base type. A DIE is
+ always returned. */
static dw_die_ref
force_type_die (tree type)
/* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE. */
if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
- at_import_die = force_type_die (TREE_TYPE (decl));
+ {
+ if (is_base_type (TREE_TYPE (decl)))
+ at_import_die = base_type_die (TREE_TYPE (decl));
+ else
+ at_import_die = force_type_die (TREE_TYPE (decl));
+ }
else
{
at_import_die = lookup_decl_die (decl);
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
if (lookup_decl_die (decl) != NULL)
- return;
+ return;
break;
case TYPE_DECL:
else
fd->emitted_number = 1;
last_emitted_file = fd;
-
+
if (DWARF2_ASM_LINE_DEBUG_INFO)
{
fprintf (asm_out_file, "\t.file %u ", fd->emitted_number);
fputc ('\n', asm_out_file);
}
}
-
+
return fd->emitted_number;
}
dwarf2out_begin_function (tree fun)
{
htab_empty (decl_loc_table);
-
+
if (function_section (fun) != text_section)
have_multiple_function_sections = true;
}
&& line != 0)
{
int file_num = maybe_emit_file (lookup_filename (filename));
-
+
switch_to_section (current_function_section ());
/* If requested, emit something human-readable. */
else if (function_section (current_function_decl) != text_section)
{
dw_separate_line_info_ref line_info;
- targetm.asm_out.internal_label (asm_out_file,
+ targetm.asm_out.internal_label (asm_out_file,
SEPARATE_LINE_CODE_LABEL,
separate_line_info_table_in_use);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
DEBUG_ABBREV_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
- ASM_GENERATE_INTERNAL_LABEL (cold_text_section_label,
+ ASM_GENERATE_INTERNAL_LABEL (cold_text_section_label,
COLD_TEXT_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (cold_end_label, COLD_END_LABEL, 0);
verify_marks_clear (dw_die_ref die)
{
dw_die_ref c;
-
+
gcc_assert (! die->die_mark);
FOR_EACH_CHILD (die, c, verify_marks_clear (c));
}
prune_unmark_dies (dw_die_ref die)
{
dw_die_ref c;
-
+
if (die->die_mark)
die->die_mark = 0;
FOR_EACH_CHILD (die, c, prune_unmark_dies (c));
prune_unused_types_walk_attribs (die);
/* If this node is a specification,
- also mark the definition, if it exists. */
+ also mark the definition, if it exists. */
if (get_AT_flag (die, DW_AT_declaration) && die->die_definition)
- prune_unused_types_mark (die->die_definition, 1);
+ prune_unused_types_mark (die->die_definition, 1);
}
if (dokids && die->die_mark != 2)
if (! die->die_child)
return;
-
+
c = die->die_child;
do {
dw_die_ref prev = c;
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_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)