aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2out.cc')
-rw-r--r--gcc/dwarf2out.cc70
1 files changed, 68 insertions, 2 deletions
diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 2437610..b5a7886 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -3466,6 +3466,12 @@ static GTY(()) limbo_die_node *limbo_die_list;
DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set. */
static GTY(()) limbo_die_node *deferred_asm_name;
+/* A list of DIEs for which we may have to add a notional code range to the
+ parent DIE. This happens for parents of nested offload kernels, and is
+ necessary because the parents don't exist on the offload target, yet GDB
+ expects parents of real functions to also appear to exist. */
+static GTY(()) limbo_die_node *notional_parents_list;
+
struct dwarf_file_hasher : ggc_ptr_hash<dwarf_file_data>
{
typedef const char *compare_type;
@@ -21024,6 +21030,15 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p)
if (list)
{
add_AT_location_description (die, DW_AT_location, list);
+
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ int action = targetm.addr_space.debug (as);
+ /* Positive values indicate an address_class. */
+ if (action >= 0)
+ add_AT_unsigned (die, DW_AT_address_class, action);
+ }
return true;
}
/* None of that worked, so it must not really have a location;
@@ -23945,8 +23960,24 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
if (fde->dw_fde_begin)
{
/* We have already generated the labels. */
- add_AT_low_high_pc (subr_die, fde->dw_fde_begin,
- fde->dw_fde_end, false);
+ add_AT_low_high_pc (subr_die, fde->dw_fde_begin,
+ fde->dw_fde_end, false);
+
+ /* Offload kernel functions are nested within a parent function
+ that doesn't actually exist within the offload object. GDB
+ will ignore the function and everything nested within unless
+ we give the parent a code range. We can't do it here because
+ that breaks the case where the parent actually does exist (as
+ it does on the host-side), so we defer the fixup for later. */
+ if (lookup_attribute ("omp target entrypoint",
+ DECL_ATTRIBUTES (decl)))
+ {
+ limbo_die_node *node = ggc_cleared_alloc<limbo_die_node> ();
+ node->die = subr_die;
+ node->created_for = decl;
+ node->next = notional_parents_list;
+ notional_parents_list = node;
+ }
}
else
{
@@ -32370,6 +32401,37 @@ flush_limbo_die_list (void)
}
}
+/* Add a code range to the notional parent function (which does not actually
+ exist) so that GDB does not ignore all the child functions. The actual
+ values do not matter, but need to be valid labels, so we simply copy those
+ from the child function.
+
+ Typically this occurs when we have an offload kernel, where the parent
+ function only exists in the host-side portion of the code. */
+
+static void
+fixup_notional_parents (void)
+{
+ limbo_die_node *node;
+
+ while ((node = notional_parents_list))
+ {
+ dw_die_ref die = node->die;
+ dw_die_ref parent = die->die_parent;
+ notional_parents_list = node->next;
+
+ if (parent
+ && parent->die_tag == DW_TAG_subprogram
+ && !get_AT_low_pc (parent))
+ {
+ dw_attr_node *low = get_AT (die, DW_AT_low_pc);
+ dw_attr_node *high = get_AT (die, DW_AT_high_pc);
+
+ add_AT_low_high_pc (parent, AT_lbl (low), AT_lbl (high), false);
+ }
+ }
+}
+
/* Reset DIEs so we can output them again. */
static void
@@ -32441,6 +32503,9 @@ dwarf2out_finish (const char *filename)
/* Flush out any latecomers to the limbo party. */
flush_limbo_die_list ();
+ /* Insert an notional parent code ranges. */
+ fixup_notional_parents ();
+
if (inline_entry_data_table)
gcc_assert (inline_entry_data_table->is_empty ());
@@ -33519,6 +33584,7 @@ dwarf2out_cc_finalize (void)
single_comp_unit_die = NULL;
comdat_type_list = NULL;
limbo_die_list = NULL;
+ notional_parents_list = NULL;
file_table = NULL;
decl_die_table = NULL;
common_block_die_table = NULL;