-/* Given a constant value VAL for bitfield FIELD, and a destination
- variable VAR, return VAL appropriately widened to fit into VAR. If
- FIELD is wider than HOST_WIDE_INT, NULL is returned. */
-
-tree
-widen_bitfield (tree val, tree field, tree var)
-{
- unsigned HOST_WIDE_INT var_size, field_size;
- tree wide_val;
- unsigned HOST_WIDE_INT mask;
- unsigned int i;
-
- /* We can only do this if the size of the type and field and VAL are
- all constants representable in HOST_WIDE_INT. */
- if (!host_integerp (TYPE_SIZE (TREE_TYPE (var)), 1)
- || !host_integerp (DECL_SIZE (field), 1)
- || !host_integerp (val, 0))
- return NULL_TREE;
-
- var_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1);
- field_size = tree_low_cst (DECL_SIZE (field), 1);
-
- /* Give up if either the bitfield or the variable are too wide. */
- if (field_size > HOST_BITS_PER_WIDE_INT || var_size > HOST_BITS_PER_WIDE_INT)
- return NULL_TREE;
-
- gcc_assert (var_size >= field_size);
-
- /* If the sign bit of the value is not set or the field's type is unsigned,
- just mask off the high order bits of the value. */
- if (DECL_UNSIGNED (field)
- || !(tree_low_cst (val, 0) & (((HOST_WIDE_INT)1) << (field_size - 1))))
- {
- /* Zero extension. Build a mask with the lower 'field_size' bits
- set and a BIT_AND_EXPR node to clear the high order bits of
- the value. */
- for (i = 0, mask = 0; i < field_size; i++)
- mask |= ((HOST_WIDE_INT) 1) << i;
-
- wide_val = fold_build2 (BIT_AND_EXPR, TREE_TYPE (var), val,
- build_int_cst (TREE_TYPE (var), mask));
- }
- else
- {
- /* Sign extension. Create a mask with the upper 'field_size'
- bits set and a BIT_IOR_EXPR to set the high order bits of the
- value. */
- for (i = 0, mask = 0; i < (var_size - field_size); i++)
- mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
-
- wide_val = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
- build_int_cst (TREE_TYPE (var), mask));
- }
-
- return wide_val;
-}
-
-