[PATCH] Avoid invalid constant pool address dwarf2out optimization
Jakub Jelinek
jakub@redhat.com
Wed Jan 27 14:20:00 GMT 2010
Hi!
As discussed in PR42861, I've discovered that mem_loc_descriptor
CONSTANT_POOL_ADDRESS_P symbol handling is wrong. The problem is
that replacing a symbol_ref/u with a symbol_ref from the constant pool (if
there is any) is incorrect, those two aren't equivalent. What actually
is equivalent is (mem/u (symbol_ref/u)) and the (symbol_ref) that is
contained in the constant pool, without throwing away the MEM we
are one indirection wrong. As a MEM is generally more usable in location
debug info than something else (if we need to dereference, we can
DW_OP_deref any time, but the other way (DW_OP_stack_value) is only
Dwarf4 and only available for toplevel locations, not embedded deeper in the
expression, the patch below just kills that "optimization" altogether
(const_ok_for_output will handle properly marked vs. unmarked constant pool
symbols) and only if for a MEM mem_loc_descriptor fails to describe
its address uses avoid_constant_pool_reference/another mem_loc_descriptor
call to see if it can be expressed as a constant instead.
Bootstrapped/regtested on {i686,x86_64,powerpc,powerpc64,s390,s390x}-linux.
Ok for trunk?
2010-01-27 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (mem_loc_descriptor): Remove special casing of
CONSTANT_POOL_ADDRESS_P SYMBOL_REFs. If for MEM recursive call
on MEM's address failed, try avoid_constant_pool_reference and
recurse if it returned something different.
(loc_descriptor): If for MEM mem_loc_descriptor failed on the
address, try avoid_constant_pool_reference and recurse if it
returned something different.
(dw_loc_list_1): If for MEM mem_loc_descriptor failed on the
address and avoid_constant_pool_reference returned something
different, don't set have_address.
--- gcc/dwarf2out.c.jj 2010-01-20 13:17:57.000000000 +0100
+++ gcc/dwarf2out.c 2010-01-26 15:03:37.000000000 +0100
@@ -11069,6 +11069,12 @@ mem_loc_descriptor (rtx rtl, enum machin
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:
@@ -11082,34 +11088,6 @@ mem_loc_descriptor (rtx rtl, enum machin
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)
{
@@ -11700,6 +11678,12 @@ loc_descriptor (rtx rtl, enum machine_mo
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:
@@ -11971,10 +11955,19 @@ dw_loc_list_1 (tree loc, rtx varloc, int
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;
Jakub
More information about the Gcc-patches
mailing list