X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fdwarf2out.c;h=0fd93cb194a481276efe0044c6ed7a52db0d268f;hb=338cce8f9ae07a2135b04b693f882c03d2de3bb5;hp=e3a641206d8d54682d5728f8c31b69b77815354e;hpb=d1b9226497e79115b89c6dc54ea8d5bb6cb077c8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e3a641206d8..0fd93cb194a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1,6 +1,6 @@ /* Output Dwarf2 format symbol table information from GCC. Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Gary Funck (gary@intrepid.com). Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com). Extensively modified by Jason Merrill (jason@cygnus.com). @@ -804,7 +804,7 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi) /* Emit the state save. */ emit_cfa_remember = false; - cfi_remember = new_cfi (); + cfi_remember = new_cfi (); cfi_remember->dw_cfi_opc = DW_CFA_remember_state; add_fde_cfi (label, cfi_remember); } @@ -1042,7 +1042,7 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) if (loc.reg == old_cfa.reg && !loc.indirect) { /* Construct a "DW_CFA_def_cfa_offset " instruction, indicating - the CFA register did not change but the offset did. The data + the CFA register did not change but the offset did. The data factoring for DW_CFA_def_cfa_offset_sf happens in output_cfi, or in the assembler via the .cfi_def_cfa_offset directive. */ if (loc.offset < 0) @@ -1524,10 +1524,10 @@ dwarf2out_args_size (const char *label, HOST_WIDE_INT size) add_fde_cfi (label, cfi); } -/* Adjust args_size based on stack adjustment OFFSET. */ +/* Record a stack adjustment of OFFSET bytes. */ static void -dwarf2out_args_size_adjust (HOST_WIDE_INT offset, const char *label) +dwarf2out_stack_adjust (HOST_WIDE_INT offset, const char *label) { if (cfa.reg == STACK_POINTER_REGNUM) cfa.offset += offset; @@ -1535,6 +1535,9 @@ dwarf2out_args_size_adjust (HOST_WIDE_INT offset, const char *label) if (cfa_store.reg == STACK_POINTER_REGNUM) cfa_store.offset += offset; + if (ACCUMULATE_OUTGOING_ARGS) + return; + #ifndef STACK_GROWS_DOWNWARD offset = -offset; #endif @@ -1549,11 +1552,11 @@ dwarf2out_args_size_adjust (HOST_WIDE_INT offset, const char *label) } /* Check INSN to see if it looks like a push or a stack adjustment, and - make a note of it if it does. EH uses this information to find out how - much extra space it needs to pop off the stack. */ + make a note of it if it does. EH uses this information to find out + how much extra space it needs to pop off the stack. */ static void -dwarf2out_stack_adjust (rtx insn, bool after_p) +dwarf2out_notice_stack_adjust (rtx insn, bool after_p) { HOST_WIDE_INT offset; const char *label; @@ -1637,7 +1640,7 @@ dwarf2out_stack_adjust (rtx insn, bool after_p) return; label = dwarf2out_cfi_label (false); - dwarf2out_args_size_adjust (offset, label); + dwarf2out_stack_adjust (offset, label); } #endif @@ -1882,7 +1885,7 @@ dwarf2out_frame_debug_cfa_offset (rtx set, const char *label) addr = XEXP (set, 0); gcc_assert (MEM_P (addr)); addr = XEXP (addr, 0); - + /* As documented, only consider extremely simple addresses. */ switch (GET_CODE (addr)) { @@ -2206,8 +2209,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label) && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE) && (RTX_FRAME_RELATED_P (elem) || par_index == 0)) dwarf2out_frame_debug_expr (elem, label); - else if (!ACCUMULATE_OUTGOING_ARGS - && GET_CODE (elem) == SET + else if (GET_CODE (elem) == SET && par_index != 0 && !RTX_FRAME_RELATED_P (elem)) { @@ -2216,7 +2218,7 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label) HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0); if (offset != 0) - dwarf2out_args_size_adjust (offset, label); + dwarf2out_stack_adjust (offset, label); } } return; @@ -2709,10 +2711,13 @@ dwarf2out_frame_debug (rtx insn, bool after_p) if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn)) flush_queued_reg_saves (); - if (! RTX_FRAME_RELATED_P (insn)) + if (!RTX_FRAME_RELATED_P (insn)) { + /* ??? This should be done unconditionally since stack adjustments + matter if the stack pointer is not the CFA register anymore but + is still used to save registers. */ if (!ACCUMULATE_OUTGOING_ARGS) - dwarf2out_stack_adjust (insn, after_p); + dwarf2out_notice_stack_adjust (insn, after_p); return; } @@ -2870,7 +2875,7 @@ dwarf2out_begin_epilogue (rtx insn) void dwarf2out_frame_debug_restore_state (void) { - dw_cfi_ref cfi = new_cfi (); + dw_cfi_ref cfi = new_cfi (); const char *label = dwarf2out_cfi_label (false); cfi->dw_cfi_opc = DW_CFA_restore_state; @@ -6057,7 +6062,8 @@ static void add_arange (tree, dw_die_ref); static void output_aranges (void); static unsigned int add_ranges_num (int); static unsigned int add_ranges (const_tree); -static unsigned int add_ranges_by_labels (const char *, const char *); +static void add_ranges_by_labels (dw_die_ref, const char *, const char *, + bool *); static void output_ranges (void); static void output_line_info (void); static void output_file_names (void); @@ -6172,10 +6178,7 @@ static void gen_generic_params_dies (tree); static void splice_child_die (dw_die_ref, dw_die_ref); static int file_info_cmp (const void *, const void *); static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, - const char *, const char *, unsigned); -static void add_loc_descr_to_loc_list (dw_loc_list_ref *, dw_loc_descr_ref, - const char *, const char *, - const char *); + const char *, const char *); static void output_loc_list (dw_loc_list_ref); static char *gen_internal_sym (const char *); @@ -7209,6 +7212,13 @@ AT_loc_list (dw_attr_ref a) return a->dw_attr_val.v.val_loc_list; } +static inline dw_loc_list_ref * +AT_loc_list_ptr (dw_attr_ref a) +{ + gcc_assert (a && AT_class (a) == dw_val_class_loc_list); + return &a->dw_attr_val.v.val_loc_list; +} + /* Add an address constant attribute value to a DIE. */ static inline void @@ -7788,8 +7798,7 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc) temp->last = loc; } } - /* Do not add empty location to the beginning of the list. */ - else if (NOTE_VAR_LOCATION_LOC (loc->var_loc_note) != NULL_RTX) + else { temp->first = loc; temp->last = loc; @@ -9605,7 +9614,7 @@ htab_decl_del (void *what) free (entry); } -/* Copy DIE and its ancestors, up to, but not including, the compile unit +/* Copy DIE and its ancestors, up to, but not including, the compile unit or type unit entry, to a new tree. Adds the new tree to UNIT and returns a pointer to the copy of DIE. If DECL_TABLE is provided, it is used to check if the ancestor has already been copied into UNIT. */ @@ -10297,12 +10306,11 @@ output_die_symbol (dw_die_ref die) } /* Return a new location list, given the begin and end range, and the - expression. gensym tells us whether to generate a new internal symbol for - this location list node, which is done for the head of the list only. */ + expression. */ static inline dw_loc_list_ref new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, - const char *section, unsigned int gensym) + const char *section) { dw_loc_list_ref retlist = GGC_CNEW (dw_loc_list_node); @@ -10310,27 +10318,18 @@ new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, retlist->end = end; retlist->expr = expr; retlist->section = section; - if (gensym) - retlist->ll_symbol = gen_internal_sym ("LLST"); return retlist; } -/* Add a location description expression to a location list. */ +/* Generate a new internal symbol for this location list node, if it + hasn't got one yet. */ static inline void -add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr, - const char *begin, const char *end, - const char *section) +gen_llsym (dw_loc_list_ref list) { - dw_loc_list_ref *d; - - /* Find the end of the chain. */ - for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) - ; - - /* Add a new location list node to the list. */ - *d = new_loc_list (descr, begin, end, section, 0); + gcc_assert (!list->ll_symbol); + list->ll_symbol = gen_internal_sym ("LLST"); } /* Output the location list given to us. */ @@ -11023,10 +11022,12 @@ add_ranges (const_tree block) /* Add a new entry to .debug_ranges corresponding to a pair of labels. */ -static unsigned int -add_ranges_by_labels (const char *begin, const char *end) +static void +add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end, + bool *added) { unsigned int in_use = ranges_by_label_in_use; + unsigned int offset; if (in_use == ranges_by_label_allocated) { @@ -11043,7 +11044,12 @@ add_ranges_by_labels (const char *begin, const char *end) ranges_by_label[in_use].end = end; ranges_by_label_in_use = in_use + 1; - return add_ranges_num (-(int)in_use - 1); + offset = add_ranges_num (-(int)in_use - 1); + if (!*added) + { + add_AT_range_list (die, DW_AT_ranges, offset); + *added = true; + } } static void @@ -11261,7 +11267,6 @@ output_file_names (void) int ndirs; int idx_offset; int i; - int idx; if (!last_emitted_file) { @@ -11388,7 +11393,6 @@ output_file_names (void) } /* Emit the directory name table. */ - idx = 1; idx_offset = dirs[0].length > 0 ? 1 : 0; for (i = 1 - idx_offset; i < ndirs; i++) dw2_asm_output_nstring (dirs[i].path, @@ -12987,6 +12991,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, mem_loc_result = tls_mem_loc_descriptor (rtl); if (mem_loc_result != 0) add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); + else + { + rtx new_rtl = avoid_constant_pool_reference (rtl); + if (new_rtl != rtl) + return mem_loc_descriptor (new_rtl, mode, initialized); + } break; case LO_SUM: @@ -13000,34 +13010,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, pool. */ case CONST: case SYMBOL_REF: - /* Alternatively, the symbol in the constant pool might be referenced - by a different symbol. */ - if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl)) - { - bool marked; - rtx tmp = get_pool_constant_mark (rtl, &marked); - - if (GET_CODE (tmp) == SYMBOL_REF) - { - rtl = tmp; - if (CONSTANT_POOL_ADDRESS_P (tmp)) - get_pool_constant_mark (tmp, &marked); - else - marked = true; - } - - /* If all references to this pool constant were optimized away, - it was not output and thus we can't represent it. - FIXME: might try to use DW_OP_const_value here, though - DW_OP_piece complicates it. */ - if (!marked) - { - expansion_failed (NULL_TREE, rtl, - "Constant was removed from constant pool.\n"); - return 0; - } - } - if (GET_CODE (rtl) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE) { @@ -13125,7 +13107,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, op = DW_OP_div; goto do_binop; - case MOD: + case UMOD: op = DW_OP_mod; goto do_binop; @@ -13167,6 +13149,24 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0)); break; + case MOD: + op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, + VAR_INIT_STATUS_INITIALIZED); + op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, + VAR_INIT_STATUS_INITIALIZED); + + if (op0 == 0 || op1 == 0) + break; + + mem_loc_result = op0; + add_loc_descr (&mem_loc_result, op1); + add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_over, 0, 0)); + add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_over, 0, 0)); + add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_div, 0, 0)); + add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0)); + add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_minus, 0, 0)); + break; + case NOT: op = DW_OP_not; goto do_unop; @@ -13438,8 +13438,18 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, case US_MULT: case SS_DIV: case US_DIV: + case SS_PLUS: + case US_PLUS: + case SS_MINUS: + case US_MINUS: + case SS_NEG: + case US_NEG: + case SS_ABS: + case SS_ASHIFT: + case US_ASHIFT: + case SS_TRUNCATE: + case US_TRUNCATE: case UDIV: - case UMOD: case UNORDERED: case ORDERED: case UNEQ: @@ -13591,6 +13601,12 @@ loc_descriptor (rtx rtl, enum machine_mode mode, initialized); if (loc_result == NULL) loc_result = tls_mem_loc_descriptor (rtl); + if (loc_result == NULL) + { + rtx new_rtl = avoid_constant_pool_reference (rtl); + if (new_rtl != rtl) + loc_result = loc_descriptor (new_rtl, mode, initialized); + } break; case CONCAT: @@ -13650,15 +13666,17 @@ loc_descriptor (rtx rtl, enum machine_mode mode, break; case CONST_DOUBLE: + if (mode == VOIDmode) + mode = GET_MODE (rtl); + if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict)) { + gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl)); + /* Note that a CONST_DOUBLE rtx could represent either an integer or a floating-point constant. A CONST_DOUBLE is used whenever the constant requires more than one word in order to be adequately represented. We output CONST_DOUBLEs as blocks. */ - if (GET_MODE (rtl) != VOIDmode) - mode = GET_MODE (rtl); - loc_result = new_loc_descr (DW_OP_implicit_value, GET_MODE_SIZE (mode), 0); if (SCALAR_FLOAT_MODE_P (mode)) @@ -13684,6 +13702,9 @@ loc_descriptor (rtx rtl, enum machine_mode mode, break; case CONST_VECTOR: + if (mode == VOIDmode) + mode = GET_MODE (rtl); + if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict)) { unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl)); @@ -13692,7 +13713,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode, unsigned int i; unsigned char *p; - mode = GET_MODE (rtl); + gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl)); switch (GET_MODE_CLASS (mode)) { case MODE_VECTOR_INT: @@ -13774,10 +13795,10 @@ loc_descriptor (rtx rtl, enum machine_mode mode, if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE && (dwarf_version >= 4 || !dwarf_strict)) { - loc_result = new_loc_descr (DW_OP_implicit_value, - DWARF2_ADDR_SIZE, 0); - loc_result->dw_loc_oprnd2.val_class = dw_val_class_addr; - loc_result->dw_loc_oprnd2.v.val_addr = rtl; + loc_result = new_loc_descr (DW_OP_addr, 0, 0); + loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; + loc_result->dw_loc_oprnd1.v.val_addr = rtl; + add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0)); VEC_safe_push (rtx, gc, used_rtx_array, rtl); } break; @@ -13839,14 +13860,6 @@ decl_by_reference_p (tree decl) && DECL_BY_REFERENCE (decl)); } -/* Return single element location list containing loc descr REF. */ - -static dw_loc_list_ref -single_element_loc_list (dw_loc_descr_ref ref) -{ - return new_loc_list (ref, NULL, NULL, NULL, 0); -} - /* Helper function for dw_loc_list. Compute proper Dwarf location descriptor for VARLOC. */ @@ -13868,10 +13881,19 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address, mode = GET_MODE (varloc); if (MEM_P (varloc)) { - varloc = XEXP (varloc, 0); - have_address = 1; + rtx addr = XEXP (varloc, 0); + descr = mem_loc_descriptor (addr, mode, initialized); + if (descr) + have_address = 1; + else + { + rtx x = avoid_constant_pool_reference (varloc); + if (x != varloc) + descr = mem_loc_descriptor (x, mode, initialized); + } } - descr = mem_loc_descriptor (varloc, mode, initialized); + else + descr = mem_loc_descriptor (varloc, mode, initialized); } else return 0; @@ -13928,20 +13950,21 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address, return descr; } -/* Return dwarf representation of location list representing for - LOC_LIST of DECL. WANT_ADDRESS has the same meaning as in - loc_list_from_tree function. */ +/* Return the dwarf representation of the location list LOC_LIST of + DECL. WANT_ADDRESS has the same meaning as in loc_list_from_tree + function. */ static dw_loc_list_ref -dw_loc_list (var_loc_list * loc_list, tree decl, int want_address) +dw_loc_list (var_loc_list *loc_list, tree decl, int want_address) { const char *endname, *secname; - dw_loc_list_ref list; rtx varloc; enum var_init_status initialized; struct var_loc_node *node; dw_loc_descr_ref descr; char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; + dw_loc_list_ref list = NULL; + dw_loc_list_ref *listp = &list; /* Now that we know what section we are using for a base, actually construct the list of locations. @@ -13954,26 +13977,9 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address) This means we have to special case the last node, and generate a range of [last location start, end of function label]. */ - node = loc_list->first; secname = secname_for_decl (decl); - if (NOTE_VAR_LOCATION_LOC (node->var_loc_note)) - initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note); - else - initialized = VAR_INIT_STATUS_INITIALIZED; - varloc = NOTE_VAR_LOCATION (node->var_loc_note); - descr = dw_loc_list_1 (decl, varloc, want_address, initialized); - - if (loc_list && loc_list->first != loc_list->last) - list = new_loc_list (descr, node->label, node->next->label, secname, 1); - else - return single_element_loc_list (descr); - node = node->next; - - if (!node) - return NULL; - - for (; node->next; node = node->next) + for (node = loc_list->first; node->next; node = node->next) if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX) { /* The variable has a location between NODE->LABEL and @@ -13981,28 +13987,46 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address) initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note); varloc = NOTE_VAR_LOCATION (node->var_loc_note); descr = dw_loc_list_1 (decl, varloc, want_address, initialized); - add_loc_descr_to_loc_list (&list, descr, - node->label, node->next->label, secname); + if (descr) + { + *listp = new_loc_list (descr, node->label, node->next->label, + secname); + listp = &(*listp)->dw_loc_next; + } } /* If the variable has a location at the last label it keeps its location until the end of function. */ if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX) { - if (!current_function_decl) - endname = text_end_label; - else - { - ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, - current_function_funcdef_no); - endname = ggc_strdup (label_id); - } - initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note); varloc = NOTE_VAR_LOCATION (node->var_loc_note); descr = dw_loc_list_1 (decl, varloc, want_address, initialized); - add_loc_descr_to_loc_list (&list, descr, node->label, endname, secname); + if (descr) + { + if (!current_function_decl) + endname = text_end_label; + else + { + ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, + current_function_funcdef_no); + endname = ggc_strdup (label_id); + } + + *listp = new_loc_list (descr, node->label, endname, secname); + listp = &(*listp)->dw_loc_next; + } } + + /* Try to avoid the overhead of a location list emitting a location + expression instead, but only if we didn't have more than one + location entry in the first place. If some entries were not + representable, we don't want to pretend a single entry that was + applies to the entire scope in which the variable is + available. */ + if (list && loc_list->first->next) + gen_llsym (list); + return list; } @@ -14012,7 +14036,8 @@ dw_loc_list (var_loc_list * loc_list, tree decl, int want_address) static bool single_element_loc_list_p (dw_loc_list_ref list) { - return (!list->dw_loc_next && !list->begin && !list->end); + gcc_assert (!list->dw_loc_next || list->ll_symbol); + return !list->ll_symbol; } /* To each location in list LIST add loc descr REF. */ @@ -14046,7 +14071,7 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref) TODO: We handle only simple cases of RET or LIST having at most one element. General case would inolve sorting the lists in program order - and merging them that will need some additional work. + and merging them that will need some additional work. Adding that will improve quality of debug info especially for SRA-ed structures. */ @@ -14309,13 +14334,17 @@ loc_list_from_tree (tree loc, int want_address) case RESULT_DECL: case FUNCTION_DECL: { - rtx rtl = rtl_for_decl_location (loc); + rtx rtl; var_loc_list *loc_list = lookup_decl_loc (loc); - if (loc_list && loc_list->first - && (list_ret = dw_loc_list (loc_list, loc, want_address))) - have_address = want_address != 0; - else if (rtl == NULL_RTX) + if (loc_list && loc_list->first) + { + list_ret = dw_loc_list (loc_list, loc, want_address); + have_address = want_address != 0; + break; + } + rtl = rtl_for_decl_location (loc); + if (rtl == NULL_RTX) { expansion_failed (loc, NULL_RTX, "DECL has no RTL"); return 0; @@ -14430,7 +14459,7 @@ loc_list_from_tree (tree loc, int want_address) if (bytepos > 0) add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); else if (bytepos < 0) - loc_list_plus_const (list_ret, bytepos); + loc_list_plus_const (list_ret, bytepos); have_address = 1; break; @@ -14489,6 +14518,8 @@ loc_list_from_tree (tree loc, int want_address) case CEIL_DIV_EXPR: case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: + if (TYPE_UNSIGNED (TREE_TYPE (loc))) + return 0; op = DW_OP_div; goto do_binop; @@ -14500,8 +14531,25 @@ loc_list_from_tree (tree loc, int want_address) case CEIL_MOD_EXPR: case ROUND_MOD_EXPR: case TRUNC_MOD_EXPR: - op = DW_OP_mod; - goto do_binop; + if (TYPE_UNSIGNED (TREE_TYPE (loc))) + { + op = DW_OP_mod; + goto do_binop; + } + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0); + list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0); + if (list_ret == 0 || list_ret1 == 0) + return 0; + + add_loc_list (&list_ret, list_ret1); + if (list_ret == 0) + return 0; + add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_over, 0, 0)); + add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_over, 0, 0)); + add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_div, 0, 0)); + add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_mul, 0, 0)); + add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_minus, 0, 0)); + break; case MULT_EXPR: op = DW_OP_mul; @@ -14721,7 +14769,7 @@ loc_list_from_tree (tree loc, int want_address) add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0)); } if (ret) - list_ret = single_element_loc_list (ret); + list_ret = new_loc_list (ret, NULL, NULL, NULL); return list_ret; } @@ -15039,11 +15087,11 @@ add_data_member_location_attribute (dw_die_ref die, tree decl) else { enum dwarf_location_atom op; - + /* The DWARF2 standard says that we should assume that the structure address is already on the stack, so we can specify a structure field address by using DW_OP_plus_uconst. */ - + #ifdef MIPS_DEBUGGING_INFO /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst operator correctly. It works only if we leave the offset on the @@ -15052,7 +15100,7 @@ add_data_member_location_attribute (dw_die_ref die, tree decl) #else op = DW_OP_plus_uconst; #endif - + loc_descr = new_loc_descr (op, offset, 0); } } @@ -15223,10 +15271,20 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) return true; case CONST_STRING: - resolve_one_addr (&rtl, NULL); - add_AT_addr (die, DW_AT_const_value, rtl); - VEC_safe_push (rtx, gc, used_rtx_array, rtl); - return true; + if (dwarf_version >= 4 || !dwarf_strict) + { + dw_loc_descr_ref loc_result; + resolve_one_addr (&rtl, NULL); + rtl_addr: + loc_result = new_loc_descr (DW_OP_addr, 0, 0); + loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; + loc_result->dw_loc_oprnd1.v.val_addr = rtl; + add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0)); + add_AT_loc (die, DW_AT_location, loc_result); + VEC_safe_push (rtx, gc, used_rtx_array, rtl); + return true; + } + return false; case CONST: if (CONSTANT_P (XEXP (rtl, 0))) @@ -15236,9 +15294,9 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) if (!const_ok_for_output (rtl)) return false; case LABEL_REF: - add_AT_addr (die, DW_AT_const_value, rtl); - VEC_safe_push (rtx, gc, used_rtx_array, rtl); - return true; + if (dwarf_version >= 4 || !dwarf_strict) + goto rtl_addr; + return false; case PLUS: /* In cases where an inlined instance of an inline function is passed @@ -15605,6 +15663,27 @@ rtl_for_decl_location (tree decl) if (rtl) rtl = avoid_constant_pool_reference (rtl); + /* Try harder to get a rtl. If this symbol ends up not being emitted + in the current CU, resolve_addr will remove the expression referencing + it. */ + if (rtl == NULL_RTX + && TREE_CODE (decl) == VAR_DECL + && !DECL_EXTERNAL (decl) + && TREE_STATIC (decl) + && DECL_NAME (decl) + && !DECL_HARD_REGISTER (decl) + && DECL_MODE (decl) != VOIDmode) + { + rtl = DECL_RTL (decl); + /* Reset DECL_RTL back, as various parts of the compiler expects + DECL_RTL set meaning it is actually going to be output. */ + SET_DECL_RTL (decl, NULL); + if (!MEM_P (rtl) + || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF + || SYMBOL_REF_DECL (XEXP (rtl, 0)) != decl) + rtl = NULL_RTX; + } + return rtl; } @@ -15694,17 +15773,18 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, a constant value. That way we are better to use add_const_value_attribute rather than expanding constant value equivalent. */ loc_list = lookup_decl_loc (decl); - if (loc_list && loc_list->first && loc_list->first == loc_list->last) + if (loc_list + && loc_list->first + && loc_list->first == loc_list->last + && NOTE_VAR_LOCATION (loc_list->first->var_loc_note) + && NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note)) { - enum var_init_status status; struct var_loc_node *node; node = loc_list->first; - status = NOTE_VAR_LOCATION_STATUS (node->var_loc_note); - rtl = NOTE_VAR_LOCATION (node->var_loc_note); - if (GET_CODE (rtl) == VAR_LOCATION - && GET_CODE (XEXP (rtl, 1)) != PARALLEL) - rtl = XEXP (XEXP (rtl, 1), 0); + rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note); + if (GET_CODE (rtl) != PARALLEL) + rtl = XEXP (rtl, 0); if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING) && add_const_value_attribute (die, rtl)) return true; @@ -15991,8 +16071,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section, - list == NULL); + start_label, last_label, section); list_tail = &(*list_tail)->dw_loc_next; last_cfa = next_cfa; @@ -16013,14 +16092,16 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset) if (!cfa_equal_p (&last_cfa, &next_cfa)) { *list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset), - start_label, last_label, section, - list == NULL); + start_label, last_label, section); list_tail = &(*list_tail)->dw_loc_next; start_label = last_label; } + *list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset), - start_label, fde->dw_fde_end, section, - list == NULL); + start_label, fde->dw_fde_end, section); + + if (list && list->dw_loc_next) + gen_llsym (list); return list; } @@ -16450,7 +16531,8 @@ add_pure_or_virtual_attribute (dw_die_ref die, tree func_decl) 0)); /* GNU extension: Record what type this method came from originally. */ - if (debug_info_level > DINFO_LEVEL_TERSE) + if (debug_info_level > DINFO_LEVEL_TERSE + && DECL_CONTEXT (func_decl)) add_AT_die_ref (die, DW_AT_containing_type, lookup_type_die (DECL_CONTEXT (func_decl))); } @@ -16868,7 +16950,7 @@ gen_array_type_die (tree type, dw_die_ref context_die) add_subscript_info (array_die, type, collapse_nested_arrays); /* Add representation of the type of the elements of this array type and - emit the corresponding DIE if we haven't done it already. */ + emit the corresponding DIE if we haven't done it already. */ element_type = TREE_TYPE (type); if (collapse_nested_arrays) while (TREE_CODE (element_type) == ARRAY_TYPE) @@ -17370,7 +17452,8 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die) /* If we're trying to avoid duplicate debug info, we may not have emitted the member decl for this function. Emit it now. */ - if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) + if (TYPE_STUB_DECL (type) + && TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) && ! lookup_decl_die (member)) { dw_die_ref type_die; @@ -17408,7 +17491,7 @@ dwarf2out_abstract_function (tree decl) dw_die_ref old_die; tree save_fn; tree context; - int was_abstract = DECL_ABSTRACT (decl); + int was_abstract; htab_t old_decl_loc_table; /* Make sure we have the actual abstract inline, not a clone. */ @@ -17440,6 +17523,7 @@ dwarf2out_abstract_function (tree decl) current_function_decl = decl; push_cfun (DECL_STRUCT_FUNCTION (decl)); + was_abstract = DECL_ABSTRACT (decl); set_decl_abstract_flags (decl, 1); dwarf2out_decl (decl); if (! was_abstract) @@ -17813,7 +17897,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) of the pack. Note that the set of pack arguments can be empty. In that case, the DW_TAG_GNU_formal_parameter_pack DIE will not have any children DIE. - + Otherwise, we just consider the parameters of DECL. */ while (generic_decl_parm || parm) { @@ -17926,26 +18010,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL; dw_die_ref origin_die; int declaration = (DECL_EXTERNAL (decl_or_origin) - /* If DECL is COMDAT and has not actually been - emitted, we cannot take its address; there - might end up being no definition anywhere in - the program. For example, consider the C++ - test case: - - template - struct S { static const int i = 7; }; - - template - const int S::i; - - int f() { return S::i; } - - Here, S::i is not DECL_EXTERNAL, but no - definition is required, so the compiler will - not emit a definition. */ - || (TREE_CODE (decl_or_origin) == VAR_DECL - && DECL_COMDAT (decl_or_origin) - && !TREE_ASM_WRITTEN (decl_or_origin)) || class_or_namespace_scope_p (context_die)); if (!origin) @@ -17957,7 +18021,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) of a data member. */ if (com_decl) { - tree field; dw_die_ref com_die; dw_loc_list_ref loc; die_node com_die_arg; @@ -17995,7 +18058,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) = htab_create_ggc (10, common_block_die_table_hash, common_block_die_table_eq, NULL); - field = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0); com_die_arg.decl_id = DECL_UID (com_decl); com_die_arg.die_parent = context_die; com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg); @@ -18059,8 +18121,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) and if we already emitted a DIE for it, don't emit a second DIE for it again. */ if (old_die - && declaration - && old_die->die_parent == context_die) + && declaration) return; /* For static data members, the declaration in the class is supposed @@ -19085,7 +19146,7 @@ get_context_die (tree context) { /* Find die that represents this context. */ if (TYPE_P (context)) - return force_type_die (context); + return force_type_die (TYPE_MAIN_VARIANT (context)); else return force_decl_die (context); } @@ -19924,7 +19985,7 @@ gen_remaining_tmpl_value_param_die_attribute (void) /* Replace DW_AT_name for the decl with name. */ - + static void dwarf2out_set_name (tree decl, tree name) { @@ -20579,7 +20640,7 @@ prune_unused_types_mark (dw_die_ref die, int dokids) breaking out types into comdat sections, do this for all type definitions. */ if (die->die_tag == DW_TAG_array_type - || (dwarf_version >= 4 + || (dwarf_version >= 4 && is_type_die (die) && ! is_declaration_die (die))) FOR_EACH_CHILD (die, c, prune_unused_types_mark (c, 1)); else @@ -20974,28 +21035,48 @@ resolve_addr (dw_die_ref die) { dw_die_ref c; dw_attr_ref a; - dw_loc_list_ref curr; + dw_loc_list_ref *curr; unsigned ix; for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) switch (AT_class (a)) { case dw_val_class_loc_list: - for (curr = AT_loc_list (a); curr != NULL; curr = curr->dw_loc_next) - if (!resolve_addr_in_expr (curr->expr)) - curr->expr = NULL; + curr = AT_loc_list_ptr (a); + while (*curr) + { + if (!resolve_addr_in_expr ((*curr)->expr)) + { + dw_loc_list_ref next = (*curr)->dw_loc_next; + if (next && (*curr)->ll_symbol) + { + gcc_assert (!next->ll_symbol); + next->ll_symbol = (*curr)->ll_symbol; + } + *curr = next; + } + else + curr = &(*curr)->dw_loc_next; + } + if (!AT_loc_list (a)) + { + remove_AT (die, a->dw_attr); + ix--; + } break; case dw_val_class_loc: if (!resolve_addr_in_expr (AT_loc (a))) - a->dw_attr_val.v.val_loc = NULL; + { + remove_AT (die, a->dw_attr); + ix--; + } break; case dw_val_class_addr: if (a->dw_attr == DW_AT_const_value && resolve_one_addr (&a->dw_attr_val.v.val_addr, NULL)) { - a->dw_attr = DW_AT_location; - a->dw_attr_val.val_class = dw_val_class_loc; - a->dw_attr_val.v.val_loc = NULL; + remove_AT (die, a->dw_attr); + ix--; } break; default: @@ -21176,6 +21257,7 @@ dwarf2out_finish (const char *filename) else { unsigned fde_idx = 0; + bool range_list_added = false; /* We need to give .debug_loc and .debug_ranges an appropriate "base address". Use zero so that these addresses become @@ -21185,12 +21267,12 @@ dwarf2out_finish (const char *filename) add_AT_addr (comp_unit_die, DW_AT_low_pc, const0_rtx); add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx); - add_AT_range_list (comp_unit_die, DW_AT_ranges, - add_ranges_by_labels (text_section_label, - text_end_label)); - if (flag_reorder_blocks_and_partition) - add_ranges_by_labels (cold_text_section_label, - cold_end_label); + if (text_section_used) + add_ranges_by_labels (comp_unit_die, text_section_label, + text_end_label, &range_list_added); + if (flag_reorder_blocks_and_partition && cold_text_section_used) + add_ranges_by_labels (comp_unit_die, cold_text_section_label, + cold_end_label, &range_list_added); for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++) { @@ -21199,18 +21281,23 @@ dwarf2out_finish (const char *filename) if (fde->dw_fde_switched_sections) { if (!fde->in_std_section) - add_ranges_by_labels (fde->dw_fde_hot_section_label, - fde->dw_fde_hot_section_end_label); + add_ranges_by_labels (comp_unit_die, + fde->dw_fde_hot_section_label, + fde->dw_fde_hot_section_end_label, + &range_list_added); if (!fde->cold_in_std_section) - add_ranges_by_labels (fde->dw_fde_unlikely_section_label, - fde->dw_fde_unlikely_section_end_label); + add_ranges_by_labels (comp_unit_die, + fde->dw_fde_unlikely_section_label, + fde->dw_fde_unlikely_section_end_label, + &range_list_added); } else if (!fde->in_std_section) - add_ranges_by_labels (fde->dw_fde_begin, - fde->dw_fde_end); + add_ranges_by_labels (comp_unit_die, fde->dw_fde_begin, + fde->dw_fde_end, &range_list_added); } - add_ranges (NULL); + if (range_list_added) + add_ranges (NULL); } /* Output location list section if necessary. */