stage2: first pass over codegen.zig for AIR memory layout

This commit is contained in:
Andrew Kelley 2021-07-11 23:38:29 -07:00
parent ef7080aed1
commit ee6432537e
4 changed files with 778 additions and 675 deletions

View File

@ -1,48 +1,10 @@
* be sure to test debug info of parameters
pub fn isUnused(self: Inst) bool {
return (self.deaths & (1 << unreferenced_bit_index)) != 0;
}
pub fn operandDies(self: Inst, index: DeathsBitIndex) bool {
assert(index < deaths_bits);
return @truncate(u1, self.deaths >> index) != 0;
}
pub fn clearOperandDeath(self: *Inst, index: DeathsBitIndex) void {
assert(index < deaths_bits);
self.deaths &= ~(@as(DeathsInt, 1) << index);
}
pub fn specialOperandDeaths(self: Inst) bool {
return (self.deaths & (1 << deaths_bits)) != 0;
}
pub fn operandCount(base: *Inst) usize {
inline for (@typeInfo(Tag).Enum.fields) |field| {
const tag = @intToEnum(Tag, field.value);
if (tag == base.tag) {
return @fieldParentPtr(tag.Type(), "base", base).operandCount();
}
}
unreachable;
}
pub fn getOperand(base: *Inst, index: usize) ?*Inst {
inline for (@typeInfo(Tag).Enum.fields) |field| {
const tag = @intToEnum(Tag, field.value);
if (tag == base.tag) {
return @fieldParentPtr(tag.Type(), "base", base).getOperand(index);
}
}
unreachable;
}
pub fn Args(comptime T: type) type {
return std.meta.fieldInfo(T, .args).field_type;
}
/// Returns `null` if runtime-known.
/// Should be called by codegen, not by Sema. Sema functions should call
/// `resolvePossiblyUndefinedValue` or `resolveDefinedValue` instead.

View File

@ -74,6 +74,26 @@ pub fn analyze(gpa: *Allocator, air: Air) Allocator.Error!Liveness {
};
}
pub fn isUnused(l: Liveness, inst: Air.Inst.Index) bool {
const usize_index = (inst * bpi) / @bitSizeOf(usize);
const mask = @as(usize, 1) << ((inst % (@bitSizeOf(usize) / bpi)) * bpi + (bpi - 1));
return (l.tomb_bits[usize_index] & mask) != 0;
}
pub fn operandDies(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) bool {
assert(operand < bpi - 1);
const usize_index = (inst * bpi) / @bitSizeOf(usize);
const mask = @as(usize, 1) << ((inst % (@bitSizeOf(usize) / bpi)) * bpi + operand);
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 = (inst * bpi) / @bitSizeOf(usize);
const mask = @as(usize, 1) << ((inst % (@bitSizeOf(usize) / bpi)) * bpi + operand);
l.tomb_bits[usize_index] |= mask;
}
pub fn deinit(l: *Liveness, gpa: *Allocator) void {
gpa.free(l.tomb_bits);
gpa.free(l.extra);
@ -83,6 +103,7 @@ pub fn deinit(l: *Liveness, gpa: *Allocator) void {
/// How many tomb bits per AIR instruction.
const bpi = 4;
const Bpi = std.meta.Int(.unsigned, bpi);
const OperandInt = std.math.Log2Int(Bpi);
/// In-progress data; on successful analysis converted into `Liveness`.
const Analysis = struct {

File diff suppressed because it is too large Load Diff

View File

@ -147,14 +147,14 @@ pub fn RegisterManager(
self.markRegUsed(reg);
} else {
const spilled_inst = self.registers[index].?;
try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
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(spilled_inst.src, reg, spilled_inst);
try self.getFunction().spillInstruction(reg, spilled_inst);
self.freeReg(reg);
}
}
@ -184,7 +184,7 @@ pub fn RegisterManager(
// stack allocation.
const spilled_inst = self.registers[index].?;
self.registers[index] = tracked_inst;
try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
try self.getFunction().spillInstruction(reg, spilled_inst);
} else {
self.getRegAssumeFree(reg, tracked_inst);
}
@ -193,7 +193,7 @@ pub fn RegisterManager(
// Move the instruction that was previously there to a
// stack allocation.
const spilled_inst = self.registers[index].?;
try self.getFunction().spillInstruction(spilled_inst.src, reg, spilled_inst);
try self.getFunction().spillInstruction(reg, spilled_inst);
self.freeReg(reg);
}
}
@ -264,8 +264,7 @@ fn MockFunction(comptime Register: type) type {
self.spilled.deinit(self.allocator);
}
pub fn spillInstruction(self: *Self, src: LazySrcLoc, reg: Register, inst: *ir.Inst) !void {
_ = src;
pub fn spillInstruction(self: *Self, reg: Register, inst: *ir.Inst) !void {
_ = inst;
try self.spilled.append(self.allocator, reg);
}