Commit 6cd402f1b4

Vexu <git@vexu.eu>
2019-12-19 09:48:32
translate-c-2 increments worst-case
1 parent 809deb6
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.*;
+        \\    });
+        \\}
+    });
 }