authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-11-25 02:58:30-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:42:07-05:00
logaf1191ea8ba55a6eab53e0b561355bb116bdbf2d
tree0bd2977ad2f8e379dcac7fdec5ba58e294bb06f5
parent257054a1467b2612725bd66852d84496024cf66c

x86_64: rewrite


12 files changed, 1885 insertions(+), 948 deletions(-)

src/Air.zig+30-6
......@@ -893,14 +893,38 @@ pub const Inst = struct {
893893 pub const Index = enum(u32) {
894894 _,
895895
896 pub fn toRef(i: Index) Inst.Ref {
897 assert(@intFromEnum(i) >> 31 == 0);
898 return @enumFromInt((1 << 31) | @intFromEnum(i));
896 pub fn unwrap(index: Index) union(enum) { ref: Inst.Ref, target: u31 } {
897 const low_index: u31 = @truncate(@intFromEnum(index));
898 return switch (@as(u1, @intCast(@intFromEnum(index) >> 31))) {
899 0 => .{ .ref = @enumFromInt(@as(u32, 1 << 31) | low_index) },
900 1 => .{ .target = low_index },
901 };
902 }
903
904 pub fn toRef(index: Index) Inst.Ref {
905 return index.unwrap().ref;
906 }
907
908 pub fn fromTargetIndex(index: u31) Index {
909 return @enumFromInt((1 << 31) | @as(u32, index));
910 }
911
912 pub fn toTargetIndex(index: Index) u31 {
913 return index.unwrap().target;
899914 }
900915
901 pub fn toTargetIndex(i: Index) u31 {
902 assert(@intFromEnum(i) >> 31 == 1);
903 return @truncate(@intFromEnum(i));
916 pub fn format(
917 index: Index,
918 comptime _: []const u8,
919 _: std.fmt.FormatOptions,
920 writer: anytype,
921 ) @TypeOf(writer).Error!void {
922 try writer.writeByte('%');
923 switch (index.unwrap()) {
924 .ref => {},
925 .target => try writer.writeByte('t'),
926 }
927 try writer.print("{d}", .{@as(u31, @truncate(@intFromEnum(index)))});
904928 }
905929 };
906930
src/Compilation.zig+1
......@@ -3067,6 +3067,7 @@ pub fn saveState(comp: *Compilation) !void {
30673067 // linker state
30683068 switch (lf.tag) {
30693069 .wasm => {
3070 dev.check(link.File.Tag.wasm.devFeature());
30703071 const wasm = lf.cast(.wasm).?;
30713072 const is_obj = comp.config.output_mode == .Obj;
30723073 try bufs.ensureUnusedCapacity(85);
src/Liveness.zig-14
......@@ -202,14 +202,6 @@ pub fn operandDies(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) bool
202202 return (l.tomb_bits[usize_index] & mask) != 0;
203203}
204204
205pub fn clearOperandDeath(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) void {
206 assert(operand < bpi - 1);
207 const usize_index = (@intFromEnum(inst) * bpi) / @bitSizeOf(usize);
208 const mask = @as(usize, 1) <<
209 @as(Log2Int(usize), @intCast((@intFromEnum(inst) % (@bitSizeOf(usize) / bpi)) * bpi + operand));
210 l.tomb_bits[usize_index] &= ~mask;
211}
212
213205const OperandCategory = enum {
214206 /// The operand lives on, but this instruction cannot possibly mutate memory.
215207 none,
......@@ -844,12 +836,6 @@ const Analysis = struct {
844836 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
845837 extra: std.ArrayListUnmanaged(u32),
846838
847 fn storeTombBits(a: *Analysis, inst: Air.Inst.Index, tomb_bits: Bpi) void {
848 const usize_index = (inst * bpi) / @bitSizeOf(usize);
849 a.tomb_bits[usize_index] |= @as(usize, tomb_bits) <<
850 @as(Log2Int(usize), @intCast((inst % (@bitSizeOf(usize) / bpi)) * bpi));
851 }
852
853839 fn addExtra(a: *Analysis, extra: anytype) Allocator.Error!u32 {
854840 const fields = std.meta.fields(@TypeOf(extra));
855841 try a.extra.ensureUnusedCapacity(a.gpa, fields.len);
src/arch/aarch64/CodeGen.zig+10-10
......@@ -71,6 +71,8 @@ end_di_column: u32,
7171/// which is a relative jump, based on the address following the reloc.
7272exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
7373
74reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
75
7476/// We postpone the creation of debug info for function args and locals
7577/// until after all Mir instructions have been generated. Only then we
7678/// will know saved_regs_stack_space which is necessary in order to
......@@ -646,6 +648,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
646648 const old_air_bookkeeping = self.air_bookkeeping;
647649 try self.ensureProcessDeathCapacity(Liveness.bpi);
648650
651 self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
649652 switch (air_tags[@intFromEnum(inst)]) {
650653 // zig fmt: off
651654 .add => try self.airBinOp(inst, .add),
......@@ -927,16 +930,13 @@ fn finishAirBookkeeping(self: *Self) void {
927930}
928931
929932fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Liveness.bpi - 1]Air.Inst.Ref) void {
930 var tomb_bits = self.liveness.getTombBits(inst);
931 for (operands) |op| {
932 const dies = @as(u1, @truncate(tomb_bits)) != 0;
933 tomb_bits >>= 1;
934 if (!dies) continue;
935 const op_index = op.toIndex() orelse continue;
936 self.processDeath(op_index);
933 const tomb_bits = self.liveness.getTombBits(inst);
934 for (0.., operands) |op_index, op| {
935 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
936 if (self.reused_operands.isSet(op_index)) continue;
937 self.processDeath(op.toIndexAllowNone() orelse continue);
937938 }
938 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
939 if (is_used) {
939 if (tomb_bits & 1 << (Liveness.bpi - 1) == 0) {
940940 log.debug("%{d} => {}", .{ inst, result });
941941 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
942942 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
......@@ -3614,7 +3614,7 @@ fn reuseOperand(
36143614 }
36153615
36163616 // Prevent the operand deaths processing code from deallocating it.
3617 self.liveness.clearOperandDeath(inst, op_index);
3617 self.reused_operands.set(op_index);
36183618
36193619 // That makes us responsible for doing the rest of the stuff that processDeath would have done.
36203620 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
src/arch/arm/CodeGen.zig+10-10
......@@ -72,6 +72,8 @@ end_di_column: u32,
7272/// which is a relative jump, based on the address following the reloc.
7373exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
7474
75reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
76
7577/// We postpone the creation of debug info for function args and locals
7678/// until after all Mir instructions have been generated. Only then we
7779/// will know saved_regs_stack_space which is necessary in order to
......@@ -635,6 +637,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
635637 const old_air_bookkeeping = self.air_bookkeeping;
636638 try self.ensureProcessDeathCapacity(Liveness.bpi);
637639
640 self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
638641 switch (air_tags[@intFromEnum(inst)]) {
639642 // zig fmt: off
640643 .add, => try self.airBinOp(inst, .add),
......@@ -918,16 +921,13 @@ fn finishAirBookkeeping(self: *Self) void {
918921}
919922
920923fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Liveness.bpi - 1]Air.Inst.Ref) void {
921 var tomb_bits = self.liveness.getTombBits(inst);
922 for (operands) |op| {
923 const dies = @as(u1, @truncate(tomb_bits)) != 0;
924 tomb_bits >>= 1;
925 if (!dies) continue;
926 const op_index = op.toIndex() orelse continue;
927 self.processDeath(op_index);
924 const tomb_bits = self.liveness.getTombBits(inst);
925 for (0.., operands) |op_index, op| {
926 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
927 if (self.reused_operands.isSet(op_index)) continue;
928 self.processDeath(op.toIndexAllowNone() orelse continue);
928929 }
929 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
930 if (is_used) {
930 if (tomb_bits & 1 << (Liveness.bpi - 1) == 0) {
931931 log.debug("%{d} => {}", .{ inst, result });
932932 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
933933 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
......@@ -2650,7 +2650,7 @@ fn reuseOperand(
26502650 }
26512651
26522652 // Prevent the operand deaths processing code from deallocating it.
2653 self.liveness.clearOperandDeath(inst, op_index);
2653 self.reused_operands.set(op_index);
26542654
26552655 // That makes us responsible for doing the rest of the stuff that processDeath would have done.
26562656 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
src/arch/riscv64/CodeGen.zig+11-7
......@@ -82,6 +82,8 @@ scope_generation: u32,
8282/// which is a relative jump, based on the address following the reloc.
8383exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
8484
85reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
86
8587/// Whenever there is a runtime branch, we push a Branch onto this stack,
8688/// and pop it off when the runtime branch joins. This provides an "overlay"
8789/// of the table of mappings from instructions to `MCValue` from within the branch.
......@@ -1443,8 +1445,11 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
14431445 verbose_tracking_log.debug("{}", .{func.fmtTracking()});
14441446
14451447 const old_air_bookkeeping = func.air_bookkeeping;
1448 try func.ensureProcessDeathCapacity(Liveness.bpi);
1449
1450 func.reused_operands = @TypeOf(func.reused_operands).initEmpty();
14461451 try func.inst_tracking.ensureUnusedCapacity(func.gpa, 1);
1447 const tag: Air.Inst.Tag = air_tags[@intFromEnum(inst)];
1452 const tag = air_tags[@intFromEnum(inst)];
14481453 switch (tag) {
14491454 // zig fmt: off
14501455 .add,
......@@ -1783,11 +1788,10 @@ fn finishAir(
17831788 result: MCValue,
17841789 operands: [Liveness.bpi - 1]Air.Inst.Ref,
17851790) !void {
1786 var tomb_bits = func.liveness.getTombBits(inst);
1787 for (operands) |op| {
1788 const dies = @as(u1, @truncate(tomb_bits)) != 0;
1789 tomb_bits >>= 1;
1790 if (!dies) continue;
1791 const tomb_bits = func.liveness.getTombBits(inst);
1792 for (0.., operands) |op_index, op| {
1793 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
1794 if (func.reused_operands.isSet(op_index)) continue;
17911795 try func.processDeath(op.toIndexAllowNone() orelse continue);
17921796 }
17931797 func.finishAirResult(inst, result);
......@@ -4424,7 +4428,7 @@ fn reuseOperandAdvanced(
44244428 }
44254429
44264430 // Prevent the operand deaths processing code from deallocating it.
4427 func.liveness.clearOperandDeath(inst, op_index);
4431 func.reused_operands.set(op_index);
44284432 const op_inst = operand.toIndex().?;
44294433 func.getResolvedInstValue(op_inst).reuse(func, maybe_tracked_inst, op_inst);
44304434
src/arch/sparc64/CodeGen.zig+10-10
......@@ -78,6 +78,8 @@ end_di_column: u32,
7878/// which is a relative jump, based on the address following the reloc.
7979exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
8080
81reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
82
8183/// Whenever there is a runtime branch, we push a Branch onto this stack,
8284/// and pop it off when the runtime branch joins. This provides an "overlay"
8385/// of the table of mappings from instructions to `MCValue` from within the branch.
......@@ -493,6 +495,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
493495 const old_air_bookkeeping = self.air_bookkeeping;
494496 try self.ensureProcessDeathCapacity(Liveness.bpi);
495497
498 self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
496499 switch (air_tags[@intFromEnum(inst)]) {
497500 // zig fmt: off
498501 .ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
......@@ -3523,16 +3526,13 @@ fn finishAirBookkeeping(self: *Self) void {
35233526}
35243527
35253528fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Liveness.bpi - 1]Air.Inst.Ref) void {
3526 var tomb_bits = self.liveness.getTombBits(inst);
3527 for (operands) |op| {
3528 const dies = @as(u1, @truncate(tomb_bits)) != 0;
3529 tomb_bits >>= 1;
3530 if (!dies) continue;
3531 const op_index = op.toIndex() orelse continue;
3532 self.processDeath(op_index);
3529 const tomb_bits = self.liveness.getTombBits(inst);
3530 for (0.., operands) |op_index, op| {
3531 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
3532 if (self.reused_operands.isSet(op_index)) continue;
3533 self.processDeath(op.toIndexAllowNone() orelse continue);
35333534 }
3534 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
3535 if (is_used) {
3535 if (tomb_bits & 1 << (Liveness.bpi - 1) == 0) {
35363536 log.debug("%{d} => {}", .{ inst, result });
35373537 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
35383538 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
......@@ -4568,7 +4568,7 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
45684568 }
45694569
45704570 // Prevent the operand deaths processing code from deallocating it.
4571 self.liveness.clearOperandDeath(inst, op_index);
4571 self.reused_operands.set(op_index);
45724572
45734573 // That makes us responsible for doing the rest of the stuff that processDeath would have done.
45744574 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
src/arch/x86_64/CodeGen.zig+1765-874
......@@ -1,41 +1,26 @@
11const std = @import("std");
2const build_options = @import("build_options");
3const builtin = @import("builtin");
42const assert = std.debug.assert;
53const codegen = @import("../../codegen.zig");
6const leb128 = std.leb;
74const link = @import("../../link.zig");
85const log = std.log.scoped(.codegen);
96const tracking_log = std.log.scoped(.tracking);
107const verbose_tracking_log = std.log.scoped(.verbose_tracking);
118const wip_mir_log = std.log.scoped(.wip_mir);
12const math = std.math;
13const mem = std.mem;
14const target_util = @import("../../target.zig");
15const trace = @import("../../tracy.zig").trace;
169
1710const Air = @import("../../Air.zig");
18const Allocator = mem.Allocator;
19const CodeGenError = codegen.CodeGenError;
20const Compilation = @import("../../Compilation.zig");
21const ErrorMsg = Zcu.ErrorMsg;
11const Allocator = std.mem.Allocator;
2212const Emit = @import("Emit.zig");
2313const Liveness = @import("../../Liveness.zig");
2414const Lower = @import("Lower.zig");
2515const Mir = @import("Mir.zig");
26const Package = @import("../../Package.zig");
2716const Zcu = @import("../../Zcu.zig");
17const Module = @import("../../Package/Module.zig");
2818const InternPool = @import("../../InternPool.zig");
29const Alignment = InternPool.Alignment;
30const Target = std.Target;
3119const Type = @import("../../Type.zig");
3220const Value = @import("../../Value.zig");
33const Instruction = @import("encoder.zig").Instruction;
3421
3522const abi = @import("abi.zig");
3623const bits = @import("bits.zig");
37const errUnionErrorOffset = codegen.errUnionErrorOffset;
38const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
3924const encoder = @import("encoder.zig");
4025
4126const Condition = bits.Condition;
......@@ -46,7 +31,7 @@ const RegisterManager = abi.RegisterManager;
4631const RegisterLock = RegisterManager.RegisterLock;
4732const FrameIndex = bits.FrameIndex;
4833
49const InnerError = CodeGenError || error{OutOfRegisters};
34const InnerError = codegen.CodeGenError || error{OutOfRegisters};
5035
5136gpa: Allocator,
5237pt: Zcu.PerThread,
......@@ -57,7 +42,7 @@ debug_output: link.File.DebugInfoOutput,
5742target: *const std.Target,
5843owner: Owner,
5944inline_func: InternPool.Index,
60mod: *Package.Module,
45mod: *Module,
6146arg_index: u32,
6247args: []MCValue,
6348va_info: union {
......@@ -89,6 +74,7 @@ end_di_column: u32,
8974/// which is a relative jump, based on the address following the reloc.
9075exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
9176
77reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
9278const_tracking: ConstTrackingMap = .{},
9379inst_tracking: InstTrackingMap = .{},
9480
......@@ -108,13 +94,11 @@ loops: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
10894 /// The state to restore before branching.
10995 state: State,
11096 /// The branch target.
111 jmp_target: Mir.Inst.Index,
97 target: Mir.Inst.Index,
11298}) = .{},
11399
114/// Debug field, used to find bugs in the compiler.
115air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
116
117const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
100next_temp_index: Temp.Index = @enumFromInt(0),
101temp_type: [Temp.Index.max]Type = undefined,
118102
119103const Owner = union(enum) {
120104 nav_index: InternPool.Nav.Index,
......@@ -433,7 +417,7 @@ pub const MCValue = union(enum) {
433417 .reserved_frame,
434418 .lea_symbol,
435419 => unreachable,
436 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
420 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
437421 .base = .{ .reg = .ds },
438422 .mod = .{ .rm = .{
439423 .size = size,
......@@ -484,8 +468,8 @@ pub const MCValue = union(enum) {
484468 .register_overflow => |pl| try writer.print("{s}:{s}", .{
485469 @tagName(pl.eflags), @tagName(pl.reg),
486470 }),
487 .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym_index, pl.off }),
488 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
471 .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
472 .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }),
489473 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
490474 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
491475 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
......@@ -562,7 +546,7 @@ const InstTracking = struct {
562546 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },
563547 else => unreachable,
564548 }
565 tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });
549 tracking_log.debug("spill {} from {} to {}", .{ inst, self.short, self.long });
566550 try function.genCopy(function.typeOfIndex(inst), self.long, self.short, .{});
567551 }
568552
......@@ -605,7 +589,7 @@ const InstTracking = struct {
605589 fn trackSpill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {
606590 try function.freeValue(self.short);
607591 self.reuseFrame();
608 tracking_log.debug("%{d} => {} (spilled)", .{ inst, self.* });
592 tracking_log.debug("{} => {} (spilled)", .{ inst, self.* });
609593 }
610594
611595 fn verifyMaterialize(self: InstTracking, target: InstTracking) void {
......@@ -678,14 +662,14 @@ const InstTracking = struct {
678662 else => target.long,
679663 } else target.long;
680664 self.short = target.short;
681 tracking_log.debug("%{d} => {} (materialize)", .{ inst, self.* });
665 tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });
682666 }
683667
684668 fn resurrect(self: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
685669 switch (self.short) {
686670 .dead => |die_generation| if (die_generation >= scope_generation) {
687671 self.reuseFrame();
688 tracking_log.debug("%{d} => {} (resurrect)", .{ inst, self.* });
672 tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });
689673 },
690674 else => {},
691675 }
......@@ -695,7 +679,7 @@ const InstTracking = struct {
695679 if (self.short == .dead) return;
696680 try function.freeValue(self.short);
697681 self.short = .{ .dead = function.scope_generation };
698 tracking_log.debug("%{d} => {} (death)", .{ inst, self.* });
682 tracking_log.debug("{} => {} (death)", .{ inst, self.* });
699683 }
700684
701685 fn reuse(
......@@ -705,16 +689,13 @@ const InstTracking = struct {
705689 old_inst: Air.Inst.Index,
706690 ) void {
707691 self.short = .{ .dead = function.scope_generation };
708 if (new_inst) |inst|
709 tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, self.*, old_inst })
710 else
711 tracking_log.debug("tmp => {} (reuse %{d})", .{ self.*, old_inst });
692 tracking_log.debug("{?} => {} (reuse {})", .{ new_inst, self.*, old_inst });
712693 }
713694
714695 fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void {
715696 for (self.getRegs()) |reg| {
716697 if (function.register_manager.isRegFree(reg)) {
717 tracking_log.debug("%{d} => {} (live-out)", .{ inst, self.* });
698 tracking_log.debug("{} => {} (live-out)", .{ inst, self.* });
718699 continue;
719700 }
720701
......@@ -741,7 +722,7 @@ const InstTracking = struct {
741722 // Perform side-effects of freeValue manually.
742723 function.register_manager.freeReg(reg);
743724
744 tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, self.*, tracked_inst });
725 tracking_log.debug("{} => {} (live-out {})", .{ inst, self.*, tracked_inst });
745726 }
746727 }
747728
......@@ -759,10 +740,10 @@ const InstTracking = struct {
759740const FrameAlloc = struct {
760741 abi_size: u31,
761742 spill_pad: u3,
762 abi_align: Alignment,
743 abi_align: InternPool.Alignment,
763744 ref_count: u16,
764745
765 fn init(alloc_abi: struct { size: u64, pad: u3 = 0, alignment: Alignment }) FrameAlloc {
746 fn init(alloc_abi: struct { size: u64, pad: u3 = 0, alignment: InternPool.Alignment }) FrameAlloc {
766747 return .{
767748 .abi_size = @intCast(alloc_abi.size),
768749 .spill_pad = alloc_abi.pad,
......@@ -779,14 +760,14 @@ const FrameAlloc = struct {
779760 fn initSpill(ty: Type, zcu: *Zcu) FrameAlloc {
780761 const abi_size = ty.abiSize(zcu);
781762 const spill_size = if (abi_size < 8)
782 math.ceilPowerOfTwoAssert(u64, abi_size)
763 std.math.ceilPowerOfTwoAssert(u64, abi_size)
783764 else
784765 std.mem.alignForward(u64, abi_size, 8);
785766 return init(.{
786767 .size = spill_size,
787768 .pad = @intCast(spill_size - abi_size),
788769 .alignment = ty.abiAlignment(zcu).maxStrict(
789 Alignment.fromNonzeroByteUnits(@min(spill_size, 8)),
770 InternPool.Alignment.fromNonzeroByteUnits(@min(spill_size, 8)),
790771 ),
791772 });
792773 }
......@@ -819,7 +800,7 @@ pub fn generate(
819800 liveness: Liveness,
820801 code: *std.ArrayListUnmanaged(u8),
821802 debug_output: link.File.DebugInfoOutput,
822) CodeGenError!void {
803) codegen.CodeGenError!void {
823804 const zcu = pt.zcu;
824805 const comp = zcu.comp;
825806 const gpa = zcu.gpa;
......@@ -862,6 +843,11 @@ pub fn generate(
862843 function.mir_instructions.deinit(gpa);
863844 function.mir_extra.deinit(gpa);
864845 }
846 try function.inst_tracking.ensureTotalCapacity(gpa, Temp.Index.max);
847 for (0..Temp.Index.max) |temp_index| {
848 const temp: Temp.Index = @enumFromInt(temp_index);
849 function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), InstTracking.init(.none));
850 }
865851
866852 wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});
867853
......@@ -891,9 +877,9 @@ pub fn generate(
891877 }));
892878 function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{
893879 .size = Type.usize.abiSize(zcu),
894 .alignment = Alignment.min(
880 .alignment = InternPool.Alignment.min(
895881 call_info.stack_align,
896 Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
882 InternPool.Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
897883 ),
898884 }));
899885 function.frame_allocs.set(
......@@ -972,7 +958,7 @@ pub fn generateLazy(
972958 lazy_sym: link.File.LazySymbol,
973959 code: *std.ArrayListUnmanaged(u8),
974960 debug_output: link.File.DebugInfoOutput,
975) CodeGenError!void {
961) codegen.CodeGenError!void {
976962 const comp = bin_file.comp;
977963 const gpa = comp.gpa;
978964 // This function is for generating global code, so we use the root module.
......@@ -1169,14 +1155,14 @@ fn formatWipMir(
11691155 lower.mir.extraData(Mir.Imm64, mir_inst.data.ai.i).data.decode(),
11701156 }),
11711157 .pseudo_dbg_local_as => {
1172 const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
1158 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
11731159 .base = .{ .reloc = mir_inst.data.as.sym_index },
11741160 }) };
11751161 try writer.print(" {}, {}", .{ mir_inst.data.as.air_inst, mem_op.fmt(.m) });
11761162 },
11771163 .pseudo_dbg_local_aso => {
11781164 const sym_off = lower.mir.extraData(bits.SymbolOffset, mir_inst.data.ax.payload).data;
1179 const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
1165 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
11801166 .base = .{ .reloc = sym_off.sym_index },
11811167 .disp = sym_off.off,
11821168 }) };
......@@ -1184,7 +1170,7 @@ fn formatWipMir(
11841170 },
11851171 .pseudo_dbg_local_aro => {
11861172 const air_off = lower.mir.extraData(Mir.AirOffset, mir_inst.data.rx.payload).data;
1187 const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
1173 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
11881174 .base = .{ .reg = mir_inst.data.rx.r1 },
11891175 .disp = air_off.off,
11901176 }) };
......@@ -1192,14 +1178,14 @@ fn formatWipMir(
11921178 },
11931179 .pseudo_dbg_local_af => {
11941180 const frame_addr = lower.mir.extraData(bits.FrameAddr, mir_inst.data.ax.payload).data;
1195 const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
1181 const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
11961182 .base = .{ .frame = frame_addr.index },
11971183 .disp = frame_addr.off,
11981184 }) };
1199 try writer.print(" {}, {d}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
1185 try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
12001186 },
12011187 .pseudo_dbg_local_am => {
1202 const mem_op: Instruction.Operand = .{
1188 const mem_op: encoder.Instruction.Operand = .{
12031189 .mem = lower.mir.extraData(Mir.Memory, mir_inst.data.ax.payload).data.decode(),
12041190 };
12051191 try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
......@@ -1221,7 +1207,7 @@ fn formatTracking(
12211207 writer: anytype,
12221208) @TypeOf(writer).Error!void {
12231209 var it = data.self.inst_tracking.iterator();
1224 while (it.next()) |entry| try writer.print("\n%{d} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });
1210 while (it.next()) |entry| try writer.print("\n{} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });
12251211}
12261212fn fmtTracking(self: *Self) std.fmt.Formatter(formatTracking) {
12271213 return .{ .data = .{ .self = self } };
......@@ -1427,7 +1413,7 @@ fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immed
14271413 .i = @bitCast(s),
14281414 } },
14291415 }),
1430 .unsigned => |u| _ = if (math.cast(u32, u)) |small| try self.addInst(.{
1416 .unsigned => |u| _ = if (std.math.cast(u32, u)) |small| try self.addInst(.{
14311417 .tag = .pseudo,
14321418 .ops = switch (tag) {
14331419 .dbg_local => .pseudo_dbg_local_ai_u,
......@@ -1632,7 +1618,7 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2
16321618fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {
16331619 const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {
16341620 .signed => |s| .{ .ri_s, @bitCast(s) },
1635 .unsigned => |u| if (math.cast(u32, u)) |small|
1621 .unsigned => |u| if (std.math.cast(u32, u)) |small|
16361622 .{ .ri_u, small }
16371623 else
16381624 .{ .ri_64, try self.addExtra(Mir.Imm64.encode(imm.unsigned)) },
......@@ -1831,8 +1817,8 @@ fn asmRegisterMemoryImmediate(
18311817 imm: Immediate,
18321818) !void {
18331819 if (switch (imm) {
1834 .signed => |s| if (math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
1835 .unsigned => |u| math.cast(u16, u),
1820 .signed => |s| if (std.math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
1821 .unsigned => |u| std.math.cast(u16, u),
18361822 .reloc => unreachable,
18371823 }) |small_imm| {
18381824 _ = try self.addInst(.{
......@@ -1967,8 +1953,8 @@ fn gen(self: *Self) InnerError!void {
19671953 const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
19681954 if (cc != .naked) {
19691955 try self.asmRegister(.{ ._, .push }, .rbp);
1970 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8));
1971 try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0));
1956 try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, .s(8));
1957 try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, .s(0));
19721958 try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
19731959 try self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, .rbp);
19741960 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
......@@ -2016,7 +2002,7 @@ fn gen(self: *Self) InnerError!void {
20162002 .{},
20172003 );
20182004
2019 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, Immediate.u(info.fp_count));
2005 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, .u(info.fp_count));
20202006 const skip_sse_reloc = try self.asmJccReloc(.na, undefined);
20212007
20222008 const vec_2_f64 = try pt.vectorType(.{ .len = 2, .child = .f64_type });
......@@ -2055,15 +2041,15 @@ fn gen(self: *Self) InnerError!void {
20552041 const backpatch_stack_dealloc = try self.asmPlaceholder();
20562042 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
20572043 try self.asmRegister(.{ ._, .pop }, .rbp);
2058 try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, Immediate.s(8));
2044 try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, .s(8));
20592045 try self.asmOpOnly(.{ ._, .ret });
20602046
20612047 const frame_layout = try self.computeFrameLayout(cc);
2062 const need_frame_align = frame_layout.stack_mask != math.maxInt(u32);
2048 const need_frame_align = frame_layout.stack_mask != std.math.maxInt(u32);
20632049 const need_stack_adjust = frame_layout.stack_adjust > 0;
20642050 const need_save_reg = frame_layout.save_reg_list.count() > 0;
20652051 if (need_frame_align) {
2066 const page_align = @as(u32, math.maxInt(u32)) << 12;
2052 const page_align = @as(u32, std.math.maxInt(u32)) << 12;
20672053 self.mir_instructions.set(backpatch_frame_align, .{
20682054 .tag = .@"and",
20692055 .ops = .ri_s,
......@@ -2170,23 +2156,18 @@ fn gen(self: *Self) InnerError!void {
21702156 });
21712157}
21722158
2173fn checkInvariantsAfterAirInst(self: *Self, inst: Air.Inst.Index, old_air_bookkeeping: @TypeOf(air_bookkeeping_init)) void {
2159fn checkInvariantsAfterAirInst(self: *Self) void {
21742160 assert(!self.register_manager.lockedRegsExist());
21752161
21762162 if (std.debug.runtime_safety) {
2177 if (self.air_bookkeeping < old_air_bookkeeping + 1) {
2178 std.debug.panic("in codegen.zig, handling of AIR instruction %{d} ('{}') did not do proper bookkeeping. Look for a missing call to finishAir.", .{ inst, self.air.instructions.items(.tag)[@intFromEnum(inst)] });
2179 }
2180
2181 { // check consistency of tracked registers
2182 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
2183 while (it.next()) |index| {
2184 const tracked_inst = self.register_manager.registers[index];
2185 const tracking = self.getResolvedInstValue(tracked_inst);
2186 for (tracking.getRegs()) |reg| {
2187 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
2188 } else unreachable; // tracked register not in use
2189 }
2163 // check consistency of tracked registers
2164 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
2165 while (it.next()) |index| {
2166 const tracked_inst = self.register_manager.registers[index];
2167 const tracking = self.getResolvedInstValue(tracked_inst);
2168 for (tracking.getRegs()) |reg| {
2169 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
2170 } else unreachable; // tracked register not in use
21902171 }
21912172 }
21922173}
......@@ -2202,6 +2183,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
22022183 const zcu = pt.zcu;
22032184 const ip = &zcu.intern_pool;
22042185 const air_tags = self.air.instructions.items(.tag);
2186 const air_datas = self.air.instructions.items(.data);
2187 const use_old = self.target.ofmt == .coff;
22052188
22062189 self.arg_index = 0;
22072190 for (body) |inst| switch (air_tags[@intFromEnum(inst)]) {
......@@ -2209,12 +2192,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
22092192 wip_mir_log.debug("{}", .{self.fmtAir(inst)});
22102193 verbose_tracking_log.debug("{}", .{self.fmtTracking()});
22112194
2212 const old_air_bookkeeping = self.air_bookkeeping;
2195 self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
22132196 try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);
22142197
22152198 try self.airArg(inst);
22162199
2217 self.checkInvariantsAfterAirInst(inst, old_air_bookkeeping);
2200 self.resetTemps();
2201 self.checkInvariantsAfterAirInst();
22182202 },
22192203 else => break,
22202204 };
......@@ -2226,7 +2210,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
22262210 wip_mir_log.debug("{}", .{self.fmtAir(inst)});
22272211 verbose_tracking_log.debug("{}", .{self.fmtTracking()});
22282212
2229 const old_air_bookkeeping = self.air_bookkeeping;
2213 self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
22302214 try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);
22312215 switch (air_tags[@intFromEnum(inst)]) {
22322216 // zig fmt: off
......@@ -2260,7 +2244,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
22602244 .sub_sat => try self.airSubSat(inst),
22612245 .mul_sat => try self.airMulSat(inst),
22622246 .shl_sat => try self.airShlSat(inst),
2263 .slice => try self.airSlice(inst),
22642247
22652248 .sin,
22662249 .cos,
......@@ -2298,127 +2281,58 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
22982281 .cmp_vector => try self.airCmpVector(inst),
22992282 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
23002283
2301 .alloc => try self.airAlloc(inst),
2302 .ret_ptr => try self.airRetPtr(inst),
2303 .arg => try self.airDbgArg(inst),
2304 .assembly => try self.airAsm(inst),
2305 .bitcast => try self.airBitCast(inst),
2306 .block => try self.airBlock(inst),
2307 .br => try self.airBr(inst),
2308 .repeat => try self.airRepeat(inst),
2309 .switch_dispatch => try self.airSwitchDispatch(inst),
2310 .trap => try self.airTrap(),
2311 .breakpoint => try self.airBreakpoint(),
2312 .ret_addr => try self.airRetAddr(inst),
2313 .frame_addr => try self.airFrameAddress(inst),
2314 .cond_br => try self.airCondBr(inst),
2315 .fptrunc => try self.airFptrunc(inst),
2316 .fpext => try self.airFpext(inst),
2317 .intcast => try self.airIntCast(inst),
2318 .trunc => try self.airTrunc(inst),
2319 .int_from_bool => try self.airIntFromBool(inst),
2320 .is_non_null => try self.airIsNonNull(inst),
2321 .is_non_null_ptr => try self.airIsNonNullPtr(inst),
2322 .is_null => try self.airIsNull(inst),
2323 .is_null_ptr => try self.airIsNullPtr(inst),
2324 .is_non_err => try self.airIsNonErr(inst),
2325 .is_non_err_ptr => try self.airIsNonErrPtr(inst),
2326 .is_err => try self.airIsErr(inst),
2327 .is_err_ptr => try self.airIsErrPtr(inst),
2328 .load => try self.airLoad(inst),
2329 .loop => try self.airLoop(inst),
2330 .int_from_ptr => try self.airIntFromPtr(inst),
2331 .ret => try self.airRet(inst, false),
2332 .ret_safe => try self.airRet(inst, true),
2333 .ret_load => try self.airRetLoad(inst),
2334 .store => try self.airStore(inst, false),
2335 .store_safe => try self.airStore(inst, true),
2336 .struct_field_ptr=> try self.airStructFieldPtr(inst),
2337 .struct_field_val=> try self.airStructFieldVal(inst),
2338 .array_to_slice => try self.airArrayToSlice(inst),
2339 .float_from_int => try self.airFloatFromInt(inst),
2340 .int_from_float => try self.airIntFromFloat(inst),
2341 .cmpxchg_strong => try self.airCmpxchg(inst),
2342 .cmpxchg_weak => try self.airCmpxchg(inst),
2343 .atomic_rmw => try self.airAtomicRmw(inst),
2344 .atomic_load => try self.airAtomicLoad(inst),
2345 .memcpy => try self.airMemcpy(inst),
2346 .memset => try self.airMemset(inst, false),
2347 .memset_safe => try self.airMemset(inst, true),
2348 .set_union_tag => try self.airSetUnionTag(inst),
2349 .get_union_tag => try self.airGetUnionTag(inst),
2350 .clz => try self.airClz(inst),
2351 .ctz => try self.airCtz(inst),
2352 .popcount => try self.airPopCount(inst),
2353 .byte_swap => try self.airByteSwap(inst),
2354 .bit_reverse => try self.airBitReverse(inst),
2355 .tag_name => try self.airTagName(inst),
2356 .error_name => try self.airErrorName(inst),
2357 .splat => try self.airSplat(inst),
2358 .select => try self.airSelect(inst),
2359 .shuffle => try self.airShuffle(inst),
2360 .reduce => try self.airReduce(inst),
2361 .aggregate_init => try self.airAggregateInit(inst),
2362 .union_init => try self.airUnionInit(inst),
2363 .prefetch => try self.airPrefetch(inst),
2364 .mul_add => try self.airMulAdd(inst),
2365 .addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}),
2366
2367 .@"try" => try self.airTry(inst),
2368 .try_cold => try self.airTry(inst), // TODO
2369 .try_ptr => try self.airTryPtr(inst),
2370 .try_ptr_cold => try self.airTryPtr(inst), // TODO
2371
2372 .dbg_stmt => try self.airDbgStmt(inst),
2373 .dbg_empty_stmt => try self.airDbgEmptyStmt(),
2374 .dbg_inline_block => try self.airDbgInlineBlock(inst),
2375 .dbg_var_ptr,
2376 .dbg_var_val,
2377 .dbg_arg_inline,
2378 => try self.airDbgVar(inst),
2379
2380 .call => try self.airCall(inst, .auto),
2381 .call_always_tail => try self.airCall(inst, .always_tail),
2382 .call_never_tail => try self.airCall(inst, .never_tail),
2383 .call_never_inline => try self.airCall(inst, .never_inline),
2284 .bitcast => try self.airBitCast(inst),
2285 .fptrunc => try self.airFptrunc(inst),
2286 .fpext => try self.airFpext(inst),
2287 .intcast => try self.airIntCast(inst),
2288 .trunc => try self.airTrunc(inst),
2289 .is_non_null => try self.airIsNonNull(inst),
2290 .is_null => try self.airIsNull(inst),
2291 .is_non_err => try self.airIsNonErr(inst),
2292 .is_err => try self.airIsErr(inst),
2293 .load => try self.airLoad(inst),
2294 .store => try self.airStore(inst, false),
2295 .store_safe => try self.airStore(inst, true),
2296 .struct_field_val => try self.airStructFieldVal(inst),
2297 .float_from_int => try self.airFloatFromInt(inst),
2298 .int_from_float => try self.airIntFromFloat(inst),
2299 .cmpxchg_strong => try self.airCmpxchg(inst),
2300 .cmpxchg_weak => try self.airCmpxchg(inst),
2301 .atomic_rmw => try self.airAtomicRmw(inst),
2302 .atomic_load => try self.airAtomicLoad(inst),
2303 .memcpy => try self.airMemcpy(inst),
2304 .memset => try self.airMemset(inst, false),
2305 .memset_safe => try self.airMemset(inst, true),
2306 .set_union_tag => try self.airSetUnionTag(inst),
2307 .get_union_tag => try self.airGetUnionTag(inst),
2308 .clz => try self.airClz(inst),
2309 .ctz => try self.airCtz(inst),
2310 .popcount => try self.airPopCount(inst),
2311 .byte_swap => try self.airByteSwap(inst),
2312 .bit_reverse => try self.airBitReverse(inst),
2313 .tag_name => try self.airTagName(inst),
2314 .error_name => try self.airErrorName(inst),
2315 .splat => try self.airSplat(inst),
2316 .select => try self.airSelect(inst),
2317 .shuffle => try self.airShuffle(inst),
2318 .reduce => try self.airReduce(inst),
2319 .aggregate_init => try self.airAggregateInit(inst),
2320 .union_init => try self.airUnionInit(inst),
2321 .prefetch => try self.airPrefetch(inst),
2322 .mul_add => try self.airMulAdd(inst),
23842323
23852324 .atomic_store_unordered => try self.airAtomicStore(inst, .unordered),
23862325 .atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),
23872326 .atomic_store_release => try self.airAtomicStore(inst, .release),
23882327 .atomic_store_seq_cst => try self.airAtomicStore(inst, .seq_cst),
23892328
2390 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
2391 .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
2392 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
2393 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
2394
2395 .field_parent_ptr => try self.airFieldParentPtr(inst),
2396
2397 .switch_br => try self.airSwitchBr(inst),
2398 .loop_switch_br => try self.airLoopSwitchBr(inst),
2399 .slice_ptr => try self.airSlicePtr(inst),
2400 .slice_len => try self.airSliceLen(inst),
2401
2402 .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst),
2403 .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst),
2404
24052329 .array_elem_val => try self.airArrayElemVal(inst),
24062330 .slice_elem_val => try self.airSliceElemVal(inst),
2407 .slice_elem_ptr => try self.airSliceElemPtr(inst),
24082331 .ptr_elem_val => try self.airPtrElemVal(inst),
2409 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
2410
2411 .inferred_alloc, .inferred_alloc_comptime => unreachable,
2412 .unreach => self.finishAirBookkeeping(),
24132332
24142333 .optional_payload => try self.airOptionalPayload(inst),
2415 .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
2416 .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),
24172334 .unwrap_errunion_err => try self.airUnwrapErrUnionErr(inst),
24182335 .unwrap_errunion_payload => try self.airUnwrapErrUnionPayload(inst),
2419 .unwrap_errunion_err_ptr => try self.airUnwrapErrUnionErrPtr(inst),
2420 .unwrap_errunion_payload_ptr=> try self.airUnwrapErrUnionPayloadPtr(inst),
2421 .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
24222336 .err_return_trace => try self.airErrReturnTrace(inst),
24232337 .set_err_return_trace => try self.airSetErrReturnTrace(inst),
24242338 .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
......@@ -2426,7 +2340,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
24262340 .wrap_optional => try self.airWrapOptional(inst),
24272341 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
24282342 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
2343 // zig fmt: on
24292344
2345 .add_safe,
2346 .sub_safe,
2347 .mul_safe,
2348 => return self.fail("TODO implement safety_checked_instructions", .{}),
24302349 .add_optimized,
24312350 .sub_optimized,
24322351 .mul_optimized,
......@@ -2448,13 +2367,429 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
24482367 .int_from_float_optimized,
24492368 => return self.fail("TODO implement optimized float mode", .{}),
24502369
2451 .add_safe,
2452 .sub_safe,
2453 .mul_safe,
2454 => return self.fail("TODO implement safety_checked_instructions", .{}),
2370 .arg => try self.airDbgArg(inst),
2371 .alloc => if (use_old) try self.airAlloc(inst) else {
2372 var slot = try self.tempFromValue(self.typeOfIndex(inst), .{ .lea_frame = .{
2373 .index = try self.allocMemPtr(inst),
2374 } });
2375 try slot.moveTo(inst, self);
2376 },
2377 .inferred_alloc => unreachable,
2378 .inferred_alloc_comptime => unreachable,
2379 .ret_ptr => if (use_old) try self.airRetPtr(inst) else {
2380 var slot = switch (self.ret_mcv.long) {
2381 else => unreachable,
2382 .none => try self.tempFromValue(self.typeOfIndex(inst), .{ .lea_frame = .{
2383 .index = try self.allocMemPtr(inst),
2384 } }),
2385 .load_frame => slot: {
2386 var slot = try self.tempFromValue(self.typeOfIndex(inst), self.ret_mcv.long);
2387 try slot.toOffset(self.ret_mcv.short.indirect.off, self);
2388 break :slot slot;
2389 },
2390 };
2391 try slot.moveTo(inst, self);
2392 },
2393 .assembly => try self.airAsm(inst),
2394 .block => if (use_old) try self.airBlock(inst) else {
2395 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2396 const extra = self.air.extraData(Air.Block, ty_pl.payload);
2397 try self.asmPseudo(.pseudo_dbg_enter_block_none);
2398 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
2399 try self.asmPseudo(.pseudo_dbg_leave_block_none);
2400 },
2401 .loop => if (use_old) try self.airLoop(inst) else {
2402 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2403 const extra = self.air.extraData(Air.Block, ty_pl.payload);
2404 self.scope_generation += 1;
2405 try self.loops.putNoClobber(self.gpa, inst, .{
2406 .state = try self.saveState(),
2407 .target = @intCast(self.mir_instructions.len),
2408 });
2409 defer assert(self.loops.remove(inst));
2410 try self.genBodyBlock(@ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
2411 },
2412 .repeat => if (use_old) try self.airRepeat(inst) else {
2413 const repeat = air_datas[@intFromEnum(inst)].repeat;
2414 const loop = self.loops.get(repeat.loop_inst).?;
2415 try self.restoreState(loop.state, &.{}, .{
2416 .emit_instructions = true,
2417 .update_tracking = false,
2418 .resurrect = false,
2419 .close_scope = true,
2420 });
2421 _ = try self.asmJmpReloc(loop.target);
2422 },
2423 .br => try self.airBr(inst),
2424 .trap => try self.asmOpOnly(.{ ._, .ud2 }),
2425 .breakpoint => try self.asmOpOnly(.{ ._, .int3 }),
2426 .ret_addr => if (use_old) try self.airRetAddr(inst) else {
2427 var slot = try self.tempFromValue(self.typeOfIndex(inst), .{ .load_frame = .{
2428 .index = .ret_addr,
2429 } });
2430 while (try slot.toAnyReg(self)) {}
2431 try slot.moveTo(inst, self);
2432 },
2433 .frame_addr => if (use_old) try self.airFrameAddress(inst) else {
2434 var slot = try self.tempFromValue(self.typeOfIndex(inst), .{ .lea_frame = .{
2435 .index = .base_ptr,
2436 } });
2437 try slot.moveTo(inst, self);
2438 },
2439 .call => try self.airCall(inst, .auto),
2440 .call_always_tail => try self.airCall(inst, .always_tail),
2441 .call_never_tail => try self.airCall(inst, .never_tail),
2442 .call_never_inline => try self.airCall(inst, .never_inline),
24552443
2456 .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
2444 .cond_br => try self.airCondBr(inst),
2445 .switch_br => try self.airSwitchBr(inst),
2446 .loop_switch_br => try self.airLoopSwitchBr(inst),
2447 .switch_dispatch => try self.airSwitchDispatch(inst),
2448 .@"try", .try_cold => try self.airTry(inst),
2449 .try_ptr, .try_ptr_cold => try self.airTryPtr(inst),
2450 .dbg_stmt => if (use_old) try self.airDbgStmt(inst) else {
2451 const dbg_stmt = air_datas[@intFromEnum(inst)].dbg_stmt;
2452 _ = try self.addInst(.{
2453 .tag = .pseudo,
2454 .ops = .pseudo_dbg_line_line_column,
2455 .data = .{ .line_column = .{
2456 .line = dbg_stmt.line,
2457 .column = dbg_stmt.column,
2458 } },
2459 });
2460 },
2461 .dbg_empty_stmt => if (use_old) try self.airDbgEmptyStmt() else {
2462 if (self.mir_instructions.len > 0) {
2463 const prev_mir_op = &self.mir_instructions.items(.ops)[self.mir_instructions.len - 1];
2464 if (prev_mir_op.* == .pseudo_dbg_line_stmt_line_column)
2465 prev_mir_op.* = .pseudo_dbg_line_line_column;
2466 }
2467 try self.asmOpOnly(.{ ._, .nop });
2468 },
2469 .dbg_inline_block => if (use_old) try self.airDbgInlineBlock(inst) else {
2470 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2471 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
2472 const old_inline_func = self.inline_func;
2473 defer self.inline_func = old_inline_func;
2474 self.inline_func = extra.data.func;
2475 _ = try self.addInst(.{
2476 .tag = .pseudo,
2477 .ops = .pseudo_dbg_enter_inline_func,
2478 .data = .{ .func = extra.data.func },
2479 });
2480 try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
2481 _ = try self.addInst(.{
2482 .tag = .pseudo,
2483 .ops = .pseudo_dbg_leave_inline_func,
2484 .data = .{ .func = old_inline_func },
2485 });
2486 },
2487 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => if (use_old) try self.airDbgVar(inst) else {
2488 const pl_op = air_datas[@intFromEnum(inst)].pl_op;
2489 var ops = try self.tempsFromOperands(inst, .{pl_op.operand});
2490 try self.genLocalDebugInfo(inst, ops[0].tracking(self).short);
2491 try ops[0].die(self);
2492 },
2493 .is_null_ptr => if (use_old) try self.airIsNullPtr(inst) else {
2494 const un_op = air_datas[@intFromEnum(inst)].un_op;
2495 const opt_ty = self.typeOf(un_op).childType(zcu);
2496 const opt_repr_is_pl = opt_ty.optionalReprIsPayload(zcu);
2497 const opt_child_ty = opt_ty.optionalChild(zcu);
2498 const opt_child_abi_size: u31 = @intCast(opt_child_ty.abiSize(zcu));
2499 var ops = try self.tempsFromOperands(inst, .{un_op});
2500 if (!opt_repr_is_pl) try ops[0].toOffset(opt_child_abi_size, self);
2501 while (try ops[0].toLea(self)) {}
2502 try self.asmMemoryImmediate(
2503 .{ ._, .cmp },
2504 try ops[0].tracking(self).short.deref().mem(self, if (!opt_repr_is_pl)
2505 .byte
2506 else if (opt_child_ty.isSlice(zcu))
2507 .qword
2508 else
2509 Memory.Size.fromSize(opt_child_abi_size)),
2510 .u(0),
2511 );
2512 var is_null = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .e });
2513 try ops[0].die(self);
2514 try is_null.moveTo(inst, self);
2515 },
2516 .is_non_null_ptr => if (use_old) try self.airIsNonNullPtr(inst) else {
2517 const un_op = air_datas[@intFromEnum(inst)].un_op;
2518 const opt_ty = self.typeOf(un_op).childType(zcu);
2519 const opt_repr_is_pl = opt_ty.optionalReprIsPayload(zcu);
2520 const opt_child_ty = opt_ty.optionalChild(zcu);
2521 const opt_child_abi_size: u31 = @intCast(opt_child_ty.abiSize(zcu));
2522 var ops = try self.tempsFromOperands(inst, .{un_op});
2523 if (!opt_repr_is_pl) try ops[0].toOffset(opt_child_abi_size, self);
2524 while (try ops[0].toLea(self)) {}
2525 try self.asmMemoryImmediate(
2526 .{ ._, .cmp },
2527 try ops[0].tracking(self).short.deref().mem(self, if (!opt_repr_is_pl)
2528 .byte
2529 else if (opt_child_ty.isSlice(zcu))
2530 .qword
2531 else
2532 Memory.Size.fromSize(opt_child_abi_size)),
2533 .u(0),
2534 );
2535 var is_non_null = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .ne });
2536 try ops[0].die(self);
2537 try is_non_null.moveTo(inst, self);
2538 },
2539 .is_err_ptr => if (use_old) try self.airIsErrPtr(inst) else {
2540 const un_op = air_datas[@intFromEnum(inst)].un_op;
2541 const eu_ty = self.typeOf(un_op).childType(zcu);
2542 const eu_err_ty = eu_ty.errorUnionSet(zcu);
2543 const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
2544 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
2545 var ops = try self.tempsFromOperands(inst, .{un_op});
2546 try ops[0].toOffset(eu_err_off, self);
2547 while (try ops[0].toLea(self)) {}
2548 try self.asmMemoryImmediate(
2549 .{ ._, .cmp },
2550 try ops[0].tracking(self).short.deref().mem(self, self.memSize(eu_err_ty)),
2551 .u(0),
2552 );
2553 var is_err = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .ne });
2554 try ops[0].die(self);
2555 try is_err.moveTo(inst, self);
2556 },
2557 .is_non_err_ptr => if (use_old) try self.airIsNonErrPtr(inst) else {
2558 const un_op = air_datas[@intFromEnum(inst)].un_op;
2559 const eu_ty = self.typeOf(un_op).childType(zcu);
2560 const eu_err_ty = eu_ty.errorUnionSet(zcu);
2561 const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
2562 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
2563 var ops = try self.tempsFromOperands(inst, .{un_op});
2564 try ops[0].toOffset(eu_err_off, self);
2565 while (try ops[0].toLea(self)) {}
2566 try self.asmMemoryImmediate(
2567 .{ ._, .cmp },
2568 try ops[0].tracking(self).short.deref().mem(self, self.memSize(eu_err_ty)),
2569 .u(0),
2570 );
2571 var is_non_err = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .e });
2572 try ops[0].die(self);
2573 try is_non_err.moveTo(inst, self);
2574 },
2575 .int_from_ptr => if (use_old) try self.airIntFromPtr(inst) else {
2576 const un_op = air_datas[@intFromEnum(inst)].un_op;
2577 var ops = try self.tempsFromOperands(inst, .{un_op});
2578 try ops[0].toLimb(0, self);
2579 try ops[0].moveTo(inst, self);
2580 },
2581 .int_from_bool => if (use_old) try self.airIntFromBool(inst) else {
2582 const un_op = air_datas[@intFromEnum(inst)].un_op;
2583 var ops = try self.tempsFromOperands(inst, .{un_op});
2584 try ops[0].moveTo(inst, self);
2585 },
2586 .ret => try self.airRet(inst, false),
2587 .ret_safe => try self.airRet(inst, true),
2588 .ret_load => try self.airRetLoad(inst),
2589 .unreach => {},
2590 .optional_payload_ptr => if (use_old) try self.airOptionalPayloadPtr(inst) else {
2591 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2592 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2593 try ops[0].moveTo(inst, self);
2594 },
2595 .optional_payload_ptr_set => if (use_old) try self.airOptionalPayloadPtrSet(inst) else {
2596 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2597 const opt_ty = self.typeOf(ty_op.operand).childType(zcu);
2598 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2599 if (!opt_ty.optionalReprIsPayload(zcu)) {
2600 const opt_child_ty = opt_ty.optionalChild(zcu);
2601 const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu));
2602 try ops[0].toOffset(opt_child_abi_size, self);
2603 var has_value = try self.tempFromValue(Type.bool, .{ .immediate = 1 });
2604 try ops[0].store(&has_value, self);
2605 try has_value.die(self);
2606 try ops[0].toOffset(-opt_child_abi_size, self);
2607 }
2608 try ops[0].moveTo(inst, self);
2609 },
2610 .unwrap_errunion_payload_ptr => if (use_old) try self.airUnwrapErrUnionPayloadPtr(inst) else {
2611 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2612 const eu_ty = self.typeOf(ty_op.operand).childType(zcu);
2613 const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
2614 const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));
2615 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2616 try ops[0].toOffset(eu_pl_off, self);
2617 try ops[0].moveTo(inst, self);
2618 },
2619 .unwrap_errunion_err_ptr => if (use_old) try self.airUnwrapErrUnionErrPtr(inst) else {
2620 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2621 const eu_ty = self.typeOf(ty_op.operand).childType(zcu);
2622 const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
2623 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
2624 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2625 try ops[0].toOffset(eu_err_off, self);
2626 var err = try ops[0].load(eu_ty.errorUnionSet(zcu), self);
2627 try ops[0].die(self);
2628 try err.moveTo(inst, self);
2629 },
2630 .errunion_payload_ptr_set => if (use_old) try self.airErrUnionPayloadPtrSet(inst) else {
2631 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2632 const eu_ty = self.typeOf(ty_op.operand).childType(zcu);
2633 const eu_err_ty = eu_ty.errorUnionSet(zcu);
2634 const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
2635 const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
2636 const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));
2637 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2638 try ops[0].toOffset(eu_err_off, self);
2639 var no_err = try self.tempFromValue(eu_err_ty, .{ .immediate = 0 });
2640 try ops[0].store(&no_err, self);
2641 try no_err.die(self);
2642 try ops[0].toOffset(eu_pl_off - eu_err_off, self);
2643 try ops[0].moveTo(inst, self);
2644 },
2645 .struct_field_ptr => if (use_old) try self.airStructFieldPtr(inst) else {
2646 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2647 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
2648 var ops = try self.tempsFromOperands(inst, .{extra.struct_operand});
2649 try ops[0].toOffset(self.fieldOffset(self.typeOf(extra.struct_operand), self.typeOfIndex(inst), extra.field_index), self);
2650 try ops[0].moveTo(inst, self);
2651 },
2652 .struct_field_ptr_index_0 => if (use_old) try self.airStructFieldPtrIndex(inst, 0) else {
2653 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2654 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2655 try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 0), self);
2656 try ops[0].moveTo(inst, self);
2657 },
2658 .struct_field_ptr_index_1 => if (use_old) try self.airStructFieldPtrIndex(inst, 1) else {
2659 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2660 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2661 try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 1), self);
2662 try ops[0].moveTo(inst, self);
2663 },
2664 .struct_field_ptr_index_2 => if (use_old) try self.airStructFieldPtrIndex(inst, 2) else {
2665 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2666 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2667 try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 2), self);
2668 try ops[0].moveTo(inst, self);
2669 },
2670 .struct_field_ptr_index_3 => if (use_old) try self.airStructFieldPtrIndex(inst, 3) else {
2671 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2672 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2673 try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 3), self);
2674 try ops[0].moveTo(inst, self);
2675 },
2676 .slice => if (use_old) try self.airSlice(inst) else {
2677 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2678 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2679 var ops = try self.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2680 try ops[0].toPair(&ops[1], self);
2681 try ops[0].moveTo(inst, self);
2682 },
2683 .slice_len => if (use_old) try self.airSliceLen(inst) else {
2684 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2685 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2686 try ops[0].toLimb(1, self);
2687 try ops[0].moveTo(inst, self);
2688 },
2689 .slice_ptr => if (use_old) try self.airSlicePtr(inst) else {
2690 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2691 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2692 try ops[0].toLimb(0, self);
2693 try ops[0].moveTo(inst, self);
2694 },
2695 .ptr_slice_len_ptr => if (use_old) try self.airPtrSliceLenPtr(inst) else {
2696 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2697 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2698 try ops[0].toOffset(8, self);
2699 try ops[0].moveTo(inst, self);
2700 },
2701 .ptr_slice_ptr_ptr => if (use_old) try self.airPtrSlicePtrPtr(inst) else {
2702 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2703 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2704 try ops[0].toOffset(0, self);
2705 try ops[0].moveTo(inst, self);
2706 },
2707 .slice_elem_ptr, .ptr_elem_ptr => |tag| if (use_old) switch (tag) {
2708 else => unreachable,
2709 .slice_elem_ptr => try self.airSliceElemPtr(inst),
2710 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
2711 } else {
2712 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2713 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2714 var ops = try self.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
2715 switch (tag) {
2716 else => unreachable,
2717 .slice_elem_ptr => try ops[0].toLimb(0, self),
2718 .ptr_elem_ptr => {},
2719 }
2720 const dst_ty = self.typeOfIndex(inst);
2721 if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {
2722 const elem_size = dst_ty.childType(zcu).abiSize(zcu);
2723 if (elem_size == 0) break :zero_offset;
2724 while (true) for (&ops) |*op| {
2725 if (try op.toAnyReg(self)) break;
2726 } else break;
2727 const lhs_reg = ops[0].unwrap(self).temp.tracking(self).short.register.to64();
2728 const rhs_reg = ops[1].unwrap(self).temp.tracking(self).short.register.to64();
2729 if (!std.math.isPowerOfTwo(elem_size)) {
2730 try self.spillEflagsIfOccupied();
2731 try self.asmRegisterRegisterImmediate(
2732 .{ .i_, .mul },
2733 rhs_reg,
2734 rhs_reg,
2735 .u(elem_size),
2736 );
2737 try self.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
2738 .base = .{ .reg = lhs_reg },
2739 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
2740 });
2741 } else if (elem_size > 8) {
2742 try self.spillEflagsIfOccupied();
2743 try self.asmRegisterImmediate(
2744 .{ ._l, .sh },
2745 rhs_reg,
2746 .u(std.math.log2_int(u64, elem_size)),
2747 );
2748 try self.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
2749 .base = .{ .reg = lhs_reg },
2750 .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
2751 });
2752 } else try self.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
2753 .base = .{ .reg = lhs_reg },
2754 .mod = .{ .rm = .{
2755 .size = .qword,
2756 .index = rhs_reg,
2757 .scale = .fromFactor(@intCast(elem_size)),
2758 } },
2759 });
2760 }
2761 try ops[1].die(self);
2762 try ops[0].moveTo(inst, self);
2763 },
2764 .array_to_slice => if (use_old) try self.airArrayToSlice(inst) else {
2765 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2766 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2767 var len = try self.tempFromValue(Type.usize, .{
2768 .immediate = self.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),
2769 });
2770 try ops[0].toPair(&len, self);
2771 try ops[0].moveTo(inst, self);
2772 },
24572773 .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),
2774 .field_parent_ptr => if (use_old) try self.airFieldParentPtr(inst) else {
2775 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
2776 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
2777 var ops = try self.tempsFromOperands(inst, .{extra.field_ptr});
2778 try ops[0].toOffset(-self.fieldOffset(self.typeOfIndex(inst), self.typeOf(extra.field_ptr), extra.field_index), self);
2779 try ops[0].moveTo(inst, self);
2780 },
2781
2782 .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
2783
2784 .wasm_memory_size => unreachable,
2785 .wasm_memory_grow => unreachable,
2786
2787 .addrspace_cast => {
2788 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
2789 var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
2790 try ops[0].moveTo(inst, self);
2791 },
2792
24582793 .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),
24592794
24602795 .c_va_arg => try self.airVaArg(inst),
......@@ -2462,15 +2797,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
24622797 .c_va_end => try self.airVaEnd(inst),
24632798 .c_va_start => try self.airVaStart(inst),
24642799
2465 .wasm_memory_size => unreachable,
2466 .wasm_memory_grow => unreachable,
2467
24682800 .work_item_id => unreachable,
24692801 .work_group_size => unreachable,
24702802 .work_group_id => unreachable,
2471 // zig fmt: on
24722803 }
2473 self.checkInvariantsAfterAirInst(inst, old_air_bookkeeping);
2804 self.resetTemps();
2805 self.checkInvariantsAfterAirInst();
24742806 }
24752807 verbose_tracking_log.debug("{}", .{self.fmtTracking()});
24762808}
......@@ -2530,7 +2862,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
25302862 data_off += @intCast(tag_name_len + 1);
25312863 }
25322864
2533 try self.airTrap();
2865 try self.asmOpOnly(.{ ._, .ud2 });
25342866
25352867 for (exitlude_jump_relocs) |reloc| self.performReloc(reloc);
25362868 try self.asmOpOnly(.{ ._, .ret });
......@@ -2544,6 +2876,10 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
25442876
25452877fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) !void {
25462878 for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst);
2879 switch (value) {
2880 else => {},
2881 .eflags, .register_overflow => self.eflags_inst = inst,
2882 }
25472883}
25482884
25492885fn getValueIfFree(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {
......@@ -2577,26 +2913,18 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) !void {
25772913 try self.inst_tracking.getPtr(inst).?.die(self, inst);
25782914}
25792915
2580/// Called when there are no operands, and the instruction is always unreferenced.
2581fn finishAirBookkeeping(self: *Self) void {
2582 if (std.debug.runtime_safety) {
2583 self.air_bookkeeping += 1;
2584 }
2585}
2586
25872916fn finishAirResult(self: *Self, inst: Air.Inst.Index, result: MCValue) void {
25882917 if (self.liveness.isUnused(inst) and self.air.instructions.items(.tag)[@intFromEnum(inst)] != .arg) switch (result) {
25892918 .none, .dead, .unreach => {},
25902919 else => unreachable, // Why didn't the result die?
25912920 } else {
2592 tracking_log.debug("%{d} => {} (birth)", .{ inst, result });
2921 tracking_log.debug("{} => {} (birth)", .{ inst, result });
25932922 self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));
25942923 // In some cases, an operand may be reused as the result.
25952924 // If that operand died and was a register, it was freed by
25962925 // processDeath, so we have to "re-allocate" the register.
25972926 self.getValueIfFree(result, inst);
25982927 }
2599 self.finishAirBookkeeping();
26002928}
26012929
26022930fn finishAir(
......@@ -2605,11 +2933,10 @@ fn finishAir(
26052933 result: MCValue,
26062934 operands: [Liveness.bpi - 1]Air.Inst.Ref,
26072935) !void {
2608 var tomb_bits = self.liveness.getTombBits(inst);
2609 for (operands) |op| {
2610 const dies = @as(u1, @truncate(tomb_bits)) != 0;
2611 tomb_bits >>= 1;
2612 if (!dies) continue;
2936 const tomb_bits = self.liveness.getTombBits(inst);
2937 for (0.., operands) |op_index, op| {
2938 if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
2939 if (self.reused_operands.isSet(op_index)) continue;
26132940 try self.processDeath(op.toIndexAllowNone() orelse continue);
26142941 }
26152942 self.finishAirResult(inst, result);
......@@ -2657,7 +2984,7 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
26572984 }
26582985 };
26592986 const sort_context = SortContext{ .frame_align = frame_align };
2660 mem.sort(FrameIndex, stack_frame_order, sort_context, SortContext.lessThan);
2987 std.mem.sort(FrameIndex, stack_frame_order, sort_context, SortContext.lessThan);
26612988 }
26622989
26632990 const call_frame_align = frame_align[@intFromEnum(FrameIndex.call_frame)];
......@@ -2697,13 +3024,13 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
26973024 @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.stack_frame)]);
26983025
26993026 return .{
2700 .stack_mask = @as(u32, math.maxInt(u32)) << @intCast(if (need_align_stack) @intFromEnum(needed_align) else 0),
3027 .stack_mask = @as(u32, std.math.maxInt(u32)) << @intCast(if (need_align_stack) @intFromEnum(needed_align) else 0),
27013028 .stack_adjust = @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.call_frame)]),
27023029 .save_reg_list = save_reg_list,
27033030 };
27043031}
27053032
2706fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
3033fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) InternPool.Alignment {
27073034 const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
27083035 return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
27093036}
......@@ -2741,7 +3068,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {
27413068 const ptr_ty = self.typeOfIndex(inst);
27423069 const val_ty = ptr_ty.childType(zcu);
27433070 return self.allocFrameIndex(FrameAlloc.init(.{
2744 .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
3071 .size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {
27453072 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(pt)});
27463073 },
27473074 .alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
......@@ -2759,7 +3086,7 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue {
27593086fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue {
27603087 const pt = self.pt;
27613088 const zcu = pt.zcu;
2762 const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
3089 const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
27633090 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});
27643091 };
27653092
......@@ -2857,8 +3184,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
28573184 }
28583185
28593186 if (opts.resurrect) for (
2860 self.inst_tracking.keys()[0..state.inst_tracking_len],
2861 self.inst_tracking.values()[0..state.inst_tracking_len],
3187 self.inst_tracking.keys()[Temp.Index.max..state.inst_tracking_len],
3188 self.inst_tracking.values()[Temp.Index.max..state.inst_tracking_len],
28623189 ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);
28633190 for (deaths) |death| try self.processDeath(death);
28643191
......@@ -3067,7 +3394,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
30673394 .{ .v_, .cvtps2ph },
30683395 dst_reg,
30693396 mat_src_reg.to128(),
3070 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
3397 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
30713398 );
30723399 },
30733400 else => unreachable,
......@@ -3267,7 +3594,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
32673594
32683595 const dst_elem_abi_size = dst_ty.childType(zcu).abiSize(zcu);
32693596 const src_elem_abi_size = src_ty.childType(zcu).abiSize(zcu);
3270 switch (math.order(dst_elem_abi_size, src_elem_abi_size)) {
3597 switch (std.math.order(dst_elem_abi_size, src_elem_abi_size)) {
32713598 .lt => {
32723599 const mir_tag: Mir.Inst.FixedTag = switch (dst_elem_abi_size) {
32733600 else => break :result null,
......@@ -3431,8 +3758,8 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
34313758 };
34323759
34333760 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and
3434 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
3435 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
3761 std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
3762 std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and
34363763 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
34373764 const dst_mcv = try self.allocRegOrMem(inst, true);
34383765 try self.genCopy(min_ty, dst_mcv, src_mcv, .{});
......@@ -3449,8 +3776,8 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
34493776 break :result .{ .register = registerAlias(dst_mcv.getReg().?, dst_abi_size) };
34503777 }
34513778
3452 const src_limbs_len = math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
3453 const dst_limbs_len = math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
3779 const src_limbs_len = std.math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
3780 const dst_limbs_len = std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
34543781
34553782 const high_mcv: MCValue = if (dst_mcv.isMemory())
34563783 dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()
......@@ -3570,7 +3897,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
35703897 const dst_info = dst_elem_ty.intInfo(zcu);
35713898 const src_info = src_elem_ty.intInfo(zcu);
35723899
3573 const mask_val = try pt.intValue(src_elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(64 - dst_info.bits));
3900 const mask_val = try pt.intValue(src_elem_ty, @as(u64, std.math.maxInt(u64)) >> @intCast(64 - dst_info.bits));
35743901
35753902 const splat_ty = try pt.vectorType(.{
35763903 .len = @intCast(@divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
......@@ -3607,7 +3934,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
36073934 .{ if (self.hasFeature(.avx2)) .v_i128 else .v_f128, .extract },
36083935 registerAlias(temp_reg, dst_abi_size),
36093936 dst_alias,
3610 Immediate.u(1),
3937 .u(1),
36113938 );
36123939 try self.asmRegisterRegisterRegister(
36133940 mir_tag,
......@@ -3806,7 +4133,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
38064133 try self.asmMemoryImmediate(
38074134 .{ ._, .mov },
38084135 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },
3809 Immediate.u(0),
4136 .u(0),
38104137 );
38114138
38124139 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
......@@ -3920,11 +4247,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
39204247 .mod = .{ .rm = .{ .size = .qword } },
39214248 },
39224249 );
3923 try self.asmRegisterImmediate(
3924 .{ ._, .sbb },
3925 dst_mcv.register_pair[1],
3926 Immediate.u(0),
3927 );
4250 try self.asmRegisterImmediate(.{ ._, .sbb }, dst_mcv.register_pair[1], .u(0));
39284251 try self.freeValue(
39294252 .{ .load_frame = .{ .index = signed_div_floor_state.frame_index } },
39304253 );
......@@ -4068,7 +4391,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
40684391 break :cc .o;
40694392 } else cc: {
40704393 try self.genSetReg(limit_reg, ty, .{
4071 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - ty.bitSize(zcu)),
4394 .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - ty.bitSize(zcu)),
40724395 }, .{});
40734396
40744397 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
......@@ -4266,12 +4589,12 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
42664589 mat_rhs_mcv.register_pair[1],
42674590 );
42684591
4269 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
4592 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, .u(63));
42704593 try self.asmRegister(.{ ._, .not }, tmp_reg);
4271 try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), Immediate.s(0));
4594 try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), .s(0));
42724595 try self.freeValue(overflow);
42734596 try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[0], tmp_reg);
4274 try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, Immediate.u(63));
4597 try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, .u(63));
42754598 try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[1], tmp_reg);
42764599 break :result dst_mcv;
42774600 }
......@@ -4321,7 +4644,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
43214644 break :cc .o;
43224645 } else cc: {
43234646 try self.genSetReg(limit_reg, ty, .{
4324 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - reg_bits),
4647 .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - reg_bits),
43254648 }, .{});
43264649 break :cc .c;
43274650 };
......@@ -4366,7 +4689,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
43664689 };
43674690
43684691 const tuple_ty = self.typeOfIndex(inst);
4369 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
4692 if (int_info.bits >= 8 and std.math.isPowerOfTwo(int_info.bits)) {
43704693 switch (partial_mcv) {
43714694 .register => |reg| {
43724695 self.eflags_inst = inst;
......@@ -4444,7 +4767,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
44444767 const cc = Condition.ne;
44454768
44464769 const tuple_ty = self.typeOfIndex(inst);
4447 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
4770 if (int_info.bits >= 8 and std.math.isPowerOfTwo(int_info.bits)) {
44484771 switch (partial_mcv) {
44494772 .register => |reg| {
44504773 self.eflags_inst = inst;
......@@ -4576,7 +4899,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
45764899 if (dst_info.bits > 128 and dst_info.signedness == .unsigned) {
45774900 const slow_inc = self.hasFeature(.slow_incdec);
45784901 const abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
4579 const limb_len = math.divCeil(u32, abi_size, 8) catch unreachable;
4902 const limb_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
45804903
45814904 try self.spillRegisters(&.{ .rax, .rcx, .rdx });
45824905 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rax, .rcx, .rdx });
......@@ -4618,7 +4941,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
46184941 try self.asmRegisterRegister(.{ ._, .xor }, .edx, .edx);
46194942
46204943 const inner_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
4621 try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, Immediate.u(1));
4944 try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, .u(1));
46224945 try self.asmMemoryRegister(.{ ._, .adc }, .{
46234946 .base = .{ .frame = dst_mcv.load_frame.index },
46244947 .mod = .{ .rm = .{
......@@ -4642,7 +4965,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
46424965 });
46434966 try self.asmRegister(.{ ._, .mul }, temp_regs[1].to64());
46444967
4645 try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, Immediate.u(1));
4968 try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, .u(1));
46464969 try self.asmMemoryRegister(.{ ._, .adc }, .{
46474970 .base = .{ .frame = dst_mcv.load_frame.index },
46484971 .mod = .{ .rm = .{
......@@ -4656,30 +4979,22 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
46564979 try self.asmSetccRegister(.c, .ch);
46574980
46584981 if (slow_inc) {
4659 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), Immediate.u(1));
4660 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), Immediate.u(1));
4982 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), .u(1));
4983 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), .u(1));
46614984 } else {
46624985 try self.asmRegister(.{ ._, .inc }, temp_regs[2].to32());
46634986 try self.asmRegister(.{ ._, .inc }, temp_regs[3].to32());
46644987 }
4665 try self.asmRegisterImmediate(
4666 .{ ._, .cmp },
4667 temp_regs[3].to32(),
4668 Immediate.u(limb_len),
4669 );
4988 try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[3].to32(), .u(limb_len));
46704989 _ = try self.asmJccReloc(.b, inner_loop);
46714990
46724991 try self.asmRegisterRegister(.{ ._, .@"or" }, .rdx, .rcx);
46734992 const overflow = try self.asmJccReloc(.nz, undefined);
46744993 const overflow_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
4675 try self.asmRegisterImmediate(
4676 .{ ._, .cmp },
4677 temp_regs[2].to32(),
4678 Immediate.u(limb_len),
4679 );
4994 try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[2].to32(), .u(limb_len));
46804995 const no_overflow = try self.asmJccReloc(.nb, undefined);
46814996 if (slow_inc) {
4682 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), Immediate.u(1));
4997 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), .u(1));
46834998 } else {
46844999 try self.asmRegister(.{ ._, .inc }, temp_regs[2].to32());
46855000 }
......@@ -4691,7 +5006,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
46915006 .scale = .@"8",
46925007 .disp = lhs_mcv.load_frame.off - 8,
46935008 } },
4694 }, Immediate.u(0));
5009 }, .u(0));
46955010 _ = try self.asmJccReloc(.z, overflow_loop);
46965011 self.performReloc(overflow);
46975012 try self.asmMemoryImmediate(.{ ._, .mov }, .{
......@@ -4701,20 +5016,16 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
47015016 .disp = dst_mcv.load_frame.off +
47025017 @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
47035018 } },
4704 }, Immediate.u(1));
5019 }, .u(1));
47055020 self.performReloc(no_overflow);
47065021
47075022 self.performReloc(skip_inner);
47085023 if (slow_inc) {
4709 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
5024 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
47105025 } else {
47115026 try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
47125027 }
4713 try self.asmRegisterImmediate(
4714 .{ ._, .cmp },
4715 temp_regs[0].to32(),
4716 Immediate.u(limb_len),
4717 );
5028 try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[0].to32(), .u(limb_len));
47185029 _ = try self.asmJccReloc(.b, outer_loop);
47195030
47205031 break :result dst_mcv;
......@@ -4750,7 +5061,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
47505061 try self.asmMemoryImmediate(
47515062 .{ ._, .cmp },
47525063 try overflow.mem(self, self.memSize(Type.c_int)),
4753 Immediate.s(0),
5064 .s(0),
47545065 );
47555066 try self.genSetMem(
47565067 .{ .frame = dst_mcv.load_frame.index },
......@@ -5038,7 +5349,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
50385349 try self.asmRegisterImmediate(
50395350 .{ ._r, .sa },
50405351 registerAlias(divisor, abi_size),
5041 Immediate.u(int_info.bits - 1),
5352 .u(int_info.bits - 1),
50425353 );
50435354 try self.asmRegisterRegister(
50445355 .{ ._, .@"test" },
......@@ -5217,8 +5528,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
52175528 defer for (reg_locks) |reg_lock| if (reg_lock) |lock|
52185529 self.register_manager.unlockReg(lock);
52195530
5220 const shift_imm =
5221 Immediate.u(@intCast(Value.fromInterned(rhs_elem).toUnsignedInt(zcu)));
5531 const shift_imm: Immediate =
5532 .u(@intCast(Value.fromInterned(rhs_elem).toUnsignedInt(zcu)));
52225533 if (self.hasFeature(.avx)) try self.asmRegisterRegisterImmediate(
52235534 mir_tag,
52245535 registerAlias(dst_reg, abi_size),
......@@ -5434,7 +5745,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
54345745 break :result operand;
54355746 }
54365747
5437 const err_off = errUnionErrorOffset(payload_ty, zcu);
5748 const err_off = codegen.errUnionErrorOffset(payload_ty, zcu);
54385749 switch (operand) {
54395750 .register => |reg| {
54405751 // TODO reuse operand
......@@ -5492,7 +5803,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
54925803 const eu_ty = src_ty.childType(zcu);
54935804 const pl_ty = eu_ty.errorUnionPayload(zcu);
54945805 const err_ty = eu_ty.errorUnionSet(zcu);
5495 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
5806 const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
54965807 const err_abi_size: u32 = @intCast(err_ty.abiSize(zcu));
54975808 try self.asmRegisterMemory(
54985809 .{ ._, .mov },
......@@ -5535,7 +5846,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
55355846 const eu_ty = src_ty.childType(zcu);
55365847 const pl_ty = eu_ty.errorUnionPayload(zcu);
55375848 const err_ty = eu_ty.errorUnionSet(zcu);
5538 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
5849 const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
55395850 const err_abi_size: u32 = @intCast(err_ty.abiSize(zcu));
55405851 try self.asmMemoryImmediate(
55415852 .{ ._, .mov },
......@@ -5546,7 +5857,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
55465857 .disp = err_off,
55475858 } },
55485859 },
5549 Immediate.u(0),
5860 .u(0),
55505861 );
55515862
55525863 if (self.liveness.isUnused(inst)) break :result .unreach;
......@@ -5559,7 +5870,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
55595870 const dst_lock = self.register_manager.lockReg(dst_reg);
55605871 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
55615872
5562 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
5873 const pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(pl_ty, zcu));
55635874 const dst_abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
55645875 try self.asmRegisterMemory(
55655876 .{ ._, .lea },
......@@ -5587,7 +5898,7 @@ fn genUnwrapErrUnionPayloadMir(
55875898 const result: MCValue = result: {
55885899 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;
55895900
5590 const payload_off: u31 = @intCast(errUnionPayloadOffset(payload_ty, zcu));
5901 const payload_off: u31 = @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu));
55915902 switch (err_union) {
55925903 .load_frame => |frame_addr| break :result .{ .load_frame = .{
55935904 .index = frame_addr.index,
......@@ -5636,7 +5947,7 @@ fn genUnwrapErrUnionPayloadPtrMir(
56365947 const payload_ty = err_union_ty.errorUnionPayload(zcu);
56375948
56385949 const result: MCValue = result: {
5639 const payload_off = errUnionPayloadOffset(payload_ty, zcu);
5950 const payload_off = codegen.errUnionPayloadOffset(payload_ty, zcu);
56405951 const result_mcv: MCValue = if (maybe_inst) |inst|
56415952 try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr_mcv)
56425953 else
......@@ -5696,7 +6007,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
56966007 try self.asmRegisterImmediate(
56976008 .{ ._s, .bt },
56986009 opt_reg,
5699 Immediate.u(@as(u6, @intCast(pl_abi_size * 8))),
6010 .u(@as(u6, @intCast(pl_abi_size * 8))),
57006011 );
57016012 },
57026013
......@@ -5709,7 +6020,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
57096020 .disp = frame_addr.off + pl_abi_size,
57106021 } },
57116022 },
5712 Immediate.u(1),
6023 .u(1),
57136024 ),
57146025 }
57156026 }
......@@ -5733,8 +6044,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
57336044 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 };
57346045
57356046 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
5736 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
5737 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
6047 const pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(pl_ty, zcu));
6048 const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
57386049 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand, .{});
57396050 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }, .{});
57406051 break :result .{ .load_frame = .{ .index = frame_index } };
......@@ -5756,8 +6067,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
57566067 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try self.resolveInst(ty_op.operand);
57576068
57586069 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
5759 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
5760 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
6070 const pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(pl_ty, zcu));
6071 const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
57616072 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef, .{});
57626073 const operand = try self.resolveInst(ty_op.operand);
57636074 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand, .{});
......@@ -5770,11 +6081,20 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
57706081 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
57716082 const result = result: {
57726083 const src_mcv = try self.resolveInst(ty_op.operand);
5773 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
6084 const ptr_mcv: MCValue = switch (src_mcv) {
6085 .register_pair => |regs| .{ .register = regs[0] },
6086 else => src_mcv,
6087 };
6088 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
6089 switch (src_mcv) {
6090 .register_pair => |regs| try self.freeValue(.{ .register = regs[1] }),
6091 else => {},
6092 }
6093 break :result ptr_mcv;
6094 }
57746095
57756096 const dst_mcv = try self.allocRegOrMem(inst, true);
5776 const dst_ty = self.typeOfIndex(inst);
5777 try self.genCopy(dst_ty, dst_mcv, src_mcv, .{});
6097 try self.genCopy(self.typeOfIndex(inst), dst_mcv, ptr_mcv, .{});
57786098 break :result dst_mcv;
57796099 };
57806100 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -5782,23 +6102,28 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
57826102
57836103fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
57846104 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5785
5786 const result: MCValue = result: {
6105 const result = result: {
57876106 const src_mcv = try self.resolveInst(ty_op.operand);
5788 switch (src_mcv) {
5789 .load_frame => |frame_addr| {
5790 const len_mcv: MCValue = .{ .load_frame = .{
5791 .index = frame_addr.index,
5792 .off = frame_addr.off + 8,
5793 } };
5794 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
5795
5796 const dst_mcv = try self.allocRegOrMem(inst, true);
5797 try self.genCopy(Type.usize, dst_mcv, len_mcv, .{});
5798 break :result dst_mcv;
5799 },
6107 const len_mcv: MCValue = switch (src_mcv) {
6108 .register_pair => |regs| .{ .register = regs[1] },
6109 .load_frame => |frame_addr| .{ .load_frame = .{
6110 .index = frame_addr.index,
6111 .off = frame_addr.off + 8,
6112 } },
58006113 else => return self.fail("TODO implement slice_len for {}", .{src_mcv}),
6114 };
6115 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
6116 switch (src_mcv) {
6117 .register_pair => |regs| try self.freeValue(.{ .register = regs[0] }),
6118 .load_frame => {},
6119 else => unreachable,
6120 }
6121 break :result len_mcv;
58016122 }
6123
6124 const dst_mcv = try self.allocRegOrMem(inst, true);
6125 try self.genCopy(self.typeOfIndex(inst), dst_mcv, len_mcv, .{});
6126 break :result dst_mcv;
58026127 };
58036128 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
58046129}
......@@ -6296,27 +6621,27 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
62966621 const src_bits: u31 = @intCast(src_ty.bitSize(zcu));
62976622 const has_lzcnt = self.hasFeature(.lzcnt);
62986623 if (src_bits > @as(u32, if (has_lzcnt) 128 else 64)) {
6299 const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
6624 const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
63006625 const extra_bits = abi_size * 8 - src_bits;
63016626
63026627 const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
63036628 const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
63046629 defer self.register_manager.unlockReg(index_lock);
63056630
6306 try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), Immediate.u(limbs_len));
6631 try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .u(limbs_len));
63076632 switch (extra_bits) {
63086633 1 => try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32()),
63096634 else => try self.asmRegisterImmediate(
63106635 .{ ._, .mov },
63116636 dst_reg.to32(),
6312 Immediate.s(@as(i32, extra_bits) - 1),
6637 .s(@as(i32, extra_bits) - 1),
63136638 ),
63146639 }
63156640 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
63166641 try self.asmRegisterRegister(.{ ._, .@"test" }, index_reg.to32(), index_reg.to32());
63176642 const zero = try self.asmJccReloc(.z, undefined);
63186643 if (self.hasFeature(.slow_incdec)) {
6319 try self.asmRegisterImmediate(.{ ._, .sub }, index_reg.to32(), Immediate.u(1));
6644 try self.asmRegisterImmediate(.{ ._, .sub }, index_reg.to32(), .u(1));
63206645 } else {
63216646 try self.asmRegister(.{ ._, .dec }, index_reg.to32());
63226647 }
......@@ -6328,7 +6653,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
63286653 .scale = .@"8",
63296654 .disp = src_mcv.load_frame.off,
63306655 } },
6331 }, Immediate.u(0));
6656 }, .u(0));
63326657 _ = try self.asmJccReloc(.e, loop);
63336658 try self.asmRegisterMemory(.{ ._, .bsr }, dst_reg.to64(), .{
63346659 .base = .{ .frame = src_mcv.load_frame.index },
......@@ -6340,9 +6665,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
63406665 } },
63416666 });
63426667 self.performReloc(zero);
6343 try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), Immediate.u(6));
6668 try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), .u(6));
63446669 try self.asmRegisterRegister(.{ ._, .add }, index_reg.to32(), dst_reg.to32());
6345 try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), Immediate.u(src_bits - 1));
6670 try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), .u(src_bits - 1));
63466671 try self.asmRegisterRegister(.{ ._, .sub }, dst_reg.to32(), index_reg.to32());
63476672 break :result dst_mcv;
63486673 }
......@@ -6404,7 +6729,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
64046729
64056730 assert(src_bits <= 64);
64066731 const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(zcu))), 2);
6407 if (math.isPowerOfTwo(src_bits)) {
6732 if (std.math.isPowerOfTwo(src_bits)) {
64086733 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
64096734 .immediate = src_bits ^ (src_bits - 1),
64106735 });
......@@ -6429,7 +6754,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
64296754 try self.genBinOpMir(.{ ._, .xor }, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 });
64306755 } else {
64316756 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
6432 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - self.regBitSize(dst_ty)),
6757 .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - self.regBitSize(dst_ty)),
64336758 });
64346759 const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg);
64356760 defer self.register_manager.unlockReg(imm_lock);
......@@ -6493,30 +6818,30 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
64936818 const src_bits: u31 = @intCast(src_ty.bitSize(zcu));
64946819 const has_bmi = self.hasFeature(.bmi);
64956820 if (src_bits > @as(u32, if (has_bmi) 128 else 64)) {
6496 const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
6821 const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
64976822 const extra_bits = abi_size * 8 - src_bits;
64986823
64996824 const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
65006825 const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
65016826 defer self.register_manager.unlockReg(index_lock);
65026827
6503 try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), Immediate.s(-1));
6828 try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .s(-1));
65046829 switch (extra_bits) {
65056830 0 => try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32()),
65066831 1 => try self.asmRegisterRegister(.{ ._, .mov }, dst_reg.to32(), dst_reg.to32()),
65076832 else => try self.asmRegisterImmediate(
65086833 .{ ._, .mov },
65096834 dst_reg.to32(),
6510 Immediate.s(-@as(i32, extra_bits)),
6835 .s(-@as(i32, extra_bits)),
65116836 ),
65126837 }
65136838 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
65146839 if (self.hasFeature(.slow_incdec)) {
6515 try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), Immediate.u(1));
6840 try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
65166841 } else {
65176842 try self.asmRegister(.{ ._, .inc }, index_reg.to32());
65186843 }
6519 try self.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), Immediate.u(limbs_len));
6844 try self.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), .u(limbs_len));
65206845 const zero = try self.asmJccReloc(.nb, undefined);
65216846 try self.asmMemoryImmediate(.{ ._, .cmp }, .{
65226847 .base = .{ .frame = src_mcv.load_frame.index },
......@@ -6526,7 +6851,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
65266851 .scale = .@"8",
65276852 .disp = src_mcv.load_frame.off,
65286853 } },
6529 }, Immediate.u(0));
6854 }, .u(0));
65306855 _ = try self.asmJccReloc(.e, loop);
65316856 try self.asmRegisterMemory(.{ ._, .bsf }, dst_reg.to64(), .{
65326857 .base = .{ .frame = src_mcv.load_frame.index },
......@@ -6538,7 +6863,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
65386863 } },
65396864 });
65406865 self.performReloc(zero);
6541 try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), Immediate.u(6));
6866 try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), .u(6));
65426867 try self.asmRegisterRegister(.{ ._, .add }, dst_reg.to32(), index_reg.to32());
65436868 break :result dst_mcv;
65446869 }
......@@ -6558,7 +6883,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
65586883 .{ ._, .@"or" },
65596884 wide_ty,
65606885 tmp_mcv,
6561 .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(64 - extra_bits)) <<
6886 .{ .immediate = (@as(u64, std.math.maxInt(u64)) >> @intCast(64 - extra_bits)) <<
65626887 @intCast(src_bits) },
65636888 );
65646889 break :masked tmp_mcv;
......@@ -6585,7 +6910,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
65856910 .{ ._, .@"or" },
65866911 Type.u64,
65876912 dst_mcv,
6588 .{ .immediate = @as(u64, math.maxInt(u64)) << @intCast(src_bits - 64) },
6913 .{ .immediate = @as(u64, std.math.maxInt(u64)) << @intCast(src_bits - 64) },
65896914 );
65906915 break :masked dst_mcv;
65916916 } else hi_mat_src_mcv;
......@@ -6602,7 +6927,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
66026927 const width_lock = self.register_manager.lockRegAssumeUnused(width_reg);
66036928 defer self.register_manager.unlockReg(width_lock);
66046929
6605 if (src_bits <= 8 or !math.isPowerOfTwo(src_bits)) {
6930 if (src_bits <= 8 or !std.math.isPowerOfTwo(src_bits)) {
66066931 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
66076932 const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg);
66086933 defer self.register_manager.unlockReg(wide_lock);
......@@ -6701,11 +7026,11 @@ fn genPopCount(
67017026 },
67027027 );
67037028
6704 const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8);
6705 const imm_0_1 = Immediate.u(mask / 0b1_1);
6706 const imm_00_11 = Immediate.u(mask / 0b01_01);
6707 const imm_0000_1111 = Immediate.u(mask / 0b0001_0001);
6708 const imm_0000_0001 = Immediate.u(mask / 0b1111_1111);
7029 const mask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8);
7030 const imm_0_1: Immediate = .u(mask / 0b1_1);
7031 const imm_00_11: Immediate = .u(mask / 0b01_01);
7032 const imm_0000_1111: Immediate = .u(mask / 0b0001_0001);
7033 const imm_0000_0001: Immediate = .u(mask / 0b1111_1111);
67097034
67107035 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
67117036 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -6722,7 +7047,7 @@ fn genPopCount(
67227047 // dst = operand
67237048 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
67247049 // tmp = operand
6725 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(1));
7050 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, .u(1));
67267051 // tmp = operand >> 1
67277052 if (src_abi_size > 4) {
67287053 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0_1);
......@@ -6733,7 +7058,7 @@ fn genPopCount(
67337058 // dst = temp1 = operand - ((operand >> 1) & 0x55...55)
67347059 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
67357060 // tmp = temp1
6736 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(2));
7061 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u(2));
67377062 // dst = temp1 >> 2
67387063 if (src_abi_size > 4) {
67397064 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_00_11);
......@@ -6749,7 +7074,7 @@ fn genPopCount(
67497074 // tmp = temp2 = (temp1 & 0x33...33) + ((temp1 >> 2) & 0x33...33)
67507075 try self.asmRegisterRegister(.{ ._, .mov }, dst, tmp);
67517076 // dst = temp2
6752 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(4));
7077 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, .u(4));
67537078 // tmp = temp2 >> 4
67547079 try self.asmRegisterRegister(.{ ._, .add }, dst, tmp);
67557080 // dst = temp2 + (temp2 >> 4)
......@@ -6767,7 +7092,7 @@ fn genPopCount(
67677092 // dst = temp3 = (temp2 + (temp2 >> 4)) & 0x0f...0f
67687093 // dst = temp3 * 0x01...01
67697094 if (src_abi_size > 1) {
6770 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u((src_abi_size - 1) * 8));
7095 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u((src_abi_size - 1) * 8));
67717096 }
67727097 // dst = (temp3 * 0x01...01) >> (bits - 8)
67737098}
......@@ -6847,7 +7172,7 @@ fn genByteSwap(
68477172 return .{ .register_pair = .{ dst_regs[1], dst_regs[0] } };
68487173 },
68497174 else => {
6850 const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
7175 const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
68517176
68527177 const temp_regs =
68537178 try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp);
......@@ -6856,11 +7181,7 @@ fn genByteSwap(
68567181
68577182 const dst_mcv = try self.allocRegOrMem(inst, false);
68587183 try self.asmRegisterRegister(.{ ._, .xor }, temp_regs[0].to32(), temp_regs[0].to32());
6859 try self.asmRegisterImmediate(
6860 .{ ._, .mov },
6861 temp_regs[1].to32(),
6862 Immediate.u(limbs_len - 1),
6863 );
7184 try self.asmRegisterImmediate(.{ ._, .mov }, temp_regs[1].to32(), .u(limbs_len - 1));
68647185
68657186 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
68667187 try self.asmRegisterMemory(
......@@ -6912,8 +7233,8 @@ fn genByteSwap(
69127233 } },
69137234 }, temp_regs[2].to64());
69147235 if (self.hasFeature(.slow_incdec)) {
6915 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
6916 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
7236 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
7237 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), .u(1));
69177238 } else {
69187239 try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
69197240 try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
......@@ -6994,10 +7315,10 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
69947315 else
69957316 undefined;
69967317
6997 const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - limb_abi_size * 8);
6998 const imm_0000_1111 = Immediate.u(mask / 0b0001_0001);
6999 const imm_00_11 = Immediate.u(mask / 0b01_01);
7000 const imm_0_1 = Immediate.u(mask / 0b1_1);
7318 const mask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - limb_abi_size * 8);
7319 const imm_0000_1111: Immediate = .u(mask / 0b0001_0001);
7320 const imm_00_11: Immediate = .u(mask / 0b01_01);
7321 const imm_0_1: Immediate = .u(mask / 0b1_1);
70017322
70027323 for (dst_mcv.getRegs()) |dst_reg| {
70037324 const dst = registerAlias(dst_reg, limb_abi_size);
......@@ -7005,7 +7326,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
70057326 // dst = temp1 = bswap(operand)
70067327 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
70077328 // tmp = temp1
7008 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(4));
7329 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u(4));
70097330 // dst = temp1 >> 4
70107331 if (limb_abi_size > 4) {
70117332 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0000_1111);
......@@ -7017,13 +7338,13 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
70177338 }
70187339 // tmp = temp1 & 0x0F...0F
70197340 // dst = (temp1 >> 4) & 0x0F...0F
7020 try self.asmRegisterImmediate(.{ ._l, .sh }, tmp, Immediate.u(4));
7341 try self.asmRegisterImmediate(.{ ._l, .sh }, tmp, .u(4));
70217342 // tmp = (temp1 & 0x0F...0F) << 4
70227343 try self.asmRegisterRegister(.{ ._, .@"or" }, dst, tmp);
70237344 // dst = temp2 = ((temp1 >> 4) & 0x0F...0F) | ((temp1 & 0x0F...0F) << 4)
70247345 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
70257346 // tmp = temp2
7026 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(2));
7347 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u(2));
70277348 // dst = temp2 >> 2
70287349 if (limb_abi_size > 4) {
70297350 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_00_11);
......@@ -7050,7 +7371,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
70507371 // tmp = temp3 = ((temp2 >> 2) & 0x33...33) + ((temp2 & 0x33...33) << 2)
70517372 try self.asmRegisterRegister(.{ ._, .mov }, dst, tmp);
70527373 // dst = temp3
7053 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(1));
7374 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, .u(1));
70547375 // tmp = temp3 >> 1
70557376 if (limb_abi_size > 4) {
70567377 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0_1);
......@@ -7337,7 +7658,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
73377658 dst_alias,
73387659 dst_alias,
73397660 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
7340 Immediate.u(@as(u5, @bitCast(mode))),
7661 .u(@as(u5, @bitCast(mode))),
73417662 ) else try self.asmRegisterRegisterRegisterImmediate(
73427663 mir_tag,
73437664 dst_alias,
......@@ -7346,13 +7667,13 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
73467667 src_mcv.getReg().?
73477668 else
73487669 try self.copyToTmpRegister(ty, src_mcv), abi_size),
7349 Immediate.u(@as(u5, @bitCast(mode))),
7670 .u(@as(u5, @bitCast(mode))),
73507671 ),
73517672 else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
73527673 mir_tag,
73537674 dst_alias,
73547675 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
7355 Immediate.u(@as(u5, @bitCast(mode))),
7676 .u(@as(u5, @bitCast(mode))),
73567677 ) else try self.asmRegisterRegisterImmediate(
73577678 mir_tag,
73587679 dst_alias,
......@@ -7360,7 +7681,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
73607681 src_mcv.getReg().?
73617682 else
73627683 try self.copyToTmpRegister(ty, src_mcv), abi_size),
7363 Immediate.u(@as(u5, @bitCast(mode))),
7684 .u(@as(u5, @bitCast(mode))),
73647685 ),
73657686 }
73667687}
......@@ -7433,7 +7754,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
74337754 defer self.register_manager.unlockReg(tmp_lock);
74347755
74357756 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]);
7436 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
7757 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, .u(63));
74377758 try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[0], tmp_reg);
74387759 try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[1], tmp_reg);
74397760 try self.asmRegisterRegister(.{ ._, .sub }, dst_regs[0], tmp_reg);
......@@ -7443,7 +7764,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
74437764 },
74447765 else => {
74457766 const abi_size: u31 = @intCast(ty.abiSize(zcu));
7446 const limb_len = math.divCeil(u31, abi_size, 8) catch unreachable;
7767 const limb_len = std.math.divCeil(u31, abi_size, 8) catch unreachable;
74477768
74487769 const tmp_regs =
74497770 try self.register_manager.allocRegs(3, .{null} ** 3, abi.RegisterClass.gp);
......@@ -7460,7 +7781,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
74607781 try self.asmMemoryImmediate(
74617782 .{ ._, .cmp },
74627783 try dst_mcv.address().offset((limb_len - 1) * 8).deref().mem(self, .qword),
7463 Immediate.u(0),
7784 .u(0),
74647785 );
74657786 const positive = try self.asmJccReloc(.ns, undefined);
74667787
......@@ -7469,7 +7790,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
74697790
74707791 const neg_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
74717792 try self.asmRegisterRegister(.{ ._, .xor }, tmp_regs[2].to32(), tmp_regs[2].to32());
7472 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp_regs[1].to8(), Immediate.u(1));
7793 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp_regs[1].to8(), .u(1));
74737794 try self.asmRegisterMemory(.{ ._, .sbb }, tmp_regs[2].to64(), .{
74747795 .base = .{ .frame = dst_mcv.load_frame.index },
74757796 .mod = .{ .rm = .{
......@@ -7491,11 +7812,11 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
74917812 }, tmp_regs[2].to64());
74927813
74937814 if (self.hasFeature(.slow_incdec)) {
7494 try self.asmRegisterImmediate(.{ ._, .add }, tmp_regs[0].to32(), Immediate.u(1));
7815 try self.asmRegisterImmediate(.{ ._, .add }, tmp_regs[0].to32(), .u(1));
74957816 } else {
74967817 try self.asmRegister(.{ ._, .inc }, tmp_regs[0].to32());
74977818 }
7498 try self.asmRegisterImmediate(.{ ._, .cmp }, tmp_regs[0].to32(), Immediate.u(limb_len));
7819 try self.asmRegisterImmediate(.{ ._, .cmp }, tmp_regs[0].to32(), .u(limb_len));
74997820 _ = try self.asmJccReloc(.b, neg_loop);
75007821
75017822 self.performReloc(positive);
......@@ -7620,7 +7941,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
76207941 .{ .v_, .cvtps2ph },
76217942 dst_reg,
76227943 dst_reg,
7623 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
7944 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
76247945 );
76257946 break :result dst_mcv;
76267947 },
......@@ -7650,7 +7971,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
76507971 .{ .v_, .cvtps2ph },
76517972 dst_reg,
76527973 dst_reg,
7653 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
7974 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
76547975 );
76557976 break :result dst_mcv;
76567977 },
......@@ -7675,7 +7996,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
76757996 .{ .v_, .cvtps2ph },
76767997 dst_reg,
76777998 wide_reg,
7678 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
7999 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
76798000 );
76808001 break :result dst_mcv;
76818002 },
......@@ -7699,9 +8020,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
76998020 else => unreachable,
77008021 },
77018022 else => unreachable,
7702 }) orelse return self.fail("TODO implement airSqrt for {}", .{
7703 ty.fmt(pt),
7704 });
8023 }) orelse return self.fail("TODO implement airSqrt for {}", .{ty.fmt(pt)});
77058024 switch (mir_tag[0]) {
77068025 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
77078026 mir_tag,
......@@ -7805,7 +8124,7 @@ fn reuseOperandAdvanced(
78058124 }
78068125
78078126 // Prevent the operand deaths processing code from deallocating it.
7808 self.liveness.clearOperandDeath(inst, op_index);
8127 self.reused_operands.set(op_index);
78098128 const op_inst = operand.toIndex().?;
78108129 self.getResolvedInstValue(op_inst).reuse(self, maybe_tracked_inst, op_inst);
78118130
......@@ -7890,7 +8209,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
78908209 } },
78918210 });
78928211 try self.spillEflagsIfOccupied();
7893 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off));
8212 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, .u(val_bit_off));
78948213 } else {
78958214 const tmp_reg =
78968215 registerAlias(try self.register_manager.allocReg(null, abi.RegisterClass.gp), val_abi_size);
......@@ -7913,12 +8232,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
79138232 } },
79148233 });
79158234 try self.spillEflagsIfOccupied();
7916 try self.asmRegisterRegisterImmediate(
7917 .{ ._rd, .sh },
7918 dst_alias,
7919 tmp_reg,
7920 Immediate.u(val_bit_off),
7921 );
8235 try self.asmRegisterRegisterImmediate(.{ ._rd, .sh }, dst_alias, tmp_reg, .u(val_bit_off));
79228236 }
79238237
79248238 if (val_extra_bits > 0) try self.truncateRegister(val_ty, dst_reg);
......@@ -8064,16 +8378,16 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
80648378 } },
80658379 };
80668380
8067 const part_mask = (@as(u64, math.maxInt(u64)) >> @intCast(64 - part_bit_size)) <<
8381 const part_mask = (@as(u64, std.math.maxInt(u64)) >> @intCast(64 - part_bit_size)) <<
80688382 @intCast(part_bit_off);
8069 const part_mask_not = part_mask ^ (@as(u64, math.maxInt(u64)) >> @intCast(64 - limb_abi_bits));
8383 const part_mask_not = part_mask ^ (@as(u64, std.math.maxInt(u64)) >> @intCast(64 - limb_abi_bits));
80708384 if (limb_abi_size <= 4) {
8071 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.u(part_mask_not));
8072 } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| {
8073 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small));
8385 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, .u(part_mask_not));
8386 } else if (std.math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| {
8387 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, .s(small));
80748388 } else {
80758389 const part_mask_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
8076 try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not));
8390 try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, .u(part_mask_not));
80778391 try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg);
80788392 }
80798393
......@@ -8209,25 +8523,14 @@ fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
82098523 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
82108524}
82118525
8212fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
8526fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, field_index: u8) !void {
82138527 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
8214 const result = try self.fieldPtr(inst, ty_op.operand, index);
8528 const result = try self.fieldPtr(inst, ty_op.operand, field_index);
82158529 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
82168530}
82178531
8218fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
8219 const pt = self.pt;
8220 const zcu = pt.zcu;
8532fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, field_index: u32) !MCValue {
82218533 const ptr_field_ty = self.typeOfIndex(inst);
8222 const ptr_container_ty = self.typeOf(operand);
8223 const container_ty = ptr_container_ty.childType(zcu);
8224
8225 const field_off: i32 = switch (container_ty.containerLayout(zcu)) {
8226 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, zcu)),
8227 .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(zcu).packed_offset.bit_offset) +
8228 (if (zcu.typeToStruct(container_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, index) else 0) -
8229 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
8230 };
82318534
82328535 const src_mcv = try self.resolveInst(operand);
82338536 const dst_mcv = if (switch (src_mcv) {
......@@ -8235,7 +8538,19 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
82358538 .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),
82368539 else => false,
82378540 }) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv);
8238 return dst_mcv.offset(field_off);
8541 return dst_mcv.offset(self.fieldOffset(self.typeOf(operand), ptr_field_ty, field_index));
8542}
8543
8544fn fieldOffset(self: *Self, ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32) i32 {
8545 const pt = self.pt;
8546 const zcu = pt.zcu;
8547 const agg_ty = ptr_agg_ty.childType(zcu);
8548 return switch (agg_ty.containerLayout(zcu)) {
8549 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(field_index, zcu)),
8550 .@"packed" => @divExact(@as(i32, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) +
8551 (if (zcu.typeToStruct(agg_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, field_index) else 0) -
8552 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
8553 };
82398554}
82408555
82418556fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
......@@ -8476,7 +8791,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
84768791 } },
84778792 });
84788793 try self.spillEflagsIfOccupied();
8479 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off));
8794 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, .u(field_bit_off));
84808795 } else {
84818796 const tmp_reg = registerAlias(
84828797 try self.register_manager.allocReg(null, abi.RegisterClass.gp),
......@@ -8509,7 +8824,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
85098824 .{ ._rd, .sh },
85108825 dst_alias,
85118826 tmp_reg,
8512 Immediate.u(field_bit_off),
8827 .u(field_bit_off),
85138828 );
85148829 }
85158830
......@@ -8528,27 +8843,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
85288843}
85298844
85308845fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
8531 const pt = self.pt;
8532 const zcu = pt.zcu;
85338846 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
85348847 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
85358848
8536 const inst_ty = self.typeOfIndex(inst);
8537 const parent_ty = inst_ty.childType(zcu);
8538 const field_off: i32 = switch (parent_ty.containerLayout(zcu)) {
8539 .auto, .@"extern" => @intCast(parent_ty.structFieldOffset(extra.field_index, zcu)),
8540 .@"packed" => @divExact(@as(i32, inst_ty.ptrInfo(zcu).packed_offset.bit_offset) +
8541 (if (zcu.typeToStruct(parent_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0) -
8542 self.typeOf(extra.field_ptr).ptrInfo(zcu).packed_offset.bit_offset, 8),
8543 };
8544
8849 const ptr_agg_ty = self.typeOfIndex(inst);
85458850 const src_mcv = try self.resolveInst(extra.field_ptr);
85468851 const dst_mcv = if (src_mcv.isRegisterOffset() and
85478852 self.reuseOperand(inst, extra.field_ptr, 0, src_mcv))
85488853 src_mcv
85498854 else
8550 try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv);
8551 const result = dst_mcv.offset(-field_off);
8855 try self.copyToRegisterWithInstTracking(inst, ptr_agg_ty, src_mcv);
8856 const result = dst_mcv.offset(-self.fieldOffset(ptr_agg_ty, self.typeOf(extra.field_ptr), extra.field_index));
85528857 return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none });
85538858}
85548859
......@@ -8613,7 +8918,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
86138918 };
86148919
86158920 if (int_info.signedness == .unsigned and self.regExtraBits(limb_ty) > 0) {
8616 const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - limb_bits);
8921 const mask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - limb_bits);
86178922 try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask });
86188923 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
86198924 }
......@@ -8698,7 +9003,7 @@ fn genShiftBinOpMir(
86989003 try self.spillEflagsIfOccupied();
86999004
87009005 if (abi_size > 16) {
8701 const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
9006 const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
87029007 assert(shift_abi_size >= 1 and shift_abi_size <= 2);
87039008
87049009 const rcx_lock: ?RegisterLock = switch (rhs_mcv) {
......@@ -8725,12 +9030,12 @@ fn genShiftBinOpMir(
87259030
87269031 switch (tag[0]) {
87279032 ._l => {
8728 try self.asmRegisterImmediate(.{ ._, .mov }, temp_regs[1].to32(), Immediate.u(limbs_len - 1));
9033 try self.asmRegisterImmediate(.{ ._, .mov }, temp_regs[1].to32(), .u(limbs_len - 1));
87299034 switch (rhs_mcv) {
87309035 .immediate => |shift_imm| try self.asmRegisterImmediate(
87319036 .{ ._, .mov },
87329037 temp_regs[0].to32(),
8733 Immediate.u(limbs_len - (shift_imm >> 6) - 1),
9038 .u(limbs_len - (shift_imm >> 6) - 1),
87349039 ),
87359040 else => {
87369041 try self.asmRegisterRegister(
......@@ -8738,16 +9043,8 @@ fn genShiftBinOpMir(
87389043 temp_regs[2].to32(),
87399044 registerAlias(.rcx, shift_abi_size),
87409045 );
8741 try self.asmRegisterImmediate(
8742 .{ ._, .@"and" },
8743 .cl,
8744 Immediate.u(math.maxInt(u6)),
8745 );
8746 try self.asmRegisterImmediate(
8747 .{ ._r, .sh },
8748 temp_regs[2].to32(),
8749 Immediate.u(6),
8750 );
9046 try self.asmRegisterImmediate(.{ ._, .@"and" }, .cl, .u(std.math.maxInt(u6)));
9047 try self.asmRegisterImmediate(.{ ._r, .sh }, temp_regs[2].to32(), .u(6));
87519048 try self.asmRegisterRegister(
87529049 .{ ._, .mov },
87539050 temp_regs[0].to32(),
......@@ -8767,7 +9064,7 @@ fn genShiftBinOpMir(
87679064 .immediate => |shift_imm| try self.asmRegisterImmediate(
87689065 .{ ._, .mov },
87699066 temp_regs[0].to32(),
8770 Immediate.u(shift_imm >> 6),
9067 .u(shift_imm >> 6),
87719068 ),
87729069 else => {
87739070 try self.asmRegisterRegister(
......@@ -8775,16 +9072,8 @@ fn genShiftBinOpMir(
87759072 temp_regs[0].to32(),
87769073 registerAlias(.rcx, shift_abi_size),
87779074 );
8778 try self.asmRegisterImmediate(
8779 .{ ._, .@"and" },
8780 .cl,
8781 Immediate.u(math.maxInt(u6)),
8782 );
8783 try self.asmRegisterImmediate(
8784 .{ ._r, .sh },
8785 temp_regs[0].to32(),
8786 Immediate.u(6),
8787 );
9075 try self.asmRegisterImmediate(.{ ._, .@"and" }, .cl, .u(std.math.maxInt(u6)));
9076 try self.asmRegisterImmediate(.{ ._r, .sh }, temp_regs[0].to32(), .u(6));
87889077 },
87899078 }
87909079 },
......@@ -8813,7 +9102,7 @@ fn genShiftBinOpMir(
88139102 try self.asmRegisterImmediate(
88149103 .{ ._, .cmp },
88159104 temp_regs[0].to32(),
8816 Immediate.u(limbs_len - 1),
9105 .u(limbs_len - 1),
88179106 );
88189107 break :skip try self.asmJccReloc(.nb, undefined);
88199108 },
......@@ -8843,7 +9132,7 @@ fn genShiftBinOpMir(
88439132 }, .sh },
88449133 temp_regs[2].to64(),
88459134 temp_regs[3].to64(),
8846 Immediate.u(shift_imm & math.maxInt(u6)),
9135 .u(shift_imm & std.math.maxInt(u6)),
88479136 ),
88489137 else => try self.asmRegisterRegisterRegister(.{ switch (tag[0]) {
88499138 ._l => ._ld,
......@@ -8864,8 +9153,8 @@ fn genShiftBinOpMir(
88649153 switch (tag[0]) {
88659154 ._l => {
88669155 if (slow_inc_dec) {
8867 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
8868 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[0].to32(), Immediate.u(1));
9156 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), .u(1));
9157 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[0].to32(), .u(1));
88699158 } else {
88709159 try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
88719160 try self.asmRegister(.{ ._, .dec }, temp_regs[0].to32());
......@@ -8874,8 +9163,8 @@ fn genShiftBinOpMir(
88749163 },
88759164 ._r => {
88769165 if (slow_inc_dec) {
8877 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), Immediate.u(1));
8878 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
9166 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), .u(1));
9167 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
88799168 } else {
88809169 try self.asmRegister(.{ ._, .inc }, temp_regs[1].to32());
88819170 try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
......@@ -8883,7 +9172,7 @@ fn genShiftBinOpMir(
88839172 try self.asmRegisterImmediate(
88849173 .{ ._, .cmp },
88859174 temp_regs[0].to32(),
8886 Immediate.u(limbs_len - 1),
9175 .u(limbs_len - 1),
88879176 );
88889177 _ = try self.asmJccReloc(.b, loop);
88899178 },
......@@ -8898,7 +9187,7 @@ fn genShiftBinOpMir(
88989187 .immediate => |shift_imm| try self.asmRegisterImmediate(
88999188 tag,
89009189 temp_regs[2].to64(),
8901 Immediate.u(shift_imm & math.maxInt(u6)),
9190 .u(shift_imm & std.math.maxInt(u6)),
89029191 ),
89039192 else => try self.asmRegisterRegister(tag, temp_regs[2].to64(), .cl),
89049193 }
......@@ -8914,7 +9203,7 @@ fn genShiftBinOpMir(
89149203 if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate(
89159204 tag,
89169205 temp_regs[2].to64(),
8917 Immediate.u(63),
9206 .u(63),
89189207 );
89199208 if (switch (rhs_mcv) {
89209209 .immediate => |shift_imm| shift_imm >> 6 > 0,
......@@ -8935,7 +9224,7 @@ fn genShiftBinOpMir(
89359224 try self.asmRegisterImmediate(
89369225 .{ ._, .cmp },
89379226 temp_regs[1].to32(),
8938 Immediate.u(limbs_len - 1),
9227 .u(limbs_len - 1),
89399228 );
89409229 break :skip try self.asmJccReloc(.nb, undefined);
89419230 },
......@@ -8945,12 +9234,12 @@ fn genShiftBinOpMir(
89459234 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
89469235 switch (tag[0]) {
89479236 ._l => if (slow_inc_dec) {
8948 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
9237 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), .u(1));
89499238 } else {
89509239 try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
89519240 },
89529241 ._r => if (slow_inc_dec) {
8953 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), Immediate.u(1));
9242 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), .u(1));
89549243 } else {
89559244 try self.asmRegister(.{ ._, .inc }, temp_regs[1].to32());
89569245 },
......@@ -8972,14 +9261,14 @@ fn genShiftBinOpMir(
89729261 .scale = .@"8",
89739262 .disp = lhs_mcv.load_frame.off,
89749263 } },
8975 }, Immediate.u(0));
9264 }, .u(0));
89769265 switch (tag[0]) {
89779266 ._l => _ = try self.asmJccReloc(.nz, loop),
89789267 ._r => {
89799268 try self.asmRegisterImmediate(
89809269 .{ ._, .cmp },
89819270 temp_regs[1].to32(),
8982 Immediate.u(limbs_len - 1),
9271 .u(limbs_len - 1),
89839272 );
89849273 _ = try self.asmJccReloc(.b, loop);
89859274 },
......@@ -9021,12 +9310,12 @@ fn genShiftBinOpMir(
90219310 info.double_tag,
90229311 lhs_regs[info.indices[1]],
90239312 lhs_regs[info.indices[0]],
9024 Immediate.u(shift_imm),
9313 .u(shift_imm),
90259314 );
90269315 try self.asmRegisterImmediate(
90279316 tag,
90289317 lhs_regs[info.indices[0]],
9029 Immediate.u(shift_imm),
9318 .u(shift_imm),
90309319 );
90319320 return;
90329321 } else {
......@@ -9039,7 +9328,7 @@ fn genShiftBinOpMir(
90399328 if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate(
90409329 tag,
90419330 lhs_regs[info.indices[0]],
9042 Immediate.u(63),
9331 .u(63),
90439332 ) else try self.asmRegisterRegister(
90449333 .{ ._, .xor },
90459334 lhs_regs[info.indices[0]],
......@@ -9048,7 +9337,7 @@ fn genShiftBinOpMir(
90489337 if (shift_imm > 64) try self.asmRegisterImmediate(
90499338 tag,
90509339 lhs_regs[info.indices[1]],
9051 Immediate.u(shift_imm - 64),
9340 .u(shift_imm - 64),
90529341 );
90539342 return;
90549343 },
......@@ -9059,7 +9348,7 @@ fn genShiftBinOpMir(
90599348
90609349 if (tag[0] == ._r and tag[1] == .sa) {
90619350 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_regs[info.indices[0]]);
9062 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
9351 try self.asmRegisterImmediate(tag, tmp_reg, .u(63));
90639352 } else try self.asmRegisterRegister(
90649353 .{ ._, .xor },
90659354 tmp_reg.to32(),
......@@ -9076,11 +9365,7 @@ fn genShiftBinOpMir(
90769365 lhs_regs[info.indices[0]],
90779366 registerAlias(shift_reg, 1),
90789367 );
9079 try self.asmRegisterImmediate(
9080 .{ ._, .cmp },
9081 registerAlias(shift_reg, 1),
9082 Immediate.u(64),
9083 );
9368 try self.asmRegisterImmediate(.{ ._, .cmp }, registerAlias(shift_reg, 1), .u(64));
90849369 try self.asmCmovccRegisterRegister(
90859370 .ae,
90869371 lhs_regs[info.indices[1]],
......@@ -9119,7 +9404,7 @@ fn genShiftBinOpMir(
91199404 } },
91209405 },
91219406 tmp_reg,
9122 Immediate.u(shift_imm),
9407 .u(shift_imm),
91239408 );
91249409 try self.asmMemoryImmediate(
91259410 tag,
......@@ -9130,7 +9415,7 @@ fn genShiftBinOpMir(
91309415 .disp = dst_frame_addr.off + info.indices[0] * 8,
91319416 } },
91329417 },
9133 Immediate.u(shift_imm),
9418 .u(shift_imm),
91349419 );
91359420 return;
91369421 } else {
......@@ -9149,7 +9434,7 @@ fn genShiftBinOpMir(
91499434 if (shift_imm > 64) try self.asmRegisterImmediate(
91509435 tag,
91519436 tmp_reg,
9152 Immediate.u(shift_imm - 64),
9437 .u(shift_imm - 64),
91539438 );
91549439 try self.asmMemoryRegister(
91559440 .{ ._, .mov },
......@@ -9171,7 +9456,7 @@ fn genShiftBinOpMir(
91719456 .disp = dst_frame_addr.off + info.indices[0] * 8,
91729457 } },
91739458 },
9174 Immediate.u(63),
9459 .u(63),
91759460 ) else {
91769461 try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());
91779462 try self.asmMemoryRegister(
......@@ -9223,7 +9508,7 @@ fn genShiftBinOpMir(
92239508 );
92249509 if (tag[0] == ._r and tag[1] == .sa) {
92259510 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);
9226 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
9511 try self.asmRegisterImmediate(tag, tmp_reg, .u(63));
92279512 } else try self.asmRegisterRegister(
92289513 .{ ._, .xor },
92299514 tmp_reg.to32(),
......@@ -9239,7 +9524,7 @@ fn genShiftBinOpMir(
92399524 try self.asmRegisterImmediate(
92409525 .{ ._, .cmp },
92419526 registerAlias(shift_reg, 1),
9242 Immediate.u(64),
9527 .u(64),
92439528 );
92449529 try self.asmCmovccRegisterRegister(.ae, second_reg, first_reg);
92459530 try self.asmCmovccRegisterRegister(.ae, first_reg, tmp_reg);
......@@ -9277,7 +9562,7 @@ fn genShiftBinOpMir(
92779562 .immediate => |shift_imm| return self.asmRegisterImmediate(
92789563 tag,
92799564 registerAlias(lhs_reg, abi_size),
9280 Immediate.u(shift_imm),
9565 .u(shift_imm),
92819566 ),
92829567 .register => |shift_reg| return self.asmRegisterRegister(
92839568 tag,
......@@ -9292,7 +9577,7 @@ fn genShiftBinOpMir(
92929577 .base = .{ .reg = .ds },
92939578 .mod = .{ .rm = .{
92949579 .size = Memory.Size.fromSize(abi_size),
9295 .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse
9580 .disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse
92969581 return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
92979582 @tagName(lhs_mcv),
92989583 @tagName(shift_mcv),
......@@ -9316,11 +9601,7 @@ fn genShiftBinOpMir(
93169601 else => unreachable,
93179602 };
93189603 switch (shift_mcv) {
9319 .immediate => |shift_imm| return self.asmMemoryImmediate(
9320 tag,
9321 lhs_mem,
9322 Immediate.u(shift_imm),
9323 ),
9604 .immediate => |shift_imm| return self.asmMemoryImmediate(tag, lhs_mem, .u(shift_imm)),
93249605 .register => |shift_reg| return self.asmMemoryRegister(
93259606 tag,
93269607 lhs_mem,
......@@ -9495,7 +9776,7 @@ fn genMulDivBinOp(
94959776 switch (tag) {
94969777 .mul, .mul_wrap => {
94979778 const slow_inc = self.hasFeature(.slow_incdec);
9498 const limb_len = math.divCeil(u32, src_abi_size, 8) catch unreachable;
9779 const limb_len = std.math.divCeil(u32, src_abi_size, 8) catch unreachable;
94999780
95009781 try self.spillRegisters(&.{ .rax, .rcx, .rdx });
95019782 const reg_locks = self.register_manager.lockRegs(3, .{ .rax, .rcx, .rdx });
......@@ -9536,7 +9817,7 @@ fn genMulDivBinOp(
95369817 try self.asmRegisterRegister(.{ ._, .xor }, .edx, .edx);
95379818
95389819 const inner_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
9539 try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, Immediate.u(1));
9820 try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, .u(1));
95409821 try self.asmMemoryRegister(.{ ._, .adc }, .{
95419822 .base = .{ .frame = dst_mcv.load_frame.index },
95429823 .mod = .{ .rm = .{
......@@ -9559,7 +9840,7 @@ fn genMulDivBinOp(
95599840 });
95609841 try self.asmRegister(.{ ._, .mul }, temp_regs[1].to64());
95619842
9562 try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, Immediate.u(1));
9843 try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, .u(1));
95639844 try self.asmMemoryRegister(.{ ._, .adc }, .{
95649845 .base = .{ .frame = dst_mcv.load_frame.index },
95659846 .mod = .{ .rm = .{
......@@ -9572,30 +9853,22 @@ fn genMulDivBinOp(
95729853 try self.asmSetccRegister(.c, .ch);
95739854
95749855 if (slow_inc) {
9575 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), Immediate.u(1));
9576 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), Immediate.u(1));
9856 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), .u(1));
9857 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), .u(1));
95779858 } else {
95789859 try self.asmRegister(.{ ._, .inc }, temp_regs[2].to32());
95799860 try self.asmRegister(.{ ._, .inc }, temp_regs[3].to32());
95809861 }
9581 try self.asmRegisterImmediate(
9582 .{ ._, .cmp },
9583 temp_regs[3].to32(),
9584 Immediate.u(limb_len),
9585 );
9862 try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[3].to32(), .u(limb_len));
95869863 _ = try self.asmJccReloc(.b, inner_loop);
95879864
95889865 self.performReloc(skip_inner);
95899866 if (slow_inc) {
9590 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
9867 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
95919868 } else {
95929869 try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
95939870 }
9594 try self.asmRegisterImmediate(
9595 .{ ._, .cmp },
9596 temp_regs[0].to32(),
9597 Immediate.u(limb_len),
9598 );
9871 try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[0].to32(), .u(limb_len));
95999872 _ = try self.asmJccReloc(.b, outer_loop);
96009873
96019874 return dst_mcv;
......@@ -9911,7 +10184,7 @@ fn genBinOp(
991110184 dst_reg,
991210185 dst_reg,
991310186 try rhs_mcv.mem(self, .word),
9914 Immediate.u(1),
10187 .u(1),
991510188 ) else try self.asmRegisterRegisterRegister(
991610189 .{ .vp_, .unpcklwd },
991710190 dst_reg,
......@@ -9969,7 +10242,7 @@ fn genBinOp(
996910242 .{ .v_, .cvtps2ph },
997010243 dst_reg,
997110244 dst_reg,
9972 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
10245 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
997310246 );
997410247 break :adjusted .{ .register = dst_reg };
997510248 },
......@@ -10278,7 +10551,7 @@ fn genBinOp(
1027810551 .lea_tlv,
1027910552 .lea_frame,
1028010553 => true,
10281 .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null,
10554 .memory => |addr| std.math.cast(i32, @as(i64, @bitCast(addr))) == null,
1028210555 else => false,
1028310556 .register_pair,
1028410557 .register_overflow,
......@@ -10410,7 +10683,7 @@ fn genBinOp(
1041010683 dst_reg,
1041110684 dst_reg,
1041210685 try src_mcv.mem(self, .word),
10413 Immediate.u(1),
10686 .u(1),
1041410687 ) else try self.asmRegisterRegisterRegister(
1041510688 .{ .vp_, .unpcklwd },
1041610689 dst_reg,
......@@ -10442,7 +10715,7 @@ fn genBinOp(
1044210715 dst_reg,
1044310716 dst_reg,
1044410717 dst_reg,
10445 Immediate.u(@as(u5, @bitCast(RoundMode{
10718 .u(@as(u5, @bitCast(RoundMode{
1044610719 .mode = switch (air_tag) {
1044710720 .div_trunc => .zero,
1044810721 .div_floor => .down,
......@@ -10457,7 +10730,7 @@ fn genBinOp(
1045710730 .{ .v_, .cvtps2ph },
1045810731 dst_reg,
1045910732 dst_reg,
10460 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
10733 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
1046110734 );
1046210735 return dst_mcv;
1046310736 },
......@@ -10856,7 +11129,7 @@ fn genBinOp(
1085611129 dst_reg,
1085711130 dst_reg,
1085811131 try src_mcv.mem(self, .word),
10859 Immediate.u(1),
11132 .u(1),
1086011133 ) else try self.asmRegisterRegisterRegister(
1086111134 .{ .vp_, .unpcklwd },
1086211135 dst_reg,
......@@ -10886,7 +11159,7 @@ fn genBinOp(
1088611159 .{ .v_, .cvtps2ph },
1088711160 dst_reg,
1088811161 dst_reg,
10889 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
11162 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
1089011163 );
1089111164 return dst_mcv;
1089211165 },
......@@ -10902,7 +11175,7 @@ fn genBinOp(
1090211175 .{ .vp_d, .insr },
1090311176 dst_reg,
1090411177 try src_mcv.mem(self, .dword),
10905 Immediate.u(1),
11178 .u(1),
1090611179 ) else try self.asmRegisterRegisterRegister(
1090711180 .{ .v_ps, .unpckl },
1090811181 dst_reg,
......@@ -10937,7 +11210,7 @@ fn genBinOp(
1093711210 .{ .v_, .cvtps2ph },
1093811211 dst_reg,
1093911212 dst_reg,
10940 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
11213 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
1094111214 );
1094211215 return dst_mcv;
1094311216 },
......@@ -10980,7 +11253,7 @@ fn genBinOp(
1098011253 .{ .v_, .cvtps2ph },
1098111254 dst_reg,
1098211255 dst_reg,
10983 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
11256 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
1098411257 );
1098511258 return dst_mcv;
1098611259 },
......@@ -11023,7 +11296,7 @@ fn genBinOp(
1102311296 .{ .v_, .cvtps2ph },
1102411297 dst_reg,
1102511298 dst_reg.to256(),
11026 Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
11299 .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
1102711300 );
1102811301 return dst_mcv;
1102911302 },
......@@ -11191,7 +11464,7 @@ fn genBinOp(
1119111464 );
1119211465 },
1119311466 .cmp => {
11194 const imm = Immediate.u(switch (air_tag) {
11467 const imm: Immediate = .u(switch (air_tag) {
1119511468 .cmp_eq => 0,
1119611469 .cmp_lt, .cmp_gt => 1,
1119711470 .cmp_lte, .cmp_gte => 2,
......@@ -11289,7 +11562,7 @@ fn genBinOp(
1128911562 mask_reg,
1129011563 rhs_copy_reg,
1129111564 rhs_copy_reg,
11292 Immediate.u(3), // unord
11565 .u(3), // unord
1129311566 );
1129411567 try self.asmRegisterRegisterRegisterRegister(
1129511568 @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(zcu)) {
......@@ -11356,7 +11629,7 @@ fn genBinOp(
1135611629 }),
1135711630 mask_reg,
1135811631 mask_reg,
11359 Immediate.u(if (has_blend) 3 else 7), // unord, ord
11632 .u(if (has_blend) 3 else 7), // unord, ord
1136011633 );
1136111634 if (has_blend) try self.asmRegisterRegisterRegister(
1136211635 @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(zcu)) {
......@@ -11567,29 +11840,29 @@ fn genBinOpMir(
1156711840 8 => try self.asmRegisterImmediate(
1156811841 mir_limb_tag,
1156911842 dst_alias,
11570 if (math.cast(i8, @as(i64, @bitCast(imm)))) |small|
11571 Immediate.s(small)
11843 if (std.math.cast(i8, @as(i64, @bitCast(imm)))) |small|
11844 .s(small)
1157211845 else
11573 Immediate.u(@as(u8, @intCast(imm))),
11846 .u(@as(u8, @intCast(imm))),
1157411847 ),
1157511848 16 => try self.asmRegisterImmediate(
1157611849 mir_limb_tag,
1157711850 dst_alias,
11578 if (math.cast(i16, @as(i64, @bitCast(imm)))) |small|
11579 Immediate.s(small)
11851 if (std.math.cast(i16, @as(i64, @bitCast(imm)))) |small|
11852 .s(small)
1158011853 else
11581 Immediate.u(@as(u16, @intCast(imm))),
11854 .u(@as(u16, @intCast(imm))),
1158211855 ),
1158311856 32 => try self.asmRegisterImmediate(
1158411857 mir_limb_tag,
1158511858 dst_alias,
11586 if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
11587 Immediate.s(small)
11859 if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
11860 .s(small)
1158811861 else
11589 Immediate.u(@as(u32, @intCast(imm))),
11862 .u(@as(u32, @intCast(imm))),
1159011863 ),
11591 64 => if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
11592 try self.asmRegisterImmediate(mir_limb_tag, dst_alias, Immediate.s(small))
11864 64 => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
11865 try self.asmRegisterImmediate(mir_limb_tag, dst_alias, .s(small))
1159311866 else
1159411867 try self.asmRegisterRegister(mir_limb_tag, dst_alias, registerAlias(
1159511868 try self.copyToTmpRegister(ty, src_mcv),
......@@ -11619,7 +11892,7 @@ fn genBinOpMir(
1161911892 .base = .{ .reg = .ds },
1162011893 .mod = .{ .rm = .{
1162111894 .size = Memory.Size.fromSize(limb_abi_size),
11622 .disp = math.cast(i32, addr + off) orelse break :direct,
11895 .disp = std.math.cast(i32, addr + off) orelse break :direct,
1162311896 } },
1162411897 },
1162511898 .indirect => |reg_off| .{
......@@ -11731,8 +12004,8 @@ fn genBinOpMir(
1173112004 => null,
1173212005 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
1173312006 switch (resolved_src_mcv) {
11734 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and
11735 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
12007 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and
12008 std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
1173612009 break :src null,
1173712010 .load_symbol, .load_got, .load_direct, .load_tlv => {},
1173812011 else => unreachable,
......@@ -11823,33 +12096,29 @@ fn genBinOpMir(
1182312096 8 => try self.asmMemoryImmediate(
1182412097 mir_limb_tag,
1182512098 dst_limb_mem,
11826 if (math.cast(i8, @as(i64, @bitCast(imm)))) |small|
11827 Immediate.s(small)
12099 if (std.math.cast(i8, @as(i64, @bitCast(imm)))) |small|
12100 .s(small)
1182812101 else
11829 Immediate.u(@as(u8, @intCast(imm))),
12102 .u(@as(u8, @intCast(imm))),
1183012103 ),
1183112104 16 => try self.asmMemoryImmediate(
1183212105 mir_limb_tag,
1183312106 dst_limb_mem,
11834 if (math.cast(i16, @as(i64, @bitCast(imm)))) |small|
11835 Immediate.s(small)
12107 if (std.math.cast(i16, @as(i64, @bitCast(imm)))) |small|
12108 .s(small)
1183612109 else
11837 Immediate.u(@as(u16, @intCast(imm))),
12110 .u(@as(u16, @intCast(imm))),
1183812111 ),
1183912112 32 => try self.asmMemoryImmediate(
1184012113 mir_limb_tag,
1184112114 dst_limb_mem,
11842 if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
11843 Immediate.s(small)
12115 if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
12116 .s(small)
1184412117 else
11845 Immediate.u(@as(u32, @intCast(imm))),
12118 .u(@as(u32, @intCast(imm))),
1184612119 ),
11847 64 => if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
11848 try self.asmMemoryImmediate(
11849 mir_limb_tag,
11850 dst_limb_mem,
11851 Immediate.s(small),
11852 )
12120 64 => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
12121 try self.asmMemoryImmediate(mir_limb_tag, dst_limb_mem, .s(small))
1185312122 else
1185412123 try self.asmMemoryRegister(
1185512124 mir_limb_tag,
......@@ -11973,12 +12242,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
1197312242 registerAlias(src_reg, abi_size),
1197412243 ),
1197512244 .immediate => |imm| {
11976 if (math.cast(i32, imm)) |small| {
12245 if (std.math.cast(i32, imm)) |small| {
1197712246 try self.asmRegisterRegisterImmediate(
1197812247 .{ .i_, .mul },
1197912248 dst_alias,
1198012249 dst_alias,
11981 Immediate.s(small),
12250 .s(small),
1198212251 );
1198312252 } else {
1198412253 const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv);
......@@ -12009,7 +12278,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
1200912278 .base = .{ .reg = .ds },
1201012279 .mod = .{ .rm = .{
1201112280 .size = Memory.Size.fromSize(abi_size),
12012 .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse
12281 .disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse
1201312282 return self.asmRegisterRegister(
1201412283 .{ .i_, .mul },
1201512284 dst_alias,
......@@ -12087,11 +12356,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1208712356 ) |dst_reg, elem_index| {
1208812357 assert(self.register_manager.isRegFree(dst_reg));
1208912358 if (elem_index > 0) {
12090 try self.asmRegisterImmediate(
12091 .{ ._l, .sh },
12092 dst_reg.to8(),
12093 Immediate.u(elem_index),
12094 );
12359 try self.asmRegisterImmediate(.{ ._l, .sh }, dst_reg.to8(), .u(elem_index));
1209512360 try self.asmRegisterRegister(
1209612361 .{ ._, .@"or" },
1209712362 dst_reg.to8(),
......@@ -12127,7 +12392,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1212712392 try self.asmRegisterImmediate(
1212812393 .{ ._, .mov },
1212912394 index_reg.to32(),
12130 Immediate.u(regs_frame_addr.regs),
12395 .u(regs_frame_addr.regs),
1213112396 );
1213212397 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
1213312398 try self.asmMemoryImmediate(.{ ._, .cmp }, .{
......@@ -12147,14 +12412,14 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1214712412 );
1214812413 self.performReloc(unset);
1214912414 if (self.hasFeature(.slow_incdec)) {
12150 try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), Immediate.u(1));
12415 try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
1215112416 } else {
1215212417 try self.asmRegister(.{ ._, .inc }, index_reg.to32());
1215312418 }
1215412419 try self.asmRegisterImmediate(
1215512420 .{ ._, .cmp },
1215612421 index_reg.to32(),
12157 Immediate.u(arg_ty.vectorLen(zcu)),
12422 .u(arg_ty.vectorLen(zcu)),
1215812423 );
1215912424 _ = try self.asmJccReloc(.b, loop);
1216012425
......@@ -12180,7 +12445,6 @@ fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void {
1218012445 for (self.args[self.arg_index..]) |arg| {
1218112446 if (arg != .none) break;
1218212447 } else try self.airDbgVarArgs();
12183 self.finishAirBookkeeping();
1218412448}
1218512449
1218612450fn airDbgVarArgs(self: *Self) !void {
......@@ -12200,9 +12464,9 @@ fn genLocalDebugInfo(
1220012464 switch (mcv) {
1220112465 .none => try self.asmAir(.dbg_local, inst),
1220212466 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
12203 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),
12467 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, .u(imm)),
1220412468 .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
12205 .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, Immediate.rel(sym_off)),
12469 .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, .rel(sym_off)),
1220612470 else => {
1220712471 const ty = switch (tag) {
1220812472 else => unreachable,
......@@ -12245,16 +12509,6 @@ fn genLocalDebugInfo(
1224512509 }
1224612510}
1224712511
12248fn airTrap(self: *Self) !void {
12249 try self.asmOpOnly(.{ ._, .ud2 });
12250 self.finishAirBookkeeping();
12251}
12252
12253fn airBreakpoint(self: *Self) !void {
12254 try self.asmOpOnly(.{ ._, .int3 });
12255 self.finishAirBookkeeping();
12256}
12257
1225812512fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {
1225912513 const dst_mcv = try self.allocRegOrMem(inst, true);
1226012514 try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }, .{});
......@@ -12426,7 +12680,7 @@ fn genCall(self: *Self, info: union(enum) {
1242612680 try self.asmRegisterImmediate(
1242712681 .{ ._, .mov },
1242812682 index_reg.to32(),
12429 Immediate.u(regs_frame_addr.regs),
12683 .u(regs_frame_addr.regs),
1243012684 );
1243112685 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
1243212686 try self.asmMemoryRegister(.{ ._, .bt }, src_mem, index_reg.to32());
......@@ -12440,14 +12694,14 @@ fn genCall(self: *Self, info: union(enum) {
1244012694 } },
1244112695 });
1244212696 if (self.hasFeature(.slow_incdec)) {
12443 try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), Immediate.u(1));
12697 try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
1244412698 } else {
1244512699 try self.asmRegister(.{ ._, .inc }, index_reg.to32());
1244612700 }
1244712701 try self.asmRegisterImmediate(
1244812702 .{ ._, .cmp },
1244912703 index_reg.to32(),
12450 Immediate.u(arg_ty.vectorLen(zcu)),
12704 .u(arg_ty.vectorLen(zcu)),
1245112705 );
1245212706 _ = try self.asmJccReloc(.b, loop);
1245312707
......@@ -12521,11 +12775,7 @@ fn genCall(self: *Self, info: union(enum) {
1252112775 0..,
1252212776 ) |dst_reg, elem_index| {
1252312777 try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
12524 try self.asmMemoryImmediate(
12525 .{ ._, .bt },
12526 src_mem,
12527 Immediate.u(elem_index),
12528 );
12778 try self.asmMemoryImmediate(.{ ._, .bt }, src_mem, .u(elem_index));
1252912779 try self.asmSetccRegister(.c, dst_reg.to8());
1253012780 }
1253112781 },
......@@ -12533,7 +12783,7 @@ fn genCall(self: *Self, info: union(enum) {
1253312783 };
1253412784
1253512785 if (fn_info.is_var_args)
12536 try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count));
12786 try self.asmRegisterImmediate(.{ ._, .mov }, .al, .u(call_info.fp_count));
1253712787
1253812788 // Due to incremental compilation, how function calls are generated depends
1253912789 // on linking.
......@@ -12551,7 +12801,7 @@ fn genCall(self: *Self, info: union(enum) {
1255112801 if (self.bin_file.cast(.elf)) |elf_file| {
1255212802 const zo = elf_file.zigObjectPtr().?;
1255312803 const sym_index = try zo.getOrCreateMetadataForNav(zcu, func.owner_nav);
12554 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
12804 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index }));
1255512805 } else if (self.bin_file.cast(.coff)) |coff_file| {
1255612806 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
1255712807 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
......@@ -12561,7 +12811,7 @@ fn genCall(self: *Self, info: union(enum) {
1256112811 const zo = macho_file.getZigObject().?;
1256212812 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
1256312813 const sym = zo.symbols.items[sym_index];
12564 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
12814 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym.nlist_idx }));
1256512815 } else if (self.bin_file.cast(.plan9)) |p9| {
1256612816 const atom_index = try p9.seeNav(pt, func.owner_nav);
1256712817 const atom = p9.getAtom(atom_index);
......@@ -12579,13 +12829,13 @@ fn genCall(self: *Self, info: union(enum) {
1257912829 @"extern".name.toSlice(ip),
1258012830 @"extern".lib_name.toSlice(ip),
1258112831 );
12582 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12832 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
1258312833 } else if (self.bin_file.cast(.macho)) |macho_file| {
1258412834 const target_sym_index = try macho_file.getGlobalSymbol(
1258512835 @"extern".name.toSlice(ip),
1258612836 @"extern".lib_name.toSlice(ip),
1258712837 );
12588 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12838 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
1258912839 } else try self.genExternSymbolRef(
1259012840 .call,
1259112841 @"extern".lib_name.toSlice(ip),
......@@ -12600,10 +12850,10 @@ fn genCall(self: *Self, info: union(enum) {
1260012850 },
1260112851 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
1260212852 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
12603 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12853 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
1260412854 } else if (self.bin_file.cast(.macho)) |macho_file| {
1260512855 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
12606 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12856 try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
1260712857 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
1260812858 }
1260912859 return call_info.return_value.short;
......@@ -12665,7 +12915,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
1266512915 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);
1266612916}
1266712917
12668fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
12918fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void {
1266912919 const pt = self.pt;
1267012920 const zcu = pt.zcu;
1267112921 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
......@@ -12754,7 +13004,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1275413004 try self.asmRegisterImmediate(
1275513005 .{ ._r, .sh },
1275613006 registerAlias(temp_lhs_reg, opt_abi_size),
12757 Immediate.u(payload_abi_size * 8),
13007 .u(payload_abi_size * 8),
1275813008 );
1275913009 }
1276013010
......@@ -12775,7 +13025,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1277513025 try self.asmRegisterImmediate(
1277613026 .{ ._r, .sh },
1277713027 registerAlias(temp_rhs_reg, opt_abi_size),
12778 Immediate.u(payload_abi_size * 8),
13028 .u(payload_abi_size * 8),
1277913029 );
1278013030 try self.asmRegisterRegister(
1278113031 .{ ._, .@"test" },
......@@ -12867,10 +13117,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1286713117 .register_pair, .load_frame => null,
1286813118 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: {
1286913119 switch (resolved_dst_mcv) {
12870 .memory => |addr| if (math.cast(
13120 .memory => |addr| if (std.math.cast(
1287113121 i32,
1287213122 @as(i64, @bitCast(addr)),
12873 ) != null and math.cast(
13123 ) != null and std.math.cast(
1287413124 i32,
1287513125 @as(i64, @bitCast(addr)) + abi_size - 8,
1287613126 ) != null) break :dst null,
......@@ -12928,10 +13178,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1292813178 .register_pair, .load_frame => null,
1292913179 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
1293013180 switch (resolved_src_mcv) {
12931 .memory => |addr| if (math.cast(
13181 .memory => |addr| if (std.math.cast(
1293213182 i32,
1293313183 @as(i64, @bitCast(addr)),
12934 ) != null and math.cast(
13184 ) != null and std.math.cast(
1293513185 i32,
1293613186 @as(i64, @bitCast(addr)) + abi_size - 8,
1293713187 ) != null) break :src null,
......@@ -12971,7 +13221,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1297113221 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);
1297213222 defer for (locks) |lock| self.register_manager.unlockReg(lock);
1297313223
12974 const limbs_len = math.divCeil(u16, abi_size, 8) catch unreachable;
13224 const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable;
1297513225 var limb_i: u16 = 0;
1297613226 while (limb_i < limbs_len) : (limb_i += 1) {
1297713227 const off = limb_i * 8;
......@@ -13067,7 +13317,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1306713317 tmp1_reg,
1306813318 dst_reg.to128(),
1306913319 try src_mcv.mem(self, .word),
13070 Immediate.u(1),
13320 .u(1),
1307113321 ) else try self.asmRegisterRegisterRegister(
1307213322 .{ .vp_, .unpcklwd },
1307313323 tmp1_reg,
......@@ -13232,7 +13482,6 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1323213482 .column = dbg_stmt.column,
1323313483 } },
1323413484 });
13235 self.finishAirBookkeeping();
1323613485}
1323713486
1323813487fn airDbgEmptyStmt(self: *Self) !void {
......@@ -13240,7 +13489,6 @@ fn airDbgEmptyStmt(self: *Self) !void {
1324013489 self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] == .pseudo_dbg_line_stmt_line_column)
1324113490 self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] = .pseudo_dbg_line_line_column;
1324213491 try self.asmOpOnly(.{ ._, .nop });
13243 self.finishAirBookkeeping();
1324413492}
1324513493
1324613494fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
......@@ -13278,7 +13526,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
1327813526 },
1327913527 .register => |reg| {
1328013528 try self.spillEflagsIfOccupied();
13281 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg.to8(), Immediate.u(1));
13529 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg.to8(), .u(1));
1328213530 return self.asmJccReloc(.z, undefined);
1328313531 },
1328413532 .immediate,
......@@ -13338,7 +13586,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1333813586 });
1333913587
1334013588 // We already took care of pl_op.operand earlier, so there's nothing left to do.
13341 self.finishAirBookkeeping();
1334213589}
1334313590
1334413591fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {
......@@ -13353,7 +13600,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1335313600
1335413601 const pl_ty = opt_ty.optionalChild(zcu);
1335513602
13356 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
13603 const some_info: struct { off: u31, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
1335713604 .{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }
1335813605 else
1335913606 .{ .off = @intCast(pl_ty.abiSize(zcu)), .ty = Type.bool };
......@@ -13366,7 +13613,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1336613613 .undef,
1336713614 .immediate,
1336813615 .eflags,
13369 .register_pair,
1337013616 .register_offset,
1337113617 .register_overflow,
1337213618 .lea_direct,
......@@ -13396,7 +13642,25 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1339613642 try self.asmRegisterImmediate(
1339713643 .{ ._, .bt },
1339813644 registerAlias(opt_reg, opt_abi_size),
13399 Immediate.u(@as(u6, @intCast(some_info.off * 8))),
13645 .u(@as(u6, @intCast(some_info.off * 8))),
13646 );
13647 return .{ .eflags = .nc };
13648 },
13649
13650 .register_pair => |opt_regs| {
13651 if (some_info.off == 0) {
13652 const some_abi_size: u32 = @intCast(some_info.ty.abiSize(zcu));
13653 const alias_reg = registerAlias(opt_regs[0], some_abi_size);
13654 assert(some_abi_size * 8 == alias_reg.bitSize());
13655 try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);
13656 return .{ .eflags = .z };
13657 }
13658 assert(some_info.ty.ip_index == .bool_type);
13659 const opt_abi_size: u32 = @intCast(opt_ty.abiSize(zcu));
13660 try self.asmRegisterImmediate(
13661 .{ ._, .bt },
13662 registerAlias(opt_regs[some_info.off / 8], opt_abi_size),
13663 .u(@as(u6, @truncate(some_info.off * 8))),
1340013664 );
1340113665 return .{ .eflags = .nc };
1340213666 },
......@@ -13422,7 +13686,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1342213686 .disp = some_info.off,
1342313687 } },
1342413688 },
13425 Immediate.u(0),
13689 .u(0),
1342613690 );
1342713691 return .{ .eflags = .e };
1342813692 },
......@@ -13448,7 +13712,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1344813712 },
1344913713 else => unreachable,
1345013714 },
13451 Immediate.u(0),
13715 .u(0),
1345213716 );
1345313717 return .{ .eflags = .e };
1345413718 },
......@@ -13485,7 +13749,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
1348513749 .disp = some_info.off,
1348613750 } },
1348713751 },
13488 Immediate.u(0),
13752 .u(0),
1348913753 );
1349013754
1349113755 self.eflags_inst = inst;
......@@ -13500,7 +13764,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
1350013764
1350113765 try self.spillEflagsIfOccupied();
1350213766
13503 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
13767 const err_off: u31 = @intCast(codegen.errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
1350413768 switch (eu_mcv) {
1350513769 .register => |reg| {
1350613770 const eu_lock = self.register_manager.lockReg(reg);
......@@ -13557,7 +13821,7 @@ fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCV
1355713821 const ptr_lock = self.register_manager.lockReg(ptr_reg);
1355813822 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
1355913823
13560 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
13824 const err_off: u31 = @intCast(codegen.errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
1356113825 try self.asmMemoryImmediate(
1356213826 .{ ._, .cmp },
1356313827 .{
......@@ -13567,7 +13831,7 @@ fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCV
1356713831 .disp = err_off,
1356813832 } },
1356913833 },
13570 Immediate.u(0),
13834 .u(0),
1357113835 );
1357213836
1357313837 if (maybe_inst) |inst| self.eflags_inst = inst;
......@@ -13686,12 +13950,11 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {
1368613950
1368713951 try self.loops.putNoClobber(self.gpa, inst, .{
1368813952 .state = state,
13689 .jmp_target = @intCast(self.mir_instructions.len),
13953 .target = @intCast(self.mir_instructions.len),
1369013954 });
1369113955 defer assert(self.loops.remove(inst));
1369213956
1369313957 try self.genBodyBlock(body);
13694 self.finishAirBookkeeping();
1369513958}
1369613959
1369713960fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
......@@ -13729,7 +13992,6 @@ fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !
1372913992 const tracking = &self.inst_tracking.values()[inst_tracking_i];
1373013993 if (self.liveness.isUnused(inst)) try tracking.die(self, inst);
1373113994 self.getValueIfFree(tracking.short, inst);
13732 self.finishAirBookkeeping();
1373313995}
1373413996
1373513997fn lowerSwitchBr(self: *Self, inst: Air.Inst.Index, switch_br: Air.UnwrappedSwitch, condition: MCValue) !void {
......@@ -13864,7 +14126,6 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
1386414126 try self.lowerSwitchBr(inst, switch_br, condition);
1386514127
1386614128 // We already took care of pl_op.operand earlier, so there's nothing left to do
13867 self.finishAirBookkeeping();
1386814129}
1386914130
1387014131fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
......@@ -13893,7 +14154,7 @@ fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
1389314154
1389414155 try self.loops.putNoClobber(self.gpa, inst, .{
1389514156 .state = state,
13896 .jmp_target = @intCast(self.mir_instructions.len),
14157 .target = @intCast(self.mir_instructions.len),
1389714158 });
1389814159 defer assert(self.loops.remove(inst));
1389914160
......@@ -13903,7 +14164,6 @@ fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
1390314164 try self.lowerSwitchBr(inst, switch_br, mat_cond);
1390414165
1390514166 try self.processDeath(inst);
13906 self.finishAirBookkeeping();
1390714167}
1390814168
1390914169fn airSwitchDispatch(self: *Self, inst: Air.Inst.Index) !void {
......@@ -13945,12 +14205,10 @@ fn airSwitchDispatch(self: *Self, inst: Air.Inst.Index) !void {
1394514205
1394614206 // Emit a jump with a relocation. It will be patched up after the block ends.
1394714207 // Leave the jump offset undefined
13948 _ = try self.asmJmpReloc(loop_data.jmp_target);
14208 _ = try self.asmJmpReloc(loop_data.target);
1394914209
1395014210 // Stop tracking block result without forgetting tracking info
1395114211 try self.freeValue(block_tracking.short);
13952
13953 self.finishAirBookkeeping();
1395414212}
1395514213
1395614214fn performReloc(self: *Self, reloc: Mir.Inst.Index) void {
......@@ -14023,8 +14281,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
1402314281
1402414282 // Stop tracking block result without forgetting tracking info
1402514283 try self.freeValue(block_tracking.short);
14026
14027 self.finishAirBookkeeping();
1402814284}
1402914285
1403014286fn airRepeat(self: *Self, inst: Air.Inst.Index) !void {
......@@ -14036,8 +14292,7 @@ fn airRepeat(self: *Self, inst: Air.Inst.Index) !void {
1403614292 .resurrect = false,
1403714293 .close_scope = true,
1403814294 });
14039 _ = try self.asmJmpReloc(repeat_info.jmp_target);
14040 self.finishAirBookkeeping();
14295 _ = try self.asmJmpReloc(repeat_info.target);
1404114296}
1404214297
1404314298fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
......@@ -14068,9 +14323,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1406814323
1406914324 var outputs_extra_i = extra_i;
1407014325 for (outputs) |output| {
14071 const extra_bytes = mem.sliceAsBytes(self.air.extra[extra_i..]);
14072 const constraint = mem.sliceTo(mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
14073 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
14326 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
14327 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
14328 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
1407414329 // This equation accounts for the fact that even if we have exactly 4 bytes
1407514330 // for the string, we still use the next u32 for the null terminator.
1407614331 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
......@@ -14097,8 +14352,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1409714352 const is_early_clobber = constraint[1] == '&';
1409814353 const rest = constraint[@as(usize, 1) + @intFromBool(is_early_clobber) ..];
1409914354 const arg_mcv: MCValue = arg_mcv: {
14100 const arg_maybe_reg: ?Register = if (mem.eql(u8, rest, "r") or
14101 mem.eql(u8, rest, "f") or mem.eql(u8, rest, "x"))
14355 const arg_maybe_reg: ?Register = if (std.mem.eql(u8, rest, "r") or
14356 std.mem.eql(u8, rest, "f") or std.mem.eql(u8, rest, "x"))
1410214357 registerAlias(
1410314358 self.register_manager.tryAllocReg(maybe_inst, switch (rest[0]) {
1410414359 'r' => abi.RegisterClass.gp,
......@@ -14108,20 +14363,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1410814363 }) orelse return self.fail("ran out of registers lowering inline asm", .{}),
1410914364 @intCast(ty.abiSize(zcu)),
1411014365 )
14111 else if (mem.eql(u8, rest, "m"))
14366 else if (std.mem.eql(u8, rest, "m"))
1411214367 if (output != .none) null else return self.fail(
1411314368 "memory constraint unsupported for asm result: '{s}'",
1411414369 .{constraint},
1411514370 )
14116 else if (mem.eql(u8, rest, "g") or
14117 mem.eql(u8, rest, "rm") or mem.eql(u8, rest, "mr") or
14118 mem.eql(u8, rest, "r,m") or mem.eql(u8, rest, "m,r"))
14371 else if (std.mem.eql(u8, rest, "g") or
14372 std.mem.eql(u8, rest, "rm") or std.mem.eql(u8, rest, "mr") or
14373 std.mem.eql(u8, rest, "r,m") or std.mem.eql(u8, rest, "m,r"))
1411914374 self.register_manager.tryAllocReg(maybe_inst, abi.RegisterClass.gp) orelse
1412014375 if (output != .none)
1412114376 null
1412214377 else
1412314378 return self.fail("ran out of registers lowering inline asm", .{})
14124 else if (mem.startsWith(u8, rest, "{") and mem.endsWith(u8, rest, "}"))
14379 else if (std.mem.startsWith(u8, rest, "{") and std.mem.endsWith(u8, rest, "}"))
1412514380 parseRegName(rest["{".len .. rest.len - "}".len]) orelse
1412614381 return self.fail("invalid register constraint: '{s}'", .{constraint})
1412714382 else if (rest.len == 1 and std.ascii.isDigit(rest[0])) {
......@@ -14134,7 +14389,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1413414389 break :arg_mcv if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
1413514390 const ptr_mcv = try self.resolveInst(output);
1413614391 switch (ptr_mcv) {
14137 .immediate => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
14392 .immediate => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
1413814393 break :arg ptr_mcv.deref(),
1413914394 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
1414014395 else => {},
......@@ -14145,7 +14400,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1414514400 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
1414614401 _ = self.register_manager.lockReg(reg);
1414714402 };
14148 if (!mem.eql(u8, name, "_"))
14403 if (!std.mem.eql(u8, name, "_"))
1414914404 arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));
1415014405 args.appendAssumeCapacity(arg_mcv);
1415114406 if (output == .none) result = arg_mcv;
......@@ -14153,17 +14408,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1415314408 }
1415414409
1415514410 for (inputs) |input| {
14156 const input_bytes = mem.sliceAsBytes(self.air.extra[extra_i..]);
14157 const constraint = mem.sliceTo(input_bytes, 0);
14158 const name = mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
14411 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
14412 const constraint = std.mem.sliceTo(input_bytes, 0);
14413 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
1415914414 // This equation accounts for the fact that even if we have exactly 4 bytes
1416014415 // for the string, we still use the next u32 for the null terminator.
1416114416 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
1416214417
1416314418 const ty = self.typeOf(input);
1416414419 const input_mcv = try self.resolveInst(input);
14165 const arg_mcv: MCValue = if (mem.eql(u8, constraint, "r") or
14166 mem.eql(u8, constraint, "f") or mem.eql(u8, constraint, "x"))
14420 const arg_mcv: MCValue = if (std.mem.eql(u8, constraint, "r") or
14421 std.mem.eql(u8, constraint, "f") or std.mem.eql(u8, constraint, "x"))
1416714422 arg: {
1416814423 const rc = switch (constraint[0]) {
1416914424 'r' => abi.RegisterClass.gp,
......@@ -14177,16 +14432,16 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1417714432 const reg = try self.register_manager.allocReg(null, rc);
1417814433 try self.genSetReg(reg, ty, input_mcv, .{});
1417914434 break :arg .{ .register = registerAlias(reg, @intCast(ty.abiSize(zcu))) };
14180 } else if (mem.eql(u8, constraint, "i") or mem.eql(u8, constraint, "n"))
14435 } else if (std.mem.eql(u8, constraint, "i") or std.mem.eql(u8, constraint, "n"))
1418114436 switch (input_mcv) {
1418214437 .immediate => |imm| .{ .immediate = imm },
1418314438 else => return self.fail("immediate operand requires comptime value: '{s}'", .{
1418414439 constraint,
1418514440 }),
1418614441 }
14187 else if (mem.eql(u8, constraint, "m")) arg: {
14442 else if (std.mem.eql(u8, constraint, "m")) arg: {
1418814443 switch (input_mcv) {
14189 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
14444 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
1419014445 break :arg input_mcv,
1419114446 .indirect, .load_frame => break :arg input_mcv,
1419214447 .load_symbol, .load_direct, .load_got, .load_tlv => {},
......@@ -14203,22 +14458,22 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1420314458 };
1420414459 try self.genSetReg(addr_reg, Type.usize, input_mcv.address(), .{});
1420514460 break :arg .{ .indirect = .{ .reg = addr_reg } };
14206 } else if (mem.eql(u8, constraint, "g") or
14207 mem.eql(u8, constraint, "rm") or mem.eql(u8, constraint, "mr") or
14208 mem.eql(u8, constraint, "r,m") or mem.eql(u8, constraint, "m,r"))
14461 } else if (std.mem.eql(u8, constraint, "g") or
14462 std.mem.eql(u8, constraint, "rm") or std.mem.eql(u8, constraint, "mr") or
14463 std.mem.eql(u8, constraint, "r,m") or std.mem.eql(u8, constraint, "m,r"))
1420914464 arg: {
1421014465 switch (input_mcv) {
1421114466 .register, .indirect, .load_frame => break :arg input_mcv,
14212 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
14467 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
1421314468 break :arg input_mcv,
1421414469 else => {},
1421514470 }
1421614471 const temp_mcv = try self.allocTempRegOrMem(ty, true);
1421714472 try self.genCopy(ty, temp_mcv, input_mcv, .{});
1421814473 break :arg temp_mcv;
14219 } else if (mem.eql(u8, constraint, "X"))
14474 } else if (std.mem.eql(u8, constraint, "X"))
1422014475 input_mcv
14221 else if (mem.startsWith(u8, constraint, "{") and mem.endsWith(u8, constraint, "}")) arg: {
14476 else if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) arg: {
1422214477 const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse
1422314478 return self.fail("invalid register constraint: '{s}'", .{constraint});
1422414479 try self.register_manager.getReg(reg, null);
......@@ -14233,7 +14488,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1423314488 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
1423414489 _ = self.register_manager.lockReg(reg);
1423514490 };
14236 if (!mem.eql(u8, name, "_"))
14491 if (!std.mem.eql(u8, name, "_"))
1423714492 arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));
1423814493 args.appendAssumeCapacity(arg_mcv);
1423914494 }
......@@ -14241,7 +14496,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1424114496 {
1424214497 var clobber_i: u32 = 0;
1424314498 while (clobber_i < clobbers_len) : (clobber_i += 1) {
14244 const clobber = mem.sliceTo(mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
14499 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
1424514500 // This equation accounts for the fact that even if we have exactly 4 bytes
1424614501 // for the string, we still use the next u32 for the null terminator.
1424714502 extra_i += clobber.len / 4 + 1;
......@@ -14294,20 +14549,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1429414549 labels.deinit(self.gpa);
1429514550 }
1429614551
14297 const asm_source = mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];
14298 var line_it = mem.tokenizeAny(u8, asm_source, "\n\r;");
14552 const asm_source = std.mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];
14553 var line_it = std.mem.tokenizeAny(u8, asm_source, "\n\r;");
1429914554 next_line: while (line_it.next()) |line| {
14300 var mnem_it = mem.tokenizeAny(u8, line, " \t");
14301 var prefix: Instruction.Prefix = .none;
14555 var mnem_it = std.mem.tokenizeAny(u8, line, " \t");
14556 var prefix: encoder.Instruction.Prefix = .none;
1430214557 const mnem_str = while (mnem_it.next()) |mnem_str| {
1430314558 if (mnem_str[0] == '#') continue :next_line;
14304 if (mem.startsWith(u8, mnem_str, "//")) continue :next_line;
14305 if (std.meta.stringToEnum(Instruction.Prefix, mnem_str)) |pre| {
14559 if (std.mem.startsWith(u8, mnem_str, "//")) continue :next_line;
14560 if (std.meta.stringToEnum(encoder.Instruction.Prefix, mnem_str)) |pre| {
1430614561 if (prefix != .none) return self.fail("extra prefix: '{s}'", .{mnem_str});
1430714562 prefix = pre;
1430814563 continue;
1430914564 }
14310 if (!mem.endsWith(u8, mnem_str, ":")) break mnem_str;
14565 if (!std.mem.endsWith(u8, mnem_str, ":")) break mnem_str;
1431114566 const label_name = mnem_str[0 .. mnem_str.len - ":".len];
1431214567 if (!Label.isValid(.definition, label_name))
1431314568 return self.fail("invalid label: '{s}'", .{label_name});
......@@ -14332,21 +14587,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1433214587
1433314588 var mnem_size: ?Memory.Size = if (prefix == .directive)
1433414589 null
14335 else if (mem.endsWith(u8, mnem_str, "b"))
14590 else if (std.mem.endsWith(u8, mnem_str, "b"))
1433614591 .byte
14337 else if (mem.endsWith(u8, mnem_str, "w"))
14592 else if (std.mem.endsWith(u8, mnem_str, "w"))
1433814593 .word
14339 else if (mem.endsWith(u8, mnem_str, "l"))
14594 else if (std.mem.endsWith(u8, mnem_str, "l"))
1434014595 .dword
14341 else if (mem.endsWith(u8, mnem_str, "q") and
14342 (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !mem.endsWith(u8, mnem_str, "dq")))
14596 else if (std.mem.endsWith(u8, mnem_str, "q") and
14597 (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq")))
1434314598 .qword
14344 else if (mem.endsWith(u8, mnem_str, "t"))
14599 else if (std.mem.endsWith(u8, mnem_str, "t"))
1434514600 .tbyte
1434614601 else
1434714602 null;
1434814603 const mnem_tag = while (true) break std.meta.stringToEnum(
14349 Instruction.Mnemonic,
14604 encoder.Instruction.Mnemonic,
1435014605 mnem_str[0 .. mnem_str.len - @intFromBool(mnem_size != null)],
1435114606 ) orelse if (mnem_size) |_| {
1435214607 mnem_size = null;
......@@ -14367,18 +14622,18 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1436714622 .{ ._, .pseudo }
1436814623 else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
1436914624 const fixes_name = @tagName(fixes);
14370 const space_i = mem.indexOfScalar(u8, fixes_name, ' ');
14625 const space_i = std.mem.indexOfScalar(u8, fixes_name, ' ');
1437114626 const fixes_prefix = if (space_i) |i|
14372 std.meta.stringToEnum(Instruction.Prefix, fixes_name[0..i]).?
14627 std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..i]).?
1437314628 else
1437414629 .none;
1437514630 if (fixes_prefix != prefix) continue;
1437614631 const pattern = fixes_name[if (space_i) |i| i + " ".len else 0..];
14377 const wildcard_i = mem.indexOfScalar(u8, pattern, '_').?;
14632 const wildcard_i = std.mem.indexOfScalar(u8, pattern, '_').?;
1437814633 const mnem_prefix = pattern[0..wildcard_i];
1437914634 const mnem_suffix = pattern[wildcard_i + "_".len ..];
14380 if (!mem.startsWith(u8, mnem_name, mnem_prefix)) continue;
14381 if (!mem.endsWith(u8, mnem_name, mnem_suffix)) continue;
14635 if (!std.mem.startsWith(u8, mnem_name, mnem_prefix)) continue;
14636 if (!std.mem.endsWith(u8, mnem_name, mnem_suffix)) continue;
1438214637 break .{ fixes, std.meta.stringToEnum(
1438314638 Mir.Inst.Tag,
1438414639 mnem_name[mnem_prefix.len .. mnem_name.len - mnem_suffix.len],
......@@ -14400,21 +14655,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1440014655 var ops: [4]Operand = .{.none} ** 4;
1440114656
1440214657 var last_op = false;
14403 var op_it = mem.splitScalar(u8, mnem_it.rest(), ',');
14658 var op_it = std.mem.splitScalar(u8, mnem_it.rest(), ',');
1440414659 next_op: for (&ops) |*op| {
1440514660 const op_str = while (!last_op) {
1440614661 const full_str = op_it.next() orelse break :next_op;
14407 const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse
14408 mem.indexOf(u8, full_str, "//")) |comment|
14662 const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse
14663 std.mem.indexOf(u8, full_str, "//")) |comment|
1440914664 code: {
1441014665 last_op = true;
1441114666 break :code full_str[0..comment];
1441214667 } else full_str;
14413 const trim_str = mem.trim(u8, code_str, " \t*");
14668 const trim_str = std.mem.trim(u8, code_str, " \t*");
1441414669 if (trim_str.len > 0) break trim_str;
1441514670 } else break;
14416 if (mem.startsWith(u8, op_str, "%%")) {
14417 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
14671 if (std.mem.startsWith(u8, op_str, "%%")) {
14672 const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
1441814673 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
1441914674 return self.fail("invalid register: '{s}'", .{op_str});
1442014675 if (colon) |colon_pos| {
......@@ -14432,8 +14687,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1443214687 return self.fail("invalid register size: '{s}'", .{op_str});
1443314688 op.* = .{ .reg = reg };
1443414689 }
14435 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {
14436 const colon = mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
14690 } else if (std.mem.startsWith(u8, op_str, "%[") and std.mem.endsWith(u8, op_str, "]")) {
14691 const colon = std.mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
1443714692 const modifier = if (colon) |colon_pos|
1443814693 op_str[colon_pos + ":".len .. op_str.len - "]".len]
1443914694 else
......@@ -14442,15 +14697,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1444214697 arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse
1444314698 return self.fail("no matching constraint: '{s}'", .{op_str})
1444414699 ]) {
14445 .immediate => |imm| if (mem.eql(u8, modifier, "") or mem.eql(u8, modifier, "c"))
14446 .{ .imm = Immediate.u(imm) }
14700 .immediate => |imm| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "c"))
14701 .{ .imm = .u(imm) }
1444714702 else
1444814703 return self.fail("invalid modifier: '{s}'", .{modifier}),
14449 .register => |reg| if (mem.eql(u8, modifier, ""))
14704 .register => |reg| if (std.mem.eql(u8, modifier, ""))
1445014705 .{ .reg = reg }
1445114706 else
1445214707 return self.fail("invalid modifier: '{s}'", .{modifier}),
14453 .memory => |addr| if (mem.eql(u8, modifier, "") or mem.eql(u8, modifier, "P"))
14708 .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P"))
1445414709 .{ .mem = .{
1445514710 .base = .{ .reg = .ds },
1445614711 .mod = .{ .rm = .{
......@@ -14461,7 +14716,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1446114716 } }
1446214717 else
1446314718 return self.fail("invalid modifier: '{s}'", .{modifier}),
14464 .indirect => |reg_off| if (mem.eql(u8, modifier, ""))
14719 .indirect => |reg_off| if (std.mem.eql(u8, modifier, ""))
1446514720 .{ .mem = .{
1446614721 .base = .{ .reg = reg_off.reg },
1446714722 .mod = .{ .rm = .{
......@@ -14472,7 +14727,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1447214727 } }
1447314728 else
1447414729 return self.fail("invalid modifier: '{s}'", .{modifier}),
14475 .load_frame => |frame_addr| if (mem.eql(u8, modifier, ""))
14730 .load_frame => |frame_addr| if (std.mem.eql(u8, modifier, ""))
1447614731 .{ .mem = .{
1447714732 .base = .{ .frame = frame_addr.index },
1447814733 .mod = .{ .rm = .{
......@@ -14483,42 +14738,42 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1448314738 } }
1448414739 else
1448514740 return self.fail("invalid modifier: '{s}'", .{modifier}),
14486 .lea_got => |sym_index| if (mem.eql(u8, modifier, "P"))
14741 .lea_got => |sym_index| if (std.mem.eql(u8, modifier, "P"))
1448714742 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }
1448814743 else
1448914744 return self.fail("invalid modifier: '{s}'", .{modifier}),
14490 .lea_symbol => |sym_off| if (mem.eql(u8, modifier, "P"))
14745 .lea_symbol => |sym_off| if (std.mem.eql(u8, modifier, "P"))
1449114746 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_symbol = sym_off }) }
1449214747 else
1449314748 return self.fail("invalid modifier: '{s}'", .{modifier}),
1449414749 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
1449514750 };
14496 } else if (mem.startsWith(u8, op_str, "$")) {
14751 } else if (std.mem.startsWith(u8, op_str, "$")) {
1449714752 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {
1449814753 if (mnem_size) |size| {
14499 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
14754 const max = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
1450014755 if ((if (s < 0) ~s else s) > max)
1450114756 return self.fail("invalid immediate size: '{s}'", .{op_str});
1450214757 }
14503 op.* = .{ .imm = Immediate.s(s) };
14758 op.* = .{ .imm = .s(s) };
1450414759 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {
1450514760 if (mnem_size) |size| {
14506 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());
14761 const max = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - size.bitSize());
1450714762 if (u > max)
1450814763 return self.fail("invalid immediate size: '{s}'", .{op_str});
1450914764 }
14510 op.* = .{ .imm = Immediate.u(u) };
14765 op.* = .{ .imm = .u(u) };
1451114766 } else |_| return self.fail("invalid immediate: '{s}'", .{op_str});
14512 } else if (mem.endsWith(u8, op_str, ")")) {
14513 const open = mem.indexOfScalar(u8, op_str, '(') orelse
14767 } else if (std.mem.endsWith(u8, op_str, ")")) {
14768 const open = std.mem.indexOfScalar(u8, op_str, '(') orelse
1451414769 return self.fail("invalid operand: '{s}'", .{op_str});
14515 var sib_it = mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
14770 var sib_it = std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
1451614771 const base_str = sib_it.next() orelse
1451714772 return self.fail("invalid memory operand: '{s}'", .{op_str});
14518 if (base_str.len > 0 and !mem.startsWith(u8, base_str, "%%"))
14773 if (base_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%"))
1451914774 return self.fail("invalid memory operand: '{s}'", .{op_str});
1452014775 const index_str = sib_it.next() orelse "";
14521 if (index_str.len > 0 and !mem.startsWith(u8, base_str, "%%"))
14776 if (index_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%"))
1452214777 return self.fail("invalid memory operand: '{s}'", .{op_str});
1452314778 const scale_str = sib_it.next() orelse "";
1452414779 if (index_str.len == 0 and scale_str.len > 0)
......@@ -14550,10 +14805,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1455014805 else
1455114806 .none,
1455214807 .scale = scale,
14553 .disp = if (mem.startsWith(u8, op_str[0..open], "%[") and
14554 mem.endsWith(u8, op_str[0..open], "]"))
14808 .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and
14809 std.mem.endsWith(u8, op_str[0..open], "]"))
1455514810 disp: {
14556 const colon = mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
14811 const colon = std.mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
1455714812 const modifier = if (colon) |colon_pos|
1455814813 op_str[colon_pos + ":".len .. open - "]".len]
1455914814 else
......@@ -14562,9 +14817,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1456214817 arg_map.get(op_str["%[".len .. colon orelse open - "]".len]) orelse
1456314818 return self.fail("no matching constraint: '{s}'", .{op_str})
1456414819 ]) {
14565 .immediate => |imm| if (mem.eql(u8, modifier, "") or
14566 mem.eql(u8, modifier, "c"))
14567 math.cast(i32, @as(i64, @bitCast(imm))) orelse
14820 .immediate => |imm| if (std.mem.eql(u8, modifier, "") or
14821 std.mem.eql(u8, modifier, "c"))
14822 std.math.cast(i32, @as(i64, @bitCast(imm))) orelse
1456814823 return self.fail("invalid displacement: '{s}'", .{op_str})
1456914824 else
1457014825 return self.fail("invalid modifier: '{s}'", .{modifier}),
......@@ -14730,10 +14985,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1473014985 return self.fail("undefined label: '{s}'", .{label.key_ptr.*});
1473114986
1473214987 for (outputs, args.items[0..outputs.len]) |output, arg_mcv| {
14733 const extra_bytes = mem.sliceAsBytes(self.air.extra[outputs_extra_i..]);
14988 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]);
1473414989 const constraint =
14735 mem.sliceTo(mem.sliceAsBytes(self.air.extra[outputs_extra_i..]), 0);
14736 const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
14990 std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]), 0);
14991 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
1473714992 // This equation accounts for the fact that even if we have exactly 4 bytes
1473814993 // for the string, we still use the next u32 for the null terminator.
1473914994 outputs_extra_i += (constraint.len + name.len + (2 + 3)) / 4;
......@@ -14777,7 +15032,10 @@ const MoveStrategy = union(enum) {
1477715032
1477815033 pub fn read(strat: MoveStrategy, self: *Self, dst_reg: Register, src_mem: Memory) !void {
1477915034 switch (strat) {
14780 .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem),
15035 .move => |tag| try self.asmRegisterMemory(tag, switch (tag[1]) {
15036 else => dst_reg,
15037 .lea => if (dst_reg.bitSize() >= 32) dst_reg else dst_reg.to32(),
15038 }, src_mem),
1478115039 .x87_load_store => {
1478215040 try self.asmMemory(.{ .f_, .ld }, src_mem);
1478315041 assert(dst_reg != .st7);
......@@ -14787,14 +15045,14 @@ const MoveStrategy = union(enum) {
1478715045 ie.insert,
1478815046 dst_reg,
1478915047 src_mem,
14790 Immediate.u(0),
15048 .u(0),
1479115049 ),
1479215050 .vex_insert_extract => |ie| try self.asmRegisterRegisterMemoryImmediate(
1479315051 ie.insert,
1479415052 dst_reg,
1479515053 dst_reg,
1479615054 src_mem,
14797 Immediate.u(0),
15055 .u(0),
1479815056 ),
1479915057 }
1480015058 }
......@@ -14809,7 +15067,7 @@ const MoveStrategy = union(enum) {
1480915067 ie.extract,
1481015068 dst_mem,
1481115069 src_reg,
14812 Immediate.u(0),
15070 .u(0),
1481315071 ),
1481415072 }
1481515073 }
......@@ -14823,7 +15081,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1482315081 .mmx => {},
1482415082 .sse => switch (ty.zigTypeTag(zcu)) {
1482515083 else => {
14826 const classes = mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
15084 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
1482715085 assert(std.mem.indexOfNone(abi.Class, classes, &.{
1482815086 .integer, .sse, .sseup, .memory, .float, .float_combine,
1482915087 }) == null);
......@@ -15135,7 +15393,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: Copy
1513515393 ),
1513615394 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
1513715395 switch (dst_mcv) {
15138 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
15396 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
1513915397 return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts),
1514015398 .load_symbol, .load_direct, .load_got, .load_tlv => {},
1514115399 else => unreachable,
......@@ -15179,17 +15437,17 @@ fn genSetReg(
1517915437 => unreachable,
1518015438 .undef => if (opts.safety) switch (dst_reg.class()) {
1518115439 .general_purpose => switch (abi_size) {
15182 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), Immediate.u(0xAA)),
15183 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), Immediate.u(0xAAAA)),
15440 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), .u(0xAA)),
15441 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), .u(0xAAAA)),
1518415442 3...4 => try self.asmRegisterImmediate(
1518515443 .{ ._, .mov },
1518615444 dst_reg.to32(),
15187 Immediate.s(@as(i32, @bitCast(@as(u32, 0xAAAAAAAA)))),
15445 .s(@as(i32, @bitCast(@as(u32, 0xAAAAAAAA)))),
1518815446 ),
1518915447 5...8 => try self.asmRegisterImmediate(
1519015448 .{ ._, .mov },
1519115449 dst_reg.to64(),
15192 Immediate.u(0xAAAAAAAAAAAAAAAA),
15450 .u(0xAAAAAAAAAAAAAAAA),
1519315451 ),
1519415452 else => unreachable,
1519515453 },
......@@ -15203,20 +15461,20 @@ fn genSetReg(
1520315461 // register is the fastest way to zero a register.
1520415462 try self.spillEflagsIfOccupied();
1520515463 try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
15206 } else if (abi_size > 4 and math.cast(u32, imm) != null) {
15464 } else if (abi_size > 4 and std.math.cast(u32, imm) != null) {
1520715465 // 32-bit moves zero-extend to 64-bit.
15208 try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), Immediate.u(imm));
15466 try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), .u(imm));
1520915467 } else if (abi_size <= 4 and @as(i64, @bitCast(imm)) < 0) {
1521015468 try self.asmRegisterImmediate(
1521115469 .{ ._, .mov },
1521215470 registerAlias(dst_reg, abi_size),
15213 Immediate.s(@intCast(@as(i64, @bitCast(imm)))),
15471 .s(@intCast(@as(i64, @bitCast(imm)))),
1521415472 );
1521515473 } else {
1521615474 try self.asmRegisterImmediate(
1521715475 .{ ._, .mov },
1521815476 registerAlias(dst_reg, abi_size),
15219 Immediate.u(imm),
15477 .u(imm),
1522015478 );
1522115479 }
1522215480 },
......@@ -15325,15 +15583,15 @@ fn genSetReg(
1532515583 .load_frame => |frame_addr| try self.moveStrategy(
1532615584 ty,
1532715585 dst_reg.class(),
15328 self.getFrameAddrAlignment(frame_addr).compare(.gte, Alignment.fromLog2Units(
15329 math.log2_int_ceil(u10, @divExact(dst_reg.bitSize(), 8)),
15586 self.getFrameAddrAlignment(frame_addr).compare(.gte, InternPool.Alignment.fromLog2Units(
15587 std.math.log2_int_ceil(u10, @divExact(dst_reg.bitSize(), 8)),
1533015588 )),
1533115589 ),
1533215590 .lea_frame => .{ .move = .{ ._, .lea } },
1533315591 else => unreachable,
1533415592 }).read(self, registerAlias(dst_reg, abi_size), switch (src_mcv) {
1533515593 .register_offset, .indirect => |reg_off| .{
15336 .base = .{ .reg = reg_off.reg },
15594 .base = .{ .reg = reg_off.reg.to64() },
1533715595 .mod = .{ .rm = .{
1533815596 .size = self.memSize(ty),
1533915597 .disp = reg_off.off,
......@@ -15350,7 +15608,7 @@ fn genSetReg(
1535015608 }),
1535115609 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
1535215610 switch (src_mcv) {
15353 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
15611 .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
1535415612 return (try self.moveStrategy(
1535515613 ty,
1535615614 dst_reg.class(),
......@@ -15400,14 +15658,10 @@ fn genSetReg(
1540015658 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
1540115659 defer self.register_manager.unlockReg(addr_lock);
1540215660
15403 try (try self.moveStrategy(ty, dst_reg.class(), false)).read(
15404 self,
15405 registerAlias(dst_reg, abi_size),
15406 .{
15407 .base = .{ .reg = addr_reg },
15408 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
15409 },
15410 );
15661 try (try self.moveStrategy(ty, dst_reg.class(), false)).read(self, registerAlias(dst_reg, abi_size), .{
15662 .base = .{ .reg = addr_reg.to64() },
15663 .mod = .{ .rm = .{ .size = self.memSize(ty) } },
15664 });
1541115665 },
1541215666 .lea_symbol => |sym_off| switch (self.bin_file.tag) {
1541315667 .elf, .macho => try self.asmRegisterMemory(
......@@ -15478,12 +15732,12 @@ fn genSetMem(
1547815732 ),
1547915733 .immediate => |imm| switch (abi_size) {
1548015734 1, 2, 4 => {
15481 const immediate = switch (if (ty.isAbiInt(zcu))
15735 const immediate: Immediate = switch (if (ty.isAbiInt(zcu))
1548215736 ty.intInfo(zcu).signedness
1548315737 else
1548415738 .unsigned) {
15485 .signed => Immediate.s(@truncate(@as(i64, @bitCast(imm)))),
15486 .unsigned => Immediate.u(@as(u32, @intCast(imm))),
15739 .signed => .s(@truncate(@as(i64, @bitCast(imm)))),
15740 .unsigned => .u(@as(u32, @intCast(imm))),
1548715741 };
1548815742 try self.asmMemoryImmediate(
1548915743 .{ ._, .mov },
......@@ -15495,14 +15749,14 @@ fn genSetMem(
1549515749 );
1549615750 },
1549715751 3, 5...7 => unreachable,
15498 else => if (math.cast(i32, @as(i64, @bitCast(imm)))) |small| {
15752 else => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small| {
1549915753 try self.asmMemoryImmediate(
1550015754 .{ ._, .mov },
1550115755 .{ .base = base, .mod = .{ .rm = .{
1550215756 .size = Memory.Size.fromSize(abi_size),
1550315757 .disp = disp,
1550415758 } } },
15505 Immediate.s(small),
15759 .s(small),
1550615760 );
1550715761 } else {
1550815762 var offset: i32 = 0;
......@@ -15512,10 +15766,10 @@ fn genSetMem(
1551215766 .size = .dword,
1551315767 .disp = disp + offset,
1551415768 } } },
15515 if (ty.isSignedInt(zcu)) Immediate.s(
15516 @truncate(@as(i64, @bitCast(imm)) >> (math.cast(u6, offset * 8) orelse 63)),
15517 ) else Immediate.u(
15518 @as(u32, @truncate(if (math.cast(u6, offset * 8)) |shift| imm >> shift else 0)),
15769 if (ty.isSignedInt(zcu)) .s(
15770 @truncate(@as(i64, @bitCast(imm)) >> (std.math.cast(u6, offset * 8) orelse 63)),
15771 ) else .u(
15772 @as(u32, @truncate(if (std.math.cast(u6, offset * 8)) |shift| imm >> shift else 0)),
1551915773 ),
1552015774 );
1552115775 },
......@@ -15542,7 +15796,9 @@ fn genSetMem(
1554215796 .general_purpose, .segment, .x87, .ip => @divExact(src_alias.bitSize(), 8),
1554315797 .mmx, .sse => abi_size,
1554415798 });
15545 const src_align = Alignment.fromNonzeroByteUnits(math.ceilPowerOfTwoAssert(u32, src_size));
15799 const src_align = InternPool.Alignment.fromNonzeroByteUnits(
15800 std.math.ceilPowerOfTwoAssert(u32, src_size),
15801 );
1554615802 if (src_size > mem_size) {
1554715803 const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{
1554815804 .size = src_size,
......@@ -15755,7 +16011,7 @@ fn genLazySymbolRef(
1575516011 .base = .{ .reloc = sym_index },
1575616012 .mod = .{ .rm = .{ .size = .qword } },
1575716013 }),
15758 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
16014 .call => try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index })),
1575916015 else => unreachable,
1576016016 }
1576116017 } else if (self.bin_file.cast(.plan9)) |p9_file| {
......@@ -15861,7 +16117,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1586116117 const dst_mcv = if (dst_rc.supersetOf(src_rc) and dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and
1586216118 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
1586316119 const dst_mcv = try self.allocRegOrMem(inst, true);
15864 try self.genCopy(switch (math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {
16120 try self.genCopy(switch (std.math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {
1586516121 .lt => dst_ty,
1586616122 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
1586716123 .gt => src_ty,
......@@ -15878,7 +16134,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1587816134 const bit_size = dst_ty.bitSize(zcu);
1587916135 if (abi_size * 8 <= bit_size or dst_ty.isVector(zcu)) break :result dst_mcv;
1588016136
15881 const dst_limbs_len = math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;
16137 const dst_limbs_len = std.math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;
1588216138 const high_mcv: MCValue = switch (dst_mcv) {
1588316139 .register => |dst_reg| .{ .register = dst_reg },
1588416140 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
......@@ -15940,7 +16196,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {
1594016196 const src_bits: u32 = @intCast(src_ty.bitSize(zcu));
1594116197 const src_signedness =
1594216198 if (src_ty.isAbiInt(zcu)) src_ty.intInfo(zcu).signedness else .unsigned;
15943 const src_size = math.divCeil(u32, @max(switch (src_signedness) {
16199 const src_size = std.math.divCeil(u32, @max(switch (src_signedness) {
1594416200 .signed => src_bits,
1594516201 .unsigned => src_bits + 1,
1594616202 }, 32), 8) catch unreachable;
......@@ -16017,7 +16273,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {
1601716273 const dst_bits: u32 = @intCast(dst_ty.bitSize(zcu));
1601816274 const dst_signedness =
1601916275 if (dst_ty.isAbiInt(zcu)) dst_ty.intInfo(zcu).signedness else .unsigned;
16020 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {
16276 const dst_size = std.math.divCeil(u32, @max(switch (dst_signedness) {
1602116277 .signed => dst_bits,
1602216278 .unsigned => dst_bits + 1,
1602316279 }, 32), 8) catch unreachable;
......@@ -16593,13 +16849,17 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1659316849 const reg_locks = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdi, .rsi, .rcx });
1659416850 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
1659516851
16596 const dst_ptr = try self.resolveInst(bin_op.lhs);
16597 const dst_ptr_ty = self.typeOf(bin_op.lhs);
16598 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
16599 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
16600 else => null,
16852 const dst = try self.resolveInst(bin_op.lhs);
16853 const dst_ty = self.typeOf(bin_op.lhs);
16854 const dst_locks: [2]?RegisterLock = switch (dst) {
16855 .register => |dst_reg| .{ self.register_manager.lockRegAssumeUnused(dst_reg), null },
16856 .register_pair => |dst_regs| .{
16857 self.register_manager.lockRegAssumeUnused(dst_regs[0]),
16858 self.register_manager.lockRegAssumeUnused(dst_regs[1]),
16859 },
16860 else => .{ null, null },
1660116861 };
16602 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
16862 for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
1660316863
1660416864 const src_val = try self.resolveInst(bin_op.rhs);
1660516865 const elem_ty = self.typeOf(bin_op.rhs);
......@@ -16612,16 +16872,20 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1661216872 const elem_abi_size: u31 = @intCast(elem_ty.abiSize(zcu));
1661316873
1661416874 if (elem_abi_size == 1) {
16615 const ptr: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
16616 // TODO: this only handles slices stored in the stack
16617 .slice => dst_ptr,
16618 .one => dst_ptr,
16875 const dst_ptr: MCValue = switch (dst_ty.ptrSize(zcu)) {
16876 .slice => switch (dst) {
16877 .register_pair => |dst_regs| .{ .register = dst_regs[0] },
16878 else => dst,
16879 },
16880 .one => dst,
1661916881 .c, .many => unreachable,
1662016882 };
16621 const len: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
16622 // TODO: this only handles slices stored in the stack
16623 .slice => dst_ptr.address().offset(8).deref(),
16624 .one => .{ .immediate = dst_ptr_ty.childType(zcu).arrayLen(zcu) },
16883 const len: MCValue = switch (dst_ty.ptrSize(zcu)) {
16884 .slice => switch (dst) {
16885 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
16886 else => dst.address().offset(8).deref(),
16887 },
16888 .one => .{ .immediate = dst_ty.childType(zcu).arrayLen(zcu) },
1662516889 .c, .many => unreachable,
1662616890 };
1662716891 const len_lock: ?RegisterLock = switch (len) {
......@@ -16630,20 +16894,25 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1663016894 };
1663116895 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
1663216896
16633 try self.genInlineMemset(ptr, src_val, len, .{ .safety = safety });
16897 try self.genInlineMemset(dst_ptr, src_val, len, .{ .safety = safety });
1663416898 break :result;
1663516899 }
1663616900
1663716901 // Store the first element, and then rely on memcpy copying forwards.
1663816902 // Length zero requires a runtime check - so we handle arrays specially
1663916903 // here to elide it.
16640 switch (dst_ptr_ty.ptrSize(zcu)) {
16904 switch (dst_ty.ptrSize(zcu)) {
1664116905 .slice => {
16642 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(zcu);
16906 const slice_ptr_ty = dst_ty.slicePtrFieldType(zcu);
1664316907
16644 // TODO: this only handles slices stored in the stack
16645 const ptr = dst_ptr;
16646 const len = dst_ptr.address().offset(8).deref();
16908 const dst_ptr: MCValue = switch (dst) {
16909 .register_pair => |dst_regs| .{ .register = dst_regs[0] },
16910 else => dst,
16911 };
16912 const len: MCValue = switch (dst) {
16913 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
16914 else => dst.address().offset(8).deref(),
16915 };
1664716916
1664816917 // Used to store the number of elements for comparison.
1664916918 // After comparison, updated to store number of bytes needed to copy.
......@@ -16656,7 +16925,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1665616925 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);
1665716926
1665816927 const skip_reloc = try self.asmJccReloc(.z, undefined);
16659 try self.store(slice_ptr_ty, ptr, src_val, .{ .safety = safety });
16928 try self.store(slice_ptr_ty, dst_ptr, src_val, .{ .safety = safety });
1666016929
1666116930 const second_elem_ptr_reg =
1666216931 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
......@@ -16666,7 +16935,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1666616935 defer self.register_manager.unlockReg(second_elem_ptr_lock);
1666716936
1666816937 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
16669 .reg = try self.copyToTmpRegister(Type.usize, ptr),
16938 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
1667016939 .off = elem_abi_size,
1667116940 } }, .{});
1667216941
......@@ -16675,19 +16944,19 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1667516944 .{ .i_, .mul },
1667616945 len_reg,
1667716946 len_reg,
16678 Immediate.s(elem_abi_size),
16947 .s(elem_abi_size),
1667916948 );
16680 try self.genInlineMemcpy(second_elem_ptr_mcv, ptr, len_mcv);
16949 try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, len_mcv);
1668116950
1668216951 self.performReloc(skip_reloc);
1668316952 },
1668416953 .one => {
1668516954 const elem_ptr_ty = try pt.singleMutPtrType(elem_ty);
1668616955
16687 const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);
16956 const len = dst_ty.childType(zcu).arrayLen(zcu);
1668816957
1668916958 assert(len != 0); // prevented by Sema
16690 try self.store(elem_ptr_ty, dst_ptr, src_val, .{ .safety = safety });
16959 try self.store(elem_ptr_ty, dst, src_val, .{ .safety = safety });
1669116960
1669216961 const second_elem_ptr_reg =
1669316962 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
......@@ -16697,12 +16966,12 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1669716966 defer self.register_manager.unlockReg(second_elem_ptr_lock);
1669816967
1669916968 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
16700 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
16969 .reg = try self.copyToTmpRegister(Type.usize, dst),
1670116970 .off = elem_abi_size,
1670216971 } }, .{});
1670316972
1670416973 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
16705 try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);
16974 try self.genInlineMemcpy(second_elem_ptr_mcv, dst, bytes_to_copy);
1670616975 },
1670716976 .c, .many => unreachable,
1670816977 }
......@@ -16719,48 +16988,72 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
1671916988 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
1672016989 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
1672116990
16722 const dst_ptr = try self.resolveInst(bin_op.lhs);
16723 const dst_ptr_ty = self.typeOf(bin_op.lhs);
16724 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
16725 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
16726 else => null,
16991 const dst = try self.resolveInst(bin_op.lhs);
16992 const dst_ty = self.typeOf(bin_op.lhs);
16993 const dst_locks: [2]?RegisterLock = switch (dst) {
16994 .register => |dst_reg| .{ self.register_manager.lockRegAssumeUnused(dst_reg), null },
16995 .register_pair => |dst_regs| .{
16996 self.register_manager.lockRegAssumeUnused(dst_regs[0]),
16997 self.register_manager.lockReg(dst_regs[1]),
16998 },
16999 else => .{ null, null },
1672717000 };
16728 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
17001 for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
1672917002
16730 const src_ptr = try self.resolveInst(bin_op.rhs);
16731 const src_ptr_lock: ?RegisterLock = switch (src_ptr) {
16732 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
16733 else => null,
17003 const src = try self.resolveInst(bin_op.rhs);
17004 const src_locks: [2]?RegisterLock = switch (src) {
17005 .register => |src_reg| .{ self.register_manager.lockReg(src_reg), null },
17006 .register_pair => |src_regs| .{
17007 self.register_manager.lockRegAssumeUnused(src_regs[0]),
17008 self.register_manager.lockRegAssumeUnused(src_regs[1]),
17009 },
17010 else => .{ null, null },
1673417011 };
16735 defer if (src_ptr_lock) |lock| self.register_manager.unlockReg(lock);
17012 for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);
1673617013
16737 const len: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
17014 const len: MCValue = switch (dst_ty.ptrSize(zcu)) {
1673817015 .slice => len: {
1673917016 const len_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
1674017017 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
1674117018 defer self.register_manager.unlockReg(len_lock);
1674217019
16743 try self.asmRegisterMemoryImmediate(
16744 .{ .i_, .mul },
16745 len_reg,
16746 try dst_ptr.address().offset(8).deref().mem(self, .qword),
16747 Immediate.s(@intCast(dst_ptr_ty.childType(zcu).abiSize(zcu))),
16748 );
17020 switch (dst) {
17021 .register_pair => |dst_regs| try self.asmRegisterRegisterImmediate(
17022 .{ .i_, .mul },
17023 len_reg,
17024 dst_regs[1],
17025 .s(@intCast(dst_ty.childType(zcu).abiSize(zcu))),
17026 ),
17027 else => try self.asmRegisterMemoryImmediate(
17028 .{ .i_, .mul },
17029 len_reg,
17030 try dst.address().offset(8).deref().mem(self, .qword),
17031 .s(@intCast(dst_ty.childType(zcu).abiSize(zcu))),
17032 ),
17033 }
1674917034 break :len .{ .register = len_reg };
1675017035 },
1675117036 .one => len: {
16752 const array_ty = dst_ptr_ty.childType(zcu);
17037 const array_ty = dst_ty.childType(zcu);
1675317038 break :len .{ .immediate = array_ty.arrayLen(zcu) * array_ty.childType(zcu).abiSize(zcu) };
1675417039 },
1675517040 .c, .many => unreachable,
1675617041 };
1675717042 const len_lock: ?RegisterLock = switch (len) {
16758 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
17043 .register => |reg| self.register_manager.lockReg(reg),
1675917044 else => null,
1676017045 };
1676117046 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
1676217047
16763 // TODO: dst_ptr and src_ptr could be slices rather than raw pointers
17048 const dst_ptr: MCValue = switch (dst) {
17049 .register_pair => |dst_regs| .{ .register = dst_regs[0] },
17050 else => dst,
17051 };
17052 const src_ptr: MCValue = switch (src) {
17053 .register_pair => |src_regs| .{ .register = src_regs[0] },
17054 else => src,
17055 };
17056
1676417057 try self.genInlineMemcpy(dst_ptr, src_ptr, len);
1676517058
1676617059 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -16930,27 +17223,23 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1693017223 try self.genSetReg(
1693117224 regs[1],
1693217225 vector_ty,
16933 .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) },
17226 .{ .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - vector_len) },
1693417227 .{},
1693517228 );
1693617229 const src_mcv = try self.resolveInst(ty_op.operand);
16937 const abi_size = @max(math.divCeil(u32, vector_len, 8) catch unreachable, 4);
17230 const abi_size = @max(std.math.divCeil(u32, vector_len, 8) catch unreachable, 4);
1693817231 try self.asmCmovccRegisterRegister(
1693917232 switch (src_mcv) {
1694017233 .eflags => |cc| cc,
1694117234 .register => |src_reg| cc: {
16942 try self.asmRegisterImmediate(
16943 .{ ._, .@"test" },
16944 src_reg.to8(),
16945 Immediate.u(1),
16946 );
17235 try self.asmRegisterImmediate(.{ ._, .@"test" }, src_reg.to8(), .u(1));
1694717236 break :cc .nz;
1694817237 },
1694917238 else => cc: {
1695017239 try self.asmMemoryImmediate(
1695117240 .{ ._, .@"test" },
1695217241 try src_mcv.mem(self, .byte),
16953 Immediate.u(1),
17242 .u(1),
1695417243 );
1695517244 break :cc .nz;
1695617245 },
......@@ -17037,7 +17326,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1703717326 .{ if (self.hasFeature(.avx)) .vp_w else .p_w, .shufl },
1703817327 dst_alias,
1703917328 dst_alias,
17040 Immediate.u(0b00_00_00_00),
17329 .u(0b00_00_00_00),
1704117330 );
1704217331 if (switch (scalar_bits) {
1704317332 1...8 => vector_len > 4,
......@@ -17049,7 +17338,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1704917338 .{ if (self.hasFeature(.avx)) .vp_d else .p_d, .shuf },
1705017339 dst_alias,
1705117340 dst_alias,
17052 Immediate.u(if (scalar_bits <= 64) 0b00_00_00_00 else 0b01_00_01_00),
17341 .u(if (scalar_bits <= 64) 0b00_00_00_00 else 0b01_00_01_00),
1705317342 );
1705417343 break :result .{ .register = dst_reg };
1705517344 },
......@@ -17080,7 +17369,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1708017369 dst_reg.to128(),
1708117370 src_reg.to128(),
1708217371 src_reg.to128(),
17083 Immediate.u(0),
17372 .u(0),
1708417373 );
1708517374 }
1708617375 break :result .{ .register = dst_reg };
......@@ -17095,7 +17384,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1709517384 .{ ._ps, .shuf },
1709617385 dst_reg.to128(),
1709717386 dst_reg.to128(),
17098 Immediate.u(0),
17387 .u(0),
1709917388 );
1710017389 break :result dst_mcv;
1710117390 }
......@@ -17122,14 +17411,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1712217411 dst_reg.to128(),
1712317412 src_reg.to128(),
1712417413 src_reg.to128(),
17125 Immediate.u(0),
17414 .u(0),
1712617415 );
1712717416 try self.asmRegisterRegisterRegisterImmediate(
1712817417 .{ .v_f128, .insert },
1712917418 dst_reg.to256(),
1713017419 dst_reg.to256(),
1713117420 dst_reg.to128(),
17132 Immediate.u(1),
17421 .u(1),
1713317422 );
1713417423 }
1713517424 }
......@@ -17198,7 +17487,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1719817487 dst_reg.to256(),
1719917488 dst_reg.to256(),
1720017489 dst_reg.to128(),
17201 Immediate.u(1),
17490 .u(1),
1720217491 );
1720317492 }
1720417493 }
......@@ -17231,7 +17520,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1723117520 dst_reg.to256(),
1723217521 src_reg.to256(),
1723317522 src_reg.to128(),
17234 Immediate.u(1),
17523 .u(1),
1723517524 );
1723617525 }
1723717526 break :result .{ .register = dst_reg };
......@@ -17308,7 +17597,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
1730817597 mask_alias,
1730917598 mask_alias,
1731017599 mask_reg.to128(),
17311 Immediate.u(1),
17600 .u(1),
1731217601 );
1731317602 break :broadcast;
1731417603 },
......@@ -17362,7 +17651,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
1736217651 .{ if (has_avx) .vp_w else .p_w, .shufl },
1736317652 mask_alias,
1736417653 mask_alias,
17365 Immediate.u(0b00_00_00_00),
17654 .u(0b00_00_00_00),
1736617655 );
1736717656 if (abi_size <= 8) break :broadcast;
1736817657 }
......@@ -17370,7 +17659,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
1737017659 .{ if (has_avx) .vp_d else .p_d, .shuf },
1737117660 mask_alias,
1737217661 mask_alias,
17373 Immediate.u(switch (elem_abi_size) {
17662 .u(switch (elem_abi_size) {
1737417663 1...2, 5...8 => 0b01_00_01_00,
1737517664 3...4 => 0b00_00_00_00,
1737617665 else => unreachable,
......@@ -17649,7 +17938,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1764917938 for (mask_elems, 0..) |maybe_mask_elem, elem_index| {
1765017939 const mask_elem = maybe_mask_elem orelse continue;
1765117940 const mask_elem_index =
17652 math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :unpck;
17941 std.math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :unpck;
1765317942 const elem_byte = (elem_index >> 1) * elem_abi_size;
1765417943 if (mask_elem_index * elem_abi_size != (elem_byte & 0b0111) | @as(u4, switch (variant) {
1765517944 .unpckl => 0b0000,
......@@ -17746,10 +18035,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1774618035 } else sources[(elem_index & 0b010) >> 1] = source;
1774718036
1774818037 const select_bit: u3 = @intCast((elem_index & 0b011) << 1);
17749 const select = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
18038 const select_mask = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
1775018039 if (elem_index & 0b100 == 0)
17751 control |= select
17752 else if (control & @as(u8, 0b11) << select_bit != select) break :pshufd;
18040 control |= select_mask
18041 else if (control & @as(u8, 0b11) << select_bit != select_mask) break :pshufd;
1775318042 }
1775418043
1775518044 const operands = [2]Air.Inst.Ref{ extra.a, extra.b };
......@@ -17767,7 +18056,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1776718056 .{ if (has_avx) .vp_d else .p_d, .shuf },
1776818057 dst_alias,
1776918058 try src_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
17770 Immediate.u(control),
18059 .u(control),
1777118060 ) else try self.asmRegisterRegisterImmediate(
1777218061 .{ if (has_avx) .vp_d else .p_d, .shuf },
1777318062 dst_alias,
......@@ -17775,7 +18064,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1777518064 src_mcv.getReg().?
1777618065 else
1777718066 try self.copyToTmpRegister(operand_tys[sources[0].?], src_mcv), max_abi_size),
17778 Immediate.u(control),
18067 .u(control),
1777918068 );
1778018069 break :result .{ .register = dst_reg };
1778118070 }
......@@ -17797,10 +18086,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1779718086 } else sources[(elem_index & 0b010) >> 1] = source;
1779818087
1779918088 const select_bit: u3 = @intCast((elem_index & 0b011) << 1);
17800 const select = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
18089 const select_mask = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
1780118090 if (elem_index & 0b100 == 0)
17802 control |= select
17803 else if (control & @as(u8, 0b11) << select_bit != select) break :shufps;
18091 control |= select_mask
18092 else if (control & @as(u8, 0b11) << select_bit != select_mask) break :shufps;
1780418093 }
1780518094 if (sources[0] orelse break :shufps == sources[1] orelse break :shufps) break :shufps;
1780618095
......@@ -17824,7 +18113,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1782418113 dst_alias,
1782518114 registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size),
1782618115 try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
17827 Immediate.u(control),
18116 .u(control),
1782818117 ) else try self.asmRegisterRegisterRegisterImmediate(
1782918118 .{ .v_ps, .shuf },
1783018119 dst_alias,
......@@ -17833,12 +18122,12 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1783318122 rhs_mcv.getReg().?
1783418123 else
1783518124 try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
17836 Immediate.u(control),
18125 .u(control),
1783718126 ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
1783818127 .{ ._ps, .shuf },
1783918128 dst_alias,
1784018129 try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
17841 Immediate.u(control),
18130 .u(control),
1784218131 ) else try self.asmRegisterRegisterImmediate(
1784318132 .{ ._ps, .shuf },
1784418133 dst_alias,
......@@ -17846,7 +18135,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1784618135 rhs_mcv.getReg().?
1784718136 else
1784818137 try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
17849 Immediate.u(control),
18138 .u(control),
1785018139 );
1785118140 break :result dst_mcv;
1785218141 }
......@@ -17891,7 +18180,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1789118180 dst_alias,
1789218181 registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size),
1789318182 try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
17894 Immediate.u(control),
18183 .u(control),
1789518184 ) else try self.asmRegisterRegisterRegisterImmediate(
1789618185 .{ .v_pd, .shuf },
1789718186 dst_alias,
......@@ -17900,12 +18189,12 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1790018189 rhs_mcv.getReg().?
1790118190 else
1790218191 try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
17903 Immediate.u(control),
18192 .u(control),
1790418193 ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
1790518194 .{ ._pd, .shuf },
1790618195 dst_alias,
1790718196 try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
17908 Immediate.u(control),
18197 .u(control),
1790918198 ) else try self.asmRegisterRegisterImmediate(
1791018199 .{ ._pd, .shuf },
1791118200 dst_alias,
......@@ -17913,7 +18202,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1791318202 rhs_mcv.getReg().?
1791418203 else
1791518204 try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
17916 Immediate.u(control),
18205 .u(control),
1791718206 );
1791818207 break :result dst_mcv;
1791918208 }
......@@ -17927,13 +18216,13 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1792718216 for (mask_elems, 0..) |maybe_mask_elem, elem_index| {
1792818217 const mask_elem = maybe_mask_elem orelse continue;
1792918218 const mask_elem_index =
17930 math.cast(u4, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blend;
18219 std.math.cast(u4, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blend;
1793118220 if (mask_elem_index != elem_index) break :blend;
1793218221
17933 const select = @as(u8, @intFromBool(mask_elem < 0)) << @truncate(elem_index);
18222 const select_mask = @as(u8, @intFromBool(mask_elem < 0)) << @truncate(elem_index);
1793418223 if (elem_index & 0b1000 == 0)
17935 control |= select
17936 else if (control & @as(u8, 0b1) << @truncate(elem_index) != select) break :blend;
18224 control |= select_mask
18225 else if (control & @as(u8, 0b1) << @truncate(elem_index) != select_mask) break :blend;
1793718226 }
1793818227
1793918228 if (!elem_ty.isRuntimeFloat() and self.hasFeature(.avx2)) vpblendd: {
......@@ -17961,7 +18250,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1796118250 registerAlias(dst_reg, dst_abi_size),
1796218251 registerAlias(lhs_reg, dst_abi_size),
1796318252 try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
17964 Immediate.u(expanded_control),
18253 .u(expanded_control),
1796518254 ) else try self.asmRegisterRegisterRegisterImmediate(
1796618255 .{ .vp_d, .blend },
1796718256 registerAlias(dst_reg, dst_abi_size),
......@@ -17970,7 +18259,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1797018259 rhs_mcv.getReg().?
1797118260 else
1797218261 try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
17973 Immediate.u(expanded_control),
18262 .u(expanded_control),
1797418263 );
1797518264 break :result .{ .register = dst_reg };
1797618265 }
......@@ -18016,7 +18305,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1801618305 else
1801718306 dst_reg, dst_abi_size),
1801818307 try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
18019 Immediate.u(expanded_control),
18308 .u(expanded_control),
1802018309 ) else try self.asmRegisterRegisterRegisterImmediate(
1802118310 .{ .vp_w, .blend },
1802218311 registerAlias(dst_reg, dst_abi_size),
......@@ -18028,12 +18317,12 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1802818317 rhs_mcv.getReg().?
1802918318 else
1803018319 try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
18031 Immediate.u(expanded_control),
18320 .u(expanded_control),
1803218321 ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
1803318322 .{ .p_w, .blend },
1803418323 registerAlias(dst_reg, dst_abi_size),
1803518324 try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
18036 Immediate.u(expanded_control),
18325 .u(expanded_control),
1803718326 ) else try self.asmRegisterRegisterImmediate(
1803818327 .{ .p_w, .blend },
1803918328 registerAlias(dst_reg, dst_abi_size),
......@@ -18041,7 +18330,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1804118330 rhs_mcv.getReg().?
1804218331 else
1804318332 try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
18044 Immediate.u(expanded_control),
18333 .u(expanded_control),
1804518334 );
1804618335 break :result .{ .register = dst_reg };
1804718336 }
......@@ -18077,7 +18366,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1807718366 else
1807818367 dst_reg, dst_abi_size),
1807918368 try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
18080 Immediate.u(expanded_control),
18369 .u(expanded_control),
1808118370 ) else try self.asmRegisterRegisterRegisterImmediate(
1808218371 switch (elem_abi_size) {
1808318372 4 => .{ .v_ps, .blend },
......@@ -18093,7 +18382,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1809318382 rhs_mcv.getReg().?
1809418383 else
1809518384 try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
18096 Immediate.u(expanded_control),
18385 .u(expanded_control),
1809718386 ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
1809818387 switch (elem_abi_size) {
1809918388 4 => .{ ._ps, .blend },
......@@ -18102,7 +18391,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1810218391 },
1810318392 registerAlias(dst_reg, dst_abi_size),
1810418393 try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
18105 Immediate.u(expanded_control),
18394 .u(expanded_control),
1810618395 ) else try self.asmRegisterRegisterImmediate(
1810718396 switch (elem_abi_size) {
1810818397 4 => .{ ._ps, .blend },
......@@ -18114,7 +18403,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1811418403 rhs_mcv.getReg().?
1811518404 else
1811618405 try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
18117 Immediate.u(expanded_control),
18406 .u(expanded_control),
1811818407 );
1811918408 break :result .{ .register = dst_reg };
1812018409 }
......@@ -18138,7 +18427,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1813818427 ) |*select_mask_elem, maybe_mask_elem, elem_index| {
1813918428 const mask_elem = maybe_mask_elem orelse continue;
1814018429 const mask_elem_index =
18141 math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blendv;
18430 std.math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blendv;
1814218431 if (mask_elem_index != elem_index) break :blendv;
1814318432
1814418433 select_mask_elem.* = (if (mask_elem < 0)
......@@ -18380,7 +18669,9 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
1838018669
1838118670 break :result null;
1838218671 }) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{
18383 lhs_ty.fmt(pt), rhs_ty.fmt(pt), dst_ty.fmt(pt),
18672 lhs_ty.fmt(pt),
18673 rhs_ty.fmt(pt),
18674 dst_ty.fmt(pt),
1838418675 Value.fromInterned(extra.mask).fmtValue(pt),
1838518676 });
1838618677 return self.finishAir(inst, result, .{ extra.a, extra.b, .none });
......@@ -18397,7 +18688,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1839718688 try self.spillEflagsIfOccupied();
1839818689
1839918690 const operand_mcv = try self.resolveInst(reduce.operand);
18400 const mask_len = (math.cast(u6, operand_ty.vectorLen(zcu)) orelse
18691 const mask_len = (std.math.cast(u6, operand_ty.vectorLen(zcu)) orelse
1840118692 return self.fail("TODO implement airReduce for {}", .{operand_ty.fmt(pt)}));
1840218693 const mask = (@as(u64, 1) << mask_len) - 1;
1840318694 const abi_size: u32 = @intCast(operand_ty.abiSize(zcu));
......@@ -18406,7 +18697,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1840618697 if (operand_mcv.isMemory()) try self.asmMemoryImmediate(
1840718698 .{ ._, .@"test" },
1840818699 try operand_mcv.mem(self, Memory.Size.fromSize(abi_size)),
18409 Immediate.u(mask),
18700 .u(mask),
1841018701 ) else {
1841118702 const operand_reg = registerAlias(if (operand_mcv.isRegister())
1841218703 operand_mcv.getReg().?
......@@ -18415,7 +18706,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1841518706 if (mask_len < abi_size * 8) try self.asmRegisterImmediate(
1841618707 .{ ._, .@"test" },
1841718708 operand_reg,
18418 Immediate.u(mask),
18709 .u(mask),
1841918710 ) else try self.asmRegisterRegister(
1842018711 .{ ._, .@"test" },
1842118712 operand_reg,
......@@ -18431,7 +18722,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1843118722
1843218723 try self.asmRegister(.{ ._, .not }, tmp_reg);
1843318724 if (mask_len < abi_size * 8)
18434 try self.asmRegisterImmediate(.{ ._, .@"test" }, tmp_reg, Immediate.u(mask))
18725 try self.asmRegisterImmediate(.{ ._, .@"test" }, tmp_reg, .u(mask))
1843518726 else
1843618727 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_reg, tmp_reg);
1843718728 break :result .{ .eflags = .z };
......@@ -18579,12 +18870,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1857918870 try self.asmRegisterImmediate(
1858018871 .{ ._, .@"and" },
1858118872 registerAlias(elem_reg, @min(result_size, 4)),
18582 Immediate.u(1),
18873 .u(1),
1858318874 );
1858418875 if (elem_i > 0) try self.asmRegisterImmediate(
1858518876 .{ ._l, .sh },
1858618877 registerAlias(elem_reg, result_size),
18587 Immediate.u(@intCast(elem_i)),
18878 .u(@intCast(elem_i)),
1858818879 );
1858918880 try self.asmRegisterRegister(
1859018881 .{ ._, .@"or" },
......@@ -18748,8 +19039,8 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1874819039 lock.* = self.register_manager.lockRegAssumeUnused(reg);
1874919040 }
1875019041
18751 const mir_tag = @as(?Mir.Inst.FixedTag, if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or
18752 mem.eql(u2, &order, &.{ 3, 1, 2 }))
19042 const mir_tag = @as(?Mir.Inst.FixedTag, if (std.mem.eql(u2, &order, &.{ 1, 3, 2 }) or
19043 std.mem.eql(u2, &order, &.{ 3, 1, 2 }))
1875319044 switch (ty.zigTypeTag(zcu)) {
1875419045 .float => switch (ty.floatBits(self.target.*)) {
1875519046 32 => .{ .v_ss, .fmadd132 },
......@@ -18776,7 +19067,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1877619067 },
1877719068 else => unreachable,
1877819069 }
18779 else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 }))
19070 else if (std.mem.eql(u2, &order, &.{ 2, 1, 3 }) or std.mem.eql(u2, &order, &.{ 1, 2, 3 }))
1878019071 switch (ty.zigTypeTag(zcu)) {
1878119072 .float => switch (ty.floatBits(self.target.*)) {
1878219073 32 => .{ .v_ss, .fmadd213 },
......@@ -18803,7 +19094,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1880319094 },
1880419095 else => unreachable,
1880519096 }
18806 else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 }))
19097 else if (std.mem.eql(u2, &order, &.{ 2, 3, 1 }) or std.mem.eql(u2, &order, &.{ 3, 2, 1 }))
1880719098 switch (ty.zigTypeTag(zcu)) {
1880819099 .float => switch (ty.floatBits(self.target.*)) {
1880919100 32 => .{ .v_ss, .fmadd231 },
......@@ -18953,13 +19244,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1895319244 const overflow_arg_area: MCValue = .{ .indirect = .{ .reg = ptr_arg_list_reg, .off = 8 } };
1895419245 const reg_save_area: MCValue = .{ .indirect = .{ .reg = ptr_arg_list_reg, .off = 16 } };
1895519246
18956 const classes = mem.sliceTo(&abi.classifySystemV(promote_ty, zcu, self.target.*, .arg), .none);
19247 const classes = std.mem.sliceTo(&abi.classifySystemV(promote_ty, zcu, self.target.*, .arg), .none);
1895719248 switch (classes[0]) {
1895819249 .integer => {
1895919250 assert(classes.len == 1);
1896019251
1896119252 try self.genSetReg(offset_reg, Type.c_uint, gp_offset, .{});
18962 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
19253 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(
1896319254 abi.SysV.c_abi_int_param_regs.len * 8,
1896419255 ));
1896519256 const mem_reloc = try self.asmJccReloc(.ae, undefined);
......@@ -19007,7 +19298,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1900719298 assert(classes.len == 1);
1900819299
1900919300 try self.genSetReg(offset_reg, Type.c_uint, fp_offset, .{});
19010 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
19301 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(
1901119302 abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,
1901219303 ));
1901319304 const mem_reloc = try self.asmJccReloc(.ae, undefined);
......@@ -19055,9 +19346,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1905519346 assert(classes.len == 1);
1905619347 unreachable;
1905719348 },
19058 else => return self.fail("TODO implement c_va_arg for {} on SysV", .{
19059 promote_ty.fmt(pt),
19060 }),
19349 else => return self.fail("TODO implement c_va_arg for {} on SysV", .{promote_ty.fmt(pt)}),
1906119350 }
1906219351
1906319352 if (unused) break :result .unreach;
......@@ -19194,7 +19483,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
1919419483 .immediate => |imm| {
1919519484 // This immediate is unsigned.
1919619485 const U = std.meta.Int(.unsigned, ti.bits - @intFromBool(ti.signedness == .signed));
19197 if (imm >= math.maxInt(U)) {
19486 if (imm >= std.math.maxInt(U)) {
1919819487 return MCValue{ .register = try self.copyToTmpRegister(Type.usize, mcv) };
1919919488 }
1920019489 },
......@@ -19226,7 +19515,7 @@ const CallMCValues = struct {
1922619515 args: []MCValue,
1922719516 return_value: InstTracking,
1922819517 stack_byte_count: u31,
19229 stack_align: Alignment,
19518 stack_align: InternPool.Alignment,
1923019519 gp_count: u32,
1923119520 fp_count: u32,
1923219521
......@@ -19303,7 +19592,7 @@ fn resolveCallingConventionValues(
1930319592 var ret_tracking_i: usize = 0;
1930419593
1930519594 const classes = switch (resolved_cc) {
19306 .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
19595 .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
1930719596 .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu)},
1930819597 else => unreachable,
1930919598 };
......@@ -19378,7 +19667,7 @@ fn resolveCallingConventionValues(
1937819667 var arg_mcv_i: usize = 0;
1937919668
1938019669 const classes = switch (resolved_cc) {
19381 .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
19670 .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
1938219671 .x86_64_win => &.{abi.classifyWindows(ty, zcu)},
1938319672 else => unreachable,
1938419673 };
......@@ -19435,7 +19724,7 @@ fn resolveCallingConventionValues(
1943519724
1943619725 const frame_elem_align = 8;
1943719726 const frame_elems_len = ty.vectorLen(zcu) - remaining_param_int_regs;
19438 const frame_elem_size = mem.alignForward(
19727 const frame_elem_size = std.mem.alignForward(
1943919728 u64,
1944019729 ty.childType(zcu).abiSize(zcu),
1944119730 frame_elem_align,
......@@ -19443,7 +19732,7 @@ fn resolveCallingConventionValues(
1944319732 const frame_size: u31 = @intCast(frame_elems_len * frame_elem_size);
1944419733
1944519734 result.stack_byte_count =
19446 mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
19735 std.mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
1944719736 arg_mcv[arg_mcv_i] = .{ .elementwise_regs_then_frame = .{
1944819737 .regs = remaining_param_int_regs,
1944919738 .frame_off = @intCast(result.stack_byte_count),
......@@ -19461,19 +19750,14 @@ fn resolveCallingConventionValues(
1946119750 continue;
1946219751 }
1946319752
19464 const param_size: u31 = @intCast(ty.abiSize(zcu));
1946519753 const param_align = ty.abiAlignment(zcu).max(.@"8");
19466 result.stack_byte_count = mem.alignForward(
19467 u31,
19468 result.stack_byte_count,
19469 @intCast(param_align.toByteUnits().?),
19470 );
19754 result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
1947119755 result.stack_align = result.stack_align.max(param_align);
1947219756 arg.* = .{ .load_frame = .{
1947319757 .index = stack_frame_base,
1947419758 .off = result.stack_byte_count,
1947519759 } };
19476 result.stack_byte_count += param_size;
19760 result.stack_byte_count += @intCast(ty.abiSize(zcu));
1947719761 }
1947819762 assert(param_int_reg_i <= 6);
1947919763 result.gp_count = param_int_reg_i;
......@@ -19509,19 +19793,14 @@ fn resolveCallingConventionValues(
1950919793 arg.* = .none;
1951019794 continue;
1951119795 }
19512 const param_size: u31 = @intCast(ty.abiSize(zcu));
1951319796 const param_align = ty.abiAlignment(zcu);
19514 result.stack_byte_count = mem.alignForward(
19515 u31,
19516 result.stack_byte_count,
19517 @intCast(param_align.toByteUnits().?),
19518 );
19797 result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
1951919798 result.stack_align = result.stack_align.max(param_align);
1952019799 arg.* = .{ .load_frame = .{
1952119800 .index = stack_frame_base,
1952219801 .off = result.stack_byte_count,
1952319802 } };
19524 result.stack_byte_count += param_size;
19803 result.stack_byte_count += @intCast(ty.abiSize(zcu));
1952519804 }
1952619805 },
1952719806 else => return self.fail("TODO implement function parameters and return values for {} on x86_64", .{cc}),
......@@ -19541,7 +19820,7 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMem
1954119820 return error.CodegenFail;
1954219821}
1954319822
19544fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {
19823fn failMsg(self: *Self, msg: *Zcu.ErrorMsg) error{ OutOfMemory, CodegenFail } {
1954519824 @branchHint(.cold);
1954619825 const zcu = self.pt.zcu;
1954719826 switch (self.owner) {
......@@ -19603,8 +19882,7 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
1960319882}
1960419883
1960519884fn memSize(self: *Self, ty: Type) Memory.Size {
19606 const pt = self.pt;
19607 const zcu = pt.zcu;
19885 const zcu = self.pt.zcu;
1960819886 return switch (ty.zigTypeTag(zcu)) {
1960919887 .float => Memory.Size.fromBitSize(ty.floatBits(self.target.*)),
1961019888 else => Memory.Size.fromSize(@intCast(ty.abiSize(zcu))),
......@@ -19614,7 +19892,7 @@ fn memSize(self: *Self, ty: Type) Memory.Size {
1961419892fn splitType(self: *Self, ty: Type) ![2]Type {
1961519893 const pt = self.pt;
1961619894 const zcu = pt.zcu;
19617 const classes = mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
19895 const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
1961819896 var parts: [2]Type = undefined;
1961919897 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
1962019898 part.* = switch (class) {
......@@ -19648,7 +19926,7 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
1964819926 .signedness = .unsigned,
1964919927 .bits = @intCast(ty.bitSize(zcu)),
1965019928 };
19651 const shift = math.cast(u6, 64 - int_info.bits % 64) orelse return;
19929 const shift = std.math.cast(u6, 64 - int_info.bits % 64) orelse return;
1965219930 try self.spillEflagsIfOccupied();
1965319931 switch (int_info.signedness) {
1965419932 .signed => {
......@@ -19690,8 +19968,7 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
1969019968}
1969119969
1969219970fn regBitSize(self: *Self, ty: Type) u64 {
19693 const pt = self.pt;
19694 const zcu = pt.zcu;
19971 const zcu = self.pt.zcu;
1969519972 const abi_size = ty.abiSize(zcu);
1969619973 return switch (ty.zigTypeTag(zcu)) {
1969719974 else => switch (abi_size) {
......@@ -19713,14 +19990,14 @@ fn regExtraBits(self: *Self, ty: Type) u64 {
1971319990 return self.regBitSize(ty) - ty.bitSize(self.pt.zcu);
1971419991}
1971519992
19716fn hasFeature(self: *Self, feature: Target.x86.Feature) bool {
19717 return Target.x86.featureSetHas(self.target.cpu.features, feature);
19993fn hasFeature(self: *Self, feature: std.Target.x86.Feature) bool {
19994 return std.Target.x86.featureSetHas(self.target.cpu.features, feature);
1971819995}
1971919996fn hasAnyFeatures(self: *Self, features: anytype) bool {
19720 return Target.x86.featureSetHasAny(self.target.cpu.features, features);
19997 return std.Target.x86.featureSetHasAny(self.target.cpu.features, features);
1972119998}
1972219999fn hasAllFeatures(self: *Self, features: anytype) bool {
19723 return Target.x86.featureSetHasAll(self.target.cpu.features, features);
20000 return std.Target.x86.featureSetHasAll(self.target.cpu.features, features);
1972420001}
1972520002
1972620003fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
......@@ -19732,9 +20009,13 @@ fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
1973220009fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
1973320010 const pt = self.pt;
1973420011 const zcu = pt.zcu;
19735 return switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
19736 .loop_switch_br => self.typeOf(self.air.unwrapSwitch(inst).operand),
19737 else => self.air.typeOfIndex(inst, &zcu.intern_pool),
20012 const temp: Temp = .{ .index = inst };
20013 return switch (temp.unwrap(self)) {
20014 .ref => switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
20015 .loop_switch_br => self.typeOf(self.air.unwrapSwitch(inst).operand),
20016 else => self.air.typeOfIndex(inst, &zcu.intern_pool),
20017 },
20018 .temp => temp.typeOf(self),
1973820019 };
1973920020}
1974020021
......@@ -19815,3 +20096,613 @@ fn promoteVarArg(self: *Self, ty: Type) Type {
1981520096 },
1981620097 }
1981720098}
20099
20100// ====================================== rewrite starts here ======================================
20101
20102const Temp = struct {
20103 index: Air.Inst.Index,
20104
20105 fn unwrap(temp: Temp, self: *Self) union(enum) {
20106 ref: Air.Inst.Ref,
20107 temp: Index,
20108 } {
20109 switch (temp.index.unwrap()) {
20110 .ref => |ref| return .{ .ref = ref },
20111 .target => |target_index| {
20112 const temp_index: Index = @enumFromInt(target_index);
20113 assert(temp_index.isValid(self));
20114 return .{ .temp = temp_index };
20115 },
20116 }
20117 }
20118
20119 fn typeOf(temp: Temp, self: *Self) Type {
20120 return switch (temp.unwrap(self)) {
20121 .ref => |ref| self.typeOf(ref),
20122 .temp => |temp_index| temp_index.typeOf(self),
20123 };
20124 }
20125
20126 fn isMut(temp: Temp, self: *Self) bool {
20127 return temp.unwrap(self) == .temp;
20128 }
20129
20130 fn tracking(temp: Temp, self: *Self) InstTracking {
20131 return self.inst_tracking.get(temp.index).?;
20132 }
20133
20134 fn getOffset(temp: Temp, off: i32, self: *Self) !Temp {
20135 const new_temp_index = self.next_temp_index;
20136 self.temp_type[@intFromEnum(new_temp_index)] = Type.usize;
20137 self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
20138 switch (temp.tracking(self).short) {
20139 else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
20140 .register => |reg| {
20141 const new_reg =
20142 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20143 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20144 try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
20145 .base = .{ .reg = reg.to64() },
20146 .mod = .{ .rm = .{
20147 .size = .qword,
20148 .disp = off,
20149 } },
20150 });
20151 },
20152 .register_offset => |reg_off| {
20153 const new_reg =
20154 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20155 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20156 try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
20157 .base = .{ .reg = reg_off.reg.to64() },
20158 .mod = .{ .rm = .{
20159 .size = .qword,
20160 .disp = reg_off.off + off,
20161 } },
20162 });
20163 },
20164 .lea_symbol => |sym_off| new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_symbol = .{
20165 .sym_index = sym_off.sym_index,
20166 .off = sym_off.off + off,
20167 } }),
20168 .load_frame => |frame_addr| {
20169 const new_reg =
20170 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20171 new_temp_index.tracking(self).* = InstTracking.init(.{ .register_offset = .{
20172 .reg = new_reg,
20173 .off = off,
20174 } });
20175 try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
20176 .base = .{ .frame = frame_addr.index },
20177 .mod = .{ .rm = .{
20178 .size = .qword,
20179 .disp = frame_addr.off,
20180 } },
20181 });
20182 },
20183 .lea_frame => |frame_addr| new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_frame = .{
20184 .index = frame_addr.index,
20185 .off = frame_addr.off + off,
20186 } }),
20187 }
20188 return .{ .index = new_temp_index.toIndex() };
20189 }
20190
20191 fn toOffset(temp: *Temp, off: i32, self: *Self) !void {
20192 if (off == 0) return;
20193 switch (temp.unwrap(self)) {
20194 .ref => {},
20195 .temp => |temp_index| {
20196 const temp_tracking = temp_index.tracking(self);
20197 switch (temp_tracking.short) {
20198 else => {},
20199 .register => |reg| {
20200 try self.freeValue(temp_tracking.long);
20201 temp_tracking.* = InstTracking.init(.{ .register_offset = .{
20202 .reg = reg,
20203 .off = off,
20204 } });
20205 return;
20206 },
20207 .register_offset => |reg_off| {
20208 try self.freeValue(temp_tracking.long);
20209 temp_tracking.* = InstTracking.init(.{ .register_offset = .{
20210 .reg = reg_off.reg,
20211 .off = reg_off.off + off,
20212 } });
20213 return;
20214 },
20215 .lea_symbol => |sym_off| {
20216 assert(std.meta.eql(temp_tracking.long.lea_symbol, sym_off));
20217 temp_tracking.* = InstTracking.init(.{ .lea_symbol = .{
20218 .sym_index = sym_off.sym_index,
20219 .off = sym_off.off + off,
20220 } });
20221 return;
20222 },
20223 .lea_frame => |frame_addr| {
20224 assert(std.meta.eql(temp_tracking.long.lea_frame, frame_addr));
20225 temp_tracking.* = InstTracking.init(.{ .lea_frame = .{
20226 .index = frame_addr.index,
20227 .off = frame_addr.off + off,
20228 } });
20229 return;
20230 },
20231 }
20232 },
20233 }
20234 const new_temp = try temp.getOffset(off, self);
20235 try temp.die(self);
20236 temp.* = new_temp;
20237 }
20238
20239 fn getLimb(temp: Temp, limb_index: u28, self: *Self) !Temp {
20240 const new_temp_index = self.next_temp_index;
20241 self.temp_type[@intFromEnum(new_temp_index)] = Type.usize;
20242 switch (temp.tracking(self).short) {
20243 else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
20244 .immediate => |imm| {
20245 assert(limb_index == 0);
20246 new_temp_index.tracking(self).* = InstTracking.init(.{ .immediate = imm });
20247 },
20248 .register => |reg| {
20249 assert(limb_index == 0);
20250 const new_reg =
20251 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20252 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20253 try self.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), reg.to64());
20254 },
20255 .register_pair => |regs| {
20256 const new_reg =
20257 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20258 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20259 try self.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), regs[limb_index].to64());
20260 },
20261 .register_offset => |reg_off| {
20262 assert(limb_index == 0);
20263 const new_reg =
20264 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20265 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20266 try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
20267 .base = .{ .reg = reg_off.reg.to64() },
20268 .mod = .{ .rm = .{
20269 .size = .qword,
20270 .disp = reg_off.off + @as(u31, limb_index) * 8,
20271 } },
20272 });
20273 },
20274 .load_symbol => |sym_off| {
20275 const new_reg =
20276 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20277 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20278 try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
20279 .base = .{ .reloc = sym_off.sym_index },
20280 .mod = .{ .rm = .{
20281 .size = .qword,
20282 .disp = sym_off.off + @as(u31, limb_index) * 8,
20283 } },
20284 });
20285 },
20286 .lea_symbol => |sym_off| {
20287 assert(limb_index == 0);
20288 new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_symbol = sym_off });
20289 },
20290 .load_frame => |frame_addr| {
20291 const new_reg =
20292 try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
20293 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20294 try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
20295 .base = .{ .frame = frame_addr.index },
20296 .mod = .{ .rm = .{
20297 .size = .qword,
20298 .disp = frame_addr.off + @as(u31, limb_index) * 8,
20299 } },
20300 });
20301 },
20302 .lea_frame => |frame_addr| {
20303 assert(limb_index == 0);
20304 new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_frame = frame_addr });
20305 },
20306 }
20307 self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
20308 return .{ .index = new_temp_index.toIndex() };
20309 }
20310
20311 fn toLimb(temp: *Temp, limb_index: u28, self: *Self) !void {
20312 switch (temp.unwrap(self)) {
20313 .ref => {},
20314 .temp => |temp_index| {
20315 const temp_tracking = temp_index.tracking(self);
20316 switch (temp_tracking.short) {
20317 else => {},
20318 .register, .lea_symbol, .lea_frame => {
20319 assert(limb_index == 0);
20320 self.temp_type[@intFromEnum(temp_index)] = Type.usize;
20321 return;
20322 },
20323 .register_pair => |regs| {
20324 switch (temp_tracking.long) {
20325 .none, .reserved_frame => {},
20326 else => temp_tracking.long =
20327 temp_tracking.long.address().offset(@as(u31, limb_index) * 8).deref(),
20328 }
20329 for (regs, 0..) |reg, reg_index| if (reg_index != limb_index)
20330 self.register_manager.freeReg(reg);
20331 temp_tracking.* = InstTracking.init(.{ .register = regs[limb_index] });
20332 self.temp_type[@intFromEnum(temp_index)] = Type.usize;
20333 return;
20334 },
20335 .load_symbol => |sym_off| {
20336 assert(std.meta.eql(temp_tracking.long.load_symbol, sym_off));
20337 temp_tracking.* = InstTracking.init(.{ .load_symbol = .{
20338 .sym_index = sym_off.sym_index,
20339 .off = sym_off.off + @as(u31, limb_index) * 8,
20340 } });
20341 self.temp_type[@intFromEnum(temp_index)] = Type.usize;
20342 return;
20343 },
20344 .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) {
20345 assert(std.meta.eql(temp_tracking.long.load_frame, frame_addr));
20346 temp_tracking.* = InstTracking.init(.{ .load_frame = .{
20347 .index = frame_addr.index,
20348 .off = frame_addr.off + @as(u31, limb_index) * 8,
20349 } });
20350 self.temp_type[@intFromEnum(temp_index)] = Type.usize;
20351 return;
20352 },
20353 }
20354 },
20355 }
20356 const new_temp = try temp.getLimb(limb_index, self);
20357 try temp.die(self);
20358 temp.* = new_temp;
20359 }
20360
20361 fn toReg(temp: *Temp, new_reg: Register, self: *Self) !bool {
20362 const val, const ty = switch (temp.unwrap(self)) {
20363 .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) },
20364 .temp => |temp_index| val: {
20365 const temp_tracking = temp_index.tracking(self);
20366 if (temp_tracking.short == .register and
20367 temp_tracking.short.register == new_reg) return false;
20368 break :val .{ temp_tracking.short, temp_index.typeOf(self) };
20369 },
20370 };
20371 const new_temp_index = self.next_temp_index;
20372 self.temp_type[@intFromEnum(new_temp_index)] = ty;
20373 try self.genSetReg(new_reg, ty, val, .{});
20374 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20375 try temp.die(self);
20376 self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
20377 temp.* = .{ .index = new_temp_index.toIndex() };
20378 return true;
20379 }
20380
20381 fn toAnyReg(temp: *Temp, self: *Self) !bool {
20382 const val, const ty = switch (temp.unwrap(self)) {
20383 .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) },
20384 .temp => |temp_index| val: {
20385 const temp_tracking = temp_index.tracking(self);
20386 if (temp_tracking.short == .register) return false;
20387 break :val .{ temp_tracking.short, temp_index.typeOf(self) };
20388 },
20389 };
20390 const new_temp_index = self.next_temp_index;
20391 self.temp_type[@intFromEnum(new_temp_index)] = ty;
20392 const new_reg =
20393 try self.register_manager.allocReg(new_temp_index.toIndex(), self.regClassForType(ty));
20394 try self.genSetReg(new_reg, ty, val, .{});
20395 new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
20396 try temp.die(self);
20397 self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
20398 temp.* = .{ .index = new_temp_index.toIndex() };
20399 return true;
20400 }
20401
20402 fn toPair(first_temp: *Temp, second_temp: *Temp, self: *Self) !void {
20403 while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| {
20404 if (try part_temp.toAnyReg(self)) break;
20405 } else break;
20406 const first_temp_tracking = first_temp.unwrap(self).temp.tracking(self);
20407 const second_temp_tracking = second_temp.unwrap(self).temp.tracking(self);
20408 const result: MCValue = .{ .register_pair = .{
20409 first_temp_tracking.short.register,
20410 second_temp_tracking.short.register,
20411 } };
20412 const result_temp_index = self.next_temp_index;
20413 const result_temp: Temp = .{ .index = result_temp_index.toIndex() };
20414 assert(self.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking));
20415 assert(self.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking));
20416 self.temp_type[@intFromEnum(result_temp_index)] = Type.slice_const_u8;
20417 result_temp_index.tracking(self).* = InstTracking.init(result);
20418 first_temp.* = result_temp;
20419 }
20420
20421 fn toLea(temp: *Temp, self: *Self) !bool {
20422 switch (temp.tracking(self).short) {
20423 .none,
20424 .unreach,
20425 .dead,
20426 .undef,
20427 .eflags,
20428 .register_pair,
20429 .register_overflow,
20430 .elementwise_regs_then_frame,
20431 .reserved_frame,
20432 .air_ref,
20433 => unreachable, // not a valid pointer
20434 .immediate,
20435 .register,
20436 .register_offset,
20437 .lea_direct,
20438 .lea_got,
20439 .lea_tlv,
20440 .lea_frame,
20441 => return false,
20442 .memory,
20443 .indirect,
20444 .load_symbol,
20445 .load_direct,
20446 .load_got,
20447 .load_tlv,
20448 .load_frame,
20449 => return temp.toAnyReg(self),
20450 .lea_symbol => |sym_off| {
20451 const off = sym_off.off;
20452 if (off == 0) return false;
20453 try temp.toOffset(-off, self);
20454 while (try temp.toAnyReg(self)) {}
20455 try temp.toOffset(off, self);
20456 return true;
20457 },
20458 }
20459 }
20460
20461 fn load(ptr: *Temp, val_ty: Type, self: *Self) !Temp {
20462 const val_abi_size: u32 = @intCast(val_ty.abiSize(self.pt.zcu));
20463 const val = try self.tempAlloc(val_ty);
20464 switch (val.tracking(self).short) {
20465 else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
20466 .register => |val_reg| {
20467 while (try ptr.toLea(self)) {}
20468 switch (val_reg.class()) {
20469 .general_purpose => try self.asmRegisterMemory(
20470 .{ ._, .mov },
20471 registerAlias(val_reg, val_abi_size),
20472 try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)),
20473 ),
20474 else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
20475 }
20476 },
20477 .load_frame => |val_frame_addr| {
20478 var val_ptr = try self.tempFromValue(Type.usize, .{ .lea_frame = val_frame_addr });
20479 var len = try self.tempFromValue(Type.usize, .{ .immediate = val_abi_size });
20480 try val_ptr.memcpy(ptr, &len, self);
20481 try val_ptr.die(self);
20482 try len.die(self);
20483 },
20484 }
20485 return val;
20486 }
20487
20488 fn store(ptr: *Temp, val: *Temp, self: *Self) !void {
20489 const val_ty = val.typeOf(self);
20490 const val_abi_size: u32 = @intCast(val_ty.abiSize(self.pt.zcu));
20491 val: switch (val.tracking(self).short) {
20492 else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
20493 .immediate => |imm| if (std.math.cast(i32, imm)) |s| {
20494 while (try ptr.toLea(self)) {}
20495 try self.asmMemoryImmediate(
20496 .{ ._, .mov },
20497 try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)),
20498 .s(s),
20499 );
20500 } else continue :val .{ .register = undefined },
20501 .register => {
20502 while (try ptr.toLea(self) or try val.toAnyReg(self)) {}
20503 const val_reg = val.tracking(self).short.register;
20504 switch (val_reg.class()) {
20505 .general_purpose => try self.asmMemoryRegister(
20506 .{ ._, .mov },
20507 try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)),
20508 registerAlias(val_reg, val_abi_size),
20509 ),
20510 else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
20511 }
20512 },
20513 }
20514 }
20515
20516 fn memcpy(dst: *Temp, src: *Temp, len: *Temp, self: *Self) !void {
20517 while (true) for ([_]*Temp{ dst, src, len }, [_]Register{ .rdi, .rsi, .rcx }) |temp, reg| {
20518 if (try temp.toReg(reg, self)) break;
20519 } else break;
20520 try self.asmOpOnly(.{ .@"rep _sb", .mov });
20521 }
20522
20523 fn moveTo(temp: Temp, inst: Air.Inst.Index, self: *Self) !void {
20524 if (self.liveness.isUnused(inst)) try temp.die(self) else switch (temp.unwrap(self)) {
20525 .ref => {
20526 const result = try self.allocRegOrMem(inst, true);
20527 try self.genCopy(self.typeOfIndex(inst), result, temp.tracking(self).short, .{});
20528 tracking_log.debug("{} => {} (birth)", .{ inst, result });
20529 self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));
20530 },
20531 .temp => |temp_index| {
20532 const temp_tracking = temp_index.tracking(self);
20533 tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short });
20534 self.inst_tracking.putAssumeCapacityNoClobber(inst, temp_tracking.*);
20535 assert(self.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
20536 },
20537 }
20538 }
20539
20540 fn die(temp: Temp, self: *Self) !void {
20541 switch (temp.unwrap(self)) {
20542 .ref => {},
20543 .temp => |temp_index| try temp_index.tracking(self).die(self, temp_index.toIndex()),
20544 }
20545 }
20546
20547 const Index = enum(u4) {
20548 _,
20549
20550 fn toIndex(index: Index) Air.Inst.Index {
20551 return Air.Inst.Index.fromTargetIndex(@intFromEnum(index));
20552 }
20553
20554 fn fromIndex(index: Air.Inst.Index) Index {
20555 return @enumFromInt(index.toTargetIndex());
20556 }
20557
20558 fn tracking(index: Index, self: *Self) *InstTracking {
20559 return &self.inst_tracking.values()[@intFromEnum(index)];
20560 }
20561
20562 fn isValid(index: Index, self: *Self) bool {
20563 return index.tracking(self).short != .dead;
20564 }
20565
20566 fn typeOf(index: Index, self: *Self) Type {
20567 assert(index.isValid(self));
20568 return self.temp_type[@intFromEnum(index)];
20569 }
20570
20571 const max = std.math.maxInt(@typeInfo(Index).@"enum".tag_type);
20572 const Set = std.StaticBitSet(max);
20573 const SafetySet = if (std.debug.runtime_safety) Set else struct {
20574 inline fn initEmpty() @This() {
20575 return .{};
20576 }
20577
20578 inline fn isSet(_: @This(), index: usize) bool {
20579 assert(index < max);
20580 return true;
20581 }
20582
20583 inline fn set(_: @This(), index: usize) void {
20584 assert(index < max);
20585 }
20586
20587 inline fn eql(_: @This(), _: @This()) bool {
20588 return true;
20589 }
20590 };
20591 };
20592};
20593
20594fn resetTemps(self: *Self) void {
20595 for (0..@intFromEnum(self.next_temp_index)) |temp_index| {
20596 const temp: Temp.Index = @enumFromInt(temp_index);
20597 assert(!temp.isValid(self));
20598 self.temp_type[temp_index] = undefined;
20599 }
20600 self.next_temp_index = @enumFromInt(0);
20601}
20602
20603fn reuseTemp(
20604 self: *Self,
20605 new_inst: Air.Inst.Index,
20606 old_inst: Air.Inst.Index,
20607 tracking: *InstTracking,
20608) bool {
20609 switch (tracking.short) {
20610 .register,
20611 .register_pair,
20612 .register_offset,
20613 .register_overflow,
20614 => for (tracking.short.getRegs()) |tracked_reg| {
20615 if (RegisterManager.indexOfRegIntoTracked(tracked_reg)) |tracked_index| {
20616 self.register_manager.registers[tracked_index] = new_inst;
20617 }
20618 },
20619 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,
20620 else => {},
20621 }
20622 switch (tracking.short) {
20623 .eflags, .register_overflow => self.eflags_inst = new_inst,
20624 else => {},
20625 }
20626 tracking.reuse(self, new_inst, old_inst);
20627 return true;
20628}
20629
20630fn tempAlloc(self: *Self, ty: Type) !Temp {
20631 const temp_index = self.next_temp_index;
20632 temp_index.tracking(self).* = InstTracking.init(try self.allocRegOrMemAdvanced(ty, temp_index.toIndex(), true));
20633 self.temp_type[@intFromEnum(temp_index)] = ty;
20634 self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
20635 return .{ .index = temp_index.toIndex() };
20636}
20637
20638fn tempFromValue(self: *Self, ty: Type, value: MCValue) !Temp {
20639 const temp_index = self.next_temp_index;
20640 temp_index.tracking(self).* = InstTracking.init(value);
20641 self.temp_type[@intFromEnum(temp_index)] = ty;
20642 try self.getValue(value, temp_index.toIndex());
20643 self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
20644 return .{ .index = temp_index.toIndex() };
20645}
20646
20647fn tempFromOperand(
20648 self: *Self,
20649 inst: Air.Inst.Index,
20650 op_index: Liveness.OperandInt,
20651 op_ref: Air.Inst.Ref,
20652) !Temp {
20653 const zcu = self.pt.zcu;
20654 const ip = &zcu.intern_pool;
20655
20656 if (!self.liveness.operandDies(inst, op_index)) {
20657 if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
20658 const val = op_ref.toInterned().?;
20659 const gop = try self.const_tracking.getOrPut(self.gpa, val);
20660 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(init: {
20661 const const_mcv = try self.genTypedValue(Value.fromInterned(val));
20662 switch (const_mcv) {
20663 .lea_tlv => |tlv_sym| switch (self.bin_file.tag) {
20664 .elf, .macho => {
20665 if (self.mod.pic) {
20666 try self.spillRegisters(&.{ .rdi, .rax });
20667 } else {
20668 try self.spillRegisters(&.{.rax});
20669 }
20670 const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{
20671 .size = 8,
20672 .alignment = .@"8",
20673 }));
20674 try self.genSetMem(
20675 .{ .frame = frame_index },
20676 0,
20677 Type.usize,
20678 .{ .lea_symbol = .{ .sym_index = tlv_sym } },
20679 .{},
20680 );
20681 break :init .{ .load_frame = .{ .index = frame_index } };
20682 },
20683 else => break :init const_mcv,
20684 },
20685 else => break :init const_mcv,
20686 }
20687 });
20688 return self.tempFromValue(Type.fromInterned(ip.typeOf(val)), gop.value_ptr.short);
20689 }
20690
20691 const temp_index = self.next_temp_index;
20692 const temp: Temp = .{ .index = temp_index.toIndex() };
20693 const op_inst = op_ref.toIndex().?;
20694 const tracking = self.getResolvedInstValue(op_inst);
20695 temp_index.tracking(self).* = tracking.*;
20696 if (!self.reuseTemp(temp.index, op_inst, tracking)) return .{ .index = op_ref.toIndex().? };
20697 self.temp_type[@intFromEnum(temp_index)] = self.typeOf(op_ref);
20698 self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
20699 return temp;
20700}
20701
20702inline fn tempsFromOperands(self: *Self, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp {
20703 var temps: [op_refs.len]Temp = undefined;
20704 inline for (&temps, 0.., op_refs) |*temp, op_index, op_ref| {
20705 temp.* = try self.tempFromOperand(inst, op_index, op_ref);
20706 }
20707 return temps;
20708}
src/arch/x86_64/abi.zig+2-3
......@@ -250,9 +250,8 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8
250250 return memory_class;
251251 },
252252 .optional => {
253 if (ty.isPtrLikeOptional(zcu)) {
254 result[0] = .integer;
255 return result;
253 if (ty.optionalReprIsPayload(zcu)) {
254 return classifySystemV(ty.optionalChild(zcu), zcu, target, ctx);
256255 }
257256 return memory_class;
258257 },
src/arch/x86_64/bits.zig+33-1
......@@ -547,7 +547,39 @@ pub const Memory = struct {
547547 }
548548 };
549549
550 pub const Scale = enum(u2) { @"1", @"2", @"4", @"8" };
550 pub const Scale = enum(u2) {
551 @"1",
552 @"2",
553 @"4",
554 @"8",
555
556 pub fn fromFactor(factor: u4) Scale {
557 return switch (factor) {
558 else => unreachable,
559 1 => .@"1",
560 2 => .@"2",
561 4 => .@"4",
562 8 => .@"8",
563 };
564 }
565
566 pub fn toFactor(scale: Scale) u4 {
567 return switch (scale) {
568 .@"1" => 1,
569 .@"2" => 2,
570 .@"4" => 4,
571 .@"8" => 8,
572 };
573 }
574
575 pub fn fromLog2(log2: u2) Scale {
576 return @enumFromInt(log2);
577 }
578
579 pub fn toLog2(scale: Scale) u2 {
580 return @intFromEnum(scale);
581 }
582 };
551583};
552584
553585pub const Immediate = union(enum) {
src/print_air.zig+12-12
......@@ -96,8 +96,8 @@ const Writer = struct {
9696 fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
9797 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];
9898 try s.writeByteNTimes(' ', w.indent);
99 try s.print("%{d}{c}= {s}(", .{
100 @intFromEnum(inst),
99 try s.print("{}{c}= {s}(", .{
100 inst,
101101 @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),
102102 @tagName(tag),
103103 });
......@@ -409,7 +409,7 @@ const Writer = struct {
409409 try s.writeAll("}");
410410
411411 for (liveness_block.deaths) |operand| {
412 try s.print(" %{d}!", .{@intFromEnum(operand)});
412 try s.print(" {}!", .{operand});
413413 }
414414 }
415415
......@@ -728,7 +728,7 @@ const Writer = struct {
728728 try s.writeByteNTimes(' ', w.indent);
729729 for (liveness_condbr.else_deaths, 0..) |operand, i| {
730730 if (i != 0) try s.writeAll(" ");
731 try s.print("%{d}!", .{@intFromEnum(operand)});
731 try s.print("{}!", .{operand});
732732 }
733733 try s.writeAll("\n");
734734 }
......@@ -739,7 +739,7 @@ const Writer = struct {
739739 try s.writeAll("}");
740740
741741 for (liveness_condbr.then_deaths) |operand| {
742 try s.print(" %{d}!", .{@intFromEnum(operand)});
742 try s.print(" {}!", .{operand});
743743 }
744744 }
745745
......@@ -765,7 +765,7 @@ const Writer = struct {
765765 try s.writeByteNTimes(' ', w.indent);
766766 for (liveness_condbr.else_deaths, 0..) |operand, i| {
767767 if (i != 0) try s.writeAll(" ");
768 try s.print("%{d}!", .{@intFromEnum(operand)});
768 try s.print("{}!", .{operand});
769769 }
770770 try s.writeAll("\n");
771771 }
......@@ -776,7 +776,7 @@ const Writer = struct {
776776 try s.writeAll("}");
777777
778778 for (liveness_condbr.then_deaths) |operand| {
779 try s.print(" %{d}!", .{@intFromEnum(operand)});
779 try s.print(" {}!", .{operand});
780780 }
781781 }
782782
......@@ -807,7 +807,7 @@ const Writer = struct {
807807 try s.writeByteNTimes(' ', w.indent);
808808 for (liveness_condbr.then_deaths, 0..) |operand, i| {
809809 if (i != 0) try s.writeAll(" ");
810 try s.print("%{d}!", .{@intFromEnum(operand)});
810 try s.print("{}!", .{operand});
811811 }
812812 try s.writeAll("\n");
813813 }
......@@ -827,7 +827,7 @@ const Writer = struct {
827827 try s.writeByteNTimes(' ', w.indent);
828828 for (liveness_condbr.else_deaths, 0..) |operand, i| {
829829 if (i != 0) try s.writeAll(" ");
830 try s.print("%{d}!", .{@intFromEnum(operand)});
830 try s.print("{}!", .{operand});
831831 }
832832 try s.writeAll("\n");
833833 }
......@@ -884,7 +884,7 @@ const Writer = struct {
884884 try s.writeByteNTimes(' ', w.indent);
885885 for (deaths, 0..) |operand, i| {
886886 if (i != 0) try s.writeAll(" ");
887 try s.print("%{d}!", .{@intFromEnum(operand)});
887 try s.print("{}!", .{operand});
888888 }
889889 try s.writeAll("\n");
890890 }
......@@ -910,7 +910,7 @@ const Writer = struct {
910910 try s.writeByteNTimes(' ', w.indent);
911911 for (deaths, 0..) |operand, i| {
912912 if (i != 0) try s.writeAll(" ");
913 try s.print("%{d}!", .{@intFromEnum(operand)});
913 try s.print("{}!", .{operand});
914914 }
915915 try s.writeAll("\n");
916916 }
......@@ -994,7 +994,7 @@ const Writer = struct {
994994 dies: bool,
995995 ) @TypeOf(s).Error!void {
996996 _ = w;
997 try s.print("%{d}", .{@intFromEnum(inst)});
997 try s.print("{}", .{inst});
998998 if (dies) try s.writeByte('!');
999999 }
10001000
tools/lldb_pretty_printers.py+1-1
......@@ -383,7 +383,7 @@ def InstRef_SummaryProvider(value, _=None):
383383 'InternPool.Index(%d)' % value.unsigned if value.unsigned < 0x80000000 else 'instructions[%d]' % (value.unsigned - 0x80000000))
384384
385385def InstIndex_SummaryProvider(value, _=None):
386 return 'instructions[%d]' % value.unsigned
386 return 'instructions[%d]' % value.unsigned if value.unsigned < 0x80000000 else 'temps[%d]' % (value.unsigned - 0x80000000)
387387
388388class zig_DeclIndex_SynthProvider:
389389 def __init__(self, value, _=None): self.value = value