| author | |
| committer | |
| log | 012ce1481e003b25e49934fce17f5e1b4aff218a |
| tree | 9d2928e6662a59c172dac26e488b82d89014dde8 |
| parent | 4c2cdf6f4da09e2986aa7a574455995168bcab8f |
2 files changed, 170 insertions(+), 29 deletions(-)
src/parsec.cpp+63-29| ... | ... | @@ -1499,38 +1499,72 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue |
| 1499 | 1499 | return trans_create_node_symbol(c, symbol_name); |
| 1500 | 1500 | } |
| 1501 | 1501 | |
| 1502 | static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) { | |
| 1503 | Expr *op_expr = stmt->getSubExpr(); | |
| 1504 | ||
| 1505 | if (!result_used) { | |
| 1506 | // common case | |
| 1507 | // c: expr++ | |
| 1508 | // zig: expr += 1 | |
| 1509 | return trans_create_node_bin_op(c, | |
| 1510 | trans_expr(c, true, block, op_expr, TransLValue), | |
| 1511 | assign_op, | |
| 1512 | trans_create_node_unsigned(c, 1)); | |
| 1513 | } else { | |
| 1514 | // worst case | |
| 1515 | // c: expr++ | |
| 1516 | // zig: { | |
| 1517 | // zig: const _ref = &expr; | |
| 1518 | // zig: const _tmp = *_ref; | |
| 1519 | // zig: *_ref += 1; | |
| 1520 | // zig: _tmp | |
| 1521 | // zig: } | |
| 1522 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | |
| 1523 | ||
| 1524 | // const _ref = &expr; | |
| 1525 | AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue); | |
| 1526 | if (expr == nullptr) return nullptr; | |
| 1527 | AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr); | |
| 1528 | // TODO: avoid name collisions with generated variable names | |
| 1529 | Buf* ref_var_name = buf_create_from_str("_ref"); | |
| 1530 | AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr); | |
| 1531 | child_block->data.block.statements.append(ref_var_decl); | |
| 1532 | ||
| 1533 | // const _tmp = *_ref; | |
| 1534 | Buf* tmp_var_name = buf_create_from_str("_tmp"); | |
| 1535 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, | |
| 1536 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1537 | trans_create_node_symbol(c, ref_var_name))); | |
| 1538 | child_block->data.block.statements.append(tmp_var_decl); | |
| 1539 | ||
| 1540 | // *_ref += 1; | |
| 1541 | AstNode *assign_statement = trans_create_node_bin_op(c, | |
| 1542 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1543 | trans_create_node_symbol(c, ref_var_name)), | |
| 1544 | assign_op, | |
| 1545 | trans_create_node_unsigned(c, 1)); | |
| 1546 | child_block->data.block.statements.append(assign_statement); | |
| 1547 | ||
| 1548 | // _tmp | |
| 1549 | child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name)); | |
| 1550 | child_block->data.block.last_statement_is_result_expression = true; | |
| 1551 | ||
| 1552 | return child_block; | |
| 1553 | } | |
| 1554 | } | |
| 1555 | ||
| 1502 | 1556 | static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) { |
| 1503 | 1557 | switch (stmt->getOpcode()) { |
| 1504 | case UO_PostInc: { | |
| 1505 | Expr *op_expr = stmt->getSubExpr(); | |
| 1506 | BinOpType bin_op = qual_type_has_wrapping_overflow(c, op_expr->getType()) | |
| 1507 | ? BinOpTypeAssignPlusWrap | |
| 1508 | : BinOpTypeAssignPlus; | |
| 1509 | ||
| 1510 | if (!result_used) { | |
| 1511 | // common case | |
| 1512 | // c: expr++ | |
| 1513 | // zig: expr += 1 | |
| 1514 | return trans_create_node_bin_op(c, | |
| 1515 | trans_expr(c, true, block, op_expr, TransLValue), | |
| 1516 | bin_op, | |
| 1517 | trans_create_node_unsigned(c, 1)); | |
| 1518 | } else { | |
| 1519 | // worst case | |
| 1520 | // c: expr++ | |
| 1521 | // zig: { | |
| 1522 | // zig: const _ref = &expr; | |
| 1523 | // zig: const _tmp = *_ref; | |
| 1524 | // zig: *_ref += 1; | |
| 1525 | // zig: _tmp | |
| 1526 | // zig: } | |
| 1527 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc with result_used"); | |
| 1528 | return nullptr; | |
| 1529 | } | |
| 1530 | } | |
| 1558 | case UO_PostInc: | |
| 1559 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | |
| 1560 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap); | |
| 1561 | else | |
| 1562 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlus); | |
| 1531 | 1563 | case UO_PostDec: |
| 1532 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec"); | |
| 1533 | return nullptr; | |
| 1564 | if (qual_type_has_wrapping_overflow(c, stmt->getType())) | |
| 1565 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap); | |
| 1566 | else | |
| 1567 | return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinus); | |
| 1534 | 1568 | case UO_PreInc: |
| 1535 | 1569 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PreInc"); |
| 1536 | 1570 | return nullptr; |
test/parsec.zig+107| ... | ... | @@ -687,6 +687,65 @@ pub fn addCases(cases: &tests.ParseCContext) { |
| 687 | 687 | \\ }); |
| 688 | 688 | \\} |
| 689 | 689 | ); |
| 690 | ||
| 691 | cases.addC("compound assignment operators unsigned", | |
| 692 | \\void foo(void) { | |
| 693 | \\ unsigned a = 0; | |
| 694 | \\ a += (a += 1); | |
| 695 | \\ a -= (a -= 1); | |
| 696 | \\ a *= (a *= 1); | |
| 697 | \\ a &= (a &= 1); | |
| 698 | \\ a |= (a |= 1); | |
| 699 | \\ a ^= (a ^= 1); | |
| 700 | \\ a >>= (a >>= 1); | |
| 701 | \\ a <<= (a <<= 1); | |
| 702 | \\} | |
| 703 | , | |
| 704 | \\export fn foo() { | |
| 705 | \\ var a: c_uint = c_uint(0); | |
| 706 | \\ a +%= { | |
| 707 | \\ const _ref = &a; | |
| 708 | \\ (*_ref) = ((*_ref) +% c_uint(1)); | |
| 709 | \\ *_ref | |
| 710 | \\ }; | |
| 711 | \\ a -%= { | |
| 712 | \\ const _ref = &a; | |
| 713 | \\ (*_ref) = ((*_ref) -% c_uint(1)); | |
| 714 | \\ *_ref | |
| 715 | \\ }; | |
| 716 | \\ a *%= { | |
| 717 | \\ const _ref = &a; | |
| 718 | \\ (*_ref) = ((*_ref) *% c_uint(1)); | |
| 719 | \\ *_ref | |
| 720 | \\ }; | |
| 721 | \\ a &= { | |
| 722 | \\ const _ref = &a; | |
| 723 | \\ (*_ref) = ((*_ref) & c_uint(1)); | |
| 724 | \\ *_ref | |
| 725 | \\ }; | |
| 726 | \\ a |= { | |
| 727 | \\ const _ref = &a; | |
| 728 | \\ (*_ref) = ((*_ref) | c_uint(1)); | |
| 729 | \\ *_ref | |
| 730 | \\ }; | |
| 731 | \\ a ^= { | |
| 732 | \\ const _ref = &a; | |
| 733 | \\ (*_ref) = ((*_ref) ^ c_uint(1)); | |
| 734 | \\ *_ref | |
| 735 | \\ }; | |
| 736 | \\ a >>= @import("std").math.Log2Int(c_uint)({ | |
| 737 | \\ const _ref = &a; | |
| 738 | \\ (*_ref) = c_uint(c_uint(*_ref) >> @import("std").math.Log2Int(c_uint)(1)); | |
| 739 | \\ *_ref | |
| 740 | \\ }); | |
| 741 | \\ a <<= @import("std").math.Log2Int(c_uint)({ | |
| 742 | \\ const _ref = &a; | |
| 743 | \\ (*_ref) = c_uint(c_uint(*_ref) << @import("std").math.Log2Int(c_uint)(1)); | |
| 744 | \\ *_ref | |
| 745 | \\ }); | |
| 746 | \\} | |
| 747 | ); | |
| 748 | ||
| 690 | 749 | cases.addC("duplicate typedef", |
| 691 | 750 | \\typedef long foo; |
| 692 | 751 | \\typedef int bar; |
| ... | ... | @@ -697,6 +756,54 @@ pub fn addCases(cases: &tests.ParseCContext) { |
| 697 | 756 | \\pub const bar = c_int; |
| 698 | 757 | \\pub const baz = c_int; |
| 699 | 758 | ); |
| 759 | ||
| 760 | cases.addC("post increment/decrement", | |
| 761 | \\void foo(void) { | |
| 762 | \\ int i = 0; | |
| 763 | \\ unsigned u = 0; | |
| 764 | \\ i++; | |
| 765 | \\ i--; | |
| 766 | \\ u++; | |
| 767 | \\ u--; | |
| 768 | \\ i = i++; | |
| 769 | \\ i = i--; | |
| 770 | \\ u = u++; | |
| 771 | \\ u = u--; | |
| 772 | \\} | |
| 773 | , | |
| 774 | \\export fn foo() { | |
| 775 | \\ var i: c_int = 0; | |
| 776 | \\ var u: c_uint = c_uint(0); | |
| 777 | \\ i += 1; | |
| 778 | \\ i -= 1; | |
| 779 | \\ u +%= 1; | |
| 780 | \\ u -%= 1; | |
| 781 | \\ i = { | |
| 782 | \\ const _ref = &i; | |
| 783 | \\ const _tmp = *_ref; | |
| 784 | \\ (*_ref) += 1; | |
| 785 | \\ _tmp | |
| 786 | \\ }; | |
| 787 | \\ i = { | |
| 788 | \\ const _ref = &i; | |
| 789 | \\ const _tmp = *_ref; | |
| 790 | \\ (*_ref) -= 1; | |
| 791 | \\ _tmp | |
| 792 | \\ }; | |
| 793 | \\ u = { | |
| 794 | \\ const _ref = &u; | |
| 795 | \\ const _tmp = *_ref; | |
| 796 | \\ (*_ref) +%= 1; | |
| 797 | \\ _tmp | |
| 798 | \\ }; | |
| 799 | \\ u = { | |
| 800 | \\ const _ref = &u; | |
| 801 | \\ const _tmp = *_ref; | |
| 802 | \\ (*_ref) -%= 1; | |
| 803 | \\ _tmp | |
| 804 | \\ }; | |
| 805 | \\} | |
| 806 | ); | |
| 700 | 807 | } |
| 701 | 808 | |
| 702 | 809 |