authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-10 23:38:45+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:05+02:00
log450b718b9ec21b328966469c851983ee8969e577
treefee2775529046a868d9da749afd8782952c67aac
parentcadd4483be80f73f192621f79eea41117183129c
signature Commit is signed but in an unrecognized format.

translate-c: convert field/array access, call, pre/postcrement


2 files changed, 129 insertions(+), 372 deletions(-)

src/translate_c.zig+113-366
......@@ -2438,11 +2438,11 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
24382438 return block_scope.complete(c);
24392439}
24402440
2441fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!*ast.Node {
2442 var container_node = try transExpr(rp, scope, stmt.getBase(), .used, .r_value);
2441fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node {
2442 var container_node = try transExpr(c, scope, stmt.getBase(), .used, .r_value);
24432443
24442444 if (stmt.isArrow()) {
2445 container_node = try transCreateNodePtrDeref(rp.c, container_node);
2445 container_node = try Node.deref.create(c.arena, container_node);
24462446 }
24472447
24482448 const member_decl = stmt.getMemberDecl();
......@@ -2453,19 +2453,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExp
24532453 if (decl_kind == .Field) {
24542454 const field_decl = @ptrCast(*const clang.FieldDecl, member_decl);
24552455 if (field_decl.isAnonymousStructOrUnion()) {
2456 const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?;
2457 break :blk try mem.dupe(rp.c.arena, u8, name);
2456 const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?;
2457 break :blk try mem.dupe(c.arena, u8, name);
24582458 }
24592459 }
24602460 const decl = @ptrCast(*const clang.NamedDecl, member_decl);
2461 break :blk try rp.c.str(decl.getName_bytes_begin());
2461 break :blk try c.str(decl.getName_bytes_begin());
24622462 };
24632463
2464 const node = try transCreateNodeFieldAccess(rp.c, container_node, name);
2465 return maybeSuppressResult(rp, scope, result_used, node);
2464 const node = try Node.field_access.create(c.arena, .{ .container = container_node, .name = name});
2465 return maybeSuppressResult(c, scope, result_used, node);
24662466}
24672467
2468fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const clang.ArraySubscriptExpr, result_used: ResultUsed) TransError!*ast.Node {
2468fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscriptExpr, result_used: ResultUsed) TransError!Node {
24692469 var base_stmt = stmt.getBase();
24702470
24712471 // Unwrap the base statement if it's an array decayed to a bare pointer type
......@@ -2478,30 +2478,23 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const clang.ArraySub
24782478 }
24792479 }
24802480
2481 const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value);
2482 const node = try transCreateNodeArrayAccess(rp.c, container_node);
2481 const container_node = try transExpr(c, scope, base_stmt, .used, .r_value);
24832482
24842483 // cast if the index is long long or signed
24852484 const subscr_expr = stmt.getIdx();
2486 const qt = getExprQualType(rp.c, subscr_expr);
2485 const qt = getExprQualType(c, subscr_expr);
24872486 const is_longlong = cIsLongLongInteger(qt);
24882487 const is_signed = cIsSignedInteger(qt);
24892488
2490 if (is_longlong or is_signed) {
2491 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
2489
2490 const node = try Node.array_access.create(c.arena, .{ .lhs = container_node, .rhs = if (is_longlong or is_signed) blk: {
2491 const cast_node = try c.createBuiltinCall("@intCast", 2);
24922492 // check if long long first so that signed long long doesn't just become unsigned long long
2493 var typeid_node = if (is_longlong) try transCreateNodeIdentifier(rp.c, "usize") else try transQualTypeIntWidthOf(rp.c, qt, false);
2494 cast_node.params()[0] = typeid_node;
2495 _ = try appendToken(rp.c, .Comma, ",");
2496 cast_node.params()[1] = try transExpr(rp, scope, subscr_expr, .used, .r_value);
2497 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2498 node.rtoken = try appendToken(rp.c, .RBrace, "]");
2499 node.index_expr = &cast_node.base;
2500 } else {
2501 node.index_expr = try transExpr(rp, scope, subscr_expr, .used, .r_value);
2502 node.rtoken = try appendToken(rp.c, .RBrace, "]");
2503 }
2504 return maybeSuppressResult(rp, scope, result_used, &node.base);
2493 var typeid_node = if (is_longlong) try transCreateNodeIdentifier(c, "usize") else try transQualTypeIntWidthOf(c, qt, false);
2494 break :blk try Node.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used, .r_value)});
2495 } else
2496 try transExpr(c, scope, subscr_expr, .used, .r_value)});
2497 return maybeSuppressResult(c, scope, result_used, node);
25052498}
25062499
25072500/// Check if an expression is ultimately a reference to a function declaration
......@@ -2536,9 +2529,9 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {
25362529 }
25372530}
25382531
2539fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!*ast.Node {
2532fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!Node {
25402533 const callee = stmt.getCallee();
2541 var raw_fn_expr = try transExpr(rp, scope, callee, .used, .r_value);
2534 var raw_fn_expr = try transExpr(c, scope, callee, .used, .r_value);
25422535
25432536 var is_ptr = false;
25442537 const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr);
......@@ -2549,16 +2542,12 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
25492542 raw_fn_expr;
25502543
25512544 const num_args = stmt.getNumArgs();
2552 const node = try rp.c.createCall(fn_expr, num_args);
2553 const call_params = node.params();
2545 const call_params = try c.arena.alloc(Node, num_args);
25542546
25552547 const args = stmt.getArgs();
25562548 var i: usize = 0;
25572549 while (i < num_args) : (i += 1) {
2558 if (i != 0) {
2559 _ = try appendToken(rp.c, .Comma, ",");
2560 }
2561 var call_param = try transExpr(rp, scope, args[i], .used, .r_value);
2550 var call_param = try transExpr(c, scope, args[i], .used, .r_value);
25622551
25632552 // In C the result type of a boolean expression is int. If this result is passed as
25642553 // an argument to a function whose parameter is also int, there is no cast. Therefore
......@@ -2570,10 +2559,7 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
25702559 if (i < param_count) {
25712560 const param_qt = fn_proto.getParamType(@intCast(c_uint, i));
25722561 if (isBoolRes(call_param) and cIsNativeInt(param_qt)) {
2573 const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);
2574 builtin_node.params()[0] = call_param;
2575 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2576 call_param = &builtin_node.base;
2562 call_param = try Node.bool_to_int.create(c.arena, call_param);
25772563 }
25782564 }
25792565 },
......@@ -2582,18 +2568,16 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
25822568 }
25832569 call_params[i] = call_param;
25842570 }
2585 node.rtoken = try appendToken(rp.c, .RParen, ")");
2586
2571 const node = try Node.call.create(c.arena, .{ .lhs = fn_expr, .args = call_params });
25872572 if (fn_ty) |ty| {
25882573 const canon = ty.getReturnType().getCanonicalType();
25892574 const ret_ty = canon.getTypePtr();
25902575 if (ret_ty.isVoidType()) {
2591 _ = try appendToken(rp.c, .Semicolon, ";");
2592 return &node.base;
2576 return node;
25932577 }
25942578 }
25952579
2596 return maybeSuppressResult(rp, scope, result_used, &node.base);
2580 return maybeSuppressResult(c, scope, result_used, node);
25972581}
25982582
25992583const ClangFunctionType = union(enum) {
......@@ -2667,21 +2651,21 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
26672651 const op_expr = stmt.getSubExpr();
26682652 switch (stmt.getOpcode()) {
26692653 .PostInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
2670 return transCreatePostCrement(c, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
2654 return transCreatePostCrement(c, scope, stmt, .assign_add_wrap, used)
26712655 else
2672 return transCreatePostCrement(c, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
2656 return transCreatePostCrement(c, scope, stmt, .assign_add, used),
26732657 .PostDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
2674 return transCreatePostCrement(c, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
2658 return transCreatePostCrement(c, scope, stmt, .assign_sub_wrap, used)
26752659 else
2676 return transCreatePostCrement(c, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
2660 return transCreatePostCrement(c, scope, stmt, .assign_sub, used),
26772661 .PreInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
2678 return transCreatePreCrement(c, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
2662 return transCreatePreCrement(c, scope, stmt, .assign_add_wrap, used)
26792663 else
2680 return transCreatePreCrement(c, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
2664 return transCreatePreCrement(c, scope, stmt, .assign_add, used),
26812665 .PreDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
2682 return transCreatePreCrement(c, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
2666 return transCreatePreCrement(c, scope, stmt, .assign_sub_wrap, used)
26832667 else
2684 return transCreatePreCrement(c, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
2668 return transCreatePreCrement(c, scope, stmt, .assign_sub, used),
26852669 .AddrOf => {
26862670 if (cIsFunctionDeclRef(op_expr)) {
26872671 return transExpr(rp, scope, op_expr, used, .r_value);
......@@ -2704,7 +2688,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
27042688 // use -% x for unsigned integers
27052689 return Node.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
27062690 } else
2707 return revertAndWarn(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{});
2691 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{});
27082692 },
27092693 .Not => {
27102694 return Node.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
......@@ -2715,31 +2699,32 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
27152699 .Extension => {
27162700 return transExpr(c, scope, stmt.getSubExpr(), used, .l_value);
27172701 },
2718 else => return revertAndWarn(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}),
2702 else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}),
27192703 }
27202704}
27212705
27222706fn transCreatePreCrement(
2723 rp: RestorePoint,
2707 c: *Context,
27242708 scope: *Scope,
27252709 stmt: *const clang.UnaryOperator,
2726 op: ast.Node.Tag,
2727 op_tok_id: std.zig.Token.Id,
2728 bytes: []const u8,
2710 op: Node.Tag,
27292711 used: ResultUsed,
2730) TransError!*ast.Node {
2712) TransError!Node {
27312713 const op_expr = stmt.getSubExpr();
27322714
27332715 if (used == .unused) {
27342716 // common case
27352717 // c: ++expr
27362718 // zig: expr += 1
2737 const expr = try transExpr(rp, scope, op_expr, .used, .r_value);
2738 const token = try appendToken(rp.c, op_tok_id, bytes);
2739 const one = try transCreateNodeInt(rp.c, 1);
2740 if (scope.id != .Condition)
2741 _ = try appendToken(rp.c, .Semicolon, ";");
2742 return transCreateNodeInfixOp(rp, scope, expr, op, token, one, .used, false);
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);
27432728 }
27442729 // worst case
27452730 // c: ++expr
......@@ -2748,71 +2733,55 @@ fn transCreatePreCrement(
27482733 // zig: _ref.* += 1;
27492734 // zig: break :blk _ref.*
27502735 // zig: })
2751 var block_scope = try Scope.Block.init(rp.c, scope, true);
2736 var block_scope = try Scope.Block.init(c, scope, true);
27522737 defer block_scope.deinit();
2753 const ref = try block_scope.makeMangledName(rp.c, "ref");
2738 const ref = try block_scope.makeMangledName(c, "ref");
27542739
2755 const mut_tok = try appendToken(rp.c, .Keyword_const, "const");
2756 const name_tok = try appendIdentifier(rp.c, ref);
2757 const eq_token = try appendToken(rp.c, .Equal, "=");
2758 const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
2759 rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value);
2760 const init_node = &rhs_node.base;
2761 const semicolon_token = try appendToken(rp.c, .Semicolon, ";");
2762 const node = try ast.Node.VarDecl.create(rp.c.arena, .{
2763 .name_token = name_tok,
2764 .mut_token = mut_tok,
2765 .semicolon_token = semicolon_token,
2766 }, .{
2767 .eq_token = eq_token,
2768 .init_node = init_node,
2769 });
2770 try block_scope.statements.append(&node.base);
2740 const expr = try transExpr(c, scope, op_expr, .used, .r_value);
2741 const addr_of = try Node.address_of.create(c.arena, expr);
2742 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
2743 try block_scope.statements.append(ref_decl);
27712744
2772 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
2773 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
2774 _ = try appendToken(rp.c, .Semicolon, ";");
2775 const token = try appendToken(rp.c, op_tok_id, bytes);
2776 const one = try transCreateNodeInt(rp.c, 1);
2777 _ = try appendToken(rp.c, .Semicolon, ";");
2778 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);
2779 try block_scope.statements.append(assign);
2780
2781 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node);
2782 try block_scope.statements.append(&break_node.base);
2783 const block_node = try block_scope.complete(rp.c);
2784 // semicolon must immediately follow rbrace because it is the last token in a block
2785 _ = try appendToken(rp.c, .Semicolon, ";");
2786 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
2787 grouped_expr.* = .{
2788 .lparen = try appendToken(rp.c, .LParen, "("),
2789 .expr = block_node,
2790 .rparen = try appendToken(rp.c, .RParen, ")"),
2745 const lhs_node = try Node.identifier.create(c.arena, ref);
2746 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 }
27912754 };
2792 return &grouped_expr.base;
2755 try block_scope.statements.append(Node.initPayload(&payload.base));
2756
2757 return Node.break_val.create(c.arena, .{
2758 .label = block_scope.label,
2759 .val = ref_node,
2760 });
27932761}
27942762
27952763fn transCreatePostCrement(
2796 rp: RestorePoint,
2764 c: *Context,
27972765 scope: *Scope,
27982766 stmt: *const clang.UnaryOperator,
2799 op: ast.Node.Tag,
2800 op_tok_id: std.zig.Token.Id,
2801 bytes: []const u8,
2767 op: Node.Tag,
28022768 used: ResultUsed,
2803) TransError!*ast.Node {
2769) TransError!Node {
28042770 const op_expr = stmt.getSubExpr();
28052771
28062772 if (used == .unused) {
28072773 // common case
28082774 // c: ++expr
28092775 // zig: expr += 1
2810 const expr = try transExpr(rp, scope, op_expr, .used, .r_value);
2811 const token = try appendToken(rp.c, op_tok_id, bytes);
2812 const one = try transCreateNodeInt(rp.c, 1);
2813 if (scope.id != .Condition)
2814 _ = try appendToken(rp.c, .Semicolon, ";");
2815 return transCreateNodeInfixOp(rp, scope, expr, op, token, one, .used, false);
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);
28162785 }
28172786 // worst case
28182787 // c: expr++
......@@ -2822,68 +2791,36 @@ fn transCreatePostCrement(
28222791 // zig: _ref.* += 1;
28232792 // zig: break :blk _tmp
28242793 // zig: })
2825 var block_scope = try Scope.Block.init(rp.c, scope, true);
2794 var block_scope = try Scope.Block.init(c, scope, true);
28262795 defer block_scope.deinit();
2827 const ref = try block_scope.makeMangledName(rp.c, "ref");
2796 const ref = try block_scope.makeMangledName(c, "ref");
28282797
2829 const mut_tok = try appendToken(rp.c, .Keyword_const, "const");
2830 const name_tok = try appendIdentifier(rp.c, ref);
2831 const eq_token = try appendToken(rp.c, .Equal, "=");
2832 const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
2833 rhs_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value);
2834 const init_node = &rhs_node.base;
2835 const semicolon_token = try appendToken(rp.c, .Semicolon, ";");
2836 const node = try ast.Node.VarDecl.create(rp.c.arena, .{
2837 .name_token = name_tok,
2838 .mut_token = mut_tok,
2839 .semicolon_token = semicolon_token,
2840 }, .{
2841 .eq_token = eq_token,
2842 .init_node = init_node,
2843 });
2844 try block_scope.statements.append(&node.base);
2798 const expr = try transExpr(c, scope, op_expr, .used, .r_value);
2799 const addr_of = try Node.address_of.create(c.arena, expr);
2800 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
2801 try block_scope.statements.append(ref_decl);
28452802
2846 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);
2847 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
2848 _ = try appendToken(rp.c, .Semicolon, ";");
2803 const lhs_node = try Node.identifier.create(c.arena, ref);
2804 const ref_node = try Node.deref.create(c.arena, lhs_node);
28492805
2850 const tmp = try block_scope.makeMangledName(rp.c, "tmp");
2851 const tmp_mut_tok = try appendToken(rp.c, .Keyword_const, "const");
2852 const tmp_name_tok = try appendIdentifier(rp.c, tmp);
2853 const tmp_eq_token = try appendToken(rp.c, .Equal, "=");
2854 const tmp_init_node = ref_node;
2855 const tmp_semicolon_token = try appendToken(rp.c, .Semicolon, ";");
2856 const tmp_node = try ast.Node.VarDecl.create(rp.c.arena, .{
2857 .name_token = tmp_name_tok,
2858 .mut_token = tmp_mut_tok,
2859 .semicolon_token = semicolon_token,
2860 }, .{
2861 .eq_token = tmp_eq_token,
2862 .init_node = tmp_init_node,
2863 });
2864 try block_scope.statements.append(&tmp_node.base);
2806 const tmp = try block_scope.makeMangledName(c, "tmp");
2807 const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node});
2808 try block_scope.statements.append(tmp_decl);
28652809
2866 const token = try appendToken(rp.c, op_tok_id, bytes);
2867 const one = try transCreateNodeInt(rp.c, 1);
2868 _ = try appendToken(rp.c, .Semicolon, ";");
2869 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);
2870 try block_scope.statements.append(assign);
2871
2872 const break_node = blk: {
2873 var tmp_ctrl_flow = try CtrlFlow.initToken(rp.c, .Break, block_scope.label);
2874 const rhs = try transCreateNodeIdentifier(rp.c, tmp);
2875 break :blk try tmp_ctrl_flow.finish(rhs);
2876 };
2877 try block_scope.statements.append(&break_node.base);
2878 _ = try appendToken(rp.c, .Semicolon, ";");
2879 const block_node = try block_scope.complete(rp.c);
2880 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
2881 grouped_expr.* = .{
2882 .lparen = try appendToken(rp.c, .LParen, "("),
2883 .expr = block_node,
2884 .rparen = try appendToken(rp.c, .RParen, ")"),
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 }
28852817 };
2886 return &grouped_expr.base;
2818 try block_scope.statements.append(Node.initPayload(&payload.base));
2819
2820 return Node.break_val.create(c.arena, .{
2821 .label = block_scope.label,
2822 .val = try Node.identifier.create(c.arena, tmp),
2823 });
28872824}
28882825
28892826fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
......@@ -3139,31 +3076,24 @@ fn transCPtrCast(
31393076 }
31403077}
31413078
3142fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
3079fn transBreak(c: *Context, scope: *Scope) TransError!Node {
31433080 const break_scope = scope.getBreakableScope();
31443081 const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {
31453082 const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);
3146 const block_scope = try scope.findBlockScope(rp.c);
3147 swtch.switch_label = try block_scope.makeMangledName(rp.c, "switch");
3083 const block_scope = try scope.findBlockScope(c);
3084 swtch.switch_label = try block_scope.makeMangledName(c, "switch");
31483085 break :blk swtch.switch_label;
31493086 } else
31503087 null;
31513088
3152 var cf = try CtrlFlow.init(rp.c, .Break, label_text);
3153 const br = try cf.finish(null);
3154 _ = try appendToken(rp.c, .Semicolon, ";");
3155 return &br.base;
3089 return Node.@"break".create(c.arena, label_text);
31563090}
31573091
3158fn transFloatingLiteral(rp: RestorePoint, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!*ast.Node {
3092fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {
31593093 // TODO use something more accurate
31603094 const dbl = stmt.getValueAsApproximateDouble();
3161 const node = try rp.c.arena.create(ast.Node.OneToken);
3162 node.* = .{
3163 .base = .{ .tag = .FloatLiteral },
3164 .token = try appendTokenFmt(rp.c, .FloatLiteral, "{d}", .{dbl}),
3165 };
3166 return maybeSuppressResult(rp, scope, used, &node.base);
3095 const node = try Node.float_literal.create(c.arena, try std.fmt.allocPrint(c.arena, "{d}", .{dbl}));
3096 return maybeSuppressResult(c, scope, used, &node.base);
31673097}
31683098
31693099fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!*ast.Node {
......@@ -3943,169 +3873,7 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
39433873 return &fn_proto.base;
39443874}
39453875
3946fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node {
3947 _ = try appendToken(c, .Period, ".");
3948 const qm = try appendToken(c, .QuestionMark, "?");
3949 const node = try c.arena.create(ast.Node.SimpleSuffixOp);
3950 node.* = .{
3951 .base = .{ .tag = .UnwrapOptional },
3952 .lhs = wrapped,
3953 .rtoken = qm,
3954 };
3955 return &node.base;
3956}
3957
3958fn transCreateNodeEnumLiteral(c: *Context, name: []const u8) !*ast.Node {
3959 const node = try c.arena.create(ast.Node.EnumLiteral);
3960 node.* = .{
3961 .dot = try appendToken(c, .Period, "."),
3962 .name = try appendIdentifier(c, name),
3963 };
3964 return &node.base;
3965}
3966
3967fn transCreateNodeStringLiteral(c: *Context, str: []const u8) !*ast.Node {
3968 const node = try c.arena.create(ast.Node.OneToken);
3969 node.* = .{
3970 .base = .{ .tag = .StringLiteral },
3971 .token = try appendToken(c, .StringLiteral, str),
3972 };
3973 return &node.base;
3974}
3975
3976fn transCreateNodeIf(c: *Context) !*ast.Node.If {
3977 const if_tok = try appendToken(c, .Keyword_if, "if");
3978 _ = try appendToken(c, .LParen, "(");
3979 const node = try c.arena.create(ast.Node.If);
3980 node.* = .{
3981 .if_token = if_tok,
3982 .condition = undefined,
3983 .payload = null,
3984 .body = undefined,
3985 .@"else" = null,
3986 };
3987 return node;
3988}
3989
3990fn transCreateNodeElse(c: *Context) !*ast.Node.Else {
3991 const node = try c.arena.create(ast.Node.Else);
3992 node.* = .{
3993 .else_token = try appendToken(c, .Keyword_else, "else"),
3994 .payload = null,
3995 .body = undefined,
3996 };
3997 return node;
3998}
3999
4000fn transCreateNodeBreak(
4001 c: *Context,
4002 label: ?ast.TokenIndex,
4003 rhs: ?*ast.Node,
4004) !*ast.Node.ControlFlowExpression {
4005 var ctrl_flow = try CtrlFlow.init(c, .Break, if (label) |l| tokenSlice(c, l) else null);
4006 return ctrl_flow.finish(rhs);
4007}
4008
4009const CtrlFlow = struct {
4010 c: *Context,
4011 ltoken: ast.TokenIndex,
4012 label_token: ?ast.TokenIndex,
4013 tag: ast.Node.Tag,
4014
4015 /// Does everything except the RHS.
4016 fn init(c: *Context, tag: ast.Node.Tag, label: ?[]const u8) !CtrlFlow {
4017 const kw: Token.Id = switch (tag) {
4018 .Break => .Keyword_break,
4019 .Continue => .Keyword_continue,
4020 .Return => .Keyword_return,
4021 else => unreachable,
4022 };
4023 const kw_text = switch (tag) {
4024 .Break => "break",
4025 .Continue => "continue",
4026 .Return => "return",
4027 else => unreachable,
4028 };
4029 const ltoken = try appendToken(c, kw, kw_text);
4030 const label_token = if (label) |l| blk: {
4031 _ = try appendToken(c, .Colon, ":");
4032 break :blk try appendIdentifier(c, l);
4033 } else null;
4034 return CtrlFlow{
4035 .c = c,
4036 .ltoken = ltoken,
4037 .label_token = label_token,
4038 .tag = tag,
4039 };
4040 }
4041
4042 fn initToken(c: *Context, tag: ast.Node.Tag, label: ?ast.TokenIndex) !CtrlFlow {
4043 const other_token = label orelse return init(c, tag, null);
4044 const loc = c.token_locs.items[other_token];
4045 const label_name = c.source_buffer.items[loc.start..loc.end];
4046 return init(c, tag, label_name);
4047 }
4048
4049 fn finish(self: *CtrlFlow, rhs: ?*ast.Node) !*ast.Node.ControlFlowExpression {
4050 return ast.Node.ControlFlowExpression.create(self.c.arena, .{
4051 .ltoken = self.ltoken,
4052 .tag = self.tag,
4053 }, .{
4054 .label = self.label_token,
4055 .rhs = rhs,
4056 });
4057 }
4058};
4059
4060fn transCreateNodeWhile(c: *Context) !*ast.Node.While {
4061 const while_tok = try appendToken(c, .Keyword_while, "while");
4062 _ = try appendToken(c, .LParen, "(");
4063
4064 const node = try c.arena.create(ast.Node.While);
4065 node.* = .{
4066 .label = null,
4067 .inline_token = null,
4068 .while_token = while_tok,
4069 .condition = undefined,
4070 .payload = null,
4071 .continue_expr = null,
4072 .body = undefined,
4073 .@"else" = null,
4074 };
4075 return node;
4076}
4077
4078fn transCreateNodeContinue(c: *Context) !*ast.Node {
4079 const ltoken = try appendToken(c, .Keyword_continue, "continue");
4080 const node = try ast.Node.ControlFlowExpression.create(c.arena, .{
4081 .ltoken = ltoken,
4082 .tag = .Continue,
4083 }, .{});
4084 _ = try appendToken(c, .Semicolon, ";");
4085 return &node.base;
4086}
4087
4088fn transCreateNodeSwitchCase(c: *Context, lhs: *ast.Node) !*ast.Node.SwitchCase {
4089 const arrow_tok = try appendToken(c, .EqualAngleBracketRight, "=>");
40903876
4091 const node = try ast.Node.SwitchCase.alloc(c.arena, 1);
4092 node.* = .{
4093 .items_len = 1,
4094 .arrow_token = arrow_tok,
4095 .payload = null,
4096 .expr = undefined,
4097 };
4098 node.items()[0] = lhs;
4099 return node;
4100}
4101
4102fn transCreateNodeSwitchElse(c: *Context) !*ast.Node {
4103 const node = try c.arena.create(ast.Node.SwitchElse);
4104 node.* = .{
4105 .token = try appendToken(c, .Keyword_else, "else"),
4106 };
4107 return &node.base;
4108}
41093877
41103878fn transCreateNodeShiftOp(
41113879 c: *Context,
......@@ -4137,27 +3905,6 @@ fn transCreateNodeShiftOp(
41373905 return Node.initPayload(&payload.base);
41383906}
41393907
4140fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
4141 const node = try c.arena.create(ast.Node.SimpleSuffixOp);
4142 node.* = .{
4143 .base = .{ .tag = .Deref },
4144 .lhs = lhs,
4145 .rtoken = try appendToken(c, .PeriodAsterisk, ".*"),
4146 };
4147 return &node.base;
4148}
4149
4150fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAccess {
4151 _ = try appendToken(c, .LBrace, "[");
4152 const node = try c.arena.create(ast.Node.ArrayAccess);
4153 node.* = .{
4154 .lhs = lhs,
4155 .index_expr = undefined,
4156 .rtoken = undefined,
4157 };
4158 return node;
4159}
4160
41613908fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
41623909 switch (ty.getTypeClass()) {
41633910 .Builtin => {
src/translate_c/ast.zig+16-6
......@@ -17,6 +17,7 @@ pub const Node = extern union {
1717 empty_block,
1818 return_void,
1919 zero_literal,
20 one_literal,
2021 void_type,
2122 noreturn_type,
2223 /// pub usingnamespace @import("std").c.builtins;
......@@ -44,7 +45,6 @@ pub const Node = extern union {
4445 break_val,
4546 @"return",
4647 field_access,
47 field_access_arrow,
4848 array_access,
4949 call,
5050 std_mem_zeroes,
......@@ -153,8 +153,10 @@ pub const Node = extern union {
153153 bit_not,
154154 not,
155155 address_of,
156 // operand.?.*
156 /// operand.?.*
157157 unwrap_deref,
158 /// .*
159 deref,
158160
159161 block,
160162 @"break",
......@@ -202,11 +204,11 @@ pub const Node = extern union {
202204 .usingnamespace_builtins,
203205 .return_void,
204206 .zero_literal,
207 .one_literal,
205208 .void_type,
206209 .noreturn_type,
207210 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
208211
209 .array_access,
210212 .std_mem_zeroes,
211213 .@"return",
212214 .discard,
......@@ -218,6 +220,7 @@ pub const Node = extern union {
218220 .optional_type,
219221 .address_of,
220222 .unwrap_deref,
223 .deref,
221224 .ptr_to_int,
222225 .enum_to_int,
223226 .empty_array,
......@@ -296,8 +299,6 @@ pub const Node = extern union {
296299 .string,
297300 .char,
298301 .identifier,
299 .field_access,
300 .field_access_arrow,
301302 .warning,
302303 .failed_decl,
303304 .sizeof,
......@@ -323,9 +324,10 @@ pub const Node = extern union {
323324 .array_type => Payload.Array,
324325 .arg_redecl => Payload.ArgRedecl,
325326 .log2_int_type => Payload.Log2IntType,
326 .typedef, .pub_typedef, .pub_var_simple => Payload.SimpleVarDecl,
327 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
327328 .enum_redecl => Payload.EnumRedecl,
328329 .array_filler => Payload.ArrayFiller,
330 .field_access => Payload.FieldAccess,
329331 };
330332 }
331333
......@@ -588,6 +590,14 @@ pub const Payload = struct {
588590 count: usize,
589591 },
590592 };
593
594 pub const FieldAccess = struct {
595 base: Node,
596 data: struct {
597 container: Node,
598 name: []const u8,
599 },
600 };
591601};
592602
593603/// Converts the nodes into a Zig ast.