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).
--- gcc/dwarf2out.c.jj 2005-06-07 00:39:11.000000000 +0200
+++ gcc/dwarf2out.c 2005-06-07 00:54:10.000000000 +0200
@@ -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);
--- gcc/var-tracking.c.jj 2005-06-07 00:39:11.000000000 +0200
+++ gcc/var-tracking.c 2005-06-07 00:52:15.000000000 +0200
@@ -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);
}
--- gcc/Makefile.in.jj 2005-06-07 00:39:11.000000000 +0200
+++ gcc/Makefile.in 2005-06-07 00:55:12.000000000 +0200
@@ -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) \