| ... | ... | @@ -987,59 +987,75 @@ static AstNode *trans_compound_assign_operator(Context *c, bool result_used, Ast |
| 987 | 987 | return nullptr; |
| 988 | 988 | case BO_ShrAssign: { |
| 989 | 989 | BinOpType bin_op = BinOpTypeBitShiftRight; |
| 990 | | // c: lhs >>= rhs; |
| 991 | | // zig: { |
| 992 | | // zig: const _ref = &lhs; |
| 993 | | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 994 | | // zig: *_ref |
| 995 | | // zig: }; |
| 996 | | // where u5 is the appropriate type |
| 997 | | |
| 998 | | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. |
| 999 | | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1000 | | |
| 1001 | | // const _ref = &lhs; |
| 1002 | | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1003 | | if (lhs == nullptr) return nullptr; |
| 1004 | | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1005 | | // TODO: avoid name collisions with generated variable names |
| 1006 | | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1007 | | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1008 | | child_block->data.block.statements.append(tmp_var_decl); |
| 1009 | | |
| 1010 | | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1011 | | |
| 1012 | | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1013 | | if (rhs == nullptr) return nullptr; |
| 990 | |
| 1014 | 991 | const SourceLocation &rhs_location = stmt->getRHS()->getLocStart(); |
| 1015 | 992 | AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location); |
| 1016 | 993 | |
| 1017 | | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1018 | | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1019 | | trans_create_node_symbol(c, tmp_var_name)), |
| 1020 | | BinOpTypeAssign, |
| 1021 | | trans_c_cast(c, rhs_location, |
| 1022 | | stmt->getComputationResultType(), |
| 1023 | | trans_create_node_bin_op(c, |
| 1024 | | trans_c_cast(c, rhs_location, |
| 1025 | | stmt->getComputationLHSType(), |
| 1026 | | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1027 | | trans_create_node_symbol(c, tmp_var_name))), |
| 1028 | | bin_op, |
| 1029 | | trans_create_node_fn_call_1(c, |
| 1030 | | rhs_type, |
| 1031 | | rhs)))); |
| 1032 | | child_block->data.block.statements.append(assign_statement); |
| 1033 | | |
| 1034 | | if (result_used) { |
| 1035 | | // *_ref |
| 1036 | | child_block->data.block.statements.append( |
| 994 | bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr(); |
| 995 | if (!use_intermediate_casts && !result_used) { |
| 996 | // simple common case, where the C and Zig are identical: |
| 997 | // lhs >>= rh* s |
| 998 | AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue); |
| 999 | if (lhs == nullptr) return nullptr; |
| 1000 | |
| 1001 | AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue); |
| 1002 | if (rhs == nullptr) return nullptr; |
| 1003 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1004 | |
| 1005 | return trans_create_node_bin_op(c, lhs, BinOpTypeAssignBitShiftRight, coerced_rhs); |
| 1006 | } else { |
| 1007 | // need more complexity. worst case, this looks like this: |
| 1008 | // c: lhs >>= rhs |
| 1009 | // zig: { |
| 1010 | // zig: const _ref = &lhs; |
| 1011 | // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1012 | // zig: *_ref |
| 1013 | // zig: } |
| 1014 | // where u5 is the appropriate type |
| 1015 | |
| 1016 | // TODO: avoid mess when we don't need the assignment value for chained assignments or anything. |
| 1017 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); |
| 1018 | |
| 1019 | // const _ref = &lhs; |
| 1020 | AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue); |
| 1021 | if (lhs == nullptr) return nullptr; |
| 1022 | AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs); |
| 1023 | // TODO: avoid name collisions with generated variable names |
| 1024 | Buf* tmp_var_name = buf_create_from_str("_ref"); |
| 1025 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs); |
| 1026 | child_block->data.block.statements.append(tmp_var_decl); |
| 1027 | |
| 1028 | // *_ref = result_type(operation_type(*_ref) >> u5(rhs)); |
| 1029 | |
| 1030 | AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue); |
| 1031 | if (rhs == nullptr) return nullptr; |
| 1032 | AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); |
| 1033 | |
| 1034 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1037 | 1035 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1038 | | trans_create_node_symbol(c, tmp_var_name))); |
| 1039 | | child_block->data.block.last_statement_is_result_expression = true; |
| 1040 | | } |
| 1036 | trans_create_node_symbol(c, tmp_var_name)), |
| 1037 | BinOpTypeAssign, |
| 1038 | trans_c_cast(c, rhs_location, |
| 1039 | stmt->getComputationResultType(), |
| 1040 | trans_create_node_bin_op(c, |
| 1041 | trans_c_cast(c, rhs_location, |
| 1042 | stmt->getComputationLHSType(), |
| 1043 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1044 | trans_create_node_symbol(c, tmp_var_name))), |
| 1045 | bin_op, |
| 1046 | coerced_rhs))); |
| 1047 | child_block->data.block.statements.append(assign_statement); |
| 1048 | |
| 1049 | if (result_used) { |
| 1050 | // *_ref |
| 1051 | child_block->data.block.statements.append( |
| 1052 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1053 | trans_create_node_symbol(c, tmp_var_name))); |
| 1054 | child_block->data.block.last_statement_is_result_expression = true; |
| 1055 | } |
| 1041 | 1056 | |
| 1042 | | return child_block; |
| 1057 | return child_block; |
| 1058 | } |
| 1043 | 1059 | } |
| 1044 | 1060 | case BO_AndAssign: |
| 1045 | 1061 | emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign"); |