aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c205
1 files changed, 171 insertions, 34 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 49bca54c951..4c683a6ca82 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1703,8 +1703,103 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
{
int regno;
- gcc_assert (GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
- offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+ /* APPLE LOCAL begin 'reg + index' case. */
+ offset = 0x696b6c6c;
+
+ if (GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT)
+ offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+ /* If it's a 'reg + index', we need to find out what value
+ the index reg has at this point. (This can happen
+ because some architectures have registers which can
+ only be stored using a "reg + index" mode.)
+
+ This method of finding out the index value is VERY
+ FRAGILE. Ideally we'd try to add a note to the save
+ insn, but... */
+ else if (GET_CODE (XEXP (XEXP (dest, 0), 1)) == REG)
+ {
+ unsigned the_reg = REGNO (XEXP (XEXP (dest, 0), 1));
+ rtx insn;
+
+ /* The REG_FRAME_RELATED_EXPR can sometimes be
+ out-of-date after the optimiser/inliner has done
+ its stuff. For example,
+
+ (insn: (set (mem:V16QI (plus:SI (reg/f:SI 1 r1)
+ (reg:SI 6 r6)) [0 S16 A8])
+ (reg:V16QI 108 v31))
+ ...
+ (expr_list:REG_FRAME_RELATED_EXPR
+ (set (mem:V16QI (plus:SI (reg/f:SI 1 r1)
+ (reg:SI 0 r0)) [0 S16 A8])
+ (reg:V16QI 108 v31))
+
+ Note that the optimiser has used R6 instead of the original
+ R0 to store the SP offset. Alas, we blindly look for R0
+ here, since DEST is the REG_FRAME_RELATED_EXPR, so we need
+ to check for that.
+
+ This needs a rework from scratch, but it'll do for now. */
+
+ insn = XEXP (XEXP (XEXP (PATTERN (current_output_insn),
+ 0), 0), 1);
+ if (GET_CODE (insn) == REG)
+ the_reg = REGNO (insn);
+
+ insn = PREV_INSN (current_output_insn);
+ for (; insn != NULL; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) != INSN
+ || PATTERN (insn) == NULL)
+ ;
+ else if (GET_CODE (PATTERN (insn)) == SET)
+ {
+ rtx p = PATTERN (insn);
+ if (SET_DEST (p) != NULL
+ && GET_CODE (SET_DEST (p)) == REG
+ && REGNO (SET_DEST (p)) == the_reg)
+ {
+ if (GET_CODE (SET_SRC (p)) == CONST_INT)
+ {
+ offset = INTVAL (SET_SRC (p));
+ break;
+ }
+ else
+ abort ();
+ }
+ }
+ else
+ /* A label? All bets are off. */
+ if (GET_CODE (PATTERN (insn)) == CODE_LABEL)
+ abort ();
+ }
+
+ /* DEST can also be something like:
+
+ (mem:V16QI (plus:SI (plus:SI (reg/f:SI 1 r1)
+ (const_int 147792 [0x24150]))
+ (reg:SI 0 r0)) [0 S16 A8])
+
+ This is handled here by adjusting the offset appropriately. */
+
+ insn = XEXP (XEXP (dest, 0), 0);
+ if (GET_CODE (insn) == PLUS && GET_CODE (XEXP (insn, 0)) == REG
+ && GET_CODE (XEXP (insn, 1)) == CONST_INT)
+ {
+ gcc_assert (offset != 0x696b6c6c);
+ offset += INTVAL (XEXP (insn, 1));
+
+ /* Set DEST to be the inner PLUS so that
+ REGNO (XEXP (XEXP (dest, 0), 0) will be sensible. */
+
+ dest = XEXP (dest, 0);
+ }
+ }
+ else
+ abort ();
+ gcc_assert (offset != 0x696b6c6c);
+ /* APPLE LOCAL end 'reg + index' case. */
+
if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset;
@@ -2468,7 +2563,12 @@ void
dwarf2out_frame_finish (void)
{
/* Output call frame information. */
- if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+ if (write_symbols == DWARF2_DEBUG
+ || write_symbols == VMS_AND_DWARF2_DEBUG
+#ifdef DWARF2_FRAME_INFO
+ || DWARF2_FRAME_INFO
+#endif
+ )
output_call_frame_info (0);
#ifndef TARGET_UNWIND_INFO
@@ -3444,7 +3544,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
dwarf2out_abstract_function, /* outlining_inline_function */
debug_nothing_rtx, /* label */
debug_nothing_int, /* handle_pch */
- dwarf2out_var_location
+ dwarf2out_var_location,
+ 1 /* start_end_main_source_file */
};
#endif
@@ -4117,7 +4218,7 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
#endif
/* We allow a language front-end to designate a function that is to be
- called to "demangle" any name before it it put into a DIE. */
+ called to "demangle" any name before it is put into a DIE. */
static const char *(*demangle_name_func) (const char *);
@@ -10156,26 +10257,22 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
tree init = DECL_INITIAL (decl);
tree type = TREE_TYPE (decl);
- if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init
- && initializer_constant_valid_p (init, type) == null_pointer_node)
- /* OK */;
- else
+ if (!init)
return;
-
- switch (TREE_CODE (type))
- {
- case INTEGER_TYPE:
- if (host_integerp (init, 0))
- add_AT_unsigned (var_die, DW_AT_const_value,
- tree_low_cst (init, 0));
- else
- add_AT_long_long (var_die, DW_AT_const_value,
- TREE_INT_CST_HIGH (init),
- TREE_INT_CST_LOW (init));
- break;
-
- default:;
- }
+ if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl))
+ return;
+ if (TREE_CODE (type) != INTEGER_TYPE)
+ return;
+ if (TREE_CODE (init) != INTEGER_CST)
+ return;
+
+ if (host_integerp (init, 0))
+ add_AT_unsigned (var_die, DW_AT_const_value,
+ tree_low_cst (init, 0));
+ else
+ add_AT_long_long (var_die, DW_AT_const_value,
+ TREE_INT_CST_HIGH (init),
+ TREE_INT_CST_LOW (init));
}
/* Generate a DW_AT_name attribute given some string value to be included as
@@ -10518,7 +10615,7 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
here. */
if (origin_die)
- add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
}
/* We do not currently support the pure_virtual attribute. */
@@ -11148,13 +11245,27 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))
&& ! lookup_decl_die (member))
{
+ dw_die_ref type_die;
gcc_assert (!decl_ultimate_origin (member));
push_decl_scope (type);
+ type_die = lookup_type_die (type);
if (TREE_CODE (member) == FUNCTION_DECL)
- gen_subprogram_die (member, lookup_type_die (type));
+ gen_subprogram_die (member, type_die);
+ else if (TREE_CODE (member) == FIELD_DECL)
+ {
+ /* Ignore the nameless fields that are used to skip bits but handle
+ C++ anonymous unions and structs. */
+ if (DECL_NAME (member) != NULL_TREE
+ || TREE_CODE (TREE_TYPE (member)) == UNION_TYPE
+ || TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE)
+ {
+ gen_type_die (member_declared_type (member), type_die);
+ gen_field_die (member, type_die);
+ }
+ }
else
- gen_variable_die (member, lookup_type_die (type));
+ gen_variable_die (member, type_die);
pop_decl_scope ();
}
@@ -12435,7 +12546,7 @@ is_redundant_typedef (tree decl)
return 0;
}
-/* Returns the DIE for decl or aborts. */
+/* Returns the DIE for decl or else. */
static dw_die_ref
force_decl_die (tree decl)
@@ -12488,8 +12599,7 @@ force_decl_die (tree decl)
gcc_unreachable ();
}
- /* See if we can find the die for this deci now.
- If not then abort. */
+ /* We should be able to find the die for this decl now. */
if (!decl_die)
decl_die = lookup_decl_die (decl);
gcc_assert (decl_die);
@@ -12498,7 +12608,7 @@ force_decl_die (tree decl)
return decl_die;
}
-/* Returns the DIE for decl or aborts. */
+/* Returns the DIE for decl or else. */
static dw_die_ref
force_type_die (tree type)
@@ -12553,6 +12663,12 @@ declare_in_namespace (tree thing, dw_die_ref context_die)
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
+ /* If this decl is from an inlined function, then don't try to emit it in its
+ namespace, as we will get confused. It would have already been emitted
+ when the abstract instance of the inline function was emitted anyways. */
+ if (DECL_P (thing) && DECL_ABSTRACT_ORIGIN (thing))
+ return;
+
ns_context = setup_namespace_context (thing, context_die);
if (ns_context != context_die)
@@ -12840,7 +12956,29 @@ dwarf2out_imported_module_or_decl (tree decl, tree context)
if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
at_import_die = force_type_die (TREE_TYPE (decl));
else
- at_import_die = force_decl_die (decl);
+ {
+ at_import_die = lookup_decl_die (decl);
+ if (!at_import_die)
+ {
+ /* If we're trying to avoid duplicate debug info, we may not have
+ emitted the member decl for this field. Emit it now. */
+ if (TREE_CODE (decl) == FIELD_DECL)
+ {
+ tree type = DECL_CONTEXT (decl);
+ dw_die_ref type_context_die;
+
+ if (TYPE_CONTEXT (type))
+ if (TYPE_P (TYPE_CONTEXT (type)))
+ type_context_die = force_type_die (TYPE_CONTEXT (type));
+ else
+ type_context_die = force_decl_die (TYPE_CONTEXT (type));
+ else
+ type_context_die = comp_unit_die;
+ gen_type_die_for_member (type, decl, type_context_die);
+ }
+ at_import_die = force_decl_die (decl);
+ }
+ }
/* OK, now we have DIEs for decl as well as scope. Emit imported die. */
if (TREE_CODE (decl) == NAMESPACE_DECL)
@@ -13795,11 +13933,10 @@ dwarf2out_finish (const char *filename)
output_ranges ();
}
- /* Have to end the primary source file. */
+ /* Have to end the macro section. */
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
- dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
dw2_asm_output_data (1, 0, "End compilation unit");
}