/* Various versions of targetm.eh_frame_section. Note these must appear
outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro guards. */
-/* Version of targetm.eh_frame_section for systems with named sections. */
+/* Version of targetm.eh_frame_section for systems with named sections. */
void
named_section_eh_frame_section (void)
{
#endif
}
-/* Version of targetm.eh_frame_section for systems using collect2. */
+/* Version of targetm.eh_frame_section for systems using collect2. */
void
collect2_eh_frame_section (void)
{
more efficient data structure. */
static GTY(()) struct reg_saved_in_data regs_saved_in_regs[4];
static GTY(()) size_t num_regs_saved_in_regs;
-
+
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
static const char *last_reg_save_label;
unsigned int regn = REGNO (reg);
size_t i;
struct queued_reg_save *q;
-
+
for (q = queued_reg_saves; q; q = q->next)
if (q->saved_reg && regn == REGNO (q->saved_reg))
return q->reg;
the intent is to save the value of SP from the previous frame.
In addition, if a register has previously been saved to a different
- register,
+ register,
Invariants / Summaries of Rules
{
/* Rule 1 */
/* Update the CFA rule wrt SP or FP. Make sure src is
- relative to the current CFA register.
+ relative to the current CFA register.
We used to require that dest be either SP or FP, but the
ARM copies SP to a temporary register, and from there to
case LO_SUM:
{
int regno;
-
+
gcc_assert (GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
offset = INTVAL (XEXP (XEXP (dest, 0), 1));
if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset;
regno = REGNO (XEXP (XEXP (dest, 0), 0));
-
+
if (cfa_store.reg == (unsigned) regno)
offset -= cfa_store.offset;
else
case REG:
{
int regno = REGNO (XEXP (dest, 0));
-
+
if (cfa_store.reg == (unsigned) regno)
offset = -cfa_store.offset;
else
if (insn == NULL_RTX)
{
size_t i;
-
+
/* Flush any queued register saves. */
flush_queued_reg_saves ();
cfa_store = cfa;
cfa_temp.reg = -1;
cfa_temp.offset = 0;
-
+
for (i = 0; i < num_regs_saved_in_regs; i++)
{
regs_saved_in_regs[i].orig_reg = NULL_RTX;
static inline int local_scope_p (dw_die_ref);
static inline int class_or_namespace_scope_p (dw_die_ref);
static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
+static void add_calling_convention_attribute (dw_die_ref, tree);
static const char *type_tag (tree);
static tree member_declared_type (tree);
#if 0
char label[32];
gcc_assert (a && AT_class (a) == dw_val_class_str);
-
+
node = a->dw_attr_val.v.val_str;
if (node->form)
return node->form;
-
+
len = strlen (node->str) + 1;
/* If the string is shorter or equal to the size of the reference, it is
case ASHIFT:
op = DW_OP_shl;
goto do_binop;
-
+
case ASHIFTRT:
op = DW_OP_shra;
goto do_binop;
if (TREE_CODE (decl) == ERROR_MARK)
return 0;
-
+
gcc_assert (TREE_CODE (decl) == FIELD_DECL);
type = field_type (decl);
if (val < 0)
add_AT_int (die, DW_AT_const_value, val);
- else
+ else
add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
}
break;
{
rtx elt = CONST_VECTOR_ELT (rtl, i);
HOST_WIDE_INT lo, hi;
-
+
switch (GET_CODE (elt))
{
case CONST_INT:
lo = INTVAL (elt);
hi = -(lo < 0);
break;
-
+
case CONST_DOUBLE:
lo = CONST_DOUBLE_LOW (elt);
hi = CONST_DOUBLE_HIGH (elt);
break;
-
+
default:
gcc_unreachable ();
}
-
+
if (elt_size <= sizeof (HOST_WIDE_INT))
insert_int (lo, elt_size, p);
else
{
unsigned char *p0 = p;
unsigned char *p1 = p + sizeof (HOST_WIDE_INT);
-
+
gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
if (WORDS_BIG_ENDIAN)
{
TREE_STRING_LENGTH (init) - 1) == 0
&& ((size_t) TREE_STRING_LENGTH (init)
== strlen (TREE_STRING_POINTER (init)) + 1))
- rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init));
+ rtl = gen_rtx_CONST_STRING (VOIDmode,
+ ggc_strdup (TREE_STRING_POINTER (init)));
}
/* If the initializer is something that we know will expand into an
immediate RTL constant, expand it now. Expanding anything else
add_AT_die_ref (object_die, DW_AT_type, type_die);
}
+/* Given an object die, add the calling convention attribute for the
+ function call type. */
+static void
+add_calling_convention_attribute (dw_die_ref subr_die, tree type)
+{
+ enum dwarf_calling_convention value = DW_CC_normal;
+
+ value = targetm.dwarf_calling_convention (type);
+
+ /* Only add the attribute if the backend requests it, and
+ is not DW_CC_normal. */
+ if (value && (value != DW_CC_normal))
+ add_AT_unsigned (subr_die, DW_AT_calling_convention, value);
+}
+
/* Given a tree pointer to a struct, class, union, or enum type node, return
a pointer to the (string) tag name for the given type, or zero if the type
was declared without a tag. */
subr_die = old_die;
/* Clear out the declaration attribute and the formal parameters.
- Do not remove all children, because it is possible that this
+ Do not remove all children, because it is possible that this
declaration die was forced using force_decl_die(). In such
cases die that forced declaration die (e.g. TAG_imported_module)
is one of the children that we do not want to remove. */
/* The first time we see a member function, it is in the context of
the class to which it belongs. We make sure of this by emitting
the class first. The next time is the definition, which is
- handled above. The two may come from the same source text.
+ handled above. The two may come from the same source text.
Note that force_decl_die() forces function declaration die. It is
later reused to represent definition. */
equate_type_number_to_die (type, subr_die);
add_prototyped_attribute (subr_die, type);
add_type_attribute (subr_die, return_type, 0, 0, context_die);
+ add_calling_convention_attribute (subr_die, type);
gen_formal_types_die (type, subr_die);
}
save_fn = current_function_decl;
current_function_decl = NULL_TREE;
gen_subprogram_die (decl, context_die);
- current_function_decl = save_fn;
+ current_function_decl = save_fn;
break;
case VAR_DECL:
default:
gcc_unreachable ();
}
-
+
/* See if we can find the die for this deci now.
If not then abort. */
if (!decl_die)
decl_die = lookup_decl_die (decl);
gcc_assert (decl_die);
}
-
+
return decl_die;
}
dwarf2out_decl (decl);
}
-/* Output debug information for imported module or decl. */
-
+/* Output debug information for imported module or decl. */
+
static void
dwarf2out_imported_module_or_decl (tree decl, tree context)
{
dw_die_ref scope_die;
unsigned file_index;
expanded_location xloc;
-
+
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
gcc_assert (decl);
/* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
- We need decl DIE for reference and scope die. First, get DIE for the decl
+ We need decl DIE for reference and scope die. First, get DIE for the decl
itself. */
/* Get the scope die for decl context. Use comp_unit_die for global module
at_import_die = force_type_die (TREE_TYPE (decl));
else
at_import_die = force_decl_die (decl);
-
- /* OK, now we have DIEs for decl as well as scope. Emit imported die. */
+
+ /* OK, now we have DIEs for decl as well as scope. Emit imported die. */
if (TREE_CODE (decl) == NAMESPACE_DECL)
imported_die = new_die (DW_TAG_imported_module, scope_die, context);
else
return file_table_last_lookup_index;
}
- /* Didn't match the previous lookup, search the table */
+ /* Didn't match the previous lookup, search the table. */
n = VARRAY_ACTIVE_SIZE (file_table);
for (i = 1; i < n; i++)
if (strcmp (file_name, VARRAY_CHAR_PTR (file_table, i)) == 0)
abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT
* sizeof (dw_die_ref));
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
- /* Zero-th entry is allocated, but unused */
+ /* Zero-th entry is allocated, but unused. */
abbrev_die_table_in_use = 1;
/* Allocate the initial hunk of the line_info_table. */
* sizeof (dw_line_info_entry));
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
- /* Zero-th entry is allocated, but unused */
+ /* Zero-th entry is allocated, but unused. */
line_info_table_in_use = 1;
/* Generate the initial DIE for the .debug section. Note that the (string)
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
DEBUG_ABBREV_SECTION_LABEL, 0);
- if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
- ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
- else
- strcpy (text_section_label, stripattributes (TEXT_SECTION_NAME));
+ ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
DEBUG_INFO_SECTION_LABEL, 0);
ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
}
- if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
- {
- text_section ();
- ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
- }
+ text_section ();
+ ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
}
/* A helper function for dwarf2out_finish called through
prune_unused_types_prune (dw_die_ref die)
{
dw_die_ref c, p, n;
-
+
gcc_assert (die->die_mark);
p = NULL;
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. */
+ this to be a child of the containing function.
+
+ It may happen that even the containing function got fully
+ inlined and optimized out. In that case we are lost and
+ assign the empty child. This should not be big issue as
+ the function is likely unreachable too. */
tree context = NULL_TREE;
gcc_assert (node->created_for);
context = DECL_CONTEXT (node->created_for);
else if (TYPE_P (node->created_for))
context = TYPE_CONTEXT (node->created_for);
-
+
gcc_assert (context && TREE_CODE (context) == FUNCTION_DECL);
-
+
origin = lookup_decl_die (context);
- gcc_assert (origin);
- add_child_die (origin, die);
+ if (origin)
+ add_child_die (origin, die);
+ else
+ add_child_die (comp_unit_die, die);
}
}
}