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(...@@ -1170,7 +1170,7 @@ fn transBinaryOperator(
1170 }1170 }
1171 },1171 },
1172 .Div => {1172 .Div => {
1173 if (!cIsUnsignedInteger(qt)) {1173 if (cIsSignedInteger(qt)) {
1174 // signed integer division uses @divTrunc1174 // signed integer division uses @divTrunc
1175 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");1175 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");
1176 try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));1176 try div_trunc_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));
...@@ -1182,7 +1182,7 @@ fn transBinaryOperator(...@@ -1182,7 +1182,7 @@ fn transBinaryOperator(
1182 }1182 }
1183 },1183 },
1184 .Rem => {1184 .Rem => {
1185 if (!cIsUnsignedInteger(qt)) {1185 if (cIsSignedInteger(qt)) {
1186 // signed integer division uses @rem1186 // signed integer division uses @rem
1187 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");1187 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
1188 try rem_node.params.push(try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value));1188 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...@@ -3018,6 +3018,8 @@ fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const Zig
3018 return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)3018 return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
3019 else3019 else
3020 return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),3020 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),
3021 .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used),3023 .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used),
3022 .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used),3024 .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used),
3023 .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used),3025 .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used),
...@@ -3046,13 +3048,37 @@ fn transCreateCompoundAssign(...@@ -3046,13 +3048,37 @@ fn transCreateCompoundAssign(
3046 used: ResultUsed,3048 used: ResultUsed,
3047) TransError!*ast.Node {3049) TransError!*ast.Node {
3048 const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;3050 const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;
3051 const is_div = bin_op == .Div;
3052 const is_mod = bin_op == .Mod;
3049 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);3053 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
3050 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);3054 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
3051 const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);3055 const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
3056 const is_signed = cIsSignedInteger(getExprQualType(rp.c, lhs));
3052 if (used == .unused) {3057 if (used == .unused) {
3053 // common case3058 // common case
3054 // c: lhs += rhs3059 // c: lhs += rhs
3055 // zig: lhs += rhs3060 // 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
3056 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);3082 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
3057 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);3083 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
3058 var rhs_node = if (is_shift)3084 var rhs_node = if (is_shift)
...@@ -3095,31 +3121,51 @@ fn transCreateCompoundAssign(...@@ -3095,31 +3121,51 @@ fn transCreateCompoundAssign(
3095 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);3121 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
3096 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);3122 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
3097 _ = try appendToken(rp.c, .Semicolon, ";");3123 _ = try appendToken(rp.c, .Semicolon, ";");
3098 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);3124
3099 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);3125 if ((is_mod or is_div) and is_signed) {
3100 if (is_shift) {3126 const op_token = try appendToken(rp.c, .Equal, "=");
3101 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");3127 const op_node = try rp.c.a().create(ast.Node.InfixOp);
3102 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);3128 const builtin = if (is_mod) "@rem" else "@divTrunc";
3103 try cast_node.params.push(rhs_type);3129 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, builtin);
3130 try builtin_node.params.push(try transCreateNodePtrDeref(rp.c, lhs_node));
3104 _ = try appendToken(rp.c, .Comma, ",");3131 _ = try appendToken(rp.c, .Comma, ",");
3105 try cast_node.params.push(rhs_node);3132 try builtin_node.params.push(try transExpr(rp, scope, rhs, .used, .r_value));
3106 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");3133 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3107 rhs_node = &cast_node.base;3134 _ = try appendToken(rp.c, .Semicolon, ";");
3108 }3135 op_node.* = .{
3109 const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);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, "=");3157 const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
3114 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false);3158 _ = try appendToken(rp.c, .Semicolon, ";");
3115 try block_scope.block_node.statements.push(assign);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
3117 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);3165 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
3118 break_node.rhs = ref_node;3166 break_node.rhs = ref_node;
3119 try block_scope.block_node.statements.push(&break_node.base);3167 try block_scope.block_node.statements.push(&break_node.base);
3120 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");3168 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, ";");
3123 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);3169 const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
3124 grouped_expr.* = .{3170 grouped_expr.* = .{
3125 .lparen = try appendToken(rp.c, .LParen, "("),3171 .lparen = try appendToken(rp.c, .LParen, "("),
test/translate_c.zig+26
...@@ -2375,6 +2375,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2375,6 +2375,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2375 cases.add("compound assignment operators",2375 cases.add("compound assignment operators",
2376 \\void foo(void) {2376 \\void foo(void) {
2377 \\ int a = 0;2377 \\ int a = 0;
2378 \\ unsigned b = 0;
2378 \\ a += (a += 1);2379 \\ a += (a += 1);
2379 \\ a -= (a -= 1);2380 \\ a -= (a -= 1);
2380 \\ a *= (a *= 1);2381 \\ a *= (a *= 1);
...@@ -2383,10 +2384,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2383,10 +2384,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2383 \\ a ^= (a ^= 1);2384 \\ a ^= (a ^= 1);
2384 \\ a >>= (a >>= 1);2385 \\ a >>= (a >>= 1);
2385 \\ a <<= (a <<= 1);2386 \\ a <<= (a <<= 1);
2387 \\ a /= (a /= 1);
2388 \\ a %= (a %= 1);
2389 \\ b /= (b /= 1);
2390 \\ b %= (b %= 1);
2386 \\}2391 \\}
2387 , &[_][]const u8{2392 , &[_][]const u8{
2388 \\pub export fn foo() void {2393 \\pub export fn foo() void {
2389 \\ var a: c_int = 0;2394 \\ var a: c_int = 0;
2395 \\ var b: c_uint = @bitCast(c_uint, @as(c_int, 0));
2390 \\ a += (blk: {2396 \\ a += (blk: {
2391 \\ const ref = &a;2397 \\ const ref = &a;
2392 \\ ref.* = ref.* + @as(c_int, 1);2398 \\ ref.* = ref.* + @as(c_int, 1);
...@@ -2427,6 +2433,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2427,6 +2433,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2427 \\ ref.* = ref.* << @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));2433 \\ ref.* = ref.* << @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2428 \\ break :blk ref.*;2434 \\ break :blk ref.*;
2429 \\ }));2435 \\ }));
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 \\ });
2430 \\}2456 \\}
2431 });2457 });
24322458