Commit 391ee996a5
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -1170,7 +1170,7 @@ fn transBinaryOperator(
}
},
.Div => {
- if (!cIsUnsignedInteger(qt)) {
+ if (cIsSignedInteger(qt)) {
// signed integer division uses @divTrunc
const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");
try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
@@ -1182,7 +1182,7 @@ fn transBinaryOperator(
}
},
.Rem => {
- if (!cIsUnsignedInteger(qt)) {
+ if (cIsSignedInteger(qt)) {
// signed integer division uses @rem
const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
try rem_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
@@ -3048,13 +3048,37 @@ fn transCreateCompoundAssign(
used: ResultUsed,
) TransError!*ast.Node {
const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;
+ const is_div = bin_op == .Div;
+ const is_mod = bin_op == .Mod;
const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
+ const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs));
if (used == .unused) {
// common case
// c: lhs += rhs
// zig: lhs += rhs
+
+ if ((is_mod or is_div) and is_signed) {
+ const op_token = try appendToken(rp.c, .Equal, "=");
+ const op_node = try rp.c.a().create(ast.Node.InfixOp);
+ const builtin = if (is_mod) "@rem" else "@divTrunc";
+ const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin);
+ const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
+ try builtin_node.params.push(lhs_node);
+ _ = try appendToken(rp.c, .Comma, ",");
+ try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value));
+ builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ op_node.* = .{
+ .op_token = op_token,
+ .lhs = lhs_node,
+ .op = .Assign,
+ .rhs = &builtin_node.base,
+ };
+ _ = try appendToken(rp.c, .Semicolon, ";");
+ return &op_node.base;
+ }
+
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
var rhs_node = if (is_shift)
@@ -3097,31 +3121,53 @@ fn transCreateCompoundAssign(
const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
_ = try appendToken(rp.c, .Semicolon, ";");
- const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
- var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
- if (is_shift) {
- const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
- const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
- try cast_node.params.push(rhs_type);
+
+ if ((is_mod or is_div) and is_signed) {
+ const op_token = try appendToken(rp.c, .Equal, "=");
+ const op_node = try rp.c.a().create(ast.Node.InfixOp);
+ const builtin = if (is_mod) "@rem" else "@divTrunc";
+ const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin);
+ try builtin_node.params.push(try transCreateNodePtrDeref(rp.c, lhs_node));
_ = try appendToken(rp.c, .Comma, ",");
- try cast_node.params.push(rhs_node);
- cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
- rhs_node = &cast_node.base;
- }
- const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
+ try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value));
+ builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ _ = try appendToken(rp.c, .Semicolon, ";");
+ op_node.* = .{
+ .op_token = op_token,
+ .lhs = ref_node,
+ .op = .Assign,
+ .rhs = &builtin_node.base,
+ };
+ _ = try appendToken(rp.c, .Semicolon, ";");
+ try block_scope.block_node.statements.push(&op_node.base);
+ } else {
+ const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
+ var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
- _ = try appendToken(rp.c, .Semicolon, ";");
+ if (is_shift) {
+ const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
+ const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
+ try cast_node.params.push(rhs_type);
+ _ = try appendToken(rp.c, .Comma, ",");
+ try cast_node.params.push(rhs_node);
+ cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ rhs_node = &cast_node.base;
+ }
- const eq_token = try appendToken(rp.c, .Equal, "=");
- const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false);
- try block_scope.block_node.statements.push(assign);
+ const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
+ _ = try appendToken(rp.c, .Semicolon, ";");
+
+ const eq_token = try appendToken(rp.c, .Equal, "=");
+ const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false);
+ try block_scope.block_node.statements.push(assign);
+ }
const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
break_node.rhs = ref_node;
try block_scope.block_node.statements.push(&break_node.base);
block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
// semicolon must immediately follow rbrace because it is the last token in a block
- _ = try appendToken(rp.c, .Semicolon, ";");
+ _ = try appendToken(rp.c, .Semicolon, ";4");
const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
grouped_expr.* = .{
.lparen = try appendToken(rp.c, .LParen, "("),
test/translate_c.zig
@@ -2375,20 +2375,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("compound assignment operators",
\\void foo(void) {
\\ int a = 0;
+ \\ unsigned b = 0;
\\ a += (a += 1);
\\ a -= (a -= 1);
\\ a *= (a *= 1);
\\ a &= (a &= 1);
\\ a |= (a |= 1);
\\ a ^= (a ^= 1);
- \\ a /= (a /= 1);
- \\ a %= (a %= 1);
\\ a >>= (a >>= 1);
\\ a <<= (a <<= 1);
+ \\ a /= (a /= 1);
+ \\ a %= (a %= 1);
+ \\ b /= (b /= 1);
+ \\ b %= (b %= 1);
\\}
, &[_][]const u8{
\\pub export fn foo() void {
\\ var a: c_int = 0;
+ \\ var b: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ a += (blk: {
\\ const ref = &a;
\\ ref.* = ref.* + @as(c_int, 1);
@@ -2419,16 +2423,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ ref.* = ref.* ^ @as(c_int, 1);
\\ break :blk ref.*;
\\ });
- \\ a /= (blk: {
- \\ const ref = &a;
- \\ ref.* = ref.* / @as(c_int, 1);
- \\ break :blk ref.*;
- \\ });
- \\ a %= (blk: {
- \\ const ref = &a;
- \\ ref.* = ref.* % @as(c_int, 1);
- \\ break :blk ref.*;
- \\ });
\\ a >>= @intCast(@import("std").math.Log2Int(c_int), (blk: {
\\ const ref = &a;
\\ ref.* = ref.* >> @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
@@ -2439,6 +2433,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ ref.* = ref.* << @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
\\ break :blk ref.*;
\\ }));
+ \\ a = @divTrunc(a, (blk: {
+ \\ const ref = &a;
+ \\ ref.* = @divTrunc(ref.*, @as(c_int, 1));
+ \\ break :blk ref.*;
+ \\ }));
+ \\ a = @rem(a, (blk: {
+ \\ const ref = &a;
+ \\ ref.* = @rem(ref.*, @as(c_int, 1));
+ \\ break :blk ref.*;
+ \\ }));
+ \\ b /= (blk: {
+ \\ const ref = &b;
+ \\ ref.* = ref.* / @bitCast(c_uint, @as(c_int, 1));
+ \\ break :blk ref.*;
+ \\ });
+ \\ b %= (blk: {
+ \\ const ref = &b;
+ \\ ref.* = ref.* % @bitCast(c_uint, @as(c_int, 1));
+ \\ break :blk ref.*;
+ \\ });
\\}
});