diff --git a/src/arch/aarch64/abi.zig b/src/arch/aarch64/abi.zig index 839b2789e4..89a3a6c21d 100644 --- a/src/arch/aarch64/abi.zig +++ b/src/arch/aarch64/abi.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const builtin = @import("builtin"); const bits = @import("bits.zig"); const Register = bits.Register; @@ -26,12 +27,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, // Register classes const RegisterBitSet = RegisterManager.RegisterBitSet; pub const RegisterClass = struct { - pub const gp: RegisterBitSet = blk: { - var set = RegisterBitSet.initEmpty(); - set.setRangeValue(.{ - .start = 0, - .end = callee_preserved_regs.len, - }, true); - break :blk set; - }; + pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet); + // TODO uncomment once #11680 is fixed. + // pub const gp: RegisterBitSet = blk: { + // var set = RegisterBitSet.initEmpty(); + // set.setRangeValue(.{ + // .start = 0, + // .end = callee_preserved_regs.len, + // }, true); + // break :blk set; + // }; }; diff --git a/src/arch/arm/abi.zig b/src/arch/arm/abi.zig index dbee1f9b90..c76c3b0ea0 100644 --- a/src/arch/arm/abi.zig +++ b/src/arch/arm/abi.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const bits = @import("bits.zig"); const Register = bits.Register; const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; @@ -14,12 +15,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, // Register classes const RegisterBitSet = RegisterManager.RegisterBitSet; pub const RegisterClass = struct { - pub const gp: RegisterBitSet = blk: { - var set = RegisterBitSet.initEmpty(); - set.setRangeValue(.{ - .start = 0, - .end = caller_preserved_regs.len + callee_preserved_regs.len, - }, true); - break :blk set; - }; + pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet); + // TODO uncomment once #11680 is fixed. + // pub const gp: RegisterBitSet = blk: { + // var set = RegisterBitSet.initEmpty(); + // set.setRangeValue(.{ + // .start = 0, + // .end = caller_preserved_regs.len + callee_preserved_regs.len, + // }, true); + // break :blk set; + // }; }; diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig index 459fd40c9c..30d3719a46 100644 --- a/src/arch/riscv64/abi.zig +++ b/src/arch/riscv64/abi.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const bits = @import("bits.zig"); const Register = bits.Register; const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; @@ -12,12 +13,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, // Register classes const RegisterBitSet = RegisterManager.RegisterBitSet; pub const RegisterClass = struct { - pub const gp: RegisterBitSet = blk: { - var set = RegisterBitSet.initEmpty(); - set.setRangeValue(.{ - .start = 0, - .end = callee_preserved_regs.len, - }, true); - break :blk set; - }; + pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet); + // TODO uncomment once #11680 is fixed. + // pub const gp: RegisterBitSet = blk: { + // var set = RegisterBitSet.initEmpty(); + // set.setRangeValue(.{ + // .start = 0, + // .end = callee_preserved_regs.len, + // }, true); + // break :blk set; + // }; }; diff --git a/src/arch/sparc64/abi.zig b/src/arch/sparc64/abi.zig index b1985a7b0b..1c6d40941f 100644 --- a/src/arch/sparc64/abi.zig +++ b/src/arch/sparc64/abi.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const bits = @import("bits.zig"); const Register = bits.Register; const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; @@ -42,12 +43,14 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, // Register classes const RegisterBitSet = RegisterManager.RegisterBitSet; pub const RegisterClass = struct { - pub const gp: RegisterBitSet = blk: { - var set = RegisterBitSet.initEmpty(); - set.setRangeValue(.{ - .start = 0, - .end = allocatable_regs.len, - }, true); - break :blk set; - }; + pub const gp: RegisterBitSet = std.math.maxInt(RegisterBitSet); + // TODO uncomment once #11680 is fixed. + // pub const gp: RegisterBitSet = blk: { + // var set = RegisterBitSet.initEmpty(); + // set.setRangeValue(.{ + // .start = 0, + // .end = allocatable_regs.len, + // }, true); + // break :blk set; + // }; }; diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig index 7e2025a23d..77f28c11f4 100644 --- a/src/arch/x86_64/abi.zig +++ b/src/arch/x86_64/abi.zig @@ -393,20 +393,26 @@ pub const RegisterManager = RegisterManagerFn(@import("CodeGen.zig"), Register, // Register classes const RegisterBitSet = RegisterManager.RegisterBitSet; pub const RegisterClass = struct { - pub const gp: RegisterBitSet = blk: { - var set = RegisterBitSet.initEmpty(); - set.setRangeValue(.{ - .start = 0, - .end = caller_preserved_regs.len + callee_preserved_regs.len, - }, true); - break :blk set; - }; - pub const sse: RegisterBitSet = blk: { - var set = RegisterBitSet.initEmpty(); - set.setRangeValue(.{ - .start = caller_preserved_regs.len + callee_preserved_regs.len, - .end = allocatable_registers.len, - }, true); - break :blk set; - }; + pub const gp: RegisterBitSet = @as(RegisterBitSet, std.math.maxInt(std.meta.Int( + .unsigned, + caller_preserved_regs.len + callee_preserved_regs.len, + ))); + pub const sse: RegisterBitSet = std.math.maxInt(RegisterBitSet) - gp; + // TODO uncomment once #11680 is fixed. + // pub const gp: RegisterBitSet = blk: { + // var set = RegisterBitSet.initEmpty(); + // set.setRangeValue(.{ + // .start = 0, + // .end = caller_preserved_regs.len + callee_preserved_regs.len, + // }, true); + // break :blk set; + // }; + // pub const sse: RegisterBitSet = blk: { + // var set = RegisterBitSet.initEmpty(); + // set.setRangeValue(.{ + // .start = caller_preserved_regs.len + callee_preserved_regs.len, + // .end = allocatable_registers.len, + // }, true); + // break :blk set; + // }; }; diff --git a/src/register_manager.zig b/src/register_manager.zig index a73f345e0c..347c916769 100644 --- a/src/register_manager.zig +++ b/src/register_manager.zig @@ -4,7 +4,6 @@ const mem = std.mem; const assert = std.debug.assert; const Allocator = std.mem.Allocator; const Air = @import("Air.zig"); -const StaticBitSet = std.bit_set.StaticBitSet; const Type = @import("type.zig").Type; const Module = @import("Module.zig"); const expect = std.testing.expect; @@ -42,39 +41,49 @@ pub fn RegisterManager( registers: [tracked_registers.len]Air.Inst.Index = undefined, /// Tracks which registers are free (in which case the /// corresponding bit is set to 1) - free_registers: RegisterBitSet = RegisterBitSet.initFull(), + free_registers: RegisterBitSet = math.maxInt(RegisterBitSet), /// Tracks all registers allocated in the course of this /// function - allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(), + allocated_registers: RegisterBitSet = 0, /// Tracks registers which are locked from being allocated - locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(), + locked_registers: RegisterBitSet = 0, const Self = @This(); - pub const RegisterBitSet = StaticBitSet(tracked_registers.len); + /// An integer whose bits represent all the registers and + /// whether they are free. + pub const RegisterBitSet = std.meta.Int(.unsigned, tracked_registers.len); + const ShiftInt = math.Log2Int(RegisterBitSet); fn getFunction(self: *Self) *Function { return @fieldParentPtr(Function, "register_manager", self); } fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool { - const index = indexOfRegIntoTracked(reg) orelse return true; - return !register_class.isSet(index); + const mask = getRegisterMask(reg) orelse return true; + return mask & register_class == 0; + } + + fn getRegisterMask(reg: Register) ?RegisterBitSet { + const index = indexOfRegIntoTracked(reg) orelse return null; + const shift = @intCast(ShiftInt, index); + const mask = @as(RegisterBitSet, 1) << shift; + return mask; } fn markRegAllocated(self: *Self, reg: Register) void { - const index = indexOfRegIntoTracked(reg) orelse return; - self.allocated_registers.set(index); + const mask = getRegisterMask(reg) orelse return; + self.allocated_registers |= mask; } fn markRegUsed(self: *Self, reg: Register) void { - const index = indexOfRegIntoTracked(reg) orelse return; - self.free_registers.unset(index); + const mask = getRegisterMask(reg) orelse return; + self.free_registers &= ~mask; } fn markRegFree(self: *Self, reg: Register) void { - const index = indexOfRegIntoTracked(reg) orelse return; - self.free_registers.set(index); + const mask = getRegisterMask(reg) orelse return; + self.free_registers |= mask; } pub fn indexOfReg( @@ -87,14 +96,14 @@ pub fn RegisterManager( return null; } - pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt { + pub fn indexOfRegIntoTracked(reg: Register) ?ShiftInt { return indexOfReg(tracked_registers, reg); } /// Returns true when this register is not tracked pub fn isRegFree(self: Self, reg: Register) bool { - const index = indexOfRegIntoTracked(reg) orelse return true; - return self.free_registers.isSet(index); + const mask = getRegisterMask(reg) orelse return true; + return self.free_registers & mask != 0; } /// Returns whether this register was allocated in the course @@ -102,16 +111,16 @@ pub fn RegisterManager( /// /// Returns false when this register is not tracked pub fn isRegAllocated(self: Self, reg: Register) bool { - const index = indexOfRegIntoTracked(reg) orelse return false; - return self.allocated_registers.isSet(index); + const mask = getRegisterMask(reg) orelse return false; + return self.allocated_registers & mask != 0; } /// Returns whether this register is locked /// /// Returns false when this register is not tracked pub fn isRegLocked(self: Self, reg: Register) bool { - const index = indexOfRegIntoTracked(reg) orelse return false; - return self.locked_registers.isSet(index); + const mask = getRegisterMask(reg) orelse return false; + return self.locked_registers & mask != 0; } pub const RegisterLock = struct { @@ -130,8 +139,8 @@ pub fn RegisterManager( log.debug(" register already locked", .{}); return null; } - const index = indexOfRegIntoTracked(reg) orelse return null; - self.locked_registers.set(index); + const mask = getRegisterMask(reg) orelse return null; + self.locked_registers |= mask; return RegisterLock{ .register = reg }; } @@ -140,8 +149,8 @@ pub fn RegisterManager( pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock { log.debug("locking asserting free {}", .{reg}); assert(!self.isRegLocked(reg)); - const index = indexOfRegIntoTracked(reg) orelse unreachable; - self.locked_registers.set(index); + const mask = getRegisterMask(reg) orelse unreachable; + self.locked_registers |= mask; return RegisterLock{ .register = reg }; } @@ -163,13 +172,13 @@ pub fn RegisterManager( /// Call `lockReg` to obtain the lock first. pub fn unlockReg(self: *Self, lock: RegisterLock) void { log.debug("unlocking {}", .{lock.register}); - const index = indexOfRegIntoTracked(lock.register) orelse return; - self.locked_registers.unset(index); + const mask = getRegisterMask(lock.register) orelse return; + self.locked_registers &= ~mask; } /// Returns true when at least one register is locked pub fn lockedRegsExist(self: Self) bool { - return self.locked_registers.count() > 0; + return self.locked_registers != 0; } /// Allocates a specified number of registers, optionally @@ -183,15 +192,10 @@ pub fn RegisterManager( ) ?[count]Register { comptime assert(count > 0 and count <= tracked_registers.len); - var free_and_not_locked_registers = self.free_registers; - free_and_not_locked_registers.setIntersection(register_class); - - var unlocked_registers = self.locked_registers; - unlocked_registers.toggleAll(); - - free_and_not_locked_registers.setIntersection(unlocked_registers); - - if (free_and_not_locked_registers.count() < count) return null; + const free_registers = self.free_registers & register_class; + const free_and_not_locked_registers = free_registers & ~self.locked_registers; + const free_and_not_locked_registers_count = @popCount(RegisterBitSet, free_and_not_locked_registers); + if (free_and_not_locked_registers_count < count) return null; var regs: [count]Register = undefined; var i: usize = 0; @@ -238,10 +242,10 @@ pub fn RegisterManager( ) AllocateRegistersError![count]Register { comptime assert(count > 0 and count <= tracked_registers.len); - var locked_registers = self.locked_registers; - locked_registers.setIntersection(register_class); - - if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters; + const available_registers_count = @popCount(RegisterBitSet, register_class); + const locked_registers = self.locked_registers & register_class; + const locked_registers_count = @popCount(RegisterBitSet, locked_registers); + if (count > available_registers_count - locked_registers_count) return error.OutOfRegisters; const result = self.tryAllocRegs(count, insts, register_class) orelse blk: { // We'll take over the first count registers. Spill @@ -348,6 +352,334 @@ pub fn RegisterManager( }; } +// TODO delete current implementation of RegisterManager above, and uncomment the one +// below once #11680 is fixed: +// https://github.com/ziglang/zig/issues/11680 + +//pub fn RegisterManager( +// comptime Function: type, +// comptime Register: type, +// comptime tracked_registers: []const Register, +//) type { +// // architectures which do not have a concept of registers should +// // refrain from using RegisterManager +// assert(tracked_registers.len > 0); // see note above + +// return struct { +// /// Tracks the AIR instruction allocated to every register. If +// /// no instruction is allocated to a register (i.e. the +// /// register is free), the value in that slot is undefined. +// /// +// /// The key must be canonical register. +// registers: [tracked_registers.len]Air.Inst.Index = undefined, +// /// Tracks which registers are free (in which case the +// /// corresponding bit is set to 1) +// free_registers: RegisterBitSet = RegisterBitSet.initFull(), +// /// Tracks all registers allocated in the course of this +// /// function +// allocated_registers: RegisterBitSet = RegisterBitSet.initEmpty(), +// /// Tracks registers which are locked from being allocated +// locked_registers: RegisterBitSet = RegisterBitSet.initEmpty(), + +// const Self = @This(); + +// pub const RegisterBitSet = StaticBitSet(tracked_registers.len); + +// fn getFunction(self: *Self) *Function { +// return @fieldParentPtr(Function, "register_manager", self); +// } + +// fn excludeRegister(reg: Register, register_class: RegisterBitSet) bool { +// const index = indexOfRegIntoTracked(reg) orelse return true; +// return !register_class.isSet(index); +// } + +// fn markRegAllocated(self: *Self, reg: Register) void { +// const index = indexOfRegIntoTracked(reg) orelse return; +// self.allocated_registers.set(index); +// } + +// fn markRegUsed(self: *Self, reg: Register) void { +// const index = indexOfRegIntoTracked(reg) orelse return; +// self.free_registers.unset(index); +// } + +// fn markRegFree(self: *Self, reg: Register) void { +// const index = indexOfRegIntoTracked(reg) orelse return; +// self.free_registers.set(index); +// } + +// pub fn indexOfReg( +// comptime registers: []const Register, +// reg: Register, +// ) ?std.math.IntFittingRange(0, registers.len - 1) { +// inline for (tracked_registers) |cpreg, i| { +// if (reg.id() == cpreg.id()) return i; +// } +// return null; +// } + +// pub fn indexOfRegIntoTracked(reg: Register) ?RegisterBitSet.ShiftInt { +// return indexOfReg(tracked_registers, reg); +// } + +// /// Returns true when this register is not tracked +// pub fn isRegFree(self: Self, reg: Register) bool { +// const index = indexOfRegIntoTracked(reg) orelse return true; +// return self.free_registers.isSet(index); +// } + +// /// Returns whether this register was allocated in the course +// /// of this function. +// /// +// /// Returns false when this register is not tracked +// pub fn isRegAllocated(self: Self, reg: Register) bool { +// const index = indexOfRegIntoTracked(reg) orelse return false; +// return self.allocated_registers.isSet(index); +// } + +// /// Returns whether this register is locked +// /// +// /// Returns false when this register is not tracked +// pub fn isRegLocked(self: Self, reg: Register) bool { +// const index = indexOfRegIntoTracked(reg) orelse return false; +// return self.locked_registers.isSet(index); +// } + +// pub const RegisterLock = struct { +// register: Register, +// }; + +// /// Prevents the register from being allocated until they are +// /// unlocked again. +// /// Returns `RegisterLock` if the register was not already +// /// locked, or `null` otherwise. +// /// Only the owner of the `RegisterLock` can unlock the +// /// register later. +// pub fn lockReg(self: *Self, reg: Register) ?RegisterLock { +// log.debug("locking {}", .{reg}); +// if (self.isRegLocked(reg)) { +// log.debug(" register already locked", .{}); +// return null; +// } +// const index = indexOfRegIntoTracked(reg) orelse return null; +// self.locked_registers.set(index); +// return RegisterLock{ .register = reg }; +// } + +// /// Like `lockReg` but asserts the register was unused always +// /// returning a valid lock. +// pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock { +// log.debug("locking asserting free {}", .{reg}); +// assert(!self.isRegLocked(reg)); +// const index = indexOfRegIntoTracked(reg) orelse unreachable; +// self.locked_registers.set(index); +// return RegisterLock{ .register = reg }; +// } + +// /// Like `lockRegAssumeUnused` but locks multiple registers. +// pub fn lockRegsAssumeUnused( +// self: *Self, +// comptime count: comptime_int, +// regs: [count]Register, +// ) [count]RegisterLock { +// var buf: [count]RegisterLock = undefined; +// for (regs) |reg, i| { +// buf[i] = self.lockRegAssumeUnused(reg); +// } +// return buf; +// } + +// /// Unlocks the register allowing its re-allocation and re-use. +// /// Requires `RegisterLock` to unlock a register. +// /// Call `lockReg` to obtain the lock first. +// pub fn unlockReg(self: *Self, lock: RegisterLock) void { +// log.debug("unlocking {}", .{lock.register}); +// const index = indexOfRegIntoTracked(lock.register) orelse return; +// self.locked_registers.unset(index); +// } + +// /// Returns true when at least one register is locked +// pub fn lockedRegsExist(self: Self) bool { +// return self.locked_registers.count() > 0; +// } + +// /// Allocates a specified number of registers, optionally +// /// tracking them. Returns `null` if not enough registers are +// /// free. +// pub fn tryAllocRegs( +// self: *Self, +// comptime count: comptime_int, +// insts: [count]?Air.Inst.Index, +// register_class: RegisterBitSet, +// ) ?[count]Register { +// comptime assert(count > 0 and count <= tracked_registers.len); + +// var free_and_not_locked_registers = self.free_registers; +// free_and_not_locked_registers.setIntersection(register_class); + +// var unlocked_registers = self.locked_registers; +// unlocked_registers.toggleAll(); + +// free_and_not_locked_registers.setIntersection(unlocked_registers); + +// if (free_and_not_locked_registers.count() < count) return null; + +// var regs: [count]Register = undefined; +// var i: usize = 0; +// for (tracked_registers) |reg| { +// if (i >= count) break; +// if (excludeRegister(reg, register_class)) continue; +// if (self.isRegLocked(reg)) continue; +// if (!self.isRegFree(reg)) continue; + +// regs[i] = reg; +// i += 1; +// } +// assert(i == count); + +// for (regs) |reg, j| { +// self.markRegAllocated(reg); + +// if (insts[j]) |inst| { +// // Track the register +// const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null +// self.registers[index] = inst; +// self.markRegUsed(reg); +// } +// } + +// return regs; +// } + +// /// Allocates a register and optionally tracks it with a +// /// corresponding instruction. Returns `null` if all registers +// /// are allocated. +// pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, register_class: RegisterBitSet) ?Register { +// return if (tryAllocRegs(self, 1, .{inst}, register_class)) |regs| regs[0] else null; +// } + +// /// Allocates a specified number of registers, optionally +// /// tracking them. Asserts that count is not +// /// larger than the total number of registers available. +// pub fn allocRegs( +// self: *Self, +// comptime count: comptime_int, +// insts: [count]?Air.Inst.Index, +// register_class: RegisterBitSet, +// ) AllocateRegistersError![count]Register { +// comptime assert(count > 0 and count <= tracked_registers.len); + +// var locked_registers = self.locked_registers; +// locked_registers.setIntersection(register_class); + +// if (count > register_class.count() - locked_registers.count()) return error.OutOfRegisters; + +// const result = self.tryAllocRegs(count, insts, register_class) orelse blk: { +// // We'll take over the first count registers. Spill +// // the instructions that were previously there to a +// // stack allocations. +// var regs: [count]Register = undefined; +// var i: usize = 0; +// for (tracked_registers) |reg| { +// if (i >= count) break; +// if (excludeRegister(reg, register_class)) break; +// if (self.isRegLocked(reg)) continue; + +// regs[i] = reg; +// self.markRegAllocated(reg); +// const index = indexOfRegIntoTracked(reg).?; // indexOfReg() on a callee-preserved reg should never return null +// if (insts[i]) |inst| { +// // Track the register +// if (self.isRegFree(reg)) { +// self.markRegUsed(reg); +// } else { +// const spilled_inst = self.registers[index]; +// try self.getFunction().spillInstruction(reg, spilled_inst); +// } +// self.registers[index] = inst; +// } else { +// // Don't track the register +// if (!self.isRegFree(reg)) { +// const spilled_inst = self.registers[index]; +// try self.getFunction().spillInstruction(reg, spilled_inst); +// self.freeReg(reg); +// } +// } + +// i += 1; +// } + +// break :blk regs; +// }; + +// log.debug("allocated registers {any} for insts {any}", .{ result, insts }); +// return result; +// } + +// /// Allocates a register and optionally tracks it with a +// /// corresponding instruction. +// pub fn allocReg( +// self: *Self, +// inst: ?Air.Inst.Index, +// register_class: RegisterBitSet, +// ) AllocateRegistersError!Register { +// return (try self.allocRegs(1, .{inst}, register_class))[0]; +// } + +// /// Spills the register if it is currently allocated. If a +// /// corresponding instruction is passed, will also track this +// /// register. +// pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void { +// const index = indexOfRegIntoTracked(reg) orelse return; +// log.debug("getReg {} for inst {}", .{ reg, inst }); +// self.markRegAllocated(reg); + +// if (inst) |tracked_inst| +// if (!self.isRegFree(reg)) { +// // Move the instruction that was previously there to a +// // stack allocation. +// const spilled_inst = self.registers[index]; +// self.registers[index] = tracked_inst; +// try self.getFunction().spillInstruction(reg, spilled_inst); +// } else { +// self.getRegAssumeFree(reg, tracked_inst); +// } +// else { +// if (!self.isRegFree(reg)) { +// // Move the instruction that was previously there to a +// // stack allocation. +// const spilled_inst = self.registers[index]; +// try self.getFunction().spillInstruction(reg, spilled_inst); +// self.freeReg(reg); +// } +// } +// } + +// /// Allocates the specified register with the specified +// /// instruction. Asserts that the register is free and no +// /// spilling is necessary. +// pub fn getRegAssumeFree(self: *Self, reg: Register, inst: Air.Inst.Index) void { +// const index = indexOfRegIntoTracked(reg) orelse return; +// log.debug("getRegAssumeFree {} for inst {}", .{ reg, inst }); +// self.markRegAllocated(reg); + +// assert(self.isRegFree(reg)); +// self.registers[index] = inst; +// self.markRegUsed(reg); +// } + +// /// Marks the specified register as free +// pub fn freeReg(self: *Self, reg: Register) void { +// const index = indexOfRegIntoTracked(reg) orelse return; +// log.debug("freeing register {}", .{reg}); + +// self.registers[index] = undefined; +// self.markRegFree(reg); +// } +// }; +//} + const MockRegister1 = enum(u2) { r0, r1, @@ -384,7 +716,7 @@ fn MockFunction(comptime Register: type) type { const RegisterManagerT = RegisterManager(Self, Register, &Register.allocatable_registers); - pub const reg_class: RegisterManagerT.RegisterBitSet = RegisterManagerT.RegisterBitSet.initFull(); + pub const reg_class: RegisterManagerT.RegisterBitSet = math.maxInt(RegisterManagerT.RegisterBitSet); pub fn deinit(self: *Self) void { self.spilled.deinit(self.allocator);