dwarf2out.c (struct dw_loc_descr_struct): Add dw_loc_addr.
* dwarf2out.c (struct dw_loc_descr_struct): Add dw_loc_addr. (size_of_locs): Set it. (output_loc_operands): Use it to compute branch displacement. (int_loc_descriptor): New. (mem_loc_descriptor): Dereference memory in the proper size. Use DW_OP_plus_uconst when possible. Use int_loc_descriptor. (loc_descriptor_from_tree): New. (rtl_for_decl_location): Break out from ... (add_location_or_const_value_attribute): ... here. (add_bound_info): Use loc_descriptor_from_tree. From-SVN: r37172
This commit is contained in:
parent
86368122e6
commit
d8041cc89f
2 changed files with 435 additions and 53 deletions
|
@ -1,3 +1,16 @@
|
|||
2000-10-31 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* dwarf2out.c (struct dw_loc_descr_struct): Add dw_loc_addr.
|
||||
(size_of_locs): Set it.
|
||||
(output_loc_operands): Use it to compute branch displacement.
|
||||
(int_loc_descriptor): New.
|
||||
(mem_loc_descriptor): Dereference memory in the proper size.
|
||||
Use DW_OP_plus_uconst when possible. Use int_loc_descriptor.
|
||||
(loc_descriptor_from_tree): New.
|
||||
(rtl_for_decl_location): Break out from ...
|
||||
(add_location_or_const_value_attribute): ... here.
|
||||
(add_bound_info): Use loc_descriptor_from_tree.
|
||||
|
||||
2000-10-31 Neil Booth <neilb@earthling.net>
|
||||
|
||||
* cpp.texi: Update for new command line assertion syntax.
|
||||
|
|
475
gcc/dwarf2out.c
475
gcc/dwarf2out.c
|
@ -2176,6 +2176,7 @@ typedef struct dw_loc_descr_struct
|
|||
enum dwarf_location_atom dw_loc_opc;
|
||||
dw_val_node dw_loc_oprnd1;
|
||||
dw_val_node dw_loc_oprnd2;
|
||||
int dw_loc_addr;
|
||||
}
|
||||
dw_loc_descr_node;
|
||||
|
||||
|
@ -2645,7 +2646,10 @@ size_of_locs (loc)
|
|||
register unsigned long size = 0;
|
||||
|
||||
for (; loc != NULL; loc = loc->dw_loc_next)
|
||||
size += size_of_loc_descr (loc);
|
||||
{
|
||||
loc->dw_loc_addr = size;
|
||||
size += size_of_loc_descr (loc);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -2683,8 +2687,17 @@ output_loc_operands (loc)
|
|||
break;
|
||||
case DW_OP_skip:
|
||||
case DW_OP_bra:
|
||||
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
|
||||
fputc ('\n', asm_out_file);
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (val1->val_class == dw_val_class_loc)
|
||||
offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
|
||||
else
|
||||
abort ();
|
||||
|
||||
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, offset);
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case DW_OP_addr:
|
||||
|
@ -3426,11 +3439,13 @@ static dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref));
|
|||
static int type_is_enum PARAMS ((tree));
|
||||
static unsigned int reg_number PARAMS ((rtx));
|
||||
static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
|
||||
static dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT));
|
||||
static dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long));
|
||||
static int is_based_loc PARAMS ((rtx));
|
||||
static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
|
||||
static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
|
||||
static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
|
||||
static dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int));
|
||||
static HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int));
|
||||
static tree field_type PARAMS ((tree));
|
||||
static unsigned int simple_type_align_in_bits PARAMS ((tree));
|
||||
|
@ -3440,6 +3455,7 @@ static void add_AT_location_description PARAMS ((dw_die_ref,
|
|||
enum dwarf_attribute, rtx));
|
||||
static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
|
||||
static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
|
||||
static rtx rtl_for_decl_location PARAMS ((tree));
|
||||
static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
|
||||
static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree));
|
||||
static void add_name_attribute PARAMS ((dw_die_ref, const char *));
|
||||
|
@ -7173,6 +7189,46 @@ reg_loc_descriptor (rtl)
|
|||
return loc_result;
|
||||
}
|
||||
|
||||
/* Return a location descriptor that designates a constant. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
int_loc_descriptor (i)
|
||||
HOST_WIDE_INT i;
|
||||
{
|
||||
enum dwarf_location_atom op;
|
||||
|
||||
/* Pick the smallest representation of a constant, rather than just
|
||||
defaulting to the LEB encoding. */
|
||||
if (i >= 0)
|
||||
{
|
||||
if (i <= 31)
|
||||
op = DW_OP_lit0 + i;
|
||||
else if (i <= 0xff)
|
||||
op = DW_OP_const1u;
|
||||
else if (i <= 0xffff)
|
||||
op = DW_OP_const2u;
|
||||
else if (HOST_BITS_PER_WIDE_INT == 32
|
||||
|| i <= 0xffffffff)
|
||||
op = DW_OP_const4u;
|
||||
else
|
||||
op = DW_OP_constu;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i >= -0x80)
|
||||
op = DW_OP_const1s;
|
||||
else if (i >= -0x8000)
|
||||
op = DW_OP_const2s;
|
||||
else if (HOST_BITS_PER_WIDE_INT == 32
|
||||
|| i >= -0x80000000)
|
||||
op = DW_OP_const4s;
|
||||
else
|
||||
op = DW_OP_consts;
|
||||
}
|
||||
|
||||
return new_loc_descr (op, i, 0);
|
||||
}
|
||||
|
||||
/* Return a location descriptor that designates a base+offset location. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
|
@ -7274,12 +7330,22 @@ mem_loc_descriptor (rtl, mode)
|
|||
break;
|
||||
|
||||
case MEM:
|
||||
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
|
||||
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
|
||||
{
|
||||
dw_loc_descr_ref deref;
|
||||
|
||||
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
|
||||
|
||||
if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
|
||||
deref = new_loc_descr (DW_OP_deref, 0, 0);
|
||||
else
|
||||
deref = new_loc_descr (DW_OP_deref_size, GET_MODE_SIZE (mode), 0);
|
||||
|
||||
add_loc_descr (&mem_loc_result, deref);
|
||||
}
|
||||
break;
|
||||
|
||||
case LABEL_REF:
|
||||
/* Some ports can transform a symbol ref into a label ref, because
|
||||
case LABEL_REF:
|
||||
/* Some ports can transform a symbol ref into a label ref, because
|
||||
the symbol ref is too far away and has to be dumped into a constant
|
||||
pool. */
|
||||
case CONST:
|
||||
|
@ -7306,24 +7372,37 @@ mem_loc_descriptor (rtl, mode)
|
|||
INTVAL (XEXP (rtl, 1)));
|
||||
else
|
||||
{
|
||||
add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0),
|
||||
mode));
|
||||
add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1),
|
||||
mode));
|
||||
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0));
|
||||
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
|
||||
|
||||
if (GET_CODE (XEXP (rtl, 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (rtl, 1)) >= 0)
|
||||
{
|
||||
add_loc_descr (&mem_loc_result,
|
||||
new_loc_descr (DW_OP_plus_uconst,
|
||||
INTVAL (XEXP (rtl, 1)), 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
add_loc_descr (&mem_loc_result,
|
||||
mem_loc_descriptor (XEXP (rtl, 1), mode));
|
||||
add_loc_descr (&mem_loc_result,
|
||||
new_loc_descr (DW_OP_plus, 0, 0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
/* If a pseudo-reg is optimized away, it is possible for it to
|
||||
be replaced with a MEM containing a multiply. */
|
||||
add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0), mode));
|
||||
add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1), mode));
|
||||
add_loc_descr (&mem_loc_result,
|
||||
mem_loc_descriptor (XEXP (rtl, 0), mode));
|
||||
add_loc_descr (&mem_loc_result,
|
||||
mem_loc_descriptor (XEXP (rtl, 1), mode));
|
||||
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
mem_loc_result = new_loc_descr (DW_OP_constu, INTVAL (rtl), 0);
|
||||
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -7399,6 +7478,260 @@ loc_descriptor (rtl)
|
|||
return loc_result;
|
||||
}
|
||||
|
||||
/* Similar, but generate the descriptor from trees instead of rtl.
|
||||
This comes up particularly with variable length arrays. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
loc_descriptor_from_tree (loc, addressp)
|
||||
tree loc;
|
||||
int addressp;
|
||||
{
|
||||
dw_loc_descr_ref ret = NULL;
|
||||
int indirect_size = 0;
|
||||
int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
|
||||
enum dwarf_location_atom op;
|
||||
|
||||
/* ??? Most of the time we do not take proper care for sign/zero
|
||||
extending the values properly. Hopefully this won't be a real
|
||||
problem... */
|
||||
|
||||
switch (TREE_CODE (loc))
|
||||
{
|
||||
case ERROR_MARK:
|
||||
break;
|
||||
|
||||
case VAR_DECL:
|
||||
case PARM_DECL:
|
||||
{
|
||||
rtx rtl = rtl_for_decl_location (loc);
|
||||
enum machine_mode mode = DECL_MODE (loc);
|
||||
|
||||
if (CONSTANT_P (rtl))
|
||||
{
|
||||
ret = new_loc_descr (DW_OP_addr, 0, 0);
|
||||
ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
||||
ret->dw_loc_oprnd1.v.val_addr = rtl;
|
||||
indirect_size = GET_MODE_SIZE (mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (rtl) == MEM)
|
||||
{
|
||||
indirect_size = GET_MODE_SIZE (mode);
|
||||
rtl = XEXP (rtl, 0);
|
||||
}
|
||||
ret = mem_loc_descriptor (rtl, mode);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case INDIRECT_REF:
|
||||
ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
|
||||
indirect_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (loc)));
|
||||
break;
|
||||
|
||||
case COMPONENT_REF:
|
||||
case BIT_FIELD_REF:
|
||||
case ARRAY_REF:
|
||||
{
|
||||
tree obj, offset;
|
||||
HOST_WIDE_INT bitsize, bitpos, bytepos;
|
||||
enum machine_mode mode;
|
||||
int volatilep;
|
||||
unsigned int alignment;
|
||||
|
||||
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
|
||||
&unsignedp, &volatilep, &alignment);
|
||||
ret = loc_descriptor_from_tree (obj, 1);
|
||||
|
||||
if (offset != NULL_TREE)
|
||||
{
|
||||
/* Variable offset. */
|
||||
add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0));
|
||||
add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
|
||||
}
|
||||
|
||||
if (addressp)
|
||||
{
|
||||
/* We cannot address anything not on a unit boundary. */
|
||||
if (bitpos % BITS_PER_UNIT != 0)
|
||||
abort ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bitpos % BITS_PER_UNIT != 0
|
||||
|| bitsize % BITS_PER_UNIT != 0)
|
||||
{
|
||||
/* ??? We could handle this by loading and shifting etc.
|
||||
Wait until someone needs it before expending the effort. */
|
||||
abort ();
|
||||
}
|
||||
|
||||
indirect_size = bitsize / BITS_PER_UNIT;
|
||||
}
|
||||
|
||||
bytepos = bitpos / BITS_PER_UNIT;
|
||||
if (bytepos > 0)
|
||||
add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
|
||||
else if (bytepos < 0)
|
||||
{
|
||||
add_loc_descr (&ret, int_loc_descriptor (bytepos));
|
||||
add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case INTEGER_CST:
|
||||
if (host_integerp (loc, 0))
|
||||
ret = int_loc_descriptor (tree_low_cst (loc, 0));
|
||||
break;
|
||||
break;
|
||||
|
||||
case BIT_AND_EXPR:
|
||||
op = DW_OP_and;
|
||||
goto do_binop;
|
||||
case BIT_XOR_EXPR:
|
||||
op = DW_OP_xor;
|
||||
goto do_binop;
|
||||
case BIT_IOR_EXPR:
|
||||
op = DW_OP_or;
|
||||
goto do_binop;
|
||||
case TRUNC_DIV_EXPR:
|
||||
op = DW_OP_div;
|
||||
goto do_binop;
|
||||
case MINUS_EXPR:
|
||||
op = DW_OP_minus;
|
||||
goto do_binop;
|
||||
case TRUNC_MOD_EXPR:
|
||||
op = DW_OP_mod;
|
||||
goto do_binop;
|
||||
case MULT_EXPR:
|
||||
op = DW_OP_mul;
|
||||
goto do_binop;
|
||||
case LSHIFT_EXPR:
|
||||
op = DW_OP_shl;
|
||||
goto do_binop;
|
||||
case RSHIFT_EXPR:
|
||||
op = (unsignedp ? DW_OP_shr : DW_OP_shra);
|
||||
goto do_binop;
|
||||
case PLUS_EXPR:
|
||||
if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
|
||||
&& host_integerp (TREE_OPERAND (loc, 1), 0))
|
||||
{
|
||||
ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
|
||||
add_loc_descr (&ret,
|
||||
new_loc_descr (DW_OP_plus_uconst,
|
||||
tree_low_cst (TREE_OPERAND (loc, 1),
|
||||
0),
|
||||
0));
|
||||
break;
|
||||
}
|
||||
op = DW_OP_plus;
|
||||
goto do_binop;
|
||||
case LE_EXPR:
|
||||
if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
||||
break;
|
||||
op = DW_OP_le;
|
||||
goto do_binop;
|
||||
case GE_EXPR:
|
||||
if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
||||
break;
|
||||
op = DW_OP_ge;
|
||||
goto do_binop;
|
||||
case LT_EXPR:
|
||||
if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
||||
break;
|
||||
op = DW_OP_lt;
|
||||
goto do_binop;
|
||||
case GT_EXPR:
|
||||
if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
||||
break;
|
||||
op = DW_OP_gt;
|
||||
goto do_binop;
|
||||
case EQ_EXPR:
|
||||
op = DW_OP_eq;
|
||||
goto do_binop;
|
||||
case NE_EXPR:
|
||||
op = DW_OP_ne;
|
||||
goto do_binop;
|
||||
|
||||
do_binop:
|
||||
ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
|
||||
add_loc_descr (&ret, loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0));
|
||||
add_loc_descr (&ret, new_loc_descr (op, 0, 0));
|
||||
break;
|
||||
|
||||
case BIT_NOT_EXPR:
|
||||
op = DW_OP_not;
|
||||
goto do_unop;
|
||||
case ABS_EXPR:
|
||||
op = DW_OP_abs;
|
||||
goto do_unop;
|
||||
case NEGATE_EXPR:
|
||||
op = DW_OP_neg;
|
||||
goto do_unop;
|
||||
|
||||
do_unop:
|
||||
ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
|
||||
add_loc_descr (&ret, new_loc_descr (op, 0, 0));
|
||||
break;
|
||||
|
||||
case MAX_EXPR:
|
||||
loc = build (COND_EXPR, TREE_TYPE (loc),
|
||||
build (LT_EXPR, integer_type_node,
|
||||
TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
|
||||
TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
|
||||
/* FALLTHRU */
|
||||
|
||||
case COND_EXPR:
|
||||
{
|
||||
dw_loc_descr_ref bra_node, jump_node, tmp;
|
||||
|
||||
ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
|
||||
bra_node = new_loc_descr (DW_OP_bra, 0, 0);
|
||||
add_loc_descr (&ret, bra_node);
|
||||
|
||||
tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
|
||||
add_loc_descr (&ret, tmp);
|
||||
jump_node = new_loc_descr (DW_OP_skip, 0, 0);
|
||||
add_loc_descr (&ret, jump_node);
|
||||
|
||||
tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
|
||||
add_loc_descr (&ret, tmp);
|
||||
bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
|
||||
bra_node->dw_loc_oprnd1.v.val_loc = tmp;
|
||||
|
||||
/* ??? Need a node to point the skip at. Use a nop. */
|
||||
tmp = new_loc_descr (DW_OP_nop, 0, 0);
|
||||
add_loc_descr (&ret, tmp);
|
||||
jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
|
||||
jump_node->dw_loc_oprnd1.v.val_loc = tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* If we can't fill the request for an address, die. */
|
||||
if (addressp && indirect_size == 0)
|
||||
abort ();
|
||||
|
||||
/* If we've got an address and don't want one, dereference. */
|
||||
if (!addressp && indirect_size > 0)
|
||||
{
|
||||
if (indirect_size > DWARF2_ADDR_SIZE)
|
||||
abort ();
|
||||
if (indirect_size == DWARF2_ADDR_SIZE)
|
||||
op = DW_OP_deref;
|
||||
else
|
||||
op = DW_OP_deref_size;
|
||||
add_loc_descr (&ret, new_loc_descr (op, indirect_size, 0));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Given a value, round it up to the lowest multiple of `boundary'
|
||||
which is not less than the value itself. */
|
||||
|
||||
|
@ -7768,31 +8101,11 @@ add_const_value_attribute (die, rtl)
|
|||
|
||||
}
|
||||
|
||||
/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value
|
||||
data attribute for a variable or a parameter. We generate the
|
||||
DW_AT_const_value attribute only in those cases where the given variable
|
||||
or parameter does not have a true "location" either in memory or in a
|
||||
register. This can happen (for example) when a constant is passed as an
|
||||
actual argument in a call to an inline function. (It's possible that
|
||||
these things can crop up in other ways also.) Note that one type of
|
||||
constant value which can be passed into an inlined function is a constant
|
||||
pointer. This can happen for example if an actual argument in an inlined
|
||||
function call evaluates to a compile-time constant address. */
|
||||
|
||||
static void
|
||||
add_location_or_const_value_attribute (die, decl)
|
||||
register dw_die_ref die;
|
||||
register tree decl;
|
||||
static rtx
|
||||
rtl_for_decl_location (decl)
|
||||
tree decl;
|
||||
{
|
||||
register rtx rtl;
|
||||
register tree declared_type;
|
||||
register tree passed_type;
|
||||
|
||||
if (TREE_CODE (decl) == ERROR_MARK)
|
||||
return;
|
||||
|
||||
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
|
||||
abort ();
|
||||
|
||||
/* Here we have to decide where we are going to say the parameter "lives"
|
||||
(as far as the debugger is concerned). We only have a couple of
|
||||
|
@ -7876,8 +8189,8 @@ add_location_or_const_value_attribute (die, decl)
|
|||
{
|
||||
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
|
||||
{
|
||||
declared_type = type_main_variant (TREE_TYPE (decl));
|
||||
passed_type = type_main_variant (DECL_ARG_TYPE (decl));
|
||||
tree declared_type = type_main_variant (TREE_TYPE (decl));
|
||||
tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
|
||||
|
||||
/* This decl represents a formal parameter which was optimized out.
|
||||
Note that DECL_INCOMING_RTL may be NULL in here, but we handle
|
||||
|
@ -7924,14 +8237,43 @@ add_location_or_const_value_attribute (die, decl)
|
|||
}
|
||||
}
|
||||
|
||||
if (rtl == NULL_RTX)
|
||||
if (rtl != NULL_RTX)
|
||||
{
|
||||
rtl = eliminate_regs (rtl, 0, NULL_RTX);
|
||||
#ifdef LEAF_REG_REMAP
|
||||
if (current_function_uses_only_leaf_regs)
|
||||
leaf_renumber_regs_insn (rtl);
|
||||
#endif
|
||||
}
|
||||
|
||||
return rtl;
|
||||
}
|
||||
|
||||
/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value
|
||||
data attribute for a variable or a parameter. We generate the
|
||||
DW_AT_const_value attribute only in those cases where the given variable
|
||||
or parameter does not have a true "location" either in memory or in a
|
||||
register. This can happen (for example) when a constant is passed as an
|
||||
actual argument in a call to an inline function. (It's possible that
|
||||
these things can crop up in other ways also.) Note that one type of
|
||||
constant value which can be passed into an inlined function is a constant
|
||||
pointer. This can happen for example if an actual argument in an inlined
|
||||
function call evaluates to a compile-time constant address. */
|
||||
|
||||
static void
|
||||
add_location_or_const_value_attribute (die, decl)
|
||||
register dw_die_ref die;
|
||||
register tree decl;
|
||||
{
|
||||
register rtx rtl;
|
||||
|
||||
if (TREE_CODE (decl) == ERROR_MARK)
|
||||
return;
|
||||
|
||||
rtl = eliminate_regs (rtl, 0, NULL_RTX);
|
||||
#ifdef LEAF_REG_REMAP
|
||||
if (current_function_uses_only_leaf_regs)
|
||||
leaf_renumber_regs_insn (rtl);
|
||||
#endif
|
||||
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
|
||||
abort ();
|
||||
|
||||
rtl = rtl_for_decl_location (decl);
|
||||
|
||||
switch (GET_CODE (rtl))
|
||||
{
|
||||
|
@ -8102,16 +8444,43 @@ add_bound_info (subrange_die, bound_attr, bound)
|
|||
/* Else leave out the attribute. */
|
||||
break;
|
||||
|
||||
case MAX_EXPR:
|
||||
case VAR_DECL:
|
||||
case COMPONENT_REF:
|
||||
case COND_EXPR:
|
||||
/* ??? These types of bounds can be created by the Ada front end,
|
||||
and it isn't clear how to emit debug info for them. */
|
||||
break;
|
||||
case PARM_DECL:
|
||||
{
|
||||
dw_die_ref decl_die = lookup_decl_die (bound);
|
||||
|
||||
/* ??? Can this happen, or should the variable have been bound
|
||||
first? Probably it can, since I imagine that we try to create
|
||||
the types of parameters in the order in which they exist in
|
||||
the list, and won't have created a forward reference to a
|
||||
later parameter. */
|
||||
if (decl_die != NULL)
|
||||
add_AT_die_ref (subrange_die, bound_attr, decl_die);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
abort ();
|
||||
{
|
||||
/* Otherwise try to create a stack operation procedure to
|
||||
evaluate the value of the array bound. */
|
||||
|
||||
dw_die_ref ctx, decl_die;
|
||||
dw_loc_descr_ref loc;
|
||||
|
||||
loc = loc_descriptor_from_tree (bound, 0);
|
||||
if (loc == NULL)
|
||||
break;
|
||||
|
||||
ctx = lookup_decl_die (current_function_decl);
|
||||
|
||||
decl_die = new_die (DW_TAG_variable, ctx);
|
||||
add_AT_flag (decl_die, DW_AT_artificial, 1);
|
||||
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
|
||||
add_AT_loc (decl_die, DW_AT_location, loc);
|
||||
|
||||
add_AT_die_ref (subrange_die, bound_attr, decl_die);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue