authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-14 17:56:25-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:47:30-05:00
log8c8dfb35f398407319764f0f8998de34c5247ed6
treea5c1fee87a9266319d8ceffa7717ca5c70b61f7b
parentc3d33440f0e68f114996dc74ec15e2b9514c4b3e

x86_64: fix crashes compiling the compiler and tests


8 files changed, 445 insertions(+), 389 deletions(-)

lib/std/Thread.zig+3-1
......@@ -372,9 +372,11 @@ pub const SpawnConfig = struct {
372372 // https://github.com/ziglang/zig/issues/157
373373
374374 /// Size in bytes of the Thread's stack
375 stack_size: usize = 16 * 1024 * 1024,
375 stack_size: usize = default_stack_size,
376376 /// The allocator to be used to allocate memory for the to-be-spawned thread
377377 allocator: ?std.mem.Allocator = null,
378
379 pub const default_stack_size = 16 * 1024 * 1024;
378380};
379381
380382pub const SpawnError = error{
lib/std/Thread/Pool.zig+5-1
......@@ -27,6 +27,7 @@ pub const Options = struct {
2727 allocator: std.mem.Allocator,
2828 n_jobs: ?usize = null,
2929 track_ids: bool = false,
30 stack_size: usize = std.Thread.SpawnConfig.default_stack_size,
3031};
3132
3233pub fn init(pool: *Pool, options: Options) !void {
......@@ -54,7 +55,10 @@ pub fn init(pool: *Pool, options: Options) !void {
5455 errdefer pool.join(spawned);
5556
5657 for (pool.threads) |*thread| {
57 thread.* = try std.Thread.spawn(.{}, worker, .{pool});
58 thread.* = try std.Thread.spawn(.{
59 .stack_size = options.stack_size,
60 .allocator = allocator,
61 }, worker, .{pool});
5862 spawned += 1;
5963 }
6064}
lib/std/crypto/aes/aesni.zig+1-1
......@@ -4,7 +4,7 @@ const mem = std.mem;
44const debug = std.debug;
55
66const has_vaes = builtin.cpu.arch == .x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .vaes);
7const has_avx512f = builtin.cpu.arch == .x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f);
7const has_avx512f = builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f);
88
99/// A single AES block.
1010pub const Block = struct {
src/arch/x86_64/CodeGen.zig+389-329
......@@ -634,42 +634,14 @@ const InstTracking = struct {
634634 }
635635
636636 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 });
673645 }
674646
675647 fn trackSpill(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void {
......@@ -681,6 +653,15 @@ const InstTracking = struct {
681653 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {
682654 switch (self.long) {
683655 .none,
656 .load_frame,
657 .reserved_frame,
658 => switch (target.long) {
659 .none,
660 .load_frame,
661 .reserved_frame,
662 => {},
663 else => unreachable,
664 },
684665 .unreach,
685666 .undef,
686667 .immediate,
......@@ -695,15 +676,6 @@ const InstTracking = struct {
695676 .load_symbol,
696677 .lea_symbol,
697678 => 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 },
707679 .dead,
708680 .eflags,
709681 .register,
......@@ -754,10 +726,11 @@ const InstTracking = struct {
754726 tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });
755727 }
756728
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 {
758730 switch (self.short) {
759731 .dead => |die_generation| if (die_generation >= scope_generation) {
760732 self.reuseFrame();
733 try function.getValue(self.short, inst);
761734 tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });
762735 },
763736 else => {},
......@@ -767,6 +740,7 @@ const InstTracking = struct {
767740 fn die(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void {
768741 if (self.short == .dead) return;
769742 try function.freeValue(self.short);
743 if (self.long == .none) self.long = self.short;
770744 self.short = .{ .dead = function.scope_generation };
771745 tracking_log.debug("{} => {} (death)", .{ inst, self.* });
772746 }
......@@ -2359,7 +2333,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
23592333}
23602334
23612335fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2362 @setEvalBranchQuota(1_600);
2336 @setEvalBranchQuota(1_700);
23632337 const pt = cg.pt;
23642338 const zcu = pt.zcu;
23652339 const ip = &zcu.intern_pool;
......@@ -2520,7 +2494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
25202494 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
25212495 try ops[0].toSlicePtr(cg);
25222496 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 &.{ .{
25242498 .patterns = &.{
25252499 .{ .src = .{ .to_gpr, .simm32 } },
25262500 },
......@@ -2625,7 +2599,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
26252599 ops[1].tracking(cg),
26262600 }),
26272601 else => |e| return e,
2628 };
2602 } else { // hack around Sema OPV bugs
2603 res[0] = ops[0];
2604 }
26292605 for (ops) |op| for (res) |r| {
26302606 if (op.index == r.index) break;
26312607 } else try op.die(cg);
......@@ -2637,7 +2613,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
26372613 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
26382614 try ops[0].toSlicePtr(cg);
26392615 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 &.{ .{
26412617 .patterns = &.{
26422618 .{ .src = .{ .to_gpr, .simm32 } },
26432619 },
......@@ -2757,7 +2733,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27572733 ops[1].tracking(cg),
27582734 }),
27592735 else => |e| return e,
2760 };
2736 } else {
2737 // hack around Sema OPV bugs
2738 res[0] = ops[0];
2739 }
27612740 for (ops) |op| for (res) |r| {
27622741 if (op.index == r.index) break;
27632742 } else try op.die(cg);
......@@ -2799,79 +2778,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
27992778 })) {
28002779 else => unreachable,
28012780 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 } },
28752782 .patterns = &.{
28762783 .{ .src = .{ .mut_mem, .imm8 } },
28772784 .{ .src = .{ .imm8, .mut_mem }, .commute = .{ 0, 1 } },
......@@ -2889,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
28892796 .{ ._, ._, mir_tag, .dst0b, .src1b, ._, ._ },
28902797 } },
28912798 }, .{
2892 .src_constraints = .{ .{ .int_or_vec = .word }, .{ .int_or_vec = .word } },
2799 .src_constraints = .{ .{ .size = .word }, .{ .size = .word } },
28932800 .patterns = &.{
28942801 .{ .src = .{ .mut_mem, .imm16 } },
28952802 .{ .src = .{ .imm16, .mut_mem }, .commute = .{ 0, 1 } },
......@@ -2907,7 +2814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
29072814 .{ ._, ._, mir_tag, .dst0w, .src1w, ._, ._ },
29082815 } },
29092816 }, .{
2910 .src_constraints = .{ .{ .int_or_vec = .dword }, .{ .int_or_vec = .dword } },
2817 .src_constraints = .{ .{ .size = .dword }, .{ .size = .dword } },
29112818 .patterns = &.{
29122819 .{ .src = .{ .mut_mem, .imm32 } },
29132820 .{ .src = .{ .imm32, .mut_mem }, .commute = .{ 0, 1 } },
......@@ -2926,7 +2833,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
29262833 } },
29272834 }, .{
29282835 .required_features = .{ .@"64bit", null, null, null },
2929 .src_constraints = .{ .{ .int_or_vec = .qword }, .{ .int_or_vec = .qword } },
2836 .src_constraints = .{ .{ .size = .qword }, .{ .size = .qword } },
29302837 .patterns = &.{
29312838 .{ .src = .{ .mut_mem, .simm32 } },
29322839 .{ .src = .{ .simm32, .mut_mem }, .commute = .{ 0, 1 } },
......@@ -2943,12 +2850,81 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
29432850 .each = .{ .once = &.{
29442851 .{ ._, ._, mir_tag, .dst0q, .src1q, ._, ._ },
29452852 } },
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 } },
29462901 }, .{
29472902 .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 } },
29512908 },
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 } },
29522928 .patterns = &.{
29532929 .{ .src = .{ .to_mem, .to_mem } },
29542930 },
......@@ -2972,10 +2948,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
29722948 } },
29732949 }, .{
29742950 .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 } },
29792952 .patterns = &.{
29802953 .{ .src = .{ .to_mem, .to_mem } },
29812954 },
......@@ -2999,10 +2972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
29992972 } },
30002973 }, .{
30012974 .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 } },
30062976 .patterns = &.{
30072977 .{ .src = .{ .to_mem, .to_mem } },
30082978 },
......@@ -3026,10 +2996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
30262996 } },
30272997 }, .{
30282998 .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 } },
30333000 .patterns = &.{
30343001 .{ .src = .{ .to_mem, .to_mem } },
30353002 },
......@@ -3053,10 +3020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
30533020 } },
30543021 }, .{
30553022 .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 } },
30603024 .patterns = &.{
30613025 .{ .src = .{ .to_mem, .to_mem } },
30623026 },
......@@ -3080,10 +3044,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
30803044 } },
30813045 }, .{
30823046 .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 } },
30873048 .patterns = &.{
30883049 .{ .src = .{ .to_mem, .to_mem } },
30893050 },
......@@ -3106,10 +3067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
31063067 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
31073068 } },
31083069 }, .{
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 } },
31133071 .patterns = &.{
31143072 .{ .src = .{ .to_mem, .to_mem } },
31153073 },
......@@ -6983,7 +6941,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
69836941 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
69846942 const extra = cg.air.extraData(Air.VectorCmp, ty_pl.payload).data;
69856943 switch (extra.compareOperator()) {
6986 .eq, .neq => {},
6944 .eq, .neq => if (cg.typeOf(extra.lhs).scalarType(zcu).isRuntimeFloat())
6945 break :fallback try cg.airCmpVector(inst),
69876946 else => break :fallback try cg.airCmpVector(inst),
69886947 }
69896948 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 {
97639722 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(extra.field_index, zcu)),
97649723 .@"packed" => break :fallback try cg.airStructFieldVal(inst),
97659724 };
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);
97769733 },
97779734 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {
97789735 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
97799736 const union_ty = cg.typeOf(bin_op.lhs).childType(zcu);
9780 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
97819737 const union_layout = union_ty.unionGetLayout(zcu);
9738 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
97829739 // hack around Sema OPV bugs
97839740 if (union_layout.tag_size > 0) try ops[0].store(&ops[1], .{
97849741 .disp = @intCast(union_layout.tagOffset()),
......@@ -9834,11 +9791,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
98349791 .ptr_elem_val => try cg.airPtrElemVal(inst),
98359792 } else {
98369793 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
9794 const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu);
98379795 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
98389796 try ops[0].toSlicePtr(cg);
98399797 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 &.{ .{
98429799 .dst_constraints = .{.{ .int = .byte }},
98439800 .patterns = &.{
98449801 .{ .src = .{ .to_gpr, .simm32 } },
......@@ -9912,51 +9869,51 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
99129869 .{ ._, ._, .mov, .dst0q, .leasi(.qword, .src0, .@"8", .src1), ._, ._ },
99139870 } },
99149871 } }) 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, .{
99489888 .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 } },
99549890 });
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);
99579911 },
99589912 else => |e| return e,
9959 };
9913 } else {
9914 // hack around Sema OPV bugs
9915 res[0] = try cg.tempInit(res_ty, .none);
9916 }
99609917 for (ops) |op| for (res) |r| {
99619918 if (op.index == r.index) break;
99629919 } else try op.die(cg);
......@@ -10499,7 +10456,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
1049910456 if (opts.resurrect) for (
1050010457 self.inst_tracking.keys()[Temp.Index.max..state.inst_tracking_len],
1050110458 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);
1050310460 for (deaths) |death| try self.processDeath(death);
1050410461
1050510462 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).array.len]RegisterLock;
......@@ -10879,7 +10836,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
1087910836 const dst_ty = self.typeOfIndex(inst);
1088010837
1088110838 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));
1088310841
1088410842 const src_int_info = src_ty.intInfo(zcu);
1088510843 const dst_int_info = dst_ty.intInfo(zcu);
......@@ -10890,7 +10848,6 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
1089010848
1089110849 const src_mcv = try self.resolveInst(ty_op.operand);
1089210850 if (dst_ty.isVector(zcu)) {
10893 const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu));
1089410851 const max_abi_size = @max(dst_abi_size, src_abi_size);
1089510852 if (max_abi_size > self.vectorSize(.int)) break :result null;
1089610853 const has_avx = self.hasFeature(.avx);
......@@ -11060,7 +11017,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
1106011017 else => src_int_info.bits,
1106111018 };
1106211019
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
1106411022 std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
1106511023 std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and
1106611024 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 {
1107911037 break :result .{ .register = registerAlias(dst_mcv.getReg().?, dst_abi_size) };
1108011038 }
1108111039
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);
1108411042
1108511043 const high_mcv: MCValue = if (dst_mcv.isBase())
1108611044 dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()
......@@ -12067,6 +12025,7 @@ fn genSetFrameTruncatedOverflowCompare(
1206712025 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1206812026
1206912027 const ty = tuple_ty.fieldType(0, zcu);
12028 const ty_size = ty.abiSize(zcu);
1207012029 const int_info = ty.intInfo(zcu);
1207112030
1207212031 const hi_bits = (int_info.bits - 1) % 64 + 1;
......@@ -12100,6 +12059,13 @@ fn genSetFrameTruncatedOverflowCompare(
1210012059 try self.asmSetccRegister(.ne, eq_reg.to8());
1210112060 try self.genBinOpMir(.{ ._, .@"or" }, .u8, .{ .register = overflow_reg }, .{ .register = eq_reg });
1210212061 }
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 );
1210312069
1210412070 const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));
1210512071 if (hi_limb_off > 0) try self.genSetMem(
......@@ -12116,13 +12082,20 @@ fn genSetFrameTruncatedOverflowCompare(
1211612082 .{ .register = scratch_reg },
1211712083 .{},
1211812084 );
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 }
1212612099}
1212712100
1212812101fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
......@@ -13581,9 +13554,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
1358113554 .{ ._, .bt },
1358213555 .{
1358313556 .base = .{ .frame = frame_index },
13584 .mod = .{ .rm = .{ .size = .qword } },
13557 .mod = .{ .rm = .{
13558 .size = .qword,
13559 .disp = @intCast(index_imm / 64 * 8),
13560 } },
1358513561 },
13586 .u(index_imm),
13562 .u(index_imm % 64),
1358713563 ),
1358813564 else => try self.asmMemoryRegister(
1358913565 .{ ._, .bt },
......@@ -13603,8 +13579,11 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
1360313579 .load_frame => switch (index_mcv) {
1360413580 .immediate => |index_imm| try self.asmMemoryImmediate(
1360513581 .{ ._, .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),
1360813587 ),
1360913588 else => try self.asmMemoryRegister(
1361013589 .{ ._, .bt },
......@@ -13622,9 +13601,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
1362213601 .base = .{
1362313602 .reg = try self.copyToTmpRegister(.usize, array_mat_mcv.address()),
1362413603 },
13625 .mod = .{ .rm = .{ .size = .qword } },
13604 .mod = .{ .rm = .{
13605 .size = .qword,
13606 .disp = @intCast(index_imm / 64 * 8),
13607 } },
1362613608 },
13627 .u(index_imm),
13609 .u(index_imm % 64),
1362813610 ),
1362913611 else => try self.asmMemoryRegister(
1363013612 .{ ._, .bt },
......@@ -14451,13 +14433,18 @@ fn genByteSwap(
1445114433 return src_mcv;
1445214434 },
1445314435 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 },
1445514442 .register_pair => |src_regs| if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
1445614443 for (src_regs) |src_reg| try self.asmRegister(.{ ._, .bswap }, src_reg.to64());
1445714444 return .{ .register_pair = .{ src_regs[1], src_regs[0] } };
14458 },
14459 else => {},
14460 }
14445 } else src_mcv,
14446 else => src_mcv,
14447 };
1446114448
1446214449 const dst_regs =
1446314450 try self.register_manager.allocRegs(2, .{ inst, inst }, abi.RegisterClass.gp);
......@@ -14465,18 +14452,18 @@ fn genByteSwap(
1446514452 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
1446614453
1446714454 for (dst_regs, 0..) |dst_reg, limb_index| {
14468 if (src_mcv.isBase()) {
14455 if (mat_src_mcv.isBase()) {
1446914456 try self.asmRegisterMemory(
1447014457 .{ ._, if (has_movbe) .movbe else .mov },
1447114458 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 }),
1447314460 );
1447414461 if (!has_movbe) try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());
1447514462 } else {
1447614463 try self.asmRegisterRegister(
1447714464 .{ ._, .mov },
1447814465 dst_reg.to64(),
14479 src_mcv.register_pair[limb_index].to64(),
14466 mat_src_mcv.register_pair[limb_index].to64(),
1448014467 );
1448114468 try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());
1448214469 }
......@@ -15680,6 +15667,15 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
1568015667 const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg);
1568115668 defer self.register_manager.unlockReg(ptr_lock);
1568215669
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
1568315679 var limb_i: u16 = 0;
1568415680 while (limb_i * limb_abi_bits < src_bit_off + src_bit_size) : (limb_i += 1) {
1568515681 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)
1571215708 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
1571315709 defer self.register_manager.unlockReg(tmp_lock);
1571415710
15715 try self.genSetReg(tmp_reg, limb_ty, src_mcv, .{});
15711 try self.genSetReg(tmp_reg, limb_ty, mat_src_mcv, .{});
1571615712 switch (limb_i) {
1571715713 0 => try self.genShiftBinOpMir(
1571815714 .{ ._l, .sh },
......@@ -15743,8 +15739,8 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
1574315739 defer self.register_manager.unlockReg(tmp_lock);
1574415740
1574515741 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(),
1574815744 }, .{});
1574915745 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });
1575015746 try self.asmMemoryRegister(
......@@ -17228,7 +17224,7 @@ fn genMulDivBinOp(
1722817224 dst_mcv.address(),
1722917225 lhs_mcv.address(),
1723017226 rhs_mcv.address(),
17231 .{ .immediate = src_info.bits },
17227 .{ .immediate = 8 * src_abi_size },
1723217228 }, .{});
1723317229 return dst_mcv;
1723417230 },
......@@ -17246,7 +17242,8 @@ fn genMulDivBinOp(
1724617242 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
1724717243 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
1724817244
17249 const signedness = ty.intInfo(zcu).signedness;
17245 const int_info = ty.intInfo(zcu);
17246 const signedness = int_info.signedness;
1725017247 switch (tag) {
1725117248 .mul,
1725217249 .mul_wrap,
......@@ -17279,6 +17276,15 @@ fn genMulDivBinOp(
1727917276 },
1728017277 }, ty, lhs_mcv, rhs_mcv);
1728117278
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
1728217288 if (dst_abi_size <= 8) return .{ .register = registerAlias(switch (tag) {
1728317289 .mul, .mul_wrap, .div_trunc, .div_exact => .rax,
1728417290 .rem => .rdx,
......@@ -21954,8 +21960,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
2195421960 break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(.usize, ptr_mcv) } };
2195521961 };
2195621962 };
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);
2195921966 };
2196021967 if (!std.mem.eql(u8, name, "_"))
2196121968 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
2288122888
2288222889 try self.asmRegisterRegister(.{ ._q, .mov }, dst_regs[0].to64(), src_reg.to128());
2288322890 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());
2288522892 }
2288622893 return;
2288722894 } else unreachable,
......@@ -23831,10 +23838,12 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {
2383123838 const dst_rc = self.regSetForType(dst_ty);
2383223839 const src_rc = self.regSetForType(src_ty);
2383323840
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;
2383523842 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
2383623843
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
2383823847 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
2383923848 const dst_mcv = try self.allocRegOrMem(inst, true);
2384023849 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 {
2770227711 reg
2770327712 else
2770427713 unreachable,
27705 .x87 => if (size_bytes == 16)
27714 .x87 => if (size_bytes >= 10 and size_bytes <= 16)
2770627715 reg
2770727716 else
2770827717 unreachable,
......@@ -28574,23 +28583,19 @@ const Temp = struct {
2857428583 try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }),
2857528584 );
2857628585 },
28577 .register => |val_reg| try ptr.storeReg(val_ty, registerAlias(
28586 .register => |val_reg| try ptr.storeRegs(val_ty, &.{registerAlias(
2857828587 val_reg,
2857928588 @intCast(val_ty.abiSize(cg.pt.zcu)),
28580 ), cg),
28589 )}, cg),
2858128590 inline .register_pair,
2858228591 .register_triple,
2858328592 .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),
2858928594 .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(
2859128596 val_reg_off.reg,
2859228597 @intCast(val_ty.abiSize(cg.pt.zcu)),
28593 ), cg),
28598 )}, cg),
2859428599 else => continue :val_to_gpr,
2859528600 },
2859628601 .register_overflow => |val_reg_ov| {
......@@ -28608,7 +28613,7 @@ const Temp = struct {
2860828613 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
2860928614 });
2861028615 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);
2861228617 try ptr.toOffset(first_size, cg);
2861328618 try cg.asmSetccMemory(
2861428619 val_reg_ov.eflags,
......@@ -28675,6 +28680,15 @@ const Temp = struct {
2867528680 const val_mcv = val.tracking(cg).short;
2867628681 switch (val_mcv) {
2867728682 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 },
2867828692 .immediate => |val_imm| {
2867928693 const val_op: Immediate = if (std.math.cast(u31, val_imm)) |val_uimm31|
2868028694 .u(val_uimm31)
......@@ -28691,24 +28705,52 @@ const Temp = struct {
2869128705 val_op,
2869228706 );
2869328707 },
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(
2869528716 val_reg,
2869628717 @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),
2870528723 .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(
2870728725 val_reg_off.reg,
2870828726 @intCast(val_ty.abiSize(cg.pt.zcu)),
28709 ), cg),
28727 )}, cg),
2871028728 else => continue :val_to_gpr,
2871128729 },
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 },
2871228754 .lea_frame, .lea_symbol => continue :val_to_gpr,
2871328755 .memory, .indirect, .load_frame, .load_symbol => {
2871428756 var dst_ptr =
......@@ -28739,33 +28781,47 @@ const Temp = struct {
2873928781 }));
2874028782 }
2874128783
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;
2876928825 }
2877028826 }
2877128827
......@@ -28777,30 +28833,41 @@ const Temp = struct {
2877728833 }));
2877828834 }
2877928835
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;
2880428871 }
2880528872 }
2880628873
......@@ -29123,8 +29190,8 @@ const Select = struct {
2912329190 signed_int_vec: Memory.Size,
2912429191 signed_int_or_full_vec: Memory.Size,
2912529192 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,
2912829195 int: Memory.Size,
2912929196 scalar_int: Memory.Size,
2913029197 scalar_signed_int: Memory.Size,
......@@ -29170,15 +29237,8 @@ const Select = struct {
2917029237 } else false,
2917129238 .unsigned_int_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and
2917229239 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,
2918229242 .int => |size| if (intInfo(ty, cg)) |int_info| size.bitSize(cg.target) >= int_info.bits else false,
2918329243 .scalar_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info|
2918429244 size.bitSize(cg.target) >= int_info.bits
src/arch/x86_64/abi.zig+6-2
......@@ -540,8 +540,12 @@ pub fn getCAbiSseReturnRegs(cc: std.builtin.CallingConvention.Tag) []const Regis
540540}
541541
542542pub fn getCAbiLinkerScratchReg(cc: std.builtin.CallingConvention.Tag) Register {
543 const int_return_regs = getCAbiIntReturnRegs(cc);
544 return int_return_regs[int_return_regs.len - 1];
543 return switch (cc) {
544 .auto => zigcc.int_return_regs[zigcc.int_return_regs.len - 1],
545 .x86_64_sysv => SysV.c_abi_int_return_regs[0],
546 .x86_64_win => Win64.c_abi_int_return_regs[0],
547 else => unreachable,
548 };
545549}
546550
547551const gp_regs = [_]Register{
src/main.zig+8
......@@ -39,6 +39,11 @@ test {
3939 _ = Package;
4040}
4141
42const thread_stack_size = switch (builtin.zig_backend) {
43 else => std.Thread.SpawnConfig.default_stack_size,
44 .stage2_x86_64 => 32 << 20,
45};
46
4247pub const std_options: std.Options = .{
4348 .wasiCwd = wasi_cwd,
4449 .logFn = log,
......@@ -3320,6 +3325,7 @@ fn buildOutputType(
33203325 .allocator = gpa,
33213326 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
33223327 .track_ids = true,
3328 .stack_size = thread_stack_size,
33233329 });
33243330 defer thread_pool.deinit();
33253331
......@@ -5024,6 +5030,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
50245030 .allocator = gpa,
50255031 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
50265032 .track_ids = true,
5033 .stack_size = thread_stack_size,
50275034 });
50285035 defer thread_pool.deinit();
50295036
......@@ -5460,6 +5467,7 @@ fn jitCmd(
54605467 .allocator = gpa,
54615468 .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
54625469 .track_ids = true,
5470 .stack_size = thread_stack_size,
54635471 });
54645472 defer thread_pool.deinit();
54655473
src/register_manager.zig+23-55
......@@ -58,11 +58,6 @@ pub fn RegisterManager(
5858 return @alignCast(@fieldParentPtr("register_manager", self));
5959 }
6060
61 fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool {
62 const index = indexOfRegIntoTracked(reg) orelse return true;
63 return !register_class.isSet(index);
64 }
65
6661 fn markRegIndexAllocated(self: *Self, tracked_index: TrackedIndex) void {
6762 self.allocated_registers.set(tracked_index);
6863 }
......@@ -234,28 +229,20 @@ pub fn RegisterManager(
234229 ) ?[count]Register {
235230 comptime assert(count > 0 and count <= tracked_registers.len);
236231
237 var free_and_not_locked_registers = self.free_registers;
238 free_and_not_locked_registers.setIntersection(register_class);
239
240 var unlocked_registers = self.locked_registers;
241 unlocked_registers.toggleAll();
242
243 free_and_not_locked_registers.setIntersection(unlocked_registers);
244
245 if (free_and_not_locked_registers.count() < count) return null;
232 var free_and_unlocked_registers = self.locked_registers;
233 free_and_unlocked_registers.toggleAll();
234 free_and_unlocked_registers.setIntersection(self.free_registers);
235 free_and_unlocked_registers.setIntersection(register_class);
246236
247237 var regs: [count]Register = undefined;
248238 var i: usize = 0;
249 for (tracked_registers) |reg| {
250 if (i >= count) break;
251 if (excludeRegister(reg, register_class)) continue;
252 if (self.isRegLocked(reg)) continue;
253 if (!self.isRegFree(reg)) continue;
254
255 regs[i] = reg;
239 var it = free_and_unlocked_registers.iterator(.{});
240 while (it.next()) |reg_index| {
241 regs[i] = regAtTrackedIndex(@intCast(reg_index));
256242 i += 1;
243 if (i >= count) break;
257244 }
258 assert(i == count);
245 if (i < count) return null;
259246
260247 for (regs, insts) |reg, inst| {
261248 log.debug("tryAllocReg {} for inst {?}", .{ reg, inst });
......@@ -290,46 +277,27 @@ pub fn RegisterManager(
290277 ) AllocationError![count]Register {
291278 comptime assert(count > 0 and count <= tracked_registers.len);
292279
293 var locked_registers = self.locked_registers;
294 locked_registers.setIntersection(register_class);
295
296 if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters;
297
298280 const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {
281 var unlocked_registers = self.locked_registers;
282 unlocked_registers.toggleAll();
283 unlocked_registers.setIntersection(register_class);
284
299285 // We'll take over the first count registers. Spill
300286 // the instructions that were previously there to a
301287 // stack allocations.
302288 var regs: [count]Register = undefined;
303289 var i: usize = 0;
304 for (tracked_registers) |reg| {
305 if (i >= count) break;
306 if (excludeRegister(reg, register_class)) break;
307 if (self.isRegLocked(reg)) continue;
308
309 log.debug("allocReg {} for inst {?}", .{ reg, insts[i] });
310 regs[i] = reg;
311 self.markRegAllocated(reg);
312 const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null
313 if (insts[i]) |inst| {
314 // Track the register
315 if (self.isRegFree(reg)) {
316 self.markRegUsed(reg);
317 } else {
318 const spilled_inst = self.registers[index];
319 try self.getFunction().spillInstruction(reg, spilled_inst);
320 }
321 self.registers[index] = inst;
322 } else {
323 // Don't track the register
324 if (!self.isRegFree(reg)) {
325 const spilled_inst = self.registers[index];
326 try self.getFunction().spillInstruction(reg, spilled_inst);
327 self.freeReg(reg);
328 }
329 }
330
290 var it = unlocked_registers.iterator(.{});
291 while (it.next()) |reg_index| {
292 const tracked_index: TrackedIndex = @intCast(reg_index);
293 if (!self.isRegIndexFree(tracked_index) and
294 self.registers[tracked_index].unwrap() == .target) continue;
295 try self.getRegIndex(tracked_index, insts[i]);
296 regs[i] = regAtTrackedIndex(tracked_index);
331297 i += 1;
298 if (i >= count) break;
332299 }
300 if (i < count) return error.OutOfRegisters;
333301
334302 break :blk regs;
335303 };
......@@ -351,7 +319,7 @@ pub fn RegisterManager(
351319 /// Spills the register if it is currently allocated. If a
352320 /// corresponding instruction is passed, will also track this
353321 /// register.
354 fn getRegIndex(
322 pub fn getRegIndex(
355323 self: *Self,
356324 tracked_index: TrackedIndex,
357325 inst: ?Air.Inst.Index,
test/behavior/x86_64/math.zig+10
......@@ -742,6 +742,16 @@ fn testBinary(comptime op: anytype) !void {
742742 0xb7935f5c2f3b1ae7a422c0a7c446884294b7d5370bada307d2fe5a4c4284a999,
743743 0x310e6e196ba4f143b8d285ca6addf7f3bb3344224aff221b27607a31e148be08,
744744 );
745 try testType(
746 u258,
747 0x186d5ddaab8cb8cb04e5b41e36f812e039d008baf49f12894c39e29a07796d800,
748 0x2072daba6ffad168826163eb136f6d28ca4360c8e7e5e41e29755e19e4753a4f5,
749 );
750 try testType(
751 u495,
752 0x6eaf4e252b3bf74b75bac59e0b43ca5326bad2a25b3fdb74a67ef132ac5e47d72eebc3316fb2351ee66c50dc5afb92a75cea9b0e35160652c7db39eeb158,
753 0x49fbed744a92b549d8c05bb3512c617d24dd824f3f69bdf3923bc326a75674b85f5b828d2566fab9c86f571d12c2a63c9164feb0d191d27905533d09622a,
754 );
745755 try testType(
746756 u512,
747757 0xe5b1fedca3c77db765e517aabd05ffc524a3a8aff1784bbf67c45b894447ede32b65b9940e78173c591e56e078932d465f235aece7ad47b7f229df7ba8f12295,