mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
translate-c-2 compound assign
This commit is contained in:
parent
6cd402f1b4
commit
f837c7c9cd
@ -1431,13 +1431,13 @@ pub const Node = struct {
|
||||
AssignBitShiftRight,
|
||||
AssignBitXor,
|
||||
AssignDiv,
|
||||
AssignMinus,
|
||||
AssignMinusWrap,
|
||||
AssignSub,
|
||||
AssignSubWrap,
|
||||
AssignMod,
|
||||
AssignPlus,
|
||||
AssignPlusWrap,
|
||||
AssignTimes,
|
||||
AssignTimesWarp,
|
||||
AssignAdd,
|
||||
AssignAddWrap,
|
||||
AssignMult,
|
||||
AssignMultWrap,
|
||||
BangEqual,
|
||||
BitAnd,
|
||||
BitOr,
|
||||
@ -1490,13 +1490,13 @@ pub const Node = struct {
|
||||
Op.AssignBitShiftRight,
|
||||
Op.AssignBitXor,
|
||||
Op.AssignDiv,
|
||||
Op.AssignMinus,
|
||||
Op.AssignMinusWrap,
|
||||
Op.AssignSub,
|
||||
Op.AssignSubWrap,
|
||||
Op.AssignMod,
|
||||
Op.AssignPlus,
|
||||
Op.AssignPlusWrap,
|
||||
Op.AssignTimes,
|
||||
Op.AssignTimesWarp,
|
||||
Op.AssignAdd,
|
||||
Op.AssignAddWrap,
|
||||
Op.AssignMult,
|
||||
Op.AssignMultWrap,
|
||||
Op.BangEqual,
|
||||
Op.BitAnd,
|
||||
Op.BitOr,
|
||||
|
||||
@ -1981,19 +1981,19 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||
|
||||
const token = nextToken(it);
|
||||
const op = switch (token.ptr.id) {
|
||||
.AsteriskEqual => Op{ .AssignTimes = {} },
|
||||
.AsteriskEqual => Op{ .AssignMult = {} },
|
||||
.SlashEqual => Op{ .AssignDiv = {} },
|
||||
.PercentEqual => Op{ .AssignMod = {} },
|
||||
.PlusEqual => Op{ .AssignPlus = {} },
|
||||
.MinusEqual => Op{ .AssignMinus = {} },
|
||||
.PlusEqual => Op{ .AssignAdd = {} },
|
||||
.MinusEqual => Op{ .AssignSub = {} },
|
||||
.AngleBracketAngleBracketLeftEqual => Op{ .AssignBitShiftLeft = {} },
|
||||
.AngleBracketAngleBracketRightEqual => Op{ .AssignBitShiftRight = {} },
|
||||
.AmpersandEqual => Op{ .AssignBitAnd = {} },
|
||||
.CaretEqual => Op{ .AssignBitXor = {} },
|
||||
.PipeEqual => Op{ .AssignBitOr = {} },
|
||||
.AsteriskPercentEqual => Op{ .AssignTimesWarp = {} },
|
||||
.PlusPercentEqual => Op{ .AssignPlusWrap = {} },
|
||||
.MinusPercentEqual => Op{ .AssignMinusWrap = {} },
|
||||
.AsteriskPercentEqual => Op{ .AssignMultWrap = {} },
|
||||
.PlusPercentEqual => Op{ .AssignAddWrap = {} },
|
||||
.MinusPercentEqual => Op{ .AssignSubWrap = {} },
|
||||
.Equal => Op{ .Assign = {} },
|
||||
else => {
|
||||
putBackToken(it, token.index);
|
||||
|
||||
@ -1120,3 +1120,11 @@ pub extern fn ZigClangUnaryOperator_getOpcode(*const ZigClangUnaryOperator) ZigC
|
||||
pub extern fn ZigClangUnaryOperator_getType(*const ZigClangUnaryOperator) ZigClangQualType;
|
||||
pub extern fn ZigClangUnaryOperator_getSubExpr(*const ZigClangUnaryOperator) *const ZigClangExpr;
|
||||
pub extern fn ZigClangUnaryOperator_getBeginLoc(*const ZigClangUnaryOperator) ZigClangSourceLocation;
|
||||
|
||||
pub extern fn ZigClangCompoundAssignOperator_getType(*const ZigClangCompoundAssignOperator) ZigClangQualType;
|
||||
pub extern fn ZigClangCompoundAssignOperator_getComputationLHSType(*const ZigClangCompoundAssignOperator) ZigClangQualType;
|
||||
pub extern fn ZigClangCompoundAssignOperator_getComputationResultType(*const ZigClangCompoundAssignOperator) ZigClangQualType;
|
||||
pub extern fn ZigClangCompoundAssignOperator_getBeginLoc(*const ZigClangCompoundAssignOperator) ZigClangSourceLocation;
|
||||
pub extern fn ZigClangCompoundAssignOperator_getOpcode(*const ZigClangCompoundAssignOperator) ZigClangBO;
|
||||
pub extern fn ZigClangCompoundAssignOperator_getLHS(*const ZigClangCompoundAssignOperator) *const ZigClangExpr;
|
||||
pub extern fn ZigClangCompoundAssignOperator_getRHS(*const ZigClangCompoundAssignOperator) *const ZigClangExpr;
|
||||
|
||||
@ -898,6 +898,7 @@ fn transStmt(
|
||||
.CallExprClass => return transCallExpr(rp, scope, @ptrCast(*const ZigClangCallExpr, stmt), result_used),
|
||||
.UnaryExprOrTypeTraitExprClass => return transUnaryExprOrTypeTraitExpr(rp, scope, @ptrCast(*const ZigClangUnaryExprOrTypeTraitExpr, stmt), result_used),
|
||||
.UnaryOperatorClass => return transUnaryOperator(rp, scope, @ptrCast(*const ZigClangUnaryOperator, stmt), result_used),
|
||||
.CompoundAssignOperatorClass => return transCompoundAssignOperator(rp, scope, @ptrCast(*const ZigClangCompoundAssignOperator, stmt), result_used),
|
||||
else => {
|
||||
return revertAndWarn(
|
||||
rp,
|
||||
@ -2178,21 +2179,21 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
|
||||
const op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
|
||||
switch (ZigClangUnaryOperator_getOpcode(stmt)) {
|
||||
.PostInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignPlusWrap, .PlusPercentEqual, "+%=", used)
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
|
||||
else
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignPlus, .PlusEqual, "+=", used),
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
|
||||
.PostDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignMinusWrap, .MinusPercentEqual, "-%=", used)
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
|
||||
else
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignMinus, .MinusEqual, "-=", used),
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
|
||||
.PreInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignPlusWrap, .PlusPercentEqual, "+%=", used)
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
|
||||
else
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignPlus, .PlusEqual, "+=", used),
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
|
||||
.PreDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignMinusWrap, .MinusPercentEqual, "-%=", used)
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
|
||||
else
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignMinus, .MinusEqual, "-=", used),
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
|
||||
.AddrOf => {
|
||||
const op_node = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
|
||||
op_node.rhs = try transExpr(rp, scope, op_expr, used, .r_value);
|
||||
@ -2232,7 +2233,7 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
|
||||
op_node.rhs = try transBoolExpr(rp, scope, op_expr, .used, .r_value, true);
|
||||
return &op_node.base;
|
||||
},
|
||||
else => return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangUnaryOperator_getBeginLoc(stmt), "TODO handle C translation UO_Real", .{}),
|
||||
else => return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangUnaryOperator_getBeginLoc(stmt), "unsupported C translation {}", .{ZigClangUnaryOperator_getOpcode(stmt)}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2353,13 +2354,129 @@ fn transCreatePostCrement(
|
||||
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);
|
||||
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 transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
|
||||
switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
|
||||
.MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMultWrap, .AsteriskPercentEqual, "*%=", .MultWrap, .AsteriskPercent, "*%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMult, .AsteriskEqual, "*=", .Mult, .Asterisk, "*", used),
|
||||
.AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used),
|
||||
.SubAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
|
||||
.ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used),
|
||||
.ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used),
|
||||
.AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used),
|
||||
.XorAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitXor, .CaretEqual, "^=", .BitXor, .Caret, "^", used),
|
||||
.OrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitOr, .PipeEqual, "|=", .BitOr, .Pipe, "|", used),
|
||||
else => return revertAndWarn(
|
||||
rp,
|
||||
error.UnsupportedTranslation,
|
||||
ZigClangCompoundAssignOperator_getBeginLoc(stmt),
|
||||
"unsupported C translation {}",
|
||||
.{ZigClangCompoundAssignOperator_getOpcode(stmt)},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn transCreateCompoundAssign(
|
||||
rp: RestorePoint,
|
||||
scope: *Scope,
|
||||
stmt: *const ZigClangCompoundAssignOperator,
|
||||
assign_op: ast.Node.InfixOp.Op,
|
||||
assign_tok_id: std.zig.Token.Id,
|
||||
assign_bytes: []const u8,
|
||||
bin_op: ast.Node.InfixOp.Op,
|
||||
bin_tok_id: std.zig.Token.Id,
|
||||
bin_bytes: []const u8,
|
||||
used: ResultUsed,
|
||||
) TransError!*ast.Node {
|
||||
const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;
|
||||
const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
|
||||
const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
|
||||
const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
|
||||
if (used == .unused) {
|
||||
// common case
|
||||
// c: lhs += rhs
|
||||
// zig: lhs += rhs
|
||||
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
|
||||
const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
|
||||
var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
|
||||
|
||||
if (is_shift) {
|
||||
const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
|
||||
const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
|
||||
try as_node.params.push(rhs_type);
|
||||
_ = try appendToken(rp.c, .Comma, ",");
|
||||
try as_node.params.push(rhs_node);
|
||||
as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
rhs_node = &as_node.base;
|
||||
}
|
||||
if (scope.id != .Condition)
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
return transCreateNodeInfixOp(rp, scope, lhs_node, assign_op, eq_token, rhs_node, .used, false);
|
||||
}
|
||||
// worst case
|
||||
// c: lhs += rhs
|
||||
// zig: (blk: {
|
||||
// zig: const _ref = &lhs;
|
||||
// zig: _ref.* = _ref.* + rhs;
|
||||
// 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 addr_node = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
|
||||
addr_node.rhs = try transExpr(rp, scope, lhs, .used, .l_value);
|
||||
node.init_node = &addr_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 bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
|
||||
var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
|
||||
if (is_shift) {
|
||||
const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
|
||||
const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
|
||||
try as_node.params.push(rhs_type);
|
||||
_ = try appendToken(rp.c, .Comma, ",");
|
||||
try as_node.params.push(rhs_node);
|
||||
as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
rhs_node = &as_node.base;
|
||||
}
|
||||
const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
|
||||
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
|
||||
const eq_token = try appendToken(rp.c, .Equal, "=");
|
||||
const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .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 transCPtrCast(
|
||||
rp: RestorePoint,
|
||||
loc: ZigClangSourceLocation,
|
||||
@ -2585,7 +2702,7 @@ fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigC
|
||||
const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math");
|
||||
const outer_field_access = try transCreateNodeFieldAccess(rp.c, inner_field_access, "Log2Int");
|
||||
const log2int_fn_call = try transCreateNodeFnCall(rp.c, outer_field_access);
|
||||
try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node);
|
||||
try @fieldParentPtr(ast.Node.SuffixOp, "base", &log2int_fn_call.base).op.Call.params.push(zig_type_node);
|
||||
log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")");
|
||||
|
||||
return &log2int_fn_call.base;
|
||||
@ -3317,7 +3434,7 @@ fn transCreateNodeShiftOp(
|
||||
const lhs_expr = ZigClangBinaryOperator_getLHS(stmt);
|
||||
const rhs_expr = ZigClangBinaryOperator_getRHS(stmt);
|
||||
const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
|
||||
// lhs >> u5(rh)
|
||||
// lhs >> @as(u5, rh)
|
||||
|
||||
const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value);
|
||||
const op_token = try appendToken(rp.c, op_tok_id, bytes);
|
||||
|
||||
@ -1830,6 +1830,207 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("shift right assign",
|
||||
\\int log2(unsigned a) {
|
||||
\\ int i = 0;
|
||||
\\ while (a > 0) {
|
||||
\\ a >>= 1;
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{// TODO function arguments should be copied
|
||||
\\pub export fn log2(a: c_uint) c_int {
|
||||
\\ var i: c_int = 0;
|
||||
\\ while ((a > @as(c_uint, 0))) {
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("shift right assign with a fixed size type",
|
||||
\\#include <stdint.h>
|
||||
\\int log2(uint32_t a) {
|
||||
\\ int i = 0;
|
||||
\\ while (a > 0) {
|
||||
\\ a >>= 1;
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(a: u32) c_int {
|
||||
\\ var i: c_int = 0;
|
||||
\\ while ((a > @as(c_uint, 0))) {
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("compound assignment operators",
|
||||
\\void foo(void) {
|
||||
\\ int a = 0;
|
||||
\\ a += (a += 1);
|
||||
\\ a -= (a -= 1);
|
||||
\\ a *= (a *= 1);
|
||||
\\ a &= (a &= 1);
|
||||
\\ a |= (a |= 1);
|
||||
\\ a ^= (a ^= 1);
|
||||
\\ a >>= (a >>= 1);
|
||||
\\ a <<= (a <<= 1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = 0;
|
||||
\\ a += (blk: {
|
||||
\\ const _ref_1 = &a;
|
||||
\\ _ref_1.* = _ref_1.* + 1;
|
||||
\\ break :blk _ref_1.*;
|
||||
\\ });
|
||||
\\ a -= (blk: {
|
||||
\\ const _ref_2 = &a;
|
||||
\\ _ref_2.* = _ref_2.* - 1;
|
||||
\\ break :blk _ref_2.*;
|
||||
\\ });
|
||||
\\ a *= (blk: {
|
||||
\\ const _ref_3 = &a;
|
||||
\\ _ref_3.* = _ref_3.* * 1;
|
||||
\\ break :blk _ref_3.*;
|
||||
\\ });
|
||||
\\ a &= (blk: {
|
||||
\\ const _ref_4 = &a;
|
||||
\\ _ref_4.* = _ref_4.* & 1;
|
||||
\\ break :blk _ref_4.*;
|
||||
\\ });
|
||||
\\ a |= (blk: {
|
||||
\\ const _ref_5 = &a;
|
||||
\\ _ref_5.* = _ref_5.* | 1;
|
||||
\\ break :blk _ref_5.*;
|
||||
\\ });
|
||||
\\ a ^= (blk: {
|
||||
\\ const _ref_6 = &a;
|
||||
\\ _ref_6.* = _ref_6.* ^ 1;
|
||||
\\ break :blk _ref_6.*;
|
||||
\\ });
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), (blk: {
|
||||
\\ const _ref_7 = &a;
|
||||
\\ _ref_7.* = _ref_7.* >> @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ break :blk _ref_7.*;
|
||||
\\ }));
|
||||
\\ a <<= @as(@import("std").math.Log2Int(c_int), (blk: {
|
||||
\\ const _ref_8 = &a;
|
||||
\\ _ref_8.* = _ref_8.* << @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ break :blk _ref_8.*;
|
||||
\\ }));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("compound assignment operators unsigned",
|
||||
\\void foo(void) {
|
||||
\\ unsigned a = 0;
|
||||
\\ a += (a += 1);
|
||||
\\ a -= (a -= 1);
|
||||
\\ a *= (a *= 1);
|
||||
\\ a &= (a &= 1);
|
||||
\\ a |= (a |= 1);
|
||||
\\ a ^= (a ^= 1);
|
||||
\\ a >>= (a >>= 1);
|
||||
\\ a <<= (a <<= 1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_uint = @as(c_uint, 0);
|
||||
\\ a +%= (blk: {
|
||||
\\ const _ref_1 = &a;
|
||||
\\ _ref_1.* = _ref_1.* +% @as(c_uint, 1);
|
||||
\\ break :blk _ref_1.*;
|
||||
\\ });
|
||||
\\ a -%= (blk: {
|
||||
\\ const _ref_2 = &a;
|
||||
\\ _ref_2.* = _ref_2.* -% @as(c_uint, 1);
|
||||
\\ break :blk _ref_2.*;
|
||||
\\ });
|
||||
\\ a *%= (blk: {
|
||||
\\ const _ref_3 = &a;
|
||||
\\ _ref_3.* = _ref_3.* *% @as(c_uint, 1);
|
||||
\\ break :blk _ref_3.*;
|
||||
\\ });
|
||||
\\ a &= (blk: {
|
||||
\\ const _ref_4 = &a;
|
||||
\\ _ref_4.* = _ref_4.* & @as(c_uint, 1);
|
||||
\\ break :blk _ref_4.*;
|
||||
\\ });
|
||||
\\ a |= (blk: {
|
||||
\\ const _ref_5 = &a;
|
||||
\\ _ref_5.* = _ref_5.* | @as(c_uint, 1);
|
||||
\\ break :blk _ref_5.*;
|
||||
\\ });
|
||||
\\ a ^= (blk: {
|
||||
\\ const _ref_6 = &a;
|
||||
\\ _ref_6.* = _ref_6.* ^ @as(c_uint, 1);
|
||||
\\ break :blk _ref_6.*;
|
||||
\\ });
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_uint), (blk: {
|
||||
\\ const _ref_7 = &a;
|
||||
\\ _ref_7.* = _ref_7.* >> @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ break :blk _ref_7.*;
|
||||
\\ }));
|
||||
\\ a <<= @as(@import("std").math.Log2Int(c_uint), (blk: {
|
||||
\\ const _ref_8 = &a;
|
||||
\\ _ref_8.* = _ref_8.* << @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ break :blk _ref_8.*;
|
||||
\\ }));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("post 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;
|
||||
\\ const _tmp_2 = _ref_1.*;
|
||||
\\ _ref_1.* += 1;
|
||||
\\ break :blk _tmp_2;
|
||||
\\ };
|
||||
\\ i = blk: {
|
||||
\\ const _ref_3 = &i;
|
||||
\\ const _tmp_4 = _ref_3.*;
|
||||
\\ _ref_3.* -= 1;
|
||||
\\ break :blk _tmp_4;
|
||||
\\ };
|
||||
\\ u = blk: {
|
||||
\\ const _ref_5 = &u;
|
||||
\\ const _tmp_6 = _ref_5.*;
|
||||
\\ _ref_5.* +%= 1;
|
||||
\\ break :blk _tmp_6;
|
||||
\\ };
|
||||
\\ u = blk: {
|
||||
\\ const _ref_7 = &u;
|
||||
\\ const _tmp_8 = _ref_7.*;
|
||||
\\ _ref_7.* -%= 1;
|
||||
\\ break :blk _tmp_8;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
cases.add("macro defines string literal with hex",
|
||||
@ -1856,45 +2057,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const FOO_CHAR = 63;
|
||||
});
|
||||
|
||||
cases.addC("shift right assign",
|
||||
\\int log2(unsigned a) {
|
||||
\\ int i = 0;
|
||||
\\ while (a > 0) {
|
||||
\\ a >>= 1;
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(_arg_a: c_uint) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var i: c_int = 0;
|
||||
\\ while (a > @as(c_uint, 0)) {
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_uint), 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("shift right assign with a fixed size type",
|
||||
\\#include <stdint.h>
|
||||
\\int log2(uint32_t a) {
|
||||
\\ int i = 0;
|
||||
\\ while (a > 0) {
|
||||
\\ a >>= 1;
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(_arg_a: u32) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var i: c_int = 0;
|
||||
\\ while (a > @as(c_uint, 0)) {
|
||||
\\ a >>= @as(u5, 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("__extension__ cast",
|
||||
\\int foo(void) {
|
||||
\\ return __extension__ 1;
|
||||
@ -1905,170 +2067,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("compound assignment operators",
|
||||
\\void foo(void) {
|
||||
\\ int a = 0;
|
||||
\\ a += (a += 1);
|
||||
\\ a -= (a -= 1);
|
||||
\\ a *= (a *= 1);
|
||||
\\ a &= (a &= 1);
|
||||
\\ a |= (a |= 1);
|
||||
\\ a ^= (a ^= 1);
|
||||
\\ a >>= (a >>= 1);
|
||||
\\ a <<= (a <<= 1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = 0;
|
||||
\\ a += (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* + 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a -= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* - 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a *= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* * 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a &= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* & 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a |= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* | 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a ^= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* ^ 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_int), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\ a <<= @as(@import("std").math.Log2Int(c_int), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_int), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("compound assignment operators unsigned",
|
||||
\\void foo(void) {
|
||||
\\ unsigned a = 0;
|
||||
\\ a += (a += 1);
|
||||
\\ a -= (a -= 1);
|
||||
\\ a *= (a *= 1);
|
||||
\\ a &= (a &= 1);
|
||||
\\ a |= (a |= 1);
|
||||
\\ a ^= (a ^= 1);
|
||||
\\ a >>= (a >>= 1);
|
||||
\\ a <<= (a <<= 1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_uint = @as(c_uint, 0);
|
||||
\\ a +%= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* +% @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a -%= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* -% @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a *%= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* *% @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a &= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* & @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a |= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* | @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a ^= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* ^ @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_uint), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_uint), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\ a <<= @as(@import("std").math.Log2Int(c_uint), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_uint), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("post 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;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* += 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\ i = (x: {
|
||||
\\ const _ref = &i;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* -= 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\ u = (x: {
|
||||
\\ const _ref = &u;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* +%= 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\ u = (x: {
|
||||
\\ const _ref = &u;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* -%= 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("implicit casts",
|
||||
\\#include <stdbool.h>
|
||||
\\
|
||||
@ -2789,4 +2787,207 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ });
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("shift right assign",
|
||||
\\int log2(unsigned a) {
|
||||
\\ int i = 0;
|
||||
\\ while (a > 0) {
|
||||
\\ a >>= 1;
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(_arg_a: c_uint) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var i: c_int = 0;
|
||||
\\ while (a > @as(c_uint, 0)) {
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_uint), 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("shift right assign with a fixed size type",
|
||||
\\#include <stdint.h>
|
||||
\\int log2(uint32_t a) {
|
||||
\\ int i = 0;
|
||||
\\ while (a > 0) {
|
||||
\\ a >>= 1;
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(_arg_a: u32) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var i: c_int = 0;
|
||||
\\ while (a > @as(c_uint, 0)) {
|
||||
\\ a >>= @as(u5, 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("compound assignment operators",
|
||||
\\void foo(void) {
|
||||
\\ int a = 0;
|
||||
\\ a += (a += 1);
|
||||
\\ a -= (a -= 1);
|
||||
\\ a *= (a *= 1);
|
||||
\\ a &= (a &= 1);
|
||||
\\ a |= (a |= 1);
|
||||
\\ a ^= (a ^= 1);
|
||||
\\ a >>= (a >>= 1);
|
||||
\\ a <<= (a <<= 1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = 0;
|
||||
\\ a += (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* + 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a -= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* - 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a *= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* * 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a &= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* & 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a |= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* | 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a ^= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* ^ 1);
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_int), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\ a <<= @as(@import("std").math.Log2Int(c_int), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_int), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("compound assignment operators unsigned",
|
||||
\\void foo(void) {
|
||||
\\ unsigned a = 0;
|
||||
\\ a += (a += 1);
|
||||
\\ a -= (a -= 1);
|
||||
\\ a *= (a *= 1);
|
||||
\\ a &= (a &= 1);
|
||||
\\ a |= (a |= 1);
|
||||
\\ a ^= (a ^= 1);
|
||||
\\ a >>= (a >>= 1);
|
||||
\\ a <<= (a <<= 1);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_uint = @as(c_uint, 0);
|
||||
\\ a +%= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* +% @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a -%= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* -% @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a *%= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* *% @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a &= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* & @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a |= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* | @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a ^= (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* ^ @as(c_uint, 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ });
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_uint), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_uint), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\ a <<= @as(@import("std").math.Log2Int(c_uint), (x: {
|
||||
\\ const _ref = &a;
|
||||
\\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_uint), 1));
|
||||
\\ break :x _ref.*;
|
||||
\\ }));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("post 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;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* += 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\ i = (x: {
|
||||
\\ const _ref = &i;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* -= 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\ u = (x: {
|
||||
\\ const _ref = &u;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* +%= 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\ u = (x: {
|
||||
\\ const _ref = &u;
|
||||
\\ const _tmp = _ref.*;
|
||||
\\ _ref.* -%= 1;
|
||||
\\ break :x _tmp;
|
||||
\\ });
|
||||
\\}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user