Commit af1191ea8b
Changed files (12)
src
arch
aarch64
arm
riscv64
sparc64
src/arch/aarch64/CodeGen.zig
@@ -71,6 +71,8 @@ end_di_column: u32,
/// which is a relative jump, based on the address following the reloc.
exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
+reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
+
/// We postpone the creation of debug info for function args and locals
/// until after all Mir instructions have been generated. Only then we
/// 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 {
const old_air_bookkeeping = self.air_bookkeeping;
try self.ensureProcessDeathCapacity(Liveness.bpi);
+ self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
switch (air_tags[@intFromEnum(inst)]) {
// zig fmt: off
.add => try self.airBinOp(inst, .add),
@@ -927,16 +930,13 @@ fn finishAirBookkeeping(self: *Self) void {
}
fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Liveness.bpi - 1]Air.Inst.Ref) void {
- var tomb_bits = self.liveness.getTombBits(inst);
- for (operands) |op| {
- const dies = @as(u1, @truncate(tomb_bits)) != 0;
- tomb_bits >>= 1;
- if (!dies) continue;
- const op_index = op.toIndex() orelse continue;
- self.processDeath(op_index);
+ const tomb_bits = self.liveness.getTombBits(inst);
+ for (0.., operands) |op_index, op| {
+ if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
+ if (self.reused_operands.isSet(op_index)) continue;
+ self.processDeath(op.toIndexAllowNone() orelse continue);
}
- const is_used = @as(u1, @truncate(tomb_bits)) == 0;
- if (is_used) {
+ if (tomb_bits & 1 << (Liveness.bpi - 1) == 0) {
log.debug("%{d} => {}", .{ inst, result });
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
@@ -3614,7 +3614,7 @@ fn reuseOperand(
}
// Prevent the operand deaths processing code from deallocating it.
- self.liveness.clearOperandDeath(inst, op_index);
+ self.reused_operands.set(op_index);
// That makes us responsible for doing the rest of the stuff that processDeath would have done.
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
src/arch/arm/CodeGen.zig
@@ -72,6 +72,8 @@ end_di_column: u32,
/// which is a relative jump, based on the address following the reloc.
exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
+reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
+
/// We postpone the creation of debug info for function args and locals
/// until after all Mir instructions have been generated. Only then we
/// 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 {
const old_air_bookkeeping = self.air_bookkeeping;
try self.ensureProcessDeathCapacity(Liveness.bpi);
+ self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
switch (air_tags[@intFromEnum(inst)]) {
// zig fmt: off
.add, => try self.airBinOp(inst, .add),
@@ -918,16 +921,13 @@ fn finishAirBookkeeping(self: *Self) void {
}
fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Liveness.bpi - 1]Air.Inst.Ref) void {
- var tomb_bits = self.liveness.getTombBits(inst);
- for (operands) |op| {
- const dies = @as(u1, @truncate(tomb_bits)) != 0;
- tomb_bits >>= 1;
- if (!dies) continue;
- const op_index = op.toIndex() orelse continue;
- self.processDeath(op_index);
+ const tomb_bits = self.liveness.getTombBits(inst);
+ for (0.., operands) |op_index, op| {
+ if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
+ if (self.reused_operands.isSet(op_index)) continue;
+ self.processDeath(op.toIndexAllowNone() orelse continue);
}
- const is_used = @as(u1, @truncate(tomb_bits)) == 0;
- if (is_used) {
+ if (tomb_bits & 1 << (Liveness.bpi - 1) == 0) {
log.debug("%{d} => {}", .{ inst, result });
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
@@ -2650,7 +2650,7 @@ fn reuseOperand(
}
// Prevent the operand deaths processing code from deallocating it.
- self.liveness.clearOperandDeath(inst, op_index);
+ self.reused_operands.set(op_index);
// That makes us responsible for doing the rest of the stuff that processDeath would have done.
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
src/arch/riscv64/CodeGen.zig
@@ -82,6 +82,8 @@ scope_generation: u32,
/// which is a relative jump, based on the address following the reloc.
exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
+reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
+
/// Whenever there is a runtime branch, we push a Branch onto this stack,
/// and pop it off when the runtime branch joins. This provides an "overlay"
/// 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 {
verbose_tracking_log.debug("{}", .{func.fmtTracking()});
const old_air_bookkeeping = func.air_bookkeeping;
+ try func.ensureProcessDeathCapacity(Liveness.bpi);
+
+ func.reused_operands = @TypeOf(func.reused_operands).initEmpty();
try func.inst_tracking.ensureUnusedCapacity(func.gpa, 1);
- const tag: Air.Inst.Tag = air_tags[@intFromEnum(inst)];
+ const tag = air_tags[@intFromEnum(inst)];
switch (tag) {
// zig fmt: off
.add,
@@ -1783,11 +1788,10 @@ fn finishAir(
result: MCValue,
operands: [Liveness.bpi - 1]Air.Inst.Ref,
) !void {
- var tomb_bits = func.liveness.getTombBits(inst);
- for (operands) |op| {
- const dies = @as(u1, @truncate(tomb_bits)) != 0;
- tomb_bits >>= 1;
- if (!dies) continue;
+ const tomb_bits = func.liveness.getTombBits(inst);
+ for (0.., operands) |op_index, op| {
+ if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
+ if (func.reused_operands.isSet(op_index)) continue;
try func.processDeath(op.toIndexAllowNone() orelse continue);
}
func.finishAirResult(inst, result);
@@ -4424,7 +4428,7 @@ fn reuseOperandAdvanced(
}
// Prevent the operand deaths processing code from deallocating it.
- func.liveness.clearOperandDeath(inst, op_index);
+ func.reused_operands.set(op_index);
const op_inst = operand.toIndex().?;
func.getResolvedInstValue(op_inst).reuse(func, maybe_tracked_inst, op_inst);
src/arch/sparc64/CodeGen.zig
@@ -78,6 +78,8 @@ end_di_column: u32,
/// which is a relative jump, based on the address following the reloc.
exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .empty,
+reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
+
/// Whenever there is a runtime branch, we push a Branch onto this stack,
/// and pop it off when the runtime branch joins. This provides an "overlay"
/// 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 {
const old_air_bookkeeping = self.air_bookkeeping;
try self.ensureProcessDeathCapacity(Liveness.bpi);
+ self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
switch (air_tags[@intFromEnum(inst)]) {
// zig fmt: off
.ptr_add => try self.airPtrArithmetic(inst, .ptr_add),
@@ -3523,16 +3526,13 @@ fn finishAirBookkeeping(self: *Self) void {
}
fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Liveness.bpi - 1]Air.Inst.Ref) void {
- var tomb_bits = self.liveness.getTombBits(inst);
- for (operands) |op| {
- const dies = @as(u1, @truncate(tomb_bits)) != 0;
- tomb_bits >>= 1;
- if (!dies) continue;
- const op_index = op.toIndex() orelse continue;
- self.processDeath(op_index);
+ const tomb_bits = self.liveness.getTombBits(inst);
+ for (0.., operands) |op_index, op| {
+ if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
+ if (self.reused_operands.isSet(op_index)) continue;
+ self.processDeath(op.toIndexAllowNone() orelse continue);
}
- const is_used = @as(u1, @truncate(tomb_bits)) == 0;
- if (is_used) {
+ if (tomb_bits & 1 << (Liveness.bpi - 1) == 0) {
log.debug("%{d} => {}", .{ inst, result });
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
branch.inst_table.putAssumeCapacityNoClobber(inst, result);
@@ -4568,7 +4568,7 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
}
// Prevent the operand deaths processing code from deallocating it.
- self.liveness.clearOperandDeath(inst, op_index);
+ self.reused_operands.set(op_index);
// That makes us responsible for doing the rest of the stuff that processDeath would have done.
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
src/arch/x86_64/abi.zig
@@ -250,9 +250,8 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: std.Target, ctx: Context) [8
return memory_class;
},
.optional => {
- if (ty.isPtrLikeOptional(zcu)) {
- result[0] = .integer;
- return result;
+ if (ty.optionalReprIsPayload(zcu)) {
+ return classifySystemV(ty.optionalChild(zcu), zcu, target, ctx);
}
return memory_class;
},
src/arch/x86_64/bits.zig
@@ -547,7 +547,39 @@ pub const Memory = struct {
}
};
- pub const Scale = enum(u2) { @"1", @"2", @"4", @"8" };
+ pub const Scale = enum(u2) {
+ @"1",
+ @"2",
+ @"4",
+ @"8",
+
+ pub fn fromFactor(factor: u4) Scale {
+ return switch (factor) {
+ else => unreachable,
+ 1 => .@"1",
+ 2 => .@"2",
+ 4 => .@"4",
+ 8 => .@"8",
+ };
+ }
+
+ pub fn toFactor(scale: Scale) u4 {
+ return switch (scale) {
+ .@"1" => 1,
+ .@"2" => 2,
+ .@"4" => 4,
+ .@"8" => 8,
+ };
+ }
+
+ pub fn fromLog2(log2: u2) Scale {
+ return @enumFromInt(log2);
+ }
+
+ pub fn toLog2(scale: Scale) u2 {
+ return @intFromEnum(scale);
+ }
+ };
};
pub const Immediate = union(enum) {
src/arch/x86_64/CodeGen.zig
@@ -1,41 +1,26 @@
const std = @import("std");
-const build_options = @import("build_options");
-const builtin = @import("builtin");
const assert = std.debug.assert;
const codegen = @import("../../codegen.zig");
-const leb128 = std.leb;
const link = @import("../../link.zig");
const log = std.log.scoped(.codegen);
const tracking_log = std.log.scoped(.tracking);
const verbose_tracking_log = std.log.scoped(.verbose_tracking);
const wip_mir_log = std.log.scoped(.wip_mir);
-const math = std.math;
-const mem = std.mem;
-const target_util = @import("../../target.zig");
-const trace = @import("../../tracy.zig").trace;
const Air = @import("../../Air.zig");
-const Allocator = mem.Allocator;
-const CodeGenError = codegen.CodeGenError;
-const Compilation = @import("../../Compilation.zig");
-const ErrorMsg = Zcu.ErrorMsg;
+const Allocator = std.mem.Allocator;
const Emit = @import("Emit.zig");
const Liveness = @import("../../Liveness.zig");
const Lower = @import("Lower.zig");
const Mir = @import("Mir.zig");
-const Package = @import("../../Package.zig");
const Zcu = @import("../../Zcu.zig");
+const Module = @import("../../Package/Module.zig");
const InternPool = @import("../../InternPool.zig");
-const Alignment = InternPool.Alignment;
-const Target = std.Target;
const Type = @import("../../Type.zig");
const Value = @import("../../Value.zig");
-const Instruction = @import("encoder.zig").Instruction;
const abi = @import("abi.zig");
const bits = @import("bits.zig");
-const errUnionErrorOffset = codegen.errUnionErrorOffset;
-const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
const encoder = @import("encoder.zig");
const Condition = bits.Condition;
@@ -46,7 +31,7 @@ const RegisterManager = abi.RegisterManager;
const RegisterLock = RegisterManager.RegisterLock;
const FrameIndex = bits.FrameIndex;
-const InnerError = CodeGenError || error{OutOfRegisters};
+const InnerError = codegen.CodeGenError || error{OutOfRegisters};
gpa: Allocator,
pt: Zcu.PerThread,
@@ -57,7 +42,7 @@ debug_output: link.File.DebugInfoOutput,
target: *const std.Target,
owner: Owner,
inline_func: InternPool.Index,
-mod: *Package.Module,
+mod: *Module,
arg_index: u32,
args: []MCValue,
va_info: union {
@@ -89,6 +74,7 @@ end_di_column: u32,
/// which is a relative jump, based on the address following the reloc.
exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
+reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
const_tracking: ConstTrackingMap = .{},
inst_tracking: InstTrackingMap = .{},
@@ -108,13 +94,11 @@ loops: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
/// The state to restore before branching.
state: State,
/// The branch target.
- jmp_target: Mir.Inst.Index,
+ target: Mir.Inst.Index,
}) = .{},
-/// Debug field, used to find bugs in the compiler.
-air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
-
-const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
+next_temp_index: Temp.Index = @enumFromInt(0),
+temp_type: [Temp.Index.max]Type = undefined,
const Owner = union(enum) {
nav_index: InternPool.Nav.Index,
@@ -433,7 +417,7 @@ pub const MCValue = union(enum) {
.reserved_frame,
.lea_symbol,
=> unreachable,
- .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
+ .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
.base = .{ .reg = .ds },
.mod = .{ .rm = .{
.size = size,
@@ -484,8 +468,8 @@ pub const MCValue = union(enum) {
.register_overflow => |pl| try writer.print("{s}:{s}", .{
@tagName(pl.eflags), @tagName(pl.reg),
}),
- .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym_index, pl.off }),
- .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
+ .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }),
+ .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }),
.indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
.load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
.lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
@@ -562,7 +546,7 @@ const InstTracking = struct {
.reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },
else => unreachable,
}
- tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });
+ tracking_log.debug("spill {} from {} to {}", .{ inst, self.short, self.long });
try function.genCopy(function.typeOfIndex(inst), self.long, self.short, .{});
}
@@ -605,7 +589,7 @@ const InstTracking = struct {
fn trackSpill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void {
try function.freeValue(self.short);
self.reuseFrame();
- tracking_log.debug("%{d} => {} (spilled)", .{ inst, self.* });
+ tracking_log.debug("{} => {} (spilled)", .{ inst, self.* });
}
fn verifyMaterialize(self: InstTracking, target: InstTracking) void {
@@ -678,14 +662,14 @@ const InstTracking = struct {
else => target.long,
} else target.long;
self.short = target.short;
- tracking_log.debug("%{d} => {} (materialize)", .{ inst, self.* });
+ tracking_log.debug("{} => {} (materialize)", .{ inst, self.* });
}
fn resurrect(self: *InstTracking, inst: Air.Inst.Index, scope_generation: u32) void {
switch (self.short) {
.dead => |die_generation| if (die_generation >= scope_generation) {
self.reuseFrame();
- tracking_log.debug("%{d} => {} (resurrect)", .{ inst, self.* });
+ tracking_log.debug("{} => {} (resurrect)", .{ inst, self.* });
},
else => {},
}
@@ -695,7 +679,7 @@ const InstTracking = struct {
if (self.short == .dead) return;
try function.freeValue(self.short);
self.short = .{ .dead = function.scope_generation };
- tracking_log.debug("%{d} => {} (death)", .{ inst, self.* });
+ tracking_log.debug("{} => {} (death)", .{ inst, self.* });
}
fn reuse(
@@ -705,16 +689,13 @@ const InstTracking = struct {
old_inst: Air.Inst.Index,
) void {
self.short = .{ .dead = function.scope_generation };
- if (new_inst) |inst|
- tracking_log.debug("%{d} => {} (reuse %{d})", .{ inst, self.*, old_inst })
- else
- tracking_log.debug("tmp => {} (reuse %{d})", .{ self.*, old_inst });
+ tracking_log.debug("{?} => {} (reuse {})", .{ new_inst, self.*, old_inst });
}
fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void {
for (self.getRegs()) |reg| {
if (function.register_manager.isRegFree(reg)) {
- tracking_log.debug("%{d} => {} (live-out)", .{ inst, self.* });
+ tracking_log.debug("{} => {} (live-out)", .{ inst, self.* });
continue;
}
@@ -741,7 +722,7 @@ const InstTracking = struct {
// Perform side-effects of freeValue manually.
function.register_manager.freeReg(reg);
- tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, self.*, tracked_inst });
+ tracking_log.debug("{} => {} (live-out {})", .{ inst, self.*, tracked_inst });
}
}
@@ -759,10 +740,10 @@ const InstTracking = struct {
const FrameAlloc = struct {
abi_size: u31,
spill_pad: u3,
- abi_align: Alignment,
+ abi_align: InternPool.Alignment,
ref_count: u16,
- fn init(alloc_abi: struct { size: u64, pad: u3 = 0, alignment: Alignment }) FrameAlloc {
+ fn init(alloc_abi: struct { size: u64, pad: u3 = 0, alignment: InternPool.Alignment }) FrameAlloc {
return .{
.abi_size = @intCast(alloc_abi.size),
.spill_pad = alloc_abi.pad,
@@ -779,14 +760,14 @@ const FrameAlloc = struct {
fn initSpill(ty: Type, zcu: *Zcu) FrameAlloc {
const abi_size = ty.abiSize(zcu);
const spill_size = if (abi_size < 8)
- math.ceilPowerOfTwoAssert(u64, abi_size)
+ std.math.ceilPowerOfTwoAssert(u64, abi_size)
else
std.mem.alignForward(u64, abi_size, 8);
return init(.{
.size = spill_size,
.pad = @intCast(spill_size - abi_size),
.alignment = ty.abiAlignment(zcu).maxStrict(
- Alignment.fromNonzeroByteUnits(@min(spill_size, 8)),
+ InternPool.Alignment.fromNonzeroByteUnits(@min(spill_size, 8)),
),
});
}
@@ -819,7 +800,7 @@ pub fn generate(
liveness: Liveness,
code: *std.ArrayListUnmanaged(u8),
debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+) codegen.CodeGenError!void {
const zcu = pt.zcu;
const comp = zcu.comp;
const gpa = zcu.gpa;
@@ -862,6 +843,11 @@ pub fn generate(
function.mir_instructions.deinit(gpa);
function.mir_extra.deinit(gpa);
}
+ try function.inst_tracking.ensureTotalCapacity(gpa, Temp.Index.max);
+ for (0..Temp.Index.max) |temp_index| {
+ const temp: Temp.Index = @enumFromInt(temp_index);
+ function.inst_tracking.putAssumeCapacityNoClobber(temp.toIndex(), InstTracking.init(.none));
+ }
wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});
@@ -891,9 +877,9 @@ pub fn generate(
}));
function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{
.size = Type.usize.abiSize(zcu),
- .alignment = Alignment.min(
+ .alignment = InternPool.Alignment.min(
call_info.stack_align,
- Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
+ InternPool.Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
),
}));
function.frame_allocs.set(
@@ -972,7 +958,7 @@ pub fn generateLazy(
lazy_sym: link.File.LazySymbol,
code: *std.ArrayListUnmanaged(u8),
debug_output: link.File.DebugInfoOutput,
-) CodeGenError!void {
+) codegen.CodeGenError!void {
const comp = bin_file.comp;
const gpa = comp.gpa;
// This function is for generating global code, so we use the root module.
@@ -1169,14 +1155,14 @@ fn formatWipMir(
lower.mir.extraData(Mir.Imm64, mir_inst.data.ai.i).data.decode(),
}),
.pseudo_dbg_local_as => {
- const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
+ const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
.base = .{ .reloc = mir_inst.data.as.sym_index },
}) };
try writer.print(" {}, {}", .{ mir_inst.data.as.air_inst, mem_op.fmt(.m) });
},
.pseudo_dbg_local_aso => {
const sym_off = lower.mir.extraData(bits.SymbolOffset, mir_inst.data.ax.payload).data;
- const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
+ const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
.base = .{ .reloc = sym_off.sym_index },
.disp = sym_off.off,
}) };
@@ -1184,7 +1170,7 @@ fn formatWipMir(
},
.pseudo_dbg_local_aro => {
const air_off = lower.mir.extraData(Mir.AirOffset, mir_inst.data.rx.payload).data;
- const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
+ const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
.base = .{ .reg = mir_inst.data.rx.r1 },
.disp = air_off.off,
}) };
@@ -1192,14 +1178,14 @@ fn formatWipMir(
},
.pseudo_dbg_local_af => {
const frame_addr = lower.mir.extraData(bits.FrameAddr, mir_inst.data.ax.payload).data;
- const mem_op: Instruction.Operand = .{ .mem = .initSib(.qword, .{
+ const mem_op: encoder.Instruction.Operand = .{ .mem = .initSib(.qword, .{
.base = .{ .frame = frame_addr.index },
.disp = frame_addr.off,
}) };
- try writer.print(" {}, {d}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
+ try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
},
.pseudo_dbg_local_am => {
- const mem_op: Instruction.Operand = .{
+ const mem_op: encoder.Instruction.Operand = .{
.mem = lower.mir.extraData(Mir.Memory, mir_inst.data.ax.payload).data.decode(),
};
try writer.print(" {}, {}", .{ mir_inst.data.ax.air_inst, mem_op.fmt(.m) });
@@ -1221,7 +1207,7 @@ fn formatTracking(
writer: anytype,
) @TypeOf(writer).Error!void {
var it = data.self.inst_tracking.iterator();
- while (it.next()) |entry| try writer.print("\n%{d} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });
+ while (it.next()) |entry| try writer.print("\n{} = {}", .{ entry.key_ptr.*, entry.value_ptr.* });
}
fn fmtTracking(self: *Self) std.fmt.Formatter(formatTracking) {
return .{ .data = .{ .self = self } };
@@ -1427,7 +1413,7 @@ fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immed
.i = @bitCast(s),
} },
}),
- .unsigned => |u| _ = if (math.cast(u32, u)) |small| try self.addInst(.{
+ .unsigned => |u| _ = if (std.math.cast(u32, u)) |small| try self.addInst(.{
.tag = .pseudo,
.ops = switch (tag) {
.dbg_local => .pseudo_dbg_local_ai_u,
@@ -1632,7 +1618,7 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2
fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {
const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {
.signed => |s| .{ .ri_s, @bitCast(s) },
- .unsigned => |u| if (math.cast(u32, u)) |small|
+ .unsigned => |u| if (std.math.cast(u32, u)) |small|
.{ .ri_u, small }
else
.{ .ri_64, try self.addExtra(Mir.Imm64.encode(imm.unsigned)) },
@@ -1831,8 +1817,8 @@ fn asmRegisterMemoryImmediate(
imm: Immediate,
) !void {
if (switch (imm) {
- .signed => |s| if (math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
- .unsigned => |u| math.cast(u16, u),
+ .signed => |s| if (std.math.cast(i16, s)) |x| @as(u16, @bitCast(x)) else null,
+ .unsigned => |u| std.math.cast(u16, u),
.reloc => unreachable,
}) |small_imm| {
_ = try self.addInst(.{
@@ -1967,8 +1953,8 @@ fn gen(self: *Self) InnerError!void {
const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
if (cc != .naked) {
try self.asmRegister(.{ ._, .push }, .rbp);
- try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8));
- try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0));
+ try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, .s(8));
+ try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, .s(0));
try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
try self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, .rbp);
const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
@@ -2016,7 +2002,7 @@ fn gen(self: *Self) InnerError!void {
.{},
);
- try self.asmRegisterImmediate(.{ ._, .cmp }, .al, Immediate.u(info.fp_count));
+ try self.asmRegisterImmediate(.{ ._, .cmp }, .al, .u(info.fp_count));
const skip_sse_reloc = try self.asmJccReloc(.na, undefined);
const vec_2_f64 = try pt.vectorType(.{ .len = 2, .child = .f64_type });
@@ -2055,15 +2041,15 @@ fn gen(self: *Self) InnerError!void {
const backpatch_stack_dealloc = try self.asmPlaceholder();
const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
try self.asmRegister(.{ ._, .pop }, .rbp);
- try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, Immediate.s(8));
+ try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, .s(8));
try self.asmOpOnly(.{ ._, .ret });
const frame_layout = try self.computeFrameLayout(cc);
- const need_frame_align = frame_layout.stack_mask != math.maxInt(u32);
+ const need_frame_align = frame_layout.stack_mask != std.math.maxInt(u32);
const need_stack_adjust = frame_layout.stack_adjust > 0;
const need_save_reg = frame_layout.save_reg_list.count() > 0;
if (need_frame_align) {
- const page_align = @as(u32, math.maxInt(u32)) << 12;
+ const page_align = @as(u32, std.math.maxInt(u32)) << 12;
self.mir_instructions.set(backpatch_frame_align, .{
.tag = .@"and",
.ops = .ri_s,
@@ -2170,23 +2156,18 @@ fn gen(self: *Self) InnerError!void {
});
}
-fn checkInvariantsAfterAirInst(self: *Self, inst: Air.Inst.Index, old_air_bookkeeping: @TypeOf(air_bookkeeping_init)) void {
+fn checkInvariantsAfterAirInst(self: *Self) void {
assert(!self.register_manager.lockedRegsExist());
if (std.debug.runtime_safety) {
- if (self.air_bookkeeping < old_air_bookkeeping + 1) {
- 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)] });
- }
-
- { // check consistency of tracked registers
- var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
- while (it.next()) |index| {
- const tracked_inst = self.register_manager.registers[index];
- const tracking = self.getResolvedInstValue(tracked_inst);
- for (tracking.getRegs()) |reg| {
- if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
- } else unreachable; // tracked register not in use
- }
+ // check consistency of tracked registers
+ var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
+ while (it.next()) |index| {
+ const tracked_inst = self.register_manager.registers[index];
+ const tracking = self.getResolvedInstValue(tracked_inst);
+ for (tracking.getRegs()) |reg| {
+ if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
+ } else unreachable; // tracked register not in use
}
}
}
@@ -2202,6 +2183,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const air_tags = self.air.instructions.items(.tag);
+ const air_datas = self.air.instructions.items(.data);
+ const use_old = self.target.ofmt == .coff;
self.arg_index = 0;
for (body) |inst| switch (air_tags[@intFromEnum(inst)]) {
@@ -2209,12 +2192,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
wip_mir_log.debug("{}", .{self.fmtAir(inst)});
verbose_tracking_log.debug("{}", .{self.fmtTracking()});
- const old_air_bookkeeping = self.air_bookkeeping;
+ self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);
try self.airArg(inst);
- self.checkInvariantsAfterAirInst(inst, old_air_bookkeeping);
+ self.resetTemps();
+ self.checkInvariantsAfterAirInst();
},
else => break,
};
@@ -2226,7 +2210,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
wip_mir_log.debug("{}", .{self.fmtAir(inst)});
verbose_tracking_log.debug("{}", .{self.fmtTracking()});
- const old_air_bookkeeping = self.air_bookkeeping;
+ self.reused_operands = @TypeOf(self.reused_operands).initEmpty();
try self.inst_tracking.ensureUnusedCapacity(self.gpa, 1);
switch (air_tags[@intFromEnum(inst)]) {
// zig fmt: off
@@ -2260,7 +2244,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.sub_sat => try self.airSubSat(inst),
.mul_sat => try self.airMulSat(inst),
.shl_sat => try self.airShlSat(inst),
- .slice => try self.airSlice(inst),
.sin,
.cos,
@@ -2298,127 +2281,58 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.cmp_vector => try self.airCmpVector(inst),
.cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
- .alloc => try self.airAlloc(inst),
- .ret_ptr => try self.airRetPtr(inst),
- .arg => try self.airDbgArg(inst),
- .assembly => try self.airAsm(inst),
- .bitcast => try self.airBitCast(inst),
- .block => try self.airBlock(inst),
- .br => try self.airBr(inst),
- .repeat => try self.airRepeat(inst),
- .switch_dispatch => try self.airSwitchDispatch(inst),
- .trap => try self.airTrap(),
- .breakpoint => try self.airBreakpoint(),
- .ret_addr => try self.airRetAddr(inst),
- .frame_addr => try self.airFrameAddress(inst),
- .cond_br => try self.airCondBr(inst),
- .fptrunc => try self.airFptrunc(inst),
- .fpext => try self.airFpext(inst),
- .intcast => try self.airIntCast(inst),
- .trunc => try self.airTrunc(inst),
- .int_from_bool => try self.airIntFromBool(inst),
- .is_non_null => try self.airIsNonNull(inst),
- .is_non_null_ptr => try self.airIsNonNullPtr(inst),
- .is_null => try self.airIsNull(inst),
- .is_null_ptr => try self.airIsNullPtr(inst),
- .is_non_err => try self.airIsNonErr(inst),
- .is_non_err_ptr => try self.airIsNonErrPtr(inst),
- .is_err => try self.airIsErr(inst),
- .is_err_ptr => try self.airIsErrPtr(inst),
- .load => try self.airLoad(inst),
- .loop => try self.airLoop(inst),
- .int_from_ptr => try self.airIntFromPtr(inst),
- .ret => try self.airRet(inst, false),
- .ret_safe => try self.airRet(inst, true),
- .ret_load => try self.airRetLoad(inst),
- .store => try self.airStore(inst, false),
- .store_safe => try self.airStore(inst, true),
- .struct_field_ptr=> try self.airStructFieldPtr(inst),
- .struct_field_val=> try self.airStructFieldVal(inst),
- .array_to_slice => try self.airArrayToSlice(inst),
- .float_from_int => try self.airFloatFromInt(inst),
- .int_from_float => try self.airIntFromFloat(inst),
- .cmpxchg_strong => try self.airCmpxchg(inst),
- .cmpxchg_weak => try self.airCmpxchg(inst),
- .atomic_rmw => try self.airAtomicRmw(inst),
- .atomic_load => try self.airAtomicLoad(inst),
- .memcpy => try self.airMemcpy(inst),
- .memset => try self.airMemset(inst, false),
- .memset_safe => try self.airMemset(inst, true),
- .set_union_tag => try self.airSetUnionTag(inst),
- .get_union_tag => try self.airGetUnionTag(inst),
- .clz => try self.airClz(inst),
- .ctz => try self.airCtz(inst),
- .popcount => try self.airPopCount(inst),
- .byte_swap => try self.airByteSwap(inst),
- .bit_reverse => try self.airBitReverse(inst),
- .tag_name => try self.airTagName(inst),
- .error_name => try self.airErrorName(inst),
- .splat => try self.airSplat(inst),
- .select => try self.airSelect(inst),
- .shuffle => try self.airShuffle(inst),
- .reduce => try self.airReduce(inst),
- .aggregate_init => try self.airAggregateInit(inst),
- .union_init => try self.airUnionInit(inst),
- .prefetch => try self.airPrefetch(inst),
- .mul_add => try self.airMulAdd(inst),
- .addrspace_cast => return self.fail("TODO implement addrspace_cast", .{}),
-
- .@"try" => try self.airTry(inst),
- .try_cold => try self.airTry(inst), // TODO
- .try_ptr => try self.airTryPtr(inst),
- .try_ptr_cold => try self.airTryPtr(inst), // TODO
-
- .dbg_stmt => try self.airDbgStmt(inst),
- .dbg_empty_stmt => try self.airDbgEmptyStmt(),
- .dbg_inline_block => try self.airDbgInlineBlock(inst),
- .dbg_var_ptr,
- .dbg_var_val,
- .dbg_arg_inline,
- => try self.airDbgVar(inst),
-
- .call => try self.airCall(inst, .auto),
- .call_always_tail => try self.airCall(inst, .always_tail),
- .call_never_tail => try self.airCall(inst, .never_tail),
- .call_never_inline => try self.airCall(inst, .never_inline),
+ .bitcast => try self.airBitCast(inst),
+ .fptrunc => try self.airFptrunc(inst),
+ .fpext => try self.airFpext(inst),
+ .intcast => try self.airIntCast(inst),
+ .trunc => try self.airTrunc(inst),
+ .is_non_null => try self.airIsNonNull(inst),
+ .is_null => try self.airIsNull(inst),
+ .is_non_err => try self.airIsNonErr(inst),
+ .is_err => try self.airIsErr(inst),
+ .load => try self.airLoad(inst),
+ .store => try self.airStore(inst, false),
+ .store_safe => try self.airStore(inst, true),
+ .struct_field_val => try self.airStructFieldVal(inst),
+ .float_from_int => try self.airFloatFromInt(inst),
+ .int_from_float => try self.airIntFromFloat(inst),
+ .cmpxchg_strong => try self.airCmpxchg(inst),
+ .cmpxchg_weak => try self.airCmpxchg(inst),
+ .atomic_rmw => try self.airAtomicRmw(inst),
+ .atomic_load => try self.airAtomicLoad(inst),
+ .memcpy => try self.airMemcpy(inst),
+ .memset => try self.airMemset(inst, false),
+ .memset_safe => try self.airMemset(inst, true),
+ .set_union_tag => try self.airSetUnionTag(inst),
+ .get_union_tag => try self.airGetUnionTag(inst),
+ .clz => try self.airClz(inst),
+ .ctz => try self.airCtz(inst),
+ .popcount => try self.airPopCount(inst),
+ .byte_swap => try self.airByteSwap(inst),
+ .bit_reverse => try self.airBitReverse(inst),
+ .tag_name => try self.airTagName(inst),
+ .error_name => try self.airErrorName(inst),
+ .splat => try self.airSplat(inst),
+ .select => try self.airSelect(inst),
+ .shuffle => try self.airShuffle(inst),
+ .reduce => try self.airReduce(inst),
+ .aggregate_init => try self.airAggregateInit(inst),
+ .union_init => try self.airUnionInit(inst),
+ .prefetch => try self.airPrefetch(inst),
+ .mul_add => try self.airMulAdd(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .monotonic),
.atomic_store_release => try self.airAtomicStore(inst, .release),
.atomic_store_seq_cst => try self.airAtomicStore(inst, .seq_cst),
- .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
- .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
- .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
- .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
-
- .field_parent_ptr => try self.airFieldParentPtr(inst),
-
- .switch_br => try self.airSwitchBr(inst),
- .loop_switch_br => try self.airLoopSwitchBr(inst),
- .slice_ptr => try self.airSlicePtr(inst),
- .slice_len => try self.airSliceLen(inst),
-
- .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst),
- .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst),
-
.array_elem_val => try self.airArrayElemVal(inst),
.slice_elem_val => try self.airSliceElemVal(inst),
- .slice_elem_ptr => try self.airSliceElemPtr(inst),
.ptr_elem_val => try self.airPtrElemVal(inst),
- .ptr_elem_ptr => try self.airPtrElemPtr(inst),
-
- .inferred_alloc, .inferred_alloc_comptime => unreachable,
- .unreach => self.finishAirBookkeeping(),
.optional_payload => try self.airOptionalPayload(inst),
- .optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
- .optional_payload_ptr_set => try self.airOptionalPayloadPtrSet(inst),
.unwrap_errunion_err => try self.airUnwrapErrUnionErr(inst),
.unwrap_errunion_payload => try self.airUnwrapErrUnionPayload(inst),
- .unwrap_errunion_err_ptr => try self.airUnwrapErrUnionErrPtr(inst),
- .unwrap_errunion_payload_ptr=> try self.airUnwrapErrUnionPayloadPtr(inst),
- .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst),
.err_return_trace => try self.airErrReturnTrace(inst),
.set_err_return_trace => try self.airSetErrReturnTrace(inst),
.save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst),
@@ -2426,7 +2340,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.wrap_optional => try self.airWrapOptional(inst),
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
+ // zig fmt: on
+ .add_safe,
+ .sub_safe,
+ .mul_safe,
+ => return self.fail("TODO implement safety_checked_instructions", .{}),
.add_optimized,
.sub_optimized,
.mul_optimized,
@@ -2448,13 +2367,429 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.int_from_float_optimized,
=> return self.fail("TODO implement optimized float mode", .{}),
- .add_safe,
- .sub_safe,
- .mul_safe,
- => return self.fail("TODO implement safety_checked_instructions", .{}),
+ .arg => try self.airDbgArg(inst),
+ .alloc => if (use_old) try self.airAlloc(inst) else {
+ var slot = try self.tempFromValue(self.typeOfIndex(inst), .{ .lea_frame = .{
+ .index = try self.allocMemPtr(inst),
+ } });
+ try slot.moveTo(inst, self);
+ },
+ .inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
+ .ret_ptr => if (use_old) try self.airRetPtr(inst) else {
+ var slot = switch (self.ret_mcv.long) {
+ else => unreachable,
+ .none => try self.tempFromValue(self.typeOfIndex(inst), .{ .lea_frame = .{
+ .index = try self.allocMemPtr(inst),
+ } }),
+ .load_frame => slot: {
+ var slot = try self.tempFromValue(self.typeOfIndex(inst), self.ret_mcv.long);
+ try slot.toOffset(self.ret_mcv.short.indirect.off, self);
+ break :slot slot;
+ },
+ };
+ try slot.moveTo(inst, self);
+ },
+ .assembly => try self.airAsm(inst),
+ .block => if (use_old) try self.airBlock(inst) else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const extra = self.air.extraData(Air.Block, ty_pl.payload);
+ try self.asmPseudo(.pseudo_dbg_enter_block_none);
+ try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
+ try self.asmPseudo(.pseudo_dbg_leave_block_none);
+ },
+ .loop => if (use_old) try self.airLoop(inst) else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const extra = self.air.extraData(Air.Block, ty_pl.payload);
+ self.scope_generation += 1;
+ try self.loops.putNoClobber(self.gpa, inst, .{
+ .state = try self.saveState(),
+ .target = @intCast(self.mir_instructions.len),
+ });
+ defer assert(self.loops.remove(inst));
+ try self.genBodyBlock(@ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
+ },
+ .repeat => if (use_old) try self.airRepeat(inst) else {
+ const repeat = air_datas[@intFromEnum(inst)].repeat;
+ const loop = self.loops.get(repeat.loop_inst).?;
+ try self.restoreState(loop.state, &.{}, .{
+ .emit_instructions = true,
+ .update_tracking = false,
+ .resurrect = false,
+ .close_scope = true,
+ });
+ _ = try self.asmJmpReloc(loop.target);
+ },
+ .br => try self.airBr(inst),
+ .trap => try self.asmOpOnly(.{ ._, .ud2 }),
+ .breakpoint => try self.asmOpOnly(.{ ._, .int3 }),
+ .ret_addr => if (use_old) try self.airRetAddr(inst) else {
+ var slot = try self.tempFromValue(self.typeOfIndex(inst), .{ .load_frame = .{
+ .index = .ret_addr,
+ } });
+ while (try slot.toAnyReg(self)) {}
+ try slot.moveTo(inst, self);
+ },
+ .frame_addr => if (use_old) try self.airFrameAddress(inst) else {
+ var slot = try self.tempFromValue(self.typeOfIndex(inst), .{ .lea_frame = .{
+ .index = .base_ptr,
+ } });
+ try slot.moveTo(inst, self);
+ },
+ .call => try self.airCall(inst, .auto),
+ .call_always_tail => try self.airCall(inst, .always_tail),
+ .call_never_tail => try self.airCall(inst, .never_tail),
+ .call_never_inline => try self.airCall(inst, .never_inline),
- .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
+ .cond_br => try self.airCondBr(inst),
+ .switch_br => try self.airSwitchBr(inst),
+ .loop_switch_br => try self.airLoopSwitchBr(inst),
+ .switch_dispatch => try self.airSwitchDispatch(inst),
+ .@"try", .try_cold => try self.airTry(inst),
+ .try_ptr, .try_ptr_cold => try self.airTryPtr(inst),
+ .dbg_stmt => if (use_old) try self.airDbgStmt(inst) else {
+ const dbg_stmt = air_datas[@intFromEnum(inst)].dbg_stmt;
+ _ = try self.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_line_line_column,
+ .data = .{ .line_column = .{
+ .line = dbg_stmt.line,
+ .column = dbg_stmt.column,
+ } },
+ });
+ },
+ .dbg_empty_stmt => if (use_old) try self.airDbgEmptyStmt() else {
+ if (self.mir_instructions.len > 0) {
+ const prev_mir_op = &self.mir_instructions.items(.ops)[self.mir_instructions.len - 1];
+ if (prev_mir_op.* == .pseudo_dbg_line_stmt_line_column)
+ prev_mir_op.* = .pseudo_dbg_line_line_column;
+ }
+ try self.asmOpOnly(.{ ._, .nop });
+ },
+ .dbg_inline_block => if (use_old) try self.airDbgInlineBlock(inst) else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
+ const old_inline_func = self.inline_func;
+ defer self.inline_func = old_inline_func;
+ self.inline_func = extra.data.func;
+ _ = try self.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_enter_inline_func,
+ .data = .{ .func = extra.data.func },
+ });
+ try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
+ _ = try self.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_dbg_leave_inline_func,
+ .data = .{ .func = old_inline_func },
+ });
+ },
+ .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => if (use_old) try self.airDbgVar(inst) else {
+ const pl_op = air_datas[@intFromEnum(inst)].pl_op;
+ var ops = try self.tempsFromOperands(inst, .{pl_op.operand});
+ try self.genLocalDebugInfo(inst, ops[0].tracking(self).short);
+ try ops[0].die(self);
+ },
+ .is_null_ptr => if (use_old) try self.airIsNullPtr(inst) else {
+ const un_op = air_datas[@intFromEnum(inst)].un_op;
+ const opt_ty = self.typeOf(un_op).childType(zcu);
+ const opt_repr_is_pl = opt_ty.optionalReprIsPayload(zcu);
+ const opt_child_ty = opt_ty.optionalChild(zcu);
+ const opt_child_abi_size: u31 = @intCast(opt_child_ty.abiSize(zcu));
+ var ops = try self.tempsFromOperands(inst, .{un_op});
+ if (!opt_repr_is_pl) try ops[0].toOffset(opt_child_abi_size, self);
+ while (try ops[0].toLea(self)) {}
+ try self.asmMemoryImmediate(
+ .{ ._, .cmp },
+ try ops[0].tracking(self).short.deref().mem(self, if (!opt_repr_is_pl)
+ .byte
+ else if (opt_child_ty.isSlice(zcu))
+ .qword
+ else
+ Memory.Size.fromSize(opt_child_abi_size)),
+ .u(0),
+ );
+ var is_null = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .e });
+ try ops[0].die(self);
+ try is_null.moveTo(inst, self);
+ },
+ .is_non_null_ptr => if (use_old) try self.airIsNonNullPtr(inst) else {
+ const un_op = air_datas[@intFromEnum(inst)].un_op;
+ const opt_ty = self.typeOf(un_op).childType(zcu);
+ const opt_repr_is_pl = opt_ty.optionalReprIsPayload(zcu);
+ const opt_child_ty = opt_ty.optionalChild(zcu);
+ const opt_child_abi_size: u31 = @intCast(opt_child_ty.abiSize(zcu));
+ var ops = try self.tempsFromOperands(inst, .{un_op});
+ if (!opt_repr_is_pl) try ops[0].toOffset(opt_child_abi_size, self);
+ while (try ops[0].toLea(self)) {}
+ try self.asmMemoryImmediate(
+ .{ ._, .cmp },
+ try ops[0].tracking(self).short.deref().mem(self, if (!opt_repr_is_pl)
+ .byte
+ else if (opt_child_ty.isSlice(zcu))
+ .qword
+ else
+ Memory.Size.fromSize(opt_child_abi_size)),
+ .u(0),
+ );
+ var is_non_null = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .ne });
+ try ops[0].die(self);
+ try is_non_null.moveTo(inst, self);
+ },
+ .is_err_ptr => if (use_old) try self.airIsErrPtr(inst) else {
+ const un_op = air_datas[@intFromEnum(inst)].un_op;
+ const eu_ty = self.typeOf(un_op).childType(zcu);
+ const eu_err_ty = eu_ty.errorUnionSet(zcu);
+ const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
+ const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
+ var ops = try self.tempsFromOperands(inst, .{un_op});
+ try ops[0].toOffset(eu_err_off, self);
+ while (try ops[0].toLea(self)) {}
+ try self.asmMemoryImmediate(
+ .{ ._, .cmp },
+ try ops[0].tracking(self).short.deref().mem(self, self.memSize(eu_err_ty)),
+ .u(0),
+ );
+ var is_err = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .ne });
+ try ops[0].die(self);
+ try is_err.moveTo(inst, self);
+ },
+ .is_non_err_ptr => if (use_old) try self.airIsNonErrPtr(inst) else {
+ const un_op = air_datas[@intFromEnum(inst)].un_op;
+ const eu_ty = self.typeOf(un_op).childType(zcu);
+ const eu_err_ty = eu_ty.errorUnionSet(zcu);
+ const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
+ const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
+ var ops = try self.tempsFromOperands(inst, .{un_op});
+ try ops[0].toOffset(eu_err_off, self);
+ while (try ops[0].toLea(self)) {}
+ try self.asmMemoryImmediate(
+ .{ ._, .cmp },
+ try ops[0].tracking(self).short.deref().mem(self, self.memSize(eu_err_ty)),
+ .u(0),
+ );
+ var is_non_err = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .e });
+ try ops[0].die(self);
+ try is_non_err.moveTo(inst, self);
+ },
+ .int_from_ptr => if (use_old) try self.airIntFromPtr(inst) else {
+ const un_op = air_datas[@intFromEnum(inst)].un_op;
+ var ops = try self.tempsFromOperands(inst, .{un_op});
+ try ops[0].toLimb(0, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .int_from_bool => if (use_old) try self.airIntFromBool(inst) else {
+ const un_op = air_datas[@intFromEnum(inst)].un_op;
+ var ops = try self.tempsFromOperands(inst, .{un_op});
+ try ops[0].moveTo(inst, self);
+ },
+ .ret => try self.airRet(inst, false),
+ .ret_safe => try self.airRet(inst, true),
+ .ret_load => try self.airRetLoad(inst),
+ .unreach => {},
+ .optional_payload_ptr => if (use_old) try self.airOptionalPayloadPtr(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].moveTo(inst, self);
+ },
+ .optional_payload_ptr_set => if (use_old) try self.airOptionalPayloadPtrSet(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ const opt_ty = self.typeOf(ty_op.operand).childType(zcu);
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ if (!opt_ty.optionalReprIsPayload(zcu)) {
+ const opt_child_ty = opt_ty.optionalChild(zcu);
+ const opt_child_abi_size: i32 = @intCast(opt_child_ty.abiSize(zcu));
+ try ops[0].toOffset(opt_child_abi_size, self);
+ var has_value = try self.tempFromValue(Type.bool, .{ .immediate = 1 });
+ try ops[0].store(&has_value, self);
+ try has_value.die(self);
+ try ops[0].toOffset(-opt_child_abi_size, self);
+ }
+ try ops[0].moveTo(inst, self);
+ },
+ .unwrap_errunion_payload_ptr => if (use_old) try self.airUnwrapErrUnionPayloadPtr(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ const eu_ty = self.typeOf(ty_op.operand).childType(zcu);
+ const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
+ const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(eu_pl_off, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .unwrap_errunion_err_ptr => if (use_old) try self.airUnwrapErrUnionErrPtr(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ const eu_ty = self.typeOf(ty_op.operand).childType(zcu);
+ const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
+ const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(eu_err_off, self);
+ var err = try ops[0].load(eu_ty.errorUnionSet(zcu), self);
+ try ops[0].die(self);
+ try err.moveTo(inst, self);
+ },
+ .errunion_payload_ptr_set => if (use_old) try self.airErrUnionPayloadPtrSet(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ const eu_ty = self.typeOf(ty_op.operand).childType(zcu);
+ const eu_err_ty = eu_ty.errorUnionSet(zcu);
+ const eu_pl_ty = eu_ty.errorUnionPayload(zcu);
+ const eu_err_off: i32 = @intCast(codegen.errUnionErrorOffset(eu_pl_ty, zcu));
+ const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu));
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(eu_err_off, self);
+ var no_err = try self.tempFromValue(eu_err_ty, .{ .immediate = 0 });
+ try ops[0].store(&no_err, self);
+ try no_err.die(self);
+ try ops[0].toOffset(eu_pl_off - eu_err_off, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .struct_field_ptr => if (use_old) try self.airStructFieldPtr(inst) else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
+ var ops = try self.tempsFromOperands(inst, .{extra.struct_operand});
+ try ops[0].toOffset(self.fieldOffset(self.typeOf(extra.struct_operand), self.typeOfIndex(inst), extra.field_index), self);
+ try ops[0].moveTo(inst, self);
+ },
+ .struct_field_ptr_index_0 => if (use_old) try self.airStructFieldPtrIndex(inst, 0) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 0), self);
+ try ops[0].moveTo(inst, self);
+ },
+ .struct_field_ptr_index_1 => if (use_old) try self.airStructFieldPtrIndex(inst, 1) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 1), self);
+ try ops[0].moveTo(inst, self);
+ },
+ .struct_field_ptr_index_2 => if (use_old) try self.airStructFieldPtrIndex(inst, 2) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 2), self);
+ try ops[0].moveTo(inst, self);
+ },
+ .struct_field_ptr_index_3 => if (use_old) try self.airStructFieldPtrIndex(inst, 3) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(self.fieldOffset(self.typeOf(ty_op.operand), self.typeOfIndex(inst), 3), self);
+ try ops[0].moveTo(inst, self);
+ },
+ .slice => if (use_old) try self.airSlice(inst) else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
+ var ops = try self.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
+ try ops[0].toPair(&ops[1], self);
+ try ops[0].moveTo(inst, self);
+ },
+ .slice_len => if (use_old) try self.airSliceLen(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toLimb(1, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .slice_ptr => if (use_old) try self.airSlicePtr(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toLimb(0, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .ptr_slice_len_ptr => if (use_old) try self.airPtrSliceLenPtr(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(8, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .ptr_slice_ptr_ptr => if (use_old) try self.airPtrSlicePtrPtr(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].toOffset(0, self);
+ try ops[0].moveTo(inst, self);
+ },
+ .slice_elem_ptr, .ptr_elem_ptr => |tag| if (use_old) switch (tag) {
+ else => unreachable,
+ .slice_elem_ptr => try self.airSliceElemPtr(inst),
+ .ptr_elem_ptr => try self.airPtrElemPtr(inst),
+ } else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
+ var ops = try self.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
+ switch (tag) {
+ else => unreachable,
+ .slice_elem_ptr => try ops[0].toLimb(0, self),
+ .ptr_elem_ptr => {},
+ }
+ const dst_ty = self.typeOfIndex(inst);
+ if (dst_ty.ptrInfo(zcu).flags.vector_index == .none) zero_offset: {
+ const elem_size = dst_ty.childType(zcu).abiSize(zcu);
+ if (elem_size == 0) break :zero_offset;
+ while (true) for (&ops) |*op| {
+ if (try op.toAnyReg(self)) break;
+ } else break;
+ const lhs_reg = ops[0].unwrap(self).temp.tracking(self).short.register.to64();
+ const rhs_reg = ops[1].unwrap(self).temp.tracking(self).short.register.to64();
+ if (!std.math.isPowerOfTwo(elem_size)) {
+ try self.spillEflagsIfOccupied();
+ try self.asmRegisterRegisterImmediate(
+ .{ .i_, .mul },
+ rhs_reg,
+ rhs_reg,
+ .u(elem_size),
+ );
+ try self.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
+ .base = .{ .reg = lhs_reg },
+ .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
+ });
+ } else if (elem_size > 8) {
+ try self.spillEflagsIfOccupied();
+ try self.asmRegisterImmediate(
+ .{ ._l, .sh },
+ rhs_reg,
+ .u(std.math.log2_int(u64, elem_size)),
+ );
+ try self.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
+ .base = .{ .reg = lhs_reg },
+ .mod = .{ .rm = .{ .size = .qword, .index = rhs_reg } },
+ });
+ } else try self.asmRegisterMemory(.{ ._, .lea }, lhs_reg, .{
+ .base = .{ .reg = lhs_reg },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .index = rhs_reg,
+ .scale = .fromFactor(@intCast(elem_size)),
+ } },
+ });
+ }
+ try ops[1].die(self);
+ try ops[0].moveTo(inst, self);
+ },
+ .array_to_slice => if (use_old) try self.airArrayToSlice(inst) else {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ var len = try self.tempFromValue(Type.usize, .{
+ .immediate = self.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu),
+ });
+ try ops[0].toPair(&len, self);
+ try ops[0].moveTo(inst, self);
+ },
.error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),
+ .field_parent_ptr => if (use_old) try self.airFieldParentPtr(inst) else {
+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
+ const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
+ var ops = try self.tempsFromOperands(inst, .{extra.field_ptr});
+ try ops[0].toOffset(-self.fieldOffset(self.typeOfIndex(inst), self.typeOf(extra.field_ptr), extra.field_index), self);
+ try ops[0].moveTo(inst, self);
+ },
+
+ .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
+
+ .wasm_memory_size => unreachable,
+ .wasm_memory_grow => unreachable,
+
+ .addrspace_cast => {
+ const ty_op = air_datas[@intFromEnum(inst)].ty_op;
+ var ops = try self.tempsFromOperands(inst, .{ty_op.operand});
+ try ops[0].moveTo(inst, self);
+ },
+
.vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),
.c_va_arg => try self.airVaArg(inst),
@@ -2462,15 +2797,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.c_va_end => try self.airVaEnd(inst),
.c_va_start => try self.airVaStart(inst),
- .wasm_memory_size => unreachable,
- .wasm_memory_grow => unreachable,
-
.work_item_id => unreachable,
.work_group_size => unreachable,
.work_group_id => unreachable,
- // zig fmt: on
}
- self.checkInvariantsAfterAirInst(inst, old_air_bookkeeping);
+ self.resetTemps();
+ self.checkInvariantsAfterAirInst();
}
verbose_tracking_log.debug("{}", .{self.fmtTracking()});
}
@@ -2530,7 +2862,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
data_off += @intCast(tag_name_len + 1);
}
- try self.airTrap();
+ try self.asmOpOnly(.{ ._, .ud2 });
for (exitlude_jump_relocs) |reloc| self.performReloc(reloc);
try self.asmOpOnly(.{ ._, .ret });
@@ -2544,6 +2876,10 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) !void {
for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst);
+ switch (value) {
+ else => {},
+ .eflags, .register_overflow => self.eflags_inst = inst,
+ }
}
fn getValueIfFree(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {
@@ -2577,26 +2913,18 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) !void {
try self.inst_tracking.getPtr(inst).?.die(self, inst);
}
-/// Called when there are no operands, and the instruction is always unreferenced.
-fn finishAirBookkeeping(self: *Self) void {
- if (std.debug.runtime_safety) {
- self.air_bookkeeping += 1;
- }
-}
-
fn finishAirResult(self: *Self, inst: Air.Inst.Index, result: MCValue) void {
if (self.liveness.isUnused(inst) and self.air.instructions.items(.tag)[@intFromEnum(inst)] != .arg) switch (result) {
.none, .dead, .unreach => {},
else => unreachable, // Why didn't the result die?
} else {
- tracking_log.debug("%{d} => {} (birth)", .{ inst, result });
+ tracking_log.debug("{} => {} (birth)", .{ inst, result });
self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));
// In some cases, an operand may be reused as the result.
// If that operand died and was a register, it was freed by
// processDeath, so we have to "re-allocate" the register.
self.getValueIfFree(result, inst);
}
- self.finishAirBookkeeping();
}
fn finishAir(
@@ -2605,11 +2933,10 @@ fn finishAir(
result: MCValue,
operands: [Liveness.bpi - 1]Air.Inst.Ref,
) !void {
- var tomb_bits = self.liveness.getTombBits(inst);
- for (operands) |op| {
- const dies = @as(u1, @truncate(tomb_bits)) != 0;
- tomb_bits >>= 1;
- if (!dies) continue;
+ const tomb_bits = self.liveness.getTombBits(inst);
+ for (0.., operands) |op_index, op| {
+ if (tomb_bits & @as(Liveness.Bpi, 1) << @intCast(op_index) == 0) continue;
+ if (self.reused_operands.isSet(op_index)) continue;
try self.processDeath(op.toIndexAllowNone() orelse continue);
}
self.finishAirResult(inst, result);
@@ -2657,7 +2984,7 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
}
};
const sort_context = SortContext{ .frame_align = frame_align };
- mem.sort(FrameIndex, stack_frame_order, sort_context, SortContext.lessThan);
+ std.mem.sort(FrameIndex, stack_frame_order, sort_context, SortContext.lessThan);
}
const call_frame_align = frame_align[@intFromEnum(FrameIndex.call_frame)];
@@ -2697,13 +3024,13 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
@intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.stack_frame)]);
return .{
- .stack_mask = @as(u32, math.maxInt(u32)) << @intCast(if (need_align_stack) @intFromEnum(needed_align) else 0),
+ .stack_mask = @as(u32, std.math.maxInt(u32)) << @intCast(if (need_align_stack) @intFromEnum(needed_align) else 0),
.stack_adjust = @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.call_frame)]),
.save_reg_list = save_reg_list,
};
}
-fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
+fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) InternPool.Alignment {
const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
}
@@ -2741,7 +3068,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {
const ptr_ty = self.typeOfIndex(inst);
const val_ty = ptr_ty.childType(zcu);
return self.allocFrameIndex(FrameAlloc.init(.{
- .size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
+ .size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {
return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(pt)});
},
.alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
@@ -2759,7 +3086,7 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue {
fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue {
const pt = self.pt;
const zcu = pt.zcu;
- const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
+ const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(pt)});
};
@@ -2857,8 +3184,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
}
if (opts.resurrect) for (
- self.inst_tracking.keys()[0..state.inst_tracking_len],
- self.inst_tracking.values()[0..state.inst_tracking_len],
+ self.inst_tracking.keys()[Temp.Index.max..state.inst_tracking_len],
+ self.inst_tracking.values()[Temp.Index.max..state.inst_tracking_len],
) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);
for (deaths) |death| try self.processDeath(death);
@@ -3067,7 +3394,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
.{ .v_, .cvtps2ph },
dst_reg,
mat_src_reg.to128(),
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
},
else => unreachable,
@@ -3267,7 +3594,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
const dst_elem_abi_size = dst_ty.childType(zcu).abiSize(zcu);
const src_elem_abi_size = src_ty.childType(zcu).abiSize(zcu);
- switch (math.order(dst_elem_abi_size, src_elem_abi_size)) {
+ switch (std.math.order(dst_elem_abi_size, src_elem_abi_size)) {
.lt => {
const mir_tag: Mir.Inst.FixedTag = switch (dst_elem_abi_size) {
else => break :result null,
@@ -3431,8 +3758,8 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
};
const dst_mcv = if (dst_int_info.bits <= src_storage_bits and
- math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
- math.divCeil(u32, src_storage_bits, 64) catch unreachable and
+ std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
+ std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and
self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
const dst_mcv = try self.allocRegOrMem(inst, true);
try self.genCopy(min_ty, dst_mcv, src_mcv, .{});
@@ -3449,8 +3776,8 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
break :result .{ .register = registerAlias(dst_mcv.getReg().?, dst_abi_size) };
}
- const src_limbs_len = math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
- const dst_limbs_len = math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
+ const src_limbs_len = std.math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
+ const dst_limbs_len = std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
const high_mcv: MCValue = if (dst_mcv.isMemory())
dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()
@@ -3570,7 +3897,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
const dst_info = dst_elem_ty.intInfo(zcu);
const src_info = src_elem_ty.intInfo(zcu);
- const mask_val = try pt.intValue(src_elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(64 - dst_info.bits));
+ const mask_val = try pt.intValue(src_elem_ty, @as(u64, std.math.maxInt(u64)) >> @intCast(64 - dst_info.bits));
const splat_ty = try pt.vectorType(.{
.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 {
.{ if (self.hasFeature(.avx2)) .v_i128 else .v_f128, .extract },
registerAlias(temp_reg, dst_abi_size),
dst_alias,
- Immediate.u(1),
+ .u(1),
);
try self.asmRegisterRegisterRegister(
mir_tag,
@@ -3806,7 +4133,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
try self.asmMemoryImmediate(
.{ ._, .mov },
.{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },
- Immediate.u(0),
+ .u(0),
);
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 {
.mod = .{ .rm = .{ .size = .qword } },
},
);
- try self.asmRegisterImmediate(
- .{ ._, .sbb },
- dst_mcv.register_pair[1],
- Immediate.u(0),
- );
+ try self.asmRegisterImmediate(.{ ._, .sbb }, dst_mcv.register_pair[1], .u(0));
try self.freeValue(
.{ .load_frame = .{ .index = signed_div_floor_state.frame_index } },
);
@@ -4068,7 +4391,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
break :cc .o;
} else cc: {
try self.genSetReg(limit_reg, ty, .{
- .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - ty.bitSize(zcu)),
+ .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - ty.bitSize(zcu)),
}, .{});
try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
@@ -4266,12 +4589,12 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
mat_rhs_mcv.register_pair[1],
);
- try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
+ try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, .u(63));
try self.asmRegister(.{ ._, .not }, tmp_reg);
- try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), Immediate.s(0));
+ try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), .s(0));
try self.freeValue(overflow);
try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[0], tmp_reg);
- try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, Immediate.u(63));
+ try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, .u(63));
try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[1], tmp_reg);
break :result dst_mcv;
}
@@ -4321,7 +4644,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
break :cc .o;
} else cc: {
try self.genSetReg(limit_reg, ty, .{
- .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - reg_bits),
+ .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - reg_bits),
}, .{});
break :cc .c;
};
@@ -4366,7 +4689,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
};
const tuple_ty = self.typeOfIndex(inst);
- if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
+ if (int_info.bits >= 8 and std.math.isPowerOfTwo(int_info.bits)) {
switch (partial_mcv) {
.register => |reg| {
self.eflags_inst = inst;
@@ -4444,7 +4767,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
const cc = Condition.ne;
const tuple_ty = self.typeOfIndex(inst);
- if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
+ if (int_info.bits >= 8 and std.math.isPowerOfTwo(int_info.bits)) {
switch (partial_mcv) {
.register => |reg| {
self.eflags_inst = inst;
@@ -4576,7 +4899,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
if (dst_info.bits > 128 and dst_info.signedness == .unsigned) {
const slow_inc = self.hasFeature(.slow_incdec);
const abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
- const limb_len = math.divCeil(u32, abi_size, 8) catch unreachable;
+ const limb_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
try self.spillRegisters(&.{ .rax, .rcx, .rdx });
const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rax, .rcx, .rdx });
@@ -4618,7 +4941,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
try self.asmRegisterRegister(.{ ._, .xor }, .edx, .edx);
const inner_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
- try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, .u(1));
try self.asmMemoryRegister(.{ ._, .adc }, .{
.base = .{ .frame = dst_mcv.load_frame.index },
.mod = .{ .rm = .{
@@ -4642,7 +4965,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
});
try self.asmRegister(.{ ._, .mul }, temp_regs[1].to64());
- try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, .u(1));
try self.asmMemoryRegister(.{ ._, .adc }, .{
.base = .{ .frame = dst_mcv.load_frame.index },
.mod = .{ .rm = .{
@@ -4656,30 +4979,22 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
try self.asmSetccRegister(.c, .ch);
if (slow_inc) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), Immediate.u(1));
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), .u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[2].to32());
try self.asmRegister(.{ ._, .inc }, temp_regs[3].to32());
}
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- temp_regs[3].to32(),
- Immediate.u(limb_len),
- );
+ try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[3].to32(), .u(limb_len));
_ = try self.asmJccReloc(.b, inner_loop);
try self.asmRegisterRegister(.{ ._, .@"or" }, .rdx, .rcx);
const overflow = try self.asmJccReloc(.nz, undefined);
const overflow_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- temp_regs[2].to32(),
- Immediate.u(limb_len),
- );
+ try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[2].to32(), .u(limb_len));
const no_overflow = try self.asmJccReloc(.nb, undefined);
if (slow_inc) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[2].to32());
}
@@ -4691,7 +5006,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
.scale = .@"8",
.disp = lhs_mcv.load_frame.off - 8,
} },
- }, Immediate.u(0));
+ }, .u(0));
_ = try self.asmJccReloc(.z, overflow_loop);
self.performReloc(overflow);
try self.asmMemoryImmediate(.{ ._, .mov }, .{
@@ -4701,20 +5016,16 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
.disp = dst_mcv.load_frame.off +
@as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
} },
- }, Immediate.u(1));
+ }, .u(1));
self.performReloc(no_overflow);
self.performReloc(skip_inner);
if (slow_inc) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
}
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- temp_regs[0].to32(),
- Immediate.u(limb_len),
- );
+ try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[0].to32(), .u(limb_len));
_ = try self.asmJccReloc(.b, outer_loop);
break :result dst_mcv;
@@ -4750,7 +5061,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
try self.asmMemoryImmediate(
.{ ._, .cmp },
try overflow.mem(self, self.memSize(Type.c_int)),
- Immediate.s(0),
+ .s(0),
);
try self.genSetMem(
.{ .frame = dst_mcv.load_frame.index },
@@ -5038,7 +5349,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
try self.asmRegisterImmediate(
.{ ._r, .sa },
registerAlias(divisor, abi_size),
- Immediate.u(int_info.bits - 1),
+ .u(int_info.bits - 1),
);
try self.asmRegisterRegister(
.{ ._, .@"test" },
@@ -5217,8 +5528,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
defer for (reg_locks) |reg_lock| if (reg_lock) |lock|
self.register_manager.unlockReg(lock);
- const shift_imm =
- Immediate.u(@intCast(Value.fromInterned(rhs_elem).toUnsignedInt(zcu)));
+ const shift_imm: Immediate =
+ .u(@intCast(Value.fromInterned(rhs_elem).toUnsignedInt(zcu)));
if (self.hasFeature(.avx)) try self.asmRegisterRegisterImmediate(
mir_tag,
registerAlias(dst_reg, abi_size),
@@ -5434,7 +5745,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
break :result operand;
}
- const err_off = errUnionErrorOffset(payload_ty, zcu);
+ const err_off = codegen.errUnionErrorOffset(payload_ty, zcu);
switch (operand) {
.register => |reg| {
// TODO reuse operand
@@ -5492,7 +5803,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
const eu_ty = src_ty.childType(zcu);
const pl_ty = eu_ty.errorUnionPayload(zcu);
const err_ty = eu_ty.errorUnionSet(zcu);
- const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
+ const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
const err_abi_size: u32 = @intCast(err_ty.abiSize(zcu));
try self.asmRegisterMemory(
.{ ._, .mov },
@@ -5535,7 +5846,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
const eu_ty = src_ty.childType(zcu);
const pl_ty = eu_ty.errorUnionPayload(zcu);
const err_ty = eu_ty.errorUnionSet(zcu);
- const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
+ const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
const err_abi_size: u32 = @intCast(err_ty.abiSize(zcu));
try self.asmMemoryImmediate(
.{ ._, .mov },
@@ -5546,7 +5857,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
.disp = err_off,
} },
},
- Immediate.u(0),
+ .u(0),
);
if (self.liveness.isUnused(inst)) break :result .unreach;
@@ -5559,7 +5870,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
const dst_lock = self.register_manager.lockReg(dst_reg);
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
- const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
+ const pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(pl_ty, zcu));
const dst_abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
try self.asmRegisterMemory(
.{ ._, .lea },
@@ -5587,7 +5898,7 @@ fn genUnwrapErrUnionPayloadMir(
const result: MCValue = result: {
if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;
- const payload_off: u31 = @intCast(errUnionPayloadOffset(payload_ty, zcu));
+ const payload_off: u31 = @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu));
switch (err_union) {
.load_frame => |frame_addr| break :result .{ .load_frame = .{
.index = frame_addr.index,
@@ -5636,7 +5947,7 @@ fn genUnwrapErrUnionPayloadPtrMir(
const payload_ty = err_union_ty.errorUnionPayload(zcu);
const result: MCValue = result: {
- const payload_off = errUnionPayloadOffset(payload_ty, zcu);
+ const payload_off = codegen.errUnionPayloadOffset(payload_ty, zcu);
const result_mcv: MCValue = if (maybe_inst) |inst|
try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr_mcv)
else
@@ -5696,7 +6007,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
try self.asmRegisterImmediate(
.{ ._s, .bt },
opt_reg,
- Immediate.u(@as(u6, @intCast(pl_abi_size * 8))),
+ .u(@as(u6, @intCast(pl_abi_size * 8))),
);
},
@@ -5709,7 +6020,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
.disp = frame_addr.off + pl_abi_size,
} },
},
- Immediate.u(1),
+ .u(1),
),
}
}
@@ -5733,8 +6044,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 };
const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
- const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
- const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
+ const pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(pl_ty, zcu));
+ const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand, .{});
try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }, .{});
break :result .{ .load_frame = .{ .index = frame_index } };
@@ -5756,8 +6067,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try self.resolveInst(ty_op.operand);
const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
- const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
- const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
+ const pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(pl_ty, zcu));
+ const err_off: i32 = @intCast(codegen.errUnionErrorOffset(pl_ty, zcu));
try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef, .{});
const operand = try self.resolveInst(ty_op.operand);
try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand, .{});
@@ -5770,11 +6081,20 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const result = result: {
const src_mcv = try self.resolveInst(ty_op.operand);
- if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
+ const ptr_mcv: MCValue = switch (src_mcv) {
+ .register_pair => |regs| .{ .register = regs[0] },
+ else => src_mcv,
+ };
+ if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
+ switch (src_mcv) {
+ .register_pair => |regs| try self.freeValue(.{ .register = regs[1] }),
+ else => {},
+ }
+ break :result ptr_mcv;
+ }
const dst_mcv = try self.allocRegOrMem(inst, true);
- const dst_ty = self.typeOfIndex(inst);
- try self.genCopy(dst_ty, dst_mcv, src_mcv, .{});
+ try self.genCopy(self.typeOfIndex(inst), dst_mcv, ptr_mcv, .{});
break :result dst_mcv;
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
@@ -5782,23 +6102,28 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
-
- const result: MCValue = result: {
+ const result = result: {
const src_mcv = try self.resolveInst(ty_op.operand);
- switch (src_mcv) {
- .load_frame => |frame_addr| {
- const len_mcv: MCValue = .{ .load_frame = .{
- .index = frame_addr.index,
- .off = frame_addr.off + 8,
- } };
- if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
-
- const dst_mcv = try self.allocRegOrMem(inst, true);
- try self.genCopy(Type.usize, dst_mcv, len_mcv, .{});
- break :result dst_mcv;
- },
+ const len_mcv: MCValue = switch (src_mcv) {
+ .register_pair => |regs| .{ .register = regs[1] },
+ .load_frame => |frame_addr| .{ .load_frame = .{
+ .index = frame_addr.index,
+ .off = frame_addr.off + 8,
+ } },
else => return self.fail("TODO implement slice_len for {}", .{src_mcv}),
+ };
+ if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
+ switch (src_mcv) {
+ .register_pair => |regs| try self.freeValue(.{ .register = regs[0] }),
+ .load_frame => {},
+ else => unreachable,
+ }
+ break :result len_mcv;
}
+
+ const dst_mcv = try self.allocRegOrMem(inst, true);
+ try self.genCopy(self.typeOfIndex(inst), dst_mcv, len_mcv, .{});
+ break :result dst_mcv;
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
@@ -6296,27 +6621,27 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
const src_bits: u31 = @intCast(src_ty.bitSize(zcu));
const has_lzcnt = self.hasFeature(.lzcnt);
if (src_bits > @as(u32, if (has_lzcnt) 128 else 64)) {
- const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
+ const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
const extra_bits = abi_size * 8 - src_bits;
const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
defer self.register_manager.unlockReg(index_lock);
- try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), Immediate.u(limbs_len));
+ try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .u(limbs_len));
switch (extra_bits) {
1 => try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32()),
else => try self.asmRegisterImmediate(
.{ ._, .mov },
dst_reg.to32(),
- Immediate.s(@as(i32, extra_bits) - 1),
+ .s(@as(i32, extra_bits) - 1),
),
}
const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
try self.asmRegisterRegister(.{ ._, .@"test" }, index_reg.to32(), index_reg.to32());
const zero = try self.asmJccReloc(.z, undefined);
if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .sub }, index_reg.to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .sub }, index_reg.to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .dec }, index_reg.to32());
}
@@ -6328,7 +6653,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
.scale = .@"8",
.disp = src_mcv.load_frame.off,
} },
- }, Immediate.u(0));
+ }, .u(0));
_ = try self.asmJccReloc(.e, loop);
try self.asmRegisterMemory(.{ ._, .bsr }, dst_reg.to64(), .{
.base = .{ .frame = src_mcv.load_frame.index },
@@ -6340,9 +6665,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
} },
});
self.performReloc(zero);
- try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), Immediate.u(6));
+ try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), .u(6));
try self.asmRegisterRegister(.{ ._, .add }, index_reg.to32(), dst_reg.to32());
- try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), Immediate.u(src_bits - 1));
+ try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), .u(src_bits - 1));
try self.asmRegisterRegister(.{ ._, .sub }, dst_reg.to32(), index_reg.to32());
break :result dst_mcv;
}
@@ -6404,7 +6729,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
assert(src_bits <= 64);
const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(zcu))), 2);
- if (math.isPowerOfTwo(src_bits)) {
+ if (std.math.isPowerOfTwo(src_bits)) {
const imm_reg = try self.copyToTmpRegister(dst_ty, .{
.immediate = src_bits ^ (src_bits - 1),
});
@@ -6429,7 +6754,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
try self.genBinOpMir(.{ ._, .xor }, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 });
} else {
const imm_reg = try self.copyToTmpRegister(dst_ty, .{
- .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - self.regBitSize(dst_ty)),
+ .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - self.regBitSize(dst_ty)),
});
const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg);
defer self.register_manager.unlockReg(imm_lock);
@@ -6493,30 +6818,30 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
const src_bits: u31 = @intCast(src_ty.bitSize(zcu));
const has_bmi = self.hasFeature(.bmi);
if (src_bits > @as(u32, if (has_bmi) 128 else 64)) {
- const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
+ const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
const extra_bits = abi_size * 8 - src_bits;
const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
const index_lock = self.register_manager.lockRegAssumeUnused(index_reg);
defer self.register_manager.unlockReg(index_lock);
- try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), Immediate.s(-1));
+ try self.asmRegisterImmediate(.{ ._, .mov }, index_reg.to32(), .s(-1));
switch (extra_bits) {
0 => try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32()),
1 => try self.asmRegisterRegister(.{ ._, .mov }, dst_reg.to32(), dst_reg.to32()),
else => try self.asmRegisterImmediate(
.{ ._, .mov },
dst_reg.to32(),
- Immediate.s(-@as(i32, extra_bits)),
+ .s(-@as(i32, extra_bits)),
),
}
const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, index_reg.to32());
}
- try self.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), Immediate.u(limbs_len));
+ try self.asmRegisterImmediate(.{ ._, .cmp }, index_reg.to32(), .u(limbs_len));
const zero = try self.asmJccReloc(.nb, undefined);
try self.asmMemoryImmediate(.{ ._, .cmp }, .{
.base = .{ .frame = src_mcv.load_frame.index },
@@ -6526,7 +6851,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
.scale = .@"8",
.disp = src_mcv.load_frame.off,
} },
- }, Immediate.u(0));
+ }, .u(0));
_ = try self.asmJccReloc(.e, loop);
try self.asmRegisterMemory(.{ ._, .bsf }, dst_reg.to64(), .{
.base = .{ .frame = src_mcv.load_frame.index },
@@ -6538,7 +6863,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
} },
});
self.performReloc(zero);
- try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), Immediate.u(6));
+ try self.asmRegisterImmediate(.{ ._l, .sh }, index_reg.to32(), .u(6));
try self.asmRegisterRegister(.{ ._, .add }, dst_reg.to32(), index_reg.to32());
break :result dst_mcv;
}
@@ -6558,7 +6883,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
.{ ._, .@"or" },
wide_ty,
tmp_mcv,
- .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(64 - extra_bits)) <<
+ .{ .immediate = (@as(u64, std.math.maxInt(u64)) >> @intCast(64 - extra_bits)) <<
@intCast(src_bits) },
);
break :masked tmp_mcv;
@@ -6585,7 +6910,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
.{ ._, .@"or" },
Type.u64,
dst_mcv,
- .{ .immediate = @as(u64, math.maxInt(u64)) << @intCast(src_bits - 64) },
+ .{ .immediate = @as(u64, std.math.maxInt(u64)) << @intCast(src_bits - 64) },
);
break :masked dst_mcv;
} else hi_mat_src_mcv;
@@ -6602,7 +6927,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
const width_lock = self.register_manager.lockRegAssumeUnused(width_reg);
defer self.register_manager.unlockReg(width_lock);
- if (src_bits <= 8 or !math.isPowerOfTwo(src_bits)) {
+ if (src_bits <= 8 or !std.math.isPowerOfTwo(src_bits)) {
const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg);
defer self.register_manager.unlockReg(wide_lock);
@@ -6701,11 +7026,11 @@ fn genPopCount(
},
);
- const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8);
- const imm_0_1 = Immediate.u(mask / 0b1_1);
- const imm_00_11 = Immediate.u(mask / 0b01_01);
- const imm_0000_1111 = Immediate.u(mask / 0b0001_0001);
- const imm_0000_0001 = Immediate.u(mask / 0b1111_1111);
+ const mask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8);
+ const imm_0_1: Immediate = .u(mask / 0b1_1);
+ const imm_00_11: Immediate = .u(mask / 0b01_01);
+ const imm_0000_1111: Immediate = .u(mask / 0b0001_0001);
+ const imm_0000_0001: Immediate = .u(mask / 0b1111_1111);
const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
@@ -6722,7 +7047,7 @@ fn genPopCount(
// dst = operand
try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
// tmp = operand
- try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, .u(1));
// tmp = operand >> 1
if (src_abi_size > 4) {
try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0_1);
@@ -6733,7 +7058,7 @@ fn genPopCount(
// dst = temp1 = operand - ((operand >> 1) & 0x55...55)
try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
// tmp = temp1
- try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(2));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u(2));
// dst = temp1 >> 2
if (src_abi_size > 4) {
try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_00_11);
@@ -6749,7 +7074,7 @@ fn genPopCount(
// tmp = temp2 = (temp1 & 0x33...33) + ((temp1 >> 2) & 0x33...33)
try self.asmRegisterRegister(.{ ._, .mov }, dst, tmp);
// dst = temp2
- try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(4));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, .u(4));
// tmp = temp2 >> 4
try self.asmRegisterRegister(.{ ._, .add }, dst, tmp);
// dst = temp2 + (temp2 >> 4)
@@ -6767,7 +7092,7 @@ fn genPopCount(
// dst = temp3 = (temp2 + (temp2 >> 4)) & 0x0f...0f
// dst = temp3 * 0x01...01
if (src_abi_size > 1) {
- try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u((src_abi_size - 1) * 8));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u((src_abi_size - 1) * 8));
}
// dst = (temp3 * 0x01...01) >> (bits - 8)
}
@@ -6847,7 +7172,7 @@ fn genByteSwap(
return .{ .register_pair = .{ dst_regs[1], dst_regs[0] } };
},
else => {
- const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
+ const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
const temp_regs =
try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp);
@@ -6856,11 +7181,7 @@ fn genByteSwap(
const dst_mcv = try self.allocRegOrMem(inst, false);
try self.asmRegisterRegister(.{ ._, .xor }, temp_regs[0].to32(), temp_regs[0].to32());
- try self.asmRegisterImmediate(
- .{ ._, .mov },
- temp_regs[1].to32(),
- Immediate.u(limbs_len - 1),
- );
+ try self.asmRegisterImmediate(.{ ._, .mov }, temp_regs[1].to32(), .u(limbs_len - 1));
const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
try self.asmRegisterMemory(
@@ -6912,8 +7233,8 @@ fn genByteSwap(
} },
}, temp_regs[2].to64());
if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
- try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
+ try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
@@ -6994,10 +7315,10 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
else
undefined;
- const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - limb_abi_size * 8);
- const imm_0000_1111 = Immediate.u(mask / 0b0001_0001);
- const imm_00_11 = Immediate.u(mask / 0b01_01);
- const imm_0_1 = Immediate.u(mask / 0b1_1);
+ const mask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - limb_abi_size * 8);
+ const imm_0000_1111: Immediate = .u(mask / 0b0001_0001);
+ const imm_00_11: Immediate = .u(mask / 0b01_01);
+ const imm_0_1: Immediate = .u(mask / 0b1_1);
for (dst_mcv.getRegs()) |dst_reg| {
const dst = registerAlias(dst_reg, limb_abi_size);
@@ -7005,7 +7326,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
// dst = temp1 = bswap(operand)
try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
// tmp = temp1
- try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(4));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u(4));
// dst = temp1 >> 4
if (limb_abi_size > 4) {
try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0000_1111);
@@ -7017,13 +7338,13 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
}
// tmp = temp1 & 0x0F...0F
// dst = (temp1 >> 4) & 0x0F...0F
- try self.asmRegisterImmediate(.{ ._l, .sh }, tmp, Immediate.u(4));
+ try self.asmRegisterImmediate(.{ ._l, .sh }, tmp, .u(4));
// tmp = (temp1 & 0x0F...0F) << 4
try self.asmRegisterRegister(.{ ._, .@"or" }, dst, tmp);
// dst = temp2 = ((temp1 >> 4) & 0x0F...0F) | ((temp1 & 0x0F...0F) << 4)
try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
// tmp = temp2
- try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(2));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, dst, .u(2));
// dst = temp2 >> 2
if (limb_abi_size > 4) {
try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_00_11);
@@ -7050,7 +7371,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
// tmp = temp3 = ((temp2 >> 2) & 0x33...33) + ((temp2 & 0x33...33) << 2)
try self.asmRegisterRegister(.{ ._, .mov }, dst, tmp);
// dst = temp3
- try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, .u(1));
// tmp = temp3 >> 1
if (limb_abi_size > 4) {
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
dst_alias,
dst_alias,
try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
- Immediate.u(@as(u5, @bitCast(mode))),
+ .u(@as(u5, @bitCast(mode))),
) else try self.asmRegisterRegisterRegisterImmediate(
mir_tag,
dst_alias,
@@ -7346,13 +7667,13 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
src_mcv.getReg().?
else
try self.copyToTmpRegister(ty, src_mcv), abi_size),
- Immediate.u(@as(u5, @bitCast(mode))),
+ .u(@as(u5, @bitCast(mode))),
),
else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
mir_tag,
dst_alias,
try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
- Immediate.u(@as(u5, @bitCast(mode))),
+ .u(@as(u5, @bitCast(mode))),
) else try self.asmRegisterRegisterImmediate(
mir_tag,
dst_alias,
@@ -7360,7 +7681,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
src_mcv.getReg().?
else
try self.copyToTmpRegister(ty, src_mcv), abi_size),
- Immediate.u(@as(u5, @bitCast(mode))),
+ .u(@as(u5, @bitCast(mode))),
),
}
}
@@ -7433,7 +7754,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
defer self.register_manager.unlockReg(tmp_lock);
try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]);
- try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
+ try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, .u(63));
try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[0], tmp_reg);
try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[1], tmp_reg);
try self.asmRegisterRegister(.{ ._, .sub }, dst_regs[0], tmp_reg);
@@ -7443,7 +7764,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
},
else => {
const abi_size: u31 = @intCast(ty.abiSize(zcu));
- const limb_len = math.divCeil(u31, abi_size, 8) catch unreachable;
+ const limb_len = std.math.divCeil(u31, abi_size, 8) catch unreachable;
const tmp_regs =
try self.register_manager.allocRegs(3, .{null} ** 3, abi.RegisterClass.gp);
@@ -7460,7 +7781,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
try self.asmMemoryImmediate(
.{ ._, .cmp },
try dst_mcv.address().offset((limb_len - 1) * 8).deref().mem(self, .qword),
- Immediate.u(0),
+ .u(0),
);
const positive = try self.asmJccReloc(.ns, undefined);
@@ -7469,7 +7790,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
const neg_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
try self.asmRegisterRegister(.{ ._, .xor }, tmp_regs[2].to32(), tmp_regs[2].to32());
- try self.asmRegisterImmediate(.{ ._r, .sh }, tmp_regs[1].to8(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, tmp_regs[1].to8(), .u(1));
try self.asmRegisterMemory(.{ ._, .sbb }, tmp_regs[2].to64(), .{
.base = .{ .frame = dst_mcv.load_frame.index },
.mod = .{ .rm = .{
@@ -7491,11 +7812,11 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
}, tmp_regs[2].to64());
if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, tmp_regs[0].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, tmp_regs[0].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, tmp_regs[0].to32());
}
- try self.asmRegisterImmediate(.{ ._, .cmp }, tmp_regs[0].to32(), Immediate.u(limb_len));
+ try self.asmRegisterImmediate(.{ ._, .cmp }, tmp_regs[0].to32(), .u(limb_len));
_ = try self.asmJccReloc(.b, neg_loop);
self.performReloc(positive);
@@ -7620,7 +7941,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
break :result dst_mcv;
},
@@ -7650,7 +7971,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
break :result dst_mcv;
},
@@ -7675,7 +7996,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
.{ .v_, .cvtps2ph },
dst_reg,
wide_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
break :result dst_mcv;
},
@@ -7699,9 +8020,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
else => unreachable,
},
else => unreachable,
- }) orelse return self.fail("TODO implement airSqrt for {}", .{
- ty.fmt(pt),
- });
+ }) orelse return self.fail("TODO implement airSqrt for {}", .{ty.fmt(pt)});
switch (mir_tag[0]) {
.v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
mir_tag,
@@ -7805,7 +8124,7 @@ fn reuseOperandAdvanced(
}
// Prevent the operand deaths processing code from deallocating it.
- self.liveness.clearOperandDeath(inst, op_index);
+ self.reused_operands.set(op_index);
const op_inst = operand.toIndex().?;
self.getResolvedInstValue(op_inst).reuse(self, maybe_tracked_inst, op_inst);
@@ -7890,7 +8209,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
} },
});
try self.spillEflagsIfOccupied();
- try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, .u(val_bit_off));
} else {
const tmp_reg =
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
} },
});
try self.spillEflagsIfOccupied();
- try self.asmRegisterRegisterImmediate(
- .{ ._rd, .sh },
- dst_alias,
- tmp_reg,
- Immediate.u(val_bit_off),
- );
+ try self.asmRegisterRegisterImmediate(.{ ._rd, .sh }, dst_alias, tmp_reg, .u(val_bit_off));
}
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
} },
};
- const part_mask = (@as(u64, math.maxInt(u64)) >> @intCast(64 - part_bit_size)) <<
+ const part_mask = (@as(u64, std.math.maxInt(u64)) >> @intCast(64 - part_bit_size)) <<
@intCast(part_bit_off);
- const part_mask_not = part_mask ^ (@as(u64, math.maxInt(u64)) >> @intCast(64 - limb_abi_bits));
+ const part_mask_not = part_mask ^ (@as(u64, std.math.maxInt(u64)) >> @intCast(64 - limb_abi_bits));
if (limb_abi_size <= 4) {
- try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.u(part_mask_not));
- } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| {
- try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small));
+ try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, .u(part_mask_not));
+ } else if (std.math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| {
+ try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, .s(small));
} else {
const part_mask_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
- try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not));
+ try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, .u(part_mask_not));
try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg);
}
@@ -8209,25 +8523,14 @@ fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
}
-fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
+fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, field_index: u8) !void {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
- const result = try self.fieldPtr(inst, ty_op.operand, index);
+ const result = try self.fieldPtr(inst, ty_op.operand, field_index);
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
-fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
- const pt = self.pt;
- const zcu = pt.zcu;
+fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, field_index: u32) !MCValue {
const ptr_field_ty = self.typeOfIndex(inst);
- const ptr_container_ty = self.typeOf(operand);
- const container_ty = ptr_container_ty.childType(zcu);
-
- const field_off: i32 = switch (container_ty.containerLayout(zcu)) {
- .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, zcu)),
- .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(zcu).packed_offset.bit_offset) +
- (if (zcu.typeToStruct(container_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, index) else 0) -
- ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
- };
const src_mcv = try self.resolveInst(operand);
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
.register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),
else => false,
}) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv);
- return dst_mcv.offset(field_off);
+ return dst_mcv.offset(self.fieldOffset(self.typeOf(operand), ptr_field_ty, field_index));
+}
+
+fn fieldOffset(self: *Self, ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32) i32 {
+ const pt = self.pt;
+ const zcu = pt.zcu;
+ const agg_ty = ptr_agg_ty.childType(zcu);
+ return switch (agg_ty.containerLayout(zcu)) {
+ .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(field_index, zcu)),
+ .@"packed" => @divExact(@as(i32, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) +
+ (if (zcu.typeToStruct(agg_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, field_index) else 0) -
+ ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
+ };
}
fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
@@ -8476,7 +8791,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
} },
});
try self.spillEflagsIfOccupied();
- try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, .u(field_bit_off));
} else {
const tmp_reg = registerAlias(
try self.register_manager.allocReg(null, abi.RegisterClass.gp),
@@ -8509,7 +8824,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
.{ ._rd, .sh },
dst_alias,
tmp_reg,
- Immediate.u(field_bit_off),
+ .u(field_bit_off),
);
}
@@ -8528,27 +8843,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
}
fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
- const pt = self.pt;
- const zcu = pt.zcu;
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
- const inst_ty = self.typeOfIndex(inst);
- const parent_ty = inst_ty.childType(zcu);
- const field_off: i32 = switch (parent_ty.containerLayout(zcu)) {
- .auto, .@"extern" => @intCast(parent_ty.structFieldOffset(extra.field_index, zcu)),
- .@"packed" => @divExact(@as(i32, inst_ty.ptrInfo(zcu).packed_offset.bit_offset) +
- (if (zcu.typeToStruct(parent_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0) -
- self.typeOf(extra.field_ptr).ptrInfo(zcu).packed_offset.bit_offset, 8),
- };
-
+ const ptr_agg_ty = self.typeOfIndex(inst);
const src_mcv = try self.resolveInst(extra.field_ptr);
const dst_mcv = if (src_mcv.isRegisterOffset() and
self.reuseOperand(inst, extra.field_ptr, 0, src_mcv))
src_mcv
else
- try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv);
- const result = dst_mcv.offset(-field_off);
+ try self.copyToRegisterWithInstTracking(inst, ptr_agg_ty, src_mcv);
+ const result = dst_mcv.offset(-self.fieldOffset(ptr_agg_ty, self.typeOf(extra.field_ptr), extra.field_index));
return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none });
}
@@ -8613,7 +8918,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
};
if (int_info.signedness == .unsigned and self.regExtraBits(limb_ty) > 0) {
- const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - limb_bits);
+ const mask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - limb_bits);
try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask });
} else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
}
@@ -8698,7 +9003,7 @@ fn genShiftBinOpMir(
try self.spillEflagsIfOccupied();
if (abi_size > 16) {
- const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
+ const limbs_len = std.math.divCeil(u32, abi_size, 8) catch unreachable;
assert(shift_abi_size >= 1 and shift_abi_size <= 2);
const rcx_lock: ?RegisterLock = switch (rhs_mcv) {
@@ -8725,12 +9030,12 @@ fn genShiftBinOpMir(
switch (tag[0]) {
._l => {
- try self.asmRegisterImmediate(.{ ._, .mov }, temp_regs[1].to32(), Immediate.u(limbs_len - 1));
+ try self.asmRegisterImmediate(.{ ._, .mov }, temp_regs[1].to32(), .u(limbs_len - 1));
switch (rhs_mcv) {
.immediate => |shift_imm| try self.asmRegisterImmediate(
.{ ._, .mov },
temp_regs[0].to32(),
- Immediate.u(limbs_len - (shift_imm >> 6) - 1),
+ .u(limbs_len - (shift_imm >> 6) - 1),
),
else => {
try self.asmRegisterRegister(
@@ -8738,16 +9043,8 @@ fn genShiftBinOpMir(
temp_regs[2].to32(),
registerAlias(.rcx, shift_abi_size),
);
- try self.asmRegisterImmediate(
- .{ ._, .@"and" },
- .cl,
- Immediate.u(math.maxInt(u6)),
- );
- try self.asmRegisterImmediate(
- .{ ._r, .sh },
- temp_regs[2].to32(),
- Immediate.u(6),
- );
+ try self.asmRegisterImmediate(.{ ._, .@"and" }, .cl, .u(std.math.maxInt(u6)));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, temp_regs[2].to32(), .u(6));
try self.asmRegisterRegister(
.{ ._, .mov },
temp_regs[0].to32(),
@@ -8767,7 +9064,7 @@ fn genShiftBinOpMir(
.immediate => |shift_imm| try self.asmRegisterImmediate(
.{ ._, .mov },
temp_regs[0].to32(),
- Immediate.u(shift_imm >> 6),
+ .u(shift_imm >> 6),
),
else => {
try self.asmRegisterRegister(
@@ -8775,16 +9072,8 @@ fn genShiftBinOpMir(
temp_regs[0].to32(),
registerAlias(.rcx, shift_abi_size),
);
- try self.asmRegisterImmediate(
- .{ ._, .@"and" },
- .cl,
- Immediate.u(math.maxInt(u6)),
- );
- try self.asmRegisterImmediate(
- .{ ._r, .sh },
- temp_regs[0].to32(),
- Immediate.u(6),
- );
+ try self.asmRegisterImmediate(.{ ._, .@"and" }, .cl, .u(std.math.maxInt(u6)));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, temp_regs[0].to32(), .u(6));
},
}
},
@@ -8813,7 +9102,7 @@ fn genShiftBinOpMir(
try self.asmRegisterImmediate(
.{ ._, .cmp },
temp_regs[0].to32(),
- Immediate.u(limbs_len - 1),
+ .u(limbs_len - 1),
);
break :skip try self.asmJccReloc(.nb, undefined);
},
@@ -8843,7 +9132,7 @@ fn genShiftBinOpMir(
}, .sh },
temp_regs[2].to64(),
temp_regs[3].to64(),
- Immediate.u(shift_imm & math.maxInt(u6)),
+ .u(shift_imm & std.math.maxInt(u6)),
),
else => try self.asmRegisterRegisterRegister(.{ switch (tag[0]) {
._l => ._ld,
@@ -8864,8 +9153,8 @@ fn genShiftBinOpMir(
switch (tag[0]) {
._l => {
if (slow_inc_dec) {
- try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
- try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[0].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), .u(1));
+ try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[0].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
try self.asmRegister(.{ ._, .dec }, temp_regs[0].to32());
@@ -8874,8 +9163,8 @@ fn genShiftBinOpMir(
},
._r => {
if (slow_inc_dec) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), Immediate.u(1));
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), .u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[1].to32());
try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
@@ -8883,7 +9172,7 @@ fn genShiftBinOpMir(
try self.asmRegisterImmediate(
.{ ._, .cmp },
temp_regs[0].to32(),
- Immediate.u(limbs_len - 1),
+ .u(limbs_len - 1),
);
_ = try self.asmJccReloc(.b, loop);
},
@@ -8898,7 +9187,7 @@ fn genShiftBinOpMir(
.immediate => |shift_imm| try self.asmRegisterImmediate(
tag,
temp_regs[2].to64(),
- Immediate.u(shift_imm & math.maxInt(u6)),
+ .u(shift_imm & std.math.maxInt(u6)),
),
else => try self.asmRegisterRegister(tag, temp_regs[2].to64(), .cl),
}
@@ -8914,7 +9203,7 @@ fn genShiftBinOpMir(
if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate(
tag,
temp_regs[2].to64(),
- Immediate.u(63),
+ .u(63),
);
if (switch (rhs_mcv) {
.immediate => |shift_imm| shift_imm >> 6 > 0,
@@ -8935,7 +9224,7 @@ fn genShiftBinOpMir(
try self.asmRegisterImmediate(
.{ ._, .cmp },
temp_regs[1].to32(),
- Immediate.u(limbs_len - 1),
+ .u(limbs_len - 1),
);
break :skip try self.asmJccReloc(.nb, undefined);
},
@@ -8945,12 +9234,12 @@ fn genShiftBinOpMir(
const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
switch (tag[0]) {
._l => if (slow_inc_dec) {
- try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
},
._r => if (slow_inc_dec) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[1].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[1].to32());
},
@@ -8972,14 +9261,14 @@ fn genShiftBinOpMir(
.scale = .@"8",
.disp = lhs_mcv.load_frame.off,
} },
- }, Immediate.u(0));
+ }, .u(0));
switch (tag[0]) {
._l => _ = try self.asmJccReloc(.nz, loop),
._r => {
try self.asmRegisterImmediate(
.{ ._, .cmp },
temp_regs[1].to32(),
- Immediate.u(limbs_len - 1),
+ .u(limbs_len - 1),
);
_ = try self.asmJccReloc(.b, loop);
},
@@ -9021,12 +9310,12 @@ fn genShiftBinOpMir(
info.double_tag,
lhs_regs[info.indices[1]],
lhs_regs[info.indices[0]],
- Immediate.u(shift_imm),
+ .u(shift_imm),
);
try self.asmRegisterImmediate(
tag,
lhs_regs[info.indices[0]],
- Immediate.u(shift_imm),
+ .u(shift_imm),
);
return;
} else {
@@ -9039,7 +9328,7 @@ fn genShiftBinOpMir(
if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate(
tag,
lhs_regs[info.indices[0]],
- Immediate.u(63),
+ .u(63),
) else try self.asmRegisterRegister(
.{ ._, .xor },
lhs_regs[info.indices[0]],
@@ -9048,7 +9337,7 @@ fn genShiftBinOpMir(
if (shift_imm > 64) try self.asmRegisterImmediate(
tag,
lhs_regs[info.indices[1]],
- Immediate.u(shift_imm - 64),
+ .u(shift_imm - 64),
);
return;
},
@@ -9059,7 +9348,7 @@ fn genShiftBinOpMir(
if (tag[0] == ._r and tag[1] == .sa) {
try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_regs[info.indices[0]]);
- try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
+ try self.asmRegisterImmediate(tag, tmp_reg, .u(63));
} else try self.asmRegisterRegister(
.{ ._, .xor },
tmp_reg.to32(),
@@ -9076,11 +9365,7 @@ fn genShiftBinOpMir(
lhs_regs[info.indices[0]],
registerAlias(shift_reg, 1),
);
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- registerAlias(shift_reg, 1),
- Immediate.u(64),
- );
+ try self.asmRegisterImmediate(.{ ._, .cmp }, registerAlias(shift_reg, 1), .u(64));
try self.asmCmovccRegisterRegister(
.ae,
lhs_regs[info.indices[1]],
@@ -9119,7 +9404,7 @@ fn genShiftBinOpMir(
} },
},
tmp_reg,
- Immediate.u(shift_imm),
+ .u(shift_imm),
);
try self.asmMemoryImmediate(
tag,
@@ -9130,7 +9415,7 @@ fn genShiftBinOpMir(
.disp = dst_frame_addr.off + info.indices[0] * 8,
} },
},
- Immediate.u(shift_imm),
+ .u(shift_imm),
);
return;
} else {
@@ -9149,7 +9434,7 @@ fn genShiftBinOpMir(
if (shift_imm > 64) try self.asmRegisterImmediate(
tag,
tmp_reg,
- Immediate.u(shift_imm - 64),
+ .u(shift_imm - 64),
);
try self.asmMemoryRegister(
.{ ._, .mov },
@@ -9171,7 +9456,7 @@ fn genShiftBinOpMir(
.disp = dst_frame_addr.off + info.indices[0] * 8,
} },
},
- Immediate.u(63),
+ .u(63),
) else {
try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());
try self.asmMemoryRegister(
@@ -9223,7 +9508,7 @@ fn genShiftBinOpMir(
);
if (tag[0] == ._r and tag[1] == .sa) {
try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);
- try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
+ try self.asmRegisterImmediate(tag, tmp_reg, .u(63));
} else try self.asmRegisterRegister(
.{ ._, .xor },
tmp_reg.to32(),
@@ -9239,7 +9524,7 @@ fn genShiftBinOpMir(
try self.asmRegisterImmediate(
.{ ._, .cmp },
registerAlias(shift_reg, 1),
- Immediate.u(64),
+ .u(64),
);
try self.asmCmovccRegisterRegister(.ae, second_reg, first_reg);
try self.asmCmovccRegisterRegister(.ae, first_reg, tmp_reg);
@@ -9277,7 +9562,7 @@ fn genShiftBinOpMir(
.immediate => |shift_imm| return self.asmRegisterImmediate(
tag,
registerAlias(lhs_reg, abi_size),
- Immediate.u(shift_imm),
+ .u(shift_imm),
),
.register => |shift_reg| return self.asmRegisterRegister(
tag,
@@ -9292,7 +9577,7 @@ fn genShiftBinOpMir(
.base = .{ .reg = .ds },
.mod = .{ .rm = .{
.size = Memory.Size.fromSize(abi_size),
- .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse
+ .disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse
return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
@tagName(lhs_mcv),
@tagName(shift_mcv),
@@ -9316,11 +9601,7 @@ fn genShiftBinOpMir(
else => unreachable,
};
switch (shift_mcv) {
- .immediate => |shift_imm| return self.asmMemoryImmediate(
- tag,
- lhs_mem,
- Immediate.u(shift_imm),
- ),
+ .immediate => |shift_imm| return self.asmMemoryImmediate(tag, lhs_mem, .u(shift_imm)),
.register => |shift_reg| return self.asmMemoryRegister(
tag,
lhs_mem,
@@ -9495,7 +9776,7 @@ fn genMulDivBinOp(
switch (tag) {
.mul, .mul_wrap => {
const slow_inc = self.hasFeature(.slow_incdec);
- const limb_len = math.divCeil(u32, src_abi_size, 8) catch unreachable;
+ const limb_len = std.math.divCeil(u32, src_abi_size, 8) catch unreachable;
try self.spillRegisters(&.{ .rax, .rcx, .rdx });
const reg_locks = self.register_manager.lockRegs(3, .{ .rax, .rcx, .rdx });
@@ -9536,7 +9817,7 @@ fn genMulDivBinOp(
try self.asmRegisterRegister(.{ ._, .xor }, .edx, .edx);
const inner_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
- try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, .cl, .u(1));
try self.asmMemoryRegister(.{ ._, .adc }, .{
.base = .{ .frame = dst_mcv.load_frame.index },
.mod = .{ .rm = .{
@@ -9559,7 +9840,7 @@ fn genMulDivBinOp(
});
try self.asmRegister(.{ ._, .mul }, temp_regs[1].to64());
- try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._r, .sh }, .ch, .u(1));
try self.asmMemoryRegister(.{ ._, .adc }, .{
.base = .{ .frame = dst_mcv.load_frame.index },
.mod = .{ .rm = .{
@@ -9572,30 +9853,22 @@ fn genMulDivBinOp(
try self.asmSetccRegister(.c, .ch);
if (slow_inc) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), Immediate.u(1));
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[2].to32(), .u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[3].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[2].to32());
try self.asmRegister(.{ ._, .inc }, temp_regs[3].to32());
}
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- temp_regs[3].to32(),
- Immediate.u(limb_len),
- );
+ try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[3].to32(), .u(limb_len));
_ = try self.asmJccReloc(.b, inner_loop);
self.performReloc(skip_inner);
if (slow_inc) {
- try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
}
- try self.asmRegisterImmediate(
- .{ ._, .cmp },
- temp_regs[0].to32(),
- Immediate.u(limb_len),
- );
+ try self.asmRegisterImmediate(.{ ._, .cmp }, temp_regs[0].to32(), .u(limb_len));
_ = try self.asmJccReloc(.b, outer_loop);
return dst_mcv;
@@ -9911,7 +10184,7 @@ fn genBinOp(
dst_reg,
dst_reg,
try rhs_mcv.mem(self, .word),
- Immediate.u(1),
+ .u(1),
) else try self.asmRegisterRegisterRegister(
.{ .vp_, .unpcklwd },
dst_reg,
@@ -9969,7 +10242,7 @@ fn genBinOp(
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
break :adjusted .{ .register = dst_reg };
},
@@ -10278,7 +10551,7 @@ fn genBinOp(
.lea_tlv,
.lea_frame,
=> true,
- .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null,
+ .memory => |addr| std.math.cast(i32, @as(i64, @bitCast(addr))) == null,
else => false,
.register_pair,
.register_overflow,
@@ -10410,7 +10683,7 @@ fn genBinOp(
dst_reg,
dst_reg,
try src_mcv.mem(self, .word),
- Immediate.u(1),
+ .u(1),
) else try self.asmRegisterRegisterRegister(
.{ .vp_, .unpcklwd },
dst_reg,
@@ -10442,7 +10715,7 @@ fn genBinOp(
dst_reg,
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{
+ .u(@as(u5, @bitCast(RoundMode{
.mode = switch (air_tag) {
.div_trunc => .zero,
.div_floor => .down,
@@ -10457,7 +10730,7 @@ fn genBinOp(
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
return dst_mcv;
},
@@ -10856,7 +11129,7 @@ fn genBinOp(
dst_reg,
dst_reg,
try src_mcv.mem(self, .word),
- Immediate.u(1),
+ .u(1),
) else try self.asmRegisterRegisterRegister(
.{ .vp_, .unpcklwd },
dst_reg,
@@ -10886,7 +11159,7 @@ fn genBinOp(
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
return dst_mcv;
},
@@ -10902,7 +11175,7 @@ fn genBinOp(
.{ .vp_d, .insr },
dst_reg,
try src_mcv.mem(self, .dword),
- Immediate.u(1),
+ .u(1),
) else try self.asmRegisterRegisterRegister(
.{ .v_ps, .unpckl },
dst_reg,
@@ -10937,7 +11210,7 @@ fn genBinOp(
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
return dst_mcv;
},
@@ -10980,7 +11253,7 @@ fn genBinOp(
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg,
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
return dst_mcv;
},
@@ -11023,7 +11296,7 @@ fn genBinOp(
.{ .v_, .cvtps2ph },
dst_reg,
dst_reg.to256(),
- Immediate.u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
+ .u(@as(u5, @bitCast(RoundMode{ .mode = .mxcsr }))),
);
return dst_mcv;
},
@@ -11191,7 +11464,7 @@ fn genBinOp(
);
},
.cmp => {
- const imm = Immediate.u(switch (air_tag) {
+ const imm: Immediate = .u(switch (air_tag) {
.cmp_eq => 0,
.cmp_lt, .cmp_gt => 1,
.cmp_lte, .cmp_gte => 2,
@@ -11289,7 +11562,7 @@ fn genBinOp(
mask_reg,
rhs_copy_reg,
rhs_copy_reg,
- Immediate.u(3), // unord
+ .u(3), // unord
);
try self.asmRegisterRegisterRegisterRegister(
@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(zcu)) {
@@ -11356,7 +11629,7 @@ fn genBinOp(
}),
mask_reg,
mask_reg,
- Immediate.u(if (has_blend) 3 else 7), // unord, ord
+ .u(if (has_blend) 3 else 7), // unord, ord
);
if (has_blend) try self.asmRegisterRegisterRegister(
@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(zcu)) {
@@ -11567,29 +11840,29 @@ fn genBinOpMir(
8 => try self.asmRegisterImmediate(
mir_limb_tag,
dst_alias,
- if (math.cast(i8, @as(i64, @bitCast(imm)))) |small|
- Immediate.s(small)
+ if (std.math.cast(i8, @as(i64, @bitCast(imm)))) |small|
+ .s(small)
else
- Immediate.u(@as(u8, @intCast(imm))),
+ .u(@as(u8, @intCast(imm))),
),
16 => try self.asmRegisterImmediate(
mir_limb_tag,
dst_alias,
- if (math.cast(i16, @as(i64, @bitCast(imm)))) |small|
- Immediate.s(small)
+ if (std.math.cast(i16, @as(i64, @bitCast(imm)))) |small|
+ .s(small)
else
- Immediate.u(@as(u16, @intCast(imm))),
+ .u(@as(u16, @intCast(imm))),
),
32 => try self.asmRegisterImmediate(
mir_limb_tag,
dst_alias,
- if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
- Immediate.s(small)
+ if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
+ .s(small)
else
- Immediate.u(@as(u32, @intCast(imm))),
+ .u(@as(u32, @intCast(imm))),
),
- 64 => if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
- try self.asmRegisterImmediate(mir_limb_tag, dst_alias, Immediate.s(small))
+ 64 => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
+ try self.asmRegisterImmediate(mir_limb_tag, dst_alias, .s(small))
else
try self.asmRegisterRegister(mir_limb_tag, dst_alias, registerAlias(
try self.copyToTmpRegister(ty, src_mcv),
@@ -11619,7 +11892,7 @@ fn genBinOpMir(
.base = .{ .reg = .ds },
.mod = .{ .rm = .{
.size = Memory.Size.fromSize(limb_abi_size),
- .disp = math.cast(i32, addr + off) orelse break :direct,
+ .disp = std.math.cast(i32, addr + off) orelse break :direct,
} },
},
.indirect => |reg_off| .{
@@ -11731,8 +12004,8 @@ fn genBinOpMir(
=> null,
.memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
switch (resolved_src_mcv) {
- .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and
- math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
+ .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and
+ std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
break :src null,
.load_symbol, .load_got, .load_direct, .load_tlv => {},
else => unreachable,
@@ -11823,33 +12096,29 @@ fn genBinOpMir(
8 => try self.asmMemoryImmediate(
mir_limb_tag,
dst_limb_mem,
- if (math.cast(i8, @as(i64, @bitCast(imm)))) |small|
- Immediate.s(small)
+ if (std.math.cast(i8, @as(i64, @bitCast(imm)))) |small|
+ .s(small)
else
- Immediate.u(@as(u8, @intCast(imm))),
+ .u(@as(u8, @intCast(imm))),
),
16 => try self.asmMemoryImmediate(
mir_limb_tag,
dst_limb_mem,
- if (math.cast(i16, @as(i64, @bitCast(imm)))) |small|
- Immediate.s(small)
+ if (std.math.cast(i16, @as(i64, @bitCast(imm)))) |small|
+ .s(small)
else
- Immediate.u(@as(u16, @intCast(imm))),
+ .u(@as(u16, @intCast(imm))),
),
32 => try self.asmMemoryImmediate(
mir_limb_tag,
dst_limb_mem,
- if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
- Immediate.s(small)
+ if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
+ .s(small)
else
- Immediate.u(@as(u32, @intCast(imm))),
+ .u(@as(u32, @intCast(imm))),
),
- 64 => if (math.cast(i32, @as(i64, @bitCast(imm)))) |small|
- try self.asmMemoryImmediate(
- mir_limb_tag,
- dst_limb_mem,
- Immediate.s(small),
- )
+ 64 => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small|
+ try self.asmMemoryImmediate(mir_limb_tag, dst_limb_mem, .s(small))
else
try self.asmMemoryRegister(
mir_limb_tag,
@@ -11973,12 +12242,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
registerAlias(src_reg, abi_size),
),
.immediate => |imm| {
- if (math.cast(i32, imm)) |small| {
+ if (std.math.cast(i32, imm)) |small| {
try self.asmRegisterRegisterImmediate(
.{ .i_, .mul },
dst_alias,
dst_alias,
- Immediate.s(small),
+ .s(small),
);
} else {
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
.base = .{ .reg = .ds },
.mod = .{ .rm = .{
.size = Memory.Size.fromSize(abi_size),
- .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse
+ .disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse
return self.asmRegisterRegister(
.{ .i_, .mul },
dst_alias,
@@ -12087,11 +12356,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
) |dst_reg, elem_index| {
assert(self.register_manager.isRegFree(dst_reg));
if (elem_index > 0) {
- try self.asmRegisterImmediate(
- .{ ._l, .sh },
- dst_reg.to8(),
- Immediate.u(elem_index),
- );
+ try self.asmRegisterImmediate(.{ ._l, .sh }, dst_reg.to8(), .u(elem_index));
try self.asmRegisterRegister(
.{ ._, .@"or" },
dst_reg.to8(),
@@ -12127,7 +12392,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
try self.asmRegisterImmediate(
.{ ._, .mov },
index_reg.to32(),
- Immediate.u(regs_frame_addr.regs),
+ .u(regs_frame_addr.regs),
);
const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
try self.asmMemoryImmediate(.{ ._, .cmp }, .{
@@ -12147,14 +12412,14 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
);
self.performReloc(unset);
if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, index_reg.to32());
}
try self.asmRegisterImmediate(
.{ ._, .cmp },
index_reg.to32(),
- Immediate.u(arg_ty.vectorLen(zcu)),
+ .u(arg_ty.vectorLen(zcu)),
);
_ = try self.asmJccReloc(.b, loop);
@@ -12180,7 +12445,6 @@ fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void {
for (self.args[self.arg_index..]) |arg| {
if (arg != .none) break;
} else try self.airDbgVarArgs();
- self.finishAirBookkeeping();
}
fn airDbgVarArgs(self: *Self) !void {
@@ -12200,9 +12464,9 @@ fn genLocalDebugInfo(
switch (mcv) {
.none => try self.asmAir(.dbg_local, inst),
.unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
- .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),
+ .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, .u(imm)),
.lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
- .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, Immediate.rel(sym_off)),
+ .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, .rel(sym_off)),
else => {
const ty = switch (tag) {
else => unreachable,
@@ -12245,16 +12509,6 @@ fn genLocalDebugInfo(
}
}
-fn airTrap(self: *Self) !void {
- try self.asmOpOnly(.{ ._, .ud2 });
- self.finishAirBookkeeping();
-}
-
-fn airBreakpoint(self: *Self) !void {
- try self.asmOpOnly(.{ ._, .int3 });
- self.finishAirBookkeeping();
-}
-
fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {
const dst_mcv = try self.allocRegOrMem(inst, true);
try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }, .{});
@@ -12426,7 +12680,7 @@ fn genCall(self: *Self, info: union(enum) {
try self.asmRegisterImmediate(
.{ ._, .mov },
index_reg.to32(),
- Immediate.u(regs_frame_addr.regs),
+ .u(regs_frame_addr.regs),
);
const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
try self.asmMemoryRegister(.{ ._, .bt }, src_mem, index_reg.to32());
@@ -12440,14 +12694,14 @@ fn genCall(self: *Self, info: union(enum) {
} },
});
if (self.hasFeature(.slow_incdec)) {
- try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .add }, index_reg.to32(), .u(1));
} else {
try self.asmRegister(.{ ._, .inc }, index_reg.to32());
}
try self.asmRegisterImmediate(
.{ ._, .cmp },
index_reg.to32(),
- Immediate.u(arg_ty.vectorLen(zcu)),
+ .u(arg_ty.vectorLen(zcu)),
);
_ = try self.asmJccReloc(.b, loop);
@@ -12521,11 +12775,7 @@ fn genCall(self: *Self, info: union(enum) {
0..,
) |dst_reg, elem_index| {
try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
- try self.asmMemoryImmediate(
- .{ ._, .bt },
- src_mem,
- Immediate.u(elem_index),
- );
+ try self.asmMemoryImmediate(.{ ._, .bt }, src_mem, .u(elem_index));
try self.asmSetccRegister(.c, dst_reg.to8());
}
},
@@ -12533,7 +12783,7 @@ fn genCall(self: *Self, info: union(enum) {
};
if (fn_info.is_var_args)
- try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count));
+ try self.asmRegisterImmediate(.{ ._, .mov }, .al, .u(call_info.fp_count));
// Due to incremental compilation, how function calls are generated depends
// on linking.
@@ -12551,7 +12801,7 @@ fn genCall(self: *Self, info: union(enum) {
if (self.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const sym_index = try zo.getOrCreateMetadataForNav(zcu, func.owner_nav);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
+ try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index }));
} else if (self.bin_file.cast(.coff)) |coff_file| {
const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
@@ -12561,7 +12811,7 @@ fn genCall(self: *Self, info: union(enum) {
const zo = macho_file.getZigObject().?;
const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
const sym = zo.symbols.items[sym_index];
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
+ try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym.nlist_idx }));
} else if (self.bin_file.cast(.plan9)) |p9| {
const atom_index = try p9.seeNav(pt, func.owner_nav);
const atom = p9.getAtom(atom_index);
@@ -12579,13 +12829,13 @@ fn genCall(self: *Self, info: union(enum) {
@"extern".name.toSlice(ip),
@"extern".lib_name.toSlice(ip),
);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
+ try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
} else if (self.bin_file.cast(.macho)) |macho_file| {
const target_sym_index = try macho_file.getGlobalSymbol(
@"extern".name.toSlice(ip),
@"extern".lib_name.toSlice(ip),
);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
+ try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
} else try self.genExternSymbolRef(
.call,
@"extern".lib_name.toSlice(ip),
@@ -12600,10 +12850,10 @@ fn genCall(self: *Self, info: union(enum) {
},
.lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
+ try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
} else if (self.bin_file.cast(.macho)) |macho_file| {
const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
+ try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = target_sym_index }));
} else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
}
return call_info.return_value.short;
@@ -12665,7 +12915,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);
}
-fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
+fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void {
const pt = self.pt;
const zcu = pt.zcu;
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 {
try self.asmRegisterImmediate(
.{ ._r, .sh },
registerAlias(temp_lhs_reg, opt_abi_size),
- Immediate.u(payload_abi_size * 8),
+ .u(payload_abi_size * 8),
);
}
@@ -12775,7 +13025,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
try self.asmRegisterImmediate(
.{ ._r, .sh },
registerAlias(temp_rhs_reg, opt_abi_size),
- Immediate.u(payload_abi_size * 8),
+ .u(payload_abi_size * 8),
);
try self.asmRegisterRegister(
.{ ._, .@"test" },
@@ -12867,10 +13117,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
.register_pair, .load_frame => null,
.memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: {
switch (resolved_dst_mcv) {
- .memory => |addr| if (math.cast(
+ .memory => |addr| if (std.math.cast(
i32,
@as(i64, @bitCast(addr)),
- ) != null and math.cast(
+ ) != null and std.math.cast(
i32,
@as(i64, @bitCast(addr)) + abi_size - 8,
) != null) break :dst null,
@@ -12928,10 +13178,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
.register_pair, .load_frame => null,
.memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
switch (resolved_src_mcv) {
- .memory => |addr| if (math.cast(
+ .memory => |addr| if (std.math.cast(
i32,
@as(i64, @bitCast(addr)),
- ) != null and math.cast(
+ ) != null and std.math.cast(
i32,
@as(i64, @bitCast(addr)) + abi_size - 8,
) != null) break :src null,
@@ -12971,7 +13221,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
const locks = self.register_manager.lockRegsAssumeUnused(2, regs);
defer for (locks) |lock| self.register_manager.unlockReg(lock);
- const limbs_len = math.divCeil(u16, abi_size, 8) catch unreachable;
+ const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable;
var limb_i: u16 = 0;
while (limb_i < limbs_len) : (limb_i += 1) {
const off = limb_i * 8;
@@ -13067,7 +13317,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
tmp1_reg,
dst_reg.to128(),
try src_mcv.mem(self, .word),
- Immediate.u(1),
+ .u(1),
) else try self.asmRegisterRegisterRegister(
.{ .vp_, .unpcklwd },
tmp1_reg,
@@ -13232,7 +13482,6 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
.column = dbg_stmt.column,
} },
});
- self.finishAirBookkeeping();
}
fn airDbgEmptyStmt(self: *Self) !void {
@@ -13240,7 +13489,6 @@ fn airDbgEmptyStmt(self: *Self) !void {
self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] == .pseudo_dbg_line_stmt_line_column)
self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] = .pseudo_dbg_line_line_column;
try self.asmOpOnly(.{ ._, .nop });
- self.finishAirBookkeeping();
}
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
@@ -13278,7 +13526,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
},
.register => |reg| {
try self.spillEflagsIfOccupied();
- try self.asmRegisterImmediate(.{ ._, .@"test" }, reg.to8(), Immediate.u(1));
+ try self.asmRegisterImmediate(.{ ._, .@"test" }, reg.to8(), .u(1));
return self.asmJccReloc(.z, undefined);
},
.immediate,
@@ -13338,7 +13586,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
});
// We already took care of pl_op.operand earlier, so there's nothing left to do.
- self.finishAirBookkeeping();
}
fn 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
const pl_ty = opt_ty.optionalChild(zcu);
- const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
+ const some_info: struct { off: u31, ty: Type } = if (opt_ty.optionalReprIsPayload(zcu))
.{ .off = 0, .ty = if (pl_ty.isSlice(zcu)) pl_ty.slicePtrFieldType(zcu) else pl_ty }
else
.{ .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
.undef,
.immediate,
.eflags,
- .register_pair,
.register_offset,
.register_overflow,
.lea_direct,
@@ -13396,7 +13642,25 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
try self.asmRegisterImmediate(
.{ ._, .bt },
registerAlias(opt_reg, opt_abi_size),
- Immediate.u(@as(u6, @intCast(some_info.off * 8))),
+ .u(@as(u6, @intCast(some_info.off * 8))),
+ );
+ return .{ .eflags = .nc };
+ },
+
+ .register_pair => |opt_regs| {
+ if (some_info.off == 0) {
+ const some_abi_size: u32 = @intCast(some_info.ty.abiSize(zcu));
+ const alias_reg = registerAlias(opt_regs[0], some_abi_size);
+ assert(some_abi_size * 8 == alias_reg.bitSize());
+ try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);
+ return .{ .eflags = .z };
+ }
+ assert(some_info.ty.ip_index == .bool_type);
+ const opt_abi_size: u32 = @intCast(opt_ty.abiSize(zcu));
+ try self.asmRegisterImmediate(
+ .{ ._, .bt },
+ registerAlias(opt_regs[some_info.off / 8], opt_abi_size),
+ .u(@as(u6, @truncate(some_info.off * 8))),
);
return .{ .eflags = .nc };
},
@@ -13422,7 +13686,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
.disp = some_info.off,
} },
},
- Immediate.u(0),
+ .u(0),
);
return .{ .eflags = .e };
},
@@ -13448,7 +13712,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
},
else => unreachable,
},
- Immediate.u(0),
+ .u(0),
);
return .{ .eflags = .e };
},
@@ -13485,7 +13749,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
.disp = some_info.off,
} },
},
- Immediate.u(0),
+ .u(0),
);
self.eflags_inst = inst;
@@ -13500,7 +13764,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
try self.spillEflagsIfOccupied();
- const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
+ const err_off: u31 = @intCast(codegen.errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
switch (eu_mcv) {
.register => |reg| {
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
const ptr_lock = self.register_manager.lockReg(ptr_reg);
defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
- const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
+ const err_off: u31 = @intCast(codegen.errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
try self.asmMemoryImmediate(
.{ ._, .cmp },
.{
@@ -13567,7 +13831,7 @@ fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCV
.disp = err_off,
} },
},
- Immediate.u(0),
+ .u(0),
);
if (maybe_inst) |inst| self.eflags_inst = inst;
@@ -13686,12 +13950,11 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {
try self.loops.putNoClobber(self.gpa, inst, .{
.state = state,
- .jmp_target = @intCast(self.mir_instructions.len),
+ .target = @intCast(self.mir_instructions.len),
});
defer assert(self.loops.remove(inst));
try self.genBodyBlock(body);
- self.finishAirBookkeeping();
}
fn 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) !
const tracking = &self.inst_tracking.values()[inst_tracking_i];
if (self.liveness.isUnused(inst)) try tracking.die(self, inst);
self.getValueIfFree(tracking.short, inst);
- self.finishAirBookkeeping();
}
fn 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 {
try self.lowerSwitchBr(inst, switch_br, condition);
// We already took care of pl_op.operand earlier, so there's nothing left to do
- self.finishAirBookkeeping();
}
fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
@@ -13893,7 +14154,7 @@ fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
try self.loops.putNoClobber(self.gpa, inst, .{
.state = state,
- .jmp_target = @intCast(self.mir_instructions.len),
+ .target = @intCast(self.mir_instructions.len),
});
defer assert(self.loops.remove(inst));
@@ -13903,7 +14164,6 @@ fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
try self.lowerSwitchBr(inst, switch_br, mat_cond);
try self.processDeath(inst);
- self.finishAirBookkeeping();
}
fn airSwitchDispatch(self: *Self, inst: Air.Inst.Index) !void {
@@ -13945,12 +14205,10 @@ fn airSwitchDispatch(self: *Self, inst: Air.Inst.Index) !void {
// Emit a jump with a relocation. It will be patched up after the block ends.
// Leave the jump offset undefined
- _ = try self.asmJmpReloc(loop_data.jmp_target);
+ _ = try self.asmJmpReloc(loop_data.target);
// Stop tracking block result without forgetting tracking info
try self.freeValue(block_tracking.short);
-
- self.finishAirBookkeeping();
}
fn performReloc(self: *Self, reloc: Mir.Inst.Index) void {
@@ -14023,8 +14281,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
// Stop tracking block result without forgetting tracking info
try self.freeValue(block_tracking.short);
-
- self.finishAirBookkeeping();
}
fn airRepeat(self: *Self, inst: Air.Inst.Index) !void {
@@ -14036,8 +14292,7 @@ fn airRepeat(self: *Self, inst: Air.Inst.Index) !void {
.resurrect = false,
.close_scope = true,
});
- _ = try self.asmJmpReloc(repeat_info.jmp_target);
- self.finishAirBookkeeping();
+ _ = try self.asmJmpReloc(repeat_info.target);
}
fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
@@ -14068,9 +14323,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
var outputs_extra_i = extra_i;
for (outputs) |output| {
- const extra_bytes = mem.sliceAsBytes(self.air.extra[extra_i..]);
- const constraint = mem.sliceTo(mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
- const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
+ const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
// for the string, we still use the next u32 for the null terminator.
extra_i += (constraint.len + name.len + (2 + 3)) / 4;
@@ -14097,8 +14352,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
const is_early_clobber = constraint[1] == '&';
const rest = constraint[@as(usize, 1) + @intFromBool(is_early_clobber) ..];
const arg_mcv: MCValue = arg_mcv: {
- const arg_maybe_reg: ?Register = if (mem.eql(u8, rest, "r") or
- mem.eql(u8, rest, "f") or mem.eql(u8, rest, "x"))
+ const arg_maybe_reg: ?Register = if (std.mem.eql(u8, rest, "r") or
+ std.mem.eql(u8, rest, "f") or std.mem.eql(u8, rest, "x"))
registerAlias(
self.register_manager.tryAllocReg(maybe_inst, switch (rest[0]) {
'r' => abi.RegisterClass.gp,
@@ -14108,20 +14363,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
}) orelse return self.fail("ran out of registers lowering inline asm", .{}),
@intCast(ty.abiSize(zcu)),
)
- else if (mem.eql(u8, rest, "m"))
+ else if (std.mem.eql(u8, rest, "m"))
if (output != .none) null else return self.fail(
"memory constraint unsupported for asm result: '{s}'",
.{constraint},
)
- else if (mem.eql(u8, rest, "g") or
- mem.eql(u8, rest, "rm") or mem.eql(u8, rest, "mr") or
- mem.eql(u8, rest, "r,m") or mem.eql(u8, rest, "m,r"))
+ else if (std.mem.eql(u8, rest, "g") or
+ std.mem.eql(u8, rest, "rm") or std.mem.eql(u8, rest, "mr") or
+ std.mem.eql(u8, rest, "r,m") or std.mem.eql(u8, rest, "m,r"))
self.register_manager.tryAllocReg(maybe_inst, abi.RegisterClass.gp) orelse
if (output != .none)
null
else
return self.fail("ran out of registers lowering inline asm", .{})
- else if (mem.startsWith(u8, rest, "{") and mem.endsWith(u8, rest, "}"))
+ else if (std.mem.startsWith(u8, rest, "{") and std.mem.endsWith(u8, rest, "}"))
parseRegName(rest["{".len .. rest.len - "}".len]) orelse
return self.fail("invalid register constraint: '{s}'", .{constraint})
else if (rest.len == 1 and std.ascii.isDigit(rest[0])) {
@@ -14134,7 +14389,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
break :arg_mcv if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
const ptr_mcv = try self.resolveInst(output);
switch (ptr_mcv) {
- .immediate => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
+ .immediate => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
break :arg ptr_mcv.deref(),
.register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
else => {},
@@ -14145,7 +14400,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
_ = self.register_manager.lockReg(reg);
};
- if (!mem.eql(u8, name, "_"))
+ if (!std.mem.eql(u8, name, "_"))
arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));
args.appendAssumeCapacity(arg_mcv);
if (output == .none) result = arg_mcv;
@@ -14153,17 +14408,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
}
for (inputs) |input| {
- const input_bytes = mem.sliceAsBytes(self.air.extra[extra_i..]);
- const constraint = mem.sliceTo(input_bytes, 0);
- const name = mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
// for the string, we still use the next u32 for the null terminator.
extra_i += (constraint.len + name.len + (2 + 3)) / 4;
const ty = self.typeOf(input);
const input_mcv = try self.resolveInst(input);
- const arg_mcv: MCValue = if (mem.eql(u8, constraint, "r") or
- mem.eql(u8, constraint, "f") or mem.eql(u8, constraint, "x"))
+ const arg_mcv: MCValue = if (std.mem.eql(u8, constraint, "r") or
+ std.mem.eql(u8, constraint, "f") or std.mem.eql(u8, constraint, "x"))
arg: {
const rc = switch (constraint[0]) {
'r' => abi.RegisterClass.gp,
@@ -14177,16 +14432,16 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
const reg = try self.register_manager.allocReg(null, rc);
try self.genSetReg(reg, ty, input_mcv, .{});
break :arg .{ .register = registerAlias(reg, @intCast(ty.abiSize(zcu))) };
- } else if (mem.eql(u8, constraint, "i") or mem.eql(u8, constraint, "n"))
+ } else if (std.mem.eql(u8, constraint, "i") or std.mem.eql(u8, constraint, "n"))
switch (input_mcv) {
.immediate => |imm| .{ .immediate = imm },
else => return self.fail("immediate operand requires comptime value: '{s}'", .{
constraint,
}),
}
- else if (mem.eql(u8, constraint, "m")) arg: {
+ else if (std.mem.eql(u8, constraint, "m")) arg: {
switch (input_mcv) {
- .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
+ .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
break :arg input_mcv,
.indirect, .load_frame => break :arg input_mcv,
.load_symbol, .load_direct, .load_got, .load_tlv => {},
@@ -14203,22 +14458,22 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
};
try self.genSetReg(addr_reg, Type.usize, input_mcv.address(), .{});
break :arg .{ .indirect = .{ .reg = addr_reg } };
- } else if (mem.eql(u8, constraint, "g") or
- mem.eql(u8, constraint, "rm") or mem.eql(u8, constraint, "mr") or
- mem.eql(u8, constraint, "r,m") or mem.eql(u8, constraint, "m,r"))
+ } else if (std.mem.eql(u8, constraint, "g") or
+ std.mem.eql(u8, constraint, "rm") or std.mem.eql(u8, constraint, "mr") or
+ std.mem.eql(u8, constraint, "r,m") or std.mem.eql(u8, constraint, "m,r"))
arg: {
switch (input_mcv) {
.register, .indirect, .load_frame => break :arg input_mcv,
- .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
+ .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |_|
break :arg input_mcv,
else => {},
}
const temp_mcv = try self.allocTempRegOrMem(ty, true);
try self.genCopy(ty, temp_mcv, input_mcv, .{});
break :arg temp_mcv;
- } else if (mem.eql(u8, constraint, "X"))
+ } else if (std.mem.eql(u8, constraint, "X"))
input_mcv
- else if (mem.startsWith(u8, constraint, "{") and mem.endsWith(u8, constraint, "}")) arg: {
+ else if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) arg: {
const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse
return self.fail("invalid register constraint: '{s}'", .{constraint});
try self.register_manager.getReg(reg, null);
@@ -14233,7 +14488,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
_ = self.register_manager.lockReg(reg);
};
- if (!mem.eql(u8, name, "_"))
+ if (!std.mem.eql(u8, name, "_"))
arg_map.putAssumeCapacityNoClobber(name, @intCast(args.items.len));
args.appendAssumeCapacity(arg_mcv);
}
@@ -14241,7 +14496,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
{
var clobber_i: u32 = 0;
while (clobber_i < clobbers_len) : (clobber_i += 1) {
- const clobber = mem.sliceTo(mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
// for the string, we still use the next u32 for the null terminator.
extra_i += clobber.len / 4 + 1;
@@ -14294,20 +14549,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
labels.deinit(self.gpa);
}
- const asm_source = mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];
- var line_it = mem.tokenizeAny(u8, asm_source, "\n\r;");
+ const asm_source = std.mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len];
+ var line_it = std.mem.tokenizeAny(u8, asm_source, "\n\r;");
next_line: while (line_it.next()) |line| {
- var mnem_it = mem.tokenizeAny(u8, line, " \t");
- var prefix: Instruction.Prefix = .none;
+ var mnem_it = std.mem.tokenizeAny(u8, line, " \t");
+ var prefix: encoder.Instruction.Prefix = .none;
const mnem_str = while (mnem_it.next()) |mnem_str| {
if (mnem_str[0] == '#') continue :next_line;
- if (mem.startsWith(u8, mnem_str, "//")) continue :next_line;
- if (std.meta.stringToEnum(Instruction.Prefix, mnem_str)) |pre| {
+ if (std.mem.startsWith(u8, mnem_str, "//")) continue :next_line;
+ if (std.meta.stringToEnum(encoder.Instruction.Prefix, mnem_str)) |pre| {
if (prefix != .none) return self.fail("extra prefix: '{s}'", .{mnem_str});
prefix = pre;
continue;
}
- if (!mem.endsWith(u8, mnem_str, ":")) break mnem_str;
+ if (!std.mem.endsWith(u8, mnem_str, ":")) break mnem_str;
const label_name = mnem_str[0 .. mnem_str.len - ":".len];
if (!Label.isValid(.definition, label_name))
return self.fail("invalid label: '{s}'", .{label_name});
@@ -14332,21 +14587,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
var mnem_size: ?Memory.Size = if (prefix == .directive)
null
- else if (mem.endsWith(u8, mnem_str, "b"))
+ else if (std.mem.endsWith(u8, mnem_str, "b"))
.byte
- else if (mem.endsWith(u8, mnem_str, "w"))
+ else if (std.mem.endsWith(u8, mnem_str, "w"))
.word
- else if (mem.endsWith(u8, mnem_str, "l"))
+ else if (std.mem.endsWith(u8, mnem_str, "l"))
.dword
- else if (mem.endsWith(u8, mnem_str, "q") and
- (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !mem.endsWith(u8, mnem_str, "dq")))
+ else if (std.mem.endsWith(u8, mnem_str, "q") and
+ (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq")))
.qword
- else if (mem.endsWith(u8, mnem_str, "t"))
+ else if (std.mem.endsWith(u8, mnem_str, "t"))
.tbyte
else
null;
const mnem_tag = while (true) break std.meta.stringToEnum(
- Instruction.Mnemonic,
+ encoder.Instruction.Mnemonic,
mnem_str[0 .. mnem_str.len - @intFromBool(mnem_size != null)],
) orelse if (mnem_size) |_| {
mnem_size = null;
@@ -14367,18 +14622,18 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
.{ ._, .pseudo }
else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
const fixes_name = @tagName(fixes);
- const space_i = mem.indexOfScalar(u8, fixes_name, ' ');
+ const space_i = std.mem.indexOfScalar(u8, fixes_name, ' ');
const fixes_prefix = if (space_i) |i|
- std.meta.stringToEnum(Instruction.Prefix, fixes_name[0..i]).?
+ std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..i]).?
else
.none;
if (fixes_prefix != prefix) continue;
const pattern = fixes_name[if (space_i) |i| i + " ".len else 0..];
- const wildcard_i = mem.indexOfScalar(u8, pattern, '_').?;
+ const wildcard_i = std.mem.indexOfScalar(u8, pattern, '_').?;
const mnem_prefix = pattern[0..wildcard_i];
const mnem_suffix = pattern[wildcard_i + "_".len ..];
- if (!mem.startsWith(u8, mnem_name, mnem_prefix)) continue;
- if (!mem.endsWith(u8, mnem_name, mnem_suffix)) continue;
+ if (!std.mem.startsWith(u8, mnem_name, mnem_prefix)) continue;
+ if (!std.mem.endsWith(u8, mnem_name, mnem_suffix)) continue;
break .{ fixes, std.meta.stringToEnum(
Mir.Inst.Tag,
mnem_name[mnem_prefix.len .. mnem_name.len - mnem_suffix.len],
@@ -14400,21 +14655,21 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
var ops: [4]Operand = .{.none} ** 4;
var last_op = false;
- var op_it = mem.splitScalar(u8, mnem_it.rest(), ',');
+ var op_it = std.mem.splitScalar(u8, mnem_it.rest(), ',');
next_op: for (&ops) |*op| {
const op_str = while (!last_op) {
const full_str = op_it.next() orelse break :next_op;
- const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse
- mem.indexOf(u8, full_str, "//")) |comment|
+ const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse
+ std.mem.indexOf(u8, full_str, "//")) |comment|
code: {
last_op = true;
break :code full_str[0..comment];
} else full_str;
- const trim_str = mem.trim(u8, code_str, " \t*");
+ const trim_str = std.mem.trim(u8, code_str, " \t*");
if (trim_str.len > 0) break trim_str;
} else break;
- if (mem.startsWith(u8, op_str, "%%")) {
- const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
+ if (std.mem.startsWith(u8, op_str, "%%")) {
+ const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
return self.fail("invalid register: '{s}'", .{op_str});
if (colon) |colon_pos| {
@@ -14432,8 +14687,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
return self.fail("invalid register size: '{s}'", .{op_str});
op.* = .{ .reg = reg };
}
- } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {
- const colon = mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
+ } else if (std.mem.startsWith(u8, op_str, "%[") and std.mem.endsWith(u8, op_str, "]")) {
+ const colon = std.mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
const modifier = if (colon) |colon_pos|
op_str[colon_pos + ":".len .. op_str.len - "]".len]
else
@@ -14442,15 +14697,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse
return self.fail("no matching constraint: '{s}'", .{op_str})
]) {
- .immediate => |imm| if (mem.eql(u8, modifier, "") or mem.eql(u8, modifier, "c"))
- .{ .imm = Immediate.u(imm) }
+ .immediate => |imm| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "c"))
+ .{ .imm = .u(imm) }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .register => |reg| if (mem.eql(u8, modifier, ""))
+ .register => |reg| if (std.mem.eql(u8, modifier, ""))
.{ .reg = reg }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .memory => |addr| if (mem.eql(u8, modifier, "") or mem.eql(u8, modifier, "P"))
+ .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P"))
.{ .mem = .{
.base = .{ .reg = .ds },
.mod = .{ .rm = .{
@@ -14461,7 +14716,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .indirect => |reg_off| if (mem.eql(u8, modifier, ""))
+ .indirect => |reg_off| if (std.mem.eql(u8, modifier, ""))
.{ .mem = .{
.base = .{ .reg = reg_off.reg },
.mod = .{ .rm = .{
@@ -14472,7 +14727,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .load_frame => |frame_addr| if (mem.eql(u8, modifier, ""))
+ .load_frame => |frame_addr| if (std.mem.eql(u8, modifier, ""))
.{ .mem = .{
.base = .{ .frame = frame_addr.index },
.mod = .{ .rm = .{
@@ -14483,42 +14738,42 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .lea_got => |sym_index| if (mem.eql(u8, modifier, "P"))
+ .lea_got => |sym_index| if (std.mem.eql(u8, modifier, "P"))
.{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
- .lea_symbol => |sym_off| if (mem.eql(u8, modifier, "P"))
+ .lea_symbol => |sym_off| if (std.mem.eql(u8, modifier, "P"))
.{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_symbol = sym_off }) }
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
else => return self.fail("invalid constraint: '{s}'", .{op_str}),
};
- } else if (mem.startsWith(u8, op_str, "$")) {
+ } else if (std.mem.startsWith(u8, op_str, "$")) {
if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {
if (mnem_size) |size| {
- const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
+ const max = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
if ((if (s < 0) ~s else s) > max)
return self.fail("invalid immediate size: '{s}'", .{op_str});
}
- op.* = .{ .imm = Immediate.s(s) };
+ op.* = .{ .imm = .s(s) };
} else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {
if (mnem_size) |size| {
- const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());
+ const max = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - size.bitSize());
if (u > max)
return self.fail("invalid immediate size: '{s}'", .{op_str});
}
- op.* = .{ .imm = Immediate.u(u) };
+ op.* = .{ .imm = .u(u) };
} else |_| return self.fail("invalid immediate: '{s}'", .{op_str});
- } else if (mem.endsWith(u8, op_str, ")")) {
- const open = mem.indexOfScalar(u8, op_str, '(') orelse
+ } else if (std.mem.endsWith(u8, op_str, ")")) {
+ const open = std.mem.indexOfScalar(u8, op_str, '(') orelse
return self.fail("invalid operand: '{s}'", .{op_str});
- var sib_it = mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
+ var sib_it = std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
const base_str = sib_it.next() orelse
return self.fail("invalid memory operand: '{s}'", .{op_str});
- if (base_str.len > 0 and !mem.startsWith(u8, base_str, "%%"))
+ if (base_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%"))
return self.fail("invalid memory operand: '{s}'", .{op_str});
const index_str = sib_it.next() orelse "";
- if (index_str.len > 0 and !mem.startsWith(u8, base_str, "%%"))
+ if (index_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%"))
return self.fail("invalid memory operand: '{s}'", .{op_str});
const scale_str = sib_it.next() orelse "";
if (index_str.len == 0 and scale_str.len > 0)
@@ -14550,10 +14805,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
else
.none,
.scale = scale,
- .disp = if (mem.startsWith(u8, op_str[0..open], "%[") and
- mem.endsWith(u8, op_str[0..open], "]"))
+ .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and
+ std.mem.endsWith(u8, op_str[0..open], "]"))
disp: {
- const colon = mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
+ const colon = std.mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
const modifier = if (colon) |colon_pos|
op_str[colon_pos + ":".len .. open - "]".len]
else
@@ -14562,9 +14817,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
arg_map.get(op_str["%[".len .. colon orelse open - "]".len]) orelse
return self.fail("no matching constraint: '{s}'", .{op_str})
]) {
- .immediate => |imm| if (mem.eql(u8, modifier, "") or
- mem.eql(u8, modifier, "c"))
- math.cast(i32, @as(i64, @bitCast(imm))) orelse
+ .immediate => |imm| if (std.mem.eql(u8, modifier, "") or
+ std.mem.eql(u8, modifier, "c"))
+ std.math.cast(i32, @as(i64, @bitCast(imm))) orelse
return self.fail("invalid displacement: '{s}'", .{op_str})
else
return self.fail("invalid modifier: '{s}'", .{modifier}),
@@ -14730,10 +14985,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
return self.fail("undefined label: '{s}'", .{label.key_ptr.*});
for (outputs, args.items[0..outputs.len]) |output, arg_mcv| {
- const extra_bytes = mem.sliceAsBytes(self.air.extra[outputs_extra_i..]);
+ const extra_bytes = std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]);
const constraint =
- mem.sliceTo(mem.sliceAsBytes(self.air.extra[outputs_extra_i..]), 0);
- const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
+ std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]), 0);
+ const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
// for the string, we still use the next u32 for the null terminator.
outputs_extra_i += (constraint.len + name.len + (2 + 3)) / 4;
@@ -14777,7 +15032,10 @@ const MoveStrategy = union(enum) {
pub fn read(strat: MoveStrategy, self: *Self, dst_reg: Register, src_mem: Memory) !void {
switch (strat) {
- .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem),
+ .move => |tag| try self.asmRegisterMemory(tag, switch (tag[1]) {
+ else => dst_reg,
+ .lea => if (dst_reg.bitSize() >= 32) dst_reg else dst_reg.to32(),
+ }, src_mem),
.x87_load_store => {
try self.asmMemory(.{ .f_, .ld }, src_mem);
assert(dst_reg != .st7);
@@ -14787,14 +15045,14 @@ const MoveStrategy = union(enum) {
ie.insert,
dst_reg,
src_mem,
- Immediate.u(0),
+ .u(0),
),
.vex_insert_extract => |ie| try self.asmRegisterRegisterMemoryImmediate(
ie.insert,
dst_reg,
dst_reg,
src_mem,
- Immediate.u(0),
+ .u(0),
),
}
}
@@ -14809,7 +15067,7 @@ const MoveStrategy = union(enum) {
ie.extract,
dst_mem,
src_reg,
- Immediate.u(0),
+ .u(0),
),
}
}
@@ -14823,7 +15081,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
.mmx => {},
.sse => switch (ty.zigTypeTag(zcu)) {
else => {
- const classes = mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
+ const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
assert(std.mem.indexOfNone(abi.Class, classes, &.{
.integer, .sse, .sseup, .memory, .float, .float_combine,
}) == null);
@@ -15135,7 +15393,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: Copy
),
.memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
switch (dst_mcv) {
- .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
+ .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts),
.load_symbol, .load_direct, .load_got, .load_tlv => {},
else => unreachable,
@@ -15179,17 +15437,17 @@ fn genSetReg(
=> unreachable,
.undef => if (opts.safety) switch (dst_reg.class()) {
.general_purpose => switch (abi_size) {
- 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), Immediate.u(0xAA)),
- 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), Immediate.u(0xAAAA)),
+ 1 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to8(), .u(0xAA)),
+ 2 => try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to16(), .u(0xAAAA)),
3...4 => try self.asmRegisterImmediate(
.{ ._, .mov },
dst_reg.to32(),
- Immediate.s(@as(i32, @bitCast(@as(u32, 0xAAAAAAAA)))),
+ .s(@as(i32, @bitCast(@as(u32, 0xAAAAAAAA)))),
),
5...8 => try self.asmRegisterImmediate(
.{ ._, .mov },
dst_reg.to64(),
- Immediate.u(0xAAAAAAAAAAAAAAAA),
+ .u(0xAAAAAAAAAAAAAAAA),
),
else => unreachable,
},
@@ -15203,20 +15461,20 @@ fn genSetReg(
// register is the fastest way to zero a register.
try self.spillEflagsIfOccupied();
try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
- } else if (abi_size > 4 and math.cast(u32, imm) != null) {
+ } else if (abi_size > 4 and std.math.cast(u32, imm) != null) {
// 32-bit moves zero-extend to 64-bit.
- try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), Immediate.u(imm));
+ try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), .u(imm));
} else if (abi_size <= 4 and @as(i64, @bitCast(imm)) < 0) {
try self.asmRegisterImmediate(
.{ ._, .mov },
registerAlias(dst_reg, abi_size),
- Immediate.s(@intCast(@as(i64, @bitCast(imm)))),
+ .s(@intCast(@as(i64, @bitCast(imm)))),
);
} else {
try self.asmRegisterImmediate(
.{ ._, .mov },
registerAlias(dst_reg, abi_size),
- Immediate.u(imm),
+ .u(imm),
);
}
},
@@ -15325,15 +15583,15 @@ fn genSetReg(
.load_frame => |frame_addr| try self.moveStrategy(
ty,
dst_reg.class(),
- self.getFrameAddrAlignment(frame_addr).compare(.gte, Alignment.fromLog2Units(
- math.log2_int_ceil(u10, @divExact(dst_reg.bitSize(), 8)),
+ self.getFrameAddrAlignment(frame_addr).compare(.gte, InternPool.Alignment.fromLog2Units(
+ std.math.log2_int_ceil(u10, @divExact(dst_reg.bitSize(), 8)),
)),
),
.lea_frame => .{ .move = .{ ._, .lea } },
else => unreachable,
}).read(self, registerAlias(dst_reg, abi_size), switch (src_mcv) {
.register_offset, .indirect => |reg_off| .{
- .base = .{ .reg = reg_off.reg },
+ .base = .{ .reg = reg_off.reg.to64() },
.mod = .{ .rm = .{
.size = self.memSize(ty),
.disp = reg_off.off,
@@ -15350,7 +15608,7 @@ fn genSetReg(
}),
.memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
switch (src_mcv) {
- .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
+ .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
return (try self.moveStrategy(
ty,
dst_reg.class(),
@@ -15400,14 +15658,10 @@ fn genSetReg(
const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
defer self.register_manager.unlockReg(addr_lock);
- try (try self.moveStrategy(ty, dst_reg.class(), false)).read(
- self,
- registerAlias(dst_reg, abi_size),
- .{
- .base = .{ .reg = addr_reg },
- .mod = .{ .rm = .{ .size = self.memSize(ty) } },
- },
- );
+ try (try self.moveStrategy(ty, dst_reg.class(), false)).read(self, registerAlias(dst_reg, abi_size), .{
+ .base = .{ .reg = addr_reg.to64() },
+ .mod = .{ .rm = .{ .size = self.memSize(ty) } },
+ });
},
.lea_symbol => |sym_off| switch (self.bin_file.tag) {
.elf, .macho => try self.asmRegisterMemory(
@@ -15478,12 +15732,12 @@ fn genSetMem(
),
.immediate => |imm| switch (abi_size) {
1, 2, 4 => {
- const immediate = switch (if (ty.isAbiInt(zcu))
+ const immediate: Immediate = switch (if (ty.isAbiInt(zcu))
ty.intInfo(zcu).signedness
else
.unsigned) {
- .signed => Immediate.s(@truncate(@as(i64, @bitCast(imm)))),
- .unsigned => Immediate.u(@as(u32, @intCast(imm))),
+ .signed => .s(@truncate(@as(i64, @bitCast(imm)))),
+ .unsigned => .u(@as(u32, @intCast(imm))),
};
try self.asmMemoryImmediate(
.{ ._, .mov },
@@ -15495,14 +15749,14 @@ fn genSetMem(
);
},
3, 5...7 => unreachable,
- else => if (math.cast(i32, @as(i64, @bitCast(imm)))) |small| {
+ else => if (std.math.cast(i32, @as(i64, @bitCast(imm)))) |small| {
try self.asmMemoryImmediate(
.{ ._, .mov },
.{ .base = base, .mod = .{ .rm = .{
.size = Memory.Size.fromSize(abi_size),
.disp = disp,
} } },
- Immediate.s(small),
+ .s(small),
);
} else {
var offset: i32 = 0;
@@ -15512,10 +15766,10 @@ fn genSetMem(
.size = .dword,
.disp = disp + offset,
} } },
- if (ty.isSignedInt(zcu)) Immediate.s(
- @truncate(@as(i64, @bitCast(imm)) >> (math.cast(u6, offset * 8) orelse 63)),
- ) else Immediate.u(
- @as(u32, @truncate(if (math.cast(u6, offset * 8)) |shift| imm >> shift else 0)),
+ if (ty.isSignedInt(zcu)) .s(
+ @truncate(@as(i64, @bitCast(imm)) >> (std.math.cast(u6, offset * 8) orelse 63)),
+ ) else .u(
+ @as(u32, @truncate(if (std.math.cast(u6, offset * 8)) |shift| imm >> shift else 0)),
),
);
},
@@ -15542,7 +15796,9 @@ fn genSetMem(
.general_purpose, .segment, .x87, .ip => @divExact(src_alias.bitSize(), 8),
.mmx, .sse => abi_size,
});
- const src_align = Alignment.fromNonzeroByteUnits(math.ceilPowerOfTwoAssert(u32, src_size));
+ const src_align = InternPool.Alignment.fromNonzeroByteUnits(
+ std.math.ceilPowerOfTwoAssert(u32, src_size),
+ );
if (src_size > mem_size) {
const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{
.size = src_size,
@@ -15755,7 +16011,7 @@ fn genLazySymbolRef(
.base = .{ .reloc = sym_index },
.mod = .{ .rm = .{ .size = .qword } },
}),
- .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
+ .call => try self.asmImmediate(.{ ._, .call }, .rel(.{ .sym_index = sym_index })),
else => unreachable,
}
} else if (self.bin_file.cast(.plan9)) |p9_file| {
@@ -15861,7 +16117,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
const dst_mcv = if (dst_rc.supersetOf(src_rc) and dst_ty.abiSize(zcu) <= src_ty.abiSize(zcu) and
self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
const dst_mcv = try self.allocRegOrMem(inst, true);
- try self.genCopy(switch (math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {
+ try self.genCopy(switch (std.math.order(dst_ty.abiSize(zcu), src_ty.abiSize(zcu))) {
.lt => dst_ty,
.eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
.gt => src_ty,
@@ -15878,7 +16134,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
const bit_size = dst_ty.bitSize(zcu);
if (abi_size * 8 <= bit_size or dst_ty.isVector(zcu)) break :result dst_mcv;
- const dst_limbs_len = math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;
+ const dst_limbs_len = std.math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;
const high_mcv: MCValue = switch (dst_mcv) {
.register => |dst_reg| .{ .register = dst_reg },
.register_pair => |dst_regs| .{ .register = dst_regs[1] },
@@ -15940,7 +16196,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {
const src_bits: u32 = @intCast(src_ty.bitSize(zcu));
const src_signedness =
if (src_ty.isAbiInt(zcu)) src_ty.intInfo(zcu).signedness else .unsigned;
- const src_size = math.divCeil(u32, @max(switch (src_signedness) {
+ const src_size = std.math.divCeil(u32, @max(switch (src_signedness) {
.signed => src_bits,
.unsigned => src_bits + 1,
}, 32), 8) catch unreachable;
@@ -16017,7 +16273,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {
const dst_bits: u32 = @intCast(dst_ty.bitSize(zcu));
const dst_signedness =
if (dst_ty.isAbiInt(zcu)) dst_ty.intInfo(zcu).signedness else .unsigned;
- const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {
+ const dst_size = std.math.divCeil(u32, @max(switch (dst_signedness) {
.signed => dst_bits,
.unsigned => dst_bits + 1,
}, 32), 8) catch unreachable;
@@ -16593,13 +16849,17 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
const reg_locks = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdi, .rsi, .rcx });
defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
- const dst_ptr = try self.resolveInst(bin_op.lhs);
- const dst_ptr_ty = self.typeOf(bin_op.lhs);
- const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
- .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
- else => null,
+ const dst = try self.resolveInst(bin_op.lhs);
+ const dst_ty = self.typeOf(bin_op.lhs);
+ const dst_locks: [2]?RegisterLock = switch (dst) {
+ .register => |dst_reg| .{ self.register_manager.lockRegAssumeUnused(dst_reg), null },
+ .register_pair => |dst_regs| .{
+ self.register_manager.lockRegAssumeUnused(dst_regs[0]),
+ self.register_manager.lockRegAssumeUnused(dst_regs[1]),
+ },
+ else => .{ null, null },
};
- defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
+ for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
const src_val = try self.resolveInst(bin_op.rhs);
const elem_ty = self.typeOf(bin_op.rhs);
@@ -16612,16 +16872,20 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
const elem_abi_size: u31 = @intCast(elem_ty.abiSize(zcu));
if (elem_abi_size == 1) {
- const ptr: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
- // TODO: this only handles slices stored in the stack
- .slice => dst_ptr,
- .one => dst_ptr,
+ const dst_ptr: MCValue = switch (dst_ty.ptrSize(zcu)) {
+ .slice => switch (dst) {
+ .register_pair => |dst_regs| .{ .register = dst_regs[0] },
+ else => dst,
+ },
+ .one => dst,
.c, .many => unreachable,
};
- const len: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
- // TODO: this only handles slices stored in the stack
- .slice => dst_ptr.address().offset(8).deref(),
- .one => .{ .immediate = dst_ptr_ty.childType(zcu).arrayLen(zcu) },
+ const len: MCValue = switch (dst_ty.ptrSize(zcu)) {
+ .slice => switch (dst) {
+ .register_pair => |dst_regs| .{ .register = dst_regs[1] },
+ else => dst.address().offset(8).deref(),
+ },
+ .one => .{ .immediate = dst_ty.childType(zcu).arrayLen(zcu) },
.c, .many => unreachable,
};
const len_lock: ?RegisterLock = switch (len) {
@@ -16630,20 +16894,25 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
};
defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
- try self.genInlineMemset(ptr, src_val, len, .{ .safety = safety });
+ try self.genInlineMemset(dst_ptr, src_val, len, .{ .safety = safety });
break :result;
}
// Store the first element, and then rely on memcpy copying forwards.
// Length zero requires a runtime check - so we handle arrays specially
// here to elide it.
- switch (dst_ptr_ty.ptrSize(zcu)) {
+ switch (dst_ty.ptrSize(zcu)) {
.slice => {
- const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(zcu);
+ const slice_ptr_ty = dst_ty.slicePtrFieldType(zcu);
- // TODO: this only handles slices stored in the stack
- const ptr = dst_ptr;
- const len = dst_ptr.address().offset(8).deref();
+ const dst_ptr: MCValue = switch (dst) {
+ .register_pair => |dst_regs| .{ .register = dst_regs[0] },
+ else => dst,
+ };
+ const len: MCValue = switch (dst) {
+ .register_pair => |dst_regs| .{ .register = dst_regs[1] },
+ else => dst.address().offset(8).deref(),
+ };
// Used to store the number of elements for comparison.
// 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 {
try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);
const skip_reloc = try self.asmJccReloc(.z, undefined);
- try self.store(slice_ptr_ty, ptr, src_val, .{ .safety = safety });
+ try self.store(slice_ptr_ty, dst_ptr, src_val, .{ .safety = safety });
const second_elem_ptr_reg =
try self.register_manager.allocReg(null, abi.RegisterClass.gp);
@@ -16666,7 +16935,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
defer self.register_manager.unlockReg(second_elem_ptr_lock);
try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
- .reg = try self.copyToTmpRegister(Type.usize, ptr),
+ .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
.off = elem_abi_size,
} }, .{});
@@ -16675,19 +16944,19 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
.{ .i_, .mul },
len_reg,
len_reg,
- Immediate.s(elem_abi_size),
+ .s(elem_abi_size),
);
- try self.genInlineMemcpy(second_elem_ptr_mcv, ptr, len_mcv);
+ try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, len_mcv);
self.performReloc(skip_reloc);
},
.one => {
const elem_ptr_ty = try pt.singleMutPtrType(elem_ty);
- const len = dst_ptr_ty.childType(zcu).arrayLen(zcu);
+ const len = dst_ty.childType(zcu).arrayLen(zcu);
assert(len != 0); // prevented by Sema
- try self.store(elem_ptr_ty, dst_ptr, src_val, .{ .safety = safety });
+ try self.store(elem_ptr_ty, dst, src_val, .{ .safety = safety });
const second_elem_ptr_reg =
try self.register_manager.allocReg(null, abi.RegisterClass.gp);
@@ -16697,12 +16966,12 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
defer self.register_manager.unlockReg(second_elem_ptr_lock);
try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
- .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
+ .reg = try self.copyToTmpRegister(Type.usize, dst),
.off = elem_abi_size,
} }, .{});
const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
- try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);
+ try self.genInlineMemcpy(second_elem_ptr_mcv, dst, bytes_to_copy);
},
.c, .many => unreachable,
}
@@ -16719,48 +16988,72 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
- const dst_ptr = try self.resolveInst(bin_op.lhs);
- const dst_ptr_ty = self.typeOf(bin_op.lhs);
- const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
- .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
- else => null,
+ const dst = try self.resolveInst(bin_op.lhs);
+ const dst_ty = self.typeOf(bin_op.lhs);
+ const dst_locks: [2]?RegisterLock = switch (dst) {
+ .register => |dst_reg| .{ self.register_manager.lockRegAssumeUnused(dst_reg), null },
+ .register_pair => |dst_regs| .{
+ self.register_manager.lockRegAssumeUnused(dst_regs[0]),
+ self.register_manager.lockReg(dst_regs[1]),
+ },
+ else => .{ null, null },
};
- defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
+ for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
- const src_ptr = try self.resolveInst(bin_op.rhs);
- const src_ptr_lock: ?RegisterLock = switch (src_ptr) {
- .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
- else => null,
+ const src = try self.resolveInst(bin_op.rhs);
+ const src_locks: [2]?RegisterLock = switch (src) {
+ .register => |src_reg| .{ self.register_manager.lockReg(src_reg), null },
+ .register_pair => |src_regs| .{
+ self.register_manager.lockRegAssumeUnused(src_regs[0]),
+ self.register_manager.lockRegAssumeUnused(src_regs[1]),
+ },
+ else => .{ null, null },
};
- defer if (src_ptr_lock) |lock| self.register_manager.unlockReg(lock);
+ for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);
- const len: MCValue = switch (dst_ptr_ty.ptrSize(zcu)) {
+ const len: MCValue = switch (dst_ty.ptrSize(zcu)) {
.slice => len: {
const len_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
defer self.register_manager.unlockReg(len_lock);
- try self.asmRegisterMemoryImmediate(
- .{ .i_, .mul },
- len_reg,
- try dst_ptr.address().offset(8).deref().mem(self, .qword),
- Immediate.s(@intCast(dst_ptr_ty.childType(zcu).abiSize(zcu))),
- );
+ switch (dst) {
+ .register_pair => |dst_regs| try self.asmRegisterRegisterImmediate(
+ .{ .i_, .mul },
+ len_reg,
+ dst_regs[1],
+ .s(@intCast(dst_ty.childType(zcu).abiSize(zcu))),
+ ),
+ else => try self.asmRegisterMemoryImmediate(
+ .{ .i_, .mul },
+ len_reg,
+ try dst.address().offset(8).deref().mem(self, .qword),
+ .s(@intCast(dst_ty.childType(zcu).abiSize(zcu))),
+ ),
+ }
break :len .{ .register = len_reg };
},
.one => len: {
- const array_ty = dst_ptr_ty.childType(zcu);
+ const array_ty = dst_ty.childType(zcu);
break :len .{ .immediate = array_ty.arrayLen(zcu) * array_ty.childType(zcu).abiSize(zcu) };
},
.c, .many => unreachable,
};
const len_lock: ?RegisterLock = switch (len) {
- .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
+ .register => |reg| self.register_manager.lockReg(reg),
else => null,
};
defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
- // TODO: dst_ptr and src_ptr could be slices rather than raw pointers
+ const dst_ptr: MCValue = switch (dst) {
+ .register_pair => |dst_regs| .{ .register = dst_regs[0] },
+ else => dst,
+ };
+ const src_ptr: MCValue = switch (src) {
+ .register_pair => |src_regs| .{ .register = src_regs[0] },
+ else => src,
+ };
+
try self.genInlineMemcpy(dst_ptr, src_ptr, len);
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 {
try self.genSetReg(
regs[1],
vector_ty,
- .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) },
+ .{ .immediate = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - vector_len) },
.{},
);
const src_mcv = try self.resolveInst(ty_op.operand);
- const abi_size = @max(math.divCeil(u32, vector_len, 8) catch unreachable, 4);
+ const abi_size = @max(std.math.divCeil(u32, vector_len, 8) catch unreachable, 4);
try self.asmCmovccRegisterRegister(
switch (src_mcv) {
.eflags => |cc| cc,
.register => |src_reg| cc: {
- try self.asmRegisterImmediate(
- .{ ._, .@"test" },
- src_reg.to8(),
- Immediate.u(1),
- );
+ try self.asmRegisterImmediate(.{ ._, .@"test" }, src_reg.to8(), .u(1));
break :cc .nz;
},
else => cc: {
try self.asmMemoryImmediate(
.{ ._, .@"test" },
try src_mcv.mem(self, .byte),
- Immediate.u(1),
+ .u(1),
);
break :cc .nz;
},
@@ -17037,7 +17326,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
.{ if (self.hasFeature(.avx)) .vp_w else .p_w, .shufl },
dst_alias,
dst_alias,
- Immediate.u(0b00_00_00_00),
+ .u(0b00_00_00_00),
);
if (switch (scalar_bits) {
1...8 => vector_len > 4,
@@ -17049,7 +17338,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
.{ if (self.hasFeature(.avx)) .vp_d else .p_d, .shuf },
dst_alias,
dst_alias,
- Immediate.u(if (scalar_bits <= 64) 0b00_00_00_00 else 0b01_00_01_00),
+ .u(if (scalar_bits <= 64) 0b00_00_00_00 else 0b01_00_01_00),
);
break :result .{ .register = dst_reg };
},
@@ -17080,7 +17369,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
dst_reg.to128(),
src_reg.to128(),
src_reg.to128(),
- Immediate.u(0),
+ .u(0),
);
}
break :result .{ .register = dst_reg };
@@ -17095,7 +17384,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
.{ ._ps, .shuf },
dst_reg.to128(),
dst_reg.to128(),
- Immediate.u(0),
+ .u(0),
);
break :result dst_mcv;
}
@@ -17122,14 +17411,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
dst_reg.to128(),
src_reg.to128(),
src_reg.to128(),
- Immediate.u(0),
+ .u(0),
);
try self.asmRegisterRegisterRegisterImmediate(
.{ .v_f128, .insert },
dst_reg.to256(),
dst_reg.to256(),
dst_reg.to128(),
- Immediate.u(1),
+ .u(1),
);
}
}
@@ -17198,7 +17487,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
dst_reg.to256(),
dst_reg.to256(),
dst_reg.to128(),
- Immediate.u(1),
+ .u(1),
);
}
}
@@ -17231,7 +17520,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
dst_reg.to256(),
src_reg.to256(),
src_reg.to128(),
- Immediate.u(1),
+ .u(1),
);
}
break :result .{ .register = dst_reg };
@@ -17308,7 +17597,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
mask_alias,
mask_alias,
mask_reg.to128(),
- Immediate.u(1),
+ .u(1),
);
break :broadcast;
},
@@ -17362,7 +17651,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
.{ if (has_avx) .vp_w else .p_w, .shufl },
mask_alias,
mask_alias,
- Immediate.u(0b00_00_00_00),
+ .u(0b00_00_00_00),
);
if (abi_size <= 8) break :broadcast;
}
@@ -17370,7 +17659,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
.{ if (has_avx) .vp_d else .p_d, .shuf },
mask_alias,
mask_alias,
- Immediate.u(switch (elem_abi_size) {
+ .u(switch (elem_abi_size) {
1...2, 5...8 => 0b01_00_01_00,
3...4 => 0b00_00_00_00,
else => unreachable,
@@ -17649,7 +17938,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
for (mask_elems, 0..) |maybe_mask_elem, elem_index| {
const mask_elem = maybe_mask_elem orelse continue;
const mask_elem_index =
- math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :unpck;
+ std.math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :unpck;
const elem_byte = (elem_index >> 1) * elem_abi_size;
if (mask_elem_index * elem_abi_size != (elem_byte & 0b0111) | @as(u4, switch (variant) {
.unpckl => 0b0000,
@@ -17746,10 +18035,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
} else sources[(elem_index & 0b010) >> 1] = source;
const select_bit: u3 = @intCast((elem_index & 0b011) << 1);
- const select = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
+ const select_mask = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
if (elem_index & 0b100 == 0)
- control |= select
- else if (control & @as(u8, 0b11) << select_bit != select) break :pshufd;
+ control |= select_mask
+ else if (control & @as(u8, 0b11) << select_bit != select_mask) break :pshufd;
}
const operands = [2]Air.Inst.Ref{ extra.a, extra.b };
@@ -17767,7 +18056,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
.{ if (has_avx) .vp_d else .p_d, .shuf },
dst_alias,
try src_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
- Immediate.u(control),
+ .u(control),
) else try self.asmRegisterRegisterImmediate(
.{ if (has_avx) .vp_d else .p_d, .shuf },
dst_alias,
@@ -17775,7 +18064,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
src_mcv.getReg().?
else
try self.copyToTmpRegister(operand_tys[sources[0].?], src_mcv), max_abi_size),
- Immediate.u(control),
+ .u(control),
);
break :result .{ .register = dst_reg };
}
@@ -17797,10 +18086,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
} else sources[(elem_index & 0b010) >> 1] = source;
const select_bit: u3 = @intCast((elem_index & 0b011) << 1);
- const select = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
+ const select_mask = @as(u8, @intCast(mask_elem_index & 0b011)) << select_bit;
if (elem_index & 0b100 == 0)
- control |= select
- else if (control & @as(u8, 0b11) << select_bit != select) break :shufps;
+ control |= select_mask
+ else if (control & @as(u8, 0b11) << select_bit != select_mask) break :shufps;
}
if (sources[0] orelse break :shufps == sources[1] orelse break :shufps) break :shufps;
@@ -17824,7 +18113,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
dst_alias,
registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
- Immediate.u(control),
+ .u(control),
) else try self.asmRegisterRegisterRegisterImmediate(
.{ .v_ps, .shuf },
dst_alias,
@@ -17833,12 +18122,12 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
- Immediate.u(control),
+ .u(control),
) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
.{ ._ps, .shuf },
dst_alias,
try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
- Immediate.u(control),
+ .u(control),
) else try self.asmRegisterRegisterImmediate(
.{ ._ps, .shuf },
dst_alias,
@@ -17846,7 +18135,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
- Immediate.u(control),
+ .u(control),
);
break :result dst_mcv;
}
@@ -17891,7 +18180,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
dst_alias,
registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
- Immediate.u(control),
+ .u(control),
) else try self.asmRegisterRegisterRegisterImmediate(
.{ .v_pd, .shuf },
dst_alias,
@@ -17900,12 +18189,12 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
- Immediate.u(control),
+ .u(control),
) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
.{ ._pd, .shuf },
dst_alias,
try rhs_mcv.mem(self, Memory.Size.fromSize(max_abi_size)),
- Immediate.u(control),
+ .u(control),
) else try self.asmRegisterRegisterImmediate(
.{ ._pd, .shuf },
dst_alias,
@@ -17913,7 +18202,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(operand_tys[sources[1].?], rhs_mcv), max_abi_size),
- Immediate.u(control),
+ .u(control),
);
break :result dst_mcv;
}
@@ -17927,13 +18216,13 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
for (mask_elems, 0..) |maybe_mask_elem, elem_index| {
const mask_elem = maybe_mask_elem orelse continue;
const mask_elem_index =
- math.cast(u4, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blend;
+ std.math.cast(u4, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blend;
if (mask_elem_index != elem_index) break :blend;
- const select = @as(u8, @intFromBool(mask_elem < 0)) << @truncate(elem_index);
+ const select_mask = @as(u8, @intFromBool(mask_elem < 0)) << @truncate(elem_index);
if (elem_index & 0b1000 == 0)
- control |= select
- else if (control & @as(u8, 0b1) << @truncate(elem_index) != select) break :blend;
+ control |= select_mask
+ else if (control & @as(u8, 0b1) << @truncate(elem_index) != select_mask) break :blend;
}
if (!elem_ty.isRuntimeFloat() and self.hasFeature(.avx2)) vpblendd: {
@@ -17961,7 +18250,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
registerAlias(dst_reg, dst_abi_size),
registerAlias(lhs_reg, dst_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else try self.asmRegisterRegisterRegisterImmediate(
.{ .vp_d, .blend },
registerAlias(dst_reg, dst_abi_size),
@@ -17970,7 +18259,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
- Immediate.u(expanded_control),
+ .u(expanded_control),
);
break :result .{ .register = dst_reg };
}
@@ -18016,7 +18305,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
else
dst_reg, dst_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else try self.asmRegisterRegisterRegisterImmediate(
.{ .vp_w, .blend },
registerAlias(dst_reg, dst_abi_size),
@@ -18028,12 +18317,12 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
.{ .p_w, .blend },
registerAlias(dst_reg, dst_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else try self.asmRegisterRegisterImmediate(
.{ .p_w, .blend },
registerAlias(dst_reg, dst_abi_size),
@@ -18041,7 +18330,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
- Immediate.u(expanded_control),
+ .u(expanded_control),
);
break :result .{ .register = dst_reg };
}
@@ -18077,7 +18366,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
else
dst_reg, dst_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else try self.asmRegisterRegisterRegisterImmediate(
switch (elem_abi_size) {
4 => .{ .v_ps, .blend },
@@ -18093,7 +18382,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
switch (elem_abi_size) {
4 => .{ ._ps, .blend },
@@ -18102,7 +18391,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
},
registerAlias(dst_reg, dst_abi_size),
try rhs_mcv.mem(self, Memory.Size.fromSize(dst_abi_size)),
- Immediate.u(expanded_control),
+ .u(expanded_control),
) else try self.asmRegisterRegisterImmediate(
switch (elem_abi_size) {
4 => .{ ._ps, .blend },
@@ -18114,7 +18403,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
rhs_mcv.getReg().?
else
try self.copyToTmpRegister(dst_ty, rhs_mcv), dst_abi_size),
- Immediate.u(expanded_control),
+ .u(expanded_control),
);
break :result .{ .register = dst_reg };
}
@@ -18138,7 +18427,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
) |*select_mask_elem, maybe_mask_elem, elem_index| {
const mask_elem = maybe_mask_elem orelse continue;
const mask_elem_index =
- math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blendv;
+ std.math.cast(u5, if (mask_elem < 0) ~mask_elem else mask_elem) orelse break :blendv;
if (mask_elem_index != elem_index) break :blendv;
select_mask_elem.* = (if (mask_elem < 0)
@@ -18380,7 +18669,9 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
break :result null;
}) orelse return self.fail("TODO implement airShuffle from {} and {} to {} with {}", .{
- lhs_ty.fmt(pt), rhs_ty.fmt(pt), dst_ty.fmt(pt),
+ lhs_ty.fmt(pt),
+ rhs_ty.fmt(pt),
+ dst_ty.fmt(pt),
Value.fromInterned(extra.mask).fmtValue(pt),
});
return self.finishAir(inst, result, .{ extra.a, extra.b, .none });
@@ -18397,7 +18688,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
try self.spillEflagsIfOccupied();
const operand_mcv = try self.resolveInst(reduce.operand);
- const mask_len = (math.cast(u6, operand_ty.vectorLen(zcu)) orelse
+ const mask_len = (std.math.cast(u6, operand_ty.vectorLen(zcu)) orelse
return self.fail("TODO implement airReduce for {}", .{operand_ty.fmt(pt)}));
const mask = (@as(u64, 1) << mask_len) - 1;
const abi_size: u32 = @intCast(operand_ty.abiSize(zcu));
@@ -18406,7 +18697,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
if (operand_mcv.isMemory()) try self.asmMemoryImmediate(
.{ ._, .@"test" },
try operand_mcv.mem(self, Memory.Size.fromSize(abi_size)),
- Immediate.u(mask),
+ .u(mask),
) else {
const operand_reg = registerAlias(if (operand_mcv.isRegister())
operand_mcv.getReg().?
@@ -18415,7 +18706,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
if (mask_len < abi_size * 8) try self.asmRegisterImmediate(
.{ ._, .@"test" },
operand_reg,
- Immediate.u(mask),
+ .u(mask),
) else try self.asmRegisterRegister(
.{ ._, .@"test" },
operand_reg,
@@ -18431,7 +18722,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
try self.asmRegister(.{ ._, .not }, tmp_reg);
if (mask_len < abi_size * 8)
- try self.asmRegisterImmediate(.{ ._, .@"test" }, tmp_reg, Immediate.u(mask))
+ try self.asmRegisterImmediate(.{ ._, .@"test" }, tmp_reg, .u(mask))
else
try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_reg, tmp_reg);
break :result .{ .eflags = .z };
@@ -18579,12 +18870,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
try self.asmRegisterImmediate(
.{ ._, .@"and" },
registerAlias(elem_reg, @min(result_size, 4)),
- Immediate.u(1),
+ .u(1),
);
if (elem_i > 0) try self.asmRegisterImmediate(
.{ ._l, .sh },
registerAlias(elem_reg, result_size),
- Immediate.u(@intCast(elem_i)),
+ .u(@intCast(elem_i)),
);
try self.asmRegisterRegister(
.{ ._, .@"or" },
@@ -18748,8 +19039,8 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
lock.* = self.register_manager.lockRegAssumeUnused(reg);
}
- const mir_tag = @as(?Mir.Inst.FixedTag, if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or
- mem.eql(u2, &order, &.{ 3, 1, 2 }))
+ const mir_tag = @as(?Mir.Inst.FixedTag, if (std.mem.eql(u2, &order, &.{ 1, 3, 2 }) or
+ std.mem.eql(u2, &order, &.{ 3, 1, 2 }))
switch (ty.zigTypeTag(zcu)) {
.float => switch (ty.floatBits(self.target.*)) {
32 => .{ .v_ss, .fmadd132 },
@@ -18776,7 +19067,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
},
else => unreachable,
}
- else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 }))
+ else if (std.mem.eql(u2, &order, &.{ 2, 1, 3 }) or std.mem.eql(u2, &order, &.{ 1, 2, 3 }))
switch (ty.zigTypeTag(zcu)) {
.float => switch (ty.floatBits(self.target.*)) {
32 => .{ .v_ss, .fmadd213 },
@@ -18803,7 +19094,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
},
else => unreachable,
}
- else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 }))
+ else if (std.mem.eql(u2, &order, &.{ 2, 3, 1 }) or std.mem.eql(u2, &order, &.{ 3, 2, 1 }))
switch (ty.zigTypeTag(zcu)) {
.float => switch (ty.floatBits(self.target.*)) {
32 => .{ .v_ss, .fmadd231 },
@@ -18953,13 +19244,13 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
const overflow_arg_area: MCValue = .{ .indirect = .{ .reg = ptr_arg_list_reg, .off = 8 } };
const reg_save_area: MCValue = .{ .indirect = .{ .reg = ptr_arg_list_reg, .off = 16 } };
- const classes = mem.sliceTo(&abi.classifySystemV(promote_ty, zcu, self.target.*, .arg), .none);
+ const classes = std.mem.sliceTo(&abi.classifySystemV(promote_ty, zcu, self.target.*, .arg), .none);
switch (classes[0]) {
.integer => {
assert(classes.len == 1);
try self.genSetReg(offset_reg, Type.c_uint, gp_offset, .{});
- try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
+ try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(
abi.SysV.c_abi_int_param_regs.len * 8,
));
const mem_reloc = try self.asmJccReloc(.ae, undefined);
@@ -19007,7 +19298,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
assert(classes.len == 1);
try self.genSetReg(offset_reg, Type.c_uint, fp_offset, .{});
- try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
+ try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, .u(
abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,
));
const mem_reloc = try self.asmJccReloc(.ae, undefined);
@@ -19055,9 +19346,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
assert(classes.len == 1);
unreachable;
},
- else => return self.fail("TODO implement c_va_arg for {} on SysV", .{
- promote_ty.fmt(pt),
- }),
+ else => return self.fail("TODO implement c_va_arg for {} on SysV", .{promote_ty.fmt(pt)}),
}
if (unused) break :result .unreach;
@@ -19194,7 +19483,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
.immediate => |imm| {
// This immediate is unsigned.
const U = std.meta.Int(.unsigned, ti.bits - @intFromBool(ti.signedness == .signed));
- if (imm >= math.maxInt(U)) {
+ if (imm >= std.math.maxInt(U)) {
return MCValue{ .register = try self.copyToTmpRegister(Type.usize, mcv) };
}
},
@@ -19226,7 +19515,7 @@ const CallMCValues = struct {
args: []MCValue,
return_value: InstTracking,
stack_byte_count: u31,
- stack_align: Alignment,
+ stack_align: InternPool.Alignment,
gp_count: u32,
fp_count: u32,
@@ -19303,7 +19592,7 @@ fn resolveCallingConventionValues(
var ret_tracking_i: usize = 0;
const classes = switch (resolved_cc) {
- .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
+ .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, self.target.*, .ret), .none),
.x86_64_win => &.{abi.classifyWindows(ret_ty, zcu)},
else => unreachable,
};
@@ -19378,7 +19667,7 @@ fn resolveCallingConventionValues(
var arg_mcv_i: usize = 0;
const classes = switch (resolved_cc) {
- .x86_64_sysv => mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
+ .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .arg), .none),
.x86_64_win => &.{abi.classifyWindows(ty, zcu)},
else => unreachable,
};
@@ -19435,7 +19724,7 @@ fn resolveCallingConventionValues(
const frame_elem_align = 8;
const frame_elems_len = ty.vectorLen(zcu) - remaining_param_int_regs;
- const frame_elem_size = mem.alignForward(
+ const frame_elem_size = std.mem.alignForward(
u64,
ty.childType(zcu).abiSize(zcu),
frame_elem_align,
@@ -19443,7 +19732,7 @@ fn resolveCallingConventionValues(
const frame_size: u31 = @intCast(frame_elems_len * frame_elem_size);
result.stack_byte_count =
- mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
+ std.mem.alignForward(u31, result.stack_byte_count, frame_elem_align);
arg_mcv[arg_mcv_i] = .{ .elementwise_regs_then_frame = .{
.regs = remaining_param_int_regs,
.frame_off = @intCast(result.stack_byte_count),
@@ -19461,19 +19750,14 @@ fn resolveCallingConventionValues(
continue;
}
- const param_size: u31 = @intCast(ty.abiSize(zcu));
const param_align = ty.abiAlignment(zcu).max(.@"8");
- result.stack_byte_count = mem.alignForward(
- u31,
- result.stack_byte_count,
- @intCast(param_align.toByteUnits().?),
- );
+ result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
result.stack_align = result.stack_align.max(param_align);
arg.* = .{ .load_frame = .{
.index = stack_frame_base,
.off = result.stack_byte_count,
} };
- result.stack_byte_count += param_size;
+ result.stack_byte_count += @intCast(ty.abiSize(zcu));
}
assert(param_int_reg_i <= 6);
result.gp_count = param_int_reg_i;
@@ -19509,19 +19793,14 @@ fn resolveCallingConventionValues(
arg.* = .none;
continue;
}
- const param_size: u31 = @intCast(ty.abiSize(zcu));
const param_align = ty.abiAlignment(zcu);
- result.stack_byte_count = mem.alignForward(
- u31,
- result.stack_byte_count,
- @intCast(param_align.toByteUnits().?),
- );
+ result.stack_byte_count = @intCast(param_align.forward(result.stack_byte_count));
result.stack_align = result.stack_align.max(param_align);
arg.* = .{ .load_frame = .{
.index = stack_frame_base,
.off = result.stack_byte_count,
} };
- result.stack_byte_count += param_size;
+ result.stack_byte_count += @intCast(ty.abiSize(zcu));
}
},
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
return error.CodegenFail;
}
-fn failMsg(self: *Self, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {
+fn failMsg(self: *Self, msg: *Zcu.ErrorMsg) error{ OutOfMemory, CodegenFail } {
@branchHint(.cold);
const zcu = self.pt.zcu;
switch (self.owner) {
@@ -19603,8 +19882,7 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
}
fn memSize(self: *Self, ty: Type) Memory.Size {
- const pt = self.pt;
- const zcu = pt.zcu;
+ const zcu = self.pt.zcu;
return switch (ty.zigTypeTag(zcu)) {
.float => Memory.Size.fromBitSize(ty.floatBits(self.target.*)),
else => Memory.Size.fromSize(@intCast(ty.abiSize(zcu))),
@@ -19614,7 +19892,7 @@ fn memSize(self: *Self, ty: Type) Memory.Size {
fn splitType(self: *Self, ty: Type) ![2]Type {
const pt = self.pt;
const zcu = pt.zcu;
- const classes = mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
+ const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none);
var parts: [2]Type = undefined;
if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
part.* = switch (class) {
@@ -19648,7 +19926,7 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
.signedness = .unsigned,
.bits = @intCast(ty.bitSize(zcu)),
};
- const shift = math.cast(u6, 64 - int_info.bits % 64) orelse return;
+ const shift = std.math.cast(u6, 64 - int_info.bits % 64) orelse return;
try self.spillEflagsIfOccupied();
switch (int_info.signedness) {
.signed => {
@@ -19690,8 +19968,7 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
}
fn regBitSize(self: *Self, ty: Type) u64 {
- const pt = self.pt;
- const zcu = pt.zcu;
+ const zcu = self.pt.zcu;
const abi_size = ty.abiSize(zcu);
return switch (ty.zigTypeTag(zcu)) {
else => switch (abi_size) {
@@ -19713,14 +19990,14 @@ fn regExtraBits(self: *Self, ty: Type) u64 {
return self.regBitSize(ty) - ty.bitSize(self.pt.zcu);
}
-fn hasFeature(self: *Self, feature: Target.x86.Feature) bool {
- return Target.x86.featureSetHas(self.target.cpu.features, feature);
+fn hasFeature(self: *Self, feature: std.Target.x86.Feature) bool {
+ return std.Target.x86.featureSetHas(self.target.cpu.features, feature);
}
fn hasAnyFeatures(self: *Self, features: anytype) bool {
- return Target.x86.featureSetHasAny(self.target.cpu.features, features);
+ return std.Target.x86.featureSetHasAny(self.target.cpu.features, features);
}
fn hasAllFeatures(self: *Self, features: anytype) bool {
- return Target.x86.featureSetHasAll(self.target.cpu.features, features);
+ return std.Target.x86.featureSetHasAll(self.target.cpu.features, features);
}
fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
@@ -19732,9 +20009,13 @@ fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
const pt = self.pt;
const zcu = pt.zcu;
- return switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
- .loop_switch_br => self.typeOf(self.air.unwrapSwitch(inst).operand),
- else => self.air.typeOfIndex(inst, &zcu.intern_pool),
+ const temp: Temp = .{ .index = inst };
+ return switch (temp.unwrap(self)) {
+ .ref => switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
+ .loop_switch_br => self.typeOf(self.air.unwrapSwitch(inst).operand),
+ else => self.air.typeOfIndex(inst, &zcu.intern_pool),
+ },
+ .temp => temp.typeOf(self),
};
}
@@ -19815,3 +20096,613 @@ fn promoteVarArg(self: *Self, ty: Type) Type {
},
}
}
+
+// ====================================== rewrite starts here ======================================
+
+const Temp = struct {
+ index: Air.Inst.Index,
+
+ fn unwrap(temp: Temp, self: *Self) union(enum) {
+ ref: Air.Inst.Ref,
+ temp: Index,
+ } {
+ switch (temp.index.unwrap()) {
+ .ref => |ref| return .{ .ref = ref },
+ .target => |target_index| {
+ const temp_index: Index = @enumFromInt(target_index);
+ assert(temp_index.isValid(self));
+ return .{ .temp = temp_index };
+ },
+ }
+ }
+
+ fn typeOf(temp: Temp, self: *Self) Type {
+ return switch (temp.unwrap(self)) {
+ .ref => |ref| self.typeOf(ref),
+ .temp => |temp_index| temp_index.typeOf(self),
+ };
+ }
+
+ fn isMut(temp: Temp, self: *Self) bool {
+ return temp.unwrap(self) == .temp;
+ }
+
+ fn tracking(temp: Temp, self: *Self) InstTracking {
+ return self.inst_tracking.get(temp.index).?;
+ }
+
+ fn getOffset(temp: Temp, off: i32, self: *Self) !Temp {
+ const new_temp_index = self.next_temp_index;
+ self.temp_type[@intFromEnum(new_temp_index)] = Type.usize;
+ self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
+ switch (temp.tracking(self).short) {
+ else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
+ .register => |reg| {
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
+ .base = .{ .reg = reg.to64() },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = off,
+ } },
+ });
+ },
+ .register_offset => |reg_off| {
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
+ .base = .{ .reg = reg_off.reg.to64() },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = reg_off.off + off,
+ } },
+ });
+ },
+ .lea_symbol => |sym_off| new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_symbol = .{
+ .sym_index = sym_off.sym_index,
+ .off = sym_off.off + off,
+ } }),
+ .load_frame => |frame_addr| {
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register_offset = .{
+ .reg = new_reg,
+ .off = off,
+ } });
+ try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
+ .base = .{ .frame = frame_addr.index },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = frame_addr.off,
+ } },
+ });
+ },
+ .lea_frame => |frame_addr| new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_frame = .{
+ .index = frame_addr.index,
+ .off = frame_addr.off + off,
+ } }),
+ }
+ return .{ .index = new_temp_index.toIndex() };
+ }
+
+ fn toOffset(temp: *Temp, off: i32, self: *Self) !void {
+ if (off == 0) return;
+ switch (temp.unwrap(self)) {
+ .ref => {},
+ .temp => |temp_index| {
+ const temp_tracking = temp_index.tracking(self);
+ switch (temp_tracking.short) {
+ else => {},
+ .register => |reg| {
+ try self.freeValue(temp_tracking.long);
+ temp_tracking.* = InstTracking.init(.{ .register_offset = .{
+ .reg = reg,
+ .off = off,
+ } });
+ return;
+ },
+ .register_offset => |reg_off| {
+ try self.freeValue(temp_tracking.long);
+ temp_tracking.* = InstTracking.init(.{ .register_offset = .{
+ .reg = reg_off.reg,
+ .off = reg_off.off + off,
+ } });
+ return;
+ },
+ .lea_symbol => |sym_off| {
+ assert(std.meta.eql(temp_tracking.long.lea_symbol, sym_off));
+ temp_tracking.* = InstTracking.init(.{ .lea_symbol = .{
+ .sym_index = sym_off.sym_index,
+ .off = sym_off.off + off,
+ } });
+ return;
+ },
+ .lea_frame => |frame_addr| {
+ assert(std.meta.eql(temp_tracking.long.lea_frame, frame_addr));
+ temp_tracking.* = InstTracking.init(.{ .lea_frame = .{
+ .index = frame_addr.index,
+ .off = frame_addr.off + off,
+ } });
+ return;
+ },
+ }
+ },
+ }
+ const new_temp = try temp.getOffset(off, self);
+ try temp.die(self);
+ temp.* = new_temp;
+ }
+
+ fn getLimb(temp: Temp, limb_index: u28, self: *Self) !Temp {
+ const new_temp_index = self.next_temp_index;
+ self.temp_type[@intFromEnum(new_temp_index)] = Type.usize;
+ switch (temp.tracking(self).short) {
+ else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
+ .immediate => |imm| {
+ assert(limb_index == 0);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .immediate = imm });
+ },
+ .register => |reg| {
+ assert(limb_index == 0);
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), reg.to64());
+ },
+ .register_pair => |regs| {
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), regs[limb_index].to64());
+ },
+ .register_offset => |reg_off| {
+ assert(limb_index == 0);
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
+ .base = .{ .reg = reg_off.reg.to64() },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = reg_off.off + @as(u31, limb_index) * 8,
+ } },
+ });
+ },
+ .load_symbol => |sym_off| {
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
+ .base = .{ .reloc = sym_off.sym_index },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = sym_off.off + @as(u31, limb_index) * 8,
+ } },
+ });
+ },
+ .lea_symbol => |sym_off| {
+ assert(limb_index == 0);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_symbol = sym_off });
+ },
+ .load_frame => |frame_addr| {
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
+ .base = .{ .frame = frame_addr.index },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = frame_addr.off + @as(u31, limb_index) * 8,
+ } },
+ });
+ },
+ .lea_frame => |frame_addr| {
+ assert(limb_index == 0);
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .lea_frame = frame_addr });
+ },
+ }
+ self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
+ return .{ .index = new_temp_index.toIndex() };
+ }
+
+ fn toLimb(temp: *Temp, limb_index: u28, self: *Self) !void {
+ switch (temp.unwrap(self)) {
+ .ref => {},
+ .temp => |temp_index| {
+ const temp_tracking = temp_index.tracking(self);
+ switch (temp_tracking.short) {
+ else => {},
+ .register, .lea_symbol, .lea_frame => {
+ assert(limb_index == 0);
+ self.temp_type[@intFromEnum(temp_index)] = Type.usize;
+ return;
+ },
+ .register_pair => |regs| {
+ switch (temp_tracking.long) {
+ .none, .reserved_frame => {},
+ else => temp_tracking.long =
+ temp_tracking.long.address().offset(@as(u31, limb_index) * 8).deref(),
+ }
+ for (regs, 0..) |reg, reg_index| if (reg_index != limb_index)
+ self.register_manager.freeReg(reg);
+ temp_tracking.* = InstTracking.init(.{ .register = regs[limb_index] });
+ self.temp_type[@intFromEnum(temp_index)] = Type.usize;
+ return;
+ },
+ .load_symbol => |sym_off| {
+ assert(std.meta.eql(temp_tracking.long.load_symbol, sym_off));
+ temp_tracking.* = InstTracking.init(.{ .load_symbol = .{
+ .sym_index = sym_off.sym_index,
+ .off = sym_off.off + @as(u31, limb_index) * 8,
+ } });
+ self.temp_type[@intFromEnum(temp_index)] = Type.usize;
+ return;
+ },
+ .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) {
+ assert(std.meta.eql(temp_tracking.long.load_frame, frame_addr));
+ temp_tracking.* = InstTracking.init(.{ .load_frame = .{
+ .index = frame_addr.index,
+ .off = frame_addr.off + @as(u31, limb_index) * 8,
+ } });
+ self.temp_type[@intFromEnum(temp_index)] = Type.usize;
+ return;
+ },
+ }
+ },
+ }
+ const new_temp = try temp.getLimb(limb_index, self);
+ try temp.die(self);
+ temp.* = new_temp;
+ }
+
+ fn toReg(temp: *Temp, new_reg: Register, self: *Self) !bool {
+ const val, const ty = switch (temp.unwrap(self)) {
+ .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) },
+ .temp => |temp_index| val: {
+ const temp_tracking = temp_index.tracking(self);
+ if (temp_tracking.short == .register and
+ temp_tracking.short.register == new_reg) return false;
+ break :val .{ temp_tracking.short, temp_index.typeOf(self) };
+ },
+ };
+ const new_temp_index = self.next_temp_index;
+ self.temp_type[@intFromEnum(new_temp_index)] = ty;
+ try self.genSetReg(new_reg, ty, val, .{});
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try temp.die(self);
+ self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
+ temp.* = .{ .index = new_temp_index.toIndex() };
+ return true;
+ }
+
+ fn toAnyReg(temp: *Temp, self: *Self) !bool {
+ const val, const ty = switch (temp.unwrap(self)) {
+ .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) },
+ .temp => |temp_index| val: {
+ const temp_tracking = temp_index.tracking(self);
+ if (temp_tracking.short == .register) return false;
+ break :val .{ temp_tracking.short, temp_index.typeOf(self) };
+ },
+ };
+ const new_temp_index = self.next_temp_index;
+ self.temp_type[@intFromEnum(new_temp_index)] = ty;
+ const new_reg =
+ try self.register_manager.allocReg(new_temp_index.toIndex(), self.regClassForType(ty));
+ try self.genSetReg(new_reg, ty, val, .{});
+ new_temp_index.tracking(self).* = InstTracking.init(.{ .register = new_reg });
+ try temp.die(self);
+ self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
+ temp.* = .{ .index = new_temp_index.toIndex() };
+ return true;
+ }
+
+ fn toPair(first_temp: *Temp, second_temp: *Temp, self: *Self) !void {
+ while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| {
+ if (try part_temp.toAnyReg(self)) break;
+ } else break;
+ const first_temp_tracking = first_temp.unwrap(self).temp.tracking(self);
+ const second_temp_tracking = second_temp.unwrap(self).temp.tracking(self);
+ const result: MCValue = .{ .register_pair = .{
+ first_temp_tracking.short.register,
+ second_temp_tracking.short.register,
+ } };
+ const result_temp_index = self.next_temp_index;
+ const result_temp: Temp = .{ .index = result_temp_index.toIndex() };
+ assert(self.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking));
+ assert(self.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking));
+ self.temp_type[@intFromEnum(result_temp_index)] = Type.slice_const_u8;
+ result_temp_index.tracking(self).* = InstTracking.init(result);
+ first_temp.* = result_temp;
+ }
+
+ fn toLea(temp: *Temp, self: *Self) !bool {
+ switch (temp.tracking(self).short) {
+ .none,
+ .unreach,
+ .dead,
+ .undef,
+ .eflags,
+ .register_pair,
+ .register_overflow,
+ .elementwise_regs_then_frame,
+ .reserved_frame,
+ .air_ref,
+ => unreachable, // not a valid pointer
+ .immediate,
+ .register,
+ .register_offset,
+ .lea_direct,
+ .lea_got,
+ .lea_tlv,
+ .lea_frame,
+ => return false,
+ .memory,
+ .indirect,
+ .load_symbol,
+ .load_direct,
+ .load_got,
+ .load_tlv,
+ .load_frame,
+ => return temp.toAnyReg(self),
+ .lea_symbol => |sym_off| {
+ const off = sym_off.off;
+ if (off == 0) return false;
+ try temp.toOffset(-off, self);
+ while (try temp.toAnyReg(self)) {}
+ try temp.toOffset(off, self);
+ return true;
+ },
+ }
+ }
+
+ fn load(ptr: *Temp, val_ty: Type, self: *Self) !Temp {
+ const val_abi_size: u32 = @intCast(val_ty.abiSize(self.pt.zcu));
+ const val = try self.tempAlloc(val_ty);
+ switch (val.tracking(self).short) {
+ else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
+ .register => |val_reg| {
+ while (try ptr.toLea(self)) {}
+ switch (val_reg.class()) {
+ .general_purpose => try self.asmRegisterMemory(
+ .{ ._, .mov },
+ registerAlias(val_reg, val_abi_size),
+ try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)),
+ ),
+ else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
+ }
+ },
+ .load_frame => |val_frame_addr| {
+ var val_ptr = try self.tempFromValue(Type.usize, .{ .lea_frame = val_frame_addr });
+ var len = try self.tempFromValue(Type.usize, .{ .immediate = val_abi_size });
+ try val_ptr.memcpy(ptr, &len, self);
+ try val_ptr.die(self);
+ try len.die(self);
+ },
+ }
+ return val;
+ }
+
+ fn store(ptr: *Temp, val: *Temp, self: *Self) !void {
+ const val_ty = val.typeOf(self);
+ const val_abi_size: u32 = @intCast(val_ty.abiSize(self.pt.zcu));
+ val: switch (val.tracking(self).short) {
+ else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
+ .immediate => |imm| if (std.math.cast(i32, imm)) |s| {
+ while (try ptr.toLea(self)) {}
+ try self.asmMemoryImmediate(
+ .{ ._, .mov },
+ try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)),
+ .s(s),
+ );
+ } else continue :val .{ .register = undefined },
+ .register => {
+ while (try ptr.toLea(self) or try val.toAnyReg(self)) {}
+ const val_reg = val.tracking(self).short.register;
+ switch (val_reg.class()) {
+ .general_purpose => try self.asmMemoryRegister(
+ .{ ._, .mov },
+ try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)),
+ registerAlias(val_reg, val_abi_size),
+ ),
+ else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }),
+ }
+ },
+ }
+ }
+
+ fn memcpy(dst: *Temp, src: *Temp, len: *Temp, self: *Self) !void {
+ while (true) for ([_]*Temp{ dst, src, len }, [_]Register{ .rdi, .rsi, .rcx }) |temp, reg| {
+ if (try temp.toReg(reg, self)) break;
+ } else break;
+ try self.asmOpOnly(.{ .@"rep _sb", .mov });
+ }
+
+ fn moveTo(temp: Temp, inst: Air.Inst.Index, self: *Self) !void {
+ if (self.liveness.isUnused(inst)) try temp.die(self) else switch (temp.unwrap(self)) {
+ .ref => {
+ const result = try self.allocRegOrMem(inst, true);
+ try self.genCopy(self.typeOfIndex(inst), result, temp.tracking(self).short, .{});
+ tracking_log.debug("{} => {} (birth)", .{ inst, result });
+ self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(result));
+ },
+ .temp => |temp_index| {
+ const temp_tracking = temp_index.tracking(self);
+ tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short });
+ self.inst_tracking.putAssumeCapacityNoClobber(inst, temp_tracking.*);
+ assert(self.reuseTemp(inst, temp_index.toIndex(), temp_tracking));
+ },
+ }
+ }
+
+ fn die(temp: Temp, self: *Self) !void {
+ switch (temp.unwrap(self)) {
+ .ref => {},
+ .temp => |temp_index| try temp_index.tracking(self).die(self, temp_index.toIndex()),
+ }
+ }
+
+ const Index = enum(u4) {
+ _,
+
+ fn toIndex(index: Index) Air.Inst.Index {
+ return Air.Inst.Index.fromTargetIndex(@intFromEnum(index));
+ }
+
+ fn fromIndex(index: Air.Inst.Index) Index {
+ return @enumFromInt(index.toTargetIndex());
+ }
+
+ fn tracking(index: Index, self: *Self) *InstTracking {
+ return &self.inst_tracking.values()[@intFromEnum(index)];
+ }
+
+ fn isValid(index: Index, self: *Self) bool {
+ return index.tracking(self).short != .dead;
+ }
+
+ fn typeOf(index: Index, self: *Self) Type {
+ assert(index.isValid(self));
+ return self.temp_type[@intFromEnum(index)];
+ }
+
+ const max = std.math.maxInt(@typeInfo(Index).@"enum".tag_type);
+ const Set = std.StaticBitSet(max);
+ const SafetySet = if (std.debug.runtime_safety) Set else struct {
+ inline fn initEmpty() @This() {
+ return .{};
+ }
+
+ inline fn isSet(_: @This(), index: usize) bool {
+ assert(index < max);
+ return true;
+ }
+
+ inline fn set(_: @This(), index: usize) void {
+ assert(index < max);
+ }
+
+ inline fn eql(_: @This(), _: @This()) bool {
+ return true;
+ }
+ };
+ };
+};
+
+fn resetTemps(self: *Self) void {
+ for (0..@intFromEnum(self.next_temp_index)) |temp_index| {
+ const temp: Temp.Index = @enumFromInt(temp_index);
+ assert(!temp.isValid(self));
+ self.temp_type[temp_index] = undefined;
+ }
+ self.next_temp_index = @enumFromInt(0);
+}
+
+fn reuseTemp(
+ self: *Self,
+ new_inst: Air.Inst.Index,
+ old_inst: Air.Inst.Index,
+ tracking: *InstTracking,
+) bool {
+ switch (tracking.short) {
+ .register,
+ .register_pair,
+ .register_offset,
+ .register_overflow,
+ => for (tracking.short.getRegs()) |tracked_reg| {
+ if (RegisterManager.indexOfRegIntoTracked(tracked_reg)) |tracked_index| {
+ self.register_manager.registers[tracked_index] = new_inst;
+ }
+ },
+ .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,
+ else => {},
+ }
+ switch (tracking.short) {
+ .eflags, .register_overflow => self.eflags_inst = new_inst,
+ else => {},
+ }
+ tracking.reuse(self, new_inst, old_inst);
+ return true;
+}
+
+fn tempAlloc(self: *Self, ty: Type) !Temp {
+ const temp_index = self.next_temp_index;
+ temp_index.tracking(self).* = InstTracking.init(try self.allocRegOrMemAdvanced(ty, temp_index.toIndex(), true));
+ self.temp_type[@intFromEnum(temp_index)] = ty;
+ self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
+ return .{ .index = temp_index.toIndex() };
+}
+
+fn tempFromValue(self: *Self, ty: Type, value: MCValue) !Temp {
+ const temp_index = self.next_temp_index;
+ temp_index.tracking(self).* = InstTracking.init(value);
+ self.temp_type[@intFromEnum(temp_index)] = ty;
+ try self.getValue(value, temp_index.toIndex());
+ self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
+ return .{ .index = temp_index.toIndex() };
+}
+
+fn tempFromOperand(
+ self: *Self,
+ inst: Air.Inst.Index,
+ op_index: Liveness.OperandInt,
+ op_ref: Air.Inst.Ref,
+) !Temp {
+ const zcu = self.pt.zcu;
+ const ip = &zcu.intern_pool;
+
+ if (!self.liveness.operandDies(inst, op_index)) {
+ if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst };
+ const val = op_ref.toInterned().?;
+ const gop = try self.const_tracking.getOrPut(self.gpa, val);
+ if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(init: {
+ const const_mcv = try self.genTypedValue(Value.fromInterned(val));
+ switch (const_mcv) {
+ .lea_tlv => |tlv_sym| switch (self.bin_file.tag) {
+ .elf, .macho => {
+ if (self.mod.pic) {
+ try self.spillRegisters(&.{ .rdi, .rax });
+ } else {
+ try self.spillRegisters(&.{.rax});
+ }
+ const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{
+ .size = 8,
+ .alignment = .@"8",
+ }));
+ try self.genSetMem(
+ .{ .frame = frame_index },
+ 0,
+ Type.usize,
+ .{ .lea_symbol = .{ .sym_index = tlv_sym } },
+ .{},
+ );
+ break :init .{ .load_frame = .{ .index = frame_index } };
+ },
+ else => break :init const_mcv,
+ },
+ else => break :init const_mcv,
+ }
+ });
+ return self.tempFromValue(Type.fromInterned(ip.typeOf(val)), gop.value_ptr.short);
+ }
+
+ const temp_index = self.next_temp_index;
+ const temp: Temp = .{ .index = temp_index.toIndex() };
+ const op_inst = op_ref.toIndex().?;
+ const tracking = self.getResolvedInstValue(op_inst);
+ temp_index.tracking(self).* = tracking.*;
+ if (!self.reuseTemp(temp.index, op_inst, tracking)) return .{ .index = op_ref.toIndex().? };
+ self.temp_type[@intFromEnum(temp_index)] = self.typeOf(op_ref);
+ self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1);
+ return temp;
+}
+
+inline fn tempsFromOperands(self: *Self, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp {
+ var temps: [op_refs.len]Temp = undefined;
+ inline for (&temps, 0.., op_refs) |*temp, op_index, op_ref| {
+ temp.* = try self.tempFromOperand(inst, op_index, op_ref);
+ }
+ return temps;
+}
src/Air.zig
@@ -893,14 +893,38 @@ pub const Inst = struct {
pub const Index = enum(u32) {
_,
- pub fn toRef(i: Index) Inst.Ref {
- assert(@intFromEnum(i) >> 31 == 0);
- return @enumFromInt((1 << 31) | @intFromEnum(i));
+ pub fn unwrap(index: Index) union(enum) { ref: Inst.Ref, target: u31 } {
+ const low_index: u31 = @truncate(@intFromEnum(index));
+ return switch (@as(u1, @intCast(@intFromEnum(index) >> 31))) {
+ 0 => .{ .ref = @enumFromInt(@as(u32, 1 << 31) | low_index) },
+ 1 => .{ .target = low_index },
+ };
+ }
+
+ pub fn toRef(index: Index) Inst.Ref {
+ return index.unwrap().ref;
+ }
+
+ pub fn fromTargetIndex(index: u31) Index {
+ return @enumFromInt((1 << 31) | @as(u32, index));
+ }
+
+ pub fn toTargetIndex(index: Index) u31 {
+ return index.unwrap().target;
}
- pub fn toTargetIndex(i: Index) u31 {
- assert(@intFromEnum(i) >> 31 == 1);
- return @truncate(@intFromEnum(i));
+ pub fn format(
+ index: Index,
+ comptime _: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: anytype,
+ ) @TypeOf(writer).Error!void {
+ try writer.writeByte('%');
+ switch (index.unwrap()) {
+ .ref => {},
+ .target => try writer.writeByte('t'),
+ }
+ try writer.print("{d}", .{@as(u31, @truncate(@intFromEnum(index)))});
}
};
src/Compilation.zig
@@ -3067,6 +3067,7 @@ pub fn saveState(comp: *Compilation) !void {
// linker state
switch (lf.tag) {
.wasm => {
+ dev.check(link.File.Tag.wasm.devFeature());
const wasm = lf.cast(.wasm).?;
const is_obj = comp.config.output_mode == .Obj;
try bufs.ensureUnusedCapacity(85);
src/Liveness.zig
@@ -202,14 +202,6 @@ pub fn operandDies(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) bool
return (l.tomb_bits[usize_index] & mask) != 0;
}
-pub fn clearOperandDeath(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) void {
- assert(operand < bpi - 1);
- const usize_index = (@intFromEnum(inst) * bpi) / @bitSizeOf(usize);
- const mask = @as(usize, 1) <<
- @as(Log2Int(usize), @intCast((@intFromEnum(inst) % (@bitSizeOf(usize) / bpi)) * bpi + operand));
- l.tomb_bits[usize_index] &= ~mask;
-}
-
const OperandCategory = enum {
/// The operand lives on, but this instruction cannot possibly mutate memory.
none,
@@ -844,12 +836,6 @@ const Analysis = struct {
special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
extra: std.ArrayListUnmanaged(u32),
- fn storeTombBits(a: *Analysis, inst: Air.Inst.Index, tomb_bits: Bpi) void {
- const usize_index = (inst * bpi) / @bitSizeOf(usize);
- a.tomb_bits[usize_index] |= @as(usize, tomb_bits) <<
- @as(Log2Int(usize), @intCast((inst % (@bitSizeOf(usize) / bpi)) * bpi));
- }
-
fn addExtra(a: *Analysis, extra: anytype) Allocator.Error!u32 {
const fields = std.meta.fields(@TypeOf(extra));
try a.extra.ensureUnusedCapacity(a.gpa, fields.len);
src/print_air.zig
@@ -96,8 +96,8 @@ const Writer = struct {
fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];
try s.writeByteNTimes(' ', w.indent);
- try s.print("%{d}{c}= {s}(", .{
- @intFromEnum(inst),
+ try s.print("{}{c}= {s}(", .{
+ inst,
@as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),
@tagName(tag),
});
@@ -409,7 +409,7 @@ const Writer = struct {
try s.writeAll("}");
for (liveness_block.deaths) |operand| {
- try s.print(" %{d}!", .{@intFromEnum(operand)});
+ try s.print(" {}!", .{operand});
}
}
@@ -728,7 +728,7 @@ const Writer = struct {
try s.writeByteNTimes(' ', w.indent);
for (liveness_condbr.else_deaths, 0..) |operand, i| {
if (i != 0) try s.writeAll(" ");
- try s.print("%{d}!", .{@intFromEnum(operand)});
+ try s.print("{}!", .{operand});
}
try s.writeAll("\n");
}
@@ -739,7 +739,7 @@ const Writer = struct {
try s.writeAll("}");
for (liveness_condbr.then_deaths) |operand| {
- try s.print(" %{d}!", .{@intFromEnum(operand)});
+ try s.print(" {}!", .{operand});
}
}
@@ -765,7 +765,7 @@ const Writer = struct {
try s.writeByteNTimes(' ', w.indent);
for (liveness_condbr.else_deaths, 0..) |operand, i| {
if (i != 0) try s.writeAll(" ");
- try s.print("%{d}!", .{@intFromEnum(operand)});
+ try s.print("{}!", .{operand});
}
try s.writeAll("\n");
}
@@ -776,7 +776,7 @@ const Writer = struct {
try s.writeAll("}");
for (liveness_condbr.then_deaths) |operand| {
- try s.print(" %{d}!", .{@intFromEnum(operand)});
+ try s.print(" {}!", .{operand});
}
}
@@ -807,7 +807,7 @@ const Writer = struct {
try s.writeByteNTimes(' ', w.indent);
for (liveness_condbr.then_deaths, 0..) |operand, i| {
if (i != 0) try s.writeAll(" ");
- try s.print("%{d}!", .{@intFromEnum(operand)});
+ try s.print("{}!", .{operand});
}
try s.writeAll("\n");
}
@@ -827,7 +827,7 @@ const Writer = struct {
try s.writeByteNTimes(' ', w.indent);
for (liveness_condbr.else_deaths, 0..) |operand, i| {
if (i != 0) try s.writeAll(" ");
- try s.print("%{d}!", .{@intFromEnum(operand)});
+ try s.print("{}!", .{operand});
}
try s.writeAll("\n");
}
@@ -884,7 +884,7 @@ const Writer = struct {
try s.writeByteNTimes(' ', w.indent);
for (deaths, 0..) |operand, i| {
if (i != 0) try s.writeAll(" ");
- try s.print("%{d}!", .{@intFromEnum(operand)});
+ try s.print("{}!", .{operand});
}
try s.writeAll("\n");
}
@@ -910,7 +910,7 @@ const Writer = struct {
try s.writeByteNTimes(' ', w.indent);
for (deaths, 0..) |operand, i| {
if (i != 0) try s.writeAll(" ");
- try s.print("%{d}!", .{@intFromEnum(operand)});
+ try s.print("{}!", .{operand});
}
try s.writeAll("\n");
}
@@ -994,7 +994,7 @@ const Writer = struct {
dies: bool,
) @TypeOf(s).Error!void {
_ = w;
- try s.print("%{d}", .{@intFromEnum(inst)});
+ try s.print("{}", .{inst});
if (dies) try s.writeByte('!');
}
tools/lldb_pretty_printers.py
@@ -383,7 +383,7 @@ def InstRef_SummaryProvider(value, _=None):
'InternPool.Index(%d)' % value.unsigned if value.unsigned < 0x80000000 else 'instructions[%d]' % (value.unsigned - 0x80000000))
def InstIndex_SummaryProvider(value, _=None):
- return 'instructions[%d]' % value.unsigned
+ return 'instructions[%d]' % value.unsigned if value.unsigned < 0x80000000 else 'temps[%d]' % (value.unsigned - 0x80000000)
class zig_DeclIndex_SynthProvider:
def __init__(self, value, _=None): self.value = value