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 {...@@ -372,9 +372,11 @@ pub const SpawnConfig = struct {
372 // https://github.com/ziglang/zig/issues/157372 // https://github.com/ziglang/zig/issues/157
373373
374 /// Size in bytes of the Thread's stack374 /// Size in bytes of the Thread's stack
375 stack_size: usize = 16 * 1024 * 1024,375 stack_size: usize = default_stack_size,
376 /// The allocator to be used to allocate memory for the to-be-spawned thread376 /// The allocator to be used to allocate memory for the to-be-spawned thread
377 allocator: ?std.mem.Allocator = null,377 allocator: ?std.mem.Allocator = null,
378
379 pub const default_stack_size = 16 * 1024 * 1024;
378};380};
379381
380pub const SpawnError = error{382pub const SpawnError = error{
lib/std/Thread/Pool.zig+5-1
...@@ -27,6 +27,7 @@ pub const Options = struct {...@@ -27,6 +27,7 @@ pub const Options = struct {
27 allocator: std.mem.Allocator,27 allocator: std.mem.Allocator,
28 n_jobs: ?usize = null,28 n_jobs: ?usize = null,
29 track_ids: bool = false,29 track_ids: bool = false,
30 stack_size: usize = std.Thread.SpawnConfig.default_stack_size,
30};31};
3132
32pub fn init(pool: *Pool, options: Options) !void {33pub fn init(pool: *Pool, options: Options) !void {
...@@ -54,7 +55,10 @@ pub fn init(pool: *Pool, options: Options) !void {...@@ -54,7 +55,10 @@ pub fn init(pool: *Pool, options: Options) !void {
54 errdefer pool.join(spawned);55 errdefer pool.join(spawned);
5556
56 for (pool.threads) |*thread| {57 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});
58 spawned += 1;62 spawned += 1;
59 }63 }
60}64}
lib/std/crypto/aes/aesni.zig+1-1
...@@ -4,7 +4,7 @@ const mem = std.mem;...@@ -4,7 +4,7 @@ const mem = std.mem;
4const debug = std.debug;4const debug = std.debug;
55
6const has_vaes = builtin.cpu.arch == .x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .vaes);6const 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
9/// A single AES block.9/// A single AES block.
10pub const Block = struct {10pub const Block = struct {
src/arch/x86_64/CodeGen.zig+389-329
...@@ -634,42 +634,14 @@ const InstTracking = struct {...@@ -634,42 +634,14 @@ const InstTracking = struct {
634 }634 }
635635
636 fn reuseFrame(self: *InstTracking) void {636 fn reuseFrame(self: *InstTracking) void {
637 switch (self.long) {637 self.* = .init(switch (self.long) {
638 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },638 .none => switch (self.short) {
639 else => {},639 .dead => .none,
640 }640 else => |short| short,
641 self.short = switch (self.long) {641 },
642 .none,642 .reserved_frame => |index| .{ .load_frame = .{ .index = index } },
643 .unreach,643 else => |long| long,
644 .undef,644 });
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 };
673 }645 }
674646
675 fn trackSpill(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void {647 fn trackSpill(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void {
...@@ -681,6 +653,15 @@ const InstTracking = struct {...@@ -681,6 +653,15 @@ const InstTracking = struct {
681 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {653 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {
682 switch (self.long) {654 switch (self.long) {
683 .none,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 .unreach,665 .unreach,
685 .undef,666 .undef,
686 .immediate,667 .immediate,
...@@ -695,15 +676,6 @@ const InstTracking = struct {...@@ -695,15 +676,6 @@ const InstTracking = struct {
695 .load_symbol,676 .load_symbol,
696 .lea_symbol,677 .lea_symbol,
697 => assert(std.meta.eql(self.long, target.long)),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 .dead,679 .dead,
708 .eflags,680 .eflags,
709 .register,681 .register,
...@@ -754,10 +726,11 @@ const InstTracking = struct {...@@ -754,10 +726,11 @@ const InstTracking = struct {
754 tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });726 tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });
755 }727 }
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 {
758 switch (self.short) {730 switch (self.short) {
759 .dead => |die_generation| if (die_generation >= scope_generation) {731 .dead => |die_generation| if (die_generation >= scope_generation) {
760 self.reuseFrame();732 self.reuseFrame();
733 try function.getValue(self.short, inst);
761 tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });734 tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });
762 },735 },
763 else => {},736 else => {},
...@@ -767,6 +740,7 @@ const InstTracking = struct {...@@ -767,6 +740,7 @@ const InstTracking = struct {
767 fn die(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void {740 fn die(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void {
768 if (self.short == .dead) return;741 if (self.short == .dead) return;
769 try function.freeValue(self.short);742 try function.freeValue(self.short);
743 if (self.long == .none) self.long = self.short;
770 self.short = .{ .dead = function.scope_generation };744 self.short = .{ .dead = function.scope_generation };
771 tracking_log.debug("{} => {} (death)", .{ inst, self.* });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,7 +2333,7 @@ fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2359}2333}
23602334
2361fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {2335fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2362 @setEvalBranchQuota(1_600);2336 @setEvalBranchQuota(1_700);
2363 const pt = cg.pt;2337 const pt = cg.pt;
2364 const zcu = pt.zcu;2338 const zcu = pt.zcu;
2365 const ip = &zcu.intern_pool;2339 const ip = &zcu.intern_pool;
...@@ -2520,7 +2494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2520,7 +2494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2520 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });2494 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2521 try ops[0].toSlicePtr(cg);2495 try ops[0].toSlicePtr(cg);
2522 var res: [1]Temp = undefined;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 .patterns = &.{2498 .patterns = &.{
2525 .{ .src = .{ .to_gpr, .simm32 } },2499 .{ .src = .{ .to_gpr, .simm32 } },
2526 },2500 },
...@@ -2625,7 +2599,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2625,7 +2599,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2625 ops[1].tracking(cg),2599 ops[1].tracking(cg),
2626 }),2600 }),
2627 else => |e| return e,2601 else => |e| return e,
2628 };2602 } else { // hack around Sema OPV bugs
2603 res[0] = ops[0];
2604 }
2629 for (ops) |op| for (res) |r| {2605 for (ops) |op| for (res) |r| {
2630 if (op.index == r.index) break;2606 if (op.index == r.index) break;
2631 } else try op.die(cg);2607 } else try op.die(cg);
...@@ -2637,7 +2613,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2637,7 +2613,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2637 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });2613 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2638 try ops[0].toSlicePtr(cg);2614 try ops[0].toSlicePtr(cg);
2639 var res: [1]Temp = undefined;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 .patterns = &.{2617 .patterns = &.{
2642 .{ .src = .{ .to_gpr, .simm32 } },2618 .{ .src = .{ .to_gpr, .simm32 } },
2643 },2619 },
...@@ -2757,7 +2733,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2757,7 +2733,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2757 ops[1].tracking(cg),2733 ops[1].tracking(cg),
2758 }),2734 }),
2759 else => |e| return e,2735 else => |e| return e,
2760 };2736 } else {
2737 // hack around Sema OPV bugs
2738 res[0] = ops[0];
2739 }
2761 for (ops) |op| for (res) |r| {2740 for (ops) |op| for (res) |r| {
2762 if (op.index == r.index) break;2741 if (op.index == r.index) break;
2763 } else try op.die(cg);2742 } else try op.die(cg);
...@@ -2799,79 +2778,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2799,79 +2778,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2799 })) {2778 })) {
2800 else => unreachable,2779 else => unreachable,
2801 inline .@"and", .@"or", .xor => |mir_tag| comptime &.{ .{2780 inline .@"and", .@"or", .xor => |mir_tag| comptime &.{ .{
2802 .required_features = .{ .avx2, null, null, null },2781 .src_constraints = .{ .{ .size = .byte }, .{ .size = .byte } },
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 } },
2875 .patterns = &.{2782 .patterns = &.{
2876 .{ .src = .{ .mut_mem, .imm8 } },2783 .{ .src = .{ .mut_mem, .imm8 } },
2877 .{ .src = .{ .imm8, .mut_mem }, .commute = .{ 0, 1 } },2784 .{ .src = .{ .imm8, .mut_mem }, .commute = .{ 0, 1 } },
...@@ -2889,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2889,7 +2796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2889 .{ ._, ._, mir_tag, .dst0b, .src1b, ._, ._ },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 .patterns = &.{2800 .patterns = &.{
2894 .{ .src = .{ .mut_mem, .imm16 } },2801 .{ .src = .{ .mut_mem, .imm16 } },
2895 .{ .src = .{ .imm16, .mut_mem }, .commute = .{ 0, 1 } },2802 .{ .src = .{ .imm16, .mut_mem }, .commute = .{ 0, 1 } },
...@@ -2907,7 +2814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2907,7 +2814,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2907 .{ ._, ._, mir_tag, .dst0w, .src1w, ._, ._ },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 .patterns = &.{2818 .patterns = &.{
2912 .{ .src = .{ .mut_mem, .imm32 } },2819 .{ .src = .{ .mut_mem, .imm32 } },
2913 .{ .src = .{ .imm32, .mut_mem }, .commute = .{ 0, 1 } },2820 .{ .src = .{ .imm32, .mut_mem }, .commute = .{ 0, 1 } },
...@@ -2926,7 +2833,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2926,7 +2833,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2926 } },2833 } },
2927 }, .{2834 }, .{
2928 .required_features = .{ .@"64bit", null, null, null },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 .patterns = &.{2837 .patterns = &.{
2931 .{ .src = .{ .mut_mem, .simm32 } },2838 .{ .src = .{ .mut_mem, .simm32 } },
2932 .{ .src = .{ .simm32, .mut_mem }, .commute = .{ 0, 1 } },2839 .{ .src = .{ .simm32, .mut_mem }, .commute = .{ 0, 1 } },
...@@ -2943,12 +2850,81 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2943,12 +2850,81 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2943 .each = .{ .once = &.{2850 .each = .{ .once = &.{
2944 .{ ._, ._, mir_tag, .dst0q, .src1q, ._, ._ },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 .required_features = .{ .avx2, null, null, null },2902 .required_features = .{ .avx2, null, null, null },
2948 .src_constraints = .{2903 .src_constraints = .{ .{ .size = .yword }, .{ .size = .yword } },
2949 .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } },2904 .patterns = &.{
2950 .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } },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 .patterns = &.{2928 .patterns = &.{
2953 .{ .src = .{ .to_mem, .to_mem } },2929 .{ .src = .{ .to_mem, .to_mem } },
2954 },2930 },
...@@ -2972,10 +2948,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2972,10 +2948,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2972 } },2948 } },
2973 }, .{2949 }, .{
2974 .required_features = .{ .avx, null, null, null },2950 .required_features = .{ .avx, null, null, null },
2975 .src_constraints = .{2951 .src_constraints = .{ .{ .multiple_size = .yword }, .{ .multiple_size = .yword } },
2976 .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } },
2977 .{ .exact_remainder_int_or_vec = .{ .of = .yword, .is = .yword } },
2978 },
2979 .patterns = &.{2952 .patterns = &.{
2980 .{ .src = .{ .to_mem, .to_mem } },2953 .{ .src = .{ .to_mem, .to_mem } },
2981 },2954 },
...@@ -2999,10 +2972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2999,10 +2972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2999 } },2972 } },
3000 }, .{2973 }, .{
3001 .required_features = .{ .avx, null, null, null },2974 .required_features = .{ .avx, null, null, null },
3002 .src_constraints = .{2975 .src_constraints = .{ .{ .multiple_size = .xword }, .{ .multiple_size = .xword } },
3003 .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } },
3004 .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } },
3005 },
3006 .patterns = &.{2976 .patterns = &.{
3007 .{ .src = .{ .to_mem, .to_mem } },2977 .{ .src = .{ .to_mem, .to_mem } },
3008 },2978 },
...@@ -3026,10 +2996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3026,10 +2996,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3026 } },2996 } },
3027 }, .{2997 }, .{
3028 .required_features = .{ .sse2, null, null, null },2998 .required_features = .{ .sse2, null, null, null },
3029 .src_constraints = .{2999 .src_constraints = .{ .{ .multiple_size = .xword }, .{ .multiple_size = .xword } },
3030 .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } },
3031 .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } },
3032 },
3033 .patterns = &.{3000 .patterns = &.{
3034 .{ .src = .{ .to_mem, .to_mem } },3001 .{ .src = .{ .to_mem, .to_mem } },
3035 },3002 },
...@@ -3053,10 +3020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3053,10 +3020,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3053 } },3020 } },
3054 }, .{3021 }, .{
3055 .required_features = .{ .sse, null, null, null },3022 .required_features = .{ .sse, null, null, null },
3056 .src_constraints = .{3023 .src_constraints = .{ .{ .multiple_size = .xword }, .{ .multiple_size = .xword } },
3057 .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } },
3058 .{ .exact_remainder_int_or_vec = .{ .of = .xword, .is = .xword } },
3059 },
3060 .patterns = &.{3024 .patterns = &.{
3061 .{ .src = .{ .to_mem, .to_mem } },3025 .{ .src = .{ .to_mem, .to_mem } },
3062 },3026 },
...@@ -3080,10 +3044,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3080,10 +3044,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3080 } },3044 } },
3081 }, .{3045 }, .{
3082 .required_features = .{ .mmx, null, null, null },3046 .required_features = .{ .mmx, null, null, null },
3083 .src_constraints = .{3047 .src_constraints = .{ .{ .multiple_size = .qword }, .{ .multiple_size = .qword } },
3084 .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } },
3085 .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } },
3086 },
3087 .patterns = &.{3048 .patterns = &.{
3088 .{ .src = .{ .to_mem, .to_mem } },3049 .{ .src = .{ .to_mem, .to_mem } },
3089 },3050 },
...@@ -3106,10 +3067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -3106,10 +3067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
3106 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },3067 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
3107 } },3068 } },
3108 }, .{3069 }, .{
3109 .src_constraints = .{3070 .src_constraints = .{ .{ .multiple_size = .qword }, .{ .multiple_size = .qword } },
3110 .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } },
3111 .{ .exact_remainder_int_or_vec = .{ .of = .qword, .is = .qword } },
3112 },
3113 .patterns = &.{3071 .patterns = &.{
3114 .{ .src = .{ .to_mem, .to_mem } },3072 .{ .src = .{ .to_mem, .to_mem } },
3115 },3073 },
...@@ -6983,7 +6941,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -6983,7 +6941,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
6983 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;6941 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
6984 const extra = cg.air.extraData(Air.VectorCmp, ty_pl.payload).data;6942 const extra = cg.air.extraData(Air.VectorCmp, ty_pl.payload).data;
6985 switch (extra.compareOperator()) {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 else => break :fallback try cg.airCmpVector(inst),6946 else => break :fallback try cg.airCmpVector(inst),
6988 }6947 }
6989 var ops = try cg.tempsFromOperands(inst, .{ extra.lhs, extra.rhs });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,22 +9722,20 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9763 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(extra.field_index, zcu)),9722 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(extra.field_index, zcu)),
9764 .@"packed" => break :fallback try cg.airStructFieldVal(inst),9723 .@"packed" => break :fallback try cg.airStructFieldVal(inst),
9765 };9724 };
9766 if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {9725 var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand});
9767 var ops = try cg.tempsFromOperands(inst, .{extra.struct_operand});9726 // hack around Sema OPV bugs
9768 var res = try ops[0].read(field_ty, .{ .disp = field_off }, cg);9727 var res = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu))
9769 for (ops) |op| if (op.index != res.index) try op.die(cg);9728 try ops[0].read(field_ty, .{ .disp = field_off }, cg)
9770 try res.moveTo(inst, cg);9729 else
9771 } else {9730 try cg.tempInit(field_ty, .none);
9772 // hack around Sema OPV bugs9731 for (ops) |op| if (op.index != res.index) try op.die(cg);
9773 const res = try cg.tempInit(field_ty, .none);9732 try res.moveTo(inst, cg);
9774 try res.moveTo(inst, cg);
9775 }
9776 },9733 },
9777 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {9734 .set_union_tag => if (use_old) try cg.airSetUnionTag(inst) else {
9778 const bin_op = air_datas[@intFromEnum(inst)].bin_op;9735 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
9779 const union_ty = cg.typeOf(bin_op.lhs).childType(zcu);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 const union_layout = union_ty.unionGetLayout(zcu);9737 const union_layout = union_ty.unionGetLayout(zcu);
9738 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9782 // hack around Sema OPV bugs9739 // hack around Sema OPV bugs
9783 if (union_layout.tag_size > 0) try ops[0].store(&ops[1], .{9740 if (union_layout.tag_size > 0) try ops[0].store(&ops[1], .{
9784 .disp = @intCast(union_layout.tagOffset()),9741 .disp = @intCast(union_layout.tagOffset()),
...@@ -9834,11 +9791,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9834,11 +9791,11 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9834 .ptr_elem_val => try cg.airPtrElemVal(inst),9791 .ptr_elem_val => try cg.airPtrElemVal(inst),
9835 } else {9792 } else {
9836 const bin_op = air_datas[@intFromEnum(inst)].bin_op;9793 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
9794 const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu);
9837 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });9795 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
9838 try ops[0].toSlicePtr(cg);9796 try ops[0].toSlicePtr(cg);
9839 var res: [1]Temp = undefined;9797 var res: [1]Temp = undefined;
9840 const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu);9798 if (res_ty.hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{
9841 cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{
9842 .dst_constraints = .{.{ .int = .byte }},9799 .dst_constraints = .{.{ .int = .byte }},
9843 .patterns = &.{9800 .patterns = &.{
9844 .{ .src = .{ .to_gpr, .simm32 } },9801 .{ .src = .{ .to_gpr, .simm32 } },
...@@ -9912,51 +9869,51 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -9912,51 +9869,51 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
9912 .{ ._, ._, .mov, .dst0q, .leasi(.qword, .src0, .@"8", .src1), ._, ._ },9869 .{ ._, ._, .mov, .dst0q, .leasi(.qword, .src0, .@"8", .src1), ._, ._ },
9913 } },9870 } },
9914 } }) catch |err| switch (err) {9871 } }) catch |err| switch (err) {
9915 error.SelectFailed => switch (res_ty.abiSize(zcu)) {9872 error.SelectFailed => {
9916 // hack around Sema OPV bugs9873 const elem_size = res_ty.abiSize(zcu);
9917 0 => res[0] = try cg.tempInit(res_ty, .none),9874 while (true) for (&ops) |*op| {
9918 else => |elem_size| {9875 if (try op.toRegClass(true, .general_purpose, cg)) break;
9919 while (true) for (&ops) |*op| {9876 } else break;
9920 if (try op.toRegClass(true, .general_purpose, cg)) break;9877 const lhs_reg = ops[0].unwrap(cg).temp.tracking(cg).short.register.to64();
9921 } else break;9878 const rhs_reg = ops[1].unwrap(cg).temp.tracking(cg).short.register.to64();
9922 const lhs_reg = ops[0].unwrap(cg).temp.tracking(cg).short.register.to64();9879 if (!std.math.isPowerOfTwo(elem_size)) {
9923 const rhs_reg = ops[1].unwrap(cg).temp.tracking(cg).short.register.to64();9880 try cg.spillEflagsIfOccupied();
9924 if (!std.math.isPowerOfTwo(elem_size)) {9881 try cg.asmRegisterRegisterImmediate(
9925 try cg.spillEflagsIfOccupied();9882 .{ .i_, .mul },
9926 try cg.asmRegisterRegisterImmediate(9883 rhs_reg,
9927 .{ .i_, .mul },9884 rhs_reg,
9928 rhs_reg,9885 .u(elem_size),
9929 rhs_reg,9886 );
9930 .u(elem_size),9887 try cg.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
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, .{
9948 .base = .{ .reg = lhs_reg },9888 .base = .{ .reg = lhs_reg },
9949 .mod = .{ .rm = .{9889 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
9950 .size = .qword,
9951 .index = rhs_reg,
9952 .scale = .fromFactor(@intCast(elem_size)),
9953 } },
9954 });9890 });
9955 res[0] = try ops[0].load(res_ty, .{}, cg);9891 } else if (elem_size > 8) {
9956 },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 else => |e| return e,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 for (ops) |op| for (res) |r| {9917 for (ops) |op| for (res) |r| {
9961 if (op.index == r.index) break;9918 if (op.index == r.index) break;
9962 } else try op.die(cg);9919 } else try op.die(cg);
...@@ -10499,7 +10456,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co...@@ -10499,7 +10456,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
10499 if (opts.resurrect) for (10456 if (opts.resurrect) for (
10500 self.inst_tracking.keys()[Temp.Index.max..state.inst_tracking_len],10457 self.inst_tracking.keys()[Temp.Index.max..state.inst_tracking_len],
10501 self.inst_tracking.values()[Temp.Index.max..state.inst_tracking_len],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 for (deaths) |death| try self.processDeath(death);10460 for (deaths) |death| try self.processDeath(death);
1050410461
10505 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).array.len]RegisterLock;10462 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).array.len]RegisterLock;
...@@ -10879,7 +10836,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -10879,7 +10836,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
10879 const dst_ty = self.typeOfIndex(inst);10836 const dst_ty = self.typeOfIndex(inst);
1088010837
10881 const result = @as(?MCValue, result: {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));
1088310841
10884 const src_int_info = src_ty.intInfo(zcu);10842 const src_int_info = src_ty.intInfo(zcu);
10885 const dst_int_info = dst_ty.intInfo(zcu);10843 const dst_int_info = dst_ty.intInfo(zcu);
...@@ -10890,7 +10848,6 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -10890,7 +10848,6 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
1089010848
10891 const src_mcv = try self.resolveInst(ty_op.operand);10849 const src_mcv = try self.resolveInst(ty_op.operand);
10892 if (dst_ty.isVector(zcu)) {10850 if (dst_ty.isVector(zcu)) {
10893 const src_abi_size: u32 = @intCast(src_ty.abiSize(zcu));
10894 const max_abi_size = @max(dst_abi_size, src_abi_size);10851 const max_abi_size = @max(dst_abi_size, src_abi_size);
10895 if (max_abi_size > self.vectorSize(.int)) break :result null;10852 if (max_abi_size > self.vectorSize(.int)) break :result null;
10896 const has_avx = self.hasFeature(.avx);10853 const has_avx = self.hasFeature(.avx);
...@@ -11060,7 +11017,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -11060,7 +11017,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
11060 else => src_int_info.bits,11017 else => src_int_info.bits,
11061 };11018 };
1106211019
11063 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and11020 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 std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==11022 std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
11065 std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and11023 std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and
11066 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {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,8 +11037,8 @@ fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void {
11079 break :result .{ .register = registerAlias(dst_mcv.getReg().?, dst_abi_size) };11037 break :result .{ .register = registerAlias(dst_mcv.getReg().?, dst_abi_size) };
11080 }11038 }
1108111039
11082 const src_limbs_len = std.math.divCeil(u16, src_int_info.bits, 64) catch unreachable;11040 const src_limbs_len = std.math.divCeil(u31, src_abi_size, 8) catch unreachable;
11083 const dst_limbs_len = std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;11041 const dst_limbs_len = @divExact(dst_abi_size, 8);
1108411042
11085 const high_mcv: MCValue = if (dst_mcv.isBase())11043 const high_mcv: MCValue = if (dst_mcv.isBase())
11086 dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()11044 dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()
...@@ -12067,6 +12025,7 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -12067,6 +12025,7 @@ fn genSetFrameTruncatedOverflowCompare(
12067 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);12025 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1206812026
12069 const ty = tuple_ty.fieldType(0, zcu);12027 const ty = tuple_ty.fieldType(0, zcu);
12028 const ty_size = ty.abiSize(zcu);
12070 const int_info = ty.intInfo(zcu);12029 const int_info = ty.intInfo(zcu);
1207112030
12072 const hi_bits = (int_info.bits - 1) % 64 + 1;12031 const hi_bits = (int_info.bits - 1) % 64 + 1;
...@@ -12100,6 +12059,13 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -12100,6 +12059,13 @@ fn genSetFrameTruncatedOverflowCompare(
12100 try self.asmSetccRegister(.ne, eq_reg.to8());12059 try self.asmSetccRegister(.ne, eq_reg.to8());
12101 try self.genBinOpMir(.{ ._, .@"or" }, .u8, .{ .register = overflow_reg }, .{ .register = eq_reg });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 );
1210312069
12104 const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));12070 const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, zcu));
12105 if (hi_limb_off > 0) try self.genSetMem(12071 if (hi_limb_off > 0) try self.genSetMem(
...@@ -12116,13 +12082,20 @@ fn genSetFrameTruncatedOverflowCompare(...@@ -12116,13 +12082,20 @@ fn genSetFrameTruncatedOverflowCompare(
12116 .{ .register = scratch_reg },12082 .{ .register = scratch_reg },
12117 .{},12083 .{},
12118 );12084 );
12119 try self.genSetMem(12085 var ext_off: i32 = hi_limb_off + 8;
12120 .{ .frame = frame_index },12086 if (ext_off < ty_size) {
12121 @intCast(tuple_ty.structFieldOffset(1, zcu)),12087 switch (int_info.signedness) {
12122 tuple_ty.fieldType(1, zcu),12088 .signed => try self.asmRegisterImmediate(.{ ._r, .sa }, scratch_reg.to64(), .s(63)),
12123 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },12089 .unsigned => try self.asmRegisterRegister(.{ ._, .xor }, scratch_reg.to32(), scratch_reg.to32()),
12124 .{},12090 }
12125 );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}
1212712100
12128fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {12101fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void {
...@@ -13581,9 +13554,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -13581,9 +13554,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
13581 .{ ._, .bt },13554 .{ ._, .bt },
13582 .{13555 .{
13583 .base = .{ .frame = frame_index },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 else => try self.asmMemoryRegister(13564 else => try self.asmMemoryRegister(
13589 .{ ._, .bt },13565 .{ ._, .bt },
...@@ -13603,8 +13579,11 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -13603,8 +13579,11 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
13603 .load_frame => switch (index_mcv) {13579 .load_frame => switch (index_mcv) {
13604 .immediate => |index_imm| try self.asmMemoryImmediate(13580 .immediate => |index_imm| try self.asmMemoryImmediate(
13605 .{ ._, .bt },13581 .{ ._, .bt },
13606 try array_mat_mcv.mem(self, .{ .size = .qword }),13582 try array_mat_mcv.mem(self, .{
13607 .u(index_imm),13583 .size = .qword,
13584 .disp = @intCast(index_imm / 64 * 8),
13585 }),
13586 .u(index_imm % 64),
13608 ),13587 ),
13609 else => try self.asmMemoryRegister(13588 else => try self.asmMemoryRegister(
13610 .{ ._, .bt },13589 .{ ._, .bt },
...@@ -13622,9 +13601,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -13622,9 +13601,12 @@ fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void {
13622 .base = .{13601 .base = .{
13623 .reg = try self.copyToTmpRegister(.usize, array_mat_mcv.address()),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 else => try self.asmMemoryRegister(13611 else => try self.asmMemoryRegister(
13630 .{ ._, .bt },13612 .{ ._, .bt },
...@@ -14451,13 +14433,18 @@ fn genByteSwap(...@@ -14451,13 +14433,18 @@ fn genByteSwap(
14451 return src_mcv;14433 return src_mcv;
14452 },14434 },
14453 9...16 => {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 .register_pair => |src_regs| if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {14442 .register_pair => |src_regs| if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
14456 for (src_regs) |src_reg| try self.asmRegister(.{ ._, .bswap }, src_reg.to64());14443 for (src_regs) |src_reg| try self.asmRegister(.{ ._, .bswap }, src_reg.to64());
14457 return .{ .register_pair = .{ src_regs[1], src_regs[0] } };14444 return .{ .register_pair = .{ src_regs[1], src_regs[0] } };
14458 },14445 } else src_mcv,
14459 else => {},14446 else => src_mcv,
14460 }14447 };
1446114448
14462 const dst_regs =14449 const dst_regs =
14463 try self.register_manager.allocRegs(2, .{ inst, inst }, abi.RegisterClass.gp);14450 try self.register_manager.allocRegs(2, .{ inst, inst }, abi.RegisterClass.gp);
...@@ -14465,18 +14452,18 @@ fn genByteSwap(...@@ -14465,18 +14452,18 @@ fn genByteSwap(
14465 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);14452 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
1446614453
14467 for (dst_regs, 0..) |dst_reg, limb_index| {14454 for (dst_regs, 0..) |dst_reg, limb_index| {
14468 if (src_mcv.isBase()) {14455 if (mat_src_mcv.isBase()) {
14469 try self.asmRegisterMemory(14456 try self.asmRegisterMemory(
14470 .{ ._, if (has_movbe) .movbe else .mov },14457 .{ ._, if (has_movbe) .movbe else .mov },
14471 dst_reg.to64(),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 if (!has_movbe) try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());14461 if (!has_movbe) try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());
14475 } else {14462 } else {
14476 try self.asmRegisterRegister(14463 try self.asmRegisterRegister(
14477 .{ ._, .mov },14464 .{ ._, .mov },
14478 dst_reg.to64(),14465 dst_reg.to64(),
14479 src_mcv.register_pair[limb_index].to64(),14466 mat_src_mcv.register_pair[limb_index].to64(),
14480 );14467 );
14481 try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());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,6 +15667,15 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
15680 const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg);15667 const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg);
15681 defer self.register_manager.unlockReg(ptr_lock);15668 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
15683 var limb_i: u16 = 0;15679 var limb_i: u16 = 0;
15684 while (limb_i * limb_abi_bits < src_bit_off + src_bit_size) : (limb_i += 1) {15680 while (limb_i * limb_abi_bits < src_bit_off + src_bit_size) : (limb_i += 1) {
15685 const part_bit_off = if (limb_i == 0) src_bit_off else 0;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,7 +15708,7 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
15712 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);15708 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
15713 defer self.register_manager.unlockReg(tmp_lock);15709 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, .{});
15716 switch (limb_i) {15712 switch (limb_i) {
15717 0 => try self.genShiftBinOpMir(15713 0 => try self.genShiftBinOpMir(
15718 .{ ._l, .sh },15714 .{ ._l, .sh },
...@@ -15743,8 +15739,8 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)...@@ -15743,8 +15739,8 @@ fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue)
15743 defer self.register_manager.unlockReg(tmp_lock);15739 defer self.register_manager.unlockReg(tmp_lock);
1574415740
15745 try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) {15741 try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) {
15746 0 => src_mcv,15742 0 => mat_src_mcv,
15747 else => src_mcv.address().offset(limb_i * limb_abi_size).deref(),15743 else => mat_src_mcv.address().offset(limb_i * limb_abi_size).deref(),
15748 }, .{});15744 }, .{});
15749 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });15745 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });
15750 try self.asmMemoryRegister(15746 try self.asmMemoryRegister(
...@@ -17228,7 +17224,7 @@ fn genMulDivBinOp(...@@ -17228,7 +17224,7 @@ fn genMulDivBinOp(
17228 dst_mcv.address(),17224 dst_mcv.address(),
17229 lhs_mcv.address(),17225 lhs_mcv.address(),
17230 rhs_mcv.address(),17226 rhs_mcv.address(),
17231 .{ .immediate = src_info.bits },17227 .{ .immediate = 8 * src_abi_size },
17232 }, .{});17228 }, .{});
17233 return dst_mcv;17229 return dst_mcv;
17234 },17230 },
...@@ -17246,7 +17242,8 @@ fn genMulDivBinOp(...@@ -17246,7 +17242,8 @@ fn genMulDivBinOp(
17246 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });17242 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
17247 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);17243 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;
17250 switch (tag) {17247 switch (tag) {
17251 .mul,17248 .mul,
17252 .mul_wrap,17249 .mul_wrap,
...@@ -17279,6 +17276,15 @@ fn genMulDivBinOp(...@@ -17279,6 +17276,15 @@ fn genMulDivBinOp(
17279 },17276 },
17280 }, ty, lhs_mcv, rhs_mcv);17277 }, 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
17282 if (dst_abi_size <= 8) return .{ .register = registerAlias(switch (tag) {17288 if (dst_abi_size <= 8) return .{ .register = registerAlias(switch (tag) {
17283 .mul, .mul_wrap, .div_trunc, .div_exact => .rax,17289 .mul, .mul_wrap, .div_trunc, .div_exact => .rax,
17284 .rem => .rdx,17290 .rem => .rdx,
...@@ -21954,8 +21960,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -21954,8 +21960,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
21954 break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(.usize, ptr_mcv) } };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)) |_| {21963 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |tracked_index| {
21958 _ = self.register_manager.lockReg(reg);21964 try self.register_manager.getRegIndex(tracked_index, if (output == .none) inst else null);
21965 _ = self.register_manager.lockRegIndexAssumeUnused(tracked_index);
21959 };21966 };
21960 if (!std.mem.eql(u8, name, "_"))21967 if (!std.mem.eql(u8, name, "_"))
21961 arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));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,7 +22888,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
2288122888
22882 try self.asmRegisterRegister(.{ ._q, .mov }, dst_regs[0].to64(), src_reg.to128());22889 try self.asmRegisterRegister(.{ ._q, .mov }, dst_regs[0].to64(), src_reg.to128());
22883 try self.asmRegisterRegister(.{ ._ps, .movhl }, tmp_reg.to128(), src_reg.to128());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 return;22893 return;
22887 } else unreachable,22894 } else unreachable,
...@@ -23831,10 +23838,12 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -23831,10 +23838,12 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {
23831 const dst_rc = self.regSetForType(dst_ty);23838 const dst_rc = self.regSetForType(dst_ty);
23832 const src_rc = self.regSetForType(src_ty);23839 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;
23835 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);23842 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) and23844 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 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {23847 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
23839 const dst_mcv = try self.allocRegOrMem(inst, true);23848 const dst_mcv = try self.allocRegOrMem(inst, true);
23840 try self.genCopy(switch (std.math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {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,7 +27711,7 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
27702 reg27711 reg
27703 else27712 else
27704 unreachable,27713 unreachable,
27705 .x87 => if (size_bytes == 16)27714 .x87 => if (size_bytes >= 10 and size_bytes <= 16)
27706 reg27715 reg
27707 else27716 else
27708 unreachable,27717 unreachable,
...@@ -28574,23 +28583,19 @@ const Temp = struct {...@@ -28574,23 +28583,19 @@ const Temp = struct {
28574 try ptr.tracking(cg).short.deref().mem(cg, .{ .size = .byte }),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 val_reg,28587 val_reg,
28579 @intCast(val_ty.abiSize(cg.pt.zcu)),28588 @intCast(val_ty.abiSize(cg.pt.zcu)),
28580 ), cg),28589 )}, cg),
28581 inline .register_pair,28590 inline .register_pair,
28582 .register_triple,28591 .register_triple,
28583 .register_quadruple,28592 .register_quadruple,
28584 => |val_regs| for (val_regs) |val_reg| {28593 => |val_regs| try ptr.storeRegs(val_ty, &val_regs, cg),
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 },
28589 .register_offset => |val_reg_off| switch (val_reg_off.off) {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 val_reg_off.reg,28596 val_reg_off.reg,
28592 @intCast(val_ty.abiSize(cg.pt.zcu)),28597 @intCast(val_ty.abiSize(cg.pt.zcu)),
28593 ), cg),28598 )}, cg),
28594 else => continue :val_to_gpr,28599 else => continue :val_to_gpr,
28595 },28600 },
28596 .register_overflow => |val_reg_ov| {28601 .register_overflow => |val_reg_ov| {
...@@ -28608,7 +28613,7 @@ const Temp = struct {...@@ -28608,7 +28613,7 @@ const Temp = struct {
28608 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),28613 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
28609 });28614 });
28610 const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));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 try ptr.toOffset(first_size, cg);28617 try ptr.toOffset(first_size, cg);
28613 try cg.asmSetccMemory(28618 try cg.asmSetccMemory(
28614 val_reg_ov.eflags,28619 val_reg_ov.eflags,
...@@ -28675,6 +28680,15 @@ const Temp = struct {...@@ -28675,6 +28680,15 @@ const Temp = struct {
28675 const val_mcv = val.tracking(cg).short;28680 const val_mcv = val.tracking(cg).short;
28676 switch (val_mcv) {28681 switch (val_mcv) {
28677 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),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 .immediate => |val_imm| {28692 .immediate => |val_imm| {
28679 const val_op: Immediate = if (std.math.cast(u31, val_imm)) |val_uimm31|28693 const val_op: Immediate = if (std.math.cast(u31, val_imm)) |val_uimm31|
28680 .u(val_uimm31)28694 .u(val_uimm31)
...@@ -28691,24 +28705,52 @@ const Temp = struct {...@@ -28691,24 +28705,52 @@ const Temp = struct {
28691 val_op,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 val_reg,28716 val_reg,
28696 @intCast(val_ty.abiSize(cg.pt.zcu)),28717 @intCast(val_ty.abiSize(cg.pt.zcu)),
28697 ), cg),28718 )}, cg),
28698 inline .register_pair, .register_triple, .register_quadruple => |val_regs| {28719 inline .register_pair,
28699 var disp = opts.disp;28720 .register_triple,
28700 for (val_regs) |val_reg| {28721 .register_quadruple,
28701 try dst.writeReg(disp, val_ty, val_reg, cg);28722 => |val_regs| try dst.writeRegs(opts.disp, val_ty, &val_regs, cg),
28702 disp += @divExact(val_reg.bitSize(), 8);
28703 }
28704 },
28705 .register_offset => |val_reg_off| switch (val_reg_off.off) {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 val_reg_off.reg,28725 val_reg_off.reg,
28708 @intCast(val_ty.abiSize(cg.pt.zcu)),28726 @intCast(val_ty.abiSize(cg.pt.zcu)),
28709 ), cg),28727 )}, cg),
28710 else => continue :val_to_gpr,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 .lea_frame, .lea_symbol => continue :val_to_gpr,28754 .lea_frame, .lea_symbol => continue :val_to_gpr,
28713 .memory, .indirect, .load_frame, .load_symbol => {28755 .memory, .indirect, .load_frame, .load_symbol => {
28714 var dst_ptr =28756 var dst_ptr =
...@@ -28739,33 +28781,47 @@ const Temp = struct {...@@ -28739,33 +28781,47 @@ const Temp = struct {
28739 }));28781 }));
28740 }28782 }
2874128783
28742 fn storeReg(ptr: *Temp, src_ty: Type, src_reg: Register, cg: *CodeGen) !void {28784 fn storeRegs(ptr: *Temp, src_ty: Type, src_regs: []const Register, cg: *CodeGen) !void {
28743 const src_rc = src_reg.class();28785 var part_disp: u31 = 0;
28744 const src_abi_size = src_ty.abiSize(cg.pt.zcu);28786 var deferred_disp: u31 = 0;
28745 const strat = try cg.moveStrategy(src_ty, src_rc, false);28787 var src_abi_size: u32 = @intCast(src_ty.abiSize(cg.pt.zcu));
28746 // hack around linker relocation bugs28788 for (src_regs) |src_reg| {
28747 switch (ptr.tracking(cg).short) {28789 const src_rc = src_reg.class();
28748 else => {},28790 const part_bit_size = @min(8 * src_abi_size, src_reg.bitSize());
28749 .lea_symbol => |sym_off| if (src_rc != .general_purpose or sym_off.off != 0)28791 const part_size = @divExact(part_bit_size, 8);
28750 while (try ptr.toRegClass(false, .general_purpose, cg)) {},28792 if (src_rc == .x87 or std.math.isPowerOfTwo(part_size)) {
28751 }28793 // hack around linker relocation bugs
28752 if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) {28794 switch (ptr.tracking(cg).short) {
28753 try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{28795 else => {},
28754 .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())),28796 .lea_symbol => while (try ptr.toRegClass(false, .general_purpose, cg)) {},
28755 }), src_reg);28797 }
28756 } else {28798 const strat = try cg.moveStrategy(src_ty, src_rc, false);
28757 const frame_alloc: FrameAlloc = .initSpill(src_ty, cg.pt.zcu);28799 try strat.write(cg, try ptr.tracking(cg).short.deref().mem(cg, .{
28758 const frame_index = try cg.allocFrameIndex(frame_alloc);28800 .size = .fromBitSize(part_bit_size),
28759 const frame_size: Memory.Size = .fromSize(frame_alloc.abi_size);28801 .disp = part_disp,
28760 try strat.write(cg, .{28802 }), registerAlias(src_reg, part_size));
28761 .base = .{ .frame = frame_index },28803 } else {
28762 .mod = .{ .rm = .{ .size = frame_size } },28804 const frame_size = std.math.ceilPowerOfTwoAssert(u32, part_size);
28763 }, src_reg);28805 const frame_index = try cg.allocFrameIndex(.init(.{
28764 var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } });28806 .size = frame_size,
28765 var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size });28807 .alignment = .fromNonzeroByteUnits(frame_size),
28766 try ptr.memcpy(&src_ptr, &len, cg);28808 }));
28767 try src_ptr.die(cg);28809 const strat = try cg.moveStrategy(src_ty, src_rc, true);
28768 try len.die(cg);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 }
2877128827
...@@ -28777,30 +28833,41 @@ const Temp = struct {...@@ -28777,30 +28833,41 @@ const Temp = struct {
28777 }));28833 }));
28778 }28834 }
2877928835
28780 fn writeReg(dst: Temp, disp: i32, src_ty: Type, src_reg: Register, cg: *CodeGen) !void {28836 fn writeRegs(dst: Temp, disp: i32, src_ty: Type, src_regs: []const Register, cg: *CodeGen) !void {
28781 const src_rc = src_reg.class();28837 var part_disp = disp;
28782 const src_abi_size = src_ty.abiSize(cg.pt.zcu);28838 var src_abi_size: u32 = @intCast(src_ty.abiSize(cg.pt.zcu));
28783 const strat = try cg.moveStrategy(src_ty, src_rc, false);28839 for (src_regs) |src_reg| {
28784 if (src_rc == .x87 or std.math.isPowerOfTwo(src_abi_size)) {28840 const src_rc = src_reg.class();
28785 try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{28841 const part_bit_size = @min(8 * src_abi_size, src_reg.bitSize());
28786 .size = .fromBitSize(@min(8 * src_abi_size, src_reg.bitSize())),28842 const part_size = @divExact(part_bit_size, 8);
28787 .disp = disp,28843 if (src_rc == .x87 or std.math.isPowerOfTwo(part_size)) {
28788 }), src_reg);28844 const strat = try cg.moveStrategy(src_ty, src_rc, false);
28789 } else {28845 try strat.write(cg, try dst.tracking(cg).short.mem(cg, .{
28790 const frame_alloc: FrameAlloc = .initSpill(src_ty, cg.pt.zcu);28846 .size = .fromBitSize(part_bit_size),
28791 const frame_index = try cg.allocFrameIndex(frame_alloc);28847 .disp = part_disp,
28792 const frame_size: Memory.Size = .fromSize(frame_alloc.abi_size);28848 }), registerAlias(src_reg, part_size));
28793 try strat.write(cg, .{28849 } else {
28794 .base = .{ .frame = frame_index },28850 const frame_size = std.math.ceilPowerOfTwoAssert(u32, part_size);
28795 .mod = .{ .rm = .{ .size = frame_size } },28851 const frame_index = try cg.allocFrameIndex(.init(.{
28796 }, src_reg);28852 .size = frame_size,
28797 var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address());28853 .alignment = .fromNonzeroByteUnits(frame_size),
28798 var src_ptr = try cg.tempInit(.usize, .{ .lea_frame = .{ .index = frame_index } });28854 }));
28799 var len = try cg.tempInit(.usize, .{ .immediate = src_abi_size });28855 const strat = try cg.moveStrategy(src_ty, src_rc, true);
28800 try dst_ptr.memcpy(&src_ptr, &len, cg);28856 try strat.write(cg, .{
28801 try dst_ptr.die(cg);28857 .base = .{ .frame = frame_index },
28802 try src_ptr.die(cg);28858 .mod = .{ .rm = .{ .size = .fromSize(frame_size) } },
28803 try len.die(cg);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 }
2880628873
...@@ -29123,8 +29190,8 @@ const Select = struct {...@@ -29123,8 +29190,8 @@ const Select = struct {
29123 signed_int_vec: Memory.Size,29190 signed_int_vec: Memory.Size,
29124 signed_int_or_full_vec: Memory.Size,29191 signed_int_or_full_vec: Memory.Size,
29125 unsigned_int_vec: Memory.Size,29192 unsigned_int_vec: Memory.Size,
29126 int_or_vec: Memory.Size,29193 size: Memory.Size,
29127 exact_remainder_int_or_vec: struct { of: Memory.Size, is: Memory.Size },29194 multiple_size: Memory.Size,
29128 int: Memory.Size,29195 int: Memory.Size,
29129 scalar_int: Memory.Size,29196 scalar_int: Memory.Size,
29130 scalar_signed_int: Memory.Size,29197 scalar_signed_int: Memory.Size,
...@@ -29170,15 +29237,8 @@ const Select = struct {...@@ -29170,15 +29237,8 @@ const Select = struct {
29170 } else false,29237 } else false,
29171 .unsigned_int_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and29238 .unsigned_int_vec => |size| ty.isVector(zcu) and size.bitSize(cg.target) >= 8 * ty.abiSize(zcu) and
29172 if (intInfo(ty.childType(zcu), cg)) |int_info| int_info.signedness == .unsigned else false,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|29240 .size => |size| size.bitSize(cg.target) >= 8 * ty.abiSize(zcu),
29174 size.bitSize(cg.target) >= int_info.bits29241 .multiple_size => |size| size.bitSize(cg.target) % 8 * ty.abiSize(zcu) == 0,
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,
29182 .int => |size| if (intInfo(ty, cg)) |int_info| size.bitSize(cg.target) >= int_info.bits else false,29242 .int => |size| if (intInfo(ty, cg)) |int_info| size.bitSize(cg.target) >= int_info.bits else false,
29183 .scalar_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info|29243 .scalar_int => |size| if (intInfo(ty.scalarType(zcu), cg)) |int_info|
29184 size.bitSize(cg.target) >= int_info.bits29244 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...@@ -540,8 +540,12 @@ pub fn getCAbiSseReturnRegs(cc: std.builtin.CallingConvention.Tag) []const Regis
540}540}
541541
542pub fn getCAbiLinkerScratchReg(cc: std.builtin.CallingConvention.Tag) Register {542pub fn getCAbiLinkerScratchReg(cc: std.builtin.CallingConvention.Tag) Register {
543 const int_return_regs = getCAbiIntReturnRegs(cc);543 return switch (cc) {
544 return int_return_regs[int_return_regs.len - 1];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 };
545}549}
546550
547const gp_regs = [_]Register{551const gp_regs = [_]Register{
src/main.zig+8
...@@ -39,6 +39,11 @@ test {...@@ -39,6 +39,11 @@ test {
39 _ = Package;39 _ = Package;
40}40}
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
42pub const std_options: std.Options = .{47pub const std_options: std.Options = .{
43 .wasiCwd = wasi_cwd,48 .wasiCwd = wasi_cwd,
44 .logFn = log,49 .logFn = log,
...@@ -3320,6 +3325,7 @@ fn buildOutputType(...@@ -3320,6 +3325,7 @@ fn buildOutputType(
3320 .allocator = gpa,3325 .allocator = gpa,
3321 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),3326 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
3322 .track_ids = true,3327 .track_ids = true,
3328 .stack_size = thread_stack_size,
3323 });3329 });
3324 defer thread_pool.deinit();3330 defer thread_pool.deinit();
33253331
...@@ -5024,6 +5030,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5024,6 +5030,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5024 .allocator = gpa,5030 .allocator = gpa,
5025 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),5031 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
5026 .track_ids = true,5032 .track_ids = true,
5033 .stack_size = thread_stack_size,
5027 });5034 });
5028 defer thread_pool.deinit();5035 defer thread_pool.deinit();
50295036
...@@ -5460,6 +5467,7 @@ fn jitCmd(...@@ -5460,6 +5467,7 @@ fn jitCmd(
5460 .allocator = gpa,5467 .allocator = gpa,
5461 .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),5468 .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),
5462 .track_ids = true,5469 .track_ids = true,
5470 .stack_size = thread_stack_size,
5463 });5471 });
5464 defer thread_pool.deinit();5472 defer thread_pool.deinit();
54655473
src/register_manager.zig+23-55
...@@ -58,11 +58,6 @@ pub fn RegisterManager(...@@ -58,11 +58,6 @@ pub fn RegisterManager(
58 return @alignCast(@fieldParentPtr("register_manager", self));58 return @alignCast(@fieldParentPtr("register_manager", self));
59 }59 }
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
66 fn markRegIndexAllocated(self: *Self, tracked_index: TrackedIndex) void {61 fn markRegIndexAllocated(self: *Self, tracked_index: TrackedIndex) void {
67 self.allocated_registers.set(tracked_index);62 self.allocated_registers.set(tracked_index);
68 }63 }
...@@ -234,28 +229,20 @@ pub fn RegisterManager(...@@ -234,28 +229,20 @@ pub fn RegisterManager(
234 ) ?[count]Register {229 ) ?[count]Register {
235 comptime assert(count > 0 and count <= tracked_registers.len);230 comptime assert(count > 0 and count <= tracked_registers.len);
236231
237 var free_and_not_locked_registers = self.free_registers;232 var free_and_unlocked_registers = self.locked_registers;
238 free_and_not_locked_registers.setIntersection(register_class);233 free_and_unlocked_registers.toggleAll();
239234 free_and_unlocked_registers.setIntersection(self.free_registers);
240 var unlocked_registers = self.locked_registers;235 free_and_unlocked_registers.setIntersection(register_class);
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;
246236
247 var regs: [count]Register = undefined;237 var regs: [count]Register = undefined;
248 var i: usize = 0;238 var i: usize = 0;
249 for (tracked_registers) |reg| {239 var it = free_and_unlocked_registers.iterator(.{});
250 if (i >= count) break;240 while (it.next()) |reg_index| {
251 if (excludeRegister(reg, register_class)) continue;241 regs[i] = regAtTrackedIndex(@intCast(reg_index));
252 if (self.isRegLocked(reg)) continue;
253 if (!self.isRegFree(reg)) continue;
254
255 regs[i] = reg;
256 i += 1;242 i += 1;
243 if (i >= count) break;
257 }244 }
258 assert(i == count);245 if (i < count) return null;
259246
260 for (regs, insts) |reg, inst| {247 for (regs, insts) |reg, inst| {
261 log.debug("tryAllocReg {} for inst {?}", .{ reg, inst });248 log.debug("tryAllocReg {} for inst {?}", .{ reg, inst });
...@@ -290,46 +277,27 @@ pub fn RegisterManager(...@@ -290,46 +277,27 @@ pub fn RegisterManager(
290 ) AllocationError![count]Register {277 ) AllocationError![count]Register {
291 comptime assert(count > 0 and count <= tracked_registers.len);278 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
298 const result = self.tryAllocRegs(count, insts, register_class) orelse blk: {280 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
299 // We'll take over the first count registers. Spill285 // We'll take over the first count registers. Spill
300 // the instructions that were previously there to a286 // the instructions that were previously there to a
301 // stack allocations.287 // stack allocations.
302 var regs: [count]Register = undefined;288 var regs: [count]Register = undefined;
303 var i: usize = 0;289 var i: usize = 0;
304 for (tracked_registers) |reg| {290 var it = unlocked_registers.iterator(.{});
305 if (i >= count) break;291 while (it.next()) |reg_index| {
306 if (excludeRegister(reg, register_class)) break;292 const tracked_index: TrackedIndex = @intCast(reg_index);
307 if (self.isRegLocked(reg)) continue;293 if (!self.isRegIndexFree(tracked_index) and
308294 self.registers[tracked_index].unwrap() == .target) continue;
309 log.debug("allocReg {} for inst {?}", .{ reg, insts[i] });295 try self.getRegIndex(tracked_index, insts[i]);
310 regs[i] = reg;296 regs[i] = regAtTrackedIndex(tracked_index);
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
331 i += 1;297 i += 1;
298 if (i >= count) break;
332 }299 }
300 if (i < count) return error.OutOfRegisters;
333301
334 break :blk regs;302 break :blk regs;
335 };303 };
...@@ -351,7 +319,7 @@ pub fn RegisterManager(...@@ -351,7 +319,7 @@ pub fn RegisterManager(
351 /// Spills the register if it is currently allocated. If a319 /// Spills the register if it is currently allocated. If a
352 /// corresponding instruction is passed, will also track this320 /// corresponding instruction is passed, will also track this
353 /// register.321 /// register.
354 fn getRegIndex(322 pub fn getRegIndex(
355 self: *Self,323 self: *Self,
356 tracked_index: TrackedIndex,324 tracked_index: TrackedIndex,
357 inst: ?Air.Inst.Index,325 inst: ?Air.Inst.Index,
test/behavior/x86_64/math.zig+10
...@@ -742,6 +742,16 @@ fn testBinary(comptime op: anytype) !void {...@@ -742,6 +742,16 @@ fn testBinary(comptime op: anytype) !void {
742 0xb7935f5c2f3b1ae7a422c0a7c446884294b7d5370bada307d2fe5a4c4284a999,742 0xb7935f5c2f3b1ae7a422c0a7c446884294b7d5370bada307d2fe5a4c4284a999,
743 0x310e6e196ba4f143b8d285ca6addf7f3bb3344224aff221b27607a31e148be08,743 0x310e6e196ba4f143b8d285ca6addf7f3bb3344224aff221b27607a31e148be08,
744 );744 );
745 try testType(
746 u258,
747 0x186d5ddaab8cb8cb04e5b41e36f812e039d008baf49f12894c39e29a07796d800,
748 0x2072daba6ffad168826163eb136f6d28ca4360c8e7e5e41e29755e19e4753a4f5,
749 );
750 try testType(
751 u495,
752 0x6eaf4e252b3bf74b75bac59e0b43ca5326bad2a25b3fdb74a67ef132ac5e47d72eebc3316fb2351ee66c50dc5afb92a75cea9b0e35160652c7db39eeb158,
753 0x49fbed744a92b549d8c05bb3512c617d24dd824f3f69bdf3923bc326a75674b85f5b828d2566fab9c86f571d12c2a63c9164feb0d191d27905533d09622a,
754 );
745 try testType(755 try testType(
746 u512,756 u512,
747 0xe5b1fedca3c77db765e517aabd05ffc524a3a8aff1784bbf67c45b894447ede32b65b9940e78173c591e56e078932d465f235aece7ad47b7f229df7ba8f12295,757 0xe5b1fedca3c77db765e517aabd05ffc524a3a8aff1784bbf67c45b894447ede32b65b9940e78173c591e56e078932d465f235aece7ad47b7f229df7ba8f12295,