mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
translate-c: Support compound assignment of pointer and signed int
This handles `ptr += idx` and `ptr -= idx` when `idx` is a signed integer expression.
This commit is contained in:
parent
874c63f89c
commit
6d69a29d75
@ -1111,6 +1111,22 @@ fn transOffsetOfExpr(
|
||||
return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO: implement complex OffsetOfExpr translation", .{});
|
||||
}
|
||||
|
||||
/// Cast a signed integer node to a usize, for use in pointer arithmetic. Negative numbers
|
||||
/// will become very large positive numbers but that is ok since we only use this in
|
||||
/// pointer arithmetic expressions, where wraparound will ensure we get the correct value.
|
||||
/// node -> @bitCast(usize, @intCast(isize, node))
|
||||
fn usizeCastForWrappingPtrArithmetic(gpa: *mem.Allocator, node: Node) TransError!Node {
|
||||
const intcast_node = try Tag.int_cast.create(gpa, .{
|
||||
.lhs = try Tag.identifier.create(gpa, "isize"),
|
||||
.rhs = node,
|
||||
});
|
||||
|
||||
return Tag.bit_cast.create(gpa, .{
|
||||
.lhs = try Tag.identifier.create(gpa, "usize"),
|
||||
.rhs = intcast_node,
|
||||
});
|
||||
}
|
||||
|
||||
/// Translate an arithmetic expression with a pointer operand and a signed-integer operand.
|
||||
/// Zig requires a usize argument for pointer arithmetic, so we intCast to isize and then
|
||||
/// bitcast to usize; pointer wraparound make the math work.
|
||||
@ -1133,15 +1149,7 @@ fn transCreatePointerArithmeticSignedOp(
|
||||
const lhs_node = try transExpr(c, scope, swizzled_lhs, .used);
|
||||
const rhs_node = try transExpr(c, scope, swizzled_rhs, .used);
|
||||
|
||||
const intcast_node = try Tag.int_cast.create(c.arena, .{
|
||||
.lhs = try Tag.identifier.create(c.arena, "isize"),
|
||||
.rhs = rhs_node,
|
||||
});
|
||||
|
||||
const bitcast_node = try Tag.bit_cast.create(c.arena, .{
|
||||
.lhs = try Tag.identifier.create(c.arena, "usize"),
|
||||
.rhs = intcast_node,
|
||||
});
|
||||
const bitcast_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
|
||||
|
||||
const arith_args = .{ .lhs = lhs_node, .rhs = bitcast_node };
|
||||
const arith_node = try if (is_add) Tag.add.create(c.arena, arith_args) else Tag.sub.create(c.arena, arith_args);
|
||||
@ -3035,6 +3043,7 @@ fn transCreateCompoundAssign(
|
||||
const lhs_qt = getExprQualType(c, lhs);
|
||||
const rhs_qt = getExprQualType(c, rhs);
|
||||
const is_signed = cIsSignedInteger(lhs_qt);
|
||||
const is_ptr_op_signed = qualTypeIsPtr(lhs_qt) and cIsSignedInteger(rhs_qt);
|
||||
const requires_int_cast = blk: {
|
||||
const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt);
|
||||
const are_same_sign = cIsSignedInteger(lhs_qt) == cIsSignedInteger(rhs_qt);
|
||||
@ -3061,6 +3070,10 @@ fn transCreateCompoundAssign(
|
||||
else
|
||||
try transExpr(c, scope, rhs, .used);
|
||||
|
||||
if (is_ptr_op_signed) {
|
||||
rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
|
||||
}
|
||||
|
||||
if (is_shift or requires_int_cast) {
|
||||
// @intCast(rhs)
|
||||
const cast_to_type = if (is_shift)
|
||||
@ -3113,6 +3126,9 @@ fn transCreateCompoundAssign(
|
||||
|
||||
rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
|
||||
}
|
||||
if (is_ptr_op_signed) {
|
||||
rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
|
||||
}
|
||||
|
||||
const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used);
|
||||
try block_scope.statements.append(assign);
|
||||
|
||||
@ -1154,6 +1154,16 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||
\\ y = x - idx;
|
||||
\\ if (y != x + 1 || y != &array[6]) abort();
|
||||
\\
|
||||
\\ idx = 1;
|
||||
\\ x += idx;
|
||||
\\ if (x != &array[6]) abort();
|
||||
\\ x -= idx;
|
||||
\\ if (x != &array[5]) abort();
|
||||
\\ y = (x += idx);
|
||||
\\ if (y != x || y != &array[6]) abort();
|
||||
\\ y = (x -= idx);
|
||||
\\ if (y != x || y != &array[5]) abort();
|
||||
\\
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user