translate-c-2 increments worst-case

This commit is contained in:
Vexu 2019-12-19 10:48:32 +02:00
parent 809deb6ec0
commit 6cd402f1b4
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 160 additions and 69 deletions

View File

@ -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;
}

View File

@ -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.*;
\\ });
\\}
});
}