{
int enc;
+#ifdef MIPS_DEBUGGING_INFO
+ return false;
+#endif
if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
return false;
if (!eh_personality_libfunc)
static void dwarf2out_global_decl (tree);
static void dwarf2out_type_decl (tree, int);
static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
+static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
+ dw_die_ref);
static void dwarf2out_abstract_function (tree);
static void dwarf2out_var_location (rtx);
static void dwarf2out_begin_function (tree);
The key is a DECL_UID() which is a unique number identifying each decl. */
static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
+/* A hash table of references to DIE's that describe COMMON blocks.
+ The key is DECL_UID() ^ die_parent. */
+static GTY ((param_is (struct die_struct))) htab_t common_block_die_table;
+
/* Node of the variable location list. */
struct var_loc_node GTY ((chain_next ("%h.next")))
{
static hashval_t decl_die_table_hash (const void *);
static int decl_die_table_eq (const void *, const void *);
static dw_die_ref lookup_decl_die (tree);
+static hashval_t common_block_die_table_hash (const void *);
+static int common_block_die_table_eq (const void *, const void *);
static hashval_t decl_loc_table_hash (const void *);
static int decl_loc_table_eq (const void *, const void *);
static var_loc_list *lookup_decl_loc (const_tree);
static void add_sibling_attributes (dw_die_ref);
static void build_abbrev_table (dw_die_ref);
static void output_location_lists (dw_die_ref);
-static int constant_size (long unsigned);
+static int constant_size (unsigned HOST_WIDE_INT);
static unsigned long size_of_die (dw_die_ref);
static void calc_die_sizes (dw_die_ref);
static void mark_dies (dw_die_ref);
static void gen_formal_types_die (tree, dw_die_ref);
static void gen_subprogram_die (tree, dw_die_ref);
static void gen_variable_die (tree, dw_die_ref);
+static void gen_const_die (tree, dw_die_ref);
static void gen_label_die (tree, dw_die_ref);
static void gen_lexical_block_die (tree, dw_die_ref, int);
static void gen_inlined_subroutine_die (tree, dw_die_ref, int);
/* Return the power-of-two number of bytes necessary to represent VALUE. */
static int
-constant_size (long unsigned int value)
+constant_size (unsigned HOST_WIDE_INT value)
{
int log;
size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */
break;
case dw_val_class_vec:
- size += 1 + (a->dw_attr_val.v.val_vec.length
- * a->dw_attr_val.v.val_vec.elt_size); /* block */
+ size += constant_size (a->dw_attr_val.v.val_vec.length
+ * a->dw_attr_val.v.val_vec.elt_size)
+ + a->dw_attr_val.v.val_vec.length
+ * a->dw_attr_val.v.val_vec.elt_size; /* block */
break;
case dw_val_class_flag:
size += 1;
case dw_val_class_long_long:
return DW_FORM_block1;
case dw_val_class_vec:
- return DW_FORM_block1;
+ switch (constant_size (a->dw_attr_val.v.val_vec.length
+ * a->dw_attr_val.v.val_vec.elt_size))
+ {
+ case 1:
+ return DW_FORM_block1;
+ case 2:
+ return DW_FORM_block2;
+ case 4:
+ return DW_FORM_block4;
+ default:
+ gcc_unreachable ();
+ }
case dw_val_class_flag:
return DW_FORM_flag;
case dw_val_class_die_ref:
unsigned int i;
unsigned char *p;
- dw2_asm_output_data (1, len * elt_size, "%s", name);
+ dw2_asm_output_data (constant_size (len * elt_size),
+ len * elt_size, "%s", name);
if (elt_size > sizeof (HOST_WIDE_INT))
{
elt_size /= 2;
return cc_loc_result;
}
+/* Try to handle TLS MEMs, for which mem_loc_descriptor on XEXP (mem, 0)
+ failed. */
+
+static dw_loc_descr_ref
+tls_mem_loc_descriptor (rtx mem)
+{
+ tree base;
+ dw_loc_descr_ref loc_result, loc_result2;
+
+ if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
+ return NULL;
+
+ base = get_base_address (MEM_EXPR (mem));
+ if (base == NULL
+ || TREE_CODE (base) != VAR_DECL
+ || !DECL_THREAD_LOCAL_P (base))
+ return NULL;
+
+ loc_result = loc_descriptor_from_tree_1 (MEM_EXPR (mem), 2);
+ if (loc_result == NULL)
+ return NULL;
+
+ if (INTVAL (MEM_OFFSET (mem)))
+ {
+ if (INTVAL (MEM_OFFSET (mem)) >= 0)
+ add_loc_descr (&loc_result,
+ new_loc_descr (DW_OP_plus_uconst,
+ INTVAL (MEM_OFFSET (mem)), 0));
+ else
+ {
+ loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem),
+ VAR_INIT_STATUS_INITIALIZED);
+ if (loc_result2 == 0)
+ return NULL;
+ add_loc_descr (&loc_result, loc_result2);
+ add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0));
+ }
+ }
+
+ return 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
distinction between OP_REG and OP_BASEREG. */
if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
mem_loc_result = based_loc_descr (rtl, 0, VAR_INIT_STATUS_INITIALIZED);
+ else if (stack_realign_drap
+ && crtl->drap_reg
+ && crtl->args.internal_arg_pointer == rtl
+ && REGNO (crtl->drap_reg) < FIRST_PSEUDO_REGISTER)
+ {
+ /* If RTL is internal_arg_pointer, which has been optimized
+ out, use DRAP instead. */
+ mem_loc_result = based_loc_descr (crtl->drap_reg, 0,
+ VAR_INIT_STATUS_INITIALIZED);
+ }
break;
case MEM:
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
VAR_INIT_STATUS_INITIALIZED);
+ if (mem_loc_result == NULL)
+ mem_loc_result = tls_mem_loc_descriptor (rtl);
if (mem_loc_result != 0)
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
break;
INTVAL (XEXP (rtl, 1)), 0));
else
{
- add_loc_descr (&mem_loc_result,
- mem_loc_descriptor (XEXP (rtl, 1), mode,
- VAR_INIT_STATUS_INITIALIZED));
+ dw_loc_descr_ref mem_loc_result2
+ = mem_loc_descriptor (XEXP (rtl, 1), mode,
+ VAR_INIT_STATUS_INITIALIZED);
+ if (mem_loc_result2 == 0)
+ break;
+ add_loc_descr (&mem_loc_result, mem_loc_result2);
add_loc_descr (&mem_loc_result,
new_loc_descr (DW_OP_plus, 0, 0));
}
VAR_INIT_STATUS_INITIALIZED);
break;
+ case UNSPEC:
+ /* If delegitimize_address couldn't do anything with the UNSPEC, we
+ can't express it in the debug info. This can happen e.g. with some
+ TLS UNSPECs. */
+ break;
+
default:
gcc_unreachable ();
}
case MEM:
loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
initialized);
+ if (loc_result == NULL)
+ loc_result = tls_mem_loc_descriptor (rtl);
break;
case CONCAT:
/* Create the first one, so we have something to add to. */
loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
initialized);
+ if (loc_result == NULL)
+ return NULL;
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
for (i = 1; i < num_elem; i++)
temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
initialized);
+ if (temp == NULL)
+ return NULL;
add_loc_descr (&loc_result, temp);
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
/* The way DW_OP_GNU_push_tls_address is specified, we
can only look up addresses of objects in the current
module. */
- if (DECL_EXTERNAL (loc))
+ if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc))
return 0;
first_op = INTERNAL_DW_OP_tls_addr;
second_op = DW_OP_GNU_push_tls_address;
if (offset != NULL_TREE)
{
/* Variable offset. */
- add_loc_descr (&ret, loc_descriptor_from_tree_1 (offset, 0));
+ ret1 = loc_descriptor_from_tree_1 (offset, 0);
+ if (ret1 == 0)
+ return 0;
+ add_loc_descr (&ret, ret1);
add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
}
return secname;
}
-/* Check whether decl is a Fortran COMMON symbol. If not, NULL_RTX is returned.
- If so, the rtx for the SYMBOL_REF for the COMMON block is returned, and the
+/* Check whether decl is a Fortran COMMON symbol. If not, NULL_TREE is
+ returned. If so, the decl for the COMMON block is returned, and the
value is the offset into the common block for the symbol. */
static tree
tree_add_const_value_attribute (die, decl);
}
+/* Helper function for tree_add_const_value_attribute. Natively encode
+ initializer INIT into an array. Return true if successful. */
+
+static bool
+native_encode_initializer (tree init, unsigned char *array, int size)
+{
+ tree type;
+
+ if (init == NULL_TREE)
+ return false;
+
+ STRIP_NOPS (init);
+ switch (TREE_CODE (init))
+ {
+ case STRING_CST:
+ type = TREE_TYPE (init);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree enttype = TREE_TYPE (type);
+ enum machine_mode mode = TYPE_MODE (enttype);
+
+ if (GET_MODE_CLASS (mode) != MODE_INT || GET_MODE_SIZE (mode) != 1)
+ return false;
+ if (int_size_in_bytes (type) != size)
+ return false;
+ if (size > TREE_STRING_LENGTH (init))
+ {
+ memcpy (array, TREE_STRING_POINTER (init),
+ TREE_STRING_LENGTH (init));
+ memset (array + TREE_STRING_LENGTH (init),
+ '\0', size - TREE_STRING_LENGTH (init));
+ }
+ else
+ memcpy (array, TREE_STRING_POINTER (init), size);
+ return true;
+ }
+ return false;
+ case CONSTRUCTOR:
+ type = TREE_TYPE (init);
+ if (int_size_in_bytes (type) != size)
+ return false;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ HOST_WIDE_INT min_index;
+ unsigned HOST_WIDE_INT cnt;
+ int curpos = 0, fieldsize;
+ constructor_elt *ce;
+
+ if (TYPE_DOMAIN (type) == NULL_TREE
+ || !host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0))
+ return false;
+
+ fieldsize = int_size_in_bytes (TREE_TYPE (type));
+ if (fieldsize <= 0)
+ return false;
+
+ min_index = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0);
+ memset (array, '\0', size);
+ for (cnt = 0;
+ VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce);
+ cnt++)
+ {
+ tree val = ce->value;
+ tree index = ce->index;
+ int pos = curpos;
+ if (index && TREE_CODE (index) == RANGE_EXPR)
+ pos = (tree_low_cst (TREE_OPERAND (index, 0), 0) - min_index)
+ * fieldsize;
+ else if (index)
+ pos = (tree_low_cst (index, 0) - min_index) * fieldsize;
+
+ if (val)
+ {
+ STRIP_NOPS (val);
+ if (!native_encode_initializer (val, array + pos, fieldsize))
+ return false;
+ }
+ curpos = pos + fieldsize;
+ if (index && TREE_CODE (index) == RANGE_EXPR)
+ {
+ int count = tree_low_cst (TREE_OPERAND (index, 1), 0)
+ - tree_low_cst (TREE_OPERAND (index, 0), 0);
+ while (count > 0)
+ {
+ if (val)
+ memcpy (array + curpos, array + pos, fieldsize);
+ curpos += fieldsize;
+ }
+ }
+ gcc_assert (curpos <= size);
+ }
+ return true;
+ }
+ else if (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ {
+ tree field = NULL_TREE;
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
+
+ if (int_size_in_bytes (type) != size)
+ return false;
+
+ if (TREE_CODE (type) == RECORD_TYPE)
+ field = TYPE_FIELDS (type);
+
+ for (cnt = 0;
+ VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce);
+ cnt++, field = field ? TREE_CHAIN (field) : 0)
+ {
+ tree val = ce->value;
+ int pos, fieldsize;
+
+ if (ce->index != 0)
+ field = ce->index;
+
+ if (val)
+ STRIP_NOPS (val);
+
+ if (field == NULL_TREE || DECL_BIT_FIELD (field))
+ return false;
+
+ if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+ && TYPE_DOMAIN (TREE_TYPE (field))
+ && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
+ return false;
+ else if (DECL_SIZE_UNIT (field) == NULL_TREE
+ || !host_integerp (DECL_SIZE_UNIT (field), 0))
+ return false;
+ fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 0);
+ pos = int_byte_position (field);
+ gcc_assert (pos + fieldsize <= size);
+ if (val
+ && !native_encode_initializer (val, array + pos, fieldsize))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ case VIEW_CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ return native_encode_initializer (TREE_OPERAND (init, 0), array, size);
+ default:
+ return native_encode_expr (init, array, size) == size;
+ }
+}
+
/* If we don't have a copy of this variable in memory for some reason (such
as a C++ member constant that doesn't have an out-of-line definition),
we should tell the debugger about the constant value. */
static void
tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
{
- tree init = DECL_INITIAL (decl);
+ tree init;
tree type = TREE_TYPE (decl);
rtx rtl;
+ if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL)
+ return;
+
+ init = DECL_INITIAL (decl);
if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init)
/* OK */;
else
rtl = rtl_for_decl_init (init, type);
if (rtl)
add_const_value_attribute (var_die, rtl);
+ /* If the host and target are sane, try harder. */
+ else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
+ && initializer_constant_valid_p (init, type))
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (init));
+ if (size > 0 && (int) size == size)
+ {
+ unsigned char *array = GGC_CNEWVEC (unsigned char, size);
+
+ if (native_encode_initializer (init, array, size))
+ add_AT_vec (var_die, DW_AT_const_value, size, 1, array);
+ }
+ }
}
/* Convert the CFI instructions for the current function into a
{
CASE_CONVERT:
return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
+ case VAR_DECL:
+ return loc_descriptor_from_tree_1 (val, 0);
case INTEGER_CST:
if (host_integerp (val, 0))
return int_loc_descriptor (tree_low_cst (val, 0));
tree type = TREE_TYPE (node);
add_name_and_src_coords_attributes (parm_die, node);
if (DECL_BY_REFERENCE (node))
- type = TREE_TYPE (type);
- add_type_attribute (parm_die, type,
- TREE_READONLY (node),
- TREE_THIS_VOLATILE (node),
- context_die);
+ add_type_attribute (parm_die, TREE_TYPE (type), 0, 0,
+ context_die);
+ else
+ add_type_attribute (parm_die, type,
+ TREE_READONLY (node),
+ TREE_THIS_VOLATILE (node),
+ context_die);
if (DECL_ARTIFICIAL (node))
add_AT_flag (parm_die, DW_AT_artificial, 1);
}
}
+/* Returns a hash value for X (which really is a die_struct). */
+
+static hashval_t
+common_block_die_table_hash (const void *x)
+{
+ const_dw_die_ref d = (const_dw_die_ref) x;
+ return (hashval_t) d->decl_id ^ htab_hash_pointer (d->die_parent);
+}
+
+/* Return nonzero if decl_id and die_parent of die_struct X is the same
+ as decl_id and die_parent of die_struct Y. */
+
+static int
+common_block_die_table_eq (const void *x, const void *y)
+{
+ const_dw_die_ref d = (const_dw_die_ref) x;
+ const_dw_die_ref e = (const_dw_die_ref) y;
+ return d->decl_id == e->decl_id && d->die_parent == e->die_parent;
+}
+
/* Generate a DIE to represent a declared data object. */
static void
tree field;
dw_die_ref com_die;
dw_loc_descr_ref loc;
+ die_node com_die_arg;
- com_die = lookup_decl_die (decl);
- if (com_die)
+ var_die = lookup_decl_die (decl);
+ if (var_die)
{
- if (get_AT (com_die, DW_AT_location) == NULL)
+ if (get_AT (var_die, DW_AT_location) == NULL)
{
loc = loc_descriptor_from_tree (com_decl);
if (loc)
{
if (off)
- add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst,
+ {
+ /* Optimize the common case. */
+ if (loc->dw_loc_opc == DW_OP_addr
+ && loc->dw_loc_next == NULL
+ && GET_CODE (loc->dw_loc_oprnd1.v.val_addr)
+ == SYMBOL_REF)
+ loc->dw_loc_oprnd1.v.val_addr
+ = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
+ else
+ add_loc_descr (&loc,
+ new_loc_descr (DW_OP_plus_uconst,
off, 0));
- add_AT_loc (com_die, DW_AT_location, loc);
- remove_AT (com_die, DW_AT_declaration);
+ }
+ add_AT_loc (var_die, DW_AT_location, loc);
+ remove_AT (var_die, DW_AT_declaration);
}
}
return;
}
+
+ if (common_block_die_table == NULL)
+ common_block_die_table
+ = htab_create_ggc (10, common_block_die_table_hash,
+ common_block_die_table_eq, NULL);
+
field = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
- var_die = lookup_decl_die (com_decl);
+ com_die_arg.decl_id = DECL_UID (com_decl);
+ com_die_arg.die_parent = context_die;
+ com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
loc = loc_descriptor_from_tree (com_decl);
- if (var_die == NULL)
+ if (com_die == NULL)
{
const char *cnam
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (com_decl));
+ void **slot;
- var_die = new_die (DW_TAG_common_block, context_die, decl);
- add_name_and_src_coords_attributes (var_die, com_decl);
+ com_die = new_die (DW_TAG_common_block, context_die, decl);
+ add_name_and_src_coords_attributes (com_die, com_decl);
if (loc)
{
- add_AT_loc (var_die, DW_AT_location, loc);
+ add_AT_loc (com_die, DW_AT_location, loc);
/* Avoid sharing the same loc descriptor between
DW_TAG_common_block and DW_TAG_variable. */
loc = loc_descriptor_from_tree (com_decl);
}
else if (DECL_EXTERNAL (decl))
- add_AT_flag (var_die, DW_AT_declaration, 1);
- add_pubname_string (cnam, var_die); /* ??? needed? */
- equate_decl_number_to_die (com_decl, var_die);
+ add_AT_flag (com_die, DW_AT_declaration, 1);
+ add_pubname_string (cnam, com_die); /* ??? needed? */
+ com_die->decl_id = DECL_UID (com_decl);
+ slot = htab_find_slot (common_block_die_table, com_die, INSERT);
+ *slot = (void *) com_die;
}
- else if (get_AT (var_die, DW_AT_location) == NULL && loc)
+ else if (get_AT (com_die, DW_AT_location) == NULL && loc)
{
- add_AT_loc (var_die, DW_AT_location, loc);
+ add_AT_loc (com_die, DW_AT_location, loc);
loc = loc_descriptor_from_tree (com_decl);
- remove_AT (var_die, DW_AT_declaration);
+ remove_AT (com_die, DW_AT_declaration);
}
- com_die = new_die (DW_TAG_variable, var_die, decl);
- add_name_and_src_coords_attributes (com_die, decl);
- add_type_attribute (com_die, TREE_TYPE (decl), TREE_READONLY (decl),
+ var_die = new_die (DW_TAG_variable, com_die, decl);
+ add_name_and_src_coords_attributes (var_die, decl);
+ add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
TREE_THIS_VOLATILE (decl), context_die);
- add_AT_flag (com_die, DW_AT_external, 1);
+ add_AT_flag (var_die, DW_AT_external, 1);
if (loc)
{
if (off)
- add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, off, 0));
- add_AT_loc (com_die, DW_AT_location, loc);
+ {
+ /* Optimize the common case. */
+ if (loc->dw_loc_opc == DW_OP_addr
+ && loc->dw_loc_next == NULL
+ && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
+ loc->dw_loc_oprnd1.v.val_addr
+ = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
+ else
+ add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst,
+ off, 0));
+ }
+ add_AT_loc (var_die, DW_AT_location, loc);
}
else if (DECL_EXTERNAL (decl))
- add_AT_flag (com_die, DW_AT_declaration, 1);
- equate_decl_number_to_die (decl, com_die);
+ add_AT_flag (var_die, DW_AT_declaration, 1);
+ equate_decl_number_to_die (decl, var_die);
return;
}
else
{
tree type = TREE_TYPE (decl);
+
+ add_name_and_src_coords_attributes (var_die, decl);
if ((TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL)
&& DECL_BY_REFERENCE (decl))
- type = TREE_TYPE (type);
-
- add_name_and_src_coords_attributes (var_die, decl);
- add_type_attribute (var_die, type, TREE_READONLY (decl),
- TREE_THIS_VOLATILE (decl), context_die);
+ add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
+ else
+ add_type_attribute (var_die, type, TREE_READONLY (decl),
+ TREE_THIS_VOLATILE (decl), context_die);
if (TREE_PUBLIC (decl))
add_AT_flag (var_die, DW_AT_external, 1);
tree_add_const_value_attribute (var_die, decl);
}
+/* Generate a DIE to represent a named constant. */
+
+static void
+gen_const_die (tree decl, dw_die_ref context_die)
+{
+ dw_die_ref const_die;
+ tree type = TREE_TYPE (decl);
+
+ const_die = new_die (DW_TAG_constant, context_die, decl);
+ add_name_and_src_coords_attributes (const_die, decl);
+ add_type_attribute (const_die, type, 1, 0, context_die);
+ if (TREE_PUBLIC (decl))
+ add_AT_flag (const_die, DW_AT_external, 1);
+ if (DECL_ARTIFICIAL (decl))
+ add_AT_flag (const_die, DW_AT_artificial, 1);
+ tree_add_const_value_attribute (const_die, decl);
+}
+
/* Generate a DIE to represent a label identifier. */
static void
if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
&& !(is_fortran () && TREE_PUBLIC (decl)))
;
+ else if (TREE_CODE (decl) == IMPORTED_DECL)
+ dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl),
+ stmt, context_die);
else
gen_decl_die (decl, context_die);
}
they are an alias of. */
if (DECL_ABSTRACT_ORIGIN (decl) == NULL)
{
- /* Output a real namespace. */
+ /* Output a real namespace or module. */
dw_die_ref namespace_die
= new_die (is_fortran () ? DW_TAG_module : DW_TAG_namespace,
context_die, decl);
- add_name_and_src_coords_attributes (namespace_die, decl);
+ /* For Fortran modules defined in different CU don't add src coords. */
+ if (namespace_die->die_tag == DW_TAG_module && DECL_EXTERNAL (decl))
+ add_name_attribute (namespace_die, dwarf2_name (decl, 0));
+ else
+ add_name_and_src_coords_attributes (namespace_die, decl);
if (DECL_EXTERNAL (decl))
add_AT_flag (namespace_die, DW_AT_declaration, 1);
equate_decl_number_to_die (decl, namespace_die);
break;
case CONST_DECL:
- /* The individual enumerators of an enum type get output when we output
- the Dwarf representation of the relevant enum type itself. */
+ if (!is_fortran ())
+ {
+ /* The individual enumerators of an enum type get output when we output
+ the Dwarf representation of the relevant enum type itself. */
+ break;
+ }
+
+ /* Emit its type. */
+ gen_type_die (TREE_TYPE (decl), context_die);
+
+ /* And its containing namespace. */
+ context_die = declare_in_namespace (decl, context_die);
+
+ gen_const_die (decl, context_die);
break;
case FUNCTION_DECL:
break;
case NAMESPACE_DECL:
+ case IMPORTED_DECL:
gen_namespace_die (decl);
break;
}
/* Output debug information for imported module or decl DECL.
- NAME is non-NULL name in context if the decl has been renamed.
- CHILD is true if decl is one of the renamed decls as part of
- importing whole module. */
-
+ NAME is non-NULL name in the lexical block if the decl has been renamed.
+ LEXICAL_BLOCK is the lexical block (which TREE_CODE is a BLOCK)
+ that DECL belongs to.
+ LEXICAL_BLOCK_DIE is the DIE of LEXICAL_BLOCK. */
static void
-dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
- bool child)
+dwarf2out_imported_module_or_decl_1 (tree decl,
+ tree name,
+ tree lexical_block,
+ dw_die_ref lexical_block_die)
{
- dw_die_ref imported_die, at_import_die;
- dw_die_ref scope_die;
expanded_location xloc;
+ dw_die_ref imported_die = NULL;
+ dw_die_ref at_import_die;
- 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
- itself. */
-
- /* Get the scope die for decl context. Use comp_unit_die for global module
- or decl. If die is not found for non globals, force new die. */
- if (context
- && TYPE_P (context)
- && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE))
- return;
- scope_die = get_context_die (context);
-
- if (child)
- {
- gcc_assert (scope_die->die_child);
- gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module);
- gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL);
- scope_die = scope_die->die_child;
- }
-
- /* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE. */
if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
{
if (is_base_type (TREE_TYPE (decl)))
gcc_assert (at_import_die);
}
}
+ else if (TREE_CODE (decl) == IMPORTED_DECL)
+ {
+ tree imported_ns_decl;
+ /* IMPORTED_DECL nodes that are not imported namespace are just not
+ supported yet. */
+ gcc_assert (DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == NAMESPACE_DECL);
+ imported_ns_decl = DECL_INITIAL (decl);
+ at_import_die = lookup_decl_die (imported_ns_decl);
+ if (!at_import_die)
+ at_import_die = force_decl_die (imported_ns_decl);
+ gcc_assert (at_import_die);
+ }
else
{
at_import_die = lookup_decl_die (decl);
}
}
- /* 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);
+ imported_die = new_die (DW_TAG_imported_module,
+ lexical_block_die,
+ lexical_block);
else
- imported_die = new_die (DW_TAG_imported_declaration, scope_die, context);
+ imported_die = new_die (DW_TAG_imported_declaration,
+ lexical_block_die,
+ lexical_block);
xloc = expand_location (input_location);
add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file));
add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line);
if (name)
- add_AT_string (imported_die, DW_AT_name, IDENTIFIER_POINTER (name));
+ add_AT_string (imported_die, DW_AT_name,
+ IDENTIFIER_POINTER (name));
add_AT_die_ref (imported_die, DW_AT_import, at_import_die);
}
+/* Output debug information for imported module or decl DECL.
+ NAME is non-NULL name in context if the decl has been renamed.
+ CHILD is true if decl is one of the renamed decls as part of
+ importing whole module. */
+
+static void
+dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
+ bool child)
+{
+ /* dw_die_ref at_import_die; */
+ dw_die_ref scope_die;
+
+ 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
+ itself. */
+
+ /* Get the scope die for decl context. Use comp_unit_die for global module
+ or decl. If die is not found for non globals, force new die. */
+ if (context
+ && TYPE_P (context)
+ && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE))
+ return;
+ scope_die = get_context_die (context);
+
+ if (child)
+ {
+ gcc_assert (scope_die->die_child);
+ gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module);
+ gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL);
+ scope_die = scope_die->die_child;
+ }
+
+ /* OK, now we have DIEs for decl as well as scope. Emit imported die. */
+ dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
+
+}
+
/* Write the debugging output for DECL. */
void
return;
break;
+ case CONST_DECL:
+ if (debug_info_level <= DINFO_LEVEL_TERSE)
+ return;
+ if (!is_fortran ())
+ return;
+ if (TREE_STATIC (decl) && decl_function_context (decl))
+ context_die = lookup_decl_die (DECL_CONTEXT (decl));
+ break;
+
case NAMESPACE_DECL:
+ case IMPORTED_DECL:
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
if (lookup_decl_die (decl) != NULL)