From c8c89648b0d98af07aad88a813a74ff650cf3bbe Mon Sep 17 00:00:00 2001 From: Merlyn Morgan-Graham Date: Sat, 14 Dec 2019 22:04:07 -0800 Subject: [PATCH] Add comparison and bitwise binary ops in translate-c-2 --- src-self-hosted/translate_c.zig | 88 +++++++++++++++++++++++++++++---- test/translate_c.zig | 52 +++++++++++++++++++ 2 files changed, 131 insertions(+), 9 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 9d011b1255..70ff1daf40 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -681,15 +681,85 @@ fn transBinaryOperator( }, .Shl, .Shr, - .LT, - .GT, - .LE, - .GE, - .EQ, - .NE, - .And, - .Xor, - .Or, + => return revertAndWarn( + rp, + error.UnsupportedTranslation, + ZigClangBinaryOperator_getBeginLoc(stmt), + "TODO: handle more C binary operators: {}", + .{op}, + ), + .LT => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .GT => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterThan, .AngleBracketRight, ">", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .LE => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessOrEqual, .AngleBracketLeftEqual, "<=", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .GE => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .GreaterOrEqual, .AngleBracketRightEqual, ">=", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .EQ => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .EqualEqual, .EqualEqual, "==", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .NE => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .BangEqual, .BangEqual, "!=", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .And => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitAnd, .Ampersand, "&", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .Xor => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitXor, .Caret, "^", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, + .Or => { + const node = try transCreateNodeInfixOp(rp, scope, stmt, .BitOr, .Pipe, "|", true); + return maybeSuppressResult(rp, scope, result_used, TransResult{ + .node = node, + .child_scope = scope, + .node_scope = scope, + }); + }, .LAnd, .LOr, .Comma, diff --git a/test/translate_c.zig b/test/translate_c.zig index 97cfc129f7..36cdc23915 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -871,6 +871,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_2("==, !=, no if", // TODO remove this test after `if` conversion supported, and switch "==, !=" to addC_both + \\int max(int a, int b) { + \\ int c = (a == b); + \\ int d = (a != b); + \\ return (c != d); + \\} + , &[_][]const u8{ + \\pub export fn max(a: c_int, b: c_int) c_int { + \\ var c: c_int = (a == b); + \\ var d: c_int = (a != b); + \\ return (c != d); + \\} + }); + cases.addC("bitwise binary operators", \\int max(int a, int b) { \\ return (a & b) ^ (a | b); @@ -881,6 +895,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_2("bitwise binary operators, simpler parens", // TODO can combine with "bitwise binary operators" when parens are correctly preserved/not added in translate-c-2 + \\int max(int a, int b) { + \\ int c = (a & b); + \\ int d = (a | b); + \\ return (c ^ d); + \\} + , &[_][]const u8{ + \\pub export fn max(a: c_int, b: c_int) c_int { + \\ var c: c_int = (a & b); + \\ var d: c_int = (a | b); + \\ return (c ^ d); + \\} + }); + cases.addC("logical and, logical or", \\int max(int a, int b) { \\ if (a < b || a == b) @@ -897,6 +925,30 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons. Can use `if` after it is added to translate-c-2 + \\int test_comparisons(int a, int b) { + \\ int c = (a < b); + \\ int d = (a > b); + \\ int e = (a <= b); + \\ int f = (a >= b); + \\ int g = (c < d); + \\ int h = (e < f); + \\ int i = (g < h); + \\ return i; + \\} + , &[_][]const u8{ + \\pub export fn test_comparisons(a: c_int, b: c_int) c_int { + \\ var c: c_int = (a < b); + \\ var d: c_int = (a > b); + \\ var e: c_int = (a <= b); + \\ var f: c_int = (a >= b); + \\ var g: c_int = (c < d); + \\ var h: c_int = (e < f); + \\ var i: c_int = (g < h); + \\ return i; + \\} + }); + cases.addC("logical and, logical or on none bool values", \\int and_or_none_bool(int a, float b, void *c) { \\ if (a && b) return 0;