From c8a27c401821b4d29c28add396177637f9f381d5 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 9 Sep 2010 08:43:47 +0200 Subject: [PATCH] rtl.def (DEBUG_IMPLICIT_PTR): New rtl code. * rtl.def (DEBUG_IMPLICIT_PTR): New rtl code. * rtl.h (DEBUG_IMPLICIT_PTR_DECL): Define. * rtl.c (rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_IMPLICIT_PTR. * print-rtl.c (print_rtx): Likewise. * cselib.c (rtx_equal_for_cselib_p, cselib_hash_rtx): Likewise. * cfgexpand.c (expand_debug_expr): Generate DEBUG_IMPLICIT_PTR for ADDR_EXPR with non-addressable object. * dwarf2out.c (enum dw_val_class): Add dw_val_class_decl_ref. (struct dw_val_struct): Add v.val_decl_ref. (dwarf_stack_op_name, output_loc_operands, output_loc_operands_raw): Handle DW_OP_GNU_implicit_pointer. (size_of_loc_descr): Likewise. Fix up DW_OP_call_ref size. (get_ref_die_offset_label): New function. (implicit_ptr_descriptor): New function. (mem_loc_descriptor): Handle DEBUG_IMPLICIT_PTR. (loc_descriptor): Likewise. (gen_variable_die): Put even definitions into decl_die_table. (resolve_addr_in_expr): Resolve still unresolved DW_OP_GNU_implicit_pointer operands, if it can't be resolved return false. (dwarf2out_finish): Call output_location_lists after outputting .debug_info and .debug_abbrev instead of before. * dwarf2.h (DW_OP_GNU_implicit_pointer): New. 2010-09-09 Roland McGrath * dwarf2out.c (DWARF_REF_SIZE): Define. (size_of_loc_descr): Use it for DW_OP_call_ref. From-SVN: r164050 --- gcc/ChangeLog | 30 ++++++++++++ gcc/cfgexpand.c | 27 ++++++++++- gcc/cselib.c | 9 ++++ gcc/dwarf2out.c | 115 ++++++++++++++++++++++++++++++++++++++++------ gcc/print-rtl.c | 5 +- gcc/rtl.c | 8 ++++ gcc/rtl.def | 4 ++ gcc/rtl.h | 3 ++ include/ChangeLog | 4 ++ include/dwarf2.h | 1 + 10 files changed, 191 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e80ee9e8bc..b815a39d993 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2010-09-09 Jakub Jelinek + + * rtl.def (DEBUG_IMPLICIT_PTR): New rtl code. + * rtl.h (DEBUG_IMPLICIT_PTR_DECL): Define. + * rtl.c (rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_IMPLICIT_PTR. + * print-rtl.c (print_rtx): Likewise. + * cselib.c (rtx_equal_for_cselib_p, cselib_hash_rtx): Likewise. + * cfgexpand.c (expand_debug_expr): Generate DEBUG_IMPLICIT_PTR + for ADDR_EXPR with non-addressable object. + * dwarf2out.c (enum dw_val_class): Add dw_val_class_decl_ref. + (struct dw_val_struct): Add v.val_decl_ref. + (dwarf_stack_op_name, output_loc_operands, output_loc_operands_raw): + Handle DW_OP_GNU_implicit_pointer. + (size_of_loc_descr): Likewise. Fix up DW_OP_call_ref size. + (get_ref_die_offset_label): New function. + (implicit_ptr_descriptor): New function. + (mem_loc_descriptor): Handle DEBUG_IMPLICIT_PTR. + (loc_descriptor): Likewise. + (gen_variable_die): Put even definitions into decl_die_table. + (resolve_addr_in_expr): Resolve still unresolved + DW_OP_GNU_implicit_pointer operands, if it can't be resolved + return false. + (dwarf2out_finish): Call output_location_lists after outputting + .debug_info and .debug_abbrev instead of before. + +2010-09-09 Roland McGrath + + * dwarf2out.c (DWARF_REF_SIZE): Define. + (size_of_loc_descr): Use it for DW_OP_call_ref. + 2010-09-09 Alan Modra * doc/invoke.text: Reinstate mcmodel=medium. diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 4ae541dd2bc..42372769049 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2911,7 +2911,32 @@ expand_debug_expr (tree exp) case ADDR_EXPR: op0 = expand_debug_expr (TREE_OPERAND (exp, 0)); if (!op0 || !MEM_P (op0)) - return NULL; + { + if ((TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL + || TREE_CODE (TREE_OPERAND (exp, 0)) == PARM_DECL + || TREE_CODE (TREE_OPERAND (exp, 0)) == RESULT_DECL) + && !TREE_ADDRESSABLE (TREE_OPERAND (exp, 0))) + return gen_rtx_DEBUG_IMPLICIT_PTR (mode, TREE_OPERAND (exp, 0)); + + if (handled_component_p (TREE_OPERAND (exp, 0))) + { + HOST_WIDE_INT bitoffset, bitsize, maxsize; + tree decl + = get_ref_base_and_extent (TREE_OPERAND (exp, 0), + &bitoffset, &bitsize, &maxsize); + if ((TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == RESULT_DECL) + && !TREE_ADDRESSABLE (decl) + && (bitoffset % BITS_PER_UNIT) == 0 + && bitsize > 0 + && bitsize == maxsize) + return plus_constant (gen_rtx_DEBUG_IMPLICIT_PTR (mode, decl), + bitoffset / BITS_PER_UNIT); + } + + return NULL; + } op0 = convert_debug_memory_address (mode, XEXP (op0, 0)); diff --git a/gcc/cselib.c b/gcc/cselib.c index 64f183f2b1e..05029fa286c 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -700,6 +700,10 @@ rtx_equal_for_cselib_p (rtx x, rtx y) case DEBUG_EXPR: return 0; + case DEBUG_IMPLICIT_PTR: + return DEBUG_IMPLICIT_PTR_DECL (x) + == DEBUG_IMPLICIT_PTR_DECL (y); + case LABEL_REF: return XEXP (x, 0) == XEXP (y, 0); @@ -834,6 +838,11 @@ cselib_hash_rtx (rtx x, int create) + DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)); return hash ? hash : (unsigned int) DEBUG_EXPR; + case DEBUG_IMPLICIT_PTR: + hash += ((unsigned) DEBUG_IMPLICIT_PTR << 7) + + DECL_UID (DEBUG_IMPLICIT_PTR_DECL (x)); + return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR; + case CONST_INT: hash += ((unsigned) CONST_INT << 7) + INTVAL (x); return hash ? hash : (unsigned int) CONST_INT; diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 237d089ea1d..11707fbbe5b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -4294,6 +4294,7 @@ enum dw_val_class dw_val_class_macptr, dw_val_class_file, dw_val_class_data8, + dw_val_class_decl_ref, dw_val_class_vms_delta }; @@ -4332,6 +4333,7 @@ typedef struct GTY(()) dw_val_struct { unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag; struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file; unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8]; + tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref; struct dw_val_vms_delta_union { char * lbl1; @@ -4695,6 +4697,8 @@ dwarf_stack_op_name (unsigned int op) return "DW_OP_GNU_uninit"; case DW_OP_GNU_encoded_addr: return "DW_OP_GNU_encoded_addr"; + case DW_OP_GNU_implicit_pointer: + return "DW_OP_GNU_implicit_pointer"; default: return "OP_"; @@ -4798,6 +4802,9 @@ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset) loc_descr_plus_const (&d->expr, offset); } +#define DWARF_REF_SIZE \ + (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE) + /* Return the size of a location descriptor. */ static unsigned long @@ -4904,12 +4911,15 @@ size_of_loc_descr (dw_loc_descr_ref loc) size += 4; break; case DW_OP_call_ref: - size += DWARF2_ADDR_SIZE; + size += DWARF_REF_SIZE; break; case DW_OP_implicit_value: size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned) + loc->dw_loc_oprnd1.v.val_unsigned; break; + case DW_OP_GNU_implicit_pointer: + size += DWARF_REF_SIZE + size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int); + break; default: break; } @@ -4946,6 +4956,7 @@ size_of_locs (dw_loc_descr_ref loc) } static HOST_WIDE_INT extract_int (const unsigned char *, unsigned); +static void get_ref_die_offset_label (char *, dw_die_ref); /* Output location description stack opcode's operands (if any). */ @@ -5165,6 +5176,17 @@ output_loc_operands (dw_loc_descr_ref loc) } break; + case DW_OP_GNU_implicit_pointer: + { + char label[MAX_ARTIFICIAL_LABEL_BYTES + + HOST_BITS_PER_WIDE_INT / 2 + 2]; + gcc_assert (val1->val_class == dw_val_class_die_ref); + get_ref_die_offset_label (label, val1->v.val_die_ref.die); + dw2_asm_output_offset (DWARF_REF_SIZE, label, debug_info_section, NULL); + dw2_asm_output_data_sleb128 (val2->v.val_int, NULL); + } + break; + default: /* Other codes have no operands. */ break; @@ -5303,6 +5325,10 @@ output_loc_operands_raw (dw_loc_descr_ref loc) dw2_asm_output_data_sleb128_raw (val2->v.val_int); break; + case DW_OP_GNU_implicit_pointer: + gcc_unreachable (); + break; + default: /* Other codes have no operands. */ break; @@ -6514,6 +6540,15 @@ is_tagged_type (const_tree type) || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE); } +/* Set label to debug_info_section_label + die_offset of a DIE reference. */ + +static void +get_ref_die_offset_label (char *label, dw_die_ref ref) +{ + sprintf (label, "%s+" HOST_WIDE_INT_PRINT_DEC, + debug_info_section_label, ref->die_offset); +} + /* Convert a DIE tag into its string name. */ static const char * @@ -13651,6 +13686,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, case CONCAT: case CONCATN: case VAR_LOCATION: + case DEBUG_IMPLICIT_PTR: expansion_failed (NULL_TREE, rtl, "CONCAT/CONCATN/VAR_LOCATION is handled only by loc_descriptor"); return 0; @@ -14240,6 +14276,35 @@ concatn_loc_descriptor (rtx concatn, enum var_init_status initialized) return cc_loc_result; } +/* Helper function for loc_descriptor. Return DW_OP_GNU_implicit_pointer + for DEBUG_IMPLICIT_PTR RTL. */ + +static dw_loc_descr_ref +implicit_ptr_descriptor (rtx rtl, HOST_WIDE_INT offset) +{ + dw_loc_descr_ref ret; + dw_die_ref ref; + + gcc_assert (TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == VAR_DECL + || TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == PARM_DECL + || TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == RESULT_DECL); + ref = lookup_decl_die (DEBUG_IMPLICIT_PTR_DECL (rtl)); + ret = new_loc_descr (DW_OP_GNU_implicit_pointer, 0, offset); + ret->dw_loc_oprnd2.val_class = dw_val_class_const; + if (ref) + { + ret->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + ret->dw_loc_oprnd1.v.val_die_ref.die = ref; + ret->dw_loc_oprnd1.v.val_die_ref.external = 0; + } + else + { + ret->dw_loc_oprnd1.val_class = dw_val_class_decl_ref; + ret->dw_loc_oprnd1.v.val_decl_ref = DEBUG_IMPLICIT_PTR_DECL (rtl); + } + return ret; +} + /* Output a proper Dwarf location descriptor for a variable or parameter which is either allocated in a register or in a memory location. For a register, we just generate an OP_REG and the register number. For a @@ -14457,6 +14522,19 @@ loc_descriptor (rtx rtl, enum machine_mode mode, } break; + case DEBUG_IMPLICIT_PTR: + loc_result = implicit_ptr_descriptor (rtl, 0); + break; + + case PLUS: + if (GET_CODE (XEXP (rtl, 0)) == DEBUG_IMPLICIT_PTR + && CONST_INT_P (XEXP (rtl, 1))) + { + loc_result + = implicit_ptr_descriptor (XEXP (rtl, 0), INTVAL (XEXP (rtl, 1))); + break; + } + /* FALLTHRU */ default: if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (rtl) == mode && GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE @@ -19190,7 +19268,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) if (declaration) add_AT_flag (var_die, DW_AT_declaration, 1); - if (decl && (DECL_ABSTRACT (decl) || declaration)) + if (decl && (DECL_ABSTRACT (decl) || declaration || old_die == NULL)) equate_decl_number_to_die (decl, var_die); if (! declaration @@ -22150,6 +22228,17 @@ resolve_addr_in_expr (dw_loc_descr_ref loc) && loc->dw_loc_oprnd2.val_class == dw_val_class_addr && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))) return false; + else if (loc->dw_loc_opc == DW_OP_GNU_implicit_pointer + && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref) + { + dw_die_ref ref + = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref); + if (ref == NULL) + return false; + loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + loc->dw_loc_oprnd1.v.val_die_ref.die = ref; + loc->dw_loc_oprnd1.v.val_die_ref.external = 0; + } return true; } @@ -22429,17 +22518,6 @@ dwarf2out_finish (const char *filename) add_ranges (NULL); } - /* Output location list section if necessary. */ - if (have_location_lists) - { - /* Output the location lists info. */ - switch_to_section (debug_loc_section); - ASM_GENERATE_INTERNAL_LABEL (loc_section_label, - DEBUG_LOC_SECTION_LABEL, 0); - ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); - output_location_lists (die); - } - if (debug_info_level >= DINFO_LEVEL_NORMAL) add_AT_lineptr (comp_unit_die, DW_AT_stmt_list, debug_line_section_label); @@ -22481,6 +22559,17 @@ dwarf2out_finish (const char *filename) switch_to_section (debug_abbrev_section); output_abbrev_section (); + /* Output location list section if necessary. */ + if (have_location_lists) + { + /* Output the location lists info. */ + switch_to_section (debug_loc_section); + ASM_GENERATE_INTERNAL_LABEL (loc_section_label, + DEBUG_LOC_SECTION_LABEL, 0); + ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); + output_location_lists (die); + } + /* Output public names table if necessary. */ if (!VEC_empty (pubname_entry, pubname_table)) { diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index 8801a88153e..04d79594b73 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -533,7 +533,10 @@ print_rtx (const_rtx in_rtx) case 't': #ifndef GENERATOR_FILE - dump_addr (outfile, " ", XTREE (in_rtx, i)); + if (i == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR) + print_mem_expr (outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx)); + else + dump_addr (outfile, " ", XTREE (in_rtx, i)); #endif break; diff --git a/gcc/rtl.c b/gcc/rtl.c index 79dafcb004f..3a6affc594f 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -407,6 +407,10 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) case CONST_FIXED: return 0; + case DEBUG_IMPLICIT_PTR: + return DEBUG_IMPLICIT_PTR_DECL (x) + == DEBUG_IMPLICIT_PTR_DECL (y); + default: break; } @@ -527,6 +531,10 @@ rtx_equal_p (const_rtx x, const_rtx y) case CONST_FIXED: return 0; + case DEBUG_IMPLICIT_PTR: + return DEBUG_IMPLICIT_PTR_DECL (x) + == DEBUG_IMPLICIT_PTR_DECL (y); + default: break; } diff --git a/gcc/rtl.def b/gcc/rtl.def index 26014ae8d49..282cca6be26 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -711,6 +711,10 @@ DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY) initialization status of variables. */ DEF_RTL_EXPR(VAR_LOCATION, "var_location", "tei", RTX_EXTRA) +/* Used in VAR_LOCATION for a pointer to a decl that is no longer + addressable. */ +DEF_RTL_EXPR(DEBUG_IMPLICIT_PTR, "debug_implicit_ptr", "t", RTX_OBJ) + /* All expressions from this point forward appear only in machine descriptions. */ #ifdef GENERATOR_FILE diff --git a/gcc/rtl.h b/gcc/rtl.h index 873c79255bf..f490a0c29e3 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -933,6 +933,9 @@ extern const char * const reg_note_name[]; /* DEBUG_EXPR_DECL corresponding to a DEBUG_EXPR RTX. */ #define DEBUG_EXPR_TREE_DECL(RTX) XCTREE (RTX, 0, DEBUG_EXPR) +/* VAR_DECL/PARM_DECL DEBUG_IMPLICIT_PTR takes address of. */ +#define DEBUG_IMPLICIT_PTR_DECL(RTX) XCTREE (RTX, 0, DEBUG_IMPLICIT_PTR) + /* Possible initialization status of a variable. When requested by the user, this information is tracked and recorded in the DWARF debug information, along with the variable's location. */ diff --git a/include/ChangeLog b/include/ChangeLog index 3fc2fa5e224..ec24917ee9a 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2010-09-09 Jakub Jelinek + + * dwarf2.h (DW_OP_GNU_implicit_pointer): New. + 2010-07-06 Ken Werner * floatformat.h (floatformat_ieee_half_big): Add declaration. diff --git a/include/dwarf2.h b/include/dwarf2.h index 03c25812d09..fea23ad61e4 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -622,6 +622,7 @@ enum dwarf_location_atom /* The following is for marking variables that are uninitialized. */ DW_OP_GNU_uninit = 0xf0, DW_OP_GNU_encoded_addr = 0xf1, + DW_OP_GNU_implicit_pointer = 0xf2, /* HP extensions. */ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ DW_OP_HP_is_value = 0xe1,