| ... | ... | @@ -634,42 +634,14 @@ const InstTracking = struct { |
| 634 | 634 | } |
| 635 | 635 | |
| 636 | 636 | fn reuseFrame(self: *InstTracking) void { |
| 637 | | switch (self.long) { |
| 638 | | .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } }, |
| 639 | | else => {}, |
| 640 | | } |
| 641 | | self.short = switch (self.long) { |
| 642 | | .none, |
| 643 | | .unreach, |
| 644 | | .undef, |
| 645 | | .immediate, |
| 646 | | .memory, |
| 647 | | .load_direct, |
| 648 | | .lea_direct, |
| 649 | | .load_got, |
| 650 | | .lea_got, |
| 651 | | .load_tlv, |
| 652 | | .lea_tlv, |
| 653 | | .load_frame, |
| 654 | | .lea_frame, |
| 655 | | .load_symbol, |
| 656 | | .lea_symbol, |
| 657 | | => self.long, |
| 658 | | .dead, |
| 659 | | .eflags, |
| 660 | | .register, |
| 661 | | .register_pair, |
| 662 | | .register_triple, |
| 663 | | .register_quadruple, |
| 664 | | .register_offset, |
| 665 | | .register_overflow, |
| 666 | | .register_mask, |
| 667 | | .indirect, |
| 668 | | .elementwise_regs_then_frame, |
| 669 | | .reserved_frame, |
| 670 | | .air_ref, |
| 671 | | => unreachable, |
| 672 | | }; |
| 637 | self.* = .init(switch (self.long) { |
| 638 | .none => switch (self.short) { |
| 639 | .dead => .none, |
| 640 | else => |short| short, |
| 641 | }, |
| 642 | .reserved_frame => |index| .{ .load_frame = .{ .index = index } }, |
| 643 | else => |long| long, |
| 644 | }); |
| 673 | 645 | } |
| 674 | 646 | |
| 675 | 647 | fn trackSpill(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -681,6 +653,15 @@ const InstTracking = struct { |
| 681 | 653 | fn verifyMaterialize(self: InstTracking, target: InstTracking) void { |
| 682 | 654 | switch (self.long) { |
| 683 | 655 | .none, |
| 656 | .load_frame, |
| 657 | .reserved_frame, |
| 658 | => switch (target.long) { |
| 659 | .none, |
| 660 | .load_frame, |
| 661 | .reserved_frame, |
| 662 | => {}, |
| 663 | else => unreachable, |
| 664 | }, |
| 684 | 665 | .unreach, |
| 685 | 666 | .undef, |
| 686 | 667 | .immediate, |
| ... | ... | @@ -695,15 +676,6 @@ const InstTracking = struct { |
| 695 | 676 | .load_symbol, |
| 696 | 677 | .lea_symbol, |
| 697 | 678 | => assert(std.meta.eql(self.long, target.long)), |
| 698 | | .load_frame, |
| 699 | | .reserved_frame, |
| 700 | | => switch (target.long) { |
| 701 | | .none, |
| 702 | | .load_frame, |
| 703 | | .reserved_frame, |
| 704 | | => {}, |
| 705 | | else => unreachable, |
| 706 | | }, |
| 707 | 679 | .dead, |
| 708 | 680 | .eflags, |
| 709 | 681 | .register, |
| ... | ... | @@ -754,10 +726,11 @@ const InstTracking = struct { |
| 754 | 726 | tracking_log.debug("{} => {} (materialize)", .{ inst, self.* }); |
| 755 | 727 | } |
| 756 | 728 | |
| 757 | | fn resurrect(self: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void { |
| 729 | fn resurrect(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index, scope_generation: u32) !void { |
| 758 | 730 | switch (self.short) { |
| 759 | 731 | .dead => |die_generation| if (die_generation >= scope_generation) { |
| 760 | 732 | self.reuseFrame(); |
| 733 | try function.getValue(self.short, inst); |
| 761 | 734 | tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* }); |
| 762 | 735 | }, |
| 763 | 736 | else => {}, |
| ... | ... | @@ -767,6 +740,7 @@ const InstTracking = struct { |
| 767 | 740 | fn die(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void { |
| 768 | 741 | if (self.short == .dead) return; |
| 769 | 742 | try function.freeValue(self.short); |
| 743 | if (self.long == .none) self.long = self.short; |
| 770 | 744 | self.short = .{ .dead = function.scope_generation }; |
| 771 | 745 | tracking_log.debug("{} => {} (death)", .{ inst, self.* }); |
| 772 | 746 | } |
| ... | ... | @@ -2359,7 +2333,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2359 | 2333 | } |
| 2360 | 2334 | |
| 2361 | 2335 | fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2362 | | @setEvalBranchQuota(1_600); |
| 2336 | @setEvalBranchQuota(1_700); |
| 2363 | 2337 | const pt = cg.pt; |
| 2364 | 2338 | const zcu = pt.zcu; |
| 2365 | 2339 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -2520,7 +2494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2520 | 2494 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2521 | 2495 | try ops[0].toSlicePtr(cg); |
| 2522 | 2496 | var res: [1]Temp = undefined; |
| 2523 | | cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ |
| 2497 | if (ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ |
| 2524 | 2498 | .patterns = &.{ |
| 2525 | 2499 | .{ .src = .{ .to_gpr, .simm32 } }, |
| 2526 | 2500 | }, |
| ... | ... | @@ -2625,7 +2599,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2625 | 2599 | ops[1].tracking(cg), |
| 2626 | 2600 | }), |
| 2627 | 2601 | else => |e| return e, |
| 2628 | | }; |
| 2602 | } else { // hack around Sema OPV bugs |
| 2603 | res[0] = ops[0]; |
| 2604 | } |
| 2629 | 2605 | for (ops) |op| for (res) |r| { |
| 2630 | 2606 | if (op.index == r.index) break; |
| 2631 | 2607 | } else try op.die(cg); |
| ... | ... | @@ -2637,7 +2613,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2637 | 2613 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2638 | 2614 | try ops[0].toSlicePtr(cg); |
| 2639 | 2615 | var res: [1]Temp = undefined; |
| 2640 | | cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ |
| 2616 | if (ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ |
| 2641 | 2617 | .patterns = &.{ |
| 2642 | 2618 | .{ .src = .{ .to_gpr, .simm32 } }, |
| 2643 | 2619 | }, |
| ... | ... | @@ -2757,7 +2733,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2757 | 2733 | ops[1].tracking(cg), |
| 2758 | 2734 | }), |
| 2759 | 2735 | else => |e| return e, |
| 2760 | | }; |
| 2736 | } else { |
| 2737 | // hack around Sema OPV bugs |
| 2738 | res[0] = ops[0]; |
| 2739 | } |
| 2761 | 2740 | for (ops) |op| for (res) |r| { |
| 2762 | 2741 | if (op.index == r.index) break; |
| 2763 | 2742 | } else try op.die(cg); |
| ... | ... | @@ -2799,79 +2778,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2799 | 2778 | })) { |
| 2800 | 2779 | else => unreachable, |
| 2801 | 2780 | inline .@"and", .@"or", .xor => |mir_tag| comptime &.{ .{ |
| 2802 | | .required_features = .{ .avx2, null, null, null }, |
| 2803 | | .src_constraints = .{ .{ .int_or_vec = .yword }, .{ .int_or_vec = .yword } }, |
| 2804 | | .patterns = &.{ |
| 2805 | | .{ .src = .{ .to_ymm, .mem } }, |
| 2806 | | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, |
| 2807 | | .{ .src = .{ .to_ymm, .to_ymm } }, |
| 2808 | | }, |
| 2809 | | .dst_temps = .{.{ .rc = .sse }}, |
| 2810 | | .each = .{ .once = &.{ |
| 2811 | | .{ ._, .vp_, mir_tag, .dst0y, .src0y, .src1y, ._ }, |
| 2812 | | } }, |
| 2813 | | }, .{ |
| 2814 | | .required_features = .{ .avx, null, null, null }, |
| 2815 | | .src_constraints = .{ .{ .int_or_vec = .yword }, .{ .int_or_vec = .yword } }, |
| 2816 | | .patterns = &.{ |
| 2817 | | .{ .src = .{ .to_ymm, .mem } }, |
| 2818 | | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, |
| 2819 | | .{ .src = .{ .to_ymm, .to_ymm } }, |
| 2820 | | }, |
| 2821 | | .dst_temps = .{.{ .rc = .sse }}, |
| 2822 | | .each = .{ .once = &.{ |
| 2823 | | .{ ._, .v_pd, mir_tag, .dst0y, .src0y, .src1y, ._ }, |
| 2824 | | } }, |
| 2825 | | }, .{ |
| 2826 | | .required_features = .{ .avx, null, null, null }, |
| 2827 | | .src_constraints = .{ .{ .int_or_vec = .xword }, .{ .int_or_vec = .xword } }, |
| 2828 | | .patterns = &.{ |
| 2829 | | .{ .src = .{ .to_xmm, .mem } }, |
| 2830 | | .{ .src = .{ .mem, .to_xmm }, .commute = .{ 0, 1 } }, |
| 2831 | | .{ .src = .{ .to_xmm, .to_xmm } }, |
| 2832 | | }, |
| 2833 | | .dst_temps = .{.{ .rc = .sse }}, |
| 2834 | | .each = .{ .once = &.{ |
| 2835 | | .{ ._, .vp_, mir_tag, .dst0x, .src0x, .src1x, ._ }, |
| 2836 | | } }, |
| 2837 | | }, .{ |
| 2838 | | .required_features = .{ .sse2, null, null, null }, |
| 2839 | | .src_constraints = .{ .{ .int_or_vec = .xword }, .{ .int_or_vec = .xword } }, |
| 2840 | | .patterns = &.{ |
| 2841 | | .{ .src = .{ .to_mut_xmm, .mem } }, |
| 2842 | | .{ .src = .{ .mem, .to_mut_xmm }, .commute = .{ 0, 1 } }, |
| 2843 | | .{ .src = .{ .to_mut_xmm, .to_xmm } }, |
| 2844 | | }, |
| 2845 | | .dst_temps = .{.{ .ref = .src0 }}, |
| 2846 | | .each = .{ .once = &.{ |
| 2847 | | .{ ._, .p_, mir_tag, .dst0x, .src1x, ._, ._ }, |
| 2848 | | } }, |
| 2849 | | }, .{ |
| 2850 | | .required_features = .{ .sse, null, null, null }, |
| 2851 | | .src_constraints = .{ .{ .int_or_vec = .xword }, .{ .int_or_vec = .xword } }, |
| 2852 | | .patterns = &.{ |
| 2853 | | .{ .src = .{ .to_mut_xmm, .mem } }, |
| 2854 | | .{ .src = .{ .mem, .to_mut_xmm }, .commute = .{ 0, 1 } }, |
| 2855 | | .{ .src = .{ .to_mut_xmm, .to_xmm } }, |
| 2856 | | }, |
| 2857 | | .dst_temps = .{.{ .ref = .src0 }}, |
| 2858 | | .each = .{ .once = &.{ |
| 2859 | | .{ ._, ._ps, mir_tag, .dst0x, .src1x, ._, ._ }, |
| 2860 | | } }, |
| 2861 | | }, .{ |
| 2862 | | .required_features = .{ .mmx, null, null, null }, |
| 2863 | | .src_constraints = .{ .{ .int_or_vec = .qword }, .{ .int_or_vec = .qword } }, |
| 2864 | | .patterns = &.{ |
| 2865 | | .{ .src = .{ .to_mut_mm, .mem } }, |
| 2866 | | .{ .src = .{ .mem, .to_mut_mm }, .commute = .{ 0, 1 } }, |
| 2867 | | .{ .src = .{ .to_mut_mm, .to_mm } }, |
| 2868 | | }, |
| 2869 | | .dst_temps = .{.{ .ref = .src0 }}, |
| 2870 | | .each = .{ .once = &.{ |
| 2871 | | .{ ._, .p_, mir_tag, .dst0q, .src1q, ._, ._ }, |
| 2872 | | } }, |
| 2873 | | }, .{ |
| 2874 | | .src_constraints = .{ .{ .int_or_vec = .byte }, .{ .int_or_vec = .byte } }, |
| 2781 | .src_constraints = .{ .{ .size = .byte }, .{ .size = .byte } }, |
| 2875 | 2782 | .patterns = &.{ |
| 2876 | 2783 | .{ .src = .{ .mut_mem, .imm8 } }, |
| 2877 | 2784 | .{ .src = .{ .imm8, .mut_mem }, .commute = .{ 0, 1 } }, |
| ... | ... | @@ -2889,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2889 | 2796 | .{ ._, ._, mir_tag, .dst0b, .src1b, ._, ._ }, |
| 2890 | 2797 | } }, |
| 2891 | 2798 | }, .{ |
| 2892 | | .src_constraints = .{ .{ .int_or_vec = .word }, .{ .int_or_vec = .word } }, |
| 2799 | .src_constraints = .{ .{ .size = .word }, .{ .size = .word } }, |
| 2893 | 2800 | .patterns = &.{ |
| 2894 | 2801 | .{ .src = .{ .mut_mem, .imm16 } }, |
| 2895 | 2802 | .{ .src = .{ .imm16, .mut_mem }, .commute = .{ 0, 1 } }, |
| ... | ... | @@ -2907,7 +2814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2907 | 2814 | .{ ._, ._, mir_tag, .dst0w, .src1w, ._, ._ }, |
| 2908 | 2815 | } }, |
| 2909 | 2816 | }, .{ |
| 2910 | | .src_constraints = .{ .{ .int_or_vec = .dword }, .{ .int_or_vec = .dword } }, |
| 2817 | .src_constraints = .{ .{ .size = .dword }, .{ .size = .dword } }, |
| 2911 | 2818 | .patterns = &.{ |
| 2912 | 2819 | .{ .src = .{ .mut_mem, .imm32 } }, |
| 2913 | 2820 | .{ .src = .{ .imm32, .mut_mem }, .commute = .{ 0, 1 } }, |
| ... | ... | @@ -2926,7 +2833,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2926 | 2833 | } }, |
| 2927 | 2834 | }, .{ |
| 2928 | 2835 | .required_features = .{ .@"64bit", null, null, null }, |
| 2929 | | .src_constraints = .{ .{ .int_or_vec = .qword }, .{ .int_or_vec = .qword } }, |
| 2836 | .src_constraints = .{ .{ .size = .qword }, .{ .size = .qword } }, |
| 2930 | 2837 | .patterns = &.{ |
| 2931 | 2838 | .{ .src = .{ .mut_mem, .simm32 } }, |
| 2932 | 2839 | .{ .src = .{ .simm32, .mut_mem }, .commute = .{ 0, 1 } }, |
| ... | ... | @@ -2943,12 +2850,81 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2943 | 2850 | .each = .{ .once = &.{ |
| 2944 | 2851 | .{ ._, ._, mir_tag, .dst0q, .src1q, ._, ._ }, |
| 2945 | 2852 | } }, |
| 2853 | }, .{ |
| 2854 | .required_features = .{ .mmx, null, null, null }, |
| 2855 | .src_constraints = .{ .{ .size = .qword }, .{ .size = .qword } }, |
| 2856 | .patterns = &.{ |
| 2857 | .{ .src = .{ .to_mut_mm, .mem } }, |
| 2858 | .{ .src = .{ .mem, .to_mut_mm }, .commute = .{ 0, 1 } }, |
| 2859 | .{ .src = .{ .to_mut_mm, .to_mm } }, |
| 2860 | }, |
| 2861 | .dst_temps = .{.{ .ref = .src0 }}, |
| 2862 | .each = .{ .once = &.{ |
| 2863 | .{ ._, .p_, mir_tag, .dst0q, .src1q, ._, ._ }, |
| 2864 | } }, |
| 2865 | }, .{ |
| 2866 | .required_features = .{ .avx, null, null, null }, |
| 2867 | .src_constraints = .{ .{ .size = .xword }, .{ .size = .xword } }, |
| 2868 | .patterns = &.{ |
| 2869 | .{ .src = .{ .to_xmm, .mem } }, |
| 2870 | .{ .src = .{ .mem, .to_xmm }, .commute = .{ 0, 1 } }, |
| 2871 | .{ .src = .{ .to_xmm, .to_xmm } }, |
| 2872 | }, |
| 2873 | .dst_temps = .{.{ .rc = .sse }}, |
| 2874 | .each = .{ .once = &.{ |
| 2875 | .{ ._, .vp_, mir_tag, .dst0x, .src0x, .src1x, ._ }, |
| 2876 | } }, |
| 2877 | }, .{ |
| 2878 | .required_features = .{ .sse2, null, null, null }, |
| 2879 | .src_constraints = .{ .{ .size = .xword }, .{ .size = .xword } }, |
| 2880 | .patterns = &.{ |
| 2881 | .{ .src = .{ .to_mut_xmm, .mem } }, |
| 2882 | .{ .src = .{ .mem, .to_mut_xmm }, .commute = .{ 0, 1 } }, |
| 2883 | .{ .src = .{ .to_mut_xmm, .to_xmm } }, |
| 2884 | }, |
| 2885 | .dst_temps = .{.{ .ref = .src0 }}, |
| 2886 | .each = .{ .once = &.{ |
| 2887 | .{ ._, .p_, mir_tag, .dst0x, .src1x, ._, ._ }, |
| 2888 | } }, |
| 2889 | }, .{ |
| 2890 | .required_features = .{ .sse, null, null, null }, |
| 2891 | .src_constraints = .{ .{ .size = .xword }, .{ .size = .xword } }, |
| 2892 | .patterns = &.{ |
| 2893 | .{ .src = .{ .to_mut_xmm, .mem } }, |
| 2894 | .{ .src = .{ .mem, .to_mut_xmm }, .commute = .{ 0, 1 } }, |
| 2895 | .{ .src = .{ .to_mut_xmm, .to_xmm } }, |
| 2896 | }, |
| 2897 | .dst_temps = .{.{ .ref = .src0 }}, |
| 2898 | .each = .{ .once = &.{ |
| 2899 | .{ ._, ._ps, mir_tag, .dst0x, .src1x, ._, ._ }, |
| 2900 | } }, |
| 2946 | 2901 | }, .{ |
| 2947 | 2902 | .required_features = .{ .avx2, null, null, null }, |
| 2948 | | .src_constraints = .{ |
| 2949 | | .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } }, |
| 2950 | | .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } }, |
| 2903 | .src_constraints = .{ .{ .size = .yword }, .{ .size = .yword } }, |
| 2904 | .patterns = &.{ |
| 2905 | .{ .src = .{ .to_ymm, .mem } }, |
| 2906 | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, |
| 2907 | .{ .src = .{ .to_ymm, .to_ymm } }, |
| 2951 | 2908 | }, |
| 2909 | .dst_temps = .{.{ .rc = .sse }}, |
| 2910 | .each = .{ .once = &.{ |
| 2911 | .{ ._, .vp_, mir_tag, .dst0y, .src0y, .src1y, ._ }, |
| 2912 | } }, |
| 2913 | }, .{ |
| 2914 | .required_features = .{ .avx, null, null, null }, |
| 2915 | .src_constraints = .{ .{ .size = .yword }, .{ .size = .yword } }, |
| 2916 | .patterns = &.{ |
| 2917 | .{ .src = .{ .to_ymm, .mem } }, |
| 2918 | .{ .src = .{ .mem, .to_ymm }, .commute = .{ 0, 1 } }, |
| 2919 | .{ .src = .{ .to_ymm, .to_ymm } }, |
| 2920 | }, |
| 2921 | .dst_temps = .{.{ .rc = .sse }}, |
| 2922 | .each = .{ .once = &.{ |
| 2923 | .{ ._, .v_pd, mir_tag, .dst0y, .src0y, .src1y, ._ }, |
| 2924 | } }, |
| 2925 | }, .{ |
| 2926 | .required_features = .{ .avx2, null, null, null }, |
| 2927 | .src_constraints = .{ .{ .multiple_size = .yword }, .{ .multiple_size = .yword } }, |
| 2952 | 2928 | .patterns = &.{ |
| 2953 | 2929 | .{ .src = .{ .to_mem, .to_mem } }, |
| 2954 | 2930 | }, |
| ... | ... | @@ -2972,10 +2948,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2972 | 2948 | } }, |
| 2973 | 2949 | }, .{ |
| 2974 | 2950 | .required_features = .{ .avx, null, null, null }, |
| 2975 | | .src_constraints = .{ |
| 2976 | | .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } }, |
| 2977 | | .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } }, |
| 2978 | | }, |
| 2951 | .src_constraints = .{ .{ .multiple_size = .yword }, .{ .multiple_size = .yword } }, |
| 2979 | 2952 | .patterns = &.{ |
| 2980 | 2953 | .{ .src = .{ .to_mem, .to_mem } }, |
| 2981 | 2954 | }, |
| ... | ... | @@ -2999,10 +2972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2999 | 2972 | } }, |
| 3000 | 2973 | }, .{ |
| 3001 | 2974 | .required_features = .{ .avx, null, null, null }, |
| 3002 | | .src_constraints = .{ |
| 3003 | | .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } }, |
| 3004 | | .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } }, |
| 3005 | | }, |
| 2975 | .src_constraints = .{ .{ .multiple_size = .xword }, .{ .multiple_size = .xword } }, |
| 3006 | 2976 | .patterns = &.{ |
| 3007 | 2977 | .{ .src = .{ .to_mem, .to_mem } }, |
| 3008 | 2978 | }, |
| ... | ... | @@ -3026,10 +2996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3026 | 2996 | } }, |
| 3027 | 2997 | }, .{ |
| 3028 | 2998 | .required_features = .{ .sse2, null, null, null }, |
| 3029 | | .src_constraints = .{ |
| 3030 | | .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } }, |
| 3031 | | .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } }, |
| 3032 | | }, |
| 2999 | .src_constraints = .{ .{ .multiple_size = .xword }, .{ .multiple_size = .xword } }, |
| 3033 | 3000 | .patterns = &.{ |
| 3034 | 3001 | .{ .src = .{ .to_mem, .to_mem } }, |
| 3035 | 3002 | }, |
| ... | ... | @@ -3053,10 +3020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3053 | 3020 | } }, |
| 3054 | 3021 | }, .{ |
| 3055 | 3022 | .required_features = .{ .sse, null, null, null }, |
| 3056 | | .src_constraints = .{ |
| 3057 | | .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } }, |
| 3058 | | .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } }, |
| 3059 | | }, |
| 3023 | .src_constraints = .{ .{ .multiple_size = .xword }, .{ .multiple_size = .xword } }, |
| 3060 | 3024 | .patterns = &.{ |
| 3061 | 3025 | .{ .src = .{ .to_mem, .to_mem } }, |
| 3062 | 3026 | }, |
| ... | ... | @@ -3080,10 +3044,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3080 | 3044 | } }, |
| 3081 | 3045 | }, .{ |
| 3082 | 3046 | .required_features = .{ .mmx, null, null, null }, |
| 3083 | | .src_constraints = .{ |
| 3084 | | .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } }, |
| 3085 | | .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } }, |
| 3086 | | }, |
| 3047 | .src_constraints = .{ .{ .multiple_size = .qword }, .{ .multiple_size = .qword } }, |
| 3087 | 3048 | .patterns = &.{ |
| 3088 | 3049 | .{ .src = .{ .to_mem, .to_mem } }, |
| 3089 | 3050 | }, |
| ... | ... | @@ -3106,10 +3067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 3106 | 3067 | .{ ._, ._nc, .j, .@"0b", ._, ._, ._ }, |
| 3107 | 3068 | } }, |
| 3108 | 3069 | }, .{ |
| 3109 | | .src_constraints = .{ |
| 3110 | | .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } }, |
| 3111 | | .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } }, |
| 3112 | | }, |
| 3070 | .src_constraints = .{ .{ .multiple_size = .qword }, .{ .multiple_size = .qword } }, |
| 3113 | 3071 | .patterns = &.{ |
| 3114 | 3072 | .{ .src = .{ .to_mem, .to_mem } }, |
| 3115 | 3073 | }, |
| ... | ... | @@ -6983,7 +6941,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 6983 | 6941 | const ty_pl = air_datas[@intFromEnum(inst)].ty_pl; |
| 6984 | 6942 | const extra = cg.air.extraData(Air.VectorCmp, ty_pl.payload).data; |
| 6985 | 6943 | switch (extra.compareOperator()) { |
| 6986 | | .eq, .neq => {}, |
| 6944 | .eq, .neq => if (cg.typeOf(extra.lhs).scalarType(zcu).isRuntimeFloat()) |
| 6945 | break :fallback try cg.airCmpVector(inst), |
| 6987 | 6946 | else => break :fallback try cg.airCmpVector(inst), |
| 6988 | 6947 | } |
| 6989 | 6948 | var ops = try cg.tempsFromOperands(inst, .{ extra.lhs, extra.rhs }); |
| ... | ... | @@ -9763,22 +9722,20 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9763 | 9722 | .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(extra.field_index, zcu)), |
| 9764 | 9723 | .@"packed" => break :fallback try cg.airStructFieldVal(inst), |
| 9765 | 9724 | }; |
| 9766 | | if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 9767 | | var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand}); |
| 9768 | | var res = try ops[0].read(field_ty, .{ .disp = field_off }, cg); |
| 9769 | | for (ops) |op| if (op.index != res.index) try op.die(cg); |
| 9770 | | try res.moveTo(inst, cg); |
| 9771 | | } else { |
| 9772 | | // hack around Sema OPV bugs |
| 9773 | | const res = try cg.tempInit(field_ty, .none); |
| 9774 | | try res.moveTo(inst, cg); |
| 9775 | | } |
| 9725 | var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand}); |
| 9726 | // hack around Sema OPV bugs |
| 9727 | var res = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 9728 | try ops[0].read(field_ty, .{ .disp = field_off }, cg) |
| 9729 | else |
| 9730 | try cg.tempInit(field_ty, .none); |
| 9731 | for (ops) |op| if (op.index != res.index) try op.die(cg); |
| 9732 | try res.moveTo(inst, cg); |
| 9776 | 9733 | }, |
| 9777 | 9734 | .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else { |
| 9778 | 9735 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 9779 | 9736 | const union_ty = cg.typeOf(bin_op.lhs).childType(zcu); |
| 9780 | | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9781 | 9737 | const union_layout = union_ty.unionGetLayout(zcu); |
| 9738 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9782 | 9739 | // hack around Sema OPV bugs |
| 9783 | 9740 | if (union_layout.tag_size > 0) try ops[0].store(&ops[1], .{ |
| 9784 | 9741 | .disp = @intCast(union_layout.tagOffset()), |
| ... | ... | @@ -9834,11 +9791,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9834 | 9791 | .ptr_elem_val => try cg.airPtrElemVal(inst), |
| 9835 | 9792 | } else { |
| 9836 | 9793 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 9794 | const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu); |
| 9837 | 9795 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 9838 | 9796 | try ops[0].toSlicePtr(cg); |
| 9839 | 9797 | var res: [1]Temp = undefined; |
| 9840 | | const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu); |
| 9841 | | cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ |
| 9798 | if (res_ty.hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ |
| 9842 | 9799 | .dst_constraints = .{.{ .int = .byte }}, |
| 9843 | 9800 | .patterns = &.{ |
| 9844 | 9801 | .{ .src = .{ .to_gpr, .simm32 } }, |
| ... | ... | @@ -9912,51 +9869,51 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 9912 | 9869 | .{ ._, ._, .mov, .dst0q, .leasi(.qword, .src0, .@"8", .src1), ._, ._ }, |
| 9913 | 9870 | } }, |
| 9914 | 9871 | } }) catch |err| switch (err) { |
| 9915 | | error.SelectFailed => switch (res_ty.abiSize(zcu)) { |
| 9916 | | // hack around Sema OPV bugs |
| 9917 | | 0 => res[0] = try cg.tempInit(res_ty, .none), |
| 9918 | | else => |elem_size| { |
| 9919 | | while (true) for (&ops) |*op| { |
| 9920 | | if (try op.toRegClass(true, .general_purpose, cg)) break; |
| 9921 | | } else break; |
| 9922 | | const lhs_reg = ops[0].unwrap(cg).temp.tracking(cg).short.register.to64(); |
| 9923 | | const rhs_reg = ops[1].unwrap(cg).temp.tracking(cg).short.register.to64(); |
| 9924 | | if (!std.math.isPowerOfTwo(elem_size)) { |
| 9925 | | try cg.spillEflagsIfOccupied(); |
| 9926 | | try cg.asmRegisterRegisterImmediate( |
| 9927 | | .{ .i_, .mul }, |
| 9928 | | rhs_reg, |
| 9929 | | rhs_reg, |
| 9930 | | .u(elem_size), |
| 9931 | | ); |
| 9932 | | try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{ |
| 9933 | | .base = .{ .reg = lhs_reg }, |
| 9934 | | .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } }, |
| 9935 | | }); |
| 9936 | | } else if (elem_size > 8) { |
| 9937 | | try cg.spillEflagsIfOccupied(); |
| 9938 | | try cg.asmRegisterImmediate( |
| 9939 | | .{ ._l, .sh }, |
| 9940 | | rhs_reg, |
| 9941 | | .u(std.math.log2_int(u64, elem_size)), |
| 9942 | | ); |
| 9943 | | try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{ |
| 9944 | | .base = .{ .reg = lhs_reg }, |
| 9945 | | .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } }, |
| 9946 | | }); |
| 9947 | | } else try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{ |
| 9872 | error.SelectFailed => { |
| 9873 | const elem_size = res_ty.abiSize(zcu); |
| 9874 | while (true) for (&ops) |*op| { |
| 9875 | if (try op.toRegClass(true, .general_purpose, cg)) break; |
| 9876 | } else break; |
| 9877 | const lhs_reg = ops[0].unwrap(cg).temp.tracking(cg).short.register.to64(); |
| 9878 | const rhs_reg = ops[1].unwrap(cg).temp.tracking(cg).short.register.to64(); |
| 9879 | if (!std.math.isPowerOfTwo(elem_size)) { |
| 9880 | try cg.spillEflagsIfOccupied(); |
| 9881 | try cg.asmRegisterRegisterImmediate( |
| 9882 | .{ .i_, .mul }, |
| 9883 | rhs_reg, |
| 9884 | rhs_reg, |
| 9885 | .u(elem_size), |
| 9886 | ); |
| 9887 | try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{ |
| 9948 | 9888 | .base = .{ .reg = lhs_reg }, |
| 9949 | | .mod = .{ .rm = .{ |
| 9950 | | .size = .qword, |
| 9951 | | .index = rhs_reg, |
| 9952 | | .scale = .fromFactor(@intCast(elem_size)), |
| 9953 | | } }, |
| 9889 | .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } }, |
| 9954 | 9890 | }); |
| 9955 | | res[0] = try ops[0].load(res_ty, .{}, cg); |
| 9956 | | }, |
| 9891 | } else if (elem_size > 8) { |
| 9892 | try cg.spillEflagsIfOccupied(); |
| 9893 | try cg.asmRegisterImmediate( |
| 9894 | .{ ._l, .sh }, |
| 9895 | rhs_reg, |
| 9896 | .u(std.math.log2_int(u64, elem_size)), |
| 9897 | ); |
| 9898 | try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{ |
| 9899 | .base = .{ .reg = lhs_reg }, |
| 9900 | .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } }, |
| 9901 | }); |
| 9902 | } else try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{ |
| 9903 | .base = .{ .reg = lhs_reg }, |
| 9904 | .mod = .{ .rm = .{ |
| 9905 | .size = .qword, |
| 9906 | .index = rhs_reg, |
| 9907 | .scale = .fromFactor(@intCast(elem_size)), |
| 9908 | } }, |
| 9909 | }); |
| 9910 | res[0] = try ops[0].load(res_ty, .{}, cg); |
| 9957 | 9911 | }, |
| 9958 | 9912 | else => |e| return e, |
| 9959 | | }; |
| 9913 | } else { |
| 9914 | // hack around Sema OPV bugs |
| 9915 | res[0] = try cg.tempInit(res_ty, .none); |
| 9916 | } |
| 9960 | 9917 | for (ops) |op| for (res) |r| { |
| 9961 | 9918 | if (op.index == r.index) break; |
| 9962 | 9919 | } else try op.die(cg); |
| ... | ... | @@ -10499,7 +10456,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co |
| 10499 | 10456 | if (opts.resurrect) for ( |
| 10500 | 10457 | self.inst_tracking.keys()[Temp.Index.max..state.inst_tracking_len], |
| 10501 | 10458 | self.inst_tracking.values()[Temp.Index.max..state.inst_tracking_len], |
| 10502 | | ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation); |
| 10459 | ) |inst, *tracking| try tracking.resurrect(self, inst, state.scope_generation); |
| 10503 | 10460 | for (deaths) |death| try self.processDeath(death); |
| 10504 | 10461 | |
| 10505 | 10462 | const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).array.len]RegisterLock; |
| ... | ... | @@ -10879,7 +10836,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 10879 | 10836 | const dst_ty = self.typeOfIndex(inst); |
| 10880 | 10837 | |
| 10881 | 10838 | const result = @as(?MCValue, result: { |
| 10882 | | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(zcu)); |
| 10839 | const src_abi_size: u31 = @intCast(src_ty.abiSize(zcu)); |
| 10840 | const dst_abi_size: u31 = @intCast(dst_ty.abiSize(zcu)); |
| 10883 | 10841 | |
| 10884 | 10842 | const src_int_info = src_ty.intInfo(zcu); |
| 10885 | 10843 | const dst_int_info = dst_ty.intInfo(zcu); |
| ... | ... | @@ -10890,7 +10848,6 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 10890 | 10848 | |
| 10891 | 10849 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 10892 | 10850 | if (dst_ty.isVector(zcu)) { |
| 10893 | | const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu)); |
| 10894 | 10851 | const max_abi_size = @max(dst_abi_size, src_abi_size); |
| 10895 | 10852 | if (max_abi_size > self.vectorSize(.int)) break :result null; |
| 10896 | 10853 | const has_avx = self.hasFeature(.avx); |
| ... | ... | @@ -11060,7 +11017,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 11060 | 11017 | else => src_int_info.bits, |
| 11061 | 11018 | }; |
| 11062 | 11019 | |
| 11063 | | const dst_mcv = if (dst_int_info.bits <= src_storage_bits and |
| 11020 | const dst_mcv = if ((if (src_mcv.getReg()) |src_reg| src_reg.class() == .general_purpose else src_abi_size > 8) and |
| 11021 | dst_int_info.bits <= src_storage_bits and |
| 11064 | 11022 | std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable == |
| 11065 | 11023 | std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and |
| 11066 | 11024 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: { |
| ... | ... | @@ -11079,8 +11037,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 11079 | 11037 | break :result .{ .register = registerAlias(dst_mcv.getReg().?, dst_abi_size) }; |
| 11080 | 11038 | } |
| 11081 | 11039 | |
| 11082 | | const src_limbs_len = std.math.divCeil(u16, src_int_info.bits, 64) catch unreachable; |
| 11083 | | const dst_limbs_len = std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable; |
| 11040 | const src_limbs_len = std.math.divCeil(u31, src_abi_size, 8) catch unreachable; |
| 11041 | const dst_limbs_len = @divExact(dst_abi_size, 8); |
| 11084 | 11042 | |
| 11085 | 11043 | const high_mcv: MCValue = if (dst_mcv.isBase()) |
| 11086 | 11044 | dst_mcv.address().offset((src_limbs_len - 1) * 8).deref() |
| ... | ... | @@ -12067,6 +12025,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 12067 | 12025 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 12068 | 12026 | |
| 12069 | 12027 | const ty = tuple_ty.fieldType(0, zcu); |
| 12028 | const ty_size = ty.abiSize(zcu); |
| 12070 | 12029 | const int_info = ty.intInfo(zcu); |
| 12071 | 12030 | |
| 12072 | 12031 | const hi_bits = (int_info.bits - 1) % 64 + 1; |
| ... | ... | @@ -12100,6 +12059,13 @@ fn genSetFrameTruncatedOverflowCompare( |
| 12100 | 12059 | try self.asmSetccRegister(.ne, eq_reg.to8()); |
| 12101 | 12060 | try self.genBinOpMir(.{ ._, .@"or" }, .u8, .{ .register = overflow_reg }, .{ .register = eq_reg }); |
| 12102 | 12061 | } |
| 12062 | try self.genSetMem( |
| 12063 | .{ .frame = frame_index }, |
| 12064 | @intCast(tuple_ty.structFieldOffset(1, zcu)), |
| 12065 | tuple_ty.fieldType(1, zcu), |
| 12066 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 12067 | .{}, |
| 12068 | ); |
| 12103 | 12069 | |
| 12104 | 12070 | const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu)); |
| 12105 | 12071 | if (hi_limb_off > 0) try self.genSetMem( |
| ... | ... | @@ -12116,13 +12082,20 @@ fn genSetFrameTruncatedOverflowCompare( |
| 12116 | 12082 | .{ .register = scratch_reg }, |
| 12117 | 12083 | .{}, |
| 12118 | 12084 | ); |
| 12119 | | try self.genSetMem( |
| 12120 | | .{ .frame = frame_index }, |
| 12121 | | @intCast(tuple_ty.structFieldOffset(1, zcu)), |
| 12122 | | tuple_ty.fieldType(1, zcu), |
| 12123 | | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 12124 | | .{}, |
| 12125 | | ); |
| 12085 | var ext_off: i32 = hi_limb_off + 8; |
| 12086 | if (ext_off < ty_size) { |
| 12087 | switch (int_info.signedness) { |
| 12088 | .signed => try self.asmRegisterImmediate(.{ ._r, .sa }, scratch_reg.to64(), .s(63)), |
| 12089 | .unsigned => try self.asmRegisterRegister(.{ ._, .xor }, scratch_reg.to32(), scratch_reg.to32()), |
| 12090 | } |
| 12091 | while (ext_off < ty_size) : (ext_off += 8) try self.genSetMem( |
| 12092 | .{ .frame = frame_index }, |
| 12093 | payload_off + ext_off, |
| 12094 | limb_ty, |
| 12095 | .{ .register = scratch_reg }, |
| 12096 | .{}, |
| 12097 | ); |
| 12098 | } |
| 12126 | 12099 | } |
| 12127 | 12100 | |
| 12128 | 12101 | fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -13581,9 +13554,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13581 | 13554 | .{ ._, .bt }, |
| 13582 | 13555 | .{ |
| 13583 | 13556 | .base = .{ .frame = frame_index }, |
| 13584 | | .mod = .{ .rm = .{ .size = .qword } }, |
| 13557 | .mod = .{ .rm = .{ |
| 13558 | .size = .qword, |
| 13559 | .disp = @intCast(index_imm / 64 * 8), |
| 13560 | } }, |
| 13585 | 13561 | }, |
| 13586 | | .u(index_imm), |
| 13562 | .u(index_imm % 64), |
| 13587 | 13563 | ), |
| 13588 | 13564 | else => try self.asmMemoryRegister( |
| 13589 | 13565 | .{ ._, .bt }, |
| ... | ... | @@ -13603,8 +13579,11 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13603 | 13579 | .load_frame => switch (index_mcv) { |
| 13604 | 13580 | .immediate => |index_imm| try self.asmMemoryImmediate( |
| 13605 | 13581 | .{ ._, .bt }, |
| 13606 | | try array_mat_mcv.mem(self, .{ .size = .qword }), |
| 13607 | | .u(index_imm), |
| 13582 | try array_mat_mcv.mem(self, .{ |
| 13583 | .size = .qword, |
| 13584 | .disp = @intCast(index_imm / 64 * 8), |
| 13585 | }), |
| 13586 | .u(index_imm % 64), |
| 13608 | 13587 | ), |
| 13609 | 13588 | else => try self.asmMemoryRegister( |
| 13610 | 13589 | .{ ._, .bt }, |
| ... | ... | @@ -13622,9 +13601,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13622 | 13601 | .base = .{ |
| 13623 | 13602 | .reg = try self.copyToTmpRegister(.usize, array_mat_mcv.address()), |
| 13624 | 13603 | }, |
| 13625 | | .mod = .{ .rm = .{ .size = .qword } }, |
| 13604 | .mod = .{ .rm = .{ |
| 13605 | .size = .qword, |
| 13606 | .disp = @intCast(index_imm / 64 * 8), |
| 13607 | } }, |
| 13626 | 13608 | }, |
| 13627 | | .u(index_imm), |
| 13609 | .u(index_imm % 64), |
| 13628 | 13610 | ), |
| 13629 | 13611 | else => try self.asmMemoryRegister( |
| 13630 | 13612 | .{ ._, .bt }, |
| ... | ... | @@ -14451,13 +14433,18 @@ fn genByteSwap( |
| 14451 | 14433 | return src_mcv; |
| 14452 | 14434 | }, |
| 14453 | 14435 | 9...16 => { |
| 14454 | | switch (src_mcv) { |
| 14436 | const mat_src_mcv: MCValue = mat_src_mcv: switch (src_mcv) { |
| 14437 | .register => { |
| 14438 | const frame_index = try self.allocFrameIndex(.initSpill(src_ty, zcu)); |
| 14439 | try self.genSetMem(.{ .frame = frame_index }, 0, src_ty, src_mcv, .{}); |
| 14440 | break :mat_src_mcv .{ .load_frame = .{ .index = frame_index } }; |
| 14441 | }, |
| 14455 | 14442 | .register_pair => |src_regs| if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) { |
| 14456 | 14443 | for (src_regs) |src_reg| try self.asmRegister(.{ ._, .bswap }, src_reg.to64()); |
| 14457 | 14444 | return .{ .register_pair = .{ src_regs[1], src_regs[0] } }; |
| 14458 | | }, |
| 14459 | | else => {}, |
| 14460 | | } |
| 14445 | } else src_mcv, |
| 14446 | else => src_mcv, |
| 14447 | }; |
| 14461 | 14448 | |
| 14462 | 14449 | const dst_regs = |
| 14463 | 14450 | try self.register_manager.allocRegs(2, .{ inst, inst }, abi.RegisterClass.gp); |
| ... | ... | @@ -14465,18 +14452,18 @@ fn genByteSwap( |
| 14465 | 14452 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 14466 | 14453 | |
| 14467 | 14454 | for (dst_regs, 0..) |dst_reg, limb_index| { |
| 14468 | | if (src_mcv.isBase()) { |
| 14455 | if (mat_src_mcv.isBase()) { |
| 14469 | 14456 | try self.asmRegisterMemory( |
| 14470 | 14457 | .{ ._, if (has_movbe) .movbe else .mov }, |
| 14471 | 14458 | dst_reg.to64(), |
| 14472 | | try src_mcv.address().offset(@intCast(limb_index * 8)).deref().mem(self, .{ .size = .qword }), |
| 14459 | try mat_src_mcv.address().offset(@intCast(limb_index * 8)).deref().mem(self, .{ .size = .qword }), |
| 14473 | 14460 | ); |
| 14474 | 14461 | if (!has_movbe) try self.asmRegister(.{ ._, .bswap }, dst_reg.to64()); |
| 14475 | 14462 | } else { |
| 14476 | 14463 | try self.asmRegisterRegister( |
| 14477 | 14464 | .{ ._, .mov }, |
| 14478 | 14465 | dst_reg.to64(), |
| 14479 | | src_mcv.register_pair[limb_index].to64(), |
| 14466 | mat_src_mcv.register_pair[limb_index].to64(), |
| 14480 | 14467 | ); |
| 14481 | 14468 | try self.asmRegister(.{ ._, .bswap }, dst_reg.to64()); |
| 14482 | 14469 | } |
| ... | ... | @@ -15680,6 +15667,15 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) |
| 15680 | 15667 | const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg); |
| 15681 | 15668 | defer self.register_manager.unlockReg(ptr_lock); |
| 15682 | 15669 | |
| 15670 | const mat_src_mcv: MCValue = mat_src_mcv: switch (src_mcv) { |
| 15671 | .register => if (src_bit_size > 64) { |
| 15672 | const frame_index = try self.allocFrameIndex(.initSpill(src_ty, self.pt.zcu)); |
| 15673 | try self.genSetMem(.{ .frame = frame_index }, 0, src_ty, src_mcv, .{}); |
| 15674 | break :mat_src_mcv .{ .load_frame = .{ .index = frame_index } }; |
| 15675 | } else src_mcv, |
| 15676 | else => src_mcv, |
| 15677 | }; |
| 15678 | |
| 15683 | 15679 | var limb_i: u16 = 0; |
| 15684 | 15680 | while (limb_i * limb_abi_bits < src_bit_off + src_bit_size) : (limb_i += 1) { |
| 15685 | 15681 | const part_bit_off = if (limb_i == 0) src_bit_off else 0; |
| ... | ... | @@ -15712,7 +15708,7 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) |
| 15712 | 15708 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 15713 | 15709 | defer self.register_manager.unlockReg(tmp_lock); |
| 15714 | 15710 | |
| 15715 | | try self.genSetReg(tmp_reg, limb_ty, src_mcv, .{}); |
| 15711 | try self.genSetReg(tmp_reg, limb_ty, mat_src_mcv, .{}); |
| 15716 | 15712 | switch (limb_i) { |
| 15717 | 15713 | 0 => try self.genShiftBinOpMir( |
| 15718 | 15714 | .{ ._l, .sh }, |
| ... | ... | @@ -15743,8 +15739,8 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) |
| 15743 | 15739 | defer self.register_manager.unlockReg(tmp_lock); |
| 15744 | 15740 | |
| 15745 | 15741 | try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) { |
| 15746 | | 0 => src_mcv, |
| 15747 | | else => src_mcv.address().offset(limb_i * limb_abi_size).deref(), |
| 15742 | 0 => mat_src_mcv, |
| 15743 | else => mat_src_mcv.address().offset(limb_i * limb_abi_size).deref(), |
| 15748 | 15744 | }, .{}); |
| 15749 | 15745 | try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask }); |
| 15750 | 15746 | try self.asmMemoryRegister( |
| ... | ... | @@ -17228,7 +17224,7 @@ fn genMulDivBinOp( |
| 17228 | 17224 | dst_mcv.address(), |
| 17229 | 17225 | lhs_mcv.address(), |
| 17230 | 17226 | rhs_mcv.address(), |
| 17231 | | .{ .immediate = src_info.bits }, |
| 17227 | .{ .immediate = 8 * src_abi_size }, |
| 17232 | 17228 | }, .{}); |
| 17233 | 17229 | return dst_mcv; |
| 17234 | 17230 | }, |
| ... | ... | @@ -17246,7 +17242,8 @@ fn genMulDivBinOp( |
| 17246 | 17242 | const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx }); |
| 17247 | 17243 | defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 17248 | 17244 | |
| 17249 | | const signedness = ty.intInfo(zcu).signedness; |
| 17245 | const int_info = ty.intInfo(zcu); |
| 17246 | const signedness = int_info.signedness; |
| 17250 | 17247 | switch (tag) { |
| 17251 | 17248 | .mul, |
| 17252 | 17249 | .mul_wrap, |
| ... | ... | @@ -17279,6 +17276,15 @@ fn genMulDivBinOp( |
| 17279 | 17276 | }, |
| 17280 | 17277 | }, ty, lhs_mcv, rhs_mcv); |
| 17281 | 17278 | |
| 17279 | switch (tag) { |
| 17280 | .mul, .rem, .div_trunc, .div_exact => {}, |
| 17281 | .mul_wrap => if (dst_ty.intInfo(zcu).bits < 8 * dst_abi_size) try self.truncateRegister( |
| 17282 | dst_ty, |
| 17283 | if (dst_abi_size <= 8) .rax else .rdx, |
| 17284 | ), |
| 17285 | else => unreachable, |
| 17286 | } |
| 17287 | |
| 17282 | 17288 | if (dst_abi_size <= 8) return .{ .register = registerAlias(switch (tag) { |
| 17283 | 17289 | .mul, .mul_wrap, .div_trunc, .div_exact => .rax, |
| 17284 | 17290 | .rem => .rdx, |
| ... | ... | @@ -21954,8 +21960,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 21954 | 21960 | break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(.usize, ptr_mcv) } }; |
| 21955 | 21961 | }; |
| 21956 | 21962 | }; |
| 21957 | | if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| { |
| 21958 | | _ = self.register_manager.lockReg(reg); |
| 21963 | if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |tracked_index| { |
| 21964 | try self.register_manager.getRegIndex(tracked_index, if (output == .none) inst else null); |
| 21965 | _ = self.register_manager.lockRegIndexAssumeUnused(tracked_index); |
| 21959 | 21966 | }; |
| 21960 | 21967 | if (!std.mem.eql(u8, name, "_")) |
| 21961 | 21968 | arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len)); |
| ... | ... | @@ -22881,7 +22888,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 22881 | 22888 | |
| 22882 | 22889 | try self.asmRegisterRegister(.{ ._q, .mov }, dst_regs[0].to64(), src_reg.to128()); |
| 22883 | 22890 | try self.asmRegisterRegister(.{ ._ps, .movhl }, tmp_reg.to128(), src_reg.to128()); |
| 22884 | | try self.asmRegisterRegister(.{ ._q, .mov }, dst_regs[1].to64(), src_reg.to128()); |
| 22891 | try self.asmRegisterRegister(.{ ._q, .mov }, dst_regs[1].to64(), tmp_reg.to128()); |
| 22885 | 22892 | } |
| 22886 | 22893 | return; |
| 22887 | 22894 | } else unreachable, |
| ... | ... | @@ -23831,10 +23838,12 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 23831 | 23838 | const dst_rc = self.regSetForType(dst_ty); |
| 23832 | 23839 | const src_rc = self.regSetForType(src_ty); |
| 23833 | 23840 | |
| 23834 | | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 23841 | const src_lock = if (src_mcv.getReg()) |src_reg| self.register_manager.lockReg(src_reg) else null; |
| 23835 | 23842 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 23836 | 23843 | |
| 23837 | | const dst_mcv = if (dst_rc.supersetOf(src_rc) and dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and |
| 23844 | const dst_mcv = if ((if (src_mcv.getReg()) |src_reg| src_reg.class() == .general_purpose else true) and |
| 23845 | dst_rc.supersetOf(src_rc) and dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and |
| 23846 | dst_ty.abiAlignment(zcu).order(src_ty.abiAlignment(zcu)).compare(.lte) and |
| 23838 | 23847 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: { |
| 23839 | 23848 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 23840 | 23849 | try self.genCopy(switch (std.math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) { |
| ... | ... | @@ -27702,7 +27711,7 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 27702 | 27711 | reg |
| 27703 | 27712 | else |
| 27704 | 27713 | unreachable, |
| 27705 | | .x87 => if (size_bytes == 16) |
| 27714 | .x87 => if (size_bytes >= 10 and size_bytes <= 16) |
| 27706 | 27715 | reg |
| 27707 | 27716 | else |
| 27708 | 27717 | unreachable, |
| ... | ... | @@ -28574,23 +28583,19 @@ const Temp = struct { |
| 28574 | 28583 | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }), |
| 28575 | 28584 | ); |
| 28576 | 28585 | }, |
| 28577 | | .register => |val_reg| try ptr.storeReg(val_ty, registerAlias( |
| 28586 | .register => |val_reg| try ptr.storeRegs(val_ty, &.{registerAlias( |
| 28578 | 28587 | val_reg, |
| 28579 | 28588 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28580 | | ), cg), |
| 28589 | )}, cg), |
| 28581 | 28590 | inline .register_pair, |
| 28582 | 28591 | .register_triple, |
| 28583 | 28592 | .register_quadruple, |
| 28584 | | => |val_regs| for (val_regs) |val_reg| { |
| 28585 | | try ptr.storeReg(val_ty, val_reg, cg); |
| 28586 | | try ptr.toOffset(@divExact(val_reg.bitSize(), 8), cg); |
| 28587 | | while (try ptr.toLea(cg)) {} |
| 28588 | | }, |
| 28593 | => |val_regs| try ptr.storeRegs(val_ty, &val_regs, cg), |
| 28589 | 28594 | .register_offset => |val_reg_off| switch (val_reg_off.off) { |
| 28590 | | 0 => try ptr.storeReg(val_ty, registerAlias( |
| 28595 | 0 => try ptr.storeRegs(val_ty, &.{registerAlias( |
| 28591 | 28596 | val_reg_off.reg, |
| 28592 | 28597 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28593 | | ), cg), |
| 28598 | )}, cg), |
| 28594 | 28599 | else => continue :val_to_gpr, |
| 28595 | 28600 | }, |
| 28596 | 28601 | .register_overflow => |val_reg_ov| { |
| ... | ... | @@ -28608,7 +28613,7 @@ const Temp = struct { |
| 28608 | 28613 | else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }), |
| 28609 | 28614 | }); |
| 28610 | 28615 | const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu)); |
| 28611 | | try ptr.storeReg(first_ty, registerAlias(val_reg_ov.reg, first_size), cg); |
| 28616 | try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg); |
| 28612 | 28617 | try ptr.toOffset(first_size, cg); |
| 28613 | 28618 | try cg.asmSetccMemory( |
| 28614 | 28619 | val_reg_ov.eflags, |
| ... | ... | @@ -28675,6 +28680,15 @@ const Temp = struct { |
| 28675 | 28680 | const val_mcv = val.tracking(cg).short; |
| 28676 | 28681 | switch (val_mcv) { |
| 28677 | 28682 | else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }), |
| 28683 | .undef => if (opts.safe) { |
| 28684 | var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp)); |
| 28685 | var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa }); |
| 28686 | var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) }); |
| 28687 | try dst_ptr.memset(&pat, &len, cg); |
| 28688 | try dst_ptr.die(cg); |
| 28689 | try pat.die(cg); |
| 28690 | try len.die(cg); |
| 28691 | }, |
| 28678 | 28692 | .immediate => |val_imm| { |
| 28679 | 28693 | const val_op: Immediate = if (std.math.cast(u31, val_imm)) |val_uimm31| |
| 28680 | 28694 | .u(val_uimm31) |
| ... | ... | @@ -28691,24 +28705,52 @@ const Temp = struct { |
| 28691 | 28705 | val_op, |
| 28692 | 28706 | ); |
| 28693 | 28707 | }, |
| 28694 | | .register => |val_reg| try dst.writeReg(opts.disp, val_ty, registerAlias( |
| 28708 | .eflags => |cc| try cg.asmSetccMemory( |
| 28709 | cc, |
| 28710 | try dst.tracking(cg).short.mem(cg, .{ |
| 28711 | .size = .byte, |
| 28712 | .disp = opts.disp, |
| 28713 | }), |
| 28714 | ), |
| 28715 | .register => |val_reg| try dst.writeRegs(opts.disp, val_ty, &.{registerAlias( |
| 28695 | 28716 | val_reg, |
| 28696 | 28717 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28697 | | ), cg), |
| 28698 | | inline .register_pair, .register_triple, .register_quadruple => |val_regs| { |
| 28699 | | var disp = opts.disp; |
| 28700 | | for (val_regs) |val_reg| { |
| 28701 | | try dst.writeReg(disp, val_ty, val_reg, cg); |
| 28702 | | disp += @divExact(val_reg.bitSize(), 8); |
| 28703 | | } |
| 28704 | | }, |
| 28718 | )}, cg), |
| 28719 | inline .register_pair, |
| 28720 | .register_triple, |
| 28721 | .register_quadruple, |
| 28722 | => |val_regs| try dst.writeRegs(opts.disp, val_ty, &val_regs, cg), |
| 28705 | 28723 | .register_offset => |val_reg_off| switch (val_reg_off.off) { |
| 28706 | | 0 => try dst.writeReg(opts.disp, val_ty, registerAlias( |
| 28724 | 0 => try dst.writeRegs(opts.disp, val_ty, &.{registerAlias( |
| 28707 | 28725 | val_reg_off.reg, |
| 28708 | 28726 | @intCast(val_ty.abiSize(cg.pt.zcu)), |
| 28709 | | ), cg), |
| 28727 | )}, cg), |
| 28710 | 28728 | else => continue :val_to_gpr, |
| 28711 | 28729 | }, |
| 28730 | .register_overflow => |val_reg_ov| { |
| 28731 | const ip = &cg.pt.zcu.intern_pool; |
| 28732 | const first_ty: Type = .fromInterned(first_ty: switch (ip.indexToKey(val_ty.toIntern())) { |
| 28733 | .tuple_type => |tuple_type| { |
| 28734 | const tuple_field_types = tuple_type.types.get(ip); |
| 28735 | assert(tuple_field_types.len == 2 and tuple_field_types[1] == .u1_type); |
| 28736 | break :first_ty tuple_field_types[0]; |
| 28737 | }, |
| 28738 | .opt_type => |opt_child| { |
| 28739 | assert(!val_ty.optionalReprIsPayload(cg.pt.zcu)); |
| 28740 | break :first_ty opt_child; |
| 28741 | }, |
| 28742 | else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }), |
| 28743 | }); |
| 28744 | const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu)); |
| 28745 | try dst.writeRegs(opts.disp, first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg); |
| 28746 | try cg.asmSetccMemory( |
| 28747 | val_reg_ov.eflags, |
| 28748 | try dst.tracking(cg).short.mem(cg, .{ |
| 28749 | .size = .byte, |
| 28750 | .disp = opts.disp + first_size, |
| 28751 | }), |
| 28752 | ); |
| 28753 | }, |
| 28712 | 28754 | .lea_frame, .lea_symbol => continue :val_to_gpr, |
| 28713 | 28755 | .memory, .indirect, .load_frame, .load_symbol => { |
| 28714 | 28756 | var dst_ptr = |
| ... | ... | @@ -28739,33 +28781,47 @@ const Temp = struct { |
| 28739 | 28781 | })); |
| 28740 | 28782 | } |
| 28741 | 28783 | |
| 28742 | | fn storeReg(ptr: *Temp, src_ty: Type, src_reg: Register, cg: *CodeGen) !void { |
| 28743 | | const src_rc = src_reg.class(); |
| 28744 | | const src_abi_size = src_ty.abiSize(cg.pt.zcu); |
| 28745 | | const strat = try cg.moveStrategy(src_ty, src_rc, false); |
| 28746 | | // hack around linker relocation bugs |
| 28747 | | switch (ptr.tracking(cg).short) { |
| 28748 | | else => {}, |
| 28749 | | .lea_symbol => |sym_off| if (src_rc != .general_purpose or sym_off.off != 0) |
| 28750 | | while (try ptr.toRegClass(false, .general_purpose, cg)) {}, |
| 28751 | | } |
| 28752 | | if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) { |
| 28753 | | try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{ |
| 28754 | | .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())), |
| 28755 | | }), src_reg); |
| 28756 | | } else { |
| 28757 | | const frame_alloc: FrameAlloc = .initSpill(src_ty, cg.pt.zcu); |
| 28758 | | const frame_index = try cg.allocFrameIndex(frame_alloc); |
| 28759 | | const frame_size: Memory.Size = .fromSize(frame_alloc.abi_size); |
| 28760 | | try strat.write(cg, .{ |
| 28761 | | .base = .{ .frame = frame_index }, |
| 28762 | | .mod = .{ .rm = .{ .size = frame_size } }, |
| 28763 | | }, src_reg); |
| 28764 | | var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } }); |
| 28765 | | var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size }); |
| 28766 | | try ptr.memcpy(&src_ptr, &len, cg); |
| 28767 | | try src_ptr.die(cg); |
| 28768 | | try len.die(cg); |
| 28784 | fn storeRegs(ptr: *Temp, src_ty: Type, src_regs: []const Register, cg: *CodeGen) !void { |
| 28785 | var part_disp: u31 = 0; |
| 28786 | var deferred_disp: u31 = 0; |
| 28787 | var src_abi_size: u32 = @intCast(src_ty.abiSize(cg.pt.zcu)); |
| 28788 | for (src_regs) |src_reg| { |
| 28789 | const src_rc = src_reg.class(); |
| 28790 | const part_bit_size = @min(8 * src_abi_size, src_reg.bitSize()); |
| 28791 | const part_size = @divExact(part_bit_size, 8); |
| 28792 | if (src_rc == .x87 or std.math.isPowerOfTwo(part_size)) { |
| 28793 | // hack around linker relocation bugs |
| 28794 | switch (ptr.tracking(cg).short) { |
| 28795 | else => {}, |
| 28796 | .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {}, |
| 28797 | } |
| 28798 | const strat = try cg.moveStrategy(src_ty, src_rc, false); |
| 28799 | try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{ |
| 28800 | .size = .fromBitSize(part_bit_size), |
| 28801 | .disp = part_disp, |
| 28802 | }), registerAlias(src_reg, part_size)); |
| 28803 | } else { |
| 28804 | const frame_size = std.math.ceilPowerOfTwoAssert(u32, part_size); |
| 28805 | const frame_index = try cg.allocFrameIndex(.init(.{ |
| 28806 | .size = frame_size, |
| 28807 | .alignment = .fromNonzeroByteUnits(frame_size), |
| 28808 | })); |
| 28809 | const strat = try cg.moveStrategy(src_ty, src_rc, true); |
| 28810 | try strat.write(cg, .{ |
| 28811 | .base = .{ .frame = frame_index }, |
| 28812 | .mod = .{ .rm = .{ .size = .fromSize(frame_size) } }, |
| 28813 | }, registerAlias(src_reg, frame_size)); |
| 28814 | try ptr.toOffset(deferred_disp, cg); |
| 28815 | deferred_disp = 0; |
| 28816 | var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } }); |
| 28817 | var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size }); |
| 28818 | try ptr.memcpy(&src_ptr, &len, cg); |
| 28819 | try src_ptr.die(cg); |
| 28820 | try len.die(cg); |
| 28821 | } |
| 28822 | part_disp += part_size; |
| 28823 | deferred_disp += part_size; |
| 28824 | src_abi_size -= part_size; |
| 28769 | 28825 | } |
| 28770 | 28826 | } |
| 28771 | 28827 | |
| ... | ... | @@ -28777,30 +28833,41 @@ const Temp = struct { |
| 28777 | 28833 | })); |
| 28778 | 28834 | } |
| 28779 | 28835 | |
| 28780 | | fn writeReg(dst: Temp, disp: i32, src_ty: Type, src_reg: Register, cg: *CodeGen) !void { |
| 28781 | | const src_rc = src_reg.class(); |
| 28782 | | const src_abi_size = src_ty.abiSize(cg.pt.zcu); |
| 28783 | | const strat = try cg.moveStrategy(src_ty, src_rc, false); |
| 28784 | | if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) { |
| 28785 | | try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{ |
| 28786 | | .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())), |
| 28787 | | .disp = disp, |
| 28788 | | }), src_reg); |
| 28789 | | } else { |
| 28790 | | const frame_alloc: FrameAlloc = .initSpill(src_ty, cg.pt.zcu); |
| 28791 | | const frame_index = try cg.allocFrameIndex(frame_alloc); |
| 28792 | | const frame_size: Memory.Size = .fromSize(frame_alloc.abi_size); |
| 28793 | | try strat.write(cg, .{ |
| 28794 | | .base = .{ .frame = frame_index }, |
| 28795 | | .mod = .{ .rm = .{ .size = frame_size } }, |
| 28796 | | }, src_reg); |
| 28797 | | var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address()); |
| 28798 | | var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } }); |
| 28799 | | var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size }); |
| 28800 | | try dst_ptr.memcpy(&src_ptr, &len, cg); |
| 28801 | | try dst_ptr.die(cg); |
| 28802 | | try src_ptr.die(cg); |
| 28803 | | try len.die(cg); |
| 28836 | fn writeRegs(dst: Temp, disp: i32, src_ty: Type, src_regs: []const Register, cg: *CodeGen) !void { |
| 28837 | var part_disp = disp; |
| 28838 | var src_abi_size: u32 = @intCast(src_ty.abiSize(cg.pt.zcu)); |
| 28839 | for (src_regs) |src_reg| { |
| 28840 | const src_rc = src_reg.class(); |
| 28841 | const part_bit_size = @min(8 * src_abi_size, src_reg.bitSize()); |
| 28842 | const part_size = @divExact(part_bit_size, 8); |
| 28843 | if (src_rc == .x87 or std.math.isPowerOfTwo(part_size)) { |
| 28844 | const strat = try cg.moveStrategy(src_ty, src_rc, false); |
| 28845 | try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{ |
| 28846 | .size = .fromBitSize(part_bit_size), |
| 28847 | .disp = part_disp, |
| 28848 | }), registerAlias(src_reg, part_size)); |
| 28849 | } else { |
| 28850 | const frame_size = std.math.ceilPowerOfTwoAssert(u32, part_size); |
| 28851 | const frame_index = try cg.allocFrameIndex(.init(.{ |
| 28852 | .size = frame_size, |
| 28853 | .alignment = .fromNonzeroByteUnits(frame_size), |
| 28854 | })); |
| 28855 | const strat = try cg.moveStrategy(src_ty, src_rc, true); |
| 28856 | try strat.write(cg, .{ |
| 28857 | .base = .{ .frame = frame_index }, |
| 28858 | .mod = .{ .rm = .{ .size = .fromSize(frame_size) } }, |
| 28859 | }, registerAlias(src_reg, frame_size)); |
| 28860 | var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address()); |
| 28861 | try dst_ptr.toOffset(part_disp, cg); |
| 28862 | var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } }); |
| 28863 | var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size }); |
| 28864 | try dst_ptr.memcpy(&src_ptr, &len, cg); |
| 28865 | try dst_ptr.die(cg); |
| 28866 | try src_ptr.die(cg); |
| 28867 | try len.die(cg); |
| 28868 | } |
| 28869 | part_disp += part_size; |
| 28870 | src_abi_size -= part_size; |
| 28804 | 28871 | } |
| 28805 | 28872 | } |
| 28806 | 28873 | |
| ... | ... | @@ -29123,8 +29190,8 @@ const Select = struct { |
| 29123 | 29190 | signed_int_vec: Memory.Size, |
| 29124 | 29191 | signed_int_or_full_vec: Memory.Size, |
| 29125 | 29192 | unsigned_int_vec: Memory.Size, |
| 29126 | | int_or_vec: Memory.Size, |
| 29127 | | exact_remainder_int_or_vec: struct { of: Memory.Size, is: Memory.Size }, |
| 29193 | size: Memory.Size, |
| 29194 | multiple_size: Memory.Size, |
| 29128 | 29195 | int: Memory.Size, |
| 29129 | 29196 | scalar_int: Memory.Size, |
| 29130 | 29197 | scalar_signed_int: Memory.Size, |
| ... | ... | @@ -29170,15 +29237,8 @@ const Select = struct { |
| 29170 | 29237 | } else false, |
| 29171 | 29238 | .unsigned_int_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and |
| 29172 | 29239 | if (intInfo(ty.childType(zcu), cg)) |int_info| int_info.signedness == .unsigned else false, |
| 29173 | | .int_or_vec => |size| if (intInfo(ty, cg)) |int_info| |
| 29174 | | size.bitSize(cg.target) >= int_info.bits |
| 29175 | | else |
| 29176 | | ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu), |
| 29177 | | .exact_remainder_int_or_vec => |of_is| if (intInfo(ty, cg)) |int_info| |
| 29178 | | of_is.is.bitSize(cg.target) == (int_info.bits - 1) % of_is.of.bitSize(cg.target) + 1 |
| 29179 | | else |
| 29180 | | ty.isVector(zcu) and ty.childType(zcu).toIntern() != .bool_type and |
| 29181 | | of_is.is.bitSize(cg.target) == (8 * ty.abiSize(zcu) - 1) % of_is.of.bitSize(cg.target) + 1, |
| 29240 | .size => |size| size.bitSize(cg.target) >= 8 * ty.abiSize(zcu), |
| 29241 | .multiple_size => |size| size.bitSize(cg.target) % 8 * ty.abiSize(zcu) == 0, |
| 29182 | 29242 | .int => |size| if (intInfo(ty, cg)) |int_info| size.bitSize(cg.target) >= int_info.bits else false, |
| 29183 | 29243 | .scalar_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info| |
| 29184 | 29244 | size.bitSize(cg.target) >= int_info.bits |