Translate DW_TAG_inlined_subroutine DIEs into S_INLINESITE CodeView symbols, marking inlined functions.
gcc/ * dwarf2codeview.cc (enum cv_sym_type): Add S_INLINESITE and S_INLINESITE_END. (get_func_id): Add declaration. (write_s_inlinesite): New function. (write_inlinesite_records): New function. (write_function): Call write_inlinesite_records. --- gcc/dwarf2codeview.cc | 124 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 4fcf3f5f1e2..edaa53f270f 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -86,6 +86,8 @@ enum cv_sym_type { S_DEFRANGE_REGISTER_REL = 0x1145, S_LPROC32_ID = 0x1146, S_GPROC32_ID = 0x1147, + S_INLINESITE = 0x114d, + S_INLINESITE_END = 0x114e, S_PROC_ID_END = 0x114f }; @@ -1461,6 +1463,8 @@ static uint32_t get_type_num_subroutine_type (dw_die_ref type, bool in_struct, uint32_t this_type, int32_t this_adjustment); static void write_cv_padding (size_t padding); +static uint32_t get_func_id (dw_die_ref die); +static void write_inlinesite_records (dw_die_ref func, dw_die_ref die); /* Return the file ID corresponding to a given source filename. */ @@ -3317,6 +3321,124 @@ write_optimized_static_local_vars (dw_die_ref die) while (c != first_child); } +/* Write an S_INLINESITE symbol, to record that a function has been inlined + inside another function. */ + +static void +write_s_inlinesite (dw_die_ref parent_func, dw_die_ref die) +{ + unsigned int label_num = ++sym_label_num; + dw_die_ref func; + uint32_t func_id; + + func = get_AT_ref (die, DW_AT_abstract_origin); + if (!func) + return; + + func_id = get_func_id (func); + if (func_id == 0) + return; + + /* This is struct inline_site in binutils and INLINESITESYM in Microsoft's + cvinfo.h: + + struct inline_site + { + uint16_t size; + uint16_t kind; + uint32_t parent; + uint32_t end; + uint32_t inlinee; + uint8_t binary_annotations[]; + } ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, + "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n", + label_num, label_num); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, S_INLINESITE); + putc ('\n', asm_out_file); + + /* parent, filled in by linker */ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, 0); + putc ('\n', asm_out_file); + + /* end, filled in by linker */ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, 0); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, func_id); + putc ('\n', asm_out_file); + + /* FIXME: there now should follow some "binary annotations", recording how + offsets in the function map to line numbers in the inlined function, + but these require support in GAS. */ + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num); + + write_inlinesite_records (parent_func, die); + + /* Write S_INLINESITE_END symbol. */ + + label_num = ++sym_label_num; + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, + "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n", + label_num, label_num); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, S_INLINESITE_END); + putc ('\n', asm_out_file); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num); +} + +/* Loop through a function, and translate its DW_TAG_inlined_subroutine DIEs + into CodeView S_INLINESITE symbols. */ + +static void +write_inlinesite_records (dw_die_ref func, dw_die_ref die) +{ + dw_die_ref first_child, c; + + first_child = dw_get_die_child (die); + + if (!first_child) + return; + + c = first_child; + do + { + c = dw_get_die_sib (c); + + switch (dw_get_die_tag (c)) + { + case DW_TAG_lexical_block: + write_inlinesite_records (func, c); + break; + + case DW_TAG_inlined_subroutine: + write_s_inlinesite (func, c); + break; + + default: + break; + } + } + while (c != first_child); +} + /* Write an S_GPROC32_ID symbol, representing a global function, or an S_LPROC32_ID symbol, for a static function. */ @@ -3443,6 +3565,8 @@ write_function (codeview_symbol *s) targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num); + write_inlinesite_records (s->function.die, s->function.die); + frame_base = get_AT (s->function.die, DW_AT_frame_base); if (frame_base && frame_base->dw_attr_val.val_class == dw_val_class_loc) -- 2.45.2