diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 859d10a441..26dbb2d424 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -2261,9 +2261,37 @@ fn transCreatePreCrement( // c: ++expr // zig: (blk: { // zig: const _ref = &expr; - // zig: *_ref += 1; - // zig: break :blk *_ref + // zig: _ref.* += 1; + // zig: break :blk _ref.* // zig: }) + const block_scope = try Scope.Block.init(rp.c, scope, "blk"); + block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); + const ref = try std.fmt.allocPrint(rp.c.a(), "_ref_{}", .{rp.c.getMangle()}); + + const node = try transCreateNodeVarDecl(rp.c, false, true, ref); + node.eq_token = try appendToken(rp.c, .Equal, "="); + const rhs_node = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); + rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); + node.init_node = &rhs_node.base; + node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); + try block_scope.block_node.statements.push(&node.base); + + const lhs_node = try transCreateNodeIdentifier(rp.c, ref); + const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); + _ = try appendToken(rp.c, .Semicolon, ";"); + const token = try appendToken(rp.c, op_tok_id, bytes); + const one = try transCreateNodeInt(rp.c, 1); + _ = try appendToken(rp.c, .Semicolon, ";"); + const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .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, ";"); + return &block_scope.block_node.base; } fn transCreatePostCrement( @@ -2291,10 +2319,45 @@ fn transCreatePostCrement( // c: expr++ // zig: (blk: { // zig: const _ref = &expr; - // zig: const _tmp = *_ref; - // zig: *_ref += 1; + // zig: const _tmp = _ref.*; + // zig: _ref.* += 1; // zig: break :blk _tmp // zig: }) + const block_scope = try Scope.Block.init(rp.c, scope, "blk"); + block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); + const ref = try std.fmt.allocPrint(rp.c.a(), "_ref_{}", .{rp.c.getMangle()}); + + const node = try transCreateNodeVarDecl(rp.c, false, true, ref); + node.eq_token = try appendToken(rp.c, .Equal, "="); + const rhs_node = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); + rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value); + node.init_node = &rhs_node.base; + node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); + try block_scope.block_node.statements.push(&node.base); + + const lhs_node = try transCreateNodeIdentifier(rp.c, ref); + const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); + _ = try appendToken(rp.c, .Semicolon, ";"); + + const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()}); + const tmp_node = try transCreateNodeVarDecl(rp.c, false, true, tmp); + tmp_node.eq_token = try appendToken(rp.c, .Equal, "="); + tmp_node.init_node = ref_node; + tmp_node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); + try block_scope.block_node.statements.push(&tmp_node.base); + + const token = try appendToken(rp.c, op_tok_id, bytes); + const one = try transCreateNodeInt(rp.c, 1); + _ = try appendToken(rp.c, .Semicolon, ";"); + const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false); + try block_scope.block_node.statements.push(assign); + + const break_node = try transCreateNodeBreak(rp.c, block_scope.label); + break_node.rhs = try transCreateNodeIdentifier(rp.c,tmp); + try block_scope.block_node.statements.push(&break_node.base); + _ = try appendToken(rp.c, .Semicolon, ";"); + block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); + return &block_scope.block_node.base; } fn transCPtrCast( @@ -2694,25 +2757,16 @@ fn transCreateNodeAssign( } if (scope.id != .Condition) _ = try appendToken(rp.c, .Semicolon, ";"); - - const node = try rp.c.a().create(ast.Node.InfixOp); - node.* = .{ - .op_token = eq_token, - .lhs = lhs_node, - .op = .Assign, - .rhs = rhs_node, - }; - return &node.base; + return transCreateNodeInfixOp(rp, scope, lhs_node, .Assign, eq_token, rhs_node, .used, false); } // worst case // c: lhs = rhs - // zig: (x: { + // zig: (blk: { // zig: const _tmp = rhs; // zig: lhs = _tmp; - // zig: break :x _tmp + // zig: break :blk _tmp // zig: }) - _ = try appendToken(rp.c, .LParen, "("); const block_scope = try Scope.Block.init(rp.c, scope, "blk"); block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()}); @@ -2735,14 +2789,8 @@ fn transCreateNodeAssign( const ident = try transCreateNodeIdentifier(rp.c, tmp); _ = try appendToken(rp.c, .Semicolon, ";"); - const assign = try rp.c.a().create(ast.Node.InfixOp); - assign.* = .{ - .op_token = eq_token, - .lhs = lhs_node, - .op = .Assign, - .rhs = ident, - }; - try block_scope.block_node.statements.push(&assign.base); + const assign = try transCreateNodeInfixOp(rp, scope, lhs_node, .Assign, eq_token, ident, .used, false); + try block_scope.block_node.statements.push(assign); const break_node = try transCreateNodeBreak(rp.c, block_scope.label); break_node.rhs = try transCreateNodeIdentifier(rp.c, tmp); @@ -2751,7 +2799,6 @@ fn transCreateNodeAssign( 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, .RParen, ")"); return &block_scope.block_node.base; } diff --git a/test/translate_c.zig b/test/translate_c.zig index 8bfa2096e7..8d1fc90833 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1786,6 +1786,50 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_2("pre increment/decrement", + \\void foo(void) { + \\ int i = 0; + \\ unsigned u = 0; + \\ ++i; + \\ --i; + \\ ++u; + \\ --u; + \\ i = ++i; + \\ i = --i; + \\ u = ++u; + \\ u = --u; + \\} + , &[_][]const u8{ + \\pub export fn foo() void { + \\ var i: c_int = 0; + \\ var u: c_uint = @as(c_uint, 0); + \\ i += 1; + \\ i -= 1; + \\ u +%= 1; + \\ u -%= 1; + \\ i = blk: { + \\ const _ref_1 = &i; + \\ _ref_1.* += 1; + \\ break :blk _ref_1.*; + \\ }; + \\ i = blk: { + \\ const _ref_2 = &i; + \\ _ref_2.* -= 1; + \\ break :blk _ref_2.*; + \\ }; + \\ u = blk: { + \\ const _ref_3 = &u; + \\ _ref_3.* +%= 1; + \\ break :blk _ref_3.*; + \\ }; + \\ u = blk: { + \\ const _ref_4 = &u; + \\ _ref_4.* -%= 1; + \\ break :blk _ref_4.*; + \\ }; + \\} + }); + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// cases.add("macro defines string literal with hex", @@ -2025,50 +2069,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); - cases.addC("pre increment/decrement", - \\void foo(void) { - \\ int i = 0; - \\ unsigned u = 0; - \\ ++i; - \\ --i; - \\ ++u; - \\ --u; - \\ i = ++i; - \\ i = --i; - \\ u = ++u; - \\ u = --u; - \\} - , &[_][]const u8{ - \\pub export fn foo() void { - \\ var i: c_int = 0; - \\ var u: c_uint = @as(c_uint, 0); - \\ i += 1; - \\ i -= 1; - \\ u +%= 1; - \\ u -%= 1; - \\ i = (x: { - \\ const _ref = &i; - \\ _ref.* += 1; - \\ break :x _ref.*; - \\ }); - \\ i = (x: { - \\ const _ref = &i; - \\ _ref.* -= 1; - \\ break :x _ref.*; - \\ }); - \\ u = (x: { - \\ const _ref = &u; - \\ _ref.* +%= 1; - \\ break :x _ref.*; - \\ }); - \\ u = (x: { - \\ const _ref = &u; - \\ _ref.* -%= 1; - \\ break :x _ref.*; - \\ }); - \\} - }); - cases.addC("implicit casts", \\#include \\ @@ -2745,4 +2745,48 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ _ = baz(); \\} }); + + cases.addC("pre increment/decrement", + \\void foo(void) { + \\ int i = 0; + \\ unsigned u = 0; + \\ ++i; + \\ --i; + \\ ++u; + \\ --u; + \\ i = ++i; + \\ i = --i; + \\ u = ++u; + \\ u = --u; + \\} + , &[_][]const u8{ + \\pub export fn foo() void { + \\ var i: c_int = 0; + \\ var u: c_uint = @as(c_uint, 0); + \\ i += 1; + \\ i -= 1; + \\ u +%= 1; + \\ u -%= 1; + \\ i = (x: { + \\ const _ref = &i; + \\ _ref.* += 1; + \\ break :x _ref.*; + \\ }); + \\ i = (x: { + \\ const _ref = &i; + \\ _ref.* -= 1; + \\ break :x _ref.*; + \\ }); + \\ u = (x: { + \\ const _ref = &u; + \\ _ref.* +%= 1; + \\ break :x _ref.*; + \\ }); + \\ u = (x: { + \\ const _ref = &u; + \\ _ref.* -%= 1; + \\ break :x _ref.*; + \\ }); + \\} + }); }