| ... | @@ -1144,18 +1144,16 @@ fn transBinaryOperator( | ... | @@ -1144,18 +1144,16 @@ fn transBinaryOperator( |
| 1144 | } | 1144 | } |
| 1145 | }, | 1145 | }, |
| 1146 | .Shl => { | 1146 | .Shl => { |
| 1147 | const node = try transCreateNodeShiftOp(c, scope, stmt, .shl); | 1147 | return transCreateNodeShiftOp(c, scope, stmt, .shl, result_used); |
| 1148 | return maybeSuppressResult(c, scope, result_used, node); | | |
| 1149 | }, | 1148 | }, |
| 1150 | .Shr => { | 1149 | .Shr => { |
| 1151 | const node = try transCreateNodeShiftOp(c, scope, stmt, .shr); | 1150 | return transCreateNodeShiftOp(c, scope, stmt, .shr, result_used); |
| 1152 | return maybeSuppressResult(c, scope, result_used, node); | | |
| 1153 | }, | 1151 | }, |
| 1154 | .LAnd => { | 1152 | .LAnd => { |
| 1155 | return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used, true); | 1153 | return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used); |
| 1156 | }, | 1154 | }, |
| 1157 | .LOr => { | 1155 | .LOr => { |
| 1158 | return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used, true); | 1156 | return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used); |
| 1159 | }, | 1157 | }, |
| 1160 | else => {}, | 1158 | else => {}, |
| 1161 | } | 1159 | } |
| ... | @@ -1233,15 +1231,7 @@ fn transBinaryOperator( | ... | @@ -1233,15 +1231,7 @@ fn transBinaryOperator( |
| 1233 | else | 1231 | else |
| 1234 | rhs_uncasted; | 1232 | rhs_uncasted; |
| 1235 | | 1233 | |
| 1236 | const payload = try c.arena.create(ast.Payload.BinOp); | 1234 | return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, used); |
| 1237 | payload.* = .{ | | |
| 1238 | .base = .{ .tag = op_id }, | | |
| 1239 | .data = .{ | | |
| 1240 | .lhs = lhs, | | |
| 1241 | .rhs = rhs, | | |
| 1242 | }, | | |
| 1243 | }; | | |
| 1244 | return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base)); | | |
| 1245 | } | 1235 | } |
| 1246 | | 1236 | |
| 1247 | fn transCompoundStmtInline( | 1237 | fn transCompoundStmtInline( |
| ... | @@ -1716,7 +1706,7 @@ fn transStringLiteralAsArray( | ... | @@ -1716,7 +1706,7 @@ fn transStringLiteralAsArray( |
| 1716 | init_list[i] = try transCreateCharLitNode(c, narrow, code_unit); | 1706 | init_list[i] = try transCreateCharLitNode(c, narrow, code_unit); |
| 1717 | } | 1707 | } |
| 1718 | while (i < array_size) : (i += 1) { | 1708 | while (i < array_size) : (i += 1) { |
| 1719 | init_list[i] = try transCreateNodeInt(c, 0); | 1709 | init_list[i] = try transCreateNodeNumber(c, 0); |
| 1720 | } | 1710 | } |
| 1721 | | 1711 | |
| 1722 | return Node.array_init.create(c.arena, init_list); | 1712 | return Node.array_init.create(c.arena, init_list); |
| ... | @@ -2398,7 +2388,7 @@ fn transCharLiteral( | ... | @@ -2398,7 +2388,7 @@ fn transCharLiteral( |
| 2398 | // C has a somewhat obscure feature called multi-character character constant | 2388 | // C has a somewhat obscure feature called multi-character character constant |
| 2399 | // e.g. 'abcd' | 2389 | // e.g. 'abcd' |
| 2400 | const int_lit_node = if (kind == .Ascii and val > 255) | 2390 | const int_lit_node = if (kind == .Ascii and val > 255) |
| 2401 | try transCreateNodeInt(c, val) | 2391 | try transCreateNodeNumber(c, val) |
| 2402 | else | 2392 | else |
| 2403 | try transCreateCharLitNode(c, narrow, val); | 2393 | try transCreateCharLitNode(c, narrow, val); |
| 2404 | | 2394 | |
| ... | @@ -2434,8 +2424,8 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: | ... | @@ -2434,8 +2424,8 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: |
| 2434 | .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value), | 2424 | .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value), |
| 2435 | }); | 2425 | }); |
| 2436 | try block_scope.statements.append(break_node); | 2426 | try block_scope.statements.append(break_node); |
| 2437 | | 2427 | const res = try block_scope.complete(c); |
| 2438 | return block_scope.complete(c); | 2428 | return maybeSuppressResult(c, scope, used, res); |
| 2439 | } | 2429 | } |
| 2440 | | 2430 | |
| 2441 | fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node { | 2431 | fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node { |
| ... | @@ -2460,8 +2450,9 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re | ... | @@ -2460,8 +2450,9 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re |
| 2460 | const decl = @ptrCast(*const clang.NamedDecl, member_decl); | 2450 | const decl = @ptrCast(*const clang.NamedDecl, member_decl); |
| 2461 | break :blk try c.str(decl.getName_bytes_begin()); | 2451 | break :blk try c.str(decl.getName_bytes_begin()); |
| 2462 | }; | 2452 | }; |
| | 2453 | const ident = try Node.identifier.create(c.arena, name); |
| 2463 | | 2454 | |
| 2464 | const node = try Node.field_access.create(c.arena, .{ .container = container_node, .name = name}); | 2455 | const node = try Node.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident}); |
| 2465 | return maybeSuppressResult(c, scope, result_used, node); | 2456 | return maybeSuppressResult(c, scope, result_used, node); |
| 2466 | } | 2457 | } |
| 2467 | | 2458 | |
| ... | @@ -2716,15 +2707,9 @@ fn transCreatePreCrement( | ... | @@ -2716,15 +2707,9 @@ fn transCreatePreCrement( |
| 2716 | // common case | 2707 | // common case |
| 2717 | // c: ++expr | 2708 | // c: ++expr |
| 2718 | // zig: expr += 1 | 2709 | // zig: expr += 1 |
| 2719 | const payload = try c.arena.create(ast.Payload.BinOp); | 2710 | const lhs = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2720 | payload.* = .{ | 2711 | const rhs = Node.one_literal.init(); |
| 2721 | .base = .{ .tag = op }, | 2712 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used); |
| 2722 | .data = .{ | | |
| 2723 | .lhs = try transExpr(c, scope, op_expr, .used, .r_value), | | |
| 2724 | .rhs = Node.one_literal.init(), | | |
| 2725 | } | | |
| 2726 | }; | | |
| 2727 | return Node.initPayload(&payload.base); | | |
| 2728 | } | 2713 | } |
| 2729 | // worst case | 2714 | // worst case |
| 2730 | // c: ++expr | 2715 | // c: ++expr |
| ... | @@ -2744,20 +2729,15 @@ fn transCreatePreCrement( | ... | @@ -2744,20 +2729,15 @@ fn transCreatePreCrement( |
| 2744 | | 2729 | |
| 2745 | const lhs_node = try Node.identifier.create(c.arena, ref); | 2730 | const lhs_node = try Node.identifier.create(c.arena, ref); |
| 2746 | const ref_node = try Node.deref.create(c.arena, lhs_node); | 2731 | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2747 | const payload = try c.arena.create(ast.Payload.BinOp); | 2732 | const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used); |
| 2748 | payload.* = .{ | 2733 | try block_scope.statements.append(node); |
| 2749 | .base = .{ .tag = op }, | | |
| 2750 | .data = .{ | | |
| 2751 | .lhs = ref_node, | | |
| 2752 | .rhs = Node.one_literal.init(), | | |
| 2753 | } | | |
| 2754 | }; | | |
| 2755 | try block_scope.statements.append(Node.initPayload(&payload.base)); | | |
| 2756 | | 2734 | |
| 2757 | return Node.break_val.create(c.arena, .{ | 2735 | const break_node = try Node.break_val.create(c.arena, .{ |
| 2758 | .label = block_scope.label, | 2736 | .label = block_scope.label, |
| 2759 | .val = ref_node, | 2737 | .val = ref_node, |
| 2760 | }); | 2738 | }); |
| | 2739 | try block_scope.statements.append(break_node); |
| | 2740 | return block_scope.complete(c); |
| 2761 | } | 2741 | } |
| 2762 | | 2742 | |
| 2763 | fn transCreatePostCrement( | 2743 | fn transCreatePostCrement( |
| ... | @@ -2771,17 +2751,11 @@ fn transCreatePostCrement( | ... | @@ -2771,17 +2751,11 @@ fn transCreatePostCrement( |
| 2771 | | 2751 | |
| 2772 | if (used == .unused) { | 2752 | if (used == .unused) { |
| 2773 | // common case | 2753 | // common case |
| 2774 | // c: ++expr | 2754 | // c: expr++ |
| 2775 | // zig: expr += 1 | 2755 | // zig: expr += 1 |
| 2776 | const payload = try c.arena.create(ast.Payload.BinOp); | 2756 | const lhs = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2777 | payload.* = .{ | 2757 | const rhs = Node.one_literal.init(); |
| 2778 | .base = .{ .tag = op }, | 2758 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used); |
| 2779 | .data = .{ | | |
| 2780 | .lhs = try transExpr(c, scope, op_expr, .used, .r_value), | | |
| 2781 | .rhs = Node.one_literal.init(), | | |
| 2782 | } | | |
| 2783 | }; | | |
| 2784 | return Node.initPayload(&payload.base); | | |
| 2785 | } | 2759 | } |
| 2786 | // worst case | 2760 | // worst case |
| 2787 | // c: expr++ | 2761 | // c: expr++ |
| ... | @@ -2807,44 +2781,39 @@ fn transCreatePostCrement( | ... | @@ -2807,44 +2781,39 @@ fn transCreatePostCrement( |
| 2807 | const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node}); | 2781 | const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node}); |
| 2808 | try block_scope.statements.append(tmp_decl); | 2782 | try block_scope.statements.append(tmp_decl); |
| 2809 | | 2783 | |
| 2810 | const payload = try c.arena.create(ast.Payload.BinOp); | 2784 | const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used); |
| 2811 | payload.* = .{ | 2785 | try block_scope.statements.append(node); |
| 2812 | .base = .{ .tag = op }, | | |
| 2813 | .data = .{ | | |
| 2814 | .lhs = ref_node, | | |
| 2815 | .rhs = Node.one_literal.init(), | | |
| 2816 | } | | |
| 2817 | }; | | |
| 2818 | try block_scope.statements.append(Node.initPayload(&payload.base)); | | |
| 2819 | | 2786 | |
| 2820 | return Node.break_val.create(c.arena, .{ | 2787 | const break_node = try Node.break_val.create(c.arena, .{ |
| 2821 | .label = block_scope.label, | 2788 | .label = block_scope.label, |
| 2822 | .val = try Node.identifier.create(c.arena, tmp), | 2789 | .val = try Node.identifier.create(c.arena, tmp), |
| 2823 | }); | 2790 | }); |
| | 2791 | try block_scope.statements.append(break_node); |
| | 2792 | return block_scope.complete(c); |
| 2824 | } | 2793 | } |
| 2825 | | 2794 | |
| 2826 | fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!*ast.Node { | 2795 | fn transCompoundAssignOperator(c: *Context, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!Node { |
| 2827 | switch (stmt.getOpcode()) { | 2796 | switch (stmt.getOpcode()) { |
| 2828 | .MulAssign => if (qualTypeHasWrappingOverflow(stmt.getType())) | 2797 | .MulAssign => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2829 | return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MulWrap, .AsteriskPercent, "*%", used) | 2798 | return transCreateCompoundAssign(c, scope, stmt, .assign_mul_wrap, used) |
| 2830 | else | 2799 | else |
| 2831 | return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used), | 2800 | return transCreateCompoundAssign(c, scope, stmt, .assign_mul, used), |
| 2832 | .AddAssign => if (qualTypeHasWrappingOverflow(stmt.getType())) | 2801 | .AddAssign => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2833 | return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used) | 2802 | return transCreateCompoundAssign(c, scope, stmt, .assign_add_wrap, used) |
| 2834 | else | 2803 | else |
| 2835 | return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used), | 2804 | return transCreateCompoundAssign(c, scope, stmt, .assign_add, used), |
| 2836 | .SubAssign => if (qualTypeHasWrappingOverflow(stmt.getType())) | 2805 | .SubAssign => if (qualTypeHasWrappingOverflow(stmt.getType())) |
| 2837 | return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used) | 2806 | return transCreateCompoundAssign(c, scope, stmt, .assign_sub_wrap, used) |
| 2838 | else | 2807 | else |
| 2839 | return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used), | 2808 | return transCreateCompoundAssign(c, scope, stmt, .assign_sub, used), |
| 2840 | .DivAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignDiv, .SlashEqual, "/=", .Div, .Slash, "/", used), | 2809 | .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_div, used), |
| 2841 | .RemAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignMod, .PercentEqual, "%=", .Mod, .Percent, "%", used), | 2810 | .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_mod, used), |
| 2842 | .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used), | 2811 | .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shl, used), |
| 2843 | .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used), | 2812 | .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shr, used), |
| 2844 | .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used), | 2813 | .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_and, used), |
| 2845 | .XorAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitXor, .CaretEqual, "^=", .BitXor, .Caret, "^", used), | 2814 | .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_xor, used), |
| 2846 | .OrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitOr, .PipeEqual, "|=", .BitOr, .Pipe, "|", used), | 2815 | .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_or, used), |
| 2847 | else => return revertAndWarn( | 2816 | else => return fail( |
| 2848 | rp, | 2817 | rp, |
| 2849 | error.UnsupportedTranslation, | 2818 | error.UnsupportedTranslation, |
| 2850 | stmt.getBeginLoc(), | 2819 | stmt.getBeginLoc(), |
| ... | @@ -2855,25 +2824,20 @@ fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const cla | ... | @@ -2855,25 +2824,20 @@ fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const cla |
| 2855 | } | 2824 | } |
| 2856 | | 2825 | |
| 2857 | fn transCreateCompoundAssign( | 2826 | fn transCreateCompoundAssign( |
| 2858 | rp: RestorePoint, | 2827 | c: *Context, |
| 2859 | scope: *Scope, | 2828 | scope: *Scope, |
| 2860 | stmt: *const clang.CompoundAssignOperator, | 2829 | stmt: *const clang.CompoundAssignOperator, |
| 2861 | assign_op: ast.Node.Tag, | 2830 | op: Node.Tag, |
| 2862 | assign_tok_id: std.zig.Token.Id, | | |
| 2863 | assign_bytes: []const u8, | | |
| 2864 | bin_op: ast.Node.Tag, | | |
| 2865 | bin_tok_id: std.zig.Token.Id, | | |
| 2866 | bin_bytes: []const u8, | | |
| 2867 | used: ResultUsed, | 2831 | used: ResultUsed, |
| 2868 | ) TransError!*ast.Node { | 2832 | ) TransError!Node { |
| 2869 | const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight; | 2833 | const is_shift = op == .assign_shl or op == .assign_shr; |
| 2870 | const is_div = bin_op == .Div; | 2834 | const is_div = op == .assign_div; |
| 2871 | const is_mod = bin_op == .Mod; | 2835 | const is_mod = op == .assign_mod; |
| 2872 | const lhs = stmt.getLHS(); | 2836 | const lhs = stmt.getLHS(); |
| 2873 | const rhs = stmt.getRHS(); | 2837 | const rhs = stmt.getRHS(); |
| 2874 | const loc = stmt.getBeginLoc(); | 2838 | const loc = stmt.getBeginLoc(); |
| 2875 | const lhs_qt = getExprQualType(rp.c, lhs); | 2839 | const lhs_qt = getExprQualType(c, lhs); |
| 2876 | const rhs_qt = getExprQualType(rp.c, rhs); | 2840 | const rhs_qt = getExprQualType(c, rhs); |
| 2877 | const is_signed = cIsSignedInteger(lhs_qt); | 2841 | const is_signed = cIsSignedInteger(lhs_qt); |
| 2878 | const requires_int_cast = blk: { | 2842 | const requires_int_cast = blk: { |
| 2879 | const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt); | 2843 | const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt); |
| ... | @@ -2885,146 +2849,99 @@ fn transCreateCompoundAssign( | ... | @@ -2885,146 +2849,99 @@ fn transCreateCompoundAssign( |
| 2885 | // c: lhs += rhs | 2849 | // c: lhs += rhs |
| 2886 | // zig: lhs += rhs | 2850 | // zig: lhs += rhs |
| 2887 | if ((is_mod or is_div) and is_signed) { | 2851 | if ((is_mod or is_div) and is_signed) { |
| 2888 | const op_token = try appendToken(rp.c, .Equal, "="); | 2852 | const lhs_node = try transExpr(c, scope, lhs, .used, .l_value); |
| 2889 | const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | 2853 | const rhs_node = try transExpr(c, scope, rhs, .used, .r_value); |
| 2890 | const builtin = if (is_mod) "@rem" else "@divTrunc"; | 2854 | const builtin = if (is_mod) |
| 2891 | const builtin_node = try rp.c.createBuiltinCall(builtin, 2); | 2855 | try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node }) |
| 2892 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); | 2856 | else |
| 2893 | builtin_node.params()[0] = lhs_node; | 2857 | try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node }); |
| 2894 | _ = try appendToken(rp.c, .Comma, ","); | 2858 | |
| 2895 | builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value); | 2859 | return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used); |
| 2896 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 2897 | op_node.* = .{ | | |
| 2898 | .base = .{ .tag = .Assign }, | | |
| 2899 | .op_token = op_token, | | |
| 2900 | .lhs = lhs_node, | | |
| 2901 | .rhs = &builtin_node.base, | | |
| 2902 | }; | | |
| 2903 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 2904 | return &op_node.base; | | |
| 2905 | } | 2860 | } |
| 2906 | | 2861 | |
| 2907 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); | 2862 | const lhs_node = try transExpr(c, scope, lhs, .used, .l_value); |
| 2908 | const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes); | | |
| 2909 | var rhs_node = if (is_shift or requires_int_cast) | 2863 | var rhs_node = if (is_shift or requires_int_cast) |
| 2910 | try transExprCoercing(rp, scope, rhs, .used, .r_value) | 2864 | try transExprCoercing(c, scope, rhs, .used, .r_value) |
| 2911 | else | 2865 | else |
| 2912 | try transExpr(rp, scope, rhs, .used, .r_value); | 2866 | try transExpr(c, scope, rhs, .used, .r_value); |
| 2913 | | 2867 | |
| 2914 | if (is_shift or requires_int_cast) { | 2868 | if (is_shift or requires_int_cast) { |
| 2915 | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); | 2869 | // @intCast(rhs) |
| 2916 | const cast_to_type = if (is_shift) | 2870 | const cast_to_type = if (is_shift) |
| 2917 | try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc) | 2871 | try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc) |
| 2918 | else | 2872 | else |
| 2919 | try transQualType(rp, getExprQualType(rp.c, lhs), loc); | 2873 | try transQualType(c, getExprQualType(c, lhs), loc); |
| 2920 | cast_node.params()[0] = cast_to_type; | 2874 | |
| 2921 | _ = try appendToken(rp.c, .Comma, ","); | 2875 | rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 2922 | cast_node.params()[1] = rhs_node; | | |
| 2923 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 2924 | rhs_node = &cast_node.base; | | |
| 2925 | } | 2876 | } |
| 2926 | if (scope.id != .Condition) | 2877 | |
| 2927 | _ = try appendToken(rp.c, .Semicolon, ";"); | 2878 | return transCreateNodeInfixOp(c, scope, assign_op, lhs_node, rhs_node, .used); |
| 2928 | return transCreateNodeInfixOp(rp, scope, lhs_node, assign_op, eq_token, rhs_node, .used, false); | | |
| 2929 | } | 2879 | } |
| 2930 | // worst case | 2880 | // worst case |
| 2931 | // c: lhs += rhs | 2881 | // c: lhs += rhs |
| 2932 | // zig: (blk: { | 2882 | // zig: (blk: { |
| 2933 | // zig: const _ref = &lhs; | 2883 | // zig: const _ref = &lhs; |
| 2934 | // zig: _ref.* = _ref.* + rhs; | 2884 | // zig: _ref.* += rhs; |
| 2935 | // zig: break :blk _ref.* | 2885 | // zig: break :blk _ref.* |
| 2936 | // zig: }) | 2886 | // zig: }) |
| 2937 | var block_scope = try Scope.Block.init(rp.c, scope, true); | 2887 | var block_scope = try Scope.Block.init(c, scope, true); |
| 2938 | defer block_scope.deinit(); | 2888 | defer block_scope.deinit(); |
| 2939 | const ref = try block_scope.makeMangledName(rp.c, "ref"); | 2889 | const ref = try block_scope.makeMangledName(c, "ref"); |
| 2940 | | | |
| 2941 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); | | |
| 2942 | const name_tok = try appendIdentifier(rp.c, ref); | | |
| 2943 | const eq_token = try appendToken(rp.c, .Equal, "="); | | |
| 2944 | const addr_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); | | |
| 2945 | addr_node.rhs = try transExpr(rp, scope, lhs, .used, .l_value); | | |
| 2946 | const init_node = &addr_node.base; | | |
| 2947 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | | |
| 2948 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ | | |
| 2949 | .name_token = name_tok, | | |
| 2950 | .mut_token = mut_tok, | | |
| 2951 | .semicolon_token = semicolon_token, | | |
| 2952 | }, .{ | | |
| 2953 | .eq_token = eq_token, | | |
| 2954 | .init_node = init_node, | | |
| 2955 | }); | | |
| 2956 | try block_scope.statements.append(&node.base); | | |
| 2957 | | 2890 | |
| 2958 | const lhs_node = try transCreateNodeIdentifier(rp.c, ref); | 2891 | const expr = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2959 | const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node); | 2892 | const addr_of = try Node.address_of.create(c.arena, expr); |
| 2960 | _ = try appendToken(rp.c, .Semicolon, ";"); | 2893 | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of}); |
| | 2894 | try block_scope.statements.append(ref_decl); |
| | 2895 | |
| | 2896 | const lhs_node = try Node.identifier.create(c.arena, ref); |
| | 2897 | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2961 | | 2898 | |
| 2962 | if ((is_mod or is_div) and is_signed) { | 2899 | if ((is_mod or is_div) and is_signed) { |
| 2963 | const op_token = try appendToken(rp.c, .Equal, "="); | 2900 | const rhs_node = try transExpr(c, scope, rhs, .used, .r_value); |
| 2964 | const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | 2901 | const builtin = if (is_mod) |
| 2965 | const builtin = if (is_mod) "@rem" else "@divTrunc"; | 2902 | try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node }) |
| 2966 | const builtin_node = try rp.c.createBuiltinCall(builtin, 2); | 2903 | else |
| 2967 | builtin_node.params()[0] = try transCreateNodePtrDeref(rp.c, lhs_node); | 2904 | try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node }); |
| 2968 | _ = try appendToken(rp.c, .Comma, ","); | 2905 | |
| 2969 | builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value); | 2906 | const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used); |
| 2970 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 2907 | try block_scope.statements.append(assign); |
| 2971 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 2972 | op_node.* = .{ | | |
| 2973 | .base = .{ .tag = .Assign }, | | |
| 2974 | .op_token = op_token, | | |
| 2975 | .lhs = ref_node, | | |
| 2976 | .rhs = &builtin_node.base, | | |
| 2977 | }; | | |
| 2978 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 2979 | try block_scope.statements.append(&op_node.base); | | |
| 2980 | } else { | 2908 | } else { |
| 2981 | const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes); | 2909 | var rhs_node = try transExpr(c, scope, rhs, .used, .r_value); |
| 2982 | var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); | | |
| 2983 | | 2910 | |
| 2984 | if (is_shift or requires_int_cast) { | 2911 | if (is_shift or requires_int_cast) { |
| 2985 | const cast_node = try rp.c.createBuiltinCall("@intCast", 2); | 2912 | // @intCast(rhs) |
| 2986 | const cast_to_type = if (is_shift) | 2913 | const cast_to_type = if (is_shift) |
| 2987 | try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc) | 2914 | try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc) |
| 2988 | else | 2915 | else |
| 2989 | try transQualType(rp, getExprQualType(rp.c, lhs), loc); | 2916 | try transQualType(c, getExprQualType(c, lhs), loc); |
| 2990 | cast_node.params()[0] = cast_to_type; | 2917 | |
| 2991 | _ = try appendToken(rp.c, .Comma, ","); | 2918 | rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 2992 | cast_node.params()[1] = rhs_node; | | |
| 2993 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 2994 | rhs_node = &cast_node.base; | | |
| 2995 | } | 2919 | } |
| 2996 | | 2920 | |
| 2997 | const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false); | 2921 | const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used); |
| 2998 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 2999 | | | |
| 3000 | const ass_eq_token = try appendToken(rp.c, .Equal, "="); | | |
| 3001 | const assign = try transCreateNodeInfixOp(rp, scope, ref_node, .Assign, ass_eq_token, rhs_bin, .used, false); | | |
| 3002 | try block_scope.statements.append(assign); | 2922 | try block_scope.statements.append(assign); |
| 3003 | } | 2923 | } |
| 3004 | | 2924 | |
| 3005 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node); | 2925 | const break_node = try Node.break_val.create(c.arena, .{ |
| 3006 | try block_scope.statements.append(&break_node.base); | 2926 | .label = block_scope.label, |
| 3007 | const block_node = try block_scope.complete(rp.c); | 2927 | .val = ref_node, |
| 3008 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); | 2928 | }); |
| 3009 | grouped_expr.* = .{ | 2929 | try block_scope.statements.append(break_node); |
| 3010 | .lparen = try appendToken(rp.c, .LParen, "("), | 2930 | return block_scope.complete(c); |
| 3011 | .expr = block_node, | | |
| 3012 | .rparen = try appendToken(rp.c, .RParen, ")"), | | |
| 3013 | }; | | |
| 3014 | return &grouped_expr.base; | | |
| 3015 | } | 2931 | } |
| 3016 | | 2932 | |
| 3017 | fn transCPtrCast( | 2933 | fn transCPtrCast( |
| 3018 | rp: RestorePoint, | 2934 | c: *Context, |
| 3019 | loc: clang.SourceLocation, | 2935 | loc: clang.SourceLocation, |
| 3020 | dst_type: clang.QualType, | 2936 | dst_type: clang.QualType, |
| 3021 | src_type: clang.QualType, | 2937 | src_type: clang.QualType, |
| 3022 | expr: *ast.Node, | 2938 | expr: Node, |
| 3023 | ) !*ast.Node { | 2939 | ) !Node { |
| 3024 | const ty = dst_type.getTypePtr(); | 2940 | const ty = dst_type.getTypePtr(); |
| 3025 | const child_type = ty.getPointeeType(); | 2941 | const child_type = ty.getPointeeType(); |
| 3026 | const src_ty = src_type.getTypePtr(); | 2942 | const src_ty = src_type.getTypePtr(); |
| 3027 | const src_child_type = src_ty.getPointeeType(); | 2943 | const src_child_type = src_ty.getPointeeType(); |
| | 2944 | const dst_type = try transType(c, ty, loc); |
| 3028 | | 2945 | |
| 3029 | if ((src_child_type.isConstQualified() and | 2946 | if ((src_child_type.isConstQualified() and |
| 3030 | !child_type.isConstQualified()) or | 2947 | !child_type.isConstQualified()) or |
| ... | @@ -3032,47 +2949,25 @@ fn transCPtrCast( | ... | @@ -3032,47 +2949,25 @@ fn transCPtrCast( |
| 3032 | !child_type.isVolatileQualified())) | 2949 | !child_type.isVolatileQualified())) |
| 3033 | { | 2950 | { |
| 3034 | // Casting away const or volatile requires us to use @intToPtr | 2951 | // Casting away const or volatile requires us to use @intToPtr |
| 3035 | const inttoptr_node = try rp.c.createBuiltinCall("@intToPtr", 2); | 2952 | const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr); |
| 3036 | const dst_type_node = try transType(rp, ty, loc); | 2953 | const int_to_ptr = try Node.int_to_ptr.create(c.arena, .{ .lhs = dst_type, .rhs = ptr_to_int }); |
| 3037 | inttoptr_node.params()[0] = dst_type_node; | 2954 | return int_to_ptr; |
| 3038 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 3039 | | | |
| 3040 | const ptrtoint_node = try rp.c.createBuiltinCall("@ptrToInt", 1); | | |
| 3041 | ptrtoint_node.params()[0] = expr; | | |
| 3042 | ptrtoint_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 3043 | | | |
| 3044 | inttoptr_node.params()[1] = &ptrtoint_node.base; | | |
| 3045 | inttoptr_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 3046 | return &inttoptr_node.base; | | |
| 3047 | } else { | 2955 | } else { |
| 3048 | // Implicit downcasting from higher to lower alignment values is forbidden, | 2956 | // Implicit downcasting from higher to lower alignment values is forbidden, |
| 3049 | // use @alignCast to side-step this problem | 2957 | // use @alignCast to side-step this problem |
| 3050 | const ptrcast_node = try rp.c.createBuiltinCall("@ptrCast", 2); | 2958 | const rhs = if (qualTypeCanon(child_type).isVoidType()) |
| 3051 | const dst_type_node = try transType(rp, ty, loc); | | |
| 3052 | ptrcast_node.params()[0] = dst_type_node; | | |
| 3053 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 3054 | | | |
| 3055 | if (qualTypeCanon(child_type).isVoidType()) { | | |
| 3056 | // void has 1-byte alignment, so @alignCast is not needed | 2959 | // void has 1-byte alignment, so @alignCast is not needed |
| 3057 | ptrcast_node.params()[1] = expr; | 2960 | expr |
| 3058 | } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) { | 2961 | else if (typeIsOpaque(c, qualTypeCanon(child_type), loc)) |
| 3059 | // For opaque types a ptrCast is enough | 2962 | // For opaque types a ptrCast is enough |
| 3060 | ptrcast_node.params()[1] = expr; | 2963 | expr |
| 3061 | } else { | 2964 | else blk: { |
| 3062 | const aligncast_node = try rp.c.createBuiltinCall("@alignCast", 2); | 2965 | const child_type_node = try transQualType(c, child_type, loc); |
| 3063 | const alignof_node = try rp.c.createBuiltinCall("@alignOf", 1); | 2966 | const alignof = try Node.alignof.create(c.arena, child_type_node); |
| 3064 | const child_type_node = try transQualType(rp, child_type, loc); | 2967 | const align_cast = try Node.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr }); |
| 3065 | alignof_node.params()[0] = child_type_node; | 2968 | break :blk align_cast; |
| 3066 | alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 2969 | }; |
| 3067 | aligncast_node.params()[0] = &alignof_node.base; | 2970 | return Node.ptr_cast.create(c.arena, .{ .lhs = dst_type, .rhs = rhs }); |
| 3068 | _ = try appendToken(rp.c, .Comma, ","); | | |
| 3069 | aligncast_node.params()[1] = expr; | | |
| 3070 | aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 3071 | ptrcast_node.params()[1] = &aligncast_node.base; | | |
| 3072 | } | | |
| 3073 | ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 3074 | | | |
| 3075 | return &ptrcast_node.base; | | |
| 3076 | } | 2971 | } |
| 3077 | } | 2972 | } |
| 3078 | | 2973 | |
| ... | @@ -3092,13 +2987,15 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node { | ... | @@ -3092,13 +2987,15 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node { |
| 3092 | fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node { | 2987 | fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node { |
| 3093 | // TODO use something more accurate | 2988 | // TODO use something more accurate |
| 3094 | const dbl = stmt.getValueAsApproximateDouble(); | 2989 | const dbl = stmt.getValueAsApproximateDouble(); |
| 3095 | const node = try Node.float_literal.create(c.arena, try std.fmt.allocPrint(c.arena, "{d}", .{dbl})); | 2990 | const node = try transCreateNodeNumber(c, dbl); |
| 3096 | return maybeSuppressResult(c, scope, used, &node.base); | 2991 | return maybeSuppressResult(c, scope, used, &node.base); |
| 3097 | } | 2992 | } |
| 3098 | | 2993 | |
| 3099 | fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!*ast.Node { | 2994 | fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node { |
| 3100 | // GNU extension of the ternary operator where the middle expression is | 2995 | // GNU extension of the ternary operator where the middle expression is |
| 3101 | // omitted, the conditition itself is returned if it evaluates to true | 2996 | // omitted, the conditition itself is returned if it evaluates to true |
| | 2997 | const qt = @ptrCast(*const clang.Stmt, stmt).getType(); |
| | 2998 | const res_is_bool = qualTypeIsBoolean(qt); |
| 3102 | const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt); | 2999 | const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt); |
| 3103 | const cond_expr = casted_stmt.getCond(); | 3000 | const cond_expr = casted_stmt.getCond(); |
| 3104 | const true_expr = casted_stmt.getTrueExpr(); | 3001 | const true_expr = casted_stmt.getTrueExpr(); |
| ... | @@ -3109,67 +3006,39 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const | ... | @@ -3109,67 +3006,39 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const |
| 3109 | // const _cond_temp = (cond_expr); | 3006 | // const _cond_temp = (cond_expr); |
| 3110 | // break :blk if (_cond_temp) _cond_temp else (false_expr); | 3007 | // break :blk if (_cond_temp) _cond_temp else (false_expr); |
| 3111 | // }) | 3008 | // }) |
| 3112 | const lparen = try appendToken(rp.c, .LParen, "("); | 3009 | var block_scope = try Scope.Block.init(c, scope, true); |
| 3113 | | | |
| 3114 | var block_scope = try Scope.Block.init(rp.c, scope, true); | | |
| 3115 | defer block_scope.deinit(); | 3010 | defer block_scope.deinit(); |
| 3116 | | 3011 | |
| 3117 | const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp"); | 3012 | const mangled_name = try block_scope.makeMangledName(c, "cond_temp"); |
| 3118 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); | 3013 | const init_node = try transExpr(c, &block_scope.base, cond_expr, .used, .r_value); |
| 3119 | const name_tok = try appendIdentifier(rp.c, mangled_name); | 3014 | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node}); |
| 3120 | const eq_token = try appendToken(rp.c, .Equal, "="); | 3015 | try block_scope.statements.append(ref_decl); |
| 3121 | const init_node = try transExpr(rp, &block_scope.base, cond_expr, .used, .r_value); | | |
| 3122 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3123 | const tmp_var = try ast.Node.VarDecl.create(rp.c.arena, .{ | | |
| 3124 | .name_token = name_tok, | | |
| 3125 | .mut_token = mut_tok, | | |
| 3126 | .semicolon_token = semicolon_token, | | |
| 3127 | }, .{ | | |
| 3128 | .eq_token = eq_token, | | |
| 3129 | .init_node = init_node, | | |
| 3130 | }); | | |
| 3131 | try block_scope.statements.append(&tmp_var.base); | | |
| 3132 | | | |
| 3133 | var break_node_tmp = try CtrlFlow.initToken(rp.c, .Break, block_scope.label); | | |
| 3134 | | | |
| 3135 | const if_node = try transCreateNodeIf(rp.c); | | |
| 3136 | var cond_scope = Scope.Condition{ | | |
| 3137 | .base = .{ | | |
| 3138 | .parent = &block_scope.base, | | |
| 3139 | .id = .Condition, | | |
| 3140 | }, | | |
| 3141 | }; | | |
| 3142 | defer cond_scope.deinit(); | | |
| 3143 | const tmp_var_node = try transCreateNodeIdentifier(rp.c, mangled_name); | | |
| 3144 | | | |
| 3145 | const ty = getExprQualType(rp.c, cond_expr).getTypePtr(); | | |
| 3146 | const cond_node = try finishBoolExpr(rp, &cond_scope.base, cond_expr.getBeginLoc(), ty, tmp_var_node, used); | | |
| 3147 | if_node.condition = cond_node; | | |
| 3148 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 3149 | | | |
| 3150 | if_node.body = try transCreateNodeIdentifier(rp.c, mangled_name); | | |
| 3151 | if_node.@"else" = try transCreateNodeElse(rp.c); | | |
| 3152 | if_node.@"else".?.body = try transExpr(rp, &block_scope.base, false_expr, .used, .r_value); | | |
| 3153 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3154 | | 3016 | |
| 3155 | const break_node = try break_node_tmp.finish(&if_node.base); | 3017 | const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used); |
| 3156 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3018 | var then_body = try Node.identifier.create(c.arena, mangled_name); |
| 3157 | try block_scope.statements.append(&break_node.base); | 3019 | if (!res_is_bool and isBoolRes(init_node)) { |
| 3158 | const block_node = try block_scope.complete(rp.c); | 3020 | then_body = try Node.bool_to_int.create(c.arena, then_body); |
| | 3021 | } |
| 3159 | | 3022 | |
| 3160 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); | 3023 | var else_body = try transExpr(c, &block_scope.base, false_expr, .used, .r_value); |
| 3161 | grouped_expr.* = .{ | 3024 | if (!res_is_bool and isBoolRes(else_body)) { |
| 3162 | .lparen = lparen, | 3025 | else_body = try Node.bool_to_int.create(c.arena, else_body); |
| 3163 | .expr = block_node, | 3026 | } |
| 3164 | .rparen = try appendToken(rp.c, .RParen, ")"), | 3027 | const if_node = try Node.@"if".create(c.arena, .{ |
| 3165 | }; | 3028 | .cond = cond, |
| 3166 | return maybeSuppressResult(rp, scope, used, &grouped_expr.base); | 3029 | .then = then_body, |
| | 3030 | .@"else" = else_body, |
| | 3031 | }); |
| | 3032 | const break_node = try Node.break_val.create(c.arena, .{ |
| | 3033 | .label = block_scope.label, |
| | 3034 | .val = if_node, |
| | 3035 | }); |
| | 3036 | try block_scope.statements.append(break_node); |
| | 3037 | const res = try block_scope.complete(c); |
| | 3038 | return maybeSuppressResult(c, scope, used, res); |
| 3167 | } | 3039 | } |
| 3168 | | 3040 | |
| 3169 | fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.ConditionalOperator, used: ResultUsed) TransError!*ast.Node { | 3041 | fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.ConditionalOperator, used: ResultUsed) TransError!Node { |
| 3170 | const grouped = scope.id == .Condition; | | |
| 3171 | const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined; | | |
| 3172 | const if_node = try transCreateNodeIf(rp.c); | | |
| 3173 | var cond_scope = Scope.Condition{ | 3042 | var cond_scope = Scope.Condition{ |
| 3174 | .base = .{ | 3043 | .base = .{ |
| 3175 | .parent = scope, | 3044 | .parent = scope, |
| ... | @@ -3178,60 +3047,41 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang. | ... | @@ -3178,60 +3047,41 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang. |
| 3178 | }; | 3047 | }; |
| 3179 | defer cond_scope.deinit(); | 3048 | defer cond_scope.deinit(); |
| 3180 | | 3049 | |
| | 3050 | const qt = @ptrCast(*const clang.Stmt, stmt).getType(); |
| | 3051 | const res_is_bool = qualTypeIsBoolean(qt); |
| 3181 | const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt); | 3052 | const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt); |
| 3182 | const cond_expr = casted_stmt.getCond(); | 3053 | const cond_expr = casted_stmt.getCond(); |
| 3183 | const true_expr = casted_stmt.getTrueExpr(); | 3054 | const true_expr = casted_stmt.getTrueExpr(); |
| 3184 | const false_expr = casted_stmt.getFalseExpr(); | 3055 | const false_expr = casted_stmt.getFalseExpr(); |
| 3185 | | 3056 | |
| 3186 | if_node.condition = try transBoolExpr(rp, &cond_scope.base, cond_expr, .used, .r_value, false); | 3057 | const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value); |
| 3187 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 3188 | | | |
| 3189 | if_node.body = try transExpr(rp, scope, true_expr, .used, .r_value); | | |
| 3190 | | 3058 | |
| 3191 | if_node.@"else" = try transCreateNodeElse(rp.c); | 3059 | var then_body = try transExpr(c, scope, true_expr, .used, .r_value); |
| 3192 | if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value); | 3060 | if (!res_is_bool and isBoolRes(then_body)) { |
| | 3061 | then_body = try Node.bool_to_int.create(c.arena, then_body); |
| | 3062 | } |
| 3193 | | 3063 | |
| 3194 | if (grouped) { | 3064 | var else_body = try transExpr(c, scope, false_expr, .used, .r_value); |
| 3195 | const rparen = try appendToken(rp.c, .RParen, ")"); | 3065 | if (!res_is_bool and isBoolRes(else_body)) { |
| 3196 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); | 3066 | else_body = try Node.bool_to_int.create(c.arena, else_body); |
| 3197 | grouped_expr.* = .{ | | |
| 3198 | .lparen = lparen, | | |
| 3199 | .expr = &if_node.base, | | |
| 3200 | .rparen = rparen, | | |
| 3201 | }; | | |
| 3202 | return maybeSuppressResult(rp, scope, used, &grouped_expr.base); | | |
| 3203 | } else { | | |
| 3204 | return maybeSuppressResult(rp, scope, used, &if_node.base); | | |
| 3205 | } | 3067 | } |
| | 3068 | |
| | 3069 | const if_node = try Node.@"if".create(c.arena, .{ |
| | 3070 | .cond = cond, |
| | 3071 | .then = then_body, |
| | 3072 | .@"else" = else_body, |
| | 3073 | }); |
| | 3074 | return maybeSuppressResult(c, scope, used, if_node); |
| 3206 | } | 3075 | } |
| 3207 | | 3076 | |
| 3208 | fn maybeSuppressResult( | 3077 | fn maybeSuppressResult( |
| 3209 | rp: RestorePoint, | 3078 | c: *Context, |
| 3210 | scope: *Scope, | 3079 | scope: *Scope, |
| 3211 | used: ResultUsed, | 3080 | used: ResultUsed, |
| 3212 | result: *ast.Node, | 3081 | result: Node, |
| 3213 | ) TransError!*ast.Node { | 3082 | ) TransError!Node { |
| 3214 | if (used == .used) return result; | 3083 | if (used == .used) return result; |
| 3215 | if (scope.id != .Condition) { | 3084 | return Node.ignore.create(c.arena, result); |
| 3216 | // NOTE: This is backwards, but the semicolon must immediately follow the node. | | |
| 3217 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3218 | } else { // TODO is there a way to avoid this hack? | | |
| 3219 | // this parenthesis must come immediately following the node | | |
| 3220 | _ = try appendToken(rp.c, .RParen, ")"); | | |
| 3221 | // these need to come before _ | | |
| 3222 | _ = try appendToken(rp.c, .Colon, ":"); | | |
| 3223 | _ = try appendToken(rp.c, .LParen, "("); | | |
| 3224 | } | | |
| 3225 | const lhs = try transCreateNodeIdentifier(rp.c, "_"); | | |
| 3226 | const op_token = try appendToken(rp.c, .Equal, "="); | | |
| 3227 | const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); | | |
| 3228 | op_node.* = .{ | | |
| 3229 | .base = .{ .tag = .Assign }, | | |
| 3230 | .op_token = op_token, | | |
| 3231 | .lhs = lhs, | | |
| 3232 | .rhs = result, | | |
| 3233 | }; | | |
| 3234 | return &op_node.base; | | |
| 3235 | } | 3085 | } |
| 3236 | | 3086 | |
| 3237 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { | 3087 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { |
| ... | @@ -3242,11 +3092,11 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { | ... | @@ -3242,11 +3092,11 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { |
| 3242 | /// only matters for incomplete arrays, since the size of the array is determined | 3092 | /// only matters for incomplete arrays, since the size of the array is determined |
| 3243 | /// by the size of the initializer | 3093 | /// by the size of the initializer |
| 3244 | fn transQualTypeInitialized( | 3094 | fn transQualTypeInitialized( |
| 3245 | rp: RestorePoint, | 3095 | c: *Context, |
| 3246 | qt: clang.QualType, | 3096 | qt: clang.QualType, |
| 3247 | decl_init: *const clang.Expr, | 3097 | decl_init: *const clang.Expr, |
| 3248 | source_loc: clang.SourceLocation, | 3098 | source_loc: clang.SourceLocation, |
| 3249 | ) TypeError!*ast.Node { | 3099 | ) TypeError!Node { |
| 3250 | const ty = qt.getTypePtr(); | 3100 | const ty = qt.getTypePtr(); |
| 3251 | if (ty.getTypeClass() == .IncompleteArray) { | 3101 | if (ty.getTypeClass() == .IncompleteArray) { |
| 3252 | const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty); | 3102 | const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty); |
| ... | @@ -3257,17 +3107,17 @@ fn transQualTypeInitialized( | ... | @@ -3257,17 +3107,17 @@ fn transQualTypeInitialized( |
| 3257 | const string_lit = @ptrCast(*const clang.StringLiteral, decl_init); | 3107 | const string_lit = @ptrCast(*const clang.StringLiteral, decl_init); |
| 3258 | const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator | 3108 | const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator |
| 3259 | const array_size = @intCast(usize, string_lit_size); | 3109 | const array_size = @intCast(usize, string_lit_size); |
| 3260 | return transCreateNodeArrayType(rp, source_loc, elem_ty, array_size); | 3110 | return Node.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty }); |
| 3261 | }, | 3111 | }, |
| 3262 | .InitListExprClass => { | 3112 | .InitListExprClass => { |
| 3263 | const init_expr = @ptrCast(*const clang.InitListExpr, decl_init); | 3113 | const init_expr = @ptrCast(*const clang.InitListExpr, decl_init); |
| 3264 | const size = init_expr.getNumInits(); | 3114 | const size = init_expr.getNumInits(); |
| 3265 | return transCreateNodeArrayType(rp, source_loc, elem_ty, size); | 3115 | return Node.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty }); |
| 3266 | }, | 3116 | }, |
| 3267 | else => {}, | 3117 | else => {}, |
| 3268 | } | 3118 | } |
| 3269 | } | 3119 | } |
| 3270 | return transQualType(rp, qt, source_loc); | 3120 | return transQualType(c, qt, source_loc); |
| 3271 | } | 3121 | } |
| 3272 | | 3122 | |
| 3273 | fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node { | 3123 | fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocation) TypeError!Node { |
| ... | @@ -3276,16 +3126,16 @@ fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocati | ... | @@ -3276,16 +3126,16 @@ fn transQualType(c: *Context, qt: clang.QualType, source_loc: clang.SourceLocati |
| 3276 | | 3126 | |
| 3277 | /// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness. | 3127 | /// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness. |
| 3278 | /// Asserts the type is an integer. | 3128 | /// Asserts the type is an integer. |
| 3279 | fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) TypeError!*ast.Node { | 3129 | fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) TypeError!Node { |
| 3280 | return transTypeIntWidthOf(c, qualTypeCanon(ty), is_signed); | 3130 | return transTypeIntWidthOf(c, qualTypeCanon(ty), is_signed); |
| 3281 | } | 3131 | } |
| 3282 | | 3132 | |
| 3283 | /// Produces a Zig AST node by translating a Clang Type, respecting the width, but modifying the signed-ness. | 3133 | /// Produces a Zig AST node by translating a Clang Type, respecting the width, but modifying the signed-ness. |
| 3284 | /// Asserts the type is an integer. | 3134 | /// Asserts the type is an integer. |
| 3285 | fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!*ast.Node { | 3135 | fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!Node { |
| 3286 | assert(ty.getTypeClass() == .Builtin); | 3136 | assert(ty.getTypeClass() == .Builtin); |
| 3287 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); | 3137 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); |
| 3288 | return transCreateNodeIdentifier(c, switch (builtin_ty.getKind()) { | 3138 | return Node.type.create(c.arena, switch (builtin_ty.getKind()) { |
| 3289 | .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8", | 3139 | .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8", |
| 3290 | .UShort, .Short => if (is_signed) "c_short" else "c_ushort", | 3140 | .UShort, .Short => if (is_signed) "c_short" else "c_ushort", |
| 3291 | .UInt, .Int => if (is_signed) "c_int" else "c_uint", | 3141 | .UInt, .Int => if (is_signed) "c_int" else "c_uint", |
| ... | @@ -3532,28 +3382,22 @@ fn cIsLongLongInteger(qt: clang.QualType) bool { | ... | @@ -3532,28 +3382,22 @@ fn cIsLongLongInteger(qt: clang.QualType) bool { |
| 3532 | }; | 3382 | }; |
| 3533 | } | 3383 | } |
| 3534 | fn transCreateNodeAssign( | 3384 | fn transCreateNodeAssign( |
| 3535 | rp: RestorePoint, | 3385 | c: *Context, |
| 3536 | scope: *Scope, | 3386 | scope: *Scope, |
| 3537 | result_used: ResultUsed, | 3387 | result_used: ResultUsed, |
| 3538 | lhs: *const clang.Expr, | 3388 | lhs: *const clang.Expr, |
| 3539 | rhs: *const clang.Expr, | 3389 | rhs: *const clang.Expr, |
| 3540 | ) !*ast.Node { | 3390 | ) !Node { |
| 3541 | // common case | 3391 | // common case |
| 3542 | // c: lhs = rhs | 3392 | // c: lhs = rhs |
| 3543 | // zig: lhs = rhs | 3393 | // zig: lhs = rhs |
| 3544 | if (result_used == .unused) { | 3394 | if (result_used == .unused) { |
| 3545 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); | 3395 | const lhs_node = try transExpr(c, scope, lhs, .used, .l_value); |
| 3546 | const eq_token = try appendToken(rp.c, .Equal, "="); | 3396 | var rhs_node = try transExprCoercing(c, scope, rhs, .used, .r_value); |
| 3547 | var rhs_node = try transExprCoercing(rp, scope, rhs, .used, .r_value); | | |
| 3548 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { | 3397 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { |
| 3549 | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); | 3398 | rhs_node = try Node.bool_to_int.create(c.arena, rhs_node); |
| 3550 | builtin_node.params()[0] = rhs_node; | | |
| 3551 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 3552 | rhs_node = &builtin_node.base; | | |
| 3553 | } | 3399 | } |
| 3554 | if (scope.id != .Condition) | 3400 | return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used); |
| 3555 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3556 | return transCreateNodeInfixOp(rp, scope, lhs_node, .Assign, eq_token, rhs_node, .used, false); | | |
| 3557 | } | 3401 | } |
| 3558 | | 3402 | |
| 3559 | // worst case | 3403 | // worst case |
| ... | @@ -3563,76 +3407,36 @@ fn transCreateNodeAssign( | ... | @@ -3563,76 +3407,36 @@ fn transCreateNodeAssign( |
| 3563 | // zig: lhs = _tmp; | 3407 | // zig: lhs = _tmp; |
| 3564 | // zig: break :blk _tmp | 3408 | // zig: break :blk _tmp |
| 3565 | // zig: }) | 3409 | // zig: }) |
| 3566 | var block_scope = try Scope.Block.init(rp.c, scope, true); | 3410 | var block_scope = try Scope.Block.init(c, scope, true); |
| 3567 | defer block_scope.deinit(); | 3411 | defer block_scope.deinit(); |
| 3568 | | 3412 | |
| 3569 | const tmp = try block_scope.makeMangledName(rp.c, "tmp"); | 3413 | const tmp = try block_scope.makeMangledName(c, "tmp"); |
| 3570 | const mut_tok = try appendToken(rp.c, .Keyword_const, "const"); | 3414 | const rhs = try transExpr(c, scope, op_expr, .used, .r_value); |
| 3571 | const name_tok = try appendIdentifier(rp.c, tmp); | 3415 | const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = rhs}); |
| 3572 | const eq_token = try appendToken(rp.c, .Equal, "="); | 3416 | try block_scope.statements.append(tmp_decl); |
| 3573 | var rhs_node = try transExpr(rp, &block_scope.base, rhs, .used, .r_value); | | |
| 3574 | if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { | | |
| 3575 | const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); | | |
| 3576 | builtin_node.params()[0] = rhs_node; | | |
| 3577 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | | |
| 3578 | rhs_node = &builtin_node.base; | | |
| 3579 | } | | |
| 3580 | const init_node = rhs_node; | | |
| 3581 | const semicolon_token = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3582 | const node = try ast.Node.VarDecl.create(rp.c.arena, .{ | | |
| 3583 | .name_token = name_tok, | | |
| 3584 | .mut_token = mut_tok, | | |
| 3585 | .semicolon_token = semicolon_token, | | |
| 3586 | }, .{ | | |
| 3587 | .eq_token = eq_token, | | |
| 3588 | .init_node = init_node, | | |
| 3589 | }); | | |
| 3590 | try block_scope.statements.append(&node.base); | | |
| 3591 | | 3417 | |
| 3592 | const lhs_node = try transExpr(rp, &block_scope.base, lhs, .used, .l_value); | | |
| 3593 | const lhs_eq_token = try appendToken(rp.c, .Equal, "="); | | |
| 3594 | const ident = try transCreateNodeIdentifier(rp.c, tmp); | | |
| 3595 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3596 | | 3418 | |
| 3597 | const assign = try transCreateNodeInfixOp(rp, &block_scope.base, lhs_node, .Assign, lhs_eq_token, ident, .used, false); | 3419 | const lhs = try transExpr(c, &block_scope.base, lhs, .used, .l_value); |
| | 3420 | const tmp_ident = try Node.identifier.create(c.arena, tmp); |
| | 3421 | const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs, tmp_iden, .used); |
| 3598 | try block_scope.statements.append(assign); | 3422 | try block_scope.statements.append(assign); |
| 3599 | | 3423 | |
| 3600 | const break_node = blk: { | 3424 | const break_node = try Node.break_val.create(c.arena, .{ |
| 3601 | var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, tokenSlice(rp.c, block_scope.label.?)); | 3425 | .label = block_scope.label, |
| 3602 | const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp); | 3426 | .val = tmp_ident, |
| 3603 | break :blk try tmp_ctrl_flow.finish(rhs_expr); | 3427 | }); |
| 3604 | }; | 3428 | try block_scope.statements.append(break_node); |
| 3605 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3429 | return block_scope.complete(c); |
| 3606 | try block_scope.statements.append(&break_node.base); | | |
| 3607 | const block_node = try block_scope.complete(rp.c); | | |
| 3608 | // semicolon must immediately follow rbrace because it is the last token in a block | | |
| 3609 | _ = try appendToken(rp.c, .Semicolon, ";"); | | |
| 3610 | return block_node; | | |
| 3611 | } | | |
| 3612 | | | |
| 3613 | fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node { | | |
| 3614 | const field_access_node = try c.arena.create(ast.Node.SimpleInfixOp); | | |
| 3615 | field_access_node.* = .{ | | |
| 3616 | .base = .{ .tag = .Period }, | | |
| 3617 | .op_token = try appendToken(c, .Period, "."), | | |
| 3618 | .lhs = container, | | |
| 3619 | .rhs = try transCreateNodeIdentifier(c, field_name), | | |
| 3620 | }; | | |
| 3621 | return &field_access_node.base; | | |
| 3622 | } | 3430 | } |
| 3623 | | 3431 | |
| 3624 | fn transCreateNodeBoolInfixOp( | 3432 | fn transCreateNodeInfixOp( |
| 3625 | c: *Context, | 3433 | c: *Context, |
| 3626 | scope: *Scope, | 3434 | scope: *Scope, |
| 3627 | stmt: *const clang.BinaryOperator, | | |
| 3628 | op: ast.Node.Tag, | 3435 | op: ast.Node.Tag, |
| | 3436 | lhs: Node, |
| | 3437 | rhs: Node, |
| 3629 | used: ResultUsed, | 3438 | used: ResultUsed, |
| 3630 | ) !Node { | 3439 | ) !Node { |
| 3631 | std.debug.assert(op == .bool_and or op == .bool_or); | | |
| 3632 | | | |
| 3633 | const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value, true); | | |
| 3634 | const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value, true); | | |
| 3635 | | | |
| 3636 | const payload = try c.arena.create(ast.Payload.BinOp); | 3440 | const payload = try c.arena.create(ast.Payload.BinOp); |
| 3637 | payload.* = .{ | 3441 | payload.* = .{ |
| 3638 | .base = .{ .tag = op }, | 3442 | .base = .{ .tag = op }, |
| ... | @@ -3644,39 +3448,19 @@ fn transCreateNodeBoolInfixOp( | ... | @@ -3644,39 +3448,19 @@ fn transCreateNodeBoolInfixOp( |
| 3644 | return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base)); | 3448 | return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base)); |
| 3645 | } | 3449 | } |
| 3646 | | 3450 | |
| 3647 | fn transCreateNodePtrType( | 3451 | fn transCreateNodeBoolInfixOp( |
| 3648 | c: *Context, | 3452 | c: *Context, |
| 3649 | is_const: bool, | 3453 | scope: *Scope, |
| 3650 | is_volatile: bool, | 3454 | stmt: *const clang.BinaryOperator, |
| 3651 | op_tok_id: std.zig.Token.Id, | 3455 | op: ast.Node.Tag, |
| 3652 | ) !*ast.Node.PtrType { | 3456 | used: ResultUsed, |
| 3653 | const node = try c.arena.create(ast.Node.PtrType); | 3457 | ) !Node { |
| 3654 | const op_token = switch (op_tok_id) { | 3458 | std.debug.assert(op == .bool_and or op == .bool_or); |
| 3655 | .LBracket => blk: { | 3459 | |
| 3656 | const lbracket = try appendToken(c, .LBracket, "["); | 3460 | const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value); |
| 3657 | _ = try appendToken(c, .Asterisk, "*"); | 3461 | const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value); |
| 3658 | _ = try appendToken(c, .RBracket, "]"); | 3462 | |
| 3659 | break :blk lbracket; | 3463 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs, used); |
| 3660 | }, | | |
| 3661 | .Identifier => blk: { | | |
| 3662 | const lbracket = try appendToken(c, .LBracket, "["); // Rendering checks if this token + 2 == .Identifier, so needs to return this token | | |
| 3663 | _ = try appendToken(c, .Asterisk, "*"); | | |
| 3664 | _ = try appendIdentifier(c, "c"); | | |
| 3665 | _ = try appendToken(c, .RBracket, "]"); | | |
| 3666 | break :blk lbracket; | | |
| 3667 | }, | | |
| 3668 | .Asterisk => try appendToken(c, .Asterisk, "*"), | | |
| 3669 | else => unreachable, | | |
| 3670 | }; | | |
| 3671 | node.* = .{ | | |
| 3672 | .op_token = op_token, | | |
| 3673 | .ptr_info = .{ | | |
| 3674 | .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null, | | |
| 3675 | .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null, | | |
| 3676 | }, | | |
| 3677 | .rhs = undefined, // translate and set afterward | | |
| 3678 | }; | | |
| 3679 | return node; | | |
| 3680 | } | 3464 | } |
| 3681 | | 3465 | |
| 3682 | fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node { | 3466 | fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node { |
| ... | @@ -3722,73 +3506,10 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node { | ... | @@ -3722,73 +3506,10 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node { |
| 3722 | return Node.int_literal.create(c.arena, str); | 3506 | return Node.int_literal.create(c.arena, str); |
| 3723 | } | 3507 | } |
| 3724 | | 3508 | |
| 3725 | fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node { | 3509 | fn transCreateNodeNumber(c: *Context, int: anytype) !Node { |
| 3726 | const token = try appendToken(c, .Keyword_undefined, "undefined"); | 3510 | const fmt_s = if (comptime std.meta.trait.isNumber(@TypeOf(int))) "{d}" else "{s}"; |
| 3727 | const node = try c.arena.create(ast.Node.OneToken); | 3511 | const str = try std.fmt.allocPrint(c.arena, fmt_s, .{int}); |
| 3728 | node.* = .{ | 3512 | return Node.int_literal.create(c.arena, str); |
| 3729 | .base = .{ .tag = .UndefinedLiteral }, | | |
| 3730 | .token = token, | | |
| 3731 | }; | | |
| 3732 | return &node.base; | | |
| 3733 | } | | |
| 3734 | | | |
| 3735 | fn transCreateNodeNullLiteral(c: *Context) !*ast.Node { | | |
| 3736 | const token = try appendToken(c, .Keyword_null, "null"); | | |
| 3737 | const node = try c.arena.create(ast.Node.OneToken); | | |
| 3738 | node.* = .{ | | |
| 3739 | .base = .{ .tag = .NullLiteral }, | | |
| 3740 | .token = token, | | |
| 3741 | }; | | |
| 3742 | return &node.base; | | |
| 3743 | } | | |
| 3744 | | | |
| 3745 | fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node { | | |
| 3746 | const token = if (value) | | |
| 3747 | try appendToken(c, .Keyword_true, "true") | | |
| 3748 | else | | |
| 3749 | try appendToken(c, .Keyword_false, "false"); | | |
| 3750 | const node = try c.arena.create(ast.Node.OneToken); | | |
| 3751 | node.* = .{ | | |
| 3752 | .base = .{ .tag = .BoolLiteral }, | | |
| 3753 | .token = token, | | |
| 3754 | }; | | |
| 3755 | return &node.base; | | |
| 3756 | } | | |
| 3757 | | | |
| 3758 | fn transCreateNodeInt(c: *Context, int: anytype) !*ast.Node { | | |
| 3759 | const fmt_s = if (comptime std.meta.trait.isIntegerNumber(@TypeOf(int))) "{d}" else "{s}"; | | |
| 3760 | const token = try appendTokenFmt(c, .IntegerLiteral, fmt_s, .{int}); | | |
| 3761 | const node = try c.arena.create(ast.Node.OneToken); | | |
| 3762 | node.* = .{ | | |
| 3763 | .base = .{ .tag = .IntegerLiteral }, | | |
| 3764 | .token = token, | | |
| 3765 | }; | | |
| 3766 | return &node.base; | | |
| 3767 | } | | |
| 3768 | | | |
| 3769 | fn transCreateNodeFloat(c: *Context, str: []const u8) !*ast.Node { | | |
| 3770 | const token = try appendTokenFmt(c, .FloatLiteral, "{s}", .{str}); | | |
| 3771 | const node = try c.arena.create(ast.Node.OneToken); | | |
| 3772 | node.* = .{ | | |
| 3773 | .base = .{ .tag = .FloatLiteral }, | | |
| 3774 | .token = token, | | |
| 3775 | }; | | |
| 3776 | return &node.base; | | |
| 3777 | } | | |
| 3778 | | | |
| 3779 | fn transCreateNodeOpaqueType(c: *Context) !*ast.Node { | | |
| 3780 | const container_tok = try appendToken(c, .Keyword_opaque, "opaque"); | | |
| 3781 | const lbrace_token = try appendToken(c, .LBrace, "{"); | | |
| 3782 | const container_node = try ast.Node.ContainerDecl.alloc(c.arena, 0); | | |
| 3783 | container_node.* = .{ | | |
| 3784 | .kind_token = container_tok, | | |
| 3785 | .layout_token = null, | | |
| 3786 | .lbrace_token = lbrace_token, | | |
| 3787 | .rbrace_token = try appendToken(c, .RBrace, "}"), | | |
| 3788 | .fields_and_decls_len = 0, | | |
| 3789 | .init_arg_expr = .None, | | |
| 3790 | }; | | |
| 3791 | return &container_node.base; | | |
| 3792 | } | 3513 | } |
| 3793 | | 3514 | |
| 3794 | fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_alias: *ast.Node.FnProto) !*ast.Node { | 3515 | fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_alias: *ast.Node.FnProto) !*ast.Node { |
| ... | @@ -3873,13 +3594,12 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a | ... | @@ -3873,13 +3594,12 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a |
| 3873 | return &fn_proto.base; | 3594 | return &fn_proto.base; |
| 3874 | } | 3595 | } |
| 3875 | | 3596 | |
| 3876 | | | |
| 3877 | | | |
| 3878 | fn transCreateNodeShiftOp( | 3597 | fn transCreateNodeShiftOp( |
| 3879 | c: *Context, | 3598 | c: *Context, |
| 3880 | scope: *Scope, | 3599 | scope: *Scope, |
| 3881 | stmt: *const clang.BinaryOperator, | 3600 | stmt: *const clang.BinaryOperator, |
| 3882 | op: Node.Tag, | 3601 | op: Node.Tag, |
| | 3602 | used: ResultUsed, |
| 3883 | ) !Node { | 3603 | ) !Node { |
| 3884 | std.debug.assert(op == .shl or op == .shr); | 3604 | std.debug.assert(op == .shl or op == .shr); |
| 3885 | | 3605 | |
| ... | @@ -3894,15 +3614,7 @@ fn transCreateNodeShiftOp( | ... | @@ -3894,15 +3614,7 @@ fn transCreateNodeShiftOp( |
| 3894 | const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value); | 3614 | const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value); |
| 3895 | const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); | 3615 | const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); |
| 3896 | | 3616 | |
| 3897 | const payload = try c.arena.create(ast.Payload.BinOp); | 3617 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used); |
| 3898 | payload.* = .{ | | |
| 3899 | .base = .{ .tag = op }, | | |
| 3900 | .data = .{ | | |
| 3901 | .lhs = lhs, | | |
| 3902 | .rhs = rhs_casted, | | |
| 3903 | }, | | |
| 3904 | }; | | |
| 3905 | return Node.initPayload(&payload.base); | | |
| 3906 | } | 3618 | } |
| 3907 | | 3619 | |
| 3908 | fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node { | 3620 | fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node { |