aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2025-05-28 22:45:19 -0400
committerJacob Young <15544577+jacobly0@users.noreply.github.com>2025-05-29 03:57:48 -0400
commitc04be630d996a0e01fd3cf05e6cade006e4226ce (patch)
treeedd9d55ad05435b91bd3cb95208a76ead2001094 /src/codegen/c.zig
parentf25212a479c4f26566b6b851e245e49c6f508b96 (diff)
downloadzig-c04be630d996a0e01fd3cf05e6cade006e4226ce.tar.gz
zig-c04be630d996a0e01fd3cf05e6cade006e4226ce.zip
Legalize: introduce a new pass before liveness
Each target can opt into different sets of legalize features. By performing these transformations before liveness, instructions that become unreferenced will have up-to-date liveness information.
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig69
1 files changed, 34 insertions, 35 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 075d9ba303..8539efdbfe 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -14,7 +14,6 @@ const C = link.File.C;
const Decl = Zcu.Decl;
const trace = @import("../tracy.zig").trace;
const Air = @import("../Air.zig");
-const Liveness = @import("../Liveness.zig");
const InternPool = @import("../InternPool.zig");
const Alignment = InternPool.Alignment;
@@ -356,7 +355,7 @@ pub fn isMangledIdent(ident: []const u8, solo: bool) bool {
/// It is not available when generating .h file.
pub const Function = struct {
air: Air,
- liveness: Liveness,
+ liveness: Air.Liveness,
value_map: CValueMap,
blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .empty,
next_arg_index: u32 = 0,
@@ -2323,9 +2322,9 @@ pub const DeclGen = struct {
const pt = dg.pt;
const zcu = pt.zcu;
- const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{
+ const int_info: std.builtin.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{
.signedness = .unsigned,
- .bits = @as(u16, @intCast(ty.bitSize(zcu))),
+ .bits = @intCast(ty.bitSize(zcu)),
};
if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
@@ -3179,7 +3178,7 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
// Remember how many locals there were before entering the body so that we can free any that
// were newly introduced. Any new locals must necessarily be logically free after the then
// branch is complete.
- const pre_locals_len = @as(LocalIndex, @intCast(f.locals.items.len));
+ const pre_locals_len: LocalIndex = @intCast(f.locals.items.len);
for (leading_deaths) |death| {
try die(f, inst, death.toRef());
@@ -4540,7 +4539,7 @@ fn airCall(
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
const extra = f.air.extraData(Air.Call, pl_op.payload);
- const args = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[extra.end..][0..extra.data.args_len]));
+ const args: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.args_len]);
const resolved_args = try gpa.alloc(CValue, args.len);
defer gpa.free(resolved_args);
@@ -4708,7 +4707,7 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
const owner_nav = ip.getNav(zcu.funcInfo(extra.data.func).owner_nav);
const writer = f.object.writer();
try writer.print("/* inline:{} */\n", .{owner_nav.fqn.fmt(&zcu.intern_pool)});
- return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
+ return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));
}
fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
@@ -4729,7 +4728,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = f.air.extraData(Air.Block, ty_pl.payload);
- return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
+ return lowerBlock(f, inst, @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]));
}
fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue {
@@ -4781,7 +4780,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
const extra = f.air.extraData(Air.Try, pl_op.payload);
- const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]);
+ const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]);
const err_union_ty = f.typeOf(pl_op.operand);
return lowerTry(f, inst, pl_op.operand, body, err_union_ty, false);
}
@@ -4791,7 +4790,7 @@ fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
const zcu = pt.zcu;
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
- const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]);
+ const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.body_len]);
const err_union_ty = f.typeOf(extra.data.ptr).childType(zcu);
return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true);
}
@@ -5100,7 +5099,7 @@ fn airUnreach(f: *Function) !void {
fn airLoop(f: *Function, inst: Air.Inst.Index) !void {
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const loop = f.air.extraData(Air.Block, ty_pl.payload);
- const body: []const Air.Inst.Index = @ptrCast(f.air.extra[loop.end..][0..loop.data.body_len]);
+ const body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[loop.end..][0..loop.data.body_len]);
const writer = f.object.writer();
// `repeat` instructions matching this loop will branch to
@@ -5116,8 +5115,8 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void {
const cond = try f.resolveInst(pl_op.operand);
try reap(f, inst, &.{pl_op.operand});
const extra = f.air.extraData(Air.CondBr, pl_op.payload);
- const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.then_body_len]);
- const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]);
+ const then_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end..][0..extra.data.then_body_len]);
+ const else_body: []const Air.Inst.Index = @ptrCast(f.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]);
const liveness_condbr = f.liveness.getCondBr(inst);
const writer = f.object.writer();
@@ -5322,12 +5321,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = f.air.extraData(Air.Asm, ty_pl.payload);
const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
- const clobbers_len = @as(u31, @truncate(extra.data.flags));
+ const clobbers_len: u31 = @truncate(extra.data.flags);
const gpa = f.object.dg.gpa;
var extra_i: usize = extra.end;
- const outputs = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[extra_i..][0..extra.data.outputs_len]));
+ const outputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.outputs_len]);
extra_i += outputs.len;
- const inputs = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[extra_i..][0..extra.data.inputs_len]));
+ const inputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.inputs_len]);
extra_i += inputs.len;
const result = result: {
@@ -5347,10 +5346,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
break :local inst_local;
} else .none;
- const locals_begin = @as(LocalIndex, @intCast(f.locals.items.len));
+ const locals_begin: LocalIndex = @intCast(f.locals.items.len);
const constraints_extra_begin = extra_i;
for (outputs) |output| {
- const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
+ const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
@@ -5384,7 +5383,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
}
}
for (inputs) |input| {
- const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
+ const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
@@ -5419,14 +5418,14 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
}
}
for (0..clobbers_len) |_| {
- const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
+ const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[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;
}
{
- const asm_source = mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len];
+ const asm_source = mem.sliceAsBytes(f.air.extra.items[extra_i..])[0..extra.data.source_len];
var stack = std.heap.stackFallback(256, f.object.dg.gpa);
const allocator = stack.get();
@@ -5484,7 +5483,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
var locals_index = locals_begin;
try writer.writeByte(':');
for (outputs, 0..) |output, index| {
- const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
+ const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
@@ -5508,7 +5507,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
}
try writer.writeByte(':');
for (inputs, 0..) |input, index| {
- const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
+ const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
@@ -5531,7 +5530,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
}
try writer.writeByte(':');
for (0..clobbers_len) |clobber_i| {
- const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
+ const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[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;
@@ -5546,7 +5545,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i = constraints_extra_begin;
locals_index = locals_begin;
for (outputs) |output| {
- const extra_bytes = mem.sliceAsBytes(f.air.extra[extra_i..]);
+ const extra_bytes = mem.sliceAsBytes(f.air.extra.items[extra_i..]);
const constraint = mem.sliceTo(extra_bytes, 0);
const name = mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
// This equation accounts for the fact that even if we have exactly 4 bytes
@@ -6725,7 +6724,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
const operand_mat = try Materialize.start(f, inst, ty, operand);
try reap(f, inst, &.{ pl_op.operand, extra.operand });
- const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8));
+ const repr_bits: u16 = @intCast(ty.abiSize(zcu) * 8);
const is_float = ty.isRuntimeFloat();
const is_128 = repr_bits == 128;
const repr_ty = if (is_float) pt.intType(.unsigned, repr_bits) catch unreachable else ty;
@@ -7325,8 +7324,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const ip = &zcu.intern_pool;
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const inst_ty = f.typeOfIndex(inst);
- const len = @as(usize, @intCast(inst_ty.arrayLen(zcu)));
- const elements = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[ty_pl.payload..][0..len]));
+ const len: usize = @intCast(inst_ty.arrayLen(zcu));
+ const elements: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[ty_pl.payload..][0..len]);
const gpa = f.object.dg.gpa;
const resolved_elements = try gpa.alloc(CValue, elements.len);
defer gpa.free(resolved_elements);
@@ -7830,7 +7829,7 @@ fn IndentWriter(comptime UnderlyingWriter: type) type {
}
pub fn write(self: *Self, bytes: []const u8) Error!usize {
- if (bytes.len == 0) return @as(usize, 0);
+ if (bytes.len == 0) return 0;
const current_indent = self.indent_count * Self.indent_delta;
if (self.current_line_empty and current_indent > 0) {
@@ -7860,7 +7859,7 @@ fn IndentWriter(comptime UnderlyingWriter: type) type {
}
fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
- if (bytes.len == 0) return @as(usize, 0);
+ if (bytes.len == 0) return 0;
try self.underlying_writer.writeAll(bytes);
if (bytes[bytes.len - 1] == '\n') {
@@ -8048,7 +8047,7 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Formatter(formatStri
fn undefPattern(comptime IntType: type) IntType {
const int_info = @typeInfo(IntType).int;
const UnsignedType = std.meta.Int(.unsigned, int_info.bits);
- return @as(IntType, @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3)));
+ return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3));
}
const FormatIntLiteralContext = struct {
@@ -8188,9 +8187,9 @@ fn formatIntLiteral(
wrap.len = wrap.limbs.len;
const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count);
- var c_limb_int_info = std.builtin.Type.Int{
+ var c_limb_int_info: std.builtin.Type.Int = .{
.signedness = undefined,
- .bits = @as(u16, @intCast(@divExact(c_bits, c_limb_info.count))),
+ .bits = @intCast(@divExact(c_bits, c_limb_info.count)),
};
var c_limb_ctype: CType = undefined;
@@ -8349,7 +8348,7 @@ fn lowersToArray(ty: Type, pt: Zcu.PerThread) bool {
}
fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !void {
- assert(operands.len <= Liveness.bpi - 1);
+ assert(operands.len <= Air.Liveness.bpi - 1);
var tomb_bits = f.liveness.getTombBits(inst);
for (operands) |operand| {
const dies = @as(u1, @truncate(tomb_bits)) != 0;
@@ -8400,7 +8399,7 @@ fn freeLocal(f: *Function, inst: ?Air.Inst.Index, local_index: LocalIndex, ref_i
const BigTomb = struct {
f: *Function,
inst: Air.Inst.Index,
- lbt: Liveness.BigTomb,
+ lbt: Air.Liveness.BigTomb,
fn feed(bt: *BigTomb, op_ref: Air.Inst.Ref) !void {
const dies = bt.lbt.feed();