mirror of
https://github.com/ziglang/zig.git
synced 2024-12-13 14:47:09 +00:00
stage2: first pass over codegen.zig for AIR memory layout
This commit is contained in:
parent
ef7080aed1
commit
ee6432537e
38
BRANCH_TODO
38
BRANCH_TODO
@ -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.
|
||||
|
@ -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 {
|
||||
|
1383
src/codegen.zig
1383
src/codegen.zig
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user