diff options
author | dnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-26 10:33:36 +0000 |
---|---|---|
committer | dnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-03-26 10:33:36 +0000 |
commit | a63f89638edc7c3120e52faf6815bfe3e9b270e2 (patch) | |
tree | 61b7552b10852929b89f1cb93878fadffc1885c2 /gcc/dwarf2out.c | |
parent | 9402409a6bd0d7d1f7358793f768bda3ec8a9574 (diff) | |
parent | 087a99ba8749638f86c111f776ed326b3fbd97c0 (diff) | |
download | gcc-cxx-conversion.tar.gz |
Merged revisions 196607-196608,196611-196614,196625,196629-196634,196636,196639,196645-196647,196649-196650,196654-196659,196666,196669,196671-196675,196682-196683,196694-196695,196697-196698,196700-196701,196704-196706,196709,196721-196748,196750-196751,196753,196755-196758,196762,196764-196765,196767-196771,196773-196779,196781-196784,196788-196792,196795-196797,196799-196800,196804-196807,196810-196814,196821,196823-196825,196828-196829,196831-196832,196834,196841-196842,196847-196853,196855-196856,196858,196860-196861,196864-196866,196868,196870-196872,196874,196876,196878-196879,196882,196884-196890,196896-196897,196899-196902,196954,196956-196961,196964-196965,196970,196977-196978,196981-196983,196989,197002-197005,197007,197011-197012,197016-197019,197021,197023-197025,197029-197034,197036-197042 via svnmerge from cxx-conversion
svn+ssh://gcc.gnu.org/svn/gcc/trunk
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/cxx-conversion@197098 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 257 |
1 files changed, 232 insertions, 25 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 01d5f7108a0..12d8578cb9e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -5012,13 +5012,13 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) struct var_loc_node *loc = NULL; HOST_WIDE_INT bitsize = -1, bitpos = -1; - if (DECL_DEBUG_EXPR_IS_FROM (decl)) + if (TREE_CODE (decl) == VAR_DECL + && DECL_HAS_DEBUG_EXPR_P (decl)) { tree realdecl = DECL_DEBUG_EXPR (decl); - if (realdecl - && (handled_component_p (realdecl) - || (TREE_CODE (realdecl) == MEM_REF - && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))) + if (handled_component_p (realdecl) + || (TREE_CODE (realdecl) == MEM_REF + && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR)) { HOST_WIDE_INT maxsize; tree innerdecl; @@ -5051,7 +5051,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) if (temp->last && temp->first == temp->last && TREE_CODE (decl) == PARM_DECL - && GET_CODE (temp->first->loc) == NOTE + && NOTE_P (temp->first->loc) && NOTE_VAR_LOCATION_DECL (temp->first->loc) == decl && DECL_INCOMING_RTL (decl) && NOTE_VAR_LOCATION_LOC (temp->first->loc) @@ -7850,6 +7850,8 @@ size_of_aranges (void) FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { + if (DECL_IGNORED_P (fde->decl)) + continue; if (!fde->in_std_section) size += 2 * DWARF2_ADDR_SIZE; if (fde->dw_fde_second_begin && !fde->second_in_std_section) @@ -10240,6 +10242,7 @@ gen_generic_params_dies (tree t) tree parms, args; int parms_num, i; dw_die_ref die = NULL; + int non_default; if (!t || (TYPE_P (t) && !COMPLETE_TYPE_P (t))) return; @@ -10259,9 +10262,14 @@ gen_generic_params_dies (tree t) parms_num = TREE_VEC_LENGTH (parms); args = lang_hooks.get_innermost_generic_args (t); + if (TREE_CHAIN (args) && TREE_CODE (TREE_CHAIN (args)) == INTEGER_CST) + non_default = int_cst_value (TREE_CHAIN (args)); + else + non_default = TREE_VEC_LENGTH (args); for (i = 0; i < parms_num; i++) { tree parm, arg, arg_pack_elems; + dw_die_ref parm_die; parm = TREE_VEC_ELT (parms, i); arg = TREE_VEC_ELT (args, i); @@ -10276,12 +10284,14 @@ gen_generic_params_dies (tree t) pack elements of ARG. Note that ARG would then be an argument pack. */ if (arg_pack_elems) - template_parameter_pack_die (TREE_VALUE (parm), - arg_pack_elems, - die); + parm_die = template_parameter_pack_die (TREE_VALUE (parm), + arg_pack_elems, + die); else - generic_parameter_die (TREE_VALUE (parm), arg, - true /* Emit DW_AT_name */, die); + parm_die = generic_parameter_die (TREE_VALUE (parm), arg, + true /* emit name */, die); + if (i >= non_default) + add_AT_flag (parm_die, DW_AT_default_value, 1); } } } @@ -13467,7 +13477,7 @@ dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) *listp = new_loc_list (descr, node->label, endname, secname); if (TREE_CODE (decl) == PARM_DECL && node == loc_list->first - && GET_CODE (node->loc) == NOTE + && NOTE_P (node->loc) && strcmp (node->label, endname) == 0) (*listp)->force = true; listp = &(*listp)->dw_loc_next; @@ -15521,6 +15531,7 @@ tree_add_const_value_attribute (dw_die_ref die, tree t) add_AT_vec (die, DW_AT_const_value, size, 1, array); return true; } + ggc_free (array); } } return false; @@ -20693,7 +20704,7 @@ dwarf2out_var_location (rtx loc_note) next_note = NEXT_INSN (loc_note); if (! next_note || INSN_DELETED_P (next_note) - || GET_CODE (next_note) != NOTE + || ! NOTE_P (next_note) || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION)) next_note = NULL_RTX; @@ -22497,6 +22508,10 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED) if (!rtl || !MEM_P (rtl)) return 1; rtl = XEXP (rtl, 0); + if (GET_CODE (rtl) == SYMBOL_REF + && SYMBOL_REF_DECL (rtl) + && !TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl))) + return 1; vec_safe_push (used_rtx_array, rtl); *addr = rtl; return 0; @@ -22521,6 +22536,103 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED) return 0; } +/* For STRING_CST, return SYMBOL_REF of its constant pool entry, + if possible, and create DW_TAG_dwarf_procedure that can be referenced + from DW_OP_GNU_implicit_pointer if the string hasn't been seen yet. */ + +static rtx +string_cst_pool_decl (tree t) +{ + rtx rtl = output_constant_def (t, 1); + unsigned char *array; + dw_loc_descr_ref l; + tree decl; + size_t len; + dw_die_ref ref; + + if (!rtl || !MEM_P (rtl)) + return NULL_RTX; + rtl = XEXP (rtl, 0); + if (GET_CODE (rtl) != SYMBOL_REF + || SYMBOL_REF_DECL (rtl) == NULL_TREE) + return NULL_RTX; + + decl = SYMBOL_REF_DECL (rtl); + if (!lookup_decl_die (decl)) + { + len = TREE_STRING_LENGTH (t); + vec_safe_push (used_rtx_array, rtl); + ref = new_die (DW_TAG_dwarf_procedure, comp_unit_die (), decl); + array = (unsigned char *) ggc_alloc_atomic (len); + memcpy (array, TREE_STRING_POINTER (t), len); + l = new_loc_descr (DW_OP_implicit_value, len, 0); + l->dw_loc_oprnd2.val_class = dw_val_class_vec; + l->dw_loc_oprnd2.v.val_vec.length = len; + l->dw_loc_oprnd2.v.val_vec.elt_size = 1; + l->dw_loc_oprnd2.v.val_vec.array = array; + add_AT_loc (ref, DW_AT_location, l); + equate_decl_number_to_die (decl, ref); + } + return rtl; +} + +/* Helper function of resolve_addr_in_expr. LOC is + a DW_OP_addr followed by DW_OP_stack_value, either at the start + of exprloc or after DW_OP_{,bit_}piece, and val_addr can't be + resolved. Replace it (both DW_OP_addr and DW_OP_stack_value) + with DW_OP_GNU_implicit_pointer if possible + and return true, if unsuccesful, return false. */ + +static bool +optimize_one_addr_into_implicit_ptr (dw_loc_descr_ref loc) +{ + rtx rtl = loc->dw_loc_oprnd1.v.val_addr; + HOST_WIDE_INT offset = 0; + dw_die_ref ref = NULL; + tree decl; + + if (GET_CODE (rtl) == CONST + && GET_CODE (XEXP (rtl, 0)) == PLUS + && CONST_INT_P (XEXP (XEXP (rtl, 0), 1))) + { + offset = INTVAL (XEXP (XEXP (rtl, 0), 1)); + rtl = XEXP (XEXP (rtl, 0), 0); + } + if (GET_CODE (rtl) == CONST_STRING) + { + size_t len = strlen (XSTR (rtl, 0)) + 1; + tree t = build_string (len, XSTR (rtl, 0)); + tree tlen = size_int (len - 1); + + TREE_TYPE (t) + = build_array_type (char_type_node, build_index_type (tlen)); + rtl = string_cst_pool_decl (t); + if (!rtl) + return false; + } + if (GET_CODE (rtl) == SYMBOL_REF && SYMBOL_REF_DECL (rtl)) + { + decl = SYMBOL_REF_DECL (rtl); + if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) + { + ref = lookup_decl_die (decl); + if (ref && (get_AT (ref, DW_AT_location) + || get_AT (ref, DW_AT_const_value))) + { + loc->dw_loc_opc = DW_OP_GNU_implicit_pointer; + loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + loc->dw_loc_oprnd1.val_entry = NULL; + loc->dw_loc_oprnd1.v.val_die_ref.die = ref; + loc->dw_loc_oprnd1.v.val_die_ref.external = 0; + loc->dw_loc_next = loc->dw_loc_next->dw_loc_next; + loc->dw_loc_oprnd2.v.val_int = offset; + return true; + } + } + } + return false; +} + /* Helper function for resolve_addr, handle one location expression, return false if at least one CONST_STRING or SYMBOL_REF in the location list couldn't be resolved. */ @@ -22529,23 +22641,31 @@ static bool resolve_addr_in_expr (dw_loc_descr_ref loc) { dw_loc_descr_ref keep = NULL; - for (; loc; loc = loc->dw_loc_next) + for (dw_loc_descr_ref prev = NULL; loc; prev = loc, loc = loc->dw_loc_next) switch (loc->dw_loc_opc) { case DW_OP_addr: if (resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) - return false; + { + if ((prev == NULL + || prev->dw_loc_opc == DW_OP_piece + || prev->dw_loc_opc == DW_OP_bit_piece) + && loc->dw_loc_next + && loc->dw_loc_next->dw_loc_opc == DW_OP_stack_value + && !dwarf_strict + && optimize_one_addr_into_implicit_ptr (loc)) + break; + return false; + } break; case DW_OP_GNU_addr_index: case DW_OP_GNU_const_index: - { - if ((loc->dw_loc_opc == DW_OP_GNU_addr_index - || (loc->dw_loc_opc == DW_OP_GNU_const_index && loc->dtprel)) - && resolve_one_addr (&loc->dw_loc_oprnd1.val_entry->addr.rtl, - NULL)) - return false; - } - break; + if ((loc->dw_loc_opc == DW_OP_GNU_addr_index + || (loc->dw_loc_opc == DW_OP_GNU_const_index && loc->dtprel)) + && resolve_one_addr (&loc->dw_loc_oprnd1.val_entry->addr.rtl, + NULL)) + return false; + break; case DW_OP_const4u: case DW_OP_const8u: if (loc->dtprel @@ -22640,6 +22760,80 @@ resolve_addr_in_expr (dw_loc_descr_ref loc) return true; } +/* Helper function of resolve_addr. DIE had DW_AT_location of + DW_OP_addr alone, which referred to DECL in DW_OP_addr's operand + and DW_OP_addr couldn't be resolved. resolve_addr has already + removed the DW_AT_location attribute. This function attempts to + add a new DW_AT_location attribute with DW_OP_GNU_implicit_pointer + to it or DW_AT_const_value attribute, if possible. */ + +static void +optimize_location_into_implicit_ptr (dw_die_ref die, tree decl) +{ + if (TREE_CODE (decl) != VAR_DECL + || lookup_decl_die (decl) != die + || DECL_EXTERNAL (decl) + || !TREE_STATIC (decl) + || DECL_INITIAL (decl) == NULL_TREE + || DECL_P (DECL_INITIAL (decl)) + || get_AT (die, DW_AT_const_value)) + return; + + tree init = DECL_INITIAL (decl); + HOST_WIDE_INT offset = 0; + /* For variables that have been optimized away and thus + don't have a memory location, see if we can emit + DW_AT_const_value instead. */ + if (tree_add_const_value_attribute (die, init)) + return; + if (dwarf_strict) + return; + /* If init is ADDR_EXPR or POINTER_PLUS_EXPR of ADDR_EXPR, + and ADDR_EXPR refers to a decl that has DW_AT_location or + DW_AT_const_value (but isn't addressable, otherwise + resolving the original DW_OP_addr wouldn't fail), see if + we can add DW_OP_GNU_implicit_pointer. */ + STRIP_NOPS (init); + if (TREE_CODE (init) == POINTER_PLUS_EXPR + && host_integerp (TREE_OPERAND (init, 1), 0)) + { + offset = tree_low_cst (TREE_OPERAND (init, 1), 0); + init = TREE_OPERAND (init, 0); + STRIP_NOPS (init); + } + if (TREE_CODE (init) != ADDR_EXPR) + return; + if ((TREE_CODE (TREE_OPERAND (init, 0)) == STRING_CST + && !TREE_ASM_WRITTEN (TREE_OPERAND (init, 0))) + || (TREE_CODE (TREE_OPERAND (init, 0)) == VAR_DECL + && !DECL_EXTERNAL (TREE_OPERAND (init, 0)) + && TREE_OPERAND (init, 0) != decl)) + { + dw_die_ref ref; + dw_loc_descr_ref l; + + if (TREE_CODE (TREE_OPERAND (init, 0)) == STRING_CST) + { + rtx rtl = string_cst_pool_decl (TREE_OPERAND (init, 0)); + if (!rtl) + return; + decl = SYMBOL_REF_DECL (rtl); + } + else + decl = TREE_OPERAND (init, 0); + ref = lookup_decl_die (decl); + if (ref == NULL + || (!get_AT (ref, DW_AT_location) + && !get_AT (ref, DW_AT_const_value))) + return; + l = new_loc_descr (DW_OP_GNU_implicit_pointer, 0, offset); + l->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + l->dw_loc_oprnd1.v.val_die_ref.die = ref; + l->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_AT_loc (die, DW_AT_location, l); + } +} + /* Resolve DW_OP_addr and DW_AT_const_value CONST_STRING arguments to an address in .rodata section if the string literal is emitted there, or remove the containing location list or replace DW_AT_const_value @@ -22726,8 +22920,21 @@ resolve_addr (dw_die_ref die) || l->dw_loc_next != NULL) && !resolve_addr_in_expr (l)) { - if (dwarf_split_debug_info) - remove_loc_list_addr_table_entries (l); + if (dwarf_split_debug_info) + remove_loc_list_addr_table_entries (l); + if (l != NULL + && l->dw_loc_next == NULL + && l->dw_loc_opc == DW_OP_addr + && GET_CODE (l->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF + && SYMBOL_REF_DECL (l->dw_loc_oprnd1.v.val_addr) + && a->dw_attr == DW_AT_location) + { + tree decl = SYMBOL_REF_DECL (l->dw_loc_oprnd1.v.val_addr); + remove_AT (die, a->dw_attr); + ix--; + optimize_location_into_implicit_ptr (die, decl); + break; + } remove_AT (die, a->dw_attr); ix--; } |