authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-04-05 21:05:18+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-04-05 21:05:18+03:00
log6ef15fc8d00c06bc767b91515e2c919448948e6f
tree4d2ff8a37b471a10dc91f432d45161ae6d3cc97b
parent607b2661a0e39fd3d03bba2fa27f02ffc27518bc
parentae376e0758bc9d756b3fb778537ad3ea1813ae00
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4901 from phase/feature/translate-c-remassign

translate-c: RemAssign and DivAssign

2 files changed, 91 insertions(+), 19 deletions(-)

src-self-hosted/translate_c.zig+65-19
......@@ -1170,7 +1170,7 @@ fn transBinaryOperator(
11701170 }
11711171 },
11721172 .Div => {
1173 if (!cIsUnsignedInteger(qt)) {
1173 if (cIsSignedInteger(qt)) {
11741174 // signed integer division uses @divTrunc
11751175 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");
11761176 try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
......@@ -1182,7 +1182,7 @@ fn transBinaryOperator(
11821182 }
11831183 },
11841184 .Rem => {
1185 if (!cIsUnsignedInteger(qt)) {
1185 if (cIsSignedInteger(qt)) {
11861186 // signed integer division uses @rem
11871187 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
11881188 try rem_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
......@@ -3018,6 +3018,8 @@ fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const Zig
30183018 return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
30193019 else
30203020 return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
3021 .DivAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignDiv, .SlashEqual, "/=", .Div, .Slash, "/", used),
3022 .RemAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignMod, .PercentEqual, "%=", .Mod, .Percent, "%", used),
30213023 .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used),
30223024 .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used),
30233025 .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used),
......@@ -3046,13 +3048,37 @@ fn transCreateCompoundAssign(
30463048 used: ResultUsed,
30473049) TransError!*ast.Node {
30483050 const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;
3051 const is_div = bin_op == .Div;
3052 const is_mod = bin_op == .Mod;
30493053 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
30503054 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
30513055 const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
3056 const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs));
30523057 if (used == .unused) {
30533058 // common case
30543059 // c: lhs += rhs
30553060 // zig: lhs += rhs
3061
3062 if ((is_mod or is_div) and is_signed) {
3063 const op_token = try appendToken(rp.c, .Equal, "=");
3064 const op_node = try rp.c.a().create(ast.Node.InfixOp);
3065 const builtin = if (is_mod) "@rem" else "@divTrunc";
3066 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin);
3067 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
3068 try builtin_node.params.push(lhs_node);
3069 _ = try appendToken(rp.c, .Comma, ",");
3070 try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value));
3071 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3072 op_node.* = .{
3073 .op_token = op_token,
3074 .lhs = lhs_node,
3075 .op = .Assign,
3076 .rhs = &builtin_node.base,
3077 };
3078 _ = try appendToken(rp.c, .Semicolon, ";");
3079 return &op_node.base;
3080 }
3081
30563082 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
30573083 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
30583084 var rhs_node = if (is_shift)
......@@ -3095,31 +3121,51 @@ fn transCreateCompoundAssign(
30953121 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
30963122 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
30973123 _ = try appendToken(rp.c, .Semicolon, ";");
3098 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
3099 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
3100 if (is_shift) {
3101 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
3102 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
3103 try cast_node.params.push(rhs_type);
3124
3125 if ((is_mod or is_div) and is_signed) {
3126 const op_token = try appendToken(rp.c, .Equal, "=");
3127 const op_node = try rp.c.a().create(ast.Node.InfixOp);
3128 const builtin = if (is_mod) "@rem" else "@divTrunc";
3129 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin);
3130 try builtin_node.params.push(try transCreateNodePtrDeref(rp.c, lhs_node));
31043131 _ = try appendToken(rp.c, .Comma, ",");
3105 try cast_node.params.push(rhs_node);
3106 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3107 rhs_node = &cast_node.base;
3108 }
3109 const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
3132 try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value));
3133 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3134 _ = try appendToken(rp.c, .Semicolon, ";");
3135 op_node.* = .{
3136 .op_token = op_token,
3137 .lhs = ref_node,
3138 .op = .Assign,
3139 .rhs = &builtin_node.base,
3140 };
3141 _ = try appendToken(rp.c, .Semicolon, ";");
3142 try block_scope.block_node.statements.push(&op_node.base);
3143 } else {
3144 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
3145 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
31103146
3111 _ = try appendToken(rp.c, .Semicolon, ";");
3147 if (is_shift) {
3148 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
3149 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
3150 try cast_node.params.push(rhs_type);
3151 _ = try appendToken(rp.c, .Comma, ",");
3152 try cast_node.params.push(rhs_node);
3153 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3154 rhs_node = &cast_node.base;
3155 }
31123156
3113 const eq_token = try appendToken(rp.c, .Equal, "=");
3114 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false);
3115 try block_scope.block_node.statements.push(assign);
3157 const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
3158 _ = try appendToken(rp.c, .Semicolon, ";");
3159
3160 const eq_token = try appendToken(rp.c, .Equal, "=");
3161 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false);
3162 try block_scope.block_node.statements.push(assign);
3163 }
31163164
31173165 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
31183166 break_node.rhs = ref_node;
31193167 try block_scope.block_node.statements.push(&break_node.base);
31203168 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
3121 // semicolon must immediately follow rbrace because it is the last token in a block
3122 _ = try appendToken(rp.c, .Semicolon, ";");
31233169 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
31243170 grouped_expr.* = .{
31253171 .lparen = try appendToken(rp.c, .LParen, "("),
test/translate_c.zig+26
......@@ -2375,6 +2375,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23752375 cases.add("compound assignment operators",
23762376 \\void foo(void) {
23772377 \\ int a = 0;
2378 \\ unsigned b = 0;
23782379 \\ a += (a += 1);
23792380 \\ a -= (a -= 1);
23802381 \\ a *= (a *= 1);
......@@ -2383,10 +2384,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
23832384 \\ a ^= (a ^= 1);
23842385 \\ a >>= (a >>= 1);
23852386 \\ a <<= (a <<= 1);
2387 \\ a /= (a /= 1);
2388 \\ a %= (a %= 1);
2389 \\ b /= (b /= 1);
2390 \\ b %= (b %= 1);
23862391 \\}
23872392 , &[_][]const u8{
23882393 \\pub export fn foo() void {
23892394 \\ var a: c_int = 0;
2395 \\ var b: c_uint = @bitCast(c_uint, @as(c_int, 0));
23902396 \\ a += (blk: {
23912397 \\ const ref = &a;
23922398 \\ ref.* = ref.* + @as(c_int, 1);
......@@ -2427,6 +2433,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
24272433 \\ ref.* = ref.* << @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
24282434 \\ break :blk ref.*;
24292435 \\ }));
2436 \\ a = @divTrunc(a, (blk: {
2437 \\ const ref = &a;
2438 \\ ref.* = @divTrunc(ref.*, @as(c_int, 1));
2439 \\ break :blk ref.*;
2440 \\ }));
2441 \\ a = @rem(a, (blk: {
2442 \\ const ref = &a;
2443 \\ ref.* = @rem(ref.*, @as(c_int, 1));
2444 \\ break :blk ref.*;
2445 \\ }));
2446 \\ b /= (blk: {
2447 \\ const ref = &b;
2448 \\ ref.* = ref.* / @bitCast(c_uint, @as(c_int, 1));
2449 \\ break :blk ref.*;
2450 \\ });
2451 \\ b %= (blk: {
2452 \\ const ref = &b;
2453 \\ ref.* = ref.* % @bitCast(c_uint, @as(c_int, 1));
2454 \\ break :blk ref.*;
2455 \\ });
24302456 \\}
24312457 });
24322458