| ... | @@ -575,6 +575,45 @@ fn transStmt( | ... | @@ -575,6 +575,45 @@ fn transStmt( |
| 575 | } | 575 | } |
| 576 | } | 576 | } |
| 577 | | 577 | |
| | 578 | fn transCreateNodeShiftOp( |
| | 579 | rp: RestorePoint, |
| | 580 | scope: *Scope, |
| | 581 | stmt: *const ZigClangBinaryOperator, |
| | 582 | comptime op: ast.Node.InfixOp.Op, |
| | 583 | comptime op_tok_id: std.zig.Token.Id, |
| | 584 | comptime bytes: []const u8, |
| | 585 | ) !*ast.Node { |
| | 586 | if (!(op == .BitShiftLeft or op == .BitShiftRight)) { |
| | 587 | @compileError("op must be either .BitShiftLeft or .BitShiftRight"); |
| | 588 | } |
| | 589 | |
| | 590 | const lhs_expr = ZigClangBinaryOperator_getLHS(stmt); |
| | 591 | const rhs_expr = ZigClangBinaryOperator_getRHS(stmt); |
| | 592 | const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr); |
| | 593 | // lhs >> u5(rh) |
| | 594 | |
| | 595 | const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value); |
| | 596 | const op_token = try appendToken(rp.c, op_tok_id, bytes); |
| | 597 | |
| | 598 | const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); |
| | 599 | const rhs_type = try qualTypeToLog2IntRef(rp, ZigClangBinaryOperator_getType(stmt), rhs_location); |
| | 600 | try as_node.params.push(rhs_type); |
| | 601 | _ = try appendToken(rp.c, .Comma, ","); |
| | 602 | const rhs = try transExpr(rp, scope, rhs_expr, .used, .l_value); |
| | 603 | try as_node.params.push(rhs.node); |
| | 604 | as_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| | 605 | |
| | 606 | const node = try rp.c.a().create(ast.Node.InfixOp); |
| | 607 | node.* = ast.Node.InfixOp{ |
| | 608 | .op_token = op_token, |
| | 609 | .lhs = lhs.node, |
| | 610 | .op = op, |
| | 611 | .rhs = &as_node.base, |
| | 612 | }; |
| | 613 | |
| | 614 | return &node.base; |
| | 615 | } |
| | 616 | |
| 578 | fn transBinaryOperator( | 617 | fn transBinaryOperator( |
| 579 | rp: RestorePoint, | 618 | rp: RestorePoint, |
| 580 | scope: *Scope, | 619 | scope: *Scope, |
| ... | @@ -679,15 +718,22 @@ fn transBinaryOperator( | ... | @@ -679,15 +718,22 @@ fn transBinaryOperator( |
| 679 | }); | 718 | }); |
| 680 | } | 719 | } |
| 681 | }, | 720 | }, |
| 682 | .Shl, | 721 | .Shl => { |
| 683 | .Shr, | 722 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<"); |
| 684 | => return revertAndWarn( | 723 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| 685 | rp, | 724 | .node = node, |
| 686 | error.UnsupportedTranslation, | 725 | .child_scope = scope, |
| 687 | ZigClangBinaryOperator_getBeginLoc(stmt), | 726 | .node_scope = scope, |
| 688 | "TODO: handle more C binary operators: {}", | 727 | }); |
| 689 | .{op}, | 728 | }, |
| 690 | ), | 729 | .Shr => { |
| | 730 | const node = try transCreateNodeShiftOp(rp, scope, stmt, .BitShiftRight, .AngleBracketAngleBracketRight, ">>"); |
| | 731 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| | 732 | .node = node, |
| | 733 | .child_scope = scope, |
| | 734 | .node_scope = scope, |
| | 735 | }); |
| | 736 | }, |
| 691 | .LT => { | 737 | .LT => { |
| 692 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true); | 738 | const node = try transCreateNodeInfixOp(rp, scope, stmt, .LessThan, .AngleBracketLeft, "<", true); |
| 693 | return maybeSuppressResult(rp, scope, result_used, TransResult{ | 739 | return maybeSuppressResult(rp, scope, result_used, TransResult{ |
| ... | @@ -1664,6 +1710,95 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool { | ... | @@ -1664,6 +1710,95 @@ fn qualTypeIsPtr(qt: ZigClangQualType) bool { |
| 1664 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; | 1710 | return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer; |
| 1665 | } | 1711 | } |
| 1666 | | 1712 | |
| | 1713 | fn qualTypeIntBitWidth(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !u32 { |
| | 1714 | const ty = ZigClangQualType_getTypePtr(qt); |
| | 1715 | |
| | 1716 | switch (ZigClangType_getTypeClass(ty)) { |
| | 1717 | .Builtin => { |
| | 1718 | const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty); |
| | 1719 | |
| | 1720 | switch (ZigClangBuiltinType_getKind(builtin_ty)) { |
| | 1721 | .Char_U, |
| | 1722 | .UChar, |
| | 1723 | .Char_S, |
| | 1724 | .SChar, |
| | 1725 | => return 8, |
| | 1726 | .UInt128, |
| | 1727 | .Int128, |
| | 1728 | => return 128, |
| | 1729 | else => return 0, |
| | 1730 | } |
| | 1731 | |
| | 1732 | unreachable; |
| | 1733 | }, |
| | 1734 | .Typedef => { |
| | 1735 | const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty); |
| | 1736 | const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty); |
| | 1737 | const type_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl))); |
| | 1738 | |
| | 1739 | if (std.mem.eql(u8, type_name, "uint8_t") or std.mem.eql(u8, type_name, "int8_t")) { |
| | 1740 | return 8; |
| | 1741 | } else if (std.mem.eql(u8, type_name, "uint16_t") or std.mem.eql(u8, type_name, "int16_t")) { |
| | 1742 | return 16; |
| | 1743 | } else if (std.mem.eql(u8, type_name, "uint32_t") or std.mem.eql(u8, type_name, "int32_t")) { |
| | 1744 | return 32; |
| | 1745 | } else if (std.mem.eql(u8, type_name, "uint64_t") or std.mem.eql(u8, type_name, "int64_t")) { |
| | 1746 | return 64; |
| | 1747 | } else { |
| | 1748 | return 0; |
| | 1749 | } |
| | 1750 | }, |
| | 1751 | else => return 0, |
| | 1752 | } |
| | 1753 | |
| | 1754 | unreachable; |
| | 1755 | } |
| | 1756 | |
| | 1757 | fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !*ast.Node { |
| | 1758 | const int_bit_width = try qualTypeIntBitWidth(rp, qt, source_loc); |
| | 1759 | |
| | 1760 | if (int_bit_width != 0) { |
| | 1761 | // we can perform the log2 now. |
| | 1762 | const cast_bit_width = std.math.log2_int(u64, int_bit_width); |
| | 1763 | const node = try rp.c.a().create(ast.Node.IntegerLiteral); |
| | 1764 | node.* = ast.Node.IntegerLiteral{ |
| | 1765 | .token = try appendTokenFmt(rp.c, .Identifier, "u{}", .{cast_bit_width}), |
| | 1766 | }; |
| | 1767 | return &node.base; |
| | 1768 | } |
| | 1769 | |
| | 1770 | const zig_type_node = try transQualType(rp, qt, source_loc); |
| | 1771 | |
| | 1772 | // @import("std").math.Log2Int(c_long); |
| | 1773 | // |
| | 1774 | // FnCall |
| | 1775 | // FieldAccess |
| | 1776 | // FieldAccess |
| | 1777 | // FnCall (.builtin = true) |
| | 1778 | // Symbol "import" |
| | 1779 | // StringLiteral "std" |
| | 1780 | // Symbol "math" |
| | 1781 | // Symbol "Log2Int" |
| | 1782 | // Symbol <zig_type_node> (var from above) |
| | 1783 | |
| | 1784 | const import_fn_call = try transCreateNodeBuiltinFnCall(rp.c, "@import"); |
| | 1785 | const std_token = try appendToken(rp.c, .StringLiteral, "\"std\""); |
| | 1786 | const std_node = try rp.c.a().create(ast.Node.StringLiteral); |
| | 1787 | std_node.* = ast.Node.StringLiteral{ |
| | 1788 | .token = std_token, |
| | 1789 | }; |
| | 1790 | try import_fn_call.params.push(&std_node.base); |
| | 1791 | import_fn_call.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| | 1792 | |
| | 1793 | const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math"); |
| | 1794 | const outer_field_access = try transCreateNodeFieldAccess(rp.c, &inner_field_access.base, "Log2Int"); |
| | 1795 | const log2int_fn_call = try transCreateNodeFnCall(rp.c, &outer_field_access.base); |
| | 1796 | try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node); |
| | 1797 | log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")"); |
| | 1798 | |
| | 1799 | return &log2int_fn_call.base; |
| | 1800 | } |
| | 1801 | |
| 1667 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { | 1802 | fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool { |
| 1668 | const ty = ZigClangQualType_getTypePtr(qt); | 1803 | const ty = ZigClangQualType_getTypePtr(qt); |
| 1669 | | 1804 | |
| ... | @@ -1827,7 +1962,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { | ... | @@ -1827,7 +1962,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 1827 | _ = try appendToken(c, .LParen, "("); | 1962 | _ = try appendToken(c, .LParen, "("); |
| 1828 | const node = try c.a().create(ast.Node.SuffixOp); | 1963 | const node = try c.a().create(ast.Node.SuffixOp); |
| 1829 | node.* = ast.Node.SuffixOp{ | 1964 | node.* = ast.Node.SuffixOp{ |
| 1830 | .lhs = fn_expr, | 1965 | .lhs = .{ .node = fn_expr }, |
| 1831 | .op = ast.Node.SuffixOp.Op{ | 1966 | .op = ast.Node.SuffixOp.Op{ |
| 1832 | .Call = ast.Node.SuffixOp.Op.Call{ | 1967 | .Call = ast.Node.SuffixOp.Op.Call{ |
| 1833 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), | 1968 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()), |
| ... | @@ -1839,6 +1974,17 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { | ... | @@ -1839,6 +1974,17 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp { |
| 1839 | return node; | 1974 | return node; |
| 1840 | } | 1975 | } |
| 1841 | | 1976 | |
| | 1977 | fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node.InfixOp { |
| | 1978 | const field_access_node = try c.a().create(ast.Node.InfixOp); |
| | 1979 | field_access_node.* = .{ |
| | 1980 | .op_token = try appendToken(c, .Period, "."), |
| | 1981 | .lhs = container, |
| | 1982 | .op = .Period, |
| | 1983 | .rhs = try transCreateNodeIdentifier(c, field_name), |
| | 1984 | }; |
| | 1985 | return field_access_node; |
| | 1986 | } |
| | 1987 | |
| 1842 | fn transCreateNodePrefixOp( | 1988 | fn transCreateNodePrefixOp( |
| 1843 | c: *Context, | 1989 | c: *Context, |
| 1844 | op: ast.Node.PrefixOp.Op, | 1990 | op: ast.Node.PrefixOp.Op, |