diff options
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r-- | gcc/cfgexpand.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 0ed6bd5903d..f4a9f5e478c 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2234,6 +2234,38 @@ unwrap_constant (rtx x) return ret; } +/* Convert X to MODE, that must be Pmode or ptr_mode, without emitting + any rtl. */ + +static rtx +convert_debug_memory_address (enum machine_mode mode, rtx x) +{ + enum machine_mode xmode = GET_MODE (x); + +#ifndef POINTERS_EXTEND_UNSIGNED + gcc_assert (mode == Pmode); + gcc_assert (xmode == mode || xmode == VOIDmode); +#else + gcc_assert (mode == Pmode || mode == ptr_mode); + + if (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode) + return x; + + if (GET_MODE_BITSIZE (mode) < GET_MODE_BITSIZE (xmode)) + x = simplify_gen_subreg (mode, x, xmode, + subreg_lowpart_offset + (mode, xmode)); + else if (POINTERS_EXTEND_UNSIGNED > 0) + x = gen_rtx_ZERO_EXTEND (mode, x); + else if (!POINTERS_EXTEND_UNSIGNED) + x = gen_rtx_SIGN_EXTEND (mode, x); + else + gcc_unreachable (); +#endif /* POINTERS_EXTEND_UNSIGNED */ + + return x; +} + /* Return an RTX equivalent to the value of the tree expression EXP. */ @@ -2410,6 +2442,7 @@ expand_debug_expr (tree exp) return NULL; gcc_assert (GET_MODE (op0) == Pmode + || GET_MODE (op0) == ptr_mode || GET_CODE (op0) == CONST_INT || GET_CODE (op0) == CONST_DOUBLE); @@ -2436,6 +2469,7 @@ expand_debug_expr (tree exp) return NULL; gcc_assert (GET_MODE (op0) == Pmode + || GET_MODE (op0) == ptr_mode || GET_CODE (op0) == CONST_INT || GET_CODE (op0) == CONST_DOUBLE); @@ -2468,13 +2502,32 @@ expand_debug_expr (tree exp) if (offset) { + enum machine_mode addrmode, offmode; + gcc_assert (MEM_P (op0)); + op0 = XEXP (op0, 0); + addrmode = GET_MODE (op0); + if (addrmode == VOIDmode) + addrmode = Pmode; + op1 = expand_debug_expr (offset); if (!op1) return NULL; - op0 = gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, XEXP (op0, 0), op1)); + offmode = GET_MODE (op1); + if (offmode == VOIDmode) + offmode = TYPE_MODE (TREE_TYPE (offset)); + + if (addrmode != offmode) + op1 = simplify_gen_subreg (addrmode, op1, offmode, + subreg_lowpart_offset (addrmode, + offmode)); + + /* Don't use offset_address here, we don't need a + recognizable address, and we don't want to generate + code. */ + op0 = gen_rtx_MEM (mode, gen_rtx_PLUS (addrmode, op0, op1)); } if (MEM_P (op0)) @@ -2785,7 +2838,9 @@ expand_debug_expr (tree exp) if (!op0 || !MEM_P (op0)) return NULL; - return XEXP (op0, 0); + op0 = convert_debug_memory_address (mode, XEXP (op0, 0)); + + return op0; case VECTOR_CST: exp = build_constructor_from_list (TREE_TYPE (exp), |