diff --git a/src/parsec.cpp b/src/parsec.cpp index 89a133c872..7626812fa3 100644 --- a/src/parsec.cpp +++ b/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; diff --git a/test/parsec.zig b/test/parsec.zig index 58b545eb28..e2b0c6f225 100644 --- a/test/parsec.zig +++ b/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);