Adriaan van Os wrote:
Waldek Hebisch wrote:
I assume that it fails.
It does.
But the machine code contains 10 comparisons, and it is not clear which one fails.
The last one.
I think the problem was that value to be assigned was internally converted to `Integer' which caused subsequent operation to treat arguments as signed. In particular shifting 1 (`True') from highest bit positions to proper place filled high sub-word with 1-s. Since later we want only low bits the range check failed. AFAICS earlier we would just silently produce wrong code (setting too many bits to 1).
The patch below should fix this:
diff -u p.bb1/expressions.c p/expressions.c --- p.bb1/expressions.c 2005-02-21 05:01:12.000000000 +0100 +++ p/expressions.c 2005-02-22 19:04:04.895349760 +0100 @@ -3652,11 +3652,18 @@ /* Now form a new expression to store the lower part of newrhs in low_lhs. Clear the bits in the target. */ shifted_mask = build_pascal_binary_op (LSHIFT_EXPR, mask, offset); - eraser = build_modify_expr (low_lhs, BIT_AND_EXPR, build_unary_op (BIT_NOT_EXPR, shifted_mask, 0)); + eraser = build_modify_expr (low_lhs, BIT_AND_EXPR, + convert(packed_array_unsigned_short_type_node, + build_unary_op (BIT_NOT_EXPR, shifted_mask, 0))); /* Do the assignment. */ - brush = build_pascal_binary_op (BIT_AND_EXPR, default_conversion (newrhs), mask); + brush = build_pascal_binary_op (BIT_AND_EXPR, + convert(packed_array_unsigned_long_type_node, newrhs), mask); brush = build_pascal_binary_op (LSHIFT_EXPR, brush, offset); - brush = build_pascal_binary_op (BIT_AND_EXPR, brush, TYPE_MAX_VALUE (packed_array_unsigned_short_type_node)); + brush = convert(packed_array_unsigned_long_type_node, brush); + brush = build_pascal_binary_op (BIT_AND_EXPR, brush, + convert(packed_array_unsigned_long_type_node, + TYPE_MAX_VALUE (packed_array_unsigned_short_type_node))); + brush = convert(packed_array_unsigned_short_type_node, brush); brush = build_modify_expr (low_lhs, BIT_IOR_EXPR, brush); low_assignment = build (COMPOUND_EXPR, TREE_TYPE (brush), save_rhs_stmt, build (COMPOUND_EXPR, TREE_TYPE (brush), eraser, brush)); @@ -3664,11 +3671,16 @@ /* Now do the same for the higher part and high_lhs. Prepare shifted_mask to access the higher half. Clear the bits in the target. */ shifted_mask = build (RSHIFT_EXPR, TREE_TYPE (shifted_mask), shifted_mask, TYPE_SIZE (TREE_TYPE (low_lhs))); - eraser = build_modify_expr (high_lhs, BIT_AND_EXPR, build_unary_op (BIT_NOT_EXPR, shifted_mask, 0)); + eraser = build_modify_expr (high_lhs, BIT_AND_EXPR, + convert(packed_array_unsigned_short_type_node, + build_unary_op (BIT_NOT_EXPR, shifted_mask, 0))); /* Do the assignment. */ - brush = build_pascal_binary_op (BIT_AND_EXPR, default_conversion (newrhs), mask); + brush = build_pascal_binary_op (BIT_AND_EXPR, + convert(packed_array_unsigned_long_type_node, newrhs), mask); brush = build_pascal_binary_op (LSHIFT_EXPR, brush, offset); + brush = convert(packed_array_unsigned_long_type_node, brush); brush = build_pascal_binary_op (RSHIFT_EXPR, brush, TYPE_SIZE (TREE_TYPE (low_lhs))); + brush = convert(packed_array_unsigned_short_type_node, brush); brush = build_modify_expr (high_lhs, BIT_IOR_EXPR, brush); /* Construct a COMPOUND_EXPR holding both. */ high_assignment = build (COMPOUND_EXPR, TREE_TYPE (brush), eraser, brush);