authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-19 16:07:33+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-19 16:13:28+02:00
logf837c7c9cd8f355aeea1dea1e9b328820802ee34
tree6978b63ecc78f994fdd0ab777d2b9289db6fadae
parent6cd402f1b44247c2e990aab7c7a1ce32f0f8d53a
signature Commit is signed but in an unrecognized format.

translate-c-2 compound assign


5 files changed, 494 insertions(+), 168 deletions(-)

lib/std/zig/ast.zig+12-12
......@@ -1431,13 +1431,13 @@ pub const Node = struct {
14311431 AssignBitShiftRight,
14321432 AssignBitXor,
14331433 AssignDiv,
1434 AssignMinus,
1435 AssignMinusWrap,
1434 AssignSub,
1435 AssignSubWrap,
14361436 AssignMod,
1437 AssignPlus,
1438 AssignPlusWrap,
1439 AssignTimes,
1440 AssignTimesWarp,
1437 AssignAdd,
1438 AssignAddWrap,
1439 AssignMult,
1440 AssignMultWrap,
14411441 BangEqual,
14421442 BitAnd,
14431443 BitOr,
......@@ -1490,13 +1490,13 @@ pub const Node = struct {
14901490 Op.AssignBitShiftRight,
14911491 Op.AssignBitXor,
14921492 Op.AssignDiv,
1493 Op.AssignMinus,
1494 Op.AssignMinusWrap,
1493 Op.AssignSub,
1494 Op.AssignSubWrap,
14951495 Op.AssignMod,
1496 Op.AssignPlus,
1497 Op.AssignPlusWrap,
1498 Op.AssignTimes,
1499 Op.AssignTimesWarp,
1496 Op.AssignAdd,
1497 Op.AssignAddWrap,
1498 Op.AssignMult,
1499 Op.AssignMultWrap,
15001500 Op.BangEqual,
15011501 Op.BitAnd,
15021502 Op.BitOr,
lib/std/zig/parse.zig+6-6
......@@ -1981,19 +1981,19 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19811981
19821982 const token = nextToken(it);
19831983 const op = switch (token.ptr.id) {
1984 .AsteriskEqual => Op{ .AssignTimes = {} },
1984 .AsteriskEqual => Op{ .AssignMult = {} },
19851985 .SlashEqual => Op{ .AssignDiv = {} },
19861986 .PercentEqual => Op{ .AssignMod = {} },
1987 .PlusEqual => Op{ .AssignPlus = {} },
1988 .MinusEqual => Op{ .AssignMinus = {} },
1987 .PlusEqual => Op{ .AssignAdd = {} },
1988 .MinusEqual => Op{ .AssignSub = {} },
19891989 .AngleBracketAngleBracketLeftEqual => Op{ .AssignBitShiftLeft = {} },
19901990 .AngleBracketAngleBracketRightEqual => Op{ .AssignBitShiftRight = {} },
19911991 .AmpersandEqual => Op{ .AssignBitAnd = {} },
19921992 .CaretEqual => Op{ .AssignBitXor = {} },
19931993 .PipeEqual => Op{ .AssignBitOr = {} },
1994 .AsteriskPercentEqual => Op{ .AssignTimesWarp = {} },
1995 .PlusPercentEqual => Op{ .AssignPlusWrap = {} },
1996 .MinusPercentEqual => Op{ .AssignMinusWrap = {} },
1994 .AsteriskPercentEqual => Op{ .AssignMultWrap = {} },
1995 .PlusPercentEqual => Op{ .AssignAddWrap = {} },
1996 .MinusPercentEqual => Op{ .AssignSubWrap = {} },
19971997 .Equal => Op{ .Assign = {} },
19981998 else => {
19991999 putBackToken(it, token.index);
src-self-hosted/clang.zig+8
......@@ -1120,3 +1120,11 @@ pub extern fn ZigClangUnaryOperator_getOpcode(*const ZigClangUnaryOperator) ZigC
11201120pub extern fn ZigClangUnaryOperator_getType(*const ZigClangUnaryOperator) ZigClangQualType;
11211121pub extern fn ZigClangUnaryOperator_getSubExpr(*const ZigClangUnaryOperator) *const ZigClangExpr;
11221122pub extern fn ZigClangUnaryOperator_getBeginLoc(*const ZigClangUnaryOperator) ZigClangSourceLocation;
1123
1124pub extern fn ZigClangCompoundAssignOperator_getType(*const ZigClangCompoundAssignOperator) ZigClangQualType;
1125pub extern fn ZigClangCompoundAssignOperator_getComputationLHSType(*const ZigClangCompoundAssignOperator) ZigClangQualType;
1126pub extern fn ZigClangCompoundAssignOperator_getComputationResultType(*const ZigClangCompoundAssignOperator) ZigClangQualType;
1127pub extern fn ZigClangCompoundAssignOperator_getBeginLoc(*const ZigClangCompoundAssignOperator) ZigClangSourceLocation;
1128pub extern fn ZigClangCompoundAssignOperator_getOpcode(*const ZigClangCompoundAssignOperator) ZigClangBO;
1129pub extern fn ZigClangCompoundAssignOperator_getLHS(*const ZigClangCompoundAssignOperator) *const ZigClangExpr;
1130pub extern fn ZigClangCompoundAssignOperator_getRHS(*const ZigClangCompoundAssignOperator) *const ZigClangExpr;
src-self-hosted/translate_c.zig+129-12
......@@ -898,6 +898,7 @@ fn transStmt(
898898 .CallExprClass => return transCallExpr(rp, scope, @ptrCast(*const ZigClangCallExpr, stmt), result_used),
899899 .UnaryExprOrTypeTraitExprClass => return transUnaryExprOrTypeTraitExpr(rp, scope, @ptrCast(*const ZigClangUnaryExprOrTypeTraitExpr, stmt), result_used),
900900 .UnaryOperatorClass => return transUnaryOperator(rp, scope, @ptrCast(*const ZigClangUnaryOperator, stmt), result_used),
901 .CompoundAssignOperatorClass => return transCompoundAssignOperator(rp, scope, @ptrCast(*const ZigClangCompoundAssignOperator, stmt), result_used),
901902 else => {
902903 return revertAndWarn(
903904 rp,
......@@ -2178,21 +2179,21 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
21782179 const op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
21792180 switch (ZigClangUnaryOperator_getOpcode(stmt)) {
21802181 .PostInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2181 return transCreatePostCrement(rp, scope, stmt, .AssignPlusWrap, .PlusPercentEqual, "+%=", used)
2182 return transCreatePostCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
21822183 else
2183 return transCreatePostCrement(rp, scope, stmt, .AssignPlus, .PlusEqual, "+=", used),
2184 return transCreatePostCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
21842185 .PostDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2185 return transCreatePostCrement(rp, scope, stmt, .AssignMinusWrap, .MinusPercentEqual, "-%=", used)
2186 return transCreatePostCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
21862187 else
2187 return transCreatePostCrement(rp, scope, stmt, .AssignMinus, .MinusEqual, "-=", used),
2188 return transCreatePostCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
21882189 .PreInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2189 return transCreatePreCrement(rp, scope, stmt, .AssignPlusWrap, .PlusPercentEqual, "+%=", used)
2190 return transCreatePreCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
21902191 else
2191 return transCreatePreCrement(rp, scope, stmt, .AssignPlus, .PlusEqual, "+=", used),
2192 return transCreatePreCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
21922193 .PreDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2193 return transCreatePreCrement(rp, scope, stmt, .AssignMinusWrap, .MinusPercentEqual, "-%=", used)
2194 return transCreatePreCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
21942195 else
2195 return transCreatePreCrement(rp, scope, stmt, .AssignMinus, .MinusEqual, "-=", used),
2196 return transCreatePreCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
21962197 .AddrOf => {
21972198 const op_node = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
21982199 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
22322233 op_node.rhs = try transBoolExpr(rp, scope, op_expr, .used, .r_value, true);
22332234 return &op_node.base;
22342235 },
2235 else => return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangUnaryOperator_getBeginLoc(stmt), "TODO handle C translation UO_Real", .{}),
2236 else => return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangUnaryOperator_getBeginLoc(stmt), "unsupported C translation {}", .{ZigClangUnaryOperator_getOpcode(stmt)}),
22362237 }
22372238}
22382239
......@@ -2353,13 +2354,129 @@ fn transCreatePostCrement(
23532354 try block_scope.block_node.statements.push(assign);
23542355
23552356 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
2356 break_node.rhs = try transCreateNodeIdentifier(rp.c,tmp);
2357 break_node.rhs = try transCreateNodeIdentifier(rp.c, tmp);
23572358 try block_scope.block_node.statements.push(&break_node.base);
23582359 _ = try appendToken(rp.c, .Semicolon, ";");
23592360 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
23602361 return &block_scope.block_node.base;
23612362}
23622363
2364fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
2365 switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
2366 .MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2367 return transCreateCompoundAssign(rp, scope, stmt, .AssignMultWrap, .AsteriskPercentEqual, "*%=", .MultWrap, .AsteriskPercent, "*%", used)
2368 else
2369 return transCreateCompoundAssign(rp, scope, stmt, .AssignMult, .AsteriskEqual, "*=", .Mult, .Asterisk, "*", used),
2370 .AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2371 return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
2372 else
2373 return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used),
2374 .SubAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2375 return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
2376 else
2377 return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
2378 .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used),
2379 .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used),
2380 .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used),
2381 .XorAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitXor, .CaretEqual, "^=", .BitXor, .Caret, "^", used),
2382 .OrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitOr, .PipeEqual, "|=", .BitOr, .Pipe, "|", used),
2383 else => return revertAndWarn(
2384 rp,
2385 error.UnsupportedTranslation,
2386 ZigClangCompoundAssignOperator_getBeginLoc(stmt),
2387 "unsupported C translation {}",
2388 .{ZigClangCompoundAssignOperator_getOpcode(stmt)},
2389 ),
2390 }
2391}
2392
2393fn transCreateCompoundAssign(
2394 rp: RestorePoint,
2395 scope: *Scope,
2396 stmt: *const ZigClangCompoundAssignOperator,
2397 assign_op: ast.Node.InfixOp.Op,
2398 assign_tok_id: std.zig.Token.Id,
2399 assign_bytes: []const u8,
2400 bin_op: ast.Node.InfixOp.Op,
2401 bin_tok_id: std.zig.Token.Id,
2402 bin_bytes: []const u8,
2403 used: ResultUsed,
2404) TransError!*ast.Node {
2405 const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;
2406 const lhs = ZigClangCompoundAssignOperator_getLHS(stmt);
2407 const rhs = ZigClangCompoundAssignOperator_getRHS(stmt);
2408 const loc = ZigClangCompoundAssignOperator_getBeginLoc(stmt);
2409 if (used == .unused) {
2410 // common case
2411 // c: lhs += rhs
2412 // zig: lhs += rhs
2413 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
2414 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
2415 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
2416
2417 if (is_shift) {
2418 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
2419 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
2420 try as_node.params.push(rhs_type);
2421 _ = try appendToken(rp.c, .Comma, ",");
2422 try as_node.params.push(rhs_node);
2423 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2424 rhs_node = &as_node.base;
2425 }
2426 if (scope.id != .Condition)
2427 _ = try appendToken(rp.c, .Semicolon, ";");
2428 return transCreateNodeInfixOp(rp, scope, lhs_node, assign_op, eq_token, rhs_node, .used, false);
2429 }
2430 // worst case
2431 // c: lhs += rhs
2432 // zig: (blk: {
2433 // zig: const _ref = &lhs;
2434 // zig: _ref.* = _ref.* + rhs;
2435 // zig: break :blk _ref.*
2436 // zig: })
2437 const block_scope = try Scope.Block.init(rp.c, scope, "blk");
2438 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
2439 const ref = try std.fmt.allocPrint(rp.c.a(), "_ref_{}", .{rp.c.getMangle()});
2440
2441 const node = try transCreateNodeVarDecl(rp.c, false, true, ref);
2442 node.eq_token = try appendToken(rp.c, .Equal, "=");
2443 const addr_node = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
2444 addr_node.rhs = try transExpr(rp, scope, lhs, .used, .l_value);
2445 node.init_node = &addr_node.base;
2446 node.semicolon_token = try appendToken(rp.c, .Semicolon, ";");
2447 try block_scope.block_node.statements.push(&node.base);
2448
2449 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
2450 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
2451 _ = try appendToken(rp.c, .Semicolon, ";");
2452 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
2453 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
2454 if (is_shift) {
2455 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
2456 const rhs_type = try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc);
2457 try as_node.params.push(rhs_type);
2458 _ = try appendToken(rp.c, .Comma, ",");
2459 try as_node.params.push(rhs_node);
2460 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2461 rhs_node = &as_node.base;
2462 }
2463 const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
2464
2465 _ = try appendToken(rp.c, .Semicolon, ";");
2466
2467 const eq_token = try appendToken(rp.c, .Equal, "=");
2468 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, eq_token, rhs_bin, .used, false);
2469 try block_scope.block_node.statements.push(assign);
2470
2471 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
2472 break_node.rhs = ref_node;
2473 try block_scope.block_node.statements.push(&break_node.base);
2474 block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
2475 // semicolon must immediately follow rbrace because it is the last token in a block
2476 _ = try appendToken(rp.c, .Semicolon, ";");
2477 return &block_scope.block_node.base;
2478}
2479
23632480fn transCPtrCast(
23642481 rp: RestorePoint,
23652482 loc: ZigClangSourceLocation,
......@@ -2585,7 +2702,7 @@ fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigC
25852702 const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math");
25862703 const outer_field_access = try transCreateNodeFieldAccess(rp.c, inner_field_access, "Log2Int");
25872704 const log2int_fn_call = try transCreateNodeFnCall(rp.c, outer_field_access);
2588 try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node);
2705 try @fieldParentPtr(ast.Node.SuffixOp, "base", &log2int_fn_call.base).op.Call.params.push(zig_type_node);
25892706 log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")");
25902707
25912708 return &log2int_fn_call.base;
......@@ -3317,7 +3434,7 @@ fn transCreateNodeShiftOp(
33173434 const lhs_expr = ZigClangBinaryOperator_getLHS(stmt);
33183435 const rhs_expr = ZigClangBinaryOperator_getRHS(stmt);
33193436 const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
3320 // lhs >> u5(rh)
3437 // lhs >> @as(u5, rh)
33213438
33223439 const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value);
33233440 const op_token = try appendToken(rp.c, op_tok_id, bytes);
test/translate_c.zig+339-138
......@@ -1830,33 +1830,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18301830 \\}
18311831 });
18321832
1833 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
1834
1835 cases.add("macro defines string literal with hex",
1836 \\#define FOO "aoeu\xab derp"
1837 \\#define FOO2 "aoeu\x0007a derp"
1838 \\#define FOO_CHAR '\xfF'
1839 , &[_][]const u8{
1840 \\pub const FOO = "aoeu\xab derp";
1841 ,
1842 \\pub const FOO2 = "aoeuz derp";
1843 ,
1844 \\pub const FOO_CHAR = 255;
1845 });
1846
1847 cases.add("macro defines string literal with octal",
1848 \\#define FOO "aoeu\023 derp"
1849 \\#define FOO2 "aoeu\0234 derp"
1850 \\#define FOO_CHAR '\077'
1851 , &[_][]const u8{
1852 \\pub const FOO = "aoeu\x13 derp";
1853 ,
1854 \\pub const FOO2 = "aoeu\x134 derp";
1855 ,
1856 \\pub const FOO_CHAR = 63;
1857 });
1858
1859 cases.addC("shift right assign",
1833 cases.add_2("shift right assign",
18601834 \\int log2(unsigned a) {
18611835 \\ int i = 0;
18621836 \\ while (a > 0) {
......@@ -1864,18 +1838,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18641838 \\ }
18651839 \\ return i;
18661840 \\}
1867 , &[_][]const u8{
1868 \\pub export fn log2(_arg_a: c_uint) c_int {
1869 \\ var a = _arg_a;
1841 , &[_][]const u8{// TODO function arguments should be copied
1842 \\pub export fn log2(a: c_uint) c_int {
18701843 \\ var i: c_int = 0;
1871 \\ while (a > @as(c_uint, 0)) {
1872 \\ a >>= @as(@import("std").math.Log2Int(c_uint), 1);
1844 \\ while ((a > @as(c_uint, 0))) {
1845 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
18731846 \\ }
18741847 \\ return i;
18751848 \\}
18761849 });
18771850
1878 cases.addC("shift right assign with a fixed size type",
1851 cases.add_2("shift right assign with a fixed size type",
18791852 \\#include <stdint.h>
18801853 \\int log2(uint32_t a) {
18811854 \\ int i = 0;
......@@ -1885,27 +1858,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18851858 \\ return i;
18861859 \\}
18871860 , &[_][]const u8{
1888 \\pub export fn log2(_arg_a: u32) c_int {
1889 \\ var a = _arg_a;
1861 \\pub export fn log2(a: u32) c_int {
18901862 \\ var i: c_int = 0;
1891 \\ while (a > @as(c_uint, 0)) {
1892 \\ a >>= @as(u5, 1);
1863 \\ while ((a > @as(c_uint, 0))) {
1864 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
18931865 \\ }
18941866 \\ return i;
18951867 \\}
18961868 });
18971869
1898 cases.addC("__extension__ cast",
1899 \\int foo(void) {
1900 \\ return __extension__ 1;
1901 \\}
1902 , &[_][]const u8{
1903 \\pub export fn foo() c_int {
1904 \\ return 1;
1905 \\}
1906 });
1907
1908 cases.addC("compound assignment operators",
1870 cases.add_2("compound assignment operators",
19091871 \\void foo(void) {
19101872 \\ int a = 0;
19111873 \\ a += (a += 1);
......@@ -1920,50 +1882,50 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
19201882 , &[_][]const u8{
19211883 \\pub export fn foo() void {
19221884 \\ var a: c_int = 0;
1923 \\ a += (x: {
1924 \\ const _ref = &a;
1925 \\ _ref.* = (_ref.* + 1);
1926 \\ break :x _ref.*;
1885 \\ a += (blk: {
1886 \\ const _ref_1 = &a;
1887 \\ _ref_1.* = _ref_1.* + 1;
1888 \\ break :blk _ref_1.*;
19271889 \\ });
1928 \\ a -= (x: {
1929 \\ const _ref = &a;
1930 \\ _ref.* = (_ref.* - 1);
1931 \\ break :x _ref.*;
1890 \\ a -= (blk: {
1891 \\ const _ref_2 = &a;
1892 \\ _ref_2.* = _ref_2.* - 1;
1893 \\ break :blk _ref_2.*;
19321894 \\ });
1933 \\ a *= (x: {
1934 \\ const _ref = &a;
1935 \\ _ref.* = (_ref.* * 1);
1936 \\ break :x _ref.*;
1895 \\ a *= (blk: {
1896 \\ const _ref_3 = &a;
1897 \\ _ref_3.* = _ref_3.* * 1;
1898 \\ break :blk _ref_3.*;
19371899 \\ });
1938 \\ a &= (x: {
1939 \\ const _ref = &a;
1940 \\ _ref.* = (_ref.* & 1);
1941 \\ break :x _ref.*;
1900 \\ a &= (blk: {
1901 \\ const _ref_4 = &a;
1902 \\ _ref_4.* = _ref_4.* & 1;
1903 \\ break :blk _ref_4.*;
19421904 \\ });
1943 \\ a |= (x: {
1944 \\ const _ref = &a;
1945 \\ _ref.* = (_ref.* | 1);
1946 \\ break :x _ref.*;
1905 \\ a |= (blk: {
1906 \\ const _ref_5 = &a;
1907 \\ _ref_5.* = _ref_5.* | 1;
1908 \\ break :blk _ref_5.*;
19471909 \\ });
1948 \\ a ^= (x: {
1949 \\ const _ref = &a;
1950 \\ _ref.* = (_ref.* ^ 1);
1951 \\ break :x _ref.*;
1910 \\ a ^= (blk: {
1911 \\ const _ref_6 = &a;
1912 \\ _ref_6.* = _ref_6.* ^ 1;
1913 \\ break :blk _ref_6.*;
19521914 \\ });
1953 \\ a >>= @as(@import("std").math.Log2Int(c_int), (x: {
1954 \\ const _ref = &a;
1955 \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_int), 1));
1956 \\ break :x _ref.*;
1915 \\ a >>= @as(@import("std").math.Log2Int(c_int), (blk: {
1916 \\ const _ref_7 = &a;
1917 \\ _ref_7.* = _ref_7.* >> @as(@import("std").math.Log2Int(c_int), 1);
1918 \\ break :blk _ref_7.*;
19571919 \\ }));
1958 \\ a <<= @as(@import("std").math.Log2Int(c_int), (x: {
1959 \\ const _ref = &a;
1960 \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_int), 1));
1961 \\ break :x _ref.*;
1920 \\ a <<= @as(@import("std").math.Log2Int(c_int), (blk: {
1921 \\ const _ref_8 = &a;
1922 \\ _ref_8.* = _ref_8.* << @as(@import("std").math.Log2Int(c_int), 1);
1923 \\ break :blk _ref_8.*;
19621924 \\ }));
19631925 \\}
19641926 });
19651927
1966 cases.addC("compound assignment operators unsigned",
1928 cases.add_2("compound assignment operators unsigned",
19671929 \\void foo(void) {
19681930 \\ unsigned a = 0;
19691931 \\ a += (a += 1);
......@@ -1978,50 +1940,50 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
19781940 , &[_][]const u8{
19791941 \\pub export fn foo() void {
19801942 \\ var a: c_uint = @as(c_uint, 0);
1981 \\ a +%= (x: {
1982 \\ const _ref = &a;
1983 \\ _ref.* = (_ref.* +% @as(c_uint, 1));
1984 \\ break :x _ref.*;
1943 \\ a +%= (blk: {
1944 \\ const _ref_1 = &a;
1945 \\ _ref_1.* = _ref_1.* +% @as(c_uint, 1);
1946 \\ break :blk _ref_1.*;
19851947 \\ });
1986 \\ a -%= (x: {
1987 \\ const _ref = &a;
1988 \\ _ref.* = (_ref.* -% @as(c_uint, 1));
1989 \\ break :x _ref.*;
1948 \\ a -%= (blk: {
1949 \\ const _ref_2 = &a;
1950 \\ _ref_2.* = _ref_2.* -% @as(c_uint, 1);
1951 \\ break :blk _ref_2.*;
19901952 \\ });
1991 \\ a *%= (x: {
1992 \\ const _ref = &a;
1993 \\ _ref.* = (_ref.* *% @as(c_uint, 1));
1994 \\ break :x _ref.*;
1953 \\ a *%= (blk: {
1954 \\ const _ref_3 = &a;
1955 \\ _ref_3.* = _ref_3.* *% @as(c_uint, 1);
1956 \\ break :blk _ref_3.*;
19951957 \\ });
1996 \\ a &= (x: {
1997 \\ const _ref = &a;
1998 \\ _ref.* = (_ref.* & @as(c_uint, 1));
1999 \\ break :x _ref.*;
1958 \\ a &= (blk: {
1959 \\ const _ref_4 = &a;
1960 \\ _ref_4.* = _ref_4.* & @as(c_uint, 1);
1961 \\ break :blk _ref_4.*;
20001962 \\ });
2001 \\ a |= (x: {
2002 \\ const _ref = &a;
2003 \\ _ref.* = (_ref.* | @as(c_uint, 1));
2004 \\ break :x _ref.*;
1963 \\ a |= (blk: {
1964 \\ const _ref_5 = &a;
1965 \\ _ref_5.* = _ref_5.* | @as(c_uint, 1);
1966 \\ break :blk _ref_5.*;
20051967 \\ });
2006 \\ a ^= (x: {
2007 \\ const _ref = &a;
2008 \\ _ref.* = (_ref.* ^ @as(c_uint, 1));
2009 \\ break :x _ref.*;
1968 \\ a ^= (blk: {
1969 \\ const _ref_6 = &a;
1970 \\ _ref_6.* = _ref_6.* ^ @as(c_uint, 1);
1971 \\ break :blk _ref_6.*;
20101972 \\ });
2011 \\ a >>= @as(@import("std").math.Log2Int(c_uint), (x: {
2012 \\ const _ref = &a;
2013 \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_uint), 1));
2014 \\ break :x _ref.*;
1973 \\ a >>= @as(@import("std").math.Log2Int(c_uint), (blk: {
1974 \\ const _ref_7 = &a;
1975 \\ _ref_7.* = _ref_7.* >> @as(@import("std").math.Log2Int(c_int), 1);
1976 \\ break :blk _ref_7.*;
20151977 \\ }));
2016 \\ a <<= @as(@import("std").math.Log2Int(c_uint), (x: {
2017 \\ const _ref = &a;
2018 \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_uint), 1));
2019 \\ break :x _ref.*;
1978 \\ a <<= @as(@import("std").math.Log2Int(c_uint), (blk: {
1979 \\ const _ref_8 = &a;
1980 \\ _ref_8.* = _ref_8.* << @as(@import("std").math.Log2Int(c_int), 1);
1981 \\ break :blk _ref_8.*;
20201982 \\ }));
20211983 \\}
20221984 });
20231985
2024 cases.addC("post increment/decrement",
1986 cases.add_2("post increment/decrement",
20251987 \\void foo(void) {
20261988 \\ int i = 0;
20271989 \\ unsigned u = 0;
......@@ -2042,30 +2004,66 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20422004 \\ i -= 1;
20432005 \\ u +%= 1;
20442006 \\ u -%= 1;
2045 \\ i = (x: {
2046 \\ const _ref = &i;
2047 \\ const _tmp = _ref.*;
2048 \\ _ref.* += 1;
2049 \\ break :x _tmp;
2050 \\ });
2051 \\ i = (x: {
2052 \\ const _ref = &i;
2053 \\ const _tmp = _ref.*;
2054 \\ _ref.* -= 1;
2055 \\ break :x _tmp;
2056 \\ });
2057 \\ u = (x: {
2058 \\ const _ref = &u;
2059 \\ const _tmp = _ref.*;
2060 \\ _ref.* +%= 1;
2061 \\ break :x _tmp;
2062 \\ });
2063 \\ u = (x: {
2064 \\ const _ref = &u;
2065 \\ const _tmp = _ref.*;
2066 \\ _ref.* -%= 1;
2067 \\ break :x _tmp;
2068 \\ });
2007 \\ i = blk: {
2008 \\ const _ref_1 = &i;
2009 \\ const _tmp_2 = _ref_1.*;
2010 \\ _ref_1.* += 1;
2011 \\ break :blk _tmp_2;
2012 \\ };
2013 \\ i = blk: {
2014 \\ const _ref_3 = &i;
2015 \\ const _tmp_4 = _ref_3.*;
2016 \\ _ref_3.* -= 1;
2017 \\ break :blk _tmp_4;
2018 \\ };
2019 \\ u = blk: {
2020 \\ const _ref_5 = &u;
2021 \\ const _tmp_6 = _ref_5.*;
2022 \\ _ref_5.* +%= 1;
2023 \\ break :blk _tmp_6;
2024 \\ };
2025 \\ u = blk: {
2026 \\ const _ref_7 = &u;
2027 \\ const _tmp_8 = _ref_7.*;
2028 \\ _ref_7.* -%= 1;
2029 \\ break :blk _tmp_8;
2030 \\ };
2031 \\}
2032 });
2033
2034 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
2035
2036 cases.add("macro defines string literal with hex",
2037 \\#define FOO "aoeu\xab derp"
2038 \\#define FOO2 "aoeu\x0007a derp"
2039 \\#define FOO_CHAR '\xfF'
2040 , &[_][]const u8{
2041 \\pub const FOO = "aoeu\xab derp";
2042 ,
2043 \\pub const FOO2 = "aoeuz derp";
2044 ,
2045 \\pub const FOO_CHAR = 255;
2046 });
2047
2048 cases.add("macro defines string literal with octal",
2049 \\#define FOO "aoeu\023 derp"
2050 \\#define FOO2 "aoeu\0234 derp"
2051 \\#define FOO_CHAR '\077'
2052 , &[_][]const u8{
2053 \\pub const FOO = "aoeu\x13 derp";
2054 ,
2055 \\pub const FOO2 = "aoeu\x134 derp";
2056 ,
2057 \\pub const FOO_CHAR = 63;
2058 });
2059
2060 cases.addC("__extension__ cast",
2061 \\int foo(void) {
2062 \\ return __extension__ 1;
2063 \\}
2064 , &[_][]const u8{
2065 \\pub export fn foo() c_int {
2066 \\ return 1;
20692067 \\}
20702068 });
20712069
......@@ -2789,4 +2787,207 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
27892787 \\ });
27902788 \\}
27912789 });
2790
2791 cases.addC("shift right assign",
2792 \\int log2(unsigned a) {
2793 \\ int i = 0;
2794 \\ while (a > 0) {
2795 \\ a >>= 1;
2796 \\ }
2797 \\ return i;
2798 \\}
2799 , &[_][]const u8{
2800 \\pub export fn log2(_arg_a: c_uint) c_int {
2801 \\ var a = _arg_a;
2802 \\ var i: c_int = 0;
2803 \\ while (a > @as(c_uint, 0)) {
2804 \\ a >>= @as(@import("std").math.Log2Int(c_uint), 1);
2805 \\ }
2806 \\ return i;
2807 \\}
2808 });
2809
2810 cases.addC("shift right assign with a fixed size type",
2811 \\#include <stdint.h>
2812 \\int log2(uint32_t a) {
2813 \\ int i = 0;
2814 \\ while (a > 0) {
2815 \\ a >>= 1;
2816 \\ }
2817 \\ return i;
2818 \\}
2819 , &[_][]const u8{
2820 \\pub export fn log2(_arg_a: u32) c_int {
2821 \\ var a = _arg_a;
2822 \\ var i: c_int = 0;
2823 \\ while (a > @as(c_uint, 0)) {
2824 \\ a >>= @as(u5, 1);
2825 \\ }
2826 \\ return i;
2827 \\}
2828 });
2829
2830 cases.addC("compound assignment operators",
2831 \\void foo(void) {
2832 \\ int a = 0;
2833 \\ a += (a += 1);
2834 \\ a -= (a -= 1);
2835 \\ a *= (a *= 1);
2836 \\ a &= (a &= 1);
2837 \\ a |= (a |= 1);
2838 \\ a ^= (a ^= 1);
2839 \\ a >>= (a >>= 1);
2840 \\ a <<= (a <<= 1);
2841 \\}
2842 , &[_][]const u8{
2843 \\pub export fn foo() void {
2844 \\ var a: c_int = 0;
2845 \\ a += (x: {
2846 \\ const _ref = &a;
2847 \\ _ref.* = (_ref.* + 1);
2848 \\ break :x _ref.*;
2849 \\ });
2850 \\ a -= (x: {
2851 \\ const _ref = &a;
2852 \\ _ref.* = (_ref.* - 1);
2853 \\ break :x _ref.*;
2854 \\ });
2855 \\ a *= (x: {
2856 \\ const _ref = &a;
2857 \\ _ref.* = (_ref.* * 1);
2858 \\ break :x _ref.*;
2859 \\ });
2860 \\ a &= (x: {
2861 \\ const _ref = &a;
2862 \\ _ref.* = (_ref.* & 1);
2863 \\ break :x _ref.*;
2864 \\ });
2865 \\ a |= (x: {
2866 \\ const _ref = &a;
2867 \\ _ref.* = (_ref.* | 1);
2868 \\ break :x _ref.*;
2869 \\ });
2870 \\ a ^= (x: {
2871 \\ const _ref = &a;
2872 \\ _ref.* = (_ref.* ^ 1);
2873 \\ break :x _ref.*;
2874 \\ });
2875 \\ a >>= @as(@import("std").math.Log2Int(c_int), (x: {
2876 \\ const _ref = &a;
2877 \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_int), 1));
2878 \\ break :x _ref.*;
2879 \\ }));
2880 \\ a <<= @as(@import("std").math.Log2Int(c_int), (x: {
2881 \\ const _ref = &a;
2882 \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_int), 1));
2883 \\ break :x _ref.*;
2884 \\ }));
2885 \\}
2886 });
2887
2888 cases.addC("compound assignment operators unsigned",
2889 \\void foo(void) {
2890 \\ unsigned a = 0;
2891 \\ a += (a += 1);
2892 \\ a -= (a -= 1);
2893 \\ a *= (a *= 1);
2894 \\ a &= (a &= 1);
2895 \\ a |= (a |= 1);
2896 \\ a ^= (a ^= 1);
2897 \\ a >>= (a >>= 1);
2898 \\ a <<= (a <<= 1);
2899 \\}
2900 , &[_][]const u8{
2901 \\pub export fn foo() void {
2902 \\ var a: c_uint = @as(c_uint, 0);
2903 \\ a +%= (x: {
2904 \\ const _ref = &a;
2905 \\ _ref.* = (_ref.* +% @as(c_uint, 1));
2906 \\ break :x _ref.*;
2907 \\ });
2908 \\ a -%= (x: {
2909 \\ const _ref = &a;
2910 \\ _ref.* = (_ref.* -% @as(c_uint, 1));
2911 \\ break :x _ref.*;
2912 \\ });
2913 \\ a *%= (x: {
2914 \\ const _ref = &a;
2915 \\ _ref.* = (_ref.* *% @as(c_uint, 1));
2916 \\ break :x _ref.*;
2917 \\ });
2918 \\ a &= (x: {
2919 \\ const _ref = &a;
2920 \\ _ref.* = (_ref.* & @as(c_uint, 1));
2921 \\ break :x _ref.*;
2922 \\ });
2923 \\ a |= (x: {
2924 \\ const _ref = &a;
2925 \\ _ref.* = (_ref.* | @as(c_uint, 1));
2926 \\ break :x _ref.*;
2927 \\ });
2928 \\ a ^= (x: {
2929 \\ const _ref = &a;
2930 \\ _ref.* = (_ref.* ^ @as(c_uint, 1));
2931 \\ break :x _ref.*;
2932 \\ });
2933 \\ a >>= @as(@import("std").math.Log2Int(c_uint), (x: {
2934 \\ const _ref = &a;
2935 \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_uint), 1));
2936 \\ break :x _ref.*;
2937 \\ }));
2938 \\ a <<= @as(@import("std").math.Log2Int(c_uint), (x: {
2939 \\ const _ref = &a;
2940 \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_uint), 1));
2941 \\ break :x _ref.*;
2942 \\ }));
2943 \\}
2944 });
2945
2946 cases.addC("post increment/decrement",
2947 \\void foo(void) {
2948 \\ int i = 0;
2949 \\ unsigned u = 0;
2950 \\ i++;
2951 \\ i--;
2952 \\ u++;
2953 \\ u--;
2954 \\ i = i++;
2955 \\ i = i--;
2956 \\ u = u++;
2957 \\ u = u--;
2958 \\}
2959 , &[_][]const u8{
2960 \\pub export fn foo() void {
2961 \\ var i: c_int = 0;
2962 \\ var u: c_uint = @as(c_uint, 0);
2963 \\ i += 1;
2964 \\ i -= 1;
2965 \\ u +%= 1;
2966 \\ u -%= 1;
2967 \\ i = (x: {
2968 \\ const _ref = &i;
2969 \\ const _tmp = _ref.*;
2970 \\ _ref.* += 1;
2971 \\ break :x _tmp;
2972 \\ });
2973 \\ i = (x: {
2974 \\ const _ref = &i;
2975 \\ const _tmp = _ref.*;
2976 \\ _ref.* -= 1;
2977 \\ break :x _tmp;
2978 \\ });
2979 \\ u = (x: {
2980 \\ const _ref = &u;
2981 \\ const _tmp = _ref.*;
2982 \\ _ref.* +%= 1;
2983 \\ break :x _tmp;
2984 \\ });
2985 \\ u = (x: {
2986 \\ const _ref = &u;
2987 \\ const _tmp = _ref.*;
2988 \\ _ref.* -%= 1;
2989 \\ break :x _tmp;
2990 \\ });
2991 \\}
2992 });
27922993}