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:...@@ -2438,11 +2438,11 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
2438 return block_scope.complete(c);2438 return block_scope.complete(c);
2439}2439}
24402440
2441fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!*ast.Node {2441fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node {
2442 var container_node = try transExpr(rp, scope, stmt.getBase(), .used, .r_value);2442 var container_node = try transExpr(c, scope, stmt.getBase(), .used, .r_value);
24432443
2444 if (stmt.isArrow()) {2444 if (stmt.isArrow()) {
2445 container_node = try transCreateNodePtrDeref(rp.c, container_node);2445 container_node = try Node.deref.create(c.arena, container_node);
2446 }2446 }
24472447
2448 const member_decl = stmt.getMemberDecl();2448 const member_decl = stmt.getMemberDecl();
...@@ -2453,19 +2453,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExp...@@ -2453,19 +2453,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.MemberExp
2453 if (decl_kind == .Field) {2453 if (decl_kind == .Field) {
2454 const field_decl = @ptrCast(*const clang.FieldDecl, member_decl);2454 const field_decl = @ptrCast(*const clang.FieldDecl, member_decl);
2455 if (field_decl.isAnonymousStructOrUnion()) {2455 if (field_decl.isAnonymousStructOrUnion()) {
2456 const name = rp.c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?;2456 const name = c.decl_table.get(@ptrToInt(field_decl.getCanonicalDecl())).?;
2457 break :blk try mem.dupe(rp.c.arena, u8, name);2457 break :blk try mem.dupe(c.arena, u8, name);
2458 }2458 }
2459 }2459 }
2460 const decl = @ptrCast(*const clang.NamedDecl, member_decl);2460 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());
2462 };2462 };
24632463
2464 const node = try transCreateNodeFieldAccess(rp.c, container_node, name);2464 const node = try Node.field_access.create(c.arena, .{ .container = container_node, .name = name});
2465 return maybeSuppressResult(rp, scope, result_used, node);2465 return maybeSuppressResult(c, scope, result_used, node);
2466}2466}
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 {
2469 var base_stmt = stmt.getBase();2469 var base_stmt = stmt.getBase();
24702470
2471 // Unwrap the base statement if it's an array decayed to a bare pointer type2471 // 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...@@ -2478,30 +2478,23 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const clang.ArraySub
2478 }2478 }
2479 }2479 }
24802480
2481 const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value);2481 const container_node = try transExpr(c, scope, base_stmt, .used, .r_value);
2482 const node = try transCreateNodeArrayAccess(rp.c, container_node);
24832482
2484 // cast if the index is long long or signed2483 // cast if the index is long long or signed
2485 const subscr_expr = stmt.getIdx();2484 const subscr_expr = stmt.getIdx();
2486 const qt = getExprQualType(rp.c, subscr_expr);2485 const qt = getExprQualType(c, subscr_expr);
2487 const is_longlong = cIsLongLongInteger(qt);2486 const is_longlong = cIsLongLongInteger(qt);
2488 const is_signed = cIsSignedInteger(qt);2487 const is_signed = cIsSignedInteger(qt);
24892488
2490 if (is_longlong or is_signed) {2489
2491 const cast_node = try rp.c.createBuiltinCall("@intCast", 2);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);
2492 // check if long long first so that signed long long doesn't just become unsigned long long2492 // 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);2493 var typeid_node = if (is_longlong) try transCreateNodeIdentifier(c, "usize") else try transQualTypeIntWidthOf(c, qt, false);
2494 cast_node.params()[0] = typeid_node;2494 break :blk try Node.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used, .r_value)});
2495 _ = try appendToken(rp.c, .Comma, ",");2495 } else
2496 cast_node.params()[1] = try transExpr(rp, scope, subscr_expr, .used, .r_value);2496 try transExpr(c, scope, subscr_expr, .used, .r_value)});
2497 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");2497 return maybeSuppressResult(c, scope, result_used, node);
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);
2505}2498}
25062499
2507/// Check if an expression is ultimately a reference to a function declaration2500/// Check if an expression is ultimately a reference to a function declaration
...@@ -2536,9 +2529,9 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {...@@ -2536,9 +2529,9 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {
2536 }2529 }
2537}2530}
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 {
2540 const callee = stmt.getCallee();2533 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
2543 var is_ptr = false;2536 var is_ptr = false;
2544 const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr);2537 const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr);
...@@ -2549,16 +2542,12 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r...@@ -2549,16 +2542,12 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
2549 raw_fn_expr;2542 raw_fn_expr;
25502543
2551 const num_args = stmt.getNumArgs();2544 const num_args = stmt.getNumArgs();
2552 const node = try rp.c.createCall(fn_expr, num_args);2545 const call_params = try c.arena.alloc(Node, num_args);
2553 const call_params = node.params();
25542546
2555 const args = stmt.getArgs();2547 const args = stmt.getArgs();
2556 var i: usize = 0;2548 var i: usize = 0;
2557 while (i < num_args) : (i += 1) {2549 while (i < num_args) : (i += 1) {
2558 if (i != 0) {2550 var call_param = try transExpr(c, scope, args[i], .used, .r_value);
2559 _ = try appendToken(rp.c, .Comma, ",");
2560 }
2561 var call_param = try transExpr(rp, scope, args[i], .used, .r_value);
25622551
2563 // In C the result type of a boolean expression is int. If this result is passed as2552 // In C the result type of a boolean expression is int. If this result is passed as
2564 // an argument to a function whose parameter is also int, there is no cast. Therefore2553 // 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...@@ -2570,10 +2559,7 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
2570 if (i < param_count) {2559 if (i < param_count) {
2571 const param_qt = fn_proto.getParamType(@intCast(c_uint, i));2560 const param_qt = fn_proto.getParamType(@intCast(c_uint, i));
2572 if (isBoolRes(call_param) and cIsNativeInt(param_qt)) {2561 if (isBoolRes(call_param) and cIsNativeInt(param_qt)) {
2573 const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);2562 call_param = try Node.bool_to_int.create(c.arena, call_param);
2574 builtin_node.params()[0] = call_param;
2575 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2576 call_param = &builtin_node.base;
2577 }2563 }
2578 }2564 }
2579 },2565 },
...@@ -2582,18 +2568,16 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r...@@ -2582,18 +2568,16 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
2582 }2568 }
2583 call_params[i] = call_param;2569 call_params[i] = call_param;
2584 }2570 }
2585 node.rtoken = try appendToken(rp.c, .RParen, ")");2571 const node = try Node.call.create(c.arena, .{ .lhs = fn_expr, .args = call_params });
2586
2587 if (fn_ty) |ty| {2572 if (fn_ty) |ty| {
2588 const canon = ty.getReturnType().getCanonicalType();2573 const canon = ty.getReturnType().getCanonicalType();
2589 const ret_ty = canon.getTypePtr();2574 const ret_ty = canon.getTypePtr();
2590 if (ret_ty.isVoidType()) {2575 if (ret_ty.isVoidType()) {
2591 _ = try appendToken(rp.c, .Semicolon, ";");2576 return node;
2592 return &node.base;
2593 }2577 }
2594 }2578 }
25952579
2596 return maybeSuppressResult(rp, scope, result_used, &node.base);2580 return maybeSuppressResult(c, scope, result_used, node);
2597}2581}
25982582
2599const ClangFunctionType = union(enum) {2583const ClangFunctionType = union(enum) {
...@@ -2667,21 +2651,21 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat...@@ -2667,21 +2651,21 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
2667 const op_expr = stmt.getSubExpr();2651 const op_expr = stmt.getSubExpr();
2668 switch (stmt.getOpcode()) {2652 switch (stmt.getOpcode()) {
2669 .PostInc => if (qualTypeHasWrappingOverflow(stmt.getType()))2653 .PostInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
2670 return transCreatePostCrement(c, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)2654 return transCreatePostCrement(c, scope, stmt, .assign_add_wrap, used)
2671 else2655 else
2672 return transCreatePostCrement(c, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),2656 return transCreatePostCrement(c, scope, stmt, .assign_add, used),
2673 .PostDec => if (qualTypeHasWrappingOverflow(stmt.getType()))2657 .PostDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
2674 return transCreatePostCrement(c, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)2658 return transCreatePostCrement(c, scope, stmt, .assign_sub_wrap, used)
2675 else2659 else
2676 return transCreatePostCrement(c, scope, stmt, .AssignSub, .MinusEqual, "-=", used),2660 return transCreatePostCrement(c, scope, stmt, .assign_sub, used),
2677 .PreInc => if (qualTypeHasWrappingOverflow(stmt.getType()))2661 .PreInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
2678 return transCreatePreCrement(c, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)2662 return transCreatePreCrement(c, scope, stmt, .assign_add_wrap, used)
2679 else2663 else
2680 return transCreatePreCrement(c, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),2664 return transCreatePreCrement(c, scope, stmt, .assign_add, used),
2681 .PreDec => if (qualTypeHasWrappingOverflow(stmt.getType()))2665 .PreDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
2682 return transCreatePreCrement(c, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)2666 return transCreatePreCrement(c, scope, stmt, .assign_sub_wrap, used)
2683 else2667 else
2684 return transCreatePreCrement(c, scope, stmt, .AssignSub, .MinusEqual, "-=", used),2668 return transCreatePreCrement(c, scope, stmt, .assign_sub, used),
2685 .AddrOf => {2669 .AddrOf => {
2686 if (cIsFunctionDeclRef(op_expr)) {2670 if (cIsFunctionDeclRef(op_expr)) {
2687 return transExpr(rp, scope, op_expr, used, .r_value);2671 return transExpr(rp, scope, op_expr, used, .r_value);
...@@ -2704,7 +2688,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat...@@ -2704,7 +2688,7 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
2704 // use -% x for unsigned integers2688 // use -% x for unsigned integers
2705 return Node.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));2689 return Node.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
2706 } else2690 } 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", .{});
2708 },2692 },
2709 .Not => {2693 .Not => {
2710 return Node.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));2694 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...@@ -2715,31 +2699,32 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
2715 .Extension => {2699 .Extension => {
2716 return transExpr(c, scope, stmt.getSubExpr(), used, .l_value);2700 return transExpr(c, scope, stmt.getSubExpr(), used, .l_value);
2717 },2701 },
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()}),
2719 }2703 }
2720}2704}
27212705
2722fn transCreatePreCrement(2706fn transCreatePreCrement(
2723 rp: RestorePoint,2707 c: *Context,
2724 scope: *Scope,2708 scope: *Scope,
2725 stmt: *const clang.UnaryOperator,2709 stmt: *const clang.UnaryOperator,
2726 op: ast.Node.Tag,2710 op: Node.Tag,
2727 op_tok_id: std.zig.Token.Id,
2728 bytes: []const u8,
2729 used: ResultUsed,2711 used: ResultUsed,
2730) TransError!*ast.Node {2712) TransError!Node {
2731 const op_expr = stmt.getSubExpr();2713 const op_expr = stmt.getSubExpr();
27322714
2733 if (used == .unused) {2715 if (used == .unused) {
2734 // common case2716 // common case
2735 // c: ++expr2717 // c: ++expr
2736 // zig: expr += 12718 // zig: expr += 1
2737 const expr = try transExpr(rp, scope, op_expr, .used, .r_value);2719 const payload = try c.arena.create(ast.Payload.BinOp);
2738 const token = try appendToken(rp.c, op_tok_id, bytes);2720 payload.* = .{
2739 const one = try transCreateNodeInt(rp.c, 1);2721 .base = .{ .tag = op },
2740 if (scope.id != .Condition)2722 .data = .{
2741 _ = try appendToken(rp.c, .Semicolon, ";");2723 .lhs = try transExpr(c, scope, op_expr, .used, .r_value),
2742 return transCreateNodeInfixOp(rp, scope, expr, op, token, one, .used, false);2724 .rhs = Node.one_literal.init(),
2725 }
2726 };
2727 return Node.initPayload(&payload.base);
2743 }2728 }
2744 // worst case2729 // worst case
2745 // c: ++expr2730 // c: ++expr
...@@ -2748,71 +2733,55 @@ fn transCreatePreCrement(...@@ -2748,71 +2733,55 @@ fn transCreatePreCrement(
2748 // zig: _ref.* += 1;2733 // zig: _ref.* += 1;
2749 // zig: break :blk _ref.*2734 // zig: break :blk _ref.*
2750 // zig: })2735 // zig: })
2751 var block_scope = try Scope.Block.init(rp.c, scope, true);2736 var block_scope = try Scope.Block.init(c, scope, true);
2752 defer block_scope.deinit();2737 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");2740 const expr = try transExpr(c, scope, op_expr, .used, .r_value);
2756 const name_tok = try appendIdentifier(rp.c, ref);2741 const addr_of = try Node.address_of.create(c.arena, expr);
2757 const eq_token = try appendToken(rp.c, .Equal, "=");2742 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
2758 const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&");2743 try block_scope.statements.append(ref_decl);
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);
27712744
2772 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);2745 const lhs_node = try Node.identifier.create(c.arena, ref);
2773 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);2746 const ref_node = try Node.deref.create(c.arena, lhs_node);
2774 _ = try appendToken(rp.c, .Semicolon, ";");2747 const payload = try c.arena.create(ast.Payload.BinOp);
2775 const token = try appendToken(rp.c, op_tok_id, bytes);2748 payload.* = .{
2776 const one = try transCreateNodeInt(rp.c, 1);2749 .base = .{ .tag = op },
2777 _ = try appendToken(rp.c, .Semicolon, ";");2750 .data = .{
2778 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);2751 .lhs = ref_node,
2779 try block_scope.statements.append(assign);2752 .rhs = Node.one_literal.init(),
27802753 }
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, ")"),
2791 };2754 };
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 });
2793}2761}
27942762
2795fn transCreatePostCrement(2763fn transCreatePostCrement(
2796 rp: RestorePoint,2764 c: *Context,
2797 scope: *Scope,2765 scope: *Scope,
2798 stmt: *const clang.UnaryOperator,2766 stmt: *const clang.UnaryOperator,
2799 op: ast.Node.Tag,2767 op: Node.Tag,
2800 op_tok_id: std.zig.Token.Id,
2801 bytes: []const u8,
2802 used: ResultUsed,2768 used: ResultUsed,
2803) TransError!*ast.Node {2769) TransError!Node {
2804 const op_expr = stmt.getSubExpr();2770 const op_expr = stmt.getSubExpr();
28052771
2806 if (used == .unused) {2772 if (used == .unused) {
2807 // common case2773 // common case
2808 // c: ++expr2774 // c: ++expr
2809 // zig: expr += 12775 // zig: expr += 1
2810 const expr = try transExpr(rp, scope, op_expr, .used, .r_value);2776 const payload = try c.arena.create(ast.Payload.BinOp);
2811 const token = try appendToken(rp.c, op_tok_id, bytes);2777 payload.* = .{
2812 const one = try transCreateNodeInt(rp.c, 1);2778 .base = .{ .tag = op },
2813 if (scope.id != .Condition)2779 .data = .{
2814 _ = try appendToken(rp.c, .Semicolon, ";");2780 .lhs = try transExpr(c, scope, op_expr, .used, .r_value),
2815 return transCreateNodeInfixOp(rp, scope, expr, op, token, one, .used, false);2781 .rhs = Node.one_literal.init(),
2782 }
2783 };
2784 return Node.initPayload(&payload.base);
2816 }2785 }
2817 // worst case2786 // worst case
2818 // c: expr++2787 // c: expr++
...@@ -2822,68 +2791,36 @@ fn transCreatePostCrement(...@@ -2822,68 +2791,36 @@ fn transCreatePostCrement(
2822 // zig: _ref.* += 1;2791 // zig: _ref.* += 1;
2823 // zig: break :blk _tmp2792 // zig: break :blk _tmp
2824 // zig: })2793 // zig: })
2825 var block_scope = try Scope.Block.init(rp.c, scope, true);2794 var block_scope = try Scope.Block.init(c, scope, true);
2826 defer block_scope.deinit();2795 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");2798 const expr = try transExpr(c, scope, op_expr, .used, .r_value);
2830 const name_tok = try appendIdentifier(rp.c, ref);2799 const addr_of = try Node.address_of.create(c.arena, expr);
2831 const eq_token = try appendToken(rp.c, .Equal, "=");2800 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
2832 const rhs_node = try transCreateNodeSimplePrefixOp(rp.c, .AddressOf, .Ampersand, "&");2801 try block_scope.statements.append(ref_decl);
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);
28452802
2846 const lhs_node = try transCreateNodeIdentifier(rp.c, ref);2803 const lhs_node = try Node.identifier.create(c.arena, ref);
2847 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);2804 const ref_node = try Node.deref.create(c.arena, lhs_node);
2848 _ = try appendToken(rp.c, .Semicolon, ";");
28492805
2850 const tmp = try block_scope.makeMangledName(rp.c, "tmp");2806 const tmp = try block_scope.makeMangledName(c, "tmp");
2851 const tmp_mut_tok = try appendToken(rp.c, .Keyword_const, "const");2807 const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node});
2852 const tmp_name_tok = try appendIdentifier(rp.c, tmp);2808 try block_scope.statements.append(tmp_decl);
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);
28652809
2866 const token = try appendToken(rp.c, op_tok_id, bytes);2810 const payload = try c.arena.create(ast.Payload.BinOp);
2867 const one = try transCreateNodeInt(rp.c, 1);2811 payload.* = .{
2868 _ = try appendToken(rp.c, .Semicolon, ";");2812 .base = .{ .tag = op },
2869 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);2813 .data = .{
2870 try block_scope.statements.append(assign);2814 .lhs = ref_node,
28712815 .rhs = Node.one_literal.init(),
2872 const break_node = blk: {2816 }
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, ")"),
2885 };2817 };
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 });
2887}2824}
28882825
2889fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {2826fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
...@@ -3139,31 +3076,24 @@ fn transCPtrCast(...@@ -3139,31 +3076,24 @@ fn transCPtrCast(
3139 }3076 }
3140}3077}
31413078
3142fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {3079fn transBreak(c: *Context, scope: *Scope) TransError!Node {
3143 const break_scope = scope.getBreakableScope();3080 const break_scope = scope.getBreakableScope();
3144 const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {3081 const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {
3145 const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);3082 const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);
3146 const block_scope = try scope.findBlockScope(rp.c);3083 const block_scope = try scope.findBlockScope(c);
3147 swtch.switch_label = try block_scope.makeMangledName(rp.c, "switch");3084 swtch.switch_label = try block_scope.makeMangledName(c, "switch");
3148 break :blk swtch.switch_label;3085 break :blk swtch.switch_label;
3149 } else3086 } else
3150 null;3087 null;
31513088
3152 var cf = try CtrlFlow.init(rp.c, .Break, label_text);3089 return Node.@"break".create(c.arena, label_text);
3153 const br = try cf.finish(null);
3154 _ = try appendToken(rp.c, .Semicolon, ";");
3155 return &br.base;
3156}3090}
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 {
3159 // TODO use something more accurate3093 // TODO use something more accurate
3160 const dbl = stmt.getValueAsApproximateDouble();3094 const dbl = stmt.getValueAsApproximateDouble();
3161 const node = try rp.c.arena.create(ast.Node.OneToken);3095 const node = try Node.float_literal.create(c.arena, try std.fmt.allocPrint(c.arena, "{d}", .{dbl}));
3162 node.* = .{3096 return maybeSuppressResult(c, scope, used, &node.base);
3163 .base = .{ .tag = .FloatLiteral },
3164 .token = try appendTokenFmt(rp.c, .FloatLiteral, "{d}", .{dbl}),
3165 };
3166 return maybeSuppressResult(rp, scope, used, &node.base);
3167}3097}
31683098
3169fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!*ast.Node {3099fn 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...@@ -3943,169 +3873,7 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
3943 return &fn_proto.base;3873 return &fn_proto.base;
3944}3874}
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
4110fn transCreateNodeShiftOp(3878fn transCreateNodeShiftOp(
4111 c: *Context,3879 c: *Context,
...@@ -4137,27 +3905,6 @@ fn transCreateNodeShiftOp(...@@ -4137,27 +3905,6 @@ fn transCreateNodeShiftOp(
4137 return Node.initPayload(&payload.base);3905 return Node.initPayload(&payload.base);
4138}3906}
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
4161fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {3908fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node {
4162 switch (ty.getTypeClass()) {3909 switch (ty.getTypeClass()) {
4163 .Builtin => {3910 .Builtin => {
src/translate_c/ast.zig+16-6
...@@ -17,6 +17,7 @@ pub const Node = extern union {...@@ -17,6 +17,7 @@ pub const Node = extern union {
17 empty_block,17 empty_block,
18 return_void,18 return_void,
19 zero_literal,19 zero_literal,
20 one_literal,
20 void_type,21 void_type,
21 noreturn_type,22 noreturn_type,
22 /// pub usingnamespace @import("std").c.builtins;23 /// pub usingnamespace @import("std").c.builtins;
...@@ -44,7 +45,6 @@ pub const Node = extern union {...@@ -44,7 +45,6 @@ pub const Node = extern union {
44 break_val,45 break_val,
45 @"return",46 @"return",
46 field_access,47 field_access,
47 field_access_arrow,
48 array_access,48 array_access,
49 call,49 call,
50 std_mem_zeroes,50 std_mem_zeroes,
...@@ -153,8 +153,10 @@ pub const Node = extern union {...@@ -153,8 +153,10 @@ pub const Node = extern union {
153 bit_not,153 bit_not,
154 not,154 not,
155 address_of,155 address_of,
156 // operand.?.*156 /// operand.?.*
157 unwrap_deref,157 unwrap_deref,
158 /// .*
159 deref,
158160
159 block,161 block,
160 @"break",162 @"break",
...@@ -202,11 +204,11 @@ pub const Node = extern union {...@@ -202,11 +204,11 @@ pub const Node = extern union {
202 .usingnamespace_builtins,204 .usingnamespace_builtins,
203 .return_void,205 .return_void,
204 .zero_literal,206 .zero_literal,
207 .one_literal,
205 .void_type,208 .void_type,
206 .noreturn_type,209 .noreturn_type,
207 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),210 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
208211
209 .array_access,
210 .std_mem_zeroes,212 .std_mem_zeroes,
211 .@"return",213 .@"return",
212 .discard,214 .discard,
...@@ -218,6 +220,7 @@ pub const Node = extern union {...@@ -218,6 +220,7 @@ pub const Node = extern union {
218 .optional_type,220 .optional_type,
219 .address_of,221 .address_of,
220 .unwrap_deref,222 .unwrap_deref,
223 .deref,
221 .ptr_to_int,224 .ptr_to_int,
222 .enum_to_int,225 .enum_to_int,
223 .empty_array,226 .empty_array,
...@@ -296,8 +299,6 @@ pub const Node = extern union {...@@ -296,8 +299,6 @@ pub const Node = extern union {
296 .string,299 .string,
297 .char,300 .char,
298 .identifier,301 .identifier,
299 .field_access,
300 .field_access_arrow,
301 .warning,302 .warning,
302 .failed_decl,303 .failed_decl,
303 .sizeof,304 .sizeof,
...@@ -323,9 +324,10 @@ pub const Node = extern union {...@@ -323,9 +324,10 @@ pub const Node = extern union {
323 .array_type => Payload.Array,324 .array_type => Payload.Array,
324 .arg_redecl => Payload.ArgRedecl,325 .arg_redecl => Payload.ArgRedecl,
325 .log2_int_type => Payload.Log2IntType,326 .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,
327 .enum_redecl => Payload.EnumRedecl,328 .enum_redecl => Payload.EnumRedecl,
328 .array_filler => Payload.ArrayFiller,329 .array_filler => Payload.ArrayFiller,
330 .field_access => Payload.FieldAccess,
329 };331 };
330 }332 }
331333
...@@ -588,6 +590,14 @@ pub const Payload = struct {...@@ -588,6 +590,14 @@ pub const Payload = struct {
588 count: usize,590 count: usize,
589 },591 },
590 };592 };
593
594 pub const FieldAccess = struct {
595 base: Node,
596 data: struct {
597 container: Node,
598 name: []const u8,
599 },
600 };
591};601};
592602
593/// Converts the nodes into a Zig ast.603/// Converts the nodes into a Zig ast.