Commit 67a5a3f3d7

Josh Wolfe <thejoshwolfe@gmail.com>
2017-09-21 07:36:33
add sub mul div rem
1 parent 0d1f64b
Changed files (2)
src/parsec.cpp
@@ -951,20 +951,47 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo
             emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");
             return nullptr;
         case BO_Mul:
-            emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Mul");
-            return nullptr;
+            return trans_create_bin_op(c, block, stmt->getLHS(),
+                qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
+                stmt->getRHS());
         case BO_Div:
-            emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Div");
-            return nullptr;
+            if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
+                // unsigned/float division uses the operator
+                return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
+            } else {
+                // signed integer division uses @divTrunc
+                AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
+                AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
+                if (lhs == nullptr) return nullptr;
+                fn_call->data.fn_call_expr.params.append(lhs);
+                AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
+                if (rhs == nullptr) return nullptr;
+                fn_call->data.fn_call_expr.params.append(rhs);
+                return fn_call;
+            }
         case BO_Rem:
-            emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Rem");
-            return nullptr;
+            if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
+                // unsigned/float division uses the operator
+                return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
+            } else {
+                // signed integer division uses @divTrunc
+                AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
+                AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
+                if (lhs == nullptr) return nullptr;
+                fn_call->data.fn_call_expr.params.append(lhs);
+                AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
+                if (rhs == nullptr) return nullptr;
+                fn_call->data.fn_call_expr.params.append(rhs);
+                return fn_call;
+            }
         case BO_Add:
-            emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Add");
-            return nullptr;
+            return trans_create_bin_op(c, block, stmt->getLHS(),
+                qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
+                stmt->getRHS());
         case BO_Sub:
-            emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Sub");
-            return nullptr;
+            return trans_create_bin_op(c, block, stmt->getLHS(),
+                qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
+                stmt->getRHS());
         case BO_Shl:
             emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl");
             return nullptr;
test/parsec.zig
@@ -389,6 +389,42 @@ pub fn addCases(cases: &tests.ParseCContext) {
         \\}
     );
 
+    cases.add("add, sub, mul, div, rem",
+        \\int s(int a, int b) {
+        \\    int c;
+        \\    c = a + b;
+        \\    c = a - b;
+        \\    c = a * b;
+        \\    c = a / b;
+        \\    c = a % b;
+        \\}
+        \\unsigned u(unsigned a, unsigned b) {
+        \\    unsigned c;
+        \\    c = a + b;
+        \\    c = a - b;
+        \\    c = a * b;
+        \\    c = a / b;
+        \\    c = a % b;
+        \\}
+    ,
+        \\export fn s(a: c_int, b: c_int) -> c_int {
+        \\    var c: c_int;
+        \\    c = (a + b);
+        \\    c = (a - b);
+        \\    c = (a * b);
+        \\    c = @divTrunc(a, b);
+        \\    c = @rem(a, b);
+        \\}
+        \\export fn u(a: c_uint, b: c_uint) -> c_uint {
+        \\    var c: c_uint;
+        \\    c = (a +% b);
+        \\    c = (a -% b);
+        \\    c = (a *% b);
+        \\    c = (a / b);
+        \\    c = (a % b);
+        \\}
+    );
+
     cases.add("bitwise binary operators",
         \\int max(int a, int b) {
         \\    return (a & b) ^ (a | b);