| 2005-06-08 Eric Botcazou <ebotcazou@libertysurf.fr> |
| |
| PR debug/21946 |
| * dwarf2out.c (add_loc_descr_op_piece): Move to the |
| DWARF2_DEBUGGING_INFO section. |
| |
| 2005-06-07 Jakub Jelinek <jakub@redhat.com> |
| |
| PR debug/21946 |
| * dwarf2out.c (add_loc_descr_op_piece): New function. |
| (multiple_reg_loc_descriptor, concat_loc_descriptor, |
| loc_descriptor): Use it. |
| |
| * var-tracking.c: Include regs.h and expr.h. |
| (emit_note_insn_var_location): Skip over pieces where offset |
| is smaller than previous offset plus previous piece mode size. |
| Optimize adjacent hard registers or memory locations. |
| * Makefile.in (var-tracking.o): Depend on $(REGS_H) and $(EXPR_H). |
| |
| |
| |
| @@ -3747,6 +3748,7 @@ static dw_die_ref subrange_type_die (tre |
| static dw_die_ref modified_type_die (tree, int, int, dw_die_ref); |
| static int type_is_enum (tree); |
| static unsigned int dbx_reg_number (rtx); |
| +static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); |
| static dw_loc_descr_ref reg_loc_descriptor (rtx); |
| static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); |
| static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); |
| @@ -8176,6 +8178,26 @@ dbx_reg_number (rtx rtl) |
| return DBX_REGISTER_NUMBER (regno); |
| } |
| |
| +/* Optionally add a DW_OP_piece term to a location description expression. |
| + DW_OP_piece is only added if the location description expression already |
| + doesn't end with DW_OP_piece. */ |
| + |
| +static void |
| +add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size) |
| +{ |
| + dw_loc_descr_ref loc; |
| + |
| + if (*list_head != NULL) |
| + { |
| + /* Find the end of the chain. */ |
| + for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next) |
| + ; |
| + |
| + if (loc->dw_loc_opc != DW_OP_piece) |
| + loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0); |
| + } |
| +} |
| + |
| /* Return a location descriptor that designates a machine register or |
| zero if there is none. */ |
| |
| @@ -8235,7 +8257,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt |
| |
| t = one_reg_loc_descriptor (reg); |
| add_loc_descr (&loc_result, t); |
| - add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); |
| + add_loc_descr_op_piece (&loc_result, size); |
| ++reg; |
| } |
| return loc_result; |
| @@ -8256,7 +8278,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt |
| t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i))); |
| add_loc_descr (&loc_result, t); |
| size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0))); |
| - add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); |
| + add_loc_descr_op_piece (&loc_result, size); |
| } |
| return loc_result; |
| } |
| @@ -8551,14 +8573,10 @@ concat_loc_descriptor (rtx x0, rtx x1) |
| return 0; |
| |
| cc_loc_result = x0_ref; |
| - add_loc_descr (&cc_loc_result, |
| - new_loc_descr (DW_OP_piece, |
| - GET_MODE_SIZE (GET_MODE (x0)), 0)); |
| + add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0))); |
| |
| add_loc_descr (&cc_loc_result, x1_ref); |
| - add_loc_descr (&cc_loc_result, |
| - new_loc_descr (DW_OP_piece, |
| - GET_MODE_SIZE (GET_MODE (x1)), 0)); |
| + add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1))); |
| |
| return cc_loc_result; |
| } |
| @@ -8619,8 +8637,7 @@ loc_descriptor (rtx rtl, bool can_use_fb |
| loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), |
| can_use_fbreg); |
| mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); |
| - add_loc_descr (&loc_result, |
| - new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); |
| + add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); |
| for (i = 1; i < num_elem; i++) |
| { |
| dw_loc_descr_ref temp; |
| @@ -8629,9 +8646,7 @@ loc_descriptor (rtx rtl, bool can_use_fb |
| can_use_fbreg); |
| add_loc_descr (&loc_result, temp); |
| mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); |
| - add_loc_descr (&loc_result, |
| - new_loc_descr (DW_OP_piece, |
| - GET_MODE_SIZE (mode), 0)); |
| + add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); |
| } |
| } |
| break; |
| @@ -9930,8 +9945,7 @@ add_location_or_const_value_attribute (d |
| /* Create the first one, so we have something to add to. */ |
| descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true); |
| mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); |
| - add_loc_descr (&descr, |
| - new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); |
| + add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); |
| for (i = 1; i < num_elem; i++) |
| { |
| dw_loc_descr_ref temp; |
| @@ -9939,9 +9953,7 @@ add_location_or_const_value_attribute (d |
| temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true); |
| add_loc_descr (&descr, temp); |
| mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); |
| - add_loc_descr (&descr, |
| - new_loc_descr (DW_OP_piece, |
| - GET_MODE_SIZE (mode), 0)); |
| + add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); |
| } |
| } |
| add_AT_location_description (die, DW_AT_location, descr); |
| |
| |
| @@ -102,6 +102,8 @@ |
| #include "alloc-pool.h" |
| #include "fibheap.h" |
| #include "hashtab.h" |
| +#include "regs.h" |
| +#include "expr.h" |
| |
| /* Type of micro operation. */ |
| enum micro_operation_type |
| @@ -2185,10 +2187,12 @@ emit_note_insn_var_location (void **varp |
| rtx insn = ((emit_note_data *)data)->insn; |
| enum emit_note_where where = ((emit_note_data *)data)->where; |
| rtx note; |
| - int i; |
| + int i, j, n_var_parts; |
| bool complete; |
| HOST_WIDE_INT last_limit; |
| tree type_size_unit; |
| + HOST_WIDE_INT offsets[MAX_VAR_PARTS]; |
| + rtx loc[MAX_VAR_PARTS]; |
| |
| #ifdef ENABLE_CHECKING |
| if (!var->decl) |
| @@ -2197,16 +2201,90 @@ emit_note_insn_var_location (void **varp |
| |
| complete = true; |
| last_limit = 0; |
| + n_var_parts = 0; |
| for (i = 0; i < var->n_var_parts; i++) |
| { |
| + enum machine_mode mode, wider_mode; |
| + |
| if (last_limit < var->var_part[i].offset) |
| { |
| complete = false; |
| break; |
| } |
| - last_limit |
| - = (var->var_part[i].offset |
| - + GET_MODE_SIZE (GET_MODE (var->var_part[i].loc_chain->loc))); |
| + else if (last_limit > var->var_part[i].offset) |
| + continue; |
| + offsets[n_var_parts] = var->var_part[i].offset; |
| + loc[n_var_parts] = var->var_part[i].loc_chain->loc; |
| + mode = GET_MODE (loc[n_var_parts]); |
| + last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); |
| + |
| + /* Attempt to merge adjacent registers or memory. */ |
| + wider_mode = GET_MODE_WIDER_MODE (mode); |
| + for (j = i + 1; j < var->n_var_parts; j++) |
| + if (last_limit <= var->var_part[j].offset) |
| + break; |
| + if (j < var->n_var_parts |
| + && wider_mode != VOIDmode |
| + && GET_CODE (loc[n_var_parts]) |
| + == GET_CODE (var->var_part[j].loc_chain->loc) |
| + && mode == GET_MODE (var->var_part[j].loc_chain->loc) |
| + && last_limit == var->var_part[j].offset) |
| + { |
| + rtx new_loc = NULL; |
| + rtx loc2 = var->var_part[j].loc_chain->loc; |
| + |
| + if (REG_P (loc[n_var_parts]) |
| + && HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode) * 2 |
| + == HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), wider_mode) |
| + && REGNO (loc[n_var_parts]) |
| + + HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode) |
| + == REGNO (loc2)) |
| + { |
| + if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN) |
| + new_loc = simplify_subreg (wider_mode, loc[n_var_parts], |
| + mode, 0); |
| + else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN) |
| + new_loc = simplify_subreg (wider_mode, loc2, mode, 0); |
| + if (new_loc) |
| + { |
| + if (!REG_P (new_loc) |
| + || REGNO (new_loc) != REGNO (loc[n_var_parts])) |
| + new_loc = NULL; |
| + else |
| + REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]); |
| + } |
| + } |
| + else if (GET_CODE (loc[n_var_parts]) == MEM |
| + && GET_CODE (XEXP (loc2, 0)) == PLUS |
| + && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG |
| + && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT) |
| + { |
| + if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG |
| + && rtx_equal_p (XEXP (loc[n_var_parts], 0), |
| + XEXP (XEXP (loc2, 0), 0)) |
| + && INTVAL (XEXP (XEXP (loc2, 0), 1)) |
| + == GET_MODE_SIZE (mode)) |
| + || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS |
| + && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1)) |
| + == CONST_INT |
| + && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0), |
| + XEXP (XEXP (loc2, 0), 0)) |
| + && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1)) |
| + + GET_MODE_SIZE (mode) |
| + == INTVAL (XEXP (XEXP (loc2, 0), 1)))) |
| + new_loc = adjust_address_nv (loc[n_var_parts], |
| + wider_mode, 0); |
| + } |
| + |
| + if (new_loc) |
| + { |
| + loc[n_var_parts] = new_loc; |
| + mode = wider_mode; |
| + last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); |
| + i = j; |
| + } |
| + } |
| + ++n_var_parts; |
| } |
| type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl)); |
| if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) |
| @@ -2222,26 +2300,24 @@ emit_note_insn_var_location (void **varp |
| NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, |
| NULL_RTX); |
| } |
| - else if (var->n_var_parts == 1) |
| + else if (n_var_parts == 1) |
| { |
| rtx expr_list |
| - = gen_rtx_EXPR_LIST (VOIDmode, |
| - var->var_part[0].loc_chain->loc, |
| - GEN_INT (var->var_part[0].offset)); |
| + = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); |
| |
| NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, |
| expr_list); |
| } |
| - else if (var->n_var_parts) |
| + else if (n_var_parts) |
| { |
| - rtx argp[MAX_VAR_PARTS]; |
| rtx parallel; |
| |
| - for (i = 0; i < var->n_var_parts; i++) |
| - argp[i] = gen_rtx_EXPR_LIST (VOIDmode, var->var_part[i].loc_chain->loc, |
| - GEN_INT (var->var_part[i].offset)); |
| + for (i = 0; i < n_var_parts; i++) |
| + loc[i] |
| + = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i])); |
| + |
| parallel = gen_rtx_PARALLEL (VOIDmode, |
| - gen_rtvec_v (var->n_var_parts, argp)); |
| + gen_rtvec_v (n_var_parts, loc)); |
| NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, |
| parallel); |
| } |
| |
| |
| @@ -1693,7 +1693,8 @@ df.o : df.c $(CONFIG_H) $(SYSTEM_H) core |
| $(BASIC_BLOCK_H) df.h $(FIBHEAP_H) |
| var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ |
| $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h flags.h \ |
| - $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) |
| + $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \ |
| + $(REGS_H) $(EXPR_H) |
| conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \ |
| $(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H) |
| profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ |