Commit 6cd402f1b4
Changed files (2)
src-self-hosted
test
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;
}
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 <stdbool.h>
\\
@@ -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.*;
+ \\ });
+ \\}
+ });
}