authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-11 12:31:48+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:05+02:00
logc30c2f7c133861a8749a9ffbc2bf6a49d9c6283e
tree81ac639745b54cb969e40ca953762f4511fdd77f
parent450b718b9ec21b328966469c851983ee8969e577
signature Commit is signed but in an unrecognized format.

translate-c: convert assignment and conditional exprs


2 files changed, 234 insertions(+), 522 deletions(-)

src/translate_c.zig+219-507
......@@ -1144,18 +1144,16 @@ fn transBinaryOperator(
11441144 }
11451145 },
11461146 .Shl => {
1147 const node = try transCreateNodeShiftOp(c, scope, stmt, .shl);
1148 return maybeSuppressResult(c, scope, result_used, node);
1147 return transCreateNodeShiftOp(c, scope, stmt, .shl, result_used);
11491148 },
11501149 .Shr => {
1151 const node = try transCreateNodeShiftOp(c, scope, stmt, .shr);
1152 return maybeSuppressResult(c, scope, result_used, node);
1150 return transCreateNodeShiftOp(c, scope, stmt, .shr, result_used);
11531151 },
11541152 .LAnd => {
1155 return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used, true);
1153 return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used);
11561154 },
11571155 .LOr => {
1158 return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used, true);
1156 return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used);
11591157 },
11601158 else => {},
11611159 }
......@@ -1233,15 +1231,7 @@ fn transBinaryOperator(
12331231 else
12341232 rhs_uncasted;
12351233
1236 const payload = try c.arena.create(ast.Payload.BinOp);
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));
1234 return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, used);
12451235}
12461236
12471237fn transCompoundStmtInline(
......@@ -1716,7 +1706,7 @@ fn transStringLiteralAsArray(
17161706 init_list[i] = try transCreateCharLitNode(c, narrow, code_unit);
17171707 }
17181708 while (i < array_size) : (i += 1) {
1719 init_list[i] = try transCreateNodeInt(c, 0);
1709 init_list[i] = try transCreateNodeNumber(c, 0);
17201710 }
17211711
17221712 return Node.array_init.create(c.arena, init_list);
......@@ -2398,7 +2388,7 @@ fn transCharLiteral(
23982388 // C has a somewhat obscure feature called multi-character character constant
23992389 // e.g. 'abcd'
24002390 const int_lit_node = if (kind == .Ascii and val > 255)
2401 try transCreateNodeInt(c, val)
2391 try transCreateNodeNumber(c, val)
24022392 else
24032393 try transCreateCharLitNode(c, narrow, val);
24042394
......@@ -2434,8 +2424,8 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
24342424 .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value),
24352425 });
24362426 try block_scope.statements.append(break_node);
2437
2438 return block_scope.complete(c);
2427 const res = try block_scope.complete(c);
2428 return maybeSuppressResult(c, scope, used, res);
24392429}
24402430
24412431fn 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
24602450 const decl = @ptrCast(*const clang.NamedDecl, member_decl);
24612451 break :blk try c.str(decl.getName_bytes_begin());
24622452 };
2453 const ident = try Node.identifier.create(c.arena, name);
24632454
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});
24652456 return maybeSuppressResult(c, scope, result_used, node);
24662457}
24672458
......@@ -2716,15 +2707,9 @@ fn transCreatePreCrement(
27162707 // common case
27172708 // c: ++expr
27182709 // zig: expr += 1
2719 const payload = try c.arena.create(ast.Payload.BinOp);
2720 payload.* = .{
2721 .base = .{ .tag = op },
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);
2710 const lhs = try transExpr(c, scope, op_expr, .used, .r_value);
2711 const rhs = Node.one_literal.init();
2712 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);
27282713 }
27292714 // worst case
27302715 // c: ++expr
......@@ -2744,20 +2729,15 @@ fn transCreatePreCrement(
27442729
27452730 const lhs_node = try Node.identifier.create(c.arena, ref);
27462731 const ref_node = try Node.deref.create(c.arena, lhs_node);
2747 const payload = try c.arena.create(ast.Payload.BinOp);
2748 payload.* = .{
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));
2732 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used);
2733 try block_scope.statements.append(node);
27562734
2757 return Node.break_val.create(c.arena, .{
2735 const break_node = try Node.break_val.create(c.arena, .{
27582736 .label = block_scope.label,
27592737 .val = ref_node,
27602738 });
2739 try block_scope.statements.append(break_node);
2740 return block_scope.complete(c);
27612741}
27622742
27632743fn transCreatePostCrement(
......@@ -2771,17 +2751,11 @@ fn transCreatePostCrement(
27712751
27722752 if (used == .unused) {
27732753 // common case
2774 // c: ++expr
2754 // c: expr++
27752755 // zig: expr += 1
2776 const payload = try c.arena.create(ast.Payload.BinOp);
2777 payload.* = .{
2778 .base = .{ .tag = op },
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);
2756 const lhs = try transExpr(c, scope, op_expr, .used, .r_value);
2757 const rhs = Node.one_literal.init();
2758 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);
27852759 }
27862760 // worst case
27872761 // c: expr++
......@@ -2807,44 +2781,39 @@ fn transCreatePostCrement(
28072781 const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node});
28082782 try block_scope.statements.append(tmp_decl);
28092783
2810 const payload = try c.arena.create(ast.Payload.BinOp);
2811 payload.* = .{
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));
2784 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used);
2785 try block_scope.statements.append(node);
28192786
2820 return Node.break_val.create(c.arena, .{
2787 const break_node = try Node.break_val.create(c.arena, .{
28212788 .label = block_scope.label,
28222789 .val = try Node.identifier.create(c.arena, tmp),
28232790 });
2791 try block_scope.statements.append(break_node);
2792 return block_scope.complete(c);
28242793}
28252794
2826fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
2795fn transCompoundAssignOperator(c: *Context, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!Node {
28272796 switch (stmt.getOpcode()) {
28282797 .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)
28302799 else
2831 return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used),
2800 return transCreateCompoundAssign(c, scope, stmt, .assign_mul, used),
28322801 .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)
28342803 else
2835 return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used),
2804 return transCreateCompoundAssign(c, scope, stmt, .assign_add, used),
28362805 .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)
28382807 else
2839 return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
2840 .DivAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignDiv, .SlashEqual, "/=", .Div, .Slash, "/", used),
2841 .RemAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignMod, .PercentEqual, "%=", .Mod, .Percent, "%", used),
2842 .ShlAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftLeft, .AngleBracketAngleBracketLeftEqual, "<<=", .BitShiftLeft, .AngleBracketAngleBracketLeft, "<<", used),
2843 .ShrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitShiftRight, .AngleBracketAngleBracketRightEqual, ">>=", .BitShiftRight, .AngleBracketAngleBracketRight, ">>", used),
2844 .AndAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitAnd, .AmpersandEqual, "&=", .BitAnd, .Ampersand, "&", used),
2845 .XorAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitXor, .CaretEqual, "^=", .BitXor, .Caret, "^", used),
2846 .OrAssign => return transCreateCompoundAssign(rp, scope, stmt, .AssignBitOr, .PipeEqual, "|=", .BitOr, .Pipe, "|", used),
2847 else => return revertAndWarn(
2808 return transCreateCompoundAssign(c, scope, stmt, .assign_sub, used),
2809 .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_div, used),
2810 .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_mod, used),
2811 .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shl, used),
2812 .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shr, used),
2813 .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_and, used),
2814 .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_xor, used),
2815 .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_or, used),
2816 else => return fail(
28482817 rp,
28492818 error.UnsupportedTranslation,
28502819 stmt.getBeginLoc(),
......@@ -2855,25 +2824,20 @@ fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const cla
28552824}
28562825
28572826fn transCreateCompoundAssign(
2858 rp: RestorePoint,
2827 c: *Context,
28592828 scope: *Scope,
28602829 stmt: *const clang.CompoundAssignOperator,
2861 assign_op: ast.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,
2830 op: Node.Tag,
28672831 used: ResultUsed,
2868) TransError!*ast.Node {
2869 const is_shift = bin_op == .BitShiftLeft or bin_op == .BitShiftRight;
2870 const is_div = bin_op == .Div;
2871 const is_mod = bin_op == .Mod;
2832) TransError!Node {
2833 const is_shift = op == .assign_shl or op == .assign_shr;
2834 const is_div = op == .assign_div;
2835 const is_mod = op == .assign_mod;
28722836 const lhs = stmt.getLHS();
28732837 const rhs = stmt.getRHS();
28742838 const loc = stmt.getBeginLoc();
2875 const lhs_qt = getExprQualType(rp.c, lhs);
2876 const rhs_qt = getExprQualType(rp.c, rhs);
2839 const lhs_qt = getExprQualType(c, lhs);
2840 const rhs_qt = getExprQualType(c, rhs);
28772841 const is_signed = cIsSignedInteger(lhs_qt);
28782842 const requires_int_cast = blk: {
28792843 const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt);
......@@ -2885,146 +2849,99 @@ fn transCreateCompoundAssign(
28852849 // c: lhs += rhs
28862850 // zig: lhs += rhs
28872851 if ((is_mod or is_div) and is_signed) {
2888 const op_token = try appendToken(rp.c, .Equal, "=");
2889 const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
2890 const builtin = if (is_mod) "@rem" else "@divTrunc";
2891 const builtin_node = try rp.c.createBuiltinCall(builtin, 2);
2892 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
2893 builtin_node.params()[0] = lhs_node;
2894 _ = try appendToken(rp.c, .Comma, ",");
2895 builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value);
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;
2852 const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);
2853 const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
2854 const builtin = if (is_mod)
2855 try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
2856 else
2857 try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
2858
2859 return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
29052860 }
29062861
2907 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
2908 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
2862 const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);
29092863 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)
29112865 else
2912 try transExpr(rp, scope, rhs, .used, .r_value);
2866 try transExpr(c, scope, rhs, .used, .r_value);
29132867
29142868 if (is_shift or requires_int_cast) {
2915 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
2869 // @intCast(rhs)
29162870 const cast_to_type = if (is_shift)
2917 try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc)
2871 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
29182872 else
2919 try transQualType(rp, getExprQualType(rp.c, lhs), loc);
2920 cast_node.params()[0] = cast_to_type;
2921 _ = try appendToken(rp.c, .Comma, ",");
2922 cast_node.params()[1] = rhs_node;
2923 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2924 rhs_node = &cast_node.base;
2873 try transQualType(c, getExprQualType(c, lhs), loc);
2874
2875 rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
29252876 }
2926 if (scope.id != .Condition)
2927 _ = try appendToken(rp.c, .Semicolon, ";");
2928 return transCreateNodeInfixOp(rp, scope, lhs_node, assign_op, eq_token, rhs_node, .used, false);
2877
2878 return transCreateNodeInfixOp(c, scope, assign_op, lhs_node, rhs_node, .used);
29292879 }
29302880 // worst case
29312881 // c: lhs += rhs
29322882 // zig: (blk: {
29332883 // zig: const _ref = &lhs;
2934 // zig: _ref.* = _ref.* + rhs;
2884 // zig: _ref.* += rhs;
29352885 // zig: break :blk _ref.*
29362886 // zig: })
2937 var block_scope = try Scope.Block.init(rp.c, scope, true);
2887 var block_scope = try Scope.Block.init(c, scope, true);
29382888 defer block_scope.deinit();
2939 const ref = try block_scope.makeMangledName(rp.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);
2889 const ref = try block_scope.makeMangledName(c, "ref");
29572890
2958 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
2959 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
2960 _ = try appendToken(rp.c, .Semicolon, ";");
2891 const expr = try transExpr(c, scope, op_expr, .used, .r_value);
2892 const addr_of = try Node.address_of.create(c.arena, expr);
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);
29612898
29622899 if ((is_mod or is_div) and is_signed) {
2963 const op_token = try appendToken(rp.c, .Equal, "=");
2964 const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
2965 const builtin = if (is_mod) "@rem" else "@divTrunc";
2966 const builtin_node = try rp.c.createBuiltinCall(builtin, 2);
2967 builtin_node.params()[0] = try transCreateNodePtrDeref(rp.c, lhs_node);
2968 _ = try appendToken(rp.c, .Comma, ",");
2969 builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value);
2970 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
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);
2900 const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
2901 const builtin = if (is_mod)
2902 try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
2903 else
2904 try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
2905
2906 const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
2907 try block_scope.statements.append(assign);
29802908 } else {
2981 const bin_token = try appendToken(rp.c, bin_tok_id, bin_bytes);
2982 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
2909 var rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
29832910
29842911 if (is_shift or requires_int_cast) {
2985 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
2912 // @intCast(rhs)
29862913 const cast_to_type = if (is_shift)
2987 try qualTypeToLog2IntRef(rp, getExprQualType(rp.c, rhs), loc)
2914 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
29882915 else
2989 try transQualType(rp, getExprQualType(rp.c, lhs), loc);
2990 cast_node.params()[0] = cast_to_type;
2991 _ = try appendToken(rp.c, .Comma, ",");
2992 cast_node.params()[1] = rhs_node;
2993 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2994 rhs_node = &cast_node.base;
2916 try transQualType(c, getExprQualType(c, lhs), loc);
2917
2918 rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
29952919 }
29962920
2997 const rhs_bin = try transCreateNodeInfixOp(rp, scope, ref_node, bin_op, bin_token, rhs_node, .used, false);
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);
2921 const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used);
30022922 try block_scope.statements.append(assign);
30032923 }
30042924
3005 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node);
3006 try block_scope.statements.append(&break_node.base);
3007 const block_node = try block_scope.complete(rp.c);
3008 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
3009 grouped_expr.* = .{
3010 .lparen = try appendToken(rp.c, .LParen, "("),
3011 .expr = block_node,
3012 .rparen = try appendToken(rp.c, .RParen, ")"),
3013 };
3014 return &grouped_expr.base;
2925 const break_node = try Node.break_val.create(c.arena, .{
2926 .label = block_scope.label,
2927 .val = ref_node,
2928 });
2929 try block_scope.statements.append(break_node);
2930 return block_scope.complete(c);
30152931}
30162932
30172933fn transCPtrCast(
3018 rp: RestorePoint,
2934 c: *Context,
30192935 loc: clang.SourceLocation,
30202936 dst_type: clang.QualType,
30212937 src_type: clang.QualType,
3022 expr: *ast.Node,
3023) !*ast.Node {
2938 expr: Node,
2939) !Node {
30242940 const ty = dst_type.getTypePtr();
30252941 const child_type = ty.getPointeeType();
30262942 const src_ty = src_type.getTypePtr();
30272943 const src_child_type = src_ty.getPointeeType();
2944 const dst_type = try transType(c, ty, loc);
30282945
30292946 if ((src_child_type.isConstQualified() and
30302947 !child_type.isConstQualified()) or
......@@ -3032,47 +2949,25 @@ fn transCPtrCast(
30322949 !child_type.isVolatileQualified()))
30332950 {
30342951 // Casting away const or volatile requires us to use @intToPtr
3035 const inttoptr_node = try rp.c.createBuiltinCall("@intToPtr", 2);
3036 const dst_type_node = try transType(rp, ty, loc);
3037 inttoptr_node.params()[0] = dst_type_node;
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;
2952 const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr);
2953 const int_to_ptr = try Node.int_to_ptr.create(c.arena, .{ .lhs = dst_type, .rhs = ptr_to_int });
2954 return int_to_ptr;
30472955 } else {
30482956 // Implicit downcasting from higher to lower alignment values is forbidden,
30492957 // use @alignCast to side-step this problem
3050 const ptrcast_node = try rp.c.createBuiltinCall("@ptrCast", 2);
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()) {
2958 const rhs = if (qualTypeCanon(child_type).isVoidType())
30562959 // void has 1-byte alignment, so @alignCast is not needed
3057 ptrcast_node.params()[1] = expr;
3058 } else if (typeIsOpaque(rp.c, qualTypeCanon(child_type), loc)) {
2960 expr
2961 else if (typeIsOpaque(c, qualTypeCanon(child_type), loc))
30592962 // For opaque types a ptrCast is enough
3060 ptrcast_node.params()[1] = expr;
3061 } else {
3062 const aligncast_node = try rp.c.createBuiltinCall("@alignCast", 2);
3063 const alignof_node = try rp.c.createBuiltinCall("@alignOf", 1);
3064 const child_type_node = try transQualType(rp, child_type, loc);
3065 alignof_node.params()[0] = child_type_node;
3066 alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3067 aligncast_node.params()[0] = &alignof_node.base;
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;
2963 expr
2964 else blk: {
2965 const child_type_node = try transQualType(c, child_type, loc);
2966 const alignof = try Node.alignof.create(c.arena, child_type_node);
2967 const align_cast = try Node.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });
2968 break :blk align_cast;
2969 };
2970 return Node.ptr_cast.create(c.arena, .{ .lhs = dst_type, .rhs = rhs });
30762971 }
30772972}
30782973
......@@ -3092,13 +2987,15 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node {
30922987fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {
30932988 // TODO use something more accurate
30942989 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);
30962991 return maybeSuppressResult(c, scope, used, &node.base);
30972992}
30982993
3099fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!*ast.Node {
2994fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node {
31002995 // GNU extension of the ternary operator where the middle expression is
31012996 // 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);
31022999 const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
31033000 const cond_expr = casted_stmt.getCond();
31043001 const true_expr = casted_stmt.getTrueExpr();
......@@ -3109,67 +3006,39 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const
31093006 // const _cond_temp = (cond_expr);
31103007 // break :blk if (_cond_temp) _cond_temp else (false_expr);
31113008 // })
3112 const lparen = try appendToken(rp.c, .LParen, "(");
3113
3114 var block_scope = try Scope.Block.init(rp.c, scope, true);
3009 var block_scope = try Scope.Block.init(c, scope, true);
31153010 defer block_scope.deinit();
31163011
3117 const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp");
3118 const mut_tok = try appendToken(rp.c, .Keyword_const, "const");
3119 const name_tok = try appendIdentifier(rp.c, mangled_name);
3120 const eq_token = try appendToken(rp.c, .Equal, "=");
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, ";");
3012 const mangled_name = try block_scope.makeMangledName(c, "cond_temp");
3013 const init_node = try transExpr(c, &block_scope.base, cond_expr, .used, .r_value);
3014 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node});
3015 try block_scope.statements.append(ref_decl);
31543016
3155 const break_node = try break_node_tmp.finish(&if_node.base);
3156 _ = try appendToken(rp.c, .Semicolon, ";");
3157 try block_scope.statements.append(&break_node.base);
3158 const block_node = try block_scope.complete(rp.c);
3017 const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
3018 var then_body = try Node.identifier.create(c.arena, mangled_name);
3019 if (!res_is_bool and isBoolRes(init_node)) {
3020 then_body = try Node.bool_to_int.create(c.arena, then_body);
3021 }
31593022
3160 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
3161 grouped_expr.* = .{
3162 .lparen = lparen,
3163 .expr = block_node,
3164 .rparen = try appendToken(rp.c, .RParen, ")"),
3165 };
3166 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
3023 var else_body = try transExpr(c, &block_scope.base, false_expr, .used, .r_value);
3024 if (!res_is_bool and isBoolRes(else_body)) {
3025 else_body = try Node.bool_to_int.create(c.arena, else_body);
3026 }
3027 const if_node = try Node.@"if".create(c.arena, .{
3028 .cond = cond,
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);
31673039}
31683040
3169fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.ConditionalOperator, used: ResultUsed) TransError!*ast.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);
3041fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.ConditionalOperator, used: ResultUsed) TransError!Node {
31733042 var cond_scope = Scope.Condition{
31743043 .base = .{
31753044 .parent = scope,
......@@ -3178,60 +3047,41 @@ fn transConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.
31783047 };
31793048 defer cond_scope.deinit();
31803049
3050 const qt = @ptrCast(*const clang.Stmt, stmt).getType();
3051 const res_is_bool = qualTypeIsBoolean(qt);
31813052 const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
31823053 const cond_expr = casted_stmt.getCond();
31833054 const true_expr = casted_stmt.getTrueExpr();
31843055 const false_expr = casted_stmt.getFalseExpr();
31853056
3186 if_node.condition = try transBoolExpr(rp, &cond_scope.base, cond_expr, .used, .r_value, false);
3187 _ = try appendToken(rp.c, .RParen, ")");
3188
3189 if_node.body = try transExpr(rp, scope, true_expr, .used, .r_value);
3057 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);
31903058
3191 if_node.@"else" = try transCreateNodeElse(rp.c);
3192 if_node.@"else".?.body = try transExpr(rp, scope, false_expr, .used, .r_value);
3059 var then_body = try transExpr(c, scope, true_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 }
31933063
3194 if (grouped) {
3195 const rparen = try appendToken(rp.c, .RParen, ")");
3196 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
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);
3064 var else_body = try transExpr(c, scope, false_expr, .used, .r_value);
3065 if (!res_is_bool and isBoolRes(else_body)) {
3066 else_body = try Node.bool_to_int.create(c.arena, else_body);
32053067 }
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);
32063075}
32073076
32083077fn maybeSuppressResult(
3209 rp: RestorePoint,
3078 c: *Context,
32103079 scope: *Scope,
32113080 used: ResultUsed,
3212 result: *ast.Node,
3213) TransError!*ast.Node {
3081 result: Node,
3082) TransError!Node {
32143083 if (used == .used) return result;
3215 if (scope.id != .Condition) {
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;
3084 return Node.ignore.create(c.arena, result);
32353085}
32363086
32373087fn 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 {
32423092/// only matters for incomplete arrays, since the size of the array is determined
32433093/// by the size of the initializer
32443094fn transQualTypeInitialized(
3245 rp: RestorePoint,
3095 c: *Context,
32463096 qt: clang.QualType,
32473097 decl_init: *const clang.Expr,
32483098 source_loc: clang.SourceLocation,
3249) TypeError!*ast.Node {
3099) TypeError!Node {
32503100 const ty = qt.getTypePtr();
32513101 if (ty.getTypeClass() == .IncompleteArray) {
32523102 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
......@@ -3257,17 +3107,17 @@ fn transQualTypeInitialized(
32573107 const string_lit = @ptrCast(*const clang.StringLiteral, decl_init);
32583108 const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator
32593109 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 });
32613111 },
32623112 .InitListExprClass => {
32633113 const init_expr = @ptrCast(*const clang.InitListExpr, decl_init);
32643114 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 });
32663116 },
32673117 else => {},
32683118 }
32693119 }
3270 return transQualType(rp, qt, source_loc);
3120 return transQualType(c, qt, source_loc);
32713121}
32723122
32733123fn 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
32763126
32773127/// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness.
32783128/// Asserts the type is an integer.
3279fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) TypeError!*ast.Node {
3129fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) TypeError!Node {
32803130 return transTypeIntWidthOf(c, qualTypeCanon(ty), is_signed);
32813131}
32823132
32833133/// Produces a Zig AST node by translating a Clang Type, respecting the width, but modifying the signed-ness.
32843134/// Asserts the type is an integer.
3285fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!*ast.Node {
3135fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!Node {
32863136 assert(ty.getTypeClass() == .Builtin);
32873137 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()) {
32893139 .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8",
32903140 .UShort, .Short => if (is_signed) "c_short" else "c_ushort",
32913141 .UInt, .Int => if (is_signed) "c_int" else "c_uint",
......@@ -3532,28 +3382,22 @@ fn cIsLongLongInteger(qt: clang.QualType) bool {
35323382 };
35333383}
35343384fn transCreateNodeAssign(
3535 rp: RestorePoint,
3385 c: *Context,
35363386 scope: *Scope,
35373387 result_used: ResultUsed,
35383388 lhs: *const clang.Expr,
35393389 rhs: *const clang.Expr,
3540) !*ast.Node {
3390) !Node {
35413391 // common case
35423392 // c: lhs = rhs
35433393 // zig: lhs = rhs
35443394 if (result_used == .unused) {
3545 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
3546 const eq_token = try appendToken(rp.c, .Equal, "=");
3547 var rhs_node = try transExprCoercing(rp, scope, rhs, .used, .r_value);
3395 const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);
3396 var rhs_node = try transExprCoercing(c, scope, rhs, .used, .r_value);
35483397 if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) {
3549 const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);
3550 builtin_node.params()[0] = rhs_node;
3551 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
3552 rhs_node = &builtin_node.base;
3398 rhs_node = try Node.bool_to_int.create(c.arena, rhs_node);
35533399 }
3554 if (scope.id != .Condition)
3555 _ = try appendToken(rp.c, .Semicolon, ";");
3556 return transCreateNodeInfixOp(rp, scope, lhs_node, .Assign, eq_token, rhs_node, .used, false);
3400 return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used);
35573401 }
35583402
35593403 // worst case
......@@ -3563,76 +3407,36 @@ fn transCreateNodeAssign(
35633407 // zig: lhs = _tmp;
35643408 // zig: break :blk _tmp
35653409 // zig: })
3566 var block_scope = try Scope.Block.init(rp.c, scope, true);
3410 var block_scope = try Scope.Block.init(c, scope, true);
35673411 defer block_scope.deinit();
35683412
3569 const tmp = try block_scope.makeMangledName(rp.c, "tmp");
3570 const mut_tok = try appendToken(rp.c, .Keyword_const, "const");
3571 const name_tok = try appendIdentifier(rp.c, tmp);
3572 const eq_token = try appendToken(rp.c, .Equal, "=");
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);
3413 const tmp = try block_scope.makeMangledName(c, "tmp");
3414 const rhs = try transExpr(c, scope, op_expr, .used, .r_value);
3415 const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = rhs});
3416 try block_scope.statements.append(tmp_decl);
35913417
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, ";");
35963418
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);
35983422 try block_scope.statements.append(assign);
35993423
3600 const break_node = blk: {
3601 var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, tokenSlice(rp.c, block_scope.label.?));
3602 const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp);
3603 break :blk try tmp_ctrl_flow.finish(rhs_expr);
3604 };
3605 _ = try appendToken(rp.c, .Semicolon, ";");
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
3613fn 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;
3424 const break_node = try Node.break_val.create(c.arena, .{
3425 .label = block_scope.label,
3426 .val = tmp_ident,
3427 });
3428 try block_scope.statements.append(break_node);
3429 return block_scope.complete(c);
36223430}
36233431
3624fn transCreateNodeBoolInfixOp(
3432fn transCreateNodeInfixOp(
36253433 c: *Context,
36263434 scope: *Scope,
3627 stmt: *const clang.BinaryOperator,
36283435 op: ast.Node.Tag,
3436 lhs: Node,
3437 rhs: Node,
36293438 used: ResultUsed,
36303439) !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
36363440 const payload = try c.arena.create(ast.Payload.BinOp);
36373441 payload.* = .{
36383442 .base = .{ .tag = op },
......@@ -3644,39 +3448,19 @@ fn transCreateNodeBoolInfixOp(
36443448 return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base));
36453449}
36463450
3647fn transCreateNodePtrType(
3451fn transCreateNodeBoolInfixOp(
36483452 c: *Context,
3649 is_const: bool,
3650 is_volatile: bool,
3651 op_tok_id: std.zig.Token.Id,
3652) !*ast.Node.PtrType {
3653 const node = try c.arena.create(ast.Node.PtrType);
3654 const op_token = switch (op_tok_id) {
3655 .LBracket => blk: {
3656 const lbracket = try appendToken(c, .LBracket, "[");
3657 _ = try appendToken(c, .Asterisk, "*");
3658 _ = try appendToken(c, .RBracket, "]");
3659 break :blk lbracket;
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;
3453 scope: *Scope,
3454 stmt: *const clang.BinaryOperator,
3455 op: ast.Node.Tag,
3456 used: ResultUsed,
3457) !Node {
3458 std.debug.assert(op == .bool_and or op == .bool_or);
3459
3460 const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value);
3461 const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value);
3462
3463 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, used);
36803464}
36813465
36823466fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {
......@@ -3722,73 +3506,10 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {
37223506 return Node.int_literal.create(c.arena, str);
37233507}
37243508
3725fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
3726 const token = try appendToken(c, .Keyword_undefined, "undefined");
3727 const node = try c.arena.create(ast.Node.OneToken);
3728 node.* = .{
3729 .base = .{ .tag = .UndefinedLiteral },
3730 .token = token,
3731 };
3732 return &node.base;
3733}
3734
3735fn 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
3745fn 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
3758fn 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
3769fn 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
3779fn 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;
3509fn transCreateNodeNumber(c: *Context, int: anytype) !Node {
3510 const fmt_s = if (comptime std.meta.trait.isNumber(@TypeOf(int))) "{d}" else "{s}";
3511 const str = try std.fmt.allocPrint(c.arena, fmt_s, .{int});
3512 return Node.int_literal.create(c.arena, str);
37923513}
37933514
37943515fn 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
38733594 return &fn_proto.base;
38743595}
38753596
3876
3877
38783597fn transCreateNodeShiftOp(
38793598 c: *Context,
38803599 scope: *Scope,
38813600 stmt: *const clang.BinaryOperator,
38823601 op: Node.Tag,
3602 used: ResultUsed,
38833603) !Node {
38843604 std.debug.assert(op == .shl or op == .shr);
38853605
......@@ -3894,15 +3614,7 @@ fn transCreateNodeShiftOp(
38943614 const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value);
38953615 const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
38963616
3897 const payload = try c.arena.create(ast.Payload.BinOp);
3898 payload.* = .{
3899 .base = .{ .tag = op },
3900 .data = .{
3901 .lhs = lhs,
3902 .rhs = rhs_casted,
3903 },
3904 };
3905 return Node.initPayload(&payload.base);
3617 return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
39063618}
39073619
39083620fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
src/translate_c/ast.zig+15-15
......@@ -24,8 +24,8 @@ pub const Node = extern union {
2424 usingnamespace_builtins,
2525 // After this, the tag requires a payload.
2626
27 int_literal,
28 float_literal,
27 // int or float, doesn't really matter
28 number_literal,
2929 string_literal,
3030 char_literal,
3131 identifier,
......@@ -115,6 +115,7 @@ pub const Node = extern union {
115115 bit_xor,
116116 array_cat,
117117 ellipsis3,
118 assign,
118119
119120 log2_int_type,
120121 /// @import("std").math.Log2Int(operand)
......@@ -147,6 +148,8 @@ pub const Node = extern union {
147148 int_to_ptr,
148149 /// @ptrToInt(operand)
149150 ptr_to_int,
151 /// @alignCast(lhs, rhs)
152 align_cast,
150153
151154 negate,
152155 negate_wrap,
......@@ -190,6 +193,9 @@ pub const Node = extern union {
190193 /// [1]type{val} ** count
191194 array_filler,
192195
196 /// _ = operand;
197 ignore,
198
193199 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
194200 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
195201
......@@ -227,6 +233,7 @@ pub const Node = extern union {
227233 .while_true,
228234 .if_not_break,
229235 .switch_else,
236 .ignore,
230237 => Payload.UnOp,
231238
232239 .add,
......@@ -292,12 +299,14 @@ pub const Node = extern union {
292299 .array_cat,
293300 .ellipsis3,
294301 .switch_prong,
302 .field_access,
303 .assign,
304 .align_cast,
295305 => Payload.BinOp,
296306
297 .int,
298 .float,
299 .string,
300 .char,
307 .number_literal,
308 .string_literal,
309 .char_literal,
301310 .identifier,
302311 .warning,
303312 .failed_decl,
......@@ -327,7 +336,6 @@ pub const Node = extern union {
327336 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
328337 .enum_redecl => Payload.EnumRedecl,
329338 .array_filler => Payload.ArrayFiller,
330 .field_access => Payload.FieldAccess,
331339 };
332340 }
333341
......@@ -590,14 +598,6 @@ pub const Payload = struct {
590598 count: usize,
591599 },
592600 };
593
594 pub const FieldAccess = struct {
595 base: Node,
596 data: struct {
597 container: Node,
598 name: []const u8,
599 },
600 };
601601};
602602
603603/// Converts the nodes into a Zig ast.