cfa_temp_value = INTVAL (src);
break;
+ case IOR:
+ assert (GET_CODE (XEXP (src, 0)) == REG
+ && REGNO (XEXP (src, 0)) == cfa_temp_reg);
+ assert (REGNO (dest) == cfa_temp_reg);
+ assert (GET_CODE (XEXP (src, 1)) == CONST_INT);
+ cfa_temp_value |= INTVAL (XEXP (src, 1));
+ break;
+
default:
abort ();
}
}
pubname_entry;
+/* The limbo die list structure. */
+typedef struct limbo_die_struct
+{
+ dw_die_ref die;
+ struct limbo_die_struct *next;
+}
+limbo_die_node;
+
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
(DECL_NAME (decl) == NULL_TREE \
|| (DECL_ARTIFICIAL (decl) \
&& is_tagged_type (TREE_TYPE (decl)) \
- && decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
+ && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \
+ /* This is necessary for stub decls that \
+ appear in nested inline functions. */ \
+ || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \
+ && (decl_ultimate_origin (decl) \
+ == TYPE_STUB_DECL (TREE_TYPE (decl)))))))
/* Information concerning the compilation unit's programming
language, and compiler version. */
/* Record the root of the DIE's built for the current compilation unit. */
static dw_die_ref comp_unit_die;
-/* The number of DIEs with a NULL parent waiting to be relocated. */
-static int limbo_die_count;
+/* A list of DIEs with a NULL parent waiting to be relocated. */
+static limbo_die_node *limbo_die_list = 0;
/* Pointer to an array of filenames referenced by this compilation unit. */
static char **file_table;
static unsigned simple_type_align_in_bits PROTO((tree));
static unsigned simple_type_size_in_bits PROTO((tree));
static unsigned field_byte_offset PROTO((tree));
-static void add_location_attribute PROTO((dw_die_ref, rtx));
+static void add_AT_location_description PROTO((dw_die_ref,
+ enum dwarf_attribute, rtx));
static void add_data_member_location_attribute PROTO((dw_die_ref, tree));
static void add_const_value_attribute PROTO((dw_die_ref, rtx));
static void add_location_or_const_value_attribute PROTO((dw_die_ref, tree));
if (parent_die != NULL)
add_child_die (parent_die, die);
else
- ++limbo_die_count;
+ {
+ limbo_die_node *limbo_node;
+
+ limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node));
+ limbo_node->die = die;
+ limbo_node->next = limbo_die_list;
+ limbo_die_list = limbo_node;
+ }
return die;
}
/* The following routines define various Dwarf attributes and any data
associated with them. */
+/* Add a location description attribute value to a DIE.
-/* Output the form of location attributes suitable for whole variables and
+ This emits location attributes suitable for whole variables and
whole parameters. Note that the location attributes for struct fields are
generated by the routine `data_member_location_attribute' below. */
static void
-add_location_attribute (die, rtl)
+add_AT_location_description (die, attr_kind, rtl)
dw_die_ref die;
+ enum dwarf_attribute attr_kind;
register rtx rtl;
{
dw_loc_descr_ref loc_descr = NULL;
loc_descr = loc_descriptor (gen_rtx (REG, word_mode, 0));
#endif
- add_AT_loc (die, DW_AT_location, loc_descr);
+ add_AT_loc (die, attr_kind, loc_descr);
}
/* Attach the specialized form of location attribute used for data
case MEM:
case REG:
case SUBREG:
- add_location_attribute (die, rtl);
+ add_AT_location_description (die, DW_AT_location, rtl);
break;
default:
register tree bound;
{
register unsigned bound_value = 0;
+
+ /* If this is an Ada unconstrained array type, then don't emit any debug
+ info because the array bounds are unknown. They are parameterized when
+ the type is instantiated. */
+ if (contains_placeholder_p (bound))
+ return;
+
switch (TREE_CODE (bound))
{
case ERROR_MARK:
register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
- add_location_attribute (decl_die, SAVE_EXPR_RTL (bound));
+ add_AT_location_description (decl_die, DW_AT_location,
+ SAVE_EXPR_RTL (bound));
add_AT_die_ref (subrange_die, bound_attr, decl_die);
}
/* Else leave out the attribute. */
break;
+ case MAX_EXPR:
+ case VAR_DECL:
+ /* ??? These types of bounds can be created by the Ada front end,
+ and it isn't clear how to emit debug info for them. */
+ break;
+
default:
abort ();
}
/* define the index type. */
if (TREE_TYPE (domain))
- add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0,
- type_die);
+ {
+ /* ??? This is probably an Ada unnamed subrange type. Ignore the
+ TREE_TYPE field. We can't emit debug info for this
+ because it is an unnamed integral type. */
+ if (TREE_CODE (domain) == INTEGER_TYPE
+ && TYPE_NAME (domain) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE
+ && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE)
+ ;
+ else
+ add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0,
+ type_die);
+ }
add_bound_info (subrange_die, DW_AT_lower_bound, lower);
add_bound_info (subrange_die, DW_AT_upper_bound, upper);
register tree containing_scope;
register unsigned long i;
- /* Function-local tags and functions get stuck in limbo until they are
- fixed up by decls_for_scope. */
- if (context_die == NULL
- && (TREE_CODE (t) == FUNCTION_DECL || is_tagged_type (t)))
- return NULL;
-
/* Walk back up the declaration tree looking for a place to define
this type. */
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
else
containing_scope = DECL_CONTEXT (t);
+ /* Function-local tags and functions get stuck in limbo until they are
+ fixed up by decls_for_scope. */
+ if (context_die == NULL && containing_scope != NULL_TREE
+ && (TREE_CODE (t) == FUNCTION_DECL || is_tagged_type (t)))
+ return NULL;
+
if (containing_scope == NULL_TREE)
scope_die = comp_unit_die;
else
register enum tree_code code = TREE_CODE (type);
register dw_die_ref type_die = NULL;
- /* If this type is an unnamed subtype of an integral or floating-point
- type, use the inner type. */
+ /* ??? If this type is an unnamed subrange type of an integral or
+ floating-point type, use the inner type. This is because we have no
+ support for unnamed types in base_type_die. This can happen if this is
+ an Ada subrange type. Correct solution is emit a subrange type die. */
if ((code == INTEGER_TYPE || code == REAL_TYPE)
&& TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0)
type = TREE_TYPE (type), code = TREE_CODE (type);
if (type_tag (type))
add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
+ /* If the first reference to this type was as the return type of an
+ inline function, then it may not have a parent. Fix this now. */
+ if (type_die->die_parent == NULL)
+ add_child_die (scope_die_for (type, context_die), type_die);
+
for (link = TYPE_FIELDS (type);
link != NULL; link = TREE_CHAIN (link))
{
= frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
+#if 0
+ /* ??? This fails for nested inline functions, because context_display
+ is not part of the state saved/restored for inline functions. */
if (current_function_needs_context)
- add_AT_loc (subr_die, DW_AT_static_link,
- loc_descriptor (lookup_static_chain (decl)));
+ add_AT_location_description (subr_die, DW_AT_static_link,
+ lookup_static_chain (decl));
+#endif
}
/* Now output descriptions of the arguments for this function. This gets
if (type_tag (type))
add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
+ /* If the first reference to this type was as the return type of an
+ inline function, then it may not have a parent. Fix this now. */
+ if (type_die->die_parent == NULL)
+ add_child_die (scope_die, type_die);
+
push_decl_scope (type);
gen_member_die (type, type_die);
pop_decl_scope ();
die = NULL;
if (die != NULL && die->die_parent == NULL)
- {
- add_child_die (context_die, die);
- --limbo_die_count;
- }
+ add_child_die (context_die, die);
else
gen_decl_die (decl, context_die);
}
having been instantiated from some other (original) TYPE_DECL node
(e.g. one which was generated within the original definition of an
inline function) we have to generate a special (abbreviated)
- DW_TAG_structure_type, DW_TAG_union_type, or DW_TAG_enumeration-type
+ DW_TAG_structure_type, DW_TAG_union_type, or DW_TAG_enumeration_type
DIE here. */
if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
{
void
dwarf2out_finish ()
{
+ limbo_die_node *node, *next_node;
+ dw_die_ref die;
+ dw_attr_ref a;
+
+ /* Traverse the limbo die list, and add parent/child links. The only
+ dies without parents that should be here are concrete instances of
+ inline functions, and the comp_unit_die. We can ignore the comp_unit_die.
+ For concrete instances, we can get the parent die from the abstract
+ instance. */
+ for (node = limbo_die_list; node; node = next_node)
+ {
+ next_node = node->next;
+ die = node->die;
+
+ if (die->die_parent == NULL)
+ {
+ a = get_AT (die, DW_AT_abstract_origin);
+ if (a)
+ add_child_die (a->dw_attr_val.v.val_die_ref->die_parent, die);
+ else if (die == comp_unit_die)
+ ;
+ else
+ abort ();
+ }
+ free (node);
+ }
+
/* Traverse the DIE tree and add sibling attributes to those DIE's
that have children. */
add_sibling_attributes (comp_unit_die);
ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);
output_aranges ();
}
-
- /* The only DIE we should have with a parent of NULL is comp_unit_die. */
- assert (limbo_die_count == 1);
}
#endif /* DWARF2_DEBUGGING_INFO */