From eeeb9b49bdae0cd4fe6bf4dc3bd75d401ae5c66d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 1 Jun 2011 18:09:28 +0200 Subject: [PATCH] dwarf2out.c (compare_loc_descriptor, [...]): New functions. * dwarf2out.c (compare_loc_descriptor, scompare_loc_descriptor, ucompare_loc_descriptor, minmax_loc_descriptor, clz_loc_descriptor, popcount_loc_descriptor, bswap_loc_descriptor, rotate_loc_descriptor): New functions. (mem_loc_descriptor): Use them. From-SVN: r174535 --- gcc/ChangeLog | 6 + gcc/dwarf2out.c | 1247 ++++++++++++++++++++++++----------------------- 2 files changed, 651 insertions(+), 602 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef16a1ce5d8..9b969a76bf5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2011-06-01 Jakub Jelinek + * dwarf2out.c (compare_loc_descriptor, scompare_loc_descriptor, + ucompare_loc_descriptor, minmax_loc_descriptor, clz_loc_descriptor, + popcount_loc_descriptor, bswap_loc_descriptor, rotate_loc_descriptor): + New functions. + (mem_loc_descriptor): Use them. + * var-tracking.c (create_entry_value): New function. (vt_add_function_parameter): Use it. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 14eec3a084b..b3cf4a65730 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -13855,6 +13855,627 @@ convert_descriptor_to_signed (enum machine_mode mode, dw_loc_descr_ref op) return op; } +/* Return location descriptor for comparison OP with operands OP0 and OP1. */ + +static dw_loc_descr_ref +compare_loc_descriptor (enum dwarf_location_atom op, dw_loc_descr_ref op0, + dw_loc_descr_ref op1) +{ + dw_loc_descr_ref ret = op0; + add_loc_descr (&ret, op1); + add_loc_descr (&ret, new_loc_descr (op, 0, 0)); + if (STORE_FLAG_VALUE != 1) + { + add_loc_descr (&ret, int_loc_descriptor (STORE_FLAG_VALUE)); + add_loc_descr (&ret, new_loc_descr (DW_OP_mul, 0, 0)); + } + return ret; +} + +/* Return location descriptor for signed comparison OP RTL. */ + +static dw_loc_descr_ref +scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl, + enum machine_mode mem_mode) +{ + enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0)); + dw_loc_descr_ref op0, op1; + int shift; + + if (op_mode == VOIDmode) + op_mode = GET_MODE (XEXP (rtl, 1)); + if (op_mode == VOIDmode) + return NULL; + + if (dwarf_strict + && (GET_MODE_CLASS (op_mode) != MODE_INT + || GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)) + return NULL; + + op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + + if (op0 == NULL || op1 == NULL) + return NULL; + + if (GET_MODE_CLASS (op_mode) != MODE_INT + || GET_MODE_SIZE (op_mode) >= DWARF2_ADDR_SIZE) + return compare_loc_descriptor (op, op0, op1); + + shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (op_mode)) * BITS_PER_UNIT; + /* For eq/ne, if the operands are known to be zero-extended, + there is no need to do the fancy shifting up. */ + if (op == DW_OP_eq || op == DW_OP_ne) + { + dw_loc_descr_ref last0, last1; + for (last0 = op0; last0->dw_loc_next != NULL; last0 = last0->dw_loc_next) + ; + for (last1 = op1; last1->dw_loc_next != NULL; last1 = last1->dw_loc_next) + ; + /* deref_size zero extends, and for constants we can check + whether they are zero extended or not. */ + if (((last0->dw_loc_opc == DW_OP_deref_size + && last0->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (op_mode)) + || (CONST_INT_P (XEXP (rtl, 0)) + && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 0)) + == (INTVAL (XEXP (rtl, 0)) & GET_MODE_MASK (op_mode)))) + && ((last1->dw_loc_opc == DW_OP_deref_size + && last1->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (op_mode)) + || (CONST_INT_P (XEXP (rtl, 1)) + && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 1)) + == (INTVAL (XEXP (rtl, 1)) & GET_MODE_MASK (op_mode))))) + return compare_loc_descriptor (op, op0, op1); + } + add_loc_descr (&op0, int_loc_descriptor (shift)); + add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0)); + if (CONST_INT_P (XEXP (rtl, 1))) + op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift); + else + { + add_loc_descr (&op1, int_loc_descriptor (shift)); + add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0)); + } + return compare_loc_descriptor (op, op0, op1); +} + +/* Return location descriptor for unsigned comparison OP RTL. */ + +static dw_loc_descr_ref +ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl, + enum machine_mode mem_mode) +{ + enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0)); + dw_loc_descr_ref op0, op1; + + if (op_mode == VOIDmode) + op_mode = GET_MODE (XEXP (rtl, 1)); + if (op_mode == VOIDmode) + return NULL; + if (GET_MODE_CLASS (op_mode) != MODE_INT) + return NULL; + + if (dwarf_strict && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE) + return NULL; + + if (op_mode != VOIDmode && GET_MODE_CLASS (op_mode) != MODE_INT) + return NULL; + + op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + + if (op0 == NULL || op1 == NULL) + return NULL; + + if (GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE) + { + HOST_WIDE_INT mask = GET_MODE_MASK (op_mode); + dw_loc_descr_ref last0, last1; + for (last0 = op0; last0->dw_loc_next != NULL; last0 = last0->dw_loc_next) + ; + for (last1 = op1; last1->dw_loc_next != NULL; last1 = last1->dw_loc_next) + ; + if (CONST_INT_P (XEXP (rtl, 0))) + op0 = int_loc_descriptor (INTVAL (XEXP (rtl, 0)) & mask); + /* deref_size zero extends, so no need to mask it again. */ + else if (last0->dw_loc_opc != DW_OP_deref_size + || last0->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (op_mode)) + { + add_loc_descr (&op0, int_loc_descriptor (mask)); + add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); + } + if (CONST_INT_P (XEXP (rtl, 1))) + op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) & mask); + /* deref_size zero extends, so no need to mask it again. */ + else if (last1->dw_loc_opc != DW_OP_deref_size + || last1->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (op_mode)) + { + add_loc_descr (&op1, int_loc_descriptor (mask)); + add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0)); + } + } + else if (GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE) + { + HOST_WIDE_INT bias = 1; + bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1); + add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0)); + if (CONST_INT_P (XEXP (rtl, 1))) + op1 = int_loc_descriptor ((unsigned HOST_WIDE_INT) bias + + INTVAL (XEXP (rtl, 1))); + else + add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, + bias, 0)); + } + else + { + dw_die_ref type_die = base_type_for_mode (op_mode, 1); + dw_loc_descr_ref cvt; + + if (type_die == NULL) + return NULL; + cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); + cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; + cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr (&op0, cvt); + cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); + cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; + cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr (&op1, cvt); + } + return compare_loc_descriptor (op, op0, op1); +} + +/* Return location descriptor for {U,S}{MIN,MAX}. */ + +static dw_loc_descr_ref +minmax_loc_descriptor (rtx rtl, enum machine_mode mode, + enum machine_mode mem_mode) +{ + enum dwarf_location_atom op; + dw_loc_descr_ref op0, op1, ret; + dw_loc_descr_ref bra_node, drop_node; + + if (dwarf_strict + && (GET_MODE_CLASS (mode) != MODE_INT + || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)) + return NULL; + + op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + + if (op0 == NULL || op1 == NULL) + return NULL; + + add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0)); + add_loc_descr (&op1, new_loc_descr (DW_OP_swap, 0, 0)); + add_loc_descr (&op1, new_loc_descr (DW_OP_over, 0, 0)); + if (GET_CODE (rtl) == UMIN || GET_CODE (rtl) == UMAX) + { + if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE) + { + HOST_WIDE_INT mask = GET_MODE_MASK (mode); + add_loc_descr (&op0, int_loc_descriptor (mask)); + add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); + add_loc_descr (&op1, int_loc_descriptor (mask)); + add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0)); + } + else if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE) + { + HOST_WIDE_INT bias = 1; + bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1); + add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0)); + add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0)); + } + else + { + dw_die_ref type_die = base_type_for_mode (mode, 1); + dw_loc_descr_ref cvt; + if (type_die == NULL) + return NULL; + cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); + cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; + cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr (&op0, cvt); + cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); + cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; + cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr (&op1, cvt); + } + } + else if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE) + { + int shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (mode)) * BITS_PER_UNIT; + add_loc_descr (&op0, int_loc_descriptor (shift)); + add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0)); + add_loc_descr (&op1, int_loc_descriptor (shift)); + add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0)); + } + + if (GET_CODE (rtl) == SMIN || GET_CODE (rtl) == UMIN) + op = DW_OP_lt; + else + op = DW_OP_gt; + ret = op0; + add_loc_descr (&ret, op1); + add_loc_descr (&ret, new_loc_descr (op, 0, 0)); + bra_node = new_loc_descr (DW_OP_bra, 0, 0); + add_loc_descr (&ret, bra_node); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + drop_node = new_loc_descr (DW_OP_drop, 0, 0); + add_loc_descr (&ret, drop_node); + bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc; + bra_node->dw_loc_oprnd1.v.val_loc = drop_node; + return ret; +} + +/* CLZ (where constV is CLZ_DEFINED_VALUE_AT_ZERO computed value, + const0 is DW_OP_lit0 or corresponding typed constant, + const1 is DW_OP_lit1 or corresponding typed constant + and constMSB is constant with just the MSB bit set + for the mode): + DW_OP_dup DW_OP_bra DW_OP_drop constV DW_OP_skip + L1: const0 DW_OP_swap + L2: DW_OP_dup constMSB DW_OP_and DW_OP_bra const1 DW_OP_shl + DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip + L3: DW_OP_drop + L4: DW_OP_nop + + CTZ is similar: + DW_OP_dup DW_OP_bra DW_OP_drop constV DW_OP_skip + L1: const0 DW_OP_swap + L2: DW_OP_dup const1 DW_OP_and DW_OP_bra const1 DW_OP_shr + DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip + L3: DW_OP_drop + L4: DW_OP_nop + + FFS is similar: + DW_OP_dup DW_OP_bra DW_OP_drop const0 DW_OP_skip + L1: const1 DW_OP_swap + L2: DW_OP_dup const1 DW_OP_and DW_OP_bra const1 DW_OP_shr + DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip + L3: DW_OP_drop + L4: DW_OP_nop */ + +static dw_loc_descr_ref +clz_loc_descriptor (rtx rtl, enum machine_mode mode, + enum machine_mode mem_mode) +{ + dw_loc_descr_ref op0, ret, tmp; + HOST_WIDE_INT valv; + dw_loc_descr_ref l1jump, l1label; + dw_loc_descr_ref l2jump, l2label; + dw_loc_descr_ref l3jump, l3label; + dw_loc_descr_ref l4jump, l4label; + rtx msb; + + if (GET_MODE_CLASS (mode) != MODE_INT + || GET_MODE (XEXP (rtl, 0)) != mode + || (GET_CODE (rtl) == CLZ + && GET_MODE_BITSIZE (mode) > 2 * HOST_BITS_PER_WIDE_INT)) + return NULL; + + op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (op0 == NULL) + return NULL; + ret = op0; + if (GET_CODE (rtl) == CLZ) + { + if (!CLZ_DEFINED_VALUE_AT_ZERO (mode, valv)) + valv = GET_MODE_BITSIZE (mode); + } + else if (GET_CODE (rtl) == FFS) + valv = 0; + else if (!CTZ_DEFINED_VALUE_AT_ZERO (mode, valv)) + valv = GET_MODE_BITSIZE (mode); + add_loc_descr (&ret, new_loc_descr (DW_OP_dup, 0, 0)); + l1jump = new_loc_descr (DW_OP_bra, 0, 0); + add_loc_descr (&ret, l1jump); + add_loc_descr (&ret, new_loc_descr (DW_OP_drop, 0, 0)); + tmp = mem_loc_descriptor (GEN_INT (valv), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + l4jump = new_loc_descr (DW_OP_skip, 0, 0); + add_loc_descr (&ret, l4jump); + l1label = mem_loc_descriptor (GET_CODE (rtl) == FFS + ? const1_rtx : const0_rtx, + mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (l1label == NULL) + return NULL; + add_loc_descr (&ret, l1label); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + l2label = new_loc_descr (DW_OP_dup, 0, 0); + add_loc_descr (&ret, l2label); + if (GET_CODE (rtl) != CLZ) + msb = const1_rtx; + else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + msb = GEN_INT ((unsigned HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (mode) - 1)); + else + msb = immed_double_const (0, (unsigned HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (mode) + - HOST_BITS_PER_WIDE_INT - 1), mode); + if (GET_CODE (msb) == CONST_INT && INTVAL (msb) < 0) + tmp = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32 + ? DW_OP_const4u : HOST_BITS_PER_WIDE_INT == 64 + ? DW_OP_const8u : DW_OP_constu, INTVAL (msb), 0); + else + tmp = mem_loc_descriptor (msb, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_and, 0, 0)); + l3jump = new_loc_descr (DW_OP_bra, 0, 0); + add_loc_descr (&ret, l3jump); + tmp = mem_loc_descriptor (const1_rtx, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (GET_CODE (rtl) == CLZ + ? DW_OP_shl : DW_OP_shr, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, 1, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + l2jump = new_loc_descr (DW_OP_skip, 0, 0); + add_loc_descr (&ret, l2jump); + l3label = new_loc_descr (DW_OP_drop, 0, 0); + add_loc_descr (&ret, l3label); + l4label = new_loc_descr (DW_OP_nop, 0, 0); + add_loc_descr (&ret, l4label); + l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l1jump->dw_loc_oprnd1.v.val_loc = l1label; + l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l2jump->dw_loc_oprnd1.v.val_loc = l2label; + l3jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l3jump->dw_loc_oprnd1.v.val_loc = l3label; + l4jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l4jump->dw_loc_oprnd1.v.val_loc = l4label; + return ret; +} + +/* POPCOUNT (const0 is DW_OP_lit0 or corresponding typed constant, + const1 is DW_OP_lit1 or corresponding typed constant): + const0 DW_OP_swap + L1: DW_OP_dup DW_OP_bra DW_OP_dup DW_OP_rot const1 DW_OP_and + DW_OP_plus DW_OP_swap const1 DW_OP_shr DW_OP_skip + L2: DW_OP_drop + + PARITY is similar: + L1: DW_OP_dup DW_OP_bra DW_OP_dup DW_OP_rot const1 DW_OP_and + DW_OP_xor DW_OP_swap const1 DW_OP_shr DW_OP_skip + L2: DW_OP_drop */ + +static dw_loc_descr_ref +popcount_loc_descriptor (rtx rtl, enum machine_mode mode, + enum machine_mode mem_mode) +{ + dw_loc_descr_ref op0, ret, tmp; + dw_loc_descr_ref l1jump, l1label; + dw_loc_descr_ref l2jump, l2label; + + if (GET_MODE_CLASS (mode) != MODE_INT + || GET_MODE (XEXP (rtl, 0)) != mode) + return NULL; + + op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (op0 == NULL) + return NULL; + ret = op0; + tmp = mem_loc_descriptor (const0_rtx, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + l1label = new_loc_descr (DW_OP_dup, 0, 0); + add_loc_descr (&ret, l1label); + l2jump = new_loc_descr (DW_OP_bra, 0, 0); + add_loc_descr (&ret, l2jump); + add_loc_descr (&ret, new_loc_descr (DW_OP_dup, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_rot, 0, 0)); + tmp = mem_loc_descriptor (const1_rtx, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_and, 0, 0)); + add_loc_descr (&ret, new_loc_descr (GET_CODE (rtl) == POPCOUNT + ? DW_OP_plus : DW_OP_xor, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + tmp = mem_loc_descriptor (const1_rtx, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0)); + l1jump = new_loc_descr (DW_OP_skip, 0, 0); + add_loc_descr (&ret, l1jump); + l2label = new_loc_descr (DW_OP_drop, 0, 0); + add_loc_descr (&ret, l2label); + l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l1jump->dw_loc_oprnd1.v.val_loc = l1label; + l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l2jump->dw_loc_oprnd1.v.val_loc = l2label; + return ret; +} + +/* BSWAP (constS is initial shift count, either 56 or 24): + constS const0 + L1: DW_OP_pick <2> constS DW_OP_pick <3> DW_OP_minus DW_OP_shr + const255 DW_OP_and DW_OP_pick <2> DW_OP_shl DW_OP_or + DW_OP_swap DW_OP_dup const0 DW_OP_eq DW_OP_bra const8 + DW_OP_minus DW_OP_swap DW_OP_skip + L2: DW_OP_drop DW_OP_swap DW_OP_drop */ + +static dw_loc_descr_ref +bswap_loc_descriptor (rtx rtl, enum machine_mode mode, + enum machine_mode mem_mode) +{ + dw_loc_descr_ref op0, ret, tmp; + dw_loc_descr_ref l1jump, l1label; + dw_loc_descr_ref l2jump, l2label; + + if (GET_MODE_CLASS (mode) != MODE_INT + || BITS_PER_UNIT != 8 + || (GET_MODE_BITSIZE (mode) != 32 + && GET_MODE_BITSIZE (mode) != 64)) + return NULL; + + op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (op0 == NULL) + return NULL; + + ret = op0; + tmp = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8), + mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + tmp = mem_loc_descriptor (const0_rtx, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + l1label = new_loc_descr (DW_OP_pick, 2, 0); + add_loc_descr (&ret, l1label); + tmp = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8), + mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_pick, 3, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_minus, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0)); + tmp = mem_loc_descriptor (GEN_INT (255), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (tmp == NULL) + return NULL; + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_and, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_pick, 2, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_shl, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_or, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_dup, 0, 0)); + tmp = mem_loc_descriptor (const0_rtx, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_eq, 0, 0)); + l2jump = new_loc_descr (DW_OP_bra, 0, 0); + add_loc_descr (&ret, l2jump); + tmp = mem_loc_descriptor (GEN_INT (8), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + add_loc_descr (&ret, tmp); + add_loc_descr (&ret, new_loc_descr (DW_OP_minus, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + l1jump = new_loc_descr (DW_OP_skip, 0, 0); + add_loc_descr (&ret, l1jump); + l2label = new_loc_descr (DW_OP_drop, 0, 0); + add_loc_descr (&ret, l2label); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_drop, 0, 0)); + l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l1jump->dw_loc_oprnd1.v.val_loc = l1label; + l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc; + l2jump->dw_loc_oprnd1.v.val_loc = l2label; + return ret; +} + +/* ROTATE (constMASK is mode mask, BITSIZE is bitsize of mode): + DW_OP_over DW_OP_over DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot + [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_neg + DW_OP_plus_uconst DW_OP_shr DW_OP_or + + ROTATERT is similar: + DW_OP_over DW_OP_over DW_OP_neg DW_OP_plus_uconst + DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot + [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_shr DW_OP_or */ + +static dw_loc_descr_ref +rotate_loc_descriptor (rtx rtl, enum machine_mode mode, + enum machine_mode mem_mode) +{ + rtx rtlop1 = XEXP (rtl, 1); + dw_loc_descr_ref op0, op1, ret, mask[2] = { NULL, NULL }; + int i; + + if (GET_MODE_CLASS (mode) != MODE_INT) + return NULL; + + if (GET_MODE (rtlop1) != VOIDmode + && GET_MODE_BITSIZE (GET_MODE (rtlop1)) < GET_MODE_BITSIZE (mode)) + rtlop1 = gen_rtx_ZERO_EXTEND (mode, rtlop1); + op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + op1 = mem_loc_descriptor (rtlop1, mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + if (op0 == NULL || op1 == NULL) + return NULL; + if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE) + for (i = 0; i < 2; i++) + { + if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT) + mask[i] = mem_loc_descriptor (GEN_INT (GET_MODE_MASK (mode)), + mode, mem_mode, + VAR_INIT_STATUS_INITIALIZED); + else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT) + mask[i] = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32 + ? DW_OP_const4u + : HOST_BITS_PER_WIDE_INT == 64 + ? DW_OP_const8u : DW_OP_constu, + GET_MODE_MASK (mode), 0); + else + mask[i] = NULL; + if (mask[i] == NULL) + return NULL; + add_loc_descr (&mask[i], new_loc_descr (DW_OP_and, 0, 0)); + } + ret = op0; + add_loc_descr (&ret, op1); + add_loc_descr (&ret, new_loc_descr (DW_OP_over, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_over, 0, 0)); + if (GET_CODE (rtl) == ROTATERT) + { + add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, + GET_MODE_BITSIZE (mode), 0)); + } + add_loc_descr (&ret, new_loc_descr (DW_OP_shl, 0, 0)); + if (mask[0] != NULL) + add_loc_descr (&ret, mask[0]); + add_loc_descr (&ret, new_loc_descr (DW_OP_rot, 0, 0)); + if (mask[1] != NULL) + { + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + add_loc_descr (&ret, mask[1]); + add_loc_descr (&ret, new_loc_descr (DW_OP_swap, 0, 0)); + } + if (GET_CODE (rtl) == ROTATE) + { + add_loc_descr (&ret, new_loc_descr (DW_OP_neg, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, + GET_MODE_BITSIZE (mode), 0)); + } + add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0)); + add_loc_descr (&ret, new_loc_descr (DW_OP_or, 0, 0)); + return ret; +} + /* The following routine converts the RTL for a variable or parameter (resident in memory) into an equivalent Dwarf representation of a mechanism for getting the address of that same variable onto the top of a @@ -14491,218 +15112,44 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, break; case EQ: - op = DW_OP_eq; - goto do_scompare; + mem_loc_result = scompare_loc_descriptor (DW_OP_eq, rtl, mem_mode); + break; case GE: - op = DW_OP_ge; - goto do_scompare; + mem_loc_result = scompare_loc_descriptor (DW_OP_ge, rtl, mem_mode); + break; case GT: - op = DW_OP_gt; - goto do_scompare; + mem_loc_result = scompare_loc_descriptor (DW_OP_gt, rtl, mem_mode); + break; case LE: - op = DW_OP_le; - goto do_scompare; + mem_loc_result = scompare_loc_descriptor (DW_OP_le, rtl, mem_mode); + break; case LT: - op = DW_OP_lt; - goto do_scompare; + mem_loc_result = scompare_loc_descriptor (DW_OP_lt, rtl, mem_mode); + break; case NE: - op = DW_OP_ne; - goto do_scompare; - - do_scompare: - { - enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0)); - - if (op_mode == VOIDmode) - op_mode = GET_MODE (XEXP (rtl, 1)); - if (op_mode == VOIDmode) - break; - - if (dwarf_strict - && (GET_MODE_CLASS (op_mode) != MODE_INT - || GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)) - break; - - op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - - if (op0 == 0 || op1 == 0) - break; - - if (GET_MODE_CLASS (op_mode) == MODE_INT - && GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE) - { - int shift = DWARF2_ADDR_SIZE - GET_MODE_SIZE (op_mode); - shift *= BITS_PER_UNIT; - /* For eq/ne, if the operands are known to be zero-extended, - there is no need to do the fancy shifting up. */ - if (op == DW_OP_eq || op == DW_OP_ne) - { - dw_loc_descr_ref last0, last1; - for (last0 = op0; - last0->dw_loc_next != NULL; - last0 = last0->dw_loc_next) - ; - for (last1 = op1; - last1->dw_loc_next != NULL; - last1 = last1->dw_loc_next) - ; - /* deref_size zero extends, and for constants we can check - whether they are zero extended or not. */ - if (((last0->dw_loc_opc == DW_OP_deref_size - && last0->dw_loc_oprnd1.v.val_int - <= GET_MODE_SIZE (op_mode)) - || (CONST_INT_P (XEXP (rtl, 0)) - && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 0)) - == (INTVAL (XEXP (rtl, 0)) - & GET_MODE_MASK (op_mode)))) - && ((last1->dw_loc_opc == DW_OP_deref_size - && last1->dw_loc_oprnd1.v.val_int - <= GET_MODE_SIZE (op_mode)) - || (CONST_INT_P (XEXP (rtl, 1)) - && (unsigned HOST_WIDE_INT) - INTVAL (XEXP (rtl, 1)) - == (INTVAL (XEXP (rtl, 1)) - & GET_MODE_MASK (op_mode))))) - goto do_compare; - } - add_loc_descr (&op0, int_loc_descriptor (shift)); - add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0)); - if (CONST_INT_P (XEXP (rtl, 1))) - op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift); - else - { - add_loc_descr (&op1, int_loc_descriptor (shift)); - add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0)); - } - } - } - - do_compare: - mem_loc_result = op0; - add_loc_descr (&mem_loc_result, op1); - add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0)); - if (STORE_FLAG_VALUE != 1) - { - add_loc_descr (&mem_loc_result, - int_loc_descriptor (STORE_FLAG_VALUE)); - add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0)); - } + mem_loc_result = scompare_loc_descriptor (DW_OP_ne, rtl, mem_mode); break; case GEU: - op = DW_OP_ge; - goto do_ucompare; + mem_loc_result = ucompare_loc_descriptor (DW_OP_ge, rtl, mem_mode); + break; case GTU: - op = DW_OP_gt; - goto do_ucompare; + mem_loc_result = ucompare_loc_descriptor (DW_OP_gt, rtl, mem_mode); + break; case LEU: - op = DW_OP_le; - goto do_ucompare; + mem_loc_result = ucompare_loc_descriptor (DW_OP_le, rtl, mem_mode); + break; case LTU: - op = DW_OP_lt; - goto do_ucompare; - - do_ucompare: - { - enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0)); - - if (op_mode == VOIDmode) - op_mode = GET_MODE (XEXP (rtl, 1)); - if (op_mode == VOIDmode) - break; - if (GET_MODE_CLASS (op_mode) != MODE_INT) - break; - - if (dwarf_strict && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE) - break; - - if (op_mode != VOIDmode && GET_MODE_CLASS (op_mode) != MODE_INT) - break; - - op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - - if (op0 == 0 || op1 == 0) - break; - - if (GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE) - { - HOST_WIDE_INT mask = GET_MODE_MASK (op_mode); - dw_loc_descr_ref last0, last1; - for (last0 = op0; - last0->dw_loc_next != NULL; - last0 = last0->dw_loc_next) - ; - for (last1 = op1; - last1->dw_loc_next != NULL; - last1 = last1->dw_loc_next) - ; - if (CONST_INT_P (XEXP (rtl, 0))) - op0 = int_loc_descriptor (INTVAL (XEXP (rtl, 0)) & mask); - /* deref_size zero extends, so no need to mask it again. */ - else if (last0->dw_loc_opc != DW_OP_deref_size - || last0->dw_loc_oprnd1.v.val_int - > GET_MODE_SIZE (op_mode)) - { - add_loc_descr (&op0, int_loc_descriptor (mask)); - add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); - } - if (CONST_INT_P (XEXP (rtl, 1))) - op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) & mask); - /* deref_size zero extends, so no need to mask it again. */ - else if (last1->dw_loc_opc != DW_OP_deref_size - || last1->dw_loc_oprnd1.v.val_int - > GET_MODE_SIZE (op_mode)) - { - add_loc_descr (&op1, int_loc_descriptor (mask)); - add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0)); - } - } - else if (GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE) - { - HOST_WIDE_INT bias = 1; - bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1); - add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0)); - if (CONST_INT_P (XEXP (rtl, 1))) - op1 = int_loc_descriptor ((unsigned HOST_WIDE_INT) bias - + INTVAL (XEXP (rtl, 1))); - else - add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, - bias, 0)); - } - else - { - dw_die_ref type_die = base_type_for_mode (op_mode, 1); - dw_loc_descr_ref cvt; - - if (type_die == NULL) - break; - cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); - cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; - cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; - add_loc_descr (&op0, cvt); - cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); - cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; - cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; - add_loc_descr (&op1, cvt); - } - } - goto do_compare; + mem_loc_result = ucompare_loc_descriptor (DW_OP_lt, rtl, mem_mode); + break; case UMIN: case UMAX: @@ -14711,87 +15158,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, /* FALLTHRU */ case SMIN: case SMAX: - if (dwarf_strict - && (GET_MODE_CLASS (mode) != MODE_INT - || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)) - break; - - op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - - if (op0 == 0 || op1 == 0) - break; - - add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0)); - add_loc_descr (&op1, new_loc_descr (DW_OP_swap, 0, 0)); - add_loc_descr (&op1, new_loc_descr (DW_OP_over, 0, 0)); - if (GET_CODE (rtl) == UMIN || GET_CODE (rtl) == UMAX) - { - if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE) - { - HOST_WIDE_INT mask = GET_MODE_MASK (mode); - add_loc_descr (&op0, int_loc_descriptor (mask)); - add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); - add_loc_descr (&op1, int_loc_descriptor (mask)); - add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0)); - } - else if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE) - { - HOST_WIDE_INT bias = 1; - bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1); - add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0)); - add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0)); - } - else - { - dw_die_ref type_die = base_type_for_mode (mode, 1); - dw_loc_descr_ref cvt; - - if (type_die == NULL) - break; - cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); - cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; - cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; - add_loc_descr (&op0, cvt); - cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0); - cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; - cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; - add_loc_descr (&op1, cvt); - } - } - else if (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE) - { - int shift = DWARF2_ADDR_SIZE - GET_MODE_SIZE (mode); - shift *= BITS_PER_UNIT; - add_loc_descr (&op0, int_loc_descriptor (shift)); - add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0)); - add_loc_descr (&op1, int_loc_descriptor (shift)); - add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0)); - } - - if (GET_CODE (rtl) == SMIN || GET_CODE (rtl) == UMIN) - op = DW_OP_lt; - else - op = DW_OP_gt; - mem_loc_result = op0; - add_loc_descr (&mem_loc_result, op1); - add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0)); - { - dw_loc_descr_ref bra_node, drop_node; - - bra_node = new_loc_descr (DW_OP_bra, 0, 0); - add_loc_descr (&mem_loc_result, bra_node); - add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_swap, 0, 0)); - drop_node = new_loc_descr (DW_OP_drop, 0, 0); - add_loc_descr (&mem_loc_result, drop_node); - bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc; - bra_node->dw_loc_oprnd1.v.val_loc = drop_node; - } + mem_loc_result = minmax_loc_descriptor (rtl, mode, mem_mode); break; case ZERO_EXTRACT: @@ -14916,345 +15283,21 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, case CLZ: case CTZ: case FFS: - /* CLZ (where constV is CLZ_DEFINED_VALUE_AT_ZERO computed value, - const0 is DW_OP_lit0 or corresponding typed constant, - const1 is DW_OP_lit1 or corresponding typed constant - and constMSB is constant with just the MSB bit set - for the mode): - DW_OP_dup DW_OP_bra DW_OP_drop constV DW_OP_skip - L1: const0 DW_OP_swap - L2: DW_OP_dup constMSB DW_OP_and DW_OP_bra const1 DW_OP_shl - DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip - L3: DW_OP_drop - L4: DW_OP_nop - - CTZ is similar: - DW_OP_dup DW_OP_bra DW_OP_drop constV DW_OP_skip - L1: const0 DW_OP_swap - L2: DW_OP_dup const1 DW_OP_and DW_OP_bra const1 DW_OP_shr - DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip - L3: DW_OP_drop - L4: DW_OP_nop - - FFS is similar: - DW_OP_dup DW_OP_bra DW_OP_drop const0 DW_OP_skip - L1: const1 DW_OP_swap - L2: DW_OP_dup const1 DW_OP_and DW_OP_bra const1 DW_OP_shr - DW_OP_swap DW_OP_plus_uconst <1> DW_OP_swap DW_OP_skip - L3: DW_OP_drop - L4: DW_OP_nop */ - if (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE (XEXP (rtl, 0)) == mode - && (GET_CODE (rtl) != CLZ - || GET_MODE_BITSIZE (mode) <= 2 * HOST_BITS_PER_WIDE_INT)) - { - HOST_WIDE_INT valv; - dw_loc_descr_ref l1jump, l1label; - dw_loc_descr_ref l2jump, l2label; - dw_loc_descr_ref l3jump, l3label; - dw_loc_descr_ref l4jump, l4label; - rtx msb; - - op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op0 == NULL) - break; - if (GET_CODE (rtl) == CLZ) - { - if (!CLZ_DEFINED_VALUE_AT_ZERO (mode, valv)) - valv = GET_MODE_BITSIZE (mode); - } - else if (GET_CODE (rtl) == FFS) - valv = 0; - else if (!CTZ_DEFINED_VALUE_AT_ZERO (mode, valv)) - valv = GET_MODE_BITSIZE (mode); - add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0)); - l1jump = new_loc_descr (DW_OP_bra, 0, 0); - add_loc_descr (&op0, l1jump); - add_loc_descr (&op0, new_loc_descr (DW_OP_drop, 0, 0)); - op1 = mem_loc_descriptor (GEN_INT (valv), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - l4jump = new_loc_descr (DW_OP_skip, 0, 0); - add_loc_descr (&op0, l4jump); - l1label = mem_loc_descriptor (GET_CODE (rtl) == FFS - ? const1_rtx : const0_rtx, - mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (l1label == NULL) - break; - add_loc_descr (&op0, l1label); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - l2label = new_loc_descr (DW_OP_dup, 0, 0); - add_loc_descr (&op0, l2label); - if (GET_CODE (rtl) != CLZ) - msb = const1_rtx; - else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) - msb = GEN_INT ((unsigned HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (mode) - 1)); - else - msb = immed_double_const (0, (unsigned HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (mode) - - HOST_BITS_PER_WIDE_INT - 1), - mode); - if (GET_CODE (msb) == CONST_INT && INTVAL (msb) < 0) - op1 = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32 - ? DW_OP_const4u - : HOST_BITS_PER_WIDE_INT == 64 - ? DW_OP_const8u : DW_OP_constu, - INTVAL (msb), 0); - else - op1 = mem_loc_descriptor (msb, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); - l3jump = new_loc_descr (DW_OP_bra, 0, 0); - add_loc_descr (&op0, l3jump); - op1 = mem_loc_descriptor (const1_rtx, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (GET_CODE (rtl) == CLZ - ? DW_OP_shl : DW_OP_shr, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, 1, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - l2jump = new_loc_descr (DW_OP_skip, 0, 0); - add_loc_descr (&op0, l2jump); - l3label = new_loc_descr (DW_OP_drop, 0, 0); - add_loc_descr (&op0, l3label); - l4label = new_loc_descr (DW_OP_nop, 0, 0); - add_loc_descr (&op0, l4label); - l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l1jump->dw_loc_oprnd1.v.val_loc = l1label; - l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l2jump->dw_loc_oprnd1.v.val_loc = l2label; - l3jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l3jump->dw_loc_oprnd1.v.val_loc = l3label; - l4jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l4jump->dw_loc_oprnd1.v.val_loc = l4label; - mem_loc_result = op0; - } + mem_loc_result = clz_loc_descriptor (rtl, mode, mem_mode); break; case POPCOUNT: case PARITY: - /* POPCOUNT (const0 is DW_OP_lit0 or corresponding typed constant, - const1 is DW_OP_lit1 or corresponding typed constant): - const0 DW_OP_swap - L1: DW_OP_dup DW_OP_bra DW_OP_dup DW_OP_rot const1 DW_OP_and - DW_OP_plus DW_OP_swap const1 DW_OP_shr DW_OP_skip - L2: DW_OP_drop - - PARITY is similar: - L1: DW_OP_dup DW_OP_bra DW_OP_dup DW_OP_rot const1 DW_OP_and - DW_OP_xor DW_OP_swap const1 DW_OP_shr DW_OP_skip - L2: DW_OP_drop */ - if (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE (XEXP (rtl, 0)) == mode) - { - dw_loc_descr_ref l1jump, l1label; - dw_loc_descr_ref l2jump, l2label; - - op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op0 == NULL) - break; - op1 = mem_loc_descriptor (const0_rtx, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - l1label = new_loc_descr (DW_OP_dup, 0, 0); - add_loc_descr (&op0, l1label); - l2jump = new_loc_descr (DW_OP_bra, 0, 0); - add_loc_descr (&op0, l2jump); - add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_rot, 0, 0)); - op1 = mem_loc_descriptor (const1_rtx, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); - add_loc_descr (&op0, new_loc_descr (GET_CODE (rtl) == POPCOUNT - ? DW_OP_plus : DW_OP_xor, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - op1 = mem_loc_descriptor (const1_rtx, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_shr, 0, 0)); - l1jump = new_loc_descr (DW_OP_skip, 0, 0); - add_loc_descr (&op0, l1jump); - l2label = new_loc_descr (DW_OP_drop, 0, 0); - add_loc_descr (&op0, l2label); - l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l1jump->dw_loc_oprnd1.v.val_loc = l1label; - l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l2jump->dw_loc_oprnd1.v.val_loc = l2label; - mem_loc_result = op0; - } + mem_loc_result = popcount_loc_descriptor (rtl, mode, mem_mode); break; case BSWAP: - /* BSWAP (constS is initial shift count, either 56 or 24): - constS const0 - L1: DW_OP_pick <2> constS DW_OP_pick <3> DW_OP_minus DW_OP_shr - const255 DW_OP_and DW_OP_pick <2> DW_OP_shl DW_OP_or - DW_OP_swap DW_OP_dup const0 DW_OP_eq DW_OP_bra const8 - DW_OP_minus DW_OP_swap DW_OP_skip - L2: DW_OP_drop DW_OP_swap DW_OP_drop */ - if (GET_MODE_CLASS (mode) == MODE_INT - && BITS_PER_UNIT == 8 - && (GET_MODE_BITSIZE (mode) == 32 - || GET_MODE_BITSIZE (mode) == 64)) - { - dw_loc_descr_ref l1jump, l1label; - dw_loc_descr_ref l2jump, l2label; - - op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op0 == NULL) - break; - - op1 = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8), - mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - op1 = mem_loc_descriptor (const0_rtx, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - l1label = new_loc_descr (DW_OP_pick, 2, 0); - add_loc_descr (&op0, l1label); - op1 = mem_loc_descriptor (GEN_INT (GET_MODE_BITSIZE (mode) - 8), - mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_pick, 3, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_minus, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_shr, 0, 0)); - op1 = mem_loc_descriptor (GEN_INT (255), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op1 == NULL) - break; - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_pick, 2, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_or, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0)); - op1 = mem_loc_descriptor (const0_rtx, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_eq, 0, 0)); - l2jump = new_loc_descr (DW_OP_bra, 0, 0); - add_loc_descr (&op0, l2jump); - op1 = mem_loc_descriptor (GEN_INT (8), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_minus, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - l1jump = new_loc_descr (DW_OP_skip, 0, 0); - add_loc_descr (&op0, l1jump); - l2label = new_loc_descr (DW_OP_drop, 0, 0); - add_loc_descr (&op0, l2label); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_drop, 0, 0)); - l1jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l1jump->dw_loc_oprnd1.v.val_loc = l1label; - l2jump->dw_loc_oprnd1.val_class = dw_val_class_loc; - l2jump->dw_loc_oprnd1.v.val_loc = l2label; - mem_loc_result = op0; - } + mem_loc_result = bswap_loc_descriptor (rtl, mode, mem_mode); break; case ROTATE: case ROTATERT: - /* ROTATE (constMASK is mode mask, BITSIZE is bitsize of mode): - DW_OP_over DW_OP_over DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot - [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_neg - DW_OP_plus_uconst DW_OP_shr DW_OP_or - - ROTATERT is similar: - DW_OP_over DW_OP_over DW_OP_neg DW_OP_plus_uconst - DW_OP_shl [ constMASK DW_OP_and ] DW_OP_rot - [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_shr DW_OP_or - */ - if (GET_MODE_CLASS (mode) == MODE_INT) - { - rtx rtlop1 = XEXP (rtl, 1); - dw_loc_descr_ref mask[2] = { NULL, NULL }; - int i; - - if (GET_MODE (rtlop1) != VOIDmode - && GET_MODE_BITSIZE (GET_MODE (rtlop1)) - < GET_MODE_BITSIZE (mode)) - rtlop1 = gen_rtx_ZERO_EXTEND (mode, rtlop1); - op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - op1 = mem_loc_descriptor (rtlop1, mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - if (op0 == NULL || op1 == NULL) - break; - if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE) - for (i = 0; i < 2; i++) - { - if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT) - mask[i] = mem_loc_descriptor (GEN_INT (GET_MODE_MASK (mode)), - mode, mem_mode, - VAR_INIT_STATUS_INITIALIZED); - else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT) - mask[i] = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32 - ? DW_OP_const4u - : HOST_BITS_PER_WIDE_INT == 64 - ? DW_OP_const8u : DW_OP_constu, - GET_MODE_MASK (mode), 0); - else - mask[i] = NULL; - if (mask[i] == NULL) - return NULL; - add_loc_descr (&mask[i], new_loc_descr (DW_OP_and, 0, 0)); - } - add_loc_descr (&op0, op1); - add_loc_descr (&op0, new_loc_descr (DW_OP_over, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_over, 0, 0)); - if (GET_CODE (rtl) == ROTATERT) - { - add_loc_descr (&op0, new_loc_descr (DW_OP_neg, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, - GET_MODE_BITSIZE (mode), 0)); - } - add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0)); - if (mask[0] != NULL) - add_loc_descr (&op0, mask[0]); - add_loc_descr (&op0, new_loc_descr (DW_OP_rot, 0, 0)); - if (mask[1] != NULL) - { - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - add_loc_descr (&op0, mask[1]); - add_loc_descr (&op0, new_loc_descr (DW_OP_swap, 0, 0)); - } - if (GET_CODE (rtl) == ROTATE) - { - add_loc_descr (&op0, new_loc_descr (DW_OP_neg, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, - GET_MODE_BITSIZE (mode), 0)); - } - add_loc_descr (&op0, new_loc_descr (DW_OP_shr, 0, 0)); - add_loc_descr (&op0, new_loc_descr (DW_OP_or, 0, 0)); - mem_loc_result = op0; - } + mem_loc_result = rotate_loc_descriptor (rtl, mode, mem_mode); break; case COMPARE: -- 2.30.2