| ... | @@ -951,20 +951,47 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo | ... | @@ -951,20 +951,47 @@ static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *blo |
| 951 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); | 951 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI"); |
| 952 | return nullptr; | 952 | return nullptr; |
| 953 | case BO_Mul: | 953 | case BO_Mul: |
| 954 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Mul"); | 954 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 955 | return nullptr; | 955 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, |
| | 956 | stmt->getRHS()); |
| 956 | case BO_Div: | 957 | case BO_Div: |
| 957 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Div"); | 958 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 958 | return nullptr; | 959 | // unsigned/float division uses the operator |
| | 960 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); |
| | 961 | } else { |
| | 962 | // signed integer division uses @divTrunc |
| | 963 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc"); |
| | 964 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| | 965 | if (lhs == nullptr) return nullptr; |
| | 966 | fn_call->data.fn_call_expr.params.append(lhs); |
| | 967 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); |
| | 968 | if (rhs == nullptr) return nullptr; |
| | 969 | fn_call->data.fn_call_expr.params.append(rhs); |
| | 970 | return fn_call; |
| | 971 | } |
| 959 | case BO_Rem: | 972 | case BO_Rem: |
| 960 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Rem"); | 973 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) { |
| 961 | return nullptr; | 974 | // unsigned/float division uses the operator |
| | 975 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); |
| | 976 | } else { |
| | 977 | // signed integer division uses @divTrunc |
| | 978 | AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); |
| | 979 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| | 980 | if (lhs == nullptr) return nullptr; |
| | 981 | fn_call->data.fn_call_expr.params.append(lhs); |
| | 982 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue); |
| | 983 | if (rhs == nullptr) return nullptr; |
| | 984 | fn_call->data.fn_call_expr.params.append(rhs); |
| | 985 | return fn_call; |
| | 986 | } |
| 962 | case BO_Add: | 987 | case BO_Add: |
| 963 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Add"); | 988 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 964 | return nullptr; | 989 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, |
| | 990 | stmt->getRHS()); |
| 965 | case BO_Sub: | 991 | case BO_Sub: |
| 966 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Sub"); | 992 | return trans_create_bin_op(c, block, stmt->getLHS(), |
| 967 | return nullptr; | 993 | qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, |
| | 994 | stmt->getRHS()); |
| 968 | case BO_Shl: | 995 | case BO_Shl: |
| 969 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl"); | 996 | emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl"); |
| 970 | return nullptr; | 997 | return nullptr; |