diff options
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 96 |
1 files changed, 51 insertions, 45 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 0b25382896f..3c72dc69ffd 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3879,6 +3879,47 @@ add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr) *d = descr; } +/* Add a constant OFFSET to a location expression. */ + +static void +loc_descr_plus_const (dw_loc_descr_ref *list_head, HOST_WIDE_INT offset) +{ + dw_loc_descr_ref loc; + HOST_WIDE_INT *p; + + gcc_assert (*list_head != NULL); + + if (!offset) + return; + + /* Find the end of the chain. */ + for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next) + ; + + p = NULL; + if (loc->dw_loc_opc == DW_OP_fbreg + || (loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31)) + p = &loc->dw_loc_oprnd1.v.val_int; + else if (loc->dw_loc_opc == DW_OP_bregx) + p = &loc->dw_loc_oprnd2.v.val_int; + + /* If the last operation is fbreg, breg{0..31,x}, optimize by adjusting its + offset. Don't optimize if an signed integer overflow would happen. */ + if (p != NULL + && ((offset > 0 && *p <= INTTYPE_MAXIMUM (HOST_WIDE_INT) - offset) + || (offset < 0 && *p >= INTTYPE_MINIMUM (HOST_WIDE_INT) - offset))) + *p += offset; + + else if (offset > 0) + loc->dw_loc_next = new_loc_descr (DW_OP_plus_uconst, offset, 0); + + else + { + loc->dw_loc_next = int_loc_descriptor (offset); + add_loc_descr (&loc->dw_loc_next, new_loc_descr (DW_OP_plus, 0, 0)); + } +} + /* Return the size of a location descriptor. */ static unsigned long @@ -4398,9 +4439,7 @@ build_cfa_aligned_loc (HOST_WIDE_INT offset, HOST_WIDE_INT alignment) head = new_reg_loc_descr (dwarf_fp, 0); add_loc_descr (&head, int_loc_descriptor (alignment)); add_loc_descr (&head, new_loc_descr (DW_OP_and, 0, 0)); - - add_loc_descr (&head, int_loc_descriptor (offset)); - add_loc_descr (&head, new_loc_descr (DW_OP_plus, 0, 0)); + loc_descr_plus_const (&head, offset); } else head = new_reg_loc_descr (dwarf_fp, offset); @@ -9904,7 +9943,7 @@ static dw_loc_descr_ref tls_mem_loc_descriptor (rtx mem) { tree base; - dw_loc_descr_ref loc_result, loc_result2; + dw_loc_descr_ref loc_result; if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX) return NULL; @@ -9920,21 +9959,7 @@ tls_mem_loc_descriptor (rtx mem) return NULL; if (INTVAL (MEM_OFFSET (mem))) - { - if (INTVAL (MEM_OFFSET (mem)) >= 0) - add_loc_descr (&loc_result, - new_loc_descr (DW_OP_plus_uconst, - INTVAL (MEM_OFFSET (mem)), 0)); - else - { - loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem), - VAR_INIT_STATUS_INITIALIZED); - if (loc_result2 == 0) - return NULL; - add_loc_descr (&loc_result, loc_result2); - add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0)); - } - } + loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem))); return loc_result; } @@ -10099,11 +10124,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, if (mem_loc_result == 0) break; - 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)); + if (GET_CODE (XEXP (rtl, 1)) == CONST_INT) + loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1))); else { dw_loc_descr_ref mem_loc_result2 @@ -10517,13 +10539,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address) } 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)); - } + loc_descr_plus_const (&ret, bytepos); have_address = 1; break; @@ -10607,11 +10623,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address) if (ret == 0) return 0; - add_loc_descr (&ret, - new_loc_descr (DW_OP_plus_uconst, - tree_low_cst (TREE_OPERAND (loc, 1), - 0), - 0)); + loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0)); break; } @@ -12994,10 +13006,7 @@ descr_info_loc (tree val, tree base_decl) loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); if (!loc) break; - add_loc_descr (&loc, - new_loc_descr (DW_OP_plus_uconst, - tree_low_cst (TREE_OPERAND (val, 1), - 1), 0)); + loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0)); } else { @@ -13913,9 +13922,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) loc->dw_loc_oprnd1.v.val_addr = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); else - add_loc_descr (&loc, - new_loc_descr (DW_OP_plus_uconst, - off, 0)); + loc_descr_plus_const (&loc, off); } add_AT_loc (var_die, DW_AT_location, loc); remove_AT (var_die, DW_AT_declaration); @@ -13978,8 +13985,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) loc->dw_loc_oprnd1.v.val_addr = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); else - add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, - off, 0)); + loc_descr_plus_const (&loc, off); } add_AT_loc (var_die, DW_AT_location, loc); } |