diff options
Diffstat (limited to 'gcc/dwarf2out.cc')
-rw-r--r-- | gcc/dwarf2out.cc | 70 |
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; |