compiler: don't mutate the InternPool when printing types and values

This change at long last replaces the `Zcu.PerThread` parameters in
`Type.print` and `Value.print` with `*Zcu` parameters. This required
various tweaks to avoid the need to intern values when printing them.
The most significant change is to `Value.pointerDerivation`, whose API
and implementation has been changed quite a bit. This API is used by the
C and SPIR-V backends, which I therefore also needed to update---but it
seems to have been surprisingly painless overall!

Most of this diff comes from replacing `fmt(pt)` with `fmt(zcu)` (plus a
few more similar patterns), then following compile errors for a while to
change parameters/constants/fields from `pt` to `zcu` where necessary.
Actual logic changes should be limited to the following source files:

* `src/print_value.zig`
* `src/Type.zig`
* `src/Value.zig`
* `src/codegen/c.zig`
* `src/codegen/spirv/CodeGen.zig`
This commit is contained in:
Matthew Lugg committed 2026-09-29 10:32:05 -07:00
1 parent ac77c23aff
commit ebb8683ef1
26 files changed
+1588 -1427

No files matched your search

+1 -1
View File
@@ -41,7 +41,7 @@ pub fn run(pt: Zcu.PerThread, func_index: InternPool.Index, air: *const Air) voi
error.Canceled => return io.recancel(),
};
defer io.unlockStderr();
air.write(&stderr.file_writer.interface, pt, null) catch |err| switch (err) {
air.write(&stderr.file_writer.interface, zcu, null) catch |err| switch (err) {
error.WriteFailed => switch (stderr.file_writer.err.?) {
error.Canceled => return io.recancel(),
else => {},
+20 -20
View File
@@ -9,7 +9,7 @@ const Type = @import("../Type.zig");
const Air = @import("../Air.zig");
const InternPool = @import("../InternPool.zig");
pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) !void {
pub fn write(air: Air, stream: *std.Io.Writer, zcu: *Zcu, liveness: ?Air.Liveness) !void {
comptime assert(build_options.enable_debug_extensions);
const instruction_bytes = air.instructions.len *
// Here we don't use @sizeOf(Air.Inst.Data) because it would include
@@ -43,8 +43,8 @@ pub fn write(air: Air, stream: *std.Io.Writer, pt: Zcu.PerThread, liveness: ?Air
// zig fmt: on
var writer: Writer = .{
.pt = pt,
.gpa = pt.zcu.gpa,
.zcu = zcu,
.gpa = zcu.comp.gpa,
.air = air,
.liveness = liveness,
.indent = 2,
@@ -57,13 +57,13 @@ pub fn writeInst(
air: Air,
stream: *std.Io.Writer,
inst: Air.Inst.Index,
pt: Zcu.PerThread,
zcu: *Zcu,
liveness: ?Air.Liveness,
) void {
comptime assert(build_options.enable_debug_extensions);
var writer: Writer = .{
.pt = pt,
.gpa = pt.zcu.gpa,
.zcu = zcu,
.gpa = zcu.comp.gpa,
.air = air,
.liveness = liveness,
.indent = 2,
@@ -89,7 +89,7 @@ pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Ai
}
const Writer = struct {
pt: Zcu.PerThread,
zcu: *Zcu,
gpa: Allocator,
air: Air,
liveness: ?Air.Liveness,
@@ -377,7 +377,7 @@ const Writer = struct {
}
fn writeType(w: *Writer, s: *std.Io.Writer, ty: Type) !void {
return ty.print(s, w.pt, null);
return ty.print(s, w.zcu, null);
}
fn writeTy(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void {
@@ -446,7 +446,7 @@ const Writer = struct {
}
fn writeAggregateInit(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void {
const zcu = w.pt.zcu;
const zcu = w.zcu;
const ty_pl = w.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
const vector_ty = ty_pl.ty;
const len = @as(usize, @intCast(vector_ty.arrayLen(zcu)));
@@ -539,7 +539,7 @@ const Writer = struct {
}
fn writeShuffleOne(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void {
const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst);
const unwrapped = w.air.unwrapShuffleOne(w.zcu, inst);
try w.writeType(s, unwrapped.result_ty);
try s.writeAll(", ");
try w.writeOperand(s, inst, 0, unwrapped.operand);
@@ -548,14 +548,14 @@ const Writer = struct {
if (mask_idx > 0) try s.writeAll(", ");
switch (mask_elem.unwrap()) {
.elem => |idx| try s.print("elem {d}", .{idx}),
.value => |val| try s.print("val {f}", .{Value.fromInterned(val).fmtValue(w.pt)}),
.value => |val| try s.print("val {f}", .{Value.fromInterned(val).fmtValue(w.zcu)}),
}
}
try s.writeByte(']');
}
fn writeShuffleTwo(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void {
const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst);
const unwrapped = w.air.unwrapShuffleTwo(w.zcu, inst);
try w.writeType(s, unwrapped.result_ty);
try s.writeAll(", ");
try w.writeOperand(s, inst, 0, unwrapped.operand_a);
@@ -574,7 +574,7 @@ const Writer = struct {
}
fn writeSelect(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void {
const zcu = w.pt.zcu;
const zcu = w.zcu;
const pl_op = w.air.instructions.items(.data)[@backingInt(inst)].pl_op;
const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
@@ -606,7 +606,7 @@ const Writer = struct {
}
fn writeRuntimeNavPtr(w: *Writer, s: *std.Io.Writer, inst: Air.Inst.Index) Error!void {
const ip = &w.pt.zcu.intern_pool;
const ip = &w.zcu.intern_pool;
const ty_nav = w.air.instructions.items(.data)[@backingInt(inst)].ty_nav;
try w.writeType(s, ty_nav.ty);
try s.print(", '{f}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)});
@@ -695,7 +695,7 @@ const Writer = struct {
try s.writeByte(')');
}
const zcu = w.pt.zcu;
const zcu = w.zcu;
const ip = &zcu.intern_pool;
const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers);
const clobbers_ty = clobbers_val.typeOf(zcu);
@@ -1019,11 +1019,11 @@ const Writer = struct {
if (@backingInt(operand) < InternPool.static_len) {
return s.print("@{}", .{operand});
} else if (operand.toInterned()) |ip_index| {
const pt = w.pt;
const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf());
const zcu = w.zcu;
const ty = Type.fromInterned(zcu.intern_pool.indexToKey(ip_index).typeOf());
try s.print("<{f}, {f}>", .{
ty.fmt(pt),
Value.fromInterned(ip_index).fmtValue(pt),
ty.fmt(zcu),
Value.fromInterned(ip_index).fmtValue(w.zcu),
});
} else {
return w.writeInstIndex(s, operand.toIndex().?, dies);
@@ -1042,7 +1042,7 @@ const Writer = struct {
}
fn typeOfIndex(w: *Writer, inst: Air.Inst.Index) Type {
const zcu = w.pt.zcu;
const zcu = w.zcu;
return w.air.typeOfIndex(inst, &zcu.intern_pool);
}
};
+384 -381
View File
File diff suppressed because it is too large. Load diff
+21 -19
View File
@@ -321,10 +321,11 @@ fn failUnsupportedResultType(
) Zcu.SemaError {
@branchHint(.cold);
const sema = self.sema;
const gpa = sema.gpa;
const pt = sema.pt;
const zcu = pt.zcu;
const gpa = zcu.comp.gpa;
return sema.failWithOwnedErrorMsg(self.block, msg: {
const msg = try sema.errMsg(self.import_src, "type '{f}' is not available in ZON", .{ty.fmt(pt)});
const msg = try sema.errMsg(self.import_src, "type '{f}' is not available in ZON", .{ty.fmt(zcu)});
errdefer msg.destroy(gpa);
if (opt_note) |n| try sema.errNote(self.import_src, msg, "{s}", .{n});
break :msg msg;
@@ -344,9 +345,9 @@ fn fail(
}
fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index {
const pt = self.sema.pt;
const zcu = self.sema.pt.zcu;
return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) {
error.WrongType => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(pt)}),
error.WrongType => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(zcu)}),
else => |e| return e,
};
}
@@ -357,20 +358,21 @@ fn lowerExprKnownResTyInner(
res_ty: Type,
) (CompileError || error{WrongType})!InternPool.Index {
const pt = self.sema.pt;
switch (res_ty.zigTypeTag(pt.zcu)) {
const zcu = pt.zcu;
switch (res_ty.zigTypeTag(zcu)) {
.optional => return pt.intern(.{
.opt = .{
.ty = res_ty.toIntern(),
.val = if (node.get(self.zoir.*) == .null) b: {
break :b .none;
} else b: {
const child_type = res_ty.optionalChild(pt.zcu);
const child_type = res_ty.optionalChild(zcu);
break :b try self.lowerExprKnownResTyInner(node, child_type);
},
},
}),
.pointer => {
const ptr_info = res_ty.ptrInfo(pt.zcu);
const ptr_info = res_ty.ptrInfo(zcu);
switch (ptr_info.flags.size) {
.one => return pt.intern(.{ .ptr = .{
.ty = res_ty.toIntern(),
@@ -411,7 +413,7 @@ fn lowerExprKnownResTyInner(
.frame,
.@"anyframe",
.void,
=> return self.fail(node, "type '{f}' not available in ZON", .{res_ty.fmt(pt)}),
=> return self.fail(node, "type '{f}' not available in ZON", .{res_ty.fmt(zcu)}),
}
}
@@ -442,7 +444,7 @@ fn lowerInt(
if (lhs_info.signedness == .unsigned and rhs < 0) return self.fail(
node,
"type '{f}' cannot represent integer value '{d}'",
.{ res_ty.fmt(self.sema.pt), rhs },
.{ res_ty.fmt(self.sema.pt.zcu), rhs },
);
// If lhs has less than the 32 bits rhs can hold, we need to check the max and
@@ -458,7 +460,7 @@ fn lowerInt(
return self.fail(
node,
"type '{f}' cannot represent integer value '{d}'",
.{ res_ty.fmt(self.sema.pt), rhs },
.{ res_ty.fmt(self.sema.pt.zcu), rhs },
);
}
}
@@ -476,7 +478,7 @@ fn lowerInt(
return self.fail(
node,
"type '{f}' cannot represent integer value '{d}'",
.{ res_ty.fmt(self.sema.pt), val },
.{ res_ty.fmt(self.sema.pt.zcu), val },
);
}
}
@@ -497,7 +499,7 @@ fn lowerInt(
.inexact => return self.fail(
node,
"fractional component prevents float value '{d}' from coercion to type '{f}'",
.{ val, res_ty.fmt(self.sema.pt) },
.{ val, res_ty.fmt(self.sema.pt.zcu) },
),
.exact => {},
}
@@ -508,7 +510,7 @@ fn lowerInt(
return self.fail(
node,
"type '{f}' cannot represent integer value '{d}'",
.{ res_ty.fmt(self.sema.pt), val },
.{ res_ty.fmt(self.sema.pt.zcu), val },
);
}
@@ -530,7 +532,7 @@ fn lowerInt(
return self.fail(
node,
"type '{f}' cannot represent integer value '{d}'",
.{ res_ty.fmt(self.sema.pt), val },
.{ res_ty.fmt(self.sema.pt.zcu), val },
);
}
}
@@ -564,7 +566,7 @@ fn lowerFloat(
if (res_ty.toIntern() == .comptime_float_type) return self.fail(
node,
"expected type '{f}'",
.{res_ty.fmt(self.sema.pt)},
.{res_ty.fmt(self.sema.pt.zcu)},
);
break :b try self.sema.pt.floatValue(res_ty, std.math.inf(f128));
},
@@ -572,7 +574,7 @@ fn lowerFloat(
if (res_ty.toIntern() == .comptime_float_type) return self.fail(
node,
"expected type '{f}'",
.{res_ty.fmt(self.sema.pt)},
.{res_ty.fmt(self.sema.pt.zcu)},
);
break :b try self.sema.pt.floatValue(res_ty, -std.math.inf(f128));
},
@@ -580,7 +582,7 @@ fn lowerFloat(
if (res_ty.toIntern() == .comptime_float_type) return self.fail(
node,
"expected type '{f}'",
.{res_ty.fmt(self.sema.pt)},
.{res_ty.fmt(self.sema.pt.zcu)},
);
break :b try self.sema.pt.floatValue(res_ty, std.math.nan(f128));
},
@@ -645,7 +647,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I
node,
"enum {f} has no member named '{f}'",
.{
res_ty.fmt(self.sema.pt),
res_ty.fmt(self.sema.pt.zcu),
std.zig.fmtId(field_name.get(self.zoir.*)),
},
);
@@ -939,7 +941,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
.struct_literal => b: {
const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.zoir.*)) {
.struct_literal => |fields| fields,
else => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(self.sema.pt)}),
else => return self.fail(node, "expected type '{f}'", .{res_ty.fmt(self.sema.pt.zcu)}),
};
if (fields.names.len != 1) {
return error.WrongType;
+25 -25
View File
@@ -317,7 +317,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
try sema.ensureLayoutResolved(field_ty, field_ty_src, .field);
if (field_ty.zigTypeTag(zcu) == .@"opaque") {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
try sema.addDeclaredHereNote(msg, field_ty);
@@ -328,7 +328,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
if (field_ty.isSpirvRuntimeArray(zcu)) {
if (struct_obj.layout != .@"extern") {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(struct_ty.srcLoc(zcu), "non-extern struct cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(struct_ty.srcLoc(zcu), "non-extern struct cannot contain fields of type '{f}'", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_name_src, msg, "while checking this field", .{});
break :msg msg;
@@ -336,7 +336,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
}
if (field_index != fields_len - 1) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(struct_ty.srcLoc(zcu), "struct field of type '{f}' must be the last field", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(struct_ty.srcLoc(zcu), "struct field of type '{f}' must be the last field", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_name_src, msg, "while checking this field", .{});
break :msg msg;
@@ -346,7 +346,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
const elem_ty: Type = field_ty.childType(zcu);
if (elem_ty.zigTypeTag(zcu) == .spirv) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "cannot embed SPIR-V type '{f}' in struct", .{elem_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "cannot embed SPIR-V type '{f}' in struct", .{elem_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
try sema.addDeclaredHereNote(msg, field_ty);
@@ -355,7 +355,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
}
} else {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "cannot directly embed SPIR-V type '{f}' in struct", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "cannot directly embed SPIR-V type '{f}' in struct", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
try sema.addDeclaredHereNote(msg, field_ty);
@@ -366,7 +366,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
if (struct_obj.layout == .@"extern" and !field_ty.validateExtern(.struct_field, zcu)) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .struct_field);
try sema.addDeclaredHereNote(msg, field_ty);
@@ -523,7 +523,7 @@ fn resolvePackedStructLayout(
try sema.ensureLayoutResolved(field_ty, field_ty_src, .field);
if (field_ty.zigTypeTag(zcu) == .@"opaque") {
return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
try sema.addDeclaredHereNote(msg, field_ty);
@@ -531,7 +531,7 @@ fn resolvePackedStructLayout(
});
}
if (field_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason);
break :msg msg;
@@ -575,7 +575,7 @@ fn resolvePackedStructLayout(
block,
backing_int_ty_src,
"expected backing integer type, found '{f}'",
.{backing_ty.fmt(pt)},
.{backing_ty.fmt(zcu)},
);
if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: {
const src = struct_ty.srcLoc(zcu);
@@ -585,7 +585,7 @@ fn resolvePackedStructLayout(
backing_int_ty_src,
msg,
"backing integer '{f}' has bit width '{d}'",
.{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) },
.{ backing_ty.fmt(zcu), backing_ty.bitSize(zcu) },
);
try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits});
break :msg msg;
@@ -798,7 +798,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
&block,
block.src(.container_arg),
"expected enum tag type, found '{f}'",
.{tag_ty.fmt(pt)},
.{tag_ty.fmt(zcu)},
);
break :validated_tag_ty tag_ty;
},
@@ -947,7 +947,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
try sema.ensureLayoutResolved(field_ty, field_ty_src, .field);
if (field_ty.zigTypeTag(zcu) == .@"opaque") {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
try sema.addDeclaredHereNote(msg, field_ty);
@@ -956,7 +956,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
}
if (field_ty.zigTypeTag(zcu) == .spirv) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "SPIR-V type '{f}' have unknown size and therefore cannot be directly embedded in unions", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "SPIR-V type '{f}' have unknown size and therefore cannot be directly embedded in unions", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.addDeclaredHereNote(msg, field_ty);
break :msg msg;
@@ -964,7 +964,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
}
if (union_obj.layout == .@"extern" and !field_ty.validateExtern(.union_field, zcu)) {
return sema.failWithOwnedErrorMsg(&block, msg: {
const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .union_field);
try sema.addDeclaredHereNote(msg, field_ty);
@@ -1081,7 +1081,7 @@ fn failUnionFieldMismatch(sema: *Sema, block: *Block, union_field_names: []const
}
const union_field_src = block.src(.{ .container_field_name = @intCast(union_field_index) });
return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name.fmt(ip), enum_tag_ty.fmt(pt) });
const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name.fmt(ip), enum_tag_ty.fmt(zcu) });
errdefer msg.destroy(gpa);
try sema.addDeclaredHereNote(msg, enum_tag_ty);
break :msg msg;
@@ -1153,7 +1153,7 @@ fn resolvePackedUnionLayout(
try sema.ensureLayoutResolved(field_ty, field_ty_src, .field);
if (field_ty.zigTypeTag(zcu) == .@"opaque") {
return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
try sema.addDeclaredHereNote(msg, field_ty);
@@ -1161,7 +1161,7 @@ fn resolvePackedUnionLayout(
});
}
if (field_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(zcu)});
errdefer msg.destroy(gpa);
try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason);
break :msg msg;
@@ -1199,7 +1199,7 @@ fn resolvePackedUnionLayout(
block,
backing_int_ty_src,
"expected backing integer type, found '{f}'",
.{backing_ty.fmt(pt)},
.{backing_ty.fmt(zcu)},
);
const backing_int_bits = backing_ty.intInfo(zcu).bits;
for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| {
@@ -1209,12 +1209,12 @@ fn resolvePackedUnionLayout(
const field_ty_src = block.src(.{ .container_field_type = @intCast(field_idx) });
const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits });
try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(zcu), field_bits });
try sema.errNote(
backing_int_ty_src,
msg,
"backing integer '{f}' has bit width '{d}'",
.{ backing_ty.fmt(pt), backing_int_bits },
.{ backing_ty.fmt(zcu), backing_int_bits },
);
try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{});
break :msg msg;
@@ -1233,8 +1233,8 @@ fn resolvePackedUnionLayout(
const field_ty_src = block.src(.{ .container_field_type = @intCast(field_idx) });
const msg = try sema.errMsg(field_ty_src, "field bit width does not match earlier field", .{});
errdefer msg.destroy(gpa);
try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits });
try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(pt), first_field_bits });
try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(zcu), field_bits });
try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(zcu), first_field_bits });
try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{});
break :msg msg;
});
@@ -1421,7 +1421,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
&block,
block.src(.container_arg),
"expected integer tag type, found '{f}'",
.{int_tag_ty.fmt(pt)},
.{int_tag_ty.fmt(zcu)},
),
}
break :ty int_tag_ty;
@@ -1532,7 +1532,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
&block,
field_val_src,
"enum tag value '{f}' too large for type '{f}'",
.{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
.{ result.val.fmtValueSema(sema), int_tag_ty.fmt(zcu) },
);
const val = result.val.toIntern();
enum_obj.field_values.get(ip)[field_idx] = val;
@@ -1542,7 +1542,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
return sema.failWithOwnedErrorMsg(&block, msg: {
const prev_field_val_src = block.src(.{ .container_field_value = prev_field_index });
const msg = try sema.errMsg(field_val_src, "enum tag value '{f}' for field '{f}' already taken", .{
Value.fromInterned(field_val).fmtValueSema(pt, sema),
Value.fromInterned(field_val).fmtValueSema(sema),
enum_obj.field_names.get(ip)[field_idx].fmt(ip),
});
errdefer msg.destroy(gpa);
+144 -162
View File
@@ -412,21 +412,14 @@ pub fn eql(a: Type, b: Type) bool {
pub const format = @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");
pub const Formatter = std.fmt.Alt(Format, Format.default);
pub fn fmt(ty: Type, pt: Zcu.PerThread) Formatter {
return .{ .data = .{
.ty = ty,
.pt = pt,
} };
pub fn fmt(ty: Type, zcu: *Zcu) Formatter {
return .{ .ty = ty, .zcu = zcu };
}
const Format = struct {
pub const Formatter = struct {
ty: Type,
pt: Zcu.PerThread,
fn default(f: Format, writer: *std.Io.Writer) std.Io.Writer.Error!void {
return print(f.ty, writer, f.pt, null);
zcu: *Zcu,
pub fn format(f: Formatter, writer: *std.Io.Writer) std.Io.Writer.Error!void {
return print(f.ty, writer, f.zcu, null);
}
};
@@ -442,9 +435,9 @@ pub fn dump(start_type: Type, writer: *std.Io.Writer) std.Io.Writer.Error!void {
/// Prints a name suitable for `@typeName`.
/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.
pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Comparison) std.Io.Writer.Error!void {
pub fn print(ty: Type, writer: *std.Io.Writer, zcu: *Zcu, ctx: ?*Comparison) std.Io.Writer.Error!void {
if (ctx) |c| {
const should_dedupe = shouldDedupeType(ty, c, pt) catch |err| switch (err) {
const should_dedupe = shouldDedupeType(ty, c, zcu) catch |err| switch (err) {
error.OutOfMemory => return error.WriteFailed,
};
switch (should_dedupe) {
@@ -453,7 +446,6 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
}
}
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
switch (ip.indexToKey(ty.toIntern())) {
.undef => return writer.writeAll("@as(type, undefined)"),
@@ -469,8 +461,8 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
if (info.sentinel != .none) switch (info.flags.size) {
.one, .c => unreachable,
.many => try writer.print("[*:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),
.slice => try writer.print("[:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(pt)}),
.many => try writer.print("[*:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(zcu)}),
.slice => try writer.print("[:{f}]", .{Value.fromInterned(info.sentinel).fmtValue(zcu)}),
} else switch (info.flags.size) {
.one => try writer.writeAll("*"),
.many => try writer.writeAll("[*]"),
@@ -485,7 +477,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
const alignment = if (info.flags.alignment != .none)
info.flags.alignment
else
Type.fromInterned(info.child).abiAlignment(pt.zcu);
Type.fromInterned(info.child).abiAlignment(zcu);
try writer.print("align({d}", .{alignment.toByteUnits() orelse 0});
if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {
@@ -504,39 +496,39 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
if (info.flags.is_const) try writer.writeAll("const ");
if (info.flags.is_volatile) try writer.writeAll("volatile ");
try print(Type.fromInterned(info.child), writer, pt, ctx);
try print(Type.fromInterned(info.child), writer, zcu, ctx);
return;
},
.array_type => |array_type| {
if (array_type.sentinel == .none) {
try writer.print("[{d}]", .{array_type.len});
try print(Type.fromInterned(array_type.child), writer, pt, ctx);
try print(Type.fromInterned(array_type.child), writer, zcu, ctx);
} else {
try writer.print("[{d}:{f}]", .{
array_type.len,
Value.fromInterned(array_type.sentinel).fmtValue(pt),
Value.fromInterned(array_type.sentinel).fmtValue(zcu),
});
try print(Type.fromInterned(array_type.child), writer, pt, ctx);
try print(Type.fromInterned(array_type.child), writer, zcu, ctx);
}
return;
},
.vector_type => |vector_type| {
try writer.print("@Vector({d}, ", .{vector_type.len});
try print(Type.fromInterned(vector_type.child), writer, pt, ctx);
try print(Type.fromInterned(vector_type.child), writer, zcu, ctx);
try writer.writeAll(")");
return;
},
.opt_type => |child| {
try writer.writeByte('?');
return print(Type.fromInterned(child), writer, pt, ctx);
return print(Type.fromInterned(child), writer, zcu, ctx);
},
.error_union_type => |error_union_type| {
try print(Type.fromInterned(error_union_type.error_set_type), writer, pt, ctx);
try print(Type.fromInterned(error_union_type.error_set_type), writer, zcu, ctx);
try writer.writeByte('!');
if (error_union_type.payload_type == .generic_poison_type) {
try writer.writeAll("anytype");
} else {
try print(Type.fromInterned(error_union_type.payload_type), writer, pt, ctx);
try print(Type.fromInterned(error_union_type.payload_type), writer, zcu, ctx);
}
return;
},
@@ -618,8 +610,8 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, val, i| {
try writer.writeAll(if (i == 0) " " else ", ");
if (val != .none) try writer.writeAll("comptime ");
try print(Type.fromInterned(field_ty), writer, pt, ctx);
if (val != .none) try writer.print(" = {f}", .{Value.fromInterned(val).fmtValue(pt)});
try print(Type.fromInterned(field_ty), writer, zcu, ctx);
if (val != .none) try writer.print(" = {f}", .{Value.fromInterned(val).fmtValue(zcu)});
}
try writer.writeAll(" }");
},
@@ -643,12 +635,12 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
.image => try writer.writeAll("@SpirvType(.image)"),
.sampled_image => {
try writer.writeAll("@SpirvType(.sampled_image, ");
try print(Type.fromInterned(info.ty), writer, pt, ctx);
try print(Type.fromInterned(info.ty), writer, zcu, ctx);
try writer.writeAll(")");
},
.runtime_array => {
try writer.writeAll("@SpirvType(.runtime_array, ");
try print(Type.fromInterned(info.ty), writer, pt, ctx);
try print(Type.fromInterned(info.ty), writer, zcu, ctx);
try writer.writeAll(")");
},
}
@@ -672,7 +664,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
if (param_ty == .generic_poison_type) {
try writer.writeAll("anytype");
} else {
try print(Type.fromInterned(param_ty), writer, pt, ctx);
try print(Type.fromInterned(param_ty), writer, zcu, ctx);
}
}
if (fn_info.is_var_args) {
@@ -699,13 +691,13 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
if (fn_info.return_type == .generic_poison_type) {
try writer.writeAll("anytype");
} else {
try print(Type.fromInterned(fn_info.return_type), writer, pt, ctx);
try print(Type.fromInterned(fn_info.return_type), writer, zcu, ctx);
}
},
.anyframe_type => |child| {
if (child == .none) return writer.writeAll("anyframe");
try writer.writeAll("anyframe->");
return print(Type.fromInterned(child), writer, pt, ctx);
return print(Type.fromInterned(child), writer, zcu, ctx);
},
// values, not types
@@ -2872,11 +2864,62 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type;
assert(ptr_info.flags.size == .one or ptr_info.flags.size == .c);
const aggregate_ty: Type = .fromInterned(ptr_info.child);
var field_ptr_info = ptr_info;
field_ptr_info.child = if (aggregate_ty.isSlice(zcu)) switch (field_index) {
Value.slice_ptr_index => aggregate_ty.slicePtrFieldType(zcu).toIntern(),
Value.slice_len_index => .usize_type,
else => unreachable,
} else aggregate_ty.fieldType(field_index, zcu).toIntern();
field_ptr_info.flags.alignment = aggregate_ty.fieldPtrAlign(ptr_info.flags.alignment, field_index, zcu);
if (aggregate_ty.zigTypeTag(zcu) == .@"struct" and
aggregate_ty.containerLayout(zcu) == .@"packed")
{
field_ptr_info.packed_offset = packed_offset: {
comptime assert(Type.packed_struct_layout_version == 2);
const bit_offset = zcu.structPackedFieldBitOffset(
ip.loadStructType(aggregate_ty.toIntern()),
field_index,
);
break :packed_offset if (ptr_info.packed_offset.host_size != 0) .{
.host_size = ptr_info.packed_offset.host_size,
.bit_offset = ptr_info.packed_offset.bit_offset + bit_offset,
} else .{
.host_size = switch (zcu.comp.getZigBackend()) {
else => @intCast((aggregate_ty.bitSize(zcu) + 7) / 8),
.stage2_x86_64, .stage2_c => @intCast(aggregate_ty.abiSize(zcu)),
},
.bit_offset = ptr_info.packed_offset.bit_offset + bit_offset,
};
};
}
return pt.ptrType(field_ptr_info);
}
pub fn fieldPtrAlign(
aggregate_ty: Type,
aggregate_ptr_align: Alignment,
field_index: u32,
zcu: *const Zcu,
) Alignment {
const ip = &zcu.intern_pool;
aggregate_ty.assertHasLayout(zcu);
const aggregate_ty_align = aggregate_ty.abiAlignment(zcu);
const aggregate_align: Alignment = switch (aggregate_ptr_align) {
.none => aggregate_ty_align,
else => |a| a,
};
// We only exit this `switch` for default-layout aggregates, where the field pointer alignment
// is a simple minimum of the aggregate pointer alignment and the field alignment.
// `field_align` is `.none` if there is no explicit alignment annotation.
const field_ty: Type, const field_align: Alignment = switch (aggregate_ty.zigTypeTag(zcu)) {
// `field_explicit_align` is `.none` if there is no explicit alignment annotation.
const field_ty: Type, const field_explicit_align: Alignment = switch (aggregate_ty.zigTypeTag(zcu)) {
.@"struct" => switch (aggregate_ty.containerLayout(zcu)) {
.auto => field: {
if (aggregate_ty.isTuple(zcu)) {
@@ -2893,56 +2936,21 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
// `extern struct { x: u32, y: u16 }`, the `y` field is 4-byte aligned.
const field_ty = aggregate_ty.fieldType(field_index, zcu);
const field_offset = aggregate_ty.structFieldOffset(field_index, zcu);
const parent_align = switch (ptr_info.flags.alignment) {
.none => aggregate_ty.abiAlignment(zcu),
else => |a| a,
};
const actual_field_align = switch (field_offset) {
0 => parent_align,
else => parent_align.minStrict(.fromLog2Units(@ctz(field_offset))),
};
const field_ptr_align: Alignment = a: {
if (ptr_info.flags.alignment == .none and
aggregate_ty.explicitFieldAlignment(field_index, zcu) == .none and
actual_field_align == field_ty.abiAlignment(zcu))
{
// There's no user-specified 'align' in sight, and the alignment from the
// field offset matches the field type's natural alignment, so just use a
// default-aligned pointer.
break :a .none;
}
break :a actual_field_align;
};
var field_ptr_info = ptr_info;
field_ptr_info.child = field_ty.toIntern();
field_ptr_info.flags.alignment = field_ptr_align;
return pt.ptrType(field_ptr_info);
},
.@"packed" => {
var field_ptr_info = ptr_info;
if (field_ptr_info.flags.alignment == .none) {
field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu);
const field_align = aggregate_align.offset(field_offset);
if (aggregate_ptr_align == .none and
aggregate_ty.explicitFieldAlignment(field_index, zcu) == .none and
field_align == field_ty.abiAlignment(zcu))
{
// There's no user-specified 'align' in sight, and the alignment from the
// field offset matches the field type's natural alignment, so just use a
// default-aligned pointer.
return .none;
}
field_ptr_info.packed_offset = packed_offset: {
comptime assert(Type.packed_struct_layout_version == 2);
const bit_offset = zcu.structPackedFieldBitOffset(
ip.loadStructType(aggregate_ty.toIntern()),
field_index,
);
break :packed_offset if (ptr_info.packed_offset.host_size != 0) .{
.host_size = ptr_info.packed_offset.host_size,
.bit_offset = ptr_info.packed_offset.bit_offset + bit_offset,
} else .{
.host_size = switch (zcu.comp.getZigBackend()) {
else => @intCast((aggregate_ty.bitSize(zcu) + 7) / 8),
.stage2_x86_64, .stage2_c => @intCast(aggregate_ty.abiSize(zcu)),
},
.bit_offset = ptr_info.packed_offset.bit_offset + bit_offset,
};
};
field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern();
return pt.ptrType(field_ptr_info);
return field_align;
},
.@"packed" => return aggregate_align,
},
.@"union" => switch (aggregate_ty.containerLayout(zcu)) {
.auto => field: {
@@ -2952,30 +2960,14 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
union_obj.field_aligns.getOrNone(ip, field_index),
};
},
.@"extern" => {
.@"extern", .@"packed" => {
// The alignment always matches that of the union pointer. If the union pointer is
// default aligned (`.none`), we may need to explicitly align the result pointer.
const field_ty = aggregate_ty.fieldType(field_index, zcu);
var field_ptr_info = ptr_info;
field_ptr_info.child = field_ty.toIntern();
if (field_ptr_info.flags.alignment == .none and
Alignment.compareStrict(field_ty.abiAlignment(zcu), .neq, aggregate_ty.abiAlignment(zcu)))
{
field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu);
}
return pt.ptrType(field_ptr_info);
},
.@"packed" => {
const field_ty = aggregate_ty.fieldType(field_index, zcu);
var field_ptr_info = ptr_info;
if (field_ptr_info.flags.alignment == .none) {
const resolved_align = aggregate_ty.abiAlignment(zcu);
if (field_ty.abiAlignment(zcu) != resolved_align) {
field_ptr_info.flags.alignment = resolved_align;
}
}
field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern();
return pt.ptrType(field_ptr_info);
const field_ty_align = aggregate_ty.fieldType(field_index, zcu).abiAlignment(zcu);
return switch (aggregate_ptr_align) {
.none => if (field_ty_align == aggregate_ty_align) .none else aggregate_ty_align,
else => |a| a,
};
},
},
.pointer => field: {
@@ -2988,39 +2980,31 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator
},
else => unreachable,
};
const field_ptr_align: Alignment = a: {
if (aggregate_ty.zigTypeTag(zcu) == .@"struct" and aggregate_ty.structFieldIsComptime(field_index, zcu)) {
// For `comptime` fields, just use exactly what was specified, or ABI alignment if nothing was specified.
break :a field_align;
}
const actual_field_align = switch (field_align) {
.none => switch (ip.indexToKey(aggregate_ty.toIntern())) {
.struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu),
.ptr_type => Type.usize.abiAlignment(zcu),
else => unreachable,
},
else => |a| a,
};
const actual_aggregate_align = switch (ptr_info.flags.alignment) {
.none => aggregate_ty.abiAlignment(zcu),
else => |a| a,
};
if (actual_aggregate_align.compareStrict(.lt, actual_field_align)) {
// Underaligned aggregate; use that alignment.
assert(ptr_info.flags.alignment != .none);
break :a actual_aggregate_align;
}
if (field_align == .none and actual_field_align == field_ty.abiAlignment(zcu)) {
// No explicit annotation on the field (nor an unusual default), and the aggregate
// alignment is irrelevant to us, so return an un-annotated pointer.
break :a .none;
}
break :a actual_field_align;
if (aggregate_ty.zigTypeTag(zcu) == .@"struct" and
aggregate_ty.structFieldIsComptime(field_index, zcu))
{
// For `comptime` fields, just use exactly what was specified, or ABI alignment if nothing was specified.
return field_explicit_align;
}
const field_align = switch (field_explicit_align) {
.none => switch (ip.indexToKey(aggregate_ty.toIntern())) {
.struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu),
.ptr_type => Type.usize.abiAlignment(zcu),
else => unreachable,
},
else => |a| a,
};
var field_ptr_info = ptr_info;
field_ptr_info.flags.alignment = field_ptr_align;
field_ptr_info.child = field_ty.toIntern();
return pt.ptrType(field_ptr_info);
if (aggregate_align.compareStrict(.lt, field_align)) {
// Underaligned aggregate; use that alignment.
assert(aggregate_ptr_align == aggregate_align);
return aggregate_align;
}
if (field_explicit_align == .none and field_align == field_ty.abiAlignment(zcu)) {
// No explicit annotation on the field (nor an unusual default), and the aggregate
// alignment is irrelevant to us, so return an un-annotated pointer.
return .none;
}
return field_align;
}
pub fn containerTypeName(ty: Type, ip: *const InternPool) struct {
@@ -3359,8 +3343,7 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
}
/// Recursively walks the type and marks for each subtype how many times it has been seen
fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.array_hash_map.Auto(Type, u16)) error{OutOfMemory}!void {
const zcu = pt.zcu;
fn collectSubtypes(ty: Type, zcu: *Zcu, visited: *std.array_hash_map.Auto(Type, u16)) error{OutOfMemory}!void {
const ip = &zcu.intern_pool;
const gop = try visited.getOrPut(zcu.gpa, ty);
@@ -3371,34 +3354,34 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.array_hash_map.Aut
}
switch (ip.indexToKey(ty.toIntern())) {
.ptr_type => try collectSubtypes(Type.fromInterned(ty.ptrInfo(zcu).child), pt, visited),
.array_type => |array_type| try collectSubtypes(Type.fromInterned(array_type.child), pt, visited),
.vector_type => |vector_type| try collectSubtypes(Type.fromInterned(vector_type.child), pt, visited),
.opt_type => |child| try collectSubtypes(Type.fromInterned(child), pt, visited),
.ptr_type => try collectSubtypes(Type.fromInterned(ty.ptrInfo(zcu).child), zcu, visited),
.array_type => |array_type| try collectSubtypes(Type.fromInterned(array_type.child), zcu, visited),
.vector_type => |vector_type| try collectSubtypes(Type.fromInterned(vector_type.child), zcu, visited),
.opt_type => |child| try collectSubtypes(Type.fromInterned(child), zcu, visited),
.error_union_type => |error_union_type| {
try collectSubtypes(Type.fromInterned(error_union_type.error_set_type), pt, visited);
try collectSubtypes(Type.fromInterned(error_union_type.error_set_type), zcu, visited);
if (error_union_type.payload_type != .generic_poison_type) {
try collectSubtypes(Type.fromInterned(error_union_type.payload_type), pt, visited);
try collectSubtypes(Type.fromInterned(error_union_type.payload_type), zcu, visited);
}
},
.tuple_type => |tuple| {
for (tuple.types.get(ip)) |field_ty| {
try collectSubtypes(Type.fromInterned(field_ty), pt, visited);
try collectSubtypes(Type.fromInterned(field_ty), zcu, visited);
}
},
.func_type => |fn_info| {
const param_types = fn_info.param_types.get(&zcu.intern_pool);
for (param_types) |param_ty| {
if (param_ty != .generic_poison_type) {
try collectSubtypes(Type.fromInterned(param_ty), pt, visited);
try collectSubtypes(Type.fromInterned(param_ty), zcu, visited);
}
}
if (fn_info.return_type != .generic_poison_type) {
try collectSubtypes(Type.fromInterned(fn_info.return_type), pt, visited);
try collectSubtypes(Type.fromInterned(fn_info.return_type), zcu, visited);
}
},
.anyframe_type => |child| try collectSubtypes(Type.fromInterned(child), pt, visited),
.anyframe_type => |child| try collectSubtypes(Type.fromInterned(child), zcu, visited),
// leaf types
.undef,
@@ -3435,7 +3418,7 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.array_hash_map.Aut
}
}
fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMemory}!Comparison.DedupeEntry {
fn shouldDedupeType(ty: Type, ctx: *Comparison, zcu: *Zcu) error{OutOfMemory}!Comparison.DedupeEntry {
if (ctx.type_occurrences.get(ty)) |occ| {
if (ctx.type_dedupe_cache.get(ty)) |cached| {
return cached;
@@ -3443,7 +3426,7 @@ fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMe
var discarding: std.Io.Writer.Discarding = .init(&.{});
print(ty, &discarding.writer, pt, null) catch
print(ty, &discarding.writer, zcu, null) catch
unreachable; // we are writing into a discarding writer, it should never fail
const type_len: i32 = @intCast(discarding.count);
@@ -3460,7 +3443,7 @@ fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMe
break :b .{ .dedupe = .{ .index = ctx.placeholder_index - 1 } };
} else .dont_dedupe;
try ctx.type_dedupe_cache.put(pt.zcu.gpa, ty, entry);
try ctx.type_dedupe_cache.put(zcu.comp.gpa, ty, entry);
return entry;
} else {
@@ -3491,38 +3474,37 @@ pub const Comparison = struct {
dedupe: Placeholder,
};
pub fn init(types: []const Type, pt: Zcu.PerThread) error{OutOfMemory}!Comparison {
pub fn init(types: []const Type, zcu: *Zcu) error{OutOfMemory}!Comparison {
var cmp: Comparison = .{
.type_occurrences = .empty,
.type_dedupe_cache = .empty,
.placeholder_index = 0,
};
errdefer cmp.deinit(pt);
errdefer cmp.deinit(zcu.comp.gpa);
for (types) |ty| {
try collectSubtypes(ty, pt, &cmp.type_occurrences);
try collectSubtypes(ty, zcu, &cmp.type_occurrences);
}
return cmp;
}
pub fn deinit(cmp: *Comparison, pt: Zcu.PerThread) void {
const gpa = pt.zcu.gpa;
pub fn deinit(cmp: *Comparison, gpa: Allocator) void {
cmp.type_occurrences.deinit(gpa);
cmp.type_dedupe_cache.deinit(gpa);
}
pub fn fmtType(ctx: *Comparison, ty: Type, pt: Zcu.PerThread) Comparison.Formatter {
return .{ .ty = ty, .ctx = ctx, .pt = pt };
pub fn fmtType(ctx: *Comparison, ty: Type, zcu: *Zcu) Comparison.Formatter {
return .{ .ty = ty, .ctx = ctx, .zcu = zcu };
}
pub const Formatter = struct {
ty: Type,
ctx: *Comparison,
pt: Zcu.PerThread,
zcu: *Zcu,
pub fn format(self: Comparison.Formatter, writer: anytype) error{WriteFailed}!void {
print(self.ty, writer, self.pt, self.ctx) catch return error.WriteFailed;
print(self.ty, writer, self.zcu, self.ctx) catch return error.WriteFailed;
}
};
};
+326 -201
View File
@@ -34,19 +34,19 @@ pub fn fmtDebug(val: Value) std.fmt.Alt(Value, dump) {
return .{ .data = val };
}
pub fn fmtValue(val: Value, pt: Zcu.PerThread) std.fmt.Alt(print_value.FormatContext, print_value.format) {
pub fn fmtValue(val: Value, zcu: *Zcu) std.fmt.Alt(print_value.FormatContext, print_value.format) {
return .{ .data = .{
.val = val,
.pt = pt,
.zcu = zcu,
.opt_sema = null,
.depth = 3,
} };
}
pub fn fmtValueSema(val: Value, pt: Zcu.PerThread, sema: *Sema) std.fmt.Alt(print_value.FormatContext, print_value.formatSema) {
pub fn fmtValueSema(val: Value, sema: *Sema) std.fmt.Alt(print_value.FormatContext, print_value.formatSema) {
return .{ .data = .{
.val = val,
.pt = pt,
.zcu = sema.pt.zcu,
.opt_sema = sema,
.depth = 3,
} };
@@ -1890,167 +1890,233 @@ pub fn getOffsetPtr(ptr_val: Value, byte_off: u64, new_ty: Type, pt: Zcu.PerThre
return Value.fromInterned(try pt.intern(.{ .ptr = ptr }));
}
pub const PointerDeriveStep = union(enum) {
int: struct {
addr: u64,
ptr_ty: Type,
},
nav_ptr: InternPool.Nav.Index,
uav_ptr: InternPool.Key.Ptr.BaseAddr.Uav,
comptime_alloc_ptr: struct {
idx: InternPool.ComptimeAllocIndex,
val: Value,
ptr_ty: Type,
},
comptime_field_ptr: Value,
eu_payload_ptr: struct {
parent: *PointerDeriveStep,
/// This type will never be cast: it is provided for convenience.
result_ptr_ty: Type,
},
opt_payload_ptr: struct {
parent: *PointerDeriveStep,
/// This type will never be cast: it is provided for convenience.
result_ptr_ty: Type,
},
field_ptr: struct {
parent: *PointerDeriveStep,
field_idx: u32,
/// This type will never be cast: it is provided for convenience.
result_ptr_ty: Type,
},
elem_ptr: struct {
parent: *PointerDeriveStep,
elem_idx: u64,
/// This type will never be cast: it is provided for convenience.
result_ptr_ty: Type,
},
offset_and_cast: struct {
parent: *PointerDeriveStep,
byte_offset: u64,
new_ptr_ty: Type,
pub const PointerDerivation = struct {
elem_ty: Type,
/// TODO: investigate eliminating this field. We should *always* know the lengths of arrays
/// which are pointed to, so `.one` should be the only possible case!
size: Size,
@"align": InternPool.Alignment,
@"const": bool,
@"volatile": bool,
@"allowzero": bool,
addr: union(enum) {
int: u64,
nav: InternPool.Nav.Index,
uav: Value,
comptime_field: Value,
comptime_alloc: struct {
idx: InternPool.ComptimeAllocIndex,
val: Value,
},
eu_payload: struct { parent: *PointerDerivation },
opt_payload: struct { parent: *PointerDerivation },
field: struct {
parent: *PointerDerivation,
field_index: u32,
},
elem: struct {
parent: *PointerDerivation,
elem_index: u64,
},
offset_and_cast: struct {
parent: *PointerDerivation,
byte_offset: u64,
},
},
pub fn ptrType(step: PointerDeriveStep, pt: Zcu.PerThread) !Type {
return switch (step) {
.int => |int| int.ptr_ty,
.nav_ptr => |nav| try pt.navPtrType(nav),
.uav_ptr => |uav| Type.fromInterned(uav.orig_ty),
.comptime_alloc_ptr => |info| info.ptr_ty,
.comptime_field_ptr => |val| try pt.singleConstPtrType(val.typeOf(pt.zcu)),
.offset_and_cast => |oac| oac.new_ptr_ty,
inline .eu_payload_ptr, .opt_payload_ptr, .field_ptr, .elem_ptr => |x| x.result_ptr_ty,
};
pub const Size = enum { one, many };
pub fn fmtType(pd: PointerDerivation, zcu: *Zcu) FormatType {
return .{ .pd = pd, .zcu = zcu };
}
pub const FormatType = struct {
pd: PointerDerivation,
zcu: *Zcu,
pub fn format(ctx: FormatType, w: *Io.Writer) Io.Writer.Error!void {
const pd = ctx.pd;
switch (pd.size) {
.one => try w.writeByte('*'),
.many => try w.writeAll("[*]"),
}
if (pd.@"align".toByteUnits()) |align_bytes| {
try w.print("align({d}) ", .{align_bytes});
}
if (pd.@"const") try w.writeAll("const ");
if (pd.@"volatile") try w.writeAll("volatile ");
if (pd.@"allowzero") try w.writeAll("allowzero ");
try pd.elem_ty.print(w, ctx.zcu, null);
}
};
};
/// Given a pointer value, get the sequence of steps to derive it, ideally by taking
/// only field and element pointers with no casts. This can be used by codegen backends
/// which prefer field/elem accesses when lowering constant pointer values.
/// It is also used by the Value printing logic for pointers.
pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, opt_sema: ?*Sema) Allocator.Error!PointerDeriveStep {
const zcu = pt.zcu;
pub fn pointerDerivation(ptr_val: Value, arena: Allocator, zcu: *Zcu, opt_sema: ?*Sema) Allocator.Error!PointerDerivation {
const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr;
const base_derive: PointerDeriveStep = switch (ptr.base_addr) {
.int => return .{ .int = .{
.addr = ptr.byte_offset,
.ptr_ty = Type.fromInterned(ptr.ty),
} },
.nav => |nav| .{ .nav_ptr = nav },
const ptr_ty_info: InternPool.Key.PtrType = info: {
var info = Type.fromInterned(ptr.ty).ptrInfo(zcu);
if (info.packed_offset.host_size != 0) {
// TODO: this function *should* handle packed pointers by returning the derivation of
// the backing int pointer. However, until https://github.com/ziglang/zig/issues/24061
// is implemented, we don't have access to the backing type. For now, fudge things a
// little by pretending that this is a pointer to anyopaque. What could go wrong?
info.child = .anyopaque_type;
}
break :info info;
};
const ptr_size: PointerDerivation.Size = switch (ptr_ty_info.flags.size) {
.one => .one,
.many, .c => .many,
.slice => unreachable,
};
const base_derive: PointerDerivation = switch (ptr.base_addr) {
.int => return .{
.elem_ty = .fromInterned(ptr_ty_info.child),
.size = ptr_size,
.@"align" = ptr_ty_info.flags.alignment,
.@"const" = ptr_ty_info.flags.is_const,
.@"volatile" = ptr_ty_info.flags.is_volatile,
.@"allowzero" = ptr_ty_info.flags.is_allowzero,
.addr = .{ .int = ptr.byte_offset },
},
.nav => |nav| base: {
const resolved = zcu.intern_pool.getNav(nav).resolved.?;
break :base .{
.elem_ty = .fromInterned(resolved.type),
.size = .one,
.@"align" = resolved.@"align",
.@"const" = resolved.@"const",
.@"volatile" = false,
.@"allowzero" = false,
.addr = .{ .nav = nav },
};
},
.uav => |uav| base: {
// A slight tweak: `orig_ty` here is sometimes not `const`, but it ought to be.
// TODO: fix this in the sites interning anon decls!
const const_ty = try pt.ptrType(info: {
var info = Type.fromInterned(uav.orig_ty).ptrInfo(zcu);
info.flags.is_const = true;
break :info info;
});
break :base .{ .uav_ptr = .{
.val = uav.val,
.orig_ty = const_ty.toIntern(),
} };
const orig_ty_info = Type.fromInterned(uav.orig_ty).ptrInfo(zcu);
break :base .{
.elem_ty = .fromInterned(orig_ty_info.child),
.size = .one,
.@"align" = orig_ty_info.flags.alignment,
// A slight tweak: `orig_ty` here is sometimes not `const`, but it ought to be.
// TODO: fix this in the sites interning anon decls!
.@"const" = true,
.@"volatile" = orig_ty_info.flags.is_volatile,
.@"allowzero" = orig_ty_info.flags.is_allowzero,
.addr = .{ .uav = .fromInterned(uav.val) },
};
},
.comptime_alloc => |idx| base: {
const sema = opt_sema.?;
const alloc = sema.getComptimeAlloc(idx);
const val = try alloc.val.intern(pt, arena);
const ty = val.typeOf(zcu);
break :base .{ .comptime_alloc_ptr = .{
.idx = idx,
.val = val,
.ptr_ty = try pt.ptrType(.{
.child = ty.toIntern(),
.flags = .{
.alignment = alloc.alignment,
},
}),
} };
const val = try alloc.val.intern(sema.pt, arena);
break :base .{
.elem_ty = val.typeOf(zcu),
.size = .one,
.@"align" = alloc.alignment,
.@"const" = alloc.is_const,
.@"volatile" = false,
.@"allowzero" = false,
.addr = .{ .comptime_alloc = .{
.idx = idx,
.val = val,
} },
};
},
.comptime_field => |val| .{
.elem_ty = Value.fromInterned(val).typeOf(zcu),
.size = .one,
.@"align" = .none,
.@"const" = true,
.@"volatile" = false,
.@"allowzero" = false,
.addr = .{ .comptime_field = .fromInterned(val) },
},
.comptime_field => |val| .{ .comptime_field_ptr = Value.fromInterned(val) },
.eu_payload => |eu_ptr| base: {
const base_ptr = Value.fromInterned(eu_ptr);
const base_ptr_ty = base_ptr.typeOf(zcu);
const parent_step = try arena.create(PointerDeriveStep);
parent_step.* = try pointerDerivation(.fromInterned(eu_ptr), arena, pt, opt_sema);
break :base .{ .eu_payload_ptr = .{
.parent = parent_step,
.result_ptr_ty = try pt.adjustPtrTypeChild(base_ptr_ty, base_ptr_ty.childType(zcu).errorUnionPayload(zcu)),
} };
const parent_step = try arena.create(PointerDerivation);
parent_step.* = try pointerDerivation(.fromInterned(eu_ptr), arena, zcu, opt_sema);
break :base .{
.elem_ty = parent_step.elem_ty.errorUnionPayload(zcu),
.size = .one,
.@"align" = parent_step.@"align",
.@"const" = parent_step.@"const",
.@"volatile" = parent_step.@"volatile",
.@"allowzero" = parent_step.@"allowzero",
.addr = .{ .eu_payload = .{
.parent = parent_step,
} },
};
},
.opt_payload => |opt_ptr| base: {
const base_ptr = Value.fromInterned(opt_ptr);
const base_ptr_ty = base_ptr.typeOf(zcu);
const parent_step = try arena.create(PointerDeriveStep);
parent_step.* = try pointerDerivation(.fromInterned(opt_ptr), arena, pt, opt_sema);
break :base .{ .opt_payload_ptr = .{
.parent = parent_step,
.result_ptr_ty = try pt.adjustPtrTypeChild(base_ptr_ty, base_ptr_ty.childType(zcu).optionalChild(zcu)),
} };
const parent_step = try arena.create(PointerDerivation);
parent_step.* = try pointerDerivation(.fromInterned(opt_ptr), arena, zcu, opt_sema);
break :base .{
.elem_ty = parent_step.elem_ty.optionalChild(zcu),
.size = .one,
.@"align" = parent_step.@"align",
.@"const" = parent_step.@"const",
.@"volatile" = parent_step.@"volatile",
.@"allowzero" = parent_step.@"allowzero",
.addr = .{ .opt_payload = .{
.parent = parent_step,
} },
};
},
.field => |field| base: {
const base_ptr = Value.fromInterned(field.base);
const base_ptr_ty = try pt.ptrType(info: {
var info = base_ptr.typeOf(zcu).ptrInfo(zcu);
info.flags.size = .one;
break :info info;
});
const parent_step = try arena.create(PointerDeriveStep);
parent_step.* = try pointerDerivation(base_ptr, arena, pt, opt_sema);
break :base .{ .field_ptr = .{
.parent = parent_step,
.field_idx = @intCast(field.index),
.result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field.index), pt),
} };
const parent_step = try arena.create(PointerDerivation);
parent_step.* = try pointerDerivation(.fromInterned(field.base), arena, zcu, opt_sema);
break :base .{
.elem_ty = if (parent_step.elem_ty.isSlice(zcu)) switch (field.index) {
Value.slice_ptr_index => parent_step.elem_ty.slicePtrFieldType(zcu),
Value.slice_len_index => .usize,
else => unreachable,
} else parent_step.elem_ty.fieldType(@intCast(field.index), zcu),
.size = .one,
.@"align" = parent_step.elem_ty.fieldPtrAlign(parent_step.@"align", @intCast(field.index), zcu),
.@"const" = parent_step.@"const",
.@"volatile" = parent_step.@"volatile",
.@"allowzero" = parent_step.@"allowzero",
.addr = .{ .field = .{
.parent = parent_step,
.field_index = @intCast(field.index),
} },
};
},
.arr_elem => |arr_elem| base: {
const parent_step = try arena.create(PointerDeriveStep);
parent_step.* = try pointerDerivation(.fromInterned(arr_elem.base), arena, pt, opt_sema);
const parent_ptr_info = (try parent_step.ptrType(pt)).ptrInfo(zcu);
const result_ptr_ty = try pt.ptrType(.{
.child = parent_ptr_info.child,
.flags = flags: {
var flags = parent_ptr_info.flags;
flags.size = .one;
if (flags.alignment != .none) flags.alignment = .minStrict(
flags.alignment,
Type.fromInterned(parent_ptr_info.child).abiAlignment(zcu),
);
break :flags flags;
const parent_step = try arena.create(PointerDerivation);
parent_step.* = try pointerDerivation(.fromInterned(arr_elem.base), arena, zcu, opt_sema);
break :base .{
.elem_ty = parent_step.elem_ty,
.size = .many,
.@"align" = switch (parent_step.@"align") {
.none => .none,
else => |a| a.minStrict(parent_step.elem_ty.abiAlignment(zcu)),
},
});
break :base .{ .elem_ptr = .{
.parent = parent_step,
.elem_idx = arr_elem.index,
.result_ptr_ty = result_ptr_ty,
} };
.@"const" = parent_step.@"const",
.@"volatile" = parent_step.@"volatile",
.@"allowzero" = parent_step.@"allowzero",
.addr = .{ .elem = .{
.parent = parent_step,
.elem_index = arr_elem.index,
} },
};
},
};
if (ptr.byte_offset == 0 and ptr.ty == (try base_derive.ptrType(pt)).toIntern()) {
if (ptr.byte_offset == 0 and
ptr_ty_info.child == base_derive.elem_ty.toIntern() and
ptr_size == base_derive.size and
ptr_ty_info.flags.alignment == base_derive.@"align" and
ptr_ty_info.flags.is_const == base_derive.@"const" and
ptr_ty_info.flags.is_volatile == base_derive.@"volatile" and
ptr_ty_info.flags.is_allowzero == base_derive.@"allowzero")
{
return base_derive;
}
const ptr_ty_info = Type.fromInterned(ptr.ty).ptrInfo(zcu);
const need_child: Type = .fromInterned(ptr_ty_info.child);
if (need_child.comptimeOnly(zcu) or
need_child.zigTypeTag(zcu) == .@"opaque" or
@@ -2058,27 +2124,50 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
{
// No refinement can happen - this pointer is presumably invalid.
// Just offset it.
const parent = try arena.create(PointerDeriveStep);
const parent = try arena.create(PointerDerivation);
parent.* = base_derive;
return .{ .offset_and_cast = .{
.parent = parent,
.byte_offset = ptr.byte_offset,
.new_ptr_ty = Type.fromInterned(ptr.ty),
} };
return .{
.elem_ty = .fromInterned(ptr_ty_info.child),
.size = ptr_size,
.@"align" = ptr_ty_info.flags.alignment,
.@"const" = ptr_ty_info.flags.is_const,
.@"volatile" = ptr_ty_info.flags.is_volatile,
.@"allowzero" = ptr_ty_info.flags.is_allowzero,
.addr = .{ .offset_and_cast = .{
.parent = parent,
.byte_offset = ptr.byte_offset,
} },
};
}
const need_bytes = need_child.abiSize(zcu);
var cur_derive = base_derive;
var cur_offset = ptr.byte_offset;
if (cur_derive.size == .many) {
const parent = try arena.create(PointerDerivation);
parent.* = cur_derive;
cur_derive = .{
.elem_ty = parent.elem_ty,
.size = .one,
.@"align" = parent.@"align",
.@"const" = parent.@"const",
.@"volatile" = parent.@"volatile",
.@"allowzero" = parent.@"allowzero",
.addr = .{ .elem = .{
.parent = parent,
.elem_index = 0,
} },
};
}
// Refine through fields and array elements as much as possible.
if (need_bytes > 0) while (true) {
const cur_ty = (try cur_derive.ptrType(pt)).childType(zcu);
if (cur_ty.toIntern() == need_child.toIntern() and cur_offset == 0) {
if (cur_derive.elem_ty.toIntern() == need_child.toIntern() and cur_offset == 0) {
break;
}
switch (cur_ty.zigTypeTag(zcu)) {
switch (cur_derive.elem_ty.zigTypeTag(zcu)) {
.noreturn,
.type,
.comptime_int,
@@ -2105,71 +2194,105 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
.optional => {
ptr_opt: {
if (!cur_ty.isPtrLikeOptional(zcu)) break :ptr_opt;
if (!cur_derive.elem_ty.isPtrLikeOptional(zcu)) break :ptr_opt;
if (need_child.zigTypeTag(zcu) != .pointer) break :ptr_opt;
switch (need_child.ptrSize(zcu)) {
.one, .many => {},
.slice, .c => break :ptr_opt,
}
const parent = try arena.create(PointerDeriveStep);
const parent = try arena.create(PointerDerivation);
parent.* = cur_derive;
cur_derive = .{ .opt_payload_ptr = .{
.parent = parent,
.result_ptr_ty = try pt.adjustPtrTypeChild(try parent.ptrType(pt), cur_ty.optionalChild(zcu)),
} };
cur_derive = .{
.elem_ty = parent.elem_ty.optionalChild(zcu),
.size = .one,
.@"align" = parent.@"align",
.@"const" = parent.@"const",
.@"volatile" = parent.@"volatile",
.@"allowzero" = parent.@"allowzero",
.addr = .{ .opt_payload = .{
.parent = parent,
} },
};
continue;
}
break;
},
.array => {
const elem_ty = cur_ty.childType(zcu);
const elem_ty = cur_derive.elem_ty.childType(zcu);
const elem_size = elem_ty.abiSize(zcu);
const start_idx = cur_offset / elem_size;
const end_idx = (cur_offset + need_bytes + elem_size - 1) / elem_size;
const start_off = start_idx * elem_size;
if (end_idx == start_idx + 1 and ptr_ty_info.flags.size == .one) {
const parent = try arena.create(PointerDeriveStep);
const parent = try arena.create(PointerDerivation);
parent.* = cur_derive;
cur_derive = .{ .elem_ptr = .{
.parent = parent,
.elem_idx = start_idx,
.result_ptr_ty = try pt.adjustPtrTypeChild(try parent.ptrType(pt), elem_ty),
} };
cur_offset -= start_idx * elem_size;
} else {
// Go into the first element if needed, but don't go any deeper.
if (start_idx > 0) {
const parent = try arena.create(PointerDeriveStep);
parent.* = cur_derive;
cur_derive = .{ .elem_ptr = .{
cur_derive = .{
.elem_ty = elem_ty,
.size = .one,
.@"align" = switch (parent.@"align") {
.none => .none,
else => |a| a.offset(start_off),
},
.@"const" = parent.@"const",
.@"volatile" = parent.@"volatile",
.@"allowzero" = parent.@"allowzero",
.addr = .{ .elem = .{
.parent = parent,
.elem_idx = start_idx,
.result_ptr_ty = try pt.adjustPtrTypeChild(try parent.ptrType(pt), elem_ty),
} };
cur_offset -= start_idx * elem_size;
.elem_index = start_idx,
} },
};
cur_offset -= start_off;
} else {
// Go into the first element if the byte offsets line up neatly, but don't try
// to go any deeper.
if (start_idx > 0 and start_idx * elem_size == cur_offset) {
const parent = try arena.create(PointerDerivation);
parent.* = cur_derive;
cur_derive = .{
.elem_ty = elem_ty,
.size = .one,
.@"align" = switch (parent.@"align") {
.none => .none,
else => |a| a.offset(start_off),
},
.@"const" = parent.@"const",
.@"volatile" = parent.@"volatile",
.@"allowzero" = parent.@"allowzero",
.addr = .{ .elem = .{
.parent = parent,
.elem_index = start_idx,
} },
};
cur_offset -= start_off;
}
break;
}
},
.@"struct" => switch (cur_ty.containerLayout(zcu)) {
.@"struct" => switch (cur_derive.elem_ty.containerLayout(zcu)) {
.auto, .@"packed" => break,
.@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| {
const field_ty = cur_ty.fieldType(field_idx, zcu);
const start_off = cur_ty.structFieldOffset(field_idx, zcu);
.@"extern" => for (0..cur_derive.elem_ty.structFieldCount(zcu)) |field_idx| {
const field_ty = cur_derive.elem_ty.fieldType(field_idx, zcu);
const start_off = cur_derive.elem_ty.structFieldOffset(field_idx, zcu);
const end_off = start_off + field_ty.abiSize(zcu);
if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) {
const base_ptr_ty = try pt.ptrType(info: {
var info = (try cur_derive.ptrType(pt)).ptrInfo(zcu);
info.flags.size = .one;
break :info info;
});
const parent = try arena.create(PointerDeriveStep);
const parent = try arena.create(PointerDerivation);
parent.* = cur_derive;
cur_derive = .{ .field_ptr = .{
.parent = parent,
.field_idx = @intCast(field_idx),
.result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field_idx), pt),
} };
cur_derive = .{
.elem_ty = field_ty,
.size = .one,
.@"align" = switch (parent.@"align") {
.none => .none,
else => |a| a.offset(start_off),
},
.@"const" = parent.@"const",
.@"volatile" = parent.@"volatile",
.@"allowzero" = parent.@"allowzero",
.addr = .{ .field = .{
.parent = parent,
.field_index = @intCast(field_idx),
} },
};
cur_offset -= start_off;
break;
}
@@ -2179,31 +2302,33 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
};
if (cur_offset == 0) compatible: {
const src_ptr_ty_info = (try cur_derive.ptrType(pt)).ptrInfo(zcu);
// We allow silently doing some "coercible" pointer things.
// In particular, we only give up if cv qualifiers are *removed*.
if (src_ptr_ty_info.flags.is_const and !ptr_ty_info.flags.is_const) break :compatible;
if (src_ptr_ty_info.flags.is_volatile and !ptr_ty_info.flags.is_volatile) break :compatible;
if (src_ptr_ty_info.flags.is_allowzero and !ptr_ty_info.flags.is_allowzero) break :compatible;
// Everything else has to match exactly.
if (src_ptr_ty_info.child != ptr_ty_info.child) break :compatible;
if (src_ptr_ty_info.sentinel != ptr_ty_info.sentinel) break :compatible;
if (src_ptr_ty_info.packed_offset != ptr_ty_info.packed_offset) break :compatible;
if (src_ptr_ty_info.flags.size != ptr_ty_info.flags.size) break :compatible;
if (src_ptr_ty_info.flags.alignment != ptr_ty_info.flags.alignment) break :compatible;
if (src_ptr_ty_info.flags.address_space != ptr_ty_info.flags.address_space) break :compatible;
if (src_ptr_ty_info.flags.vector_index != ptr_ty_info.flags.vector_index) break :compatible;
if (cur_derive.@"const" and !ptr_ty_info.flags.is_const) break :compatible;
if (cur_derive.@"volatile" and !ptr_ty_info.flags.is_volatile) break :compatible;
if (cur_derive.@"allowzero" and !ptr_ty_info.flags.is_allowzero) break :compatible;
// Element type and alignment, however, have to match exactly.
if (cur_derive.elem_ty.toIntern() != ptr_ty_info.child) break :compatible;
if (cur_derive.size != ptr_size) break :compatible;
if (cur_derive.@"align" != ptr_ty_info.flags.alignment) break :compatible;
return cur_derive;
}
const parent = try arena.create(PointerDeriveStep);
const parent = try arena.create(PointerDerivation);
parent.* = cur_derive;
return .{ .offset_and_cast = .{
.parent = parent,
.byte_offset = cur_offset,
.new_ptr_ty = Type.fromInterned(ptr.ty),
} };
return .{
.elem_ty = .fromInterned(ptr_ty_info.child),
.size = ptr_size,
.@"align" = ptr_ty_info.flags.alignment,
.@"const" = ptr_ty_info.flags.is_const,
.@"volatile" = ptr_ty_info.flags.is_volatile,
.@"allowzero" = ptr_ty_info.flags.is_allowzero,
.addr = .{ .offset_and_cast = .{
.parent = parent,
.byte_offset = cur_offset,
} },
};
}
const InterpretMode = enum {
+2 -2
View File
@@ -3471,7 +3471,7 @@ fn analyzeFuncBodyInner(
&inner_block,
inner_block.nodeOffset(.zero),
"cannot resolve inferred error set of {s} function type '{f}'",
.{ description, fn_ty.fmt(pt) },
.{ description, fn_ty.fmt(zcu) },
);
}
@@ -4587,6 +4587,6 @@ fn printVerboseAir(
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
try w.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)});
try air.write(w, pt, liveness);
try air.write(w, zcu, liveness);
try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)});
}
+7 -6
View File
@@ -255,7 +255,6 @@ pub fn generateLazySymbol(
) link.EmitError!void {
const tracy = trace(@src());
defer tracy.end();
tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) });
const comp = bin_file.comp;
const zcu = pt.zcu;
@@ -263,9 +262,11 @@ pub fn generateLazySymbol(
const target = &comp.root_mod.resolved_target.result;
const endian = target.cpu.arch.endian();
tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(zcu) });
log.debug("generateLazySymbol: kind = {s}, ty = {f}", .{
@tagName(lazy_sym.kind),
Type.fromInterned(lazy_sym.ty).fmt(pt),
Type.fromInterned(lazy_sym.ty).fmt(zcu),
});
if (lazy_sym.kind == .code) {
@@ -303,7 +304,7 @@ pub fn generateLazySymbol(
}
} else {
return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{
@tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),
@tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(zcu),
});
}
}
@@ -325,7 +326,7 @@ pub fn generateSymbol(
const target = zcu.getTarget();
const endian = target.cpu.arch.endian();
log.debug("generateSymbol: val = {f}", .{val.fmtValue(pt)});
log.debug("generateSymbol: val = {f}", .{val.fmtValue(zcu)});
const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse {
return zcu.comp.link_diags.fail("failed to generate symbol: type size overflow", .{});
@@ -733,7 +734,7 @@ fn lowerUavRef(
const uav_ty = Type.fromInterned(ip.typeOf(uav_val));
const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(pt)});
log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(zcu)});
if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) {
try w.splatByteAll(0xaa, ptr_width_bytes);
@@ -876,7 +877,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
const ip = &zcu.intern_pool;
const ty = val.typeOf(zcu);
log.debug("lowerValue(@as({f}, {f}))", .{ ty.fmt(pt), val.fmtValue(pt) });
log.debug("lowerValue(@as({f}, {f}))", .{ ty.fmt(zcu), val.fmtValue(zcu) });
if (val.isUndef(zcu)) return .undef;
+3 -3
View File
@@ -946,7 +946,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void
isel: *Select,
inst: Air.Inst.Index,
pub fn format(fmt_air: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
fmt_air.isel.air.writeInst(writer, fmt_air.inst, fmt_air.isel.pt, null);
fmt_air.isel.air.writeInst(writer, fmt_air.inst, fmt_air.isel.pt.zcu, null);
}
} {
return .{ .isel = it.isel, .inst = inst };
@@ -7974,11 +7974,11 @@ fn fmtLoopLive(isel: *Select, loop_inst: Air.Inst.Index) struct {
}
fn fmtType(isel: *Select, ty: ZigType) ZigType.Formatter {
return ty.fmt(isel.pt);
return ty.fmt(isel.pt.zcu);
}
fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmtValue)).@"fn".return_type.? {
return constant.fmtValue(isel.pt);
return constant.fmtValue(isel.pt.zcu);
}
fn block(
+112 -90
View File
@@ -740,59 +740,57 @@ pub const DeclGen = struct {
fn renderUav(
dg: *DeclGen,
w: *Writer,
uav: InternPool.Key.Ptr.BaseAddr.Uav,
uav_val: Value,
derivation: Value.PointerDerivation,
location: ValueRenderLocation,
) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const uav_val = Value.fromInterned(uav.val);
const uav_ty = uav_val.typeOf(zcu);
// Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
const ptr_ty: Type = .fromInterned(uav.orig_ty);
if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
try w.writeByte('(');
try dg.renderOpvPointer(w, ptr_ty, location);
return w.writeByte(')');
if (!uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
const target = zcu.getTarget();
const alignment = switch (derivation.@"align") {
.none => derivation.elem_ty.abiAlignment(zcu),
else => |a| a,
};
try w.writeAll("((");
try dg.renderDerivedPointerType(w, derivation);
try w.print("){f})", .{fmtUnsignedIntLiteralSmall(
target,
.uintptr_t,
alignment.forward(undefPattern(u64) >> @intCast(64 - target.ptrBitWidth())),
location == .static_initializer,
16,
.lower,
)});
return;
}
switch (ip.indexToKey(uav.val)) {
switch (ip.indexToKey(uav_val.toIntern())) {
.func => unreachable,
.@"extern" => unreachable,
else => {},
}
// We shouldn't cast C function pointers as this is UB (when you call
// them). The analysis until now should ensure that the C function
// pointers are compatible. If they are not, then there is a bug
// somewhere and we should let the C compiler tell us about it.
const elem_ty = ptr_ty.childType(zcu);
const need_cast = elem_ty.toIntern() != uav_ty.toIntern() and
elem_ty.zigTypeTag(zcu) != .@"fn" or uav_ty.zigTypeTag(zcu) != .@"fn";
if (need_cast) {
try w.writeAll("((");
try dg.renderType(w, ptr_ty);
try w.writeByte(')');
}
try w.writeByte('&');
try renderUavName(w, uav_val);
if (need_cast) try w.writeByte(')');
// Indicate that the anon decl should be rendered to the output so that
// our reference above is not undefined.
const ptr_type = ip.indexToKey(uav.orig_ty).ptr_type;
const gop = try dg.uavs.getOrPut(dg.gpa, uav.val);
const gop = try dg.uavs.getOrPut(dg.gpa, uav_val.toIntern());
if (!gop.found_existing) gop.value_ptr.* = .none;
// If there is an explicit alignment, greater than the current one, use it.
// Note that we intentionally start at `.none`, so `gop.value_ptr.*` is never
// underaligned, so we don't need to worry about the `.none` case here.
if (ptr_type.flags.alignment != .none) {
if (derivation.@"align" != .none) {
// Resolve the current alignment so we can choose the bigger one.
const cur_alignment: Alignment = if (gop.value_ptr.* == .none) abi: {
break :abi Type.fromInterned(ptr_type.child).abiAlignment(zcu);
break :abi uav_ty.abiAlignment(zcu);
} else gop.value_ptr.*;
gop.value_ptr.* = cur_alignment.maxStrict(ptr_type.flags.alignment);
gop.value_ptr.* = cur_alignment.maxStrict(derivation.@"align");
}
}
@@ -818,28 +816,14 @@ pub const DeclGen = struct {
// Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type);
const ptr_ty = try pt.navPtrType(owner_nav);
if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
try w.writeByte('(');
try dg.renderOpvPointer(w, ptr_ty, location);
try dg.renderOpvPointer(w, try pt.navPtrType(owner_nav), location);
return w.writeByte(')');
}
// We shouldn't cast C function pointers as this is UB (when you call
// them). The analysis until now should ensure that the C function
// pointers are compatible. If they are not, then there is a bug
// somewhere and we should let the C compiler tell us about it.
const elem_ty = ptr_ty.childType(zcu);
const need_cast = elem_ty.toIntern() != nav_ty.toIntern() and
elem_ty.zigTypeTag(zcu) != .@"fn" or nav_ty.zigTypeTag(zcu) != .@"fn";
if (need_cast) {
try w.writeAll("((");
try dg.renderType(w, ptr_ty);
try w.writeByte(')');
}
try w.writeByte('&');
try renderNavName(w, owner_nav, ip);
if (need_cast) try w.writeByte(')');
}
fn renderOpvPointer(
@@ -865,92 +849,108 @@ pub const DeclGen = struct {
fn renderPointer(
dg: *DeclGen,
w: *Writer,
derivation: Value.PointerDeriveStep,
derivation: Value.PointerDerivation,
location: ValueRenderLocation,
) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
switch (derivation) {
.comptime_alloc_ptr, .comptime_field_ptr => unreachable,
switch (derivation.addr) {
.comptime_alloc, .comptime_field => unreachable,
.int => |int| {
const addr_val = try pt.intValue(.usize, int.addr);
const addr_val = try pt.intValue(.usize, int);
try w.writeByte('(');
try dg.renderType(w, int.ptr_ty);
try dg.renderDerivedPointerType(w, derivation);
try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .other)});
},
.nav_ptr => |nav| try dg.renderNav(w, nav, location),
.uav_ptr => |uav| try dg.renderUav(w, uav, location),
.nav => |nav| try dg.renderNav(w, nav, location),
.uav => |val| try dg.renderUav(w, val, derivation, location),
inline .eu_payload_ptr, .opt_payload_ptr => |info| {
inline .eu_payload, .opt_payload => |info| {
try w.writeAll("&(");
try dg.renderPointer(w, info.parent.*, location);
try w.writeAll(")->payload");
},
.field_ptr => |field| {
const parent_ptr_ty = try field.parent.ptrType(pt);
switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, zcu)) {
.field => |derived| {
switch (fieldLocation(derived.parent.elem_ty, derivation.elem_ty, derived.field_index, zcu)) {
.begin => {
try w.writeByte('(');
try dg.renderType(w, field.result_ptr_ty);
try dg.renderDerivedPointerType(w, derivation);
try w.writeByte(')');
try dg.renderPointer(w, field.parent.*, location);
try dg.renderPointer(w, derived.parent.*, location);
},
.field => |name| {
try w.writeAll("&(");
try dg.renderPointer(w, field.parent.*, location);
try dg.renderPointer(w, derived.parent.*, location);
try w.writeAll(")->");
try dg.writeCValue(w, name);
},
.byte_offset => |byte_offset| {
try w.writeByte('(');
try dg.renderType(w, field.result_ptr_ty);
try dg.renderDerivedPointerType(w, derivation);
try w.writeByte(')');
const offset_val = try pt.intValue(.usize, byte_offset);
try w.writeAll("((char *)");
try dg.renderPointer(w, field.parent.*, location);
try dg.renderPointer(w, derived.parent.*, location);
try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .other)});
},
}
},
.elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) {
.elem => |derived| if (!derived.parent.elem_ty.hasRuntimeBits(zcu)) {
// Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer.
try w.writeByte('(');
try dg.renderType(w, elem.result_ptr_ty);
try dg.renderDerivedPointerType(w, derivation);
try w.writeByte(')');
try dg.renderPointer(w, elem.parent.*, location);
try dg.renderPointer(w, derived.parent.*, location);
} else {
const index_val = try pt.intValue(.usize, elem.elem_idx);
const index_val = try pt.intValue(.usize, derived.elem_index);
try w.writeByte('(');
// We want to do pointer arithmetic on a pointer to the element type, but the parent
// might be a pointer-to-array, in which case we must cast it.
if (elem.result_ptr_ty.toIntern() != (try elem.parent.ptrType(pt)).toIntern()) {
try w.writeByte('(');
try dg.renderType(w, elem.result_ptr_ty);
try w.writeByte(')');
}
try dg.renderPointer(w, elem.parent.*, location);
// is a pointer-to-array, so we need to cast first.
try w.writeByte('(');
try dg.renderDerivedPointerType(w, derivation);
try w.writeByte(')');
try dg.renderPointer(w, derived.parent.*, location);
try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .other)});
},
.offset_and_cast => |oac| {
.offset_and_cast => |derived| {
try w.writeByte('(');
try dg.renderType(w, oac.new_ptr_ty);
try dg.renderDerivedPointerType(w, derivation);
try w.writeByte(')');
if (oac.byte_offset == 0) {
try dg.renderPointer(w, oac.parent.*, location);
if (derived.byte_offset == 0) {
try dg.renderPointer(w, derived.parent.*, location);
} else {
const offset_val = try pt.intValue(.usize, oac.byte_offset);
const offset_val = try pt.intValue(.usize, derived.byte_offset);
try w.writeAll("((char *)");
try dg.renderPointer(w, oac.parent.*, location);
try dg.renderPointer(w, derived.parent.*, location);
try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .other)});
}
},
}
}
fn renderDerivedPointerType(
dg: *DeclGen,
w: *Writer,
derivation: Value.PointerDerivation,
) Error!void {
return dg.renderType(w, try dg.pt.ptrType(.{
.child = derivation.elem_ty.toIntern(),
.flags = .{
.size = switch (derivation.size) {
.one => .one,
.many => .many,
},
.alignment = derivation.@"align",
.is_const = derivation.@"const",
.is_volatile = derivation.@"volatile",
.is_allowzero = derivation.@"allowzero",
},
}));
}
fn renderValueAsLvalue(
dg: *DeclGen,
@@ -1166,7 +1166,31 @@ pub const DeclGen = struct {
try w.writeByte('}');
},
.ptr => {
const derivation = try val.pointerDerivation(dg.arena, pt, null);
// TODO: `Value.pointerDerivation` ought to do this for us, but it doesn't receive
// `pt`, so it actually *can't* until https://github.com/ziglang/zig/issues/24061 is
// implemented.
const non_packed_ptr: Value = non_packed_ptr: {
const ptr_info = val.typeOf(zcu).ptrInfo(zcu);
if (ptr_info.packed_offset.host_size == 0) {
break :non_packed_ptr val;
}
const backing_ty: Type = switch (ptr_info.flags.vector_index) {
_ => .fromInterned(ptr_info.child),
.none => try pt.intType(
.unsigned,
@intCast(ptr_info.packed_offset.host_size * 8),
),
};
const new_ptr_ty = try pt.ptrType(info: {
var info = ptr_info;
info.child = backing_ty.toIntern();
info.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
info.flags.vector_index = .none;
break :info info;
});
break :non_packed_ptr try pt.getCoerced(val, new_ptr_ty);
};
const derivation = try non_packed_ptr.pointerDerivation(dg.arena, zcu, null);
try w.writeByte('(');
try dg.renderPointer(w, derivation, location);
try w.writeByte(')');
@@ -5380,8 +5404,8 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
}
fn fieldLocation(
container_ptr_ty: Type,
field_ptr_ty: Type,
container_ty: Type,
field_ty: Type,
field_index: u32,
zcu: *Zcu,
) union(enum) {
@@ -5390,27 +5414,22 @@ fn fieldLocation(
byte_offset: u64,
} {
const ip = &zcu.intern_pool;
const container_ty: Type = .fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child);
switch (ip.indexToKey(container_ty.toIntern())) {
.struct_type => {
const loaded_struct = ip.loadStructType(container_ty.toIntern());
return switch (loaded_struct.layout) {
.auto, .@"extern" => if (!container_ty.hasRuntimeBits(zcu))
.begin
else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu))
else if (!field_ty.hasRuntimeBits(zcu))
.{ .byte_offset = loaded_struct.field_offsets.get(ip)[field_index] }
else
.{ .field = .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) } },
.@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0)
.{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) +
container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) }
else
.begin,
.@"packed" => .begin,
};
},
.tuple_type => return if (!container_ty.hasRuntimeBits(zcu))
.begin
else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu))
else if (!field_ty.hasRuntimeBits(zcu))
.{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) }
else
.{ .field = .{ .field = field_index } },
@@ -5418,7 +5437,6 @@ fn fieldLocation(
const loaded_union = ip.loadUnionType(container_ty.toIntern());
switch (loaded_union.layout) {
.auto => {
const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBits(zcu)) {
if (container_ty.unionHasAllZeroBitFieldTypes(zcu)) return .begin;
return .{ .field = .{ .identifier = "payload" } };
@@ -5427,7 +5445,6 @@ fn fieldLocation(
return .{ .field = .{ .payload_identifier = field_name.toSlice(ip) } };
},
.@"extern" => {
const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]);
if (!field_ty.hasRuntimeBits(zcu)) return .begin;
const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index];
return .{ .field = .{ .identifier = field_name.toSlice(ip) } };
@@ -5486,7 +5503,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
try f.renderType(w, container_ptr_ty);
try w.writeByte(')');
switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) {
switch (fieldLocation(container_ty, field_ptr_ty.childType(zcu), extra.field_index, zcu)) {
.begin => try f.writeCValue(w, field_ptr_val, .other),
.field => |field| {
const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
@@ -5537,7 +5554,12 @@ fn fieldPtr(
try f.renderType(w, field_ptr_ty);
try w.writeByte(')');
switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) {
switch (fieldLocation(
container_ptr_ty.childType(zcu),
field_ptr_ty.childType(zcu),
field_index,
zcu,
)) {
.begin => try f.writeCValue(w, container_ptr_val, .other),
.field => |field| {
try w.writeByte('&');
+4 -4
View File
@@ -28,7 +28,7 @@ pub fn defineAligned(
});
if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{
alignment.toByteUnits().?,
ty.fmt(pt),
ty.fmt(zcu),
});
try w.writeByte('\n');
}
@@ -113,7 +113,7 @@ pub fn errunionDefineComplete(
});
}
if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{
payload_ty.fmt(pt),
payload_ty.fmt(zcu),
});
try w.writeByte('\n');
}
@@ -159,7 +159,7 @@ pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!vo
name_cty.fmtTypeName(zcu),
});
if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
ty.fmt(pt),
ty.fmt(zcu),
});
try w.writeByte('\n');
}
@@ -337,7 +337,7 @@ pub fn defineComplete(
else => return,
};
if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{
ty.fmt(pt),
ty.fmt(zcu),
});
try w.writeByte('\n');
if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu);
+4 -3
View File
@@ -1354,6 +1354,7 @@ pub const Object = struct {
///
/// `val` is always a type because `o.type_pool` only contains types.
pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void {
_ = pt;
const zcu = o.zcu;
assert(zcu.intern_pool.typeOf(val) == .type_type);
@@ -1367,7 +1368,7 @@ pub const Object = struct {
if (!o.builder.strip) {
assert(val != .anyerror_type);
const fwd_ref = o.debug_types.items[@backingInt(index)];
const name_str = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)});
const name_str = try o.builder.metadataStringFmt("{f}", .{ty.fmt(zcu)});
// If `ty` is a function, use a dummy *function* type to prevent existing debug
// subprograms from becoming ill-formed.
const debug_incomplete_type = switch (ty.zigTypeTag(zcu)) {
@@ -1458,7 +1459,7 @@ pub const Object = struct {
const target = zcu.getTarget();
const ip = &zcu.intern_pool;
const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)});
const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(zcu)});
// lldb cannot handle non-byte-sized types, so in the logic below, bit sizes are padded up.
// For instance, `bool` is considered to be 8 bits, and `u60` is considered to be 64 bits.
@@ -1967,7 +1968,7 @@ pub const Object = struct {
const debug_payload_type = try o.builder.debugUnionType(
payload_name: {
if (layout.tag_size == 0) break :payload_name name;
break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(pt)});
break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(zcu)});
},
file,
scope,
+3 -3
View File
@@ -3016,7 +3016,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) codegen.Error!void
isel: *Select,
inst: Air.Inst.Index,
pub fn format(fmt_air: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
fmt_air.isel.air.writeInst(writer, fmt_air.inst, fmt_air.isel.pt, null);
fmt_air.isel.air.writeInst(writer, fmt_air.inst, fmt_air.isel.pt.zcu, null);
}
} {
return .{ .isel = it.isel, .inst = inst };
@@ -5266,11 +5266,11 @@ fn fmtLoopLive(isel: *Select, loop_inst: Air.Inst.Index) struct {
}
fn fmtType(isel: *Select, ty: ZigType) ZigType.Formatter {
return ty.fmt(isel.pt);
return ty.fmt(isel.pt.zcu);
}
fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmtValue)).@"fn".return_type.? {
return constant.fmtValue(isel.pt);
return constant.fmtValue(isel.pt.zcu);
}
fn fmtRegisterSet(regs: RegisterSet) struct {
+18 -18
View File
@@ -1291,7 +1291,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {
.@"enum" => {
const enum_ty = Type.fromInterned(lazy_sym.ty);
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(zcu)});
const param_regs = abi.Registers.Integer.function_arg_regs;
const ret_reg = param_regs[0];
@@ -1374,7 +1374,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
},
else => return func.fail(
"TODO implement {s} for {f}",
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(zcu) },
),
}
}
@@ -1911,7 +1911,7 @@ fn splitType(func: *Func, ty: Type) ![2]Type {
else => return func.fail("TODO: splitType class {}", .{class}),
};
} else if (parts[0].abiSize(zcu) + parts[1].abiSize(zcu) == ty.abiSize(zcu)) return parts;
return func.fail("TODO implement splitType for {f}", .{ty.fmt(func.pt)});
return func.fail("TODO implement splitType for {f}", .{ty.fmt(zcu)});
}
/// Truncates the value in the register in place.
@@ -2024,7 +2024,7 @@ fn allocMemPtr(func: *Func, inst: Air.Inst.Index) !FrameIndex {
const val_ty = ptr_ty.childType(zcu);
return func.allocFrameIndex(FrameAlloc.init(.{
.size = math.cast(u32, val_ty.abiSize(zcu)) orelse {
return func.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(pt)});
return func.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(zcu)});
},
.alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
}));
@@ -2164,7 +2164,7 @@ pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {
/// allocated. A second call to `copyToTmpRegister` may return the same register.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToTmpRegister(func: *Func, ty: Type, mcv: MCValue) !Register {
log.debug("copyToTmpRegister ty: {f}", .{ty.fmt(func.pt)});
log.debug("copyToTmpRegister ty: {f}", .{ty.fmt(func.pt.zcu)});
const reg = try func.register_manager.allocReg(null, func.regTempClassForType(ty));
try func.genSetReg(ty, reg, mcv);
return reg;
@@ -2249,7 +2249,7 @@ fn airIntCast(func: *Func, inst: Air.Inst.Index) !void {
break :result dst_mcv;
} orelse return func.fail("TODO: implement airIntCast from {f} to {f}", .{
src_ty.fmt(pt), dst_ty.fmt(pt),
src_ty.fmt(zcu), dst_ty.fmt(zcu),
});
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
@@ -2636,7 +2636,7 @@ fn genBinOp(
.add_sat,
=> {
if (bit_size != 64 or !is_unsigned)
return func.fail("TODO: genBinOp ty: {f}", .{lhs_ty.fmt(pt)});
return func.fail("TODO: genBinOp ty: {f}", .{lhs_ty.fmt(zcu)});
const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
@@ -4057,7 +4057,7 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void {
} else {
return func.fail(
"TODO implement get_union_tag for ABI larger than 8 bytes and operand {}, tag {f}",
.{ frame_mcv, tag_ty.fmt(pt) },
.{ frame_mcv, tag_ty.fmt(zcu) },
);
}
},
@@ -4177,7 +4177,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
switch (scalar_ty.zigTypeTag(zcu)) {
.int => if (ty.zigTypeTag(zcu) == .vector) {
return func.fail("TODO implement airAbs for {f}", .{ty.fmt(pt)});
return func.fail("TODO implement airAbs for {f}", .{ty.fmt(zcu)});
} else {
const int_info = scalar_ty.intInfo(zcu);
const int_bits = int_info.bits;
@@ -4258,7 +4258,7 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
break :result return_mcv;
},
else => return func.fail("TODO: implement airAbs {f}", .{scalar_ty.fmt(pt)}),
else => return func.fail("TODO: implement airAbs {f}", .{scalar_ty.fmt(zcu)}),
}
break :result .unreach;
@@ -4322,7 +4322,7 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void {
break :result dest_mcv;
},
else => return func.fail("TODO: airByteSwap {f}", .{ty.fmt(pt)}),
else => return func.fail("TODO: airByteSwap {f}", .{ty.fmt(zcu)}),
}
};
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
@@ -4388,7 +4388,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),
}
},
else => return func.fail("TODO: airUnaryMath ty: {f}", .{ty.fmt(pt)}),
else => return func.fail("TODO: airUnaryMath ty: {f}", .{ty.fmt(zcu)}),
}
break :result MCValue{ .register = dst_reg };
@@ -4488,7 +4488,7 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro
const zcu = pt.zcu;
const dst_ty = ptr_ty.childType(zcu);
log.debug("loading {}:{f} into {}", .{ ptr_mcv, ptr_ty.fmt(pt), dst_mcv });
log.debug("loading {}:{f} into {}", .{ ptr_mcv, ptr_ty.fmt(zcu), dst_mcv });
switch (ptr_mcv) {
.none,
@@ -4541,7 +4541,7 @@ fn airStore(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void {
const zcu = func.pt.zcu;
const src_ty = ptr_ty.childType(zcu);
log.debug("storing {}:{f} in {}:{f}", .{ src_mcv, src_ty.fmt(func.pt), ptr_mcv, ptr_ty.fmt(func.pt) });
log.debug("storing {}:{f} in {}:{f}", .{ src_mcv, src_ty.fmt(zcu), ptr_mcv, ptr_ty.fmt(zcu) });
switch (ptr_mcv) {
.none => unreachable,
@@ -7269,7 +7269,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
const bit_size = dst_ty.bitSize(zcu);
if (abi_size * 8 <= bit_size) break :result dst_mcv;
return func.fail("TODO: airBitCast {f} to {f}", .{ src_ty.fmt(pt), dst_ty.fmt(pt) });
return func.fail("TODO: airBitCast {f} to {f}", .{ src_ty.fmt(zcu), dst_ty.fmt(zcu) });
};
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
@@ -8085,7 +8085,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {
);
break :result .{ .load_frame = .{ .index = frame_index } };
},
else => return func.fail("TODO: airAggregate {f}", .{result_ty.fmt(pt)}),
else => return func.fail("TODO: airAggregate {f}", .{result_ty.fmt(zcu)}),
}
};
@@ -8279,7 +8279,7 @@ fn resolveCallingConventionValues(
};
result.return_value = switch (ret_tracking_i) {
else => return func.fail("ty {f} took {} tracking return indices", .{ ret_ty.fmt(pt), ret_tracking_i }),
else => return func.fail("ty {f} took {} tracking return indices", .{ ret_ty.fmt(zcu), ret_tracking_i }),
1 => ret_tracking[0],
2 => InstTracking.init(.{ .register_pair = .{
ret_tracking[0].short.register, ret_tracking[1].short.register,
@@ -8334,7 +8334,7 @@ fn resolveCallingConventionValues(
else => return func.fail("TODO: C calling convention arg class {}", .{class}),
} else {
arg.* = switch (arg_mcv_i) {
else => return func.fail("ty {f} took {} tracking arg indices", .{ ty.fmt(pt), arg_mcv_i }),
else => return func.fail("ty {f} took {} tracking arg indices", .{ ty.fmt(zcu), arg_mcv_i }),
1 => arg_mcv[0],
2 => .{ .register_pair = .{ arg_mcv[0].register, arg_mcv[1].register } },
};
+3 -3
View File
@@ -985,7 +985,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!void {
switch (self.args[arg_index]) {
.stack_offset => |off| {
const abi_size = math.cast(u32, ty.abiSize(zcu)) orelse {
return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(pt)});
return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(zcu)});
};
const offset = off + abi_size;
break :blk .{ .stack_offset = offset };
@@ -2722,7 +2722,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
}
const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(zcu)});
};
// TODO swap this for inst.ty.ptrAlign
const abi_align = elem_ty.abiAlignment(zcu);
@@ -2734,7 +2734,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
const zcu = pt.zcu;
const elem_ty = self.typeOfIndex(inst);
const abi_size = math.cast(u32, elem_ty.abiSize(zcu)) orelse {
return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(pt)});
return self.fail("type '{f}' too big to fit into stack frame", .{elem_ty.fmt(zcu)});
};
const abi_align = elem_ty.abiAlignment(zcu);
self.stack_align = self.stack_align.max(abi_align);
+157 -121
View File
@@ -1297,8 +1297,8 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
const ip = &zcu.intern_pool;
log.debug("lowering constant: ty = {f}, val = {f}, key = {s}", .{
ty.fmt(pt),
val.fmtValue(pt),
ty.fmt(zcu),
val.fmtValue(zcu),
@tagName(ip.indexToKey(val.toIntern())),
});
assert(!ty.isPtrAtRuntime(zcu));
@@ -1640,7 +1640,6 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
}
fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
const pt = cg.pt;
const zcu = cg.zcu;
const gpa = cg.gpa;
@@ -1653,32 +1652,64 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
var arena = std.heap.ArenaAllocator.init(gpa);
defer arena.deinit();
const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt, null);
return cg.derivePtr(derivation);
// TODO: `Value.pointerDerivation` ought to do this for us, but it doesn't receive
// `pt`, so it actually *can't* until https://github.com/ziglang/zig/issues/24061 is
// implemented.
const non_packed_ptr_val: Value = non_packed_ptr: {
const ptr_info = ptr_val.typeOf(zcu).ptrInfo(zcu);
if (ptr_info.packed_offset.host_size == 0) {
break :non_packed_ptr ptr_val;
}
const backing_ty: Type = switch (ptr_info.flags.vector_index) {
_ => try cg.pt.vectorType(.{
.child = ptr_info.child,
.len = ptr_info.packed_offset.host_size,
}),
.none => try cg.pt.intType(
.unsigned,
@intCast(ptr_info.packed_offset.host_size * 8),
),
};
const new_ptr_ty = try cg.pt.ptrType(info: {
var info = ptr_info;
info.child = backing_ty.toIntern();
info.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
info.flags.vector_index = .none;
break :info info;
});
break :non_packed_ptr try cg.pt.getCoerced(ptr_val, new_ptr_ty);
};
const derivation = try non_packed_ptr_val.pointerDerivation(arena.allocator(), zcu, null);
return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation);
}
fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
const gpa = cg.gpa;
const pt = cg.pt;
const zcu = cg.zcu;
const target = zcu.getTarget();
switch (derivation) {
.comptime_alloc_ptr, .comptime_field_ptr => unreachable,
const result_ty_id = try cg.ptrType(
try cg.pointeeType(@"addrspace", derivation.elem_ty, false),
cg.storageClass(@"addrspace"),
);
switch (derivation.addr) {
.comptime_alloc, .comptime_field => unreachable,
.int => |int| {
if (target.os.tag != .opencl) {
if (int.ptr_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) {
if (@"addrspace" != .physical_storage_buffer) {
return cg.fail(
"cannot cast integer to pointer with address space '{s}'",
.{@tagName(int.ptr_ty.ptrAddressSpace(zcu))},
.{@tagName(@"addrspace")},
);
}
}
const result_ty_id = try cg.resolveType(int.ptr_ty, .direct);
// TODO: This can probably be an OpSpecConstantOp Bitcast, but
// that is not implemented by Mesa yet. Therefore, just generate it
// as a runtime operation.
const result_ptr_id = cg.allocId();
const value_id = try cg.constInt(.usize, int.addr);
const value_id = try cg.constInt(.usize, int);
try cg.body.emit(gpa, .OpConvertUToPtr, .{
.id_result_type = result_ty_id,
.id_result = result_ptr_id,
@@ -1686,10 +1717,8 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
});
return result_ptr_id;
},
.nav_ptr => |nav_index| {
.nav => |nav_index| {
const ip = &zcu.intern_pool;
const result_ptr_ty = try pt.navPtrType(nav_index);
const ty_id = try cg.resolveType(result_ptr_ty, .direct);
const nav = ip.getNav(nav_index);
const nav_ty: Type = .fromInterned(nav.resolved.?.type);
@@ -1698,10 +1727,10 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
if (ip.isFunctionType(nav_ty.toIntern())) {
if (is_extern) return try cg.resolveExternFn(nav_index);
return try cg.constUndef(ty_id);
return try cg.constUndef(result_ty_id);
}
if (!nav_ty.hasRuntimeBits(zcu) and nav_ty.zigTypeTag(zcu) != .spirv) {
return cg.constUndef(ty_id);
return cg.constUndef(result_ty_id);
}
if (!is_extern) {
return cg.todo("pointer to constant '{f}'", .{nav.fqn.fmt(ip)});
@@ -1718,7 +1747,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
try cg.block_var_ids.put(gpa, var_id, {});
}
if (decl_ptr_ty_id == ty_id) return var_id;
if (decl_ptr_ty_id == result_ty_id) return var_id;
switch (target.os.tag) {
.vulkan, .opengl => return var_id,
else => {},
@@ -1726,63 +1755,63 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
const casted_ptr_id = cg.allocId();
try cg.body.emit(gpa, .OpBitcast, .{
.id_result_type = ty_id,
.id_result_type = result_ty_id,
.id_result = casted_ptr_id,
.operand = var_id,
});
return casted_ptr_id;
},
.uav_ptr => |uav| {
.uav => |uav_val| {
const ip = &zcu.intern_pool;
const result_ptr_ty: Type = .fromInterned(uav.orig_ty);
const ty_id = try cg.resolveType(result_ptr_ty, .direct);
const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
const uav_ty = uav_val.typeOf(zcu);
switch (ip.indexToKey(uav.val)) {
switch (ip.indexToKey(uav_val.toIntern())) {
.func => unreachable, // TODO
.@"extern" => assert(!ip.isFunctionType(uav_ty.toIntern())),
else => {},
}
if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) {
return cg.constUndef(ty_id);
return cg.constUndef(result_ty_id);
}
if (cg.storageClass(result_ptr_ty.ptrAddressSpace(zcu)) != .function) {
return cg.todo("pointer to an anonymous constant of type '{f}'", .{uav_ty.fmt(pt)});
if (cg.storageClass(@"addrspace") != .function) {
return cg.todo("pointer to an anonymous constant of type '{f}'", .{uav_ty.fmt(zcu)});
}
const uav_ty_id = try cg.resolveType(uav_ty, .indirect);
const ptr_id = try cg.alloc(uav_ty_id, null);
const val_id = try cg.constant(uav_ty, .fromInterned(uav.val), .indirect);
const val_id = try cg.constant(uav_ty, uav_val, .indirect);
try cg.body.emit(gpa, .OpStore, .{ .pointer = ptr_id, .object = val_id });
return ptr_id;
},
.eu_payload_ptr => @panic("TODO"),
.opt_payload_ptr => @panic("TODO"),
.field_ptr => |field| {
const parent_ptr_id = try cg.derivePtr(field.parent.*);
const parent_ptr_ty = try field.parent.ptrType(pt);
return cg.structFieldPtr(field.result_ptr_ty, parent_ptr_ty, parent_ptr_id, field.field_idx);
},
.elem_ptr => |elem| {
const parent_ptr_id = try cg.derivePtr(elem.parent.*);
const parent_ptr_ty = try elem.parent.ptrType(pt);
const index_id = try cg.constInt(.usize, elem.elem_idx);
return cg.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id);
},
.offset_and_cast => |oac| {
const parent_ptr_id = try cg.derivePtr(oac.parent.*);
const parent_ptr_ty = try oac.parent.ptrType(pt);
.eu_payload => @panic("TODO"),
.opt_payload => @panic("TODO"),
.field => |derived| return cg.structFieldPtr(
@"addrspace",
result_ty_id,
derivation.elem_ty,
derived.parent.elem_ty,
try cg.derivePtr(@"addrspace", derived.parent.*),
derived.field_index,
),
.elem => |derived| return cg.ptrElemPtr(
switch (derived.parent.size) {
.one => .single_array_ptr,
.many => .many_ptr,
},
@"addrspace",
derived.parent.elem_ty,
try cg.derivePtr(@"addrspace", derived.parent.*),
try cg.constInt(.usize, derived.elem_index),
),
.offset_and_cast => |derived| {
const parent_ptr_id = try cg.derivePtr(@"addrspace", derived.parent.*);
if (oac.new_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) {
return parent_ptr_id;
}
if (oac.byte_offset == 0) {
if (derived.byte_offset == 0) {
var depth: u32 = 0;
var cur = parent_ptr_ty.childType(zcu);
const dst_child = oac.new_ptr_ty.childType(zcu);
var cur = derived.parent.elem_ty;
const dst_child = derivation.elem_ty;
while (cur.toIntern() != dst_child.toIntern()) {
switch (cur.zigTypeTag(zcu)) {
.array => {
@@ -1807,9 +1836,6 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
}
if (cur.toIntern() == dst_child.toIntern()) {
if (depth != 0) {
const as = oac.new_ptr_ty.ptrAddressSpace(zcu);
const child_ty_id = try cg.pointeeType(as, dst_child, false);
const result_ty_id = try cg.ptrType(child_ty_id, cg.storageClass(as));
const scratch_top = cg.id_scratch.items.len;
defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
const zero = try cg.constInt(.u32, 0);
@@ -1820,7 +1846,6 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
return parent_ptr_id;
}
}
const result_ty_id = try cg.resolveType(oac.new_ptr_ty, .direct);
if (target.os.tag == .opencl) {
const result_ptr_id = cg.allocId();
try cg.body.emit(gpa, .OpBitcast, .{
@@ -1832,9 +1857,9 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id {
}
}
return cg.fail("cannot cast pointer '{f}' to '{f}'", .{
parent_ptr_ty.fmt(pt),
oac.new_ptr_ty.fmt(pt),
return cg.fail("cannot cast pointer '*{f}' to '*{f}'", .{
derived.parent.elem_ty.fmt(zcu),
derivation.elem_ty.fmt(zcu),
});
},
}
@@ -1881,7 +1906,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
const ip = &zcu.intern_pool;
const target = cg.zcu.getTarget();
log.debug("resolveType: ty = {f}", .{ty.fmt(pt)});
log.debug("resolveType: ty = {f}", .{ty.fmt(zcu)});
switch (ty.zigTypeTag(zcu)) {
.noreturn => {
@@ -1919,7 +1944,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
};
if (!supported) return cg.fail(
"'{f}' is not supported on the current SPIR-V feature set",
.{ty.fmt(cg.pt)},
.{ty.fmt(zcu)},
);
return try cg.floatType(bits);
},
@@ -2047,7 +2072,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
null,
.none,
);
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(cg.pt)});
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(zcu)});
return result_id;
},
.struct_type => ip.loadStructType(ty.toIntern()),
@@ -2080,7 +2105,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
ty.toIntern(),
);
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(cg.pt)});
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(zcu)});
return result_id;
},
@@ -2134,7 +2159,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
}
const result_id = try cg.structType(member_types[0..len], null, .none);
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(cg.pt)});
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(zcu)});
return result_id;
},
}
@@ -2169,7 +2194,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
member_names[0..layout.total_fields],
.none,
);
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(cg.pt)});
try cg.debugNameFmt(result_id, "{f}", .{ty.fmt(zcu)});
return result_id;
},
.error_set => {
@@ -2206,7 +2231,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
},
.@"opaque" => {
if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{});
return try cg.opaqueType("{f}", .{ty.fmt(cg.pt)});
return try cg.opaqueType("{f}", .{ty.fmt(zcu)});
},
.spirv => {
const spirv_type = ip.loadSpirvType(ty.toIntern());
@@ -6455,21 +6480,28 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
return try cg.load(slice_ty.childType(zcu), elem_ptr, .{ .is_volatile = slice_ty.isVolatilePtr(zcu) });
}
fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id {
const zcu = cg.zcu;
fn ptrElemPtr(
cg: *CodeGen,
mode: enum { single_array_ptr, many_ptr },
@"addrspace": std.lang.AddressSpace,
elem_ty: Type,
ptr_id: Id,
index_id: Id,
) !Id {
// Construct new pointer type for the resulting pointer
const as = ptr_ty.ptrAddressSpace(zcu);
const is_single_ptr = ptr_ty.isSinglePointer(zcu);
const elem_is_block = cg.block_var_ids.contains(ptr_id);
const elem_ty_id = try cg.pointeeType(as, ptr_ty.indexableElem(zcu), elem_is_block);
const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(as));
if (is_single_ptr) {
// Pointer-to-array. In this case, the resulting pointer is not of the same type
// as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
return cg.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id});
} else {
// Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
return cg.ptrAccessChain(elem_ptr_ty_id, ptr_id, index_id, &.{});
const elem_ty_id = try cg.pointeeType(@"addrspace", elem_ty, elem_is_block);
const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(@"addrspace"));
switch (mode) {
.single_array_ptr => {
// Pointer-to-array. In this case, the resulting pointer is not of the same type
// as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
return cg.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id});
},
.many_ptr => {
// Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
return cg.ptrAccessChain(elem_ptr_ty_id, ptr_id, index_id, &.{});
},
}
}
@@ -6483,13 +6515,19 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const ty_pl = cg.air.instructions.items(.data)[@backingInt(inst)].ty_pl;
const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data;
const src_ptr_ty = cg.typeOf(bin_op.lhs);
const elem_ty = src_ptr_ty.childType(zcu);
const elem_ty = src_ptr_ty.indexableElem(zcu);
const ptr_id = try cg.resolve(bin_op.lhs);
assert(elem_ty.hasRuntimeBits(zcu));
const index_id = try cg.resolve(bin_op.rhs);
return try cg.ptrElemPtr(src_ptr_ty, ptr_id, index_id);
return try cg.ptrElemPtr(
if (src_ptr_ty.isSinglePointer(zcu)) .single_array_ptr else .many_ptr,
src_ptr_ty.ptrAddressSpace(zcu),
elem_ty,
ptr_id,
index_id,
);
}
fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
@@ -6551,7 +6589,13 @@ fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const elem_ty = cg.typeOfIndex(inst);
const ptr_id = try cg.resolve(bin_op.lhs);
const index_id = try cg.resolve(bin_op.rhs);
const elem_ptr_id = try cg.ptrElemPtr(ptr_ty, ptr_id, index_id);
const elem_ptr_id = try cg.ptrElemPtr(
if (ptr_ty.isSinglePointer(zcu)) .single_array_ptr else .many_ptr,
ptr_ty.ptrAddressSpace(zcu),
elem_ty,
ptr_id,
index_id,
);
return try cg.load(elem_ty, elem_ptr_id, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) });
}
@@ -6845,66 +6889,44 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
fn structFieldPtr(
cg: *CodeGen,
result_ptr_ty: Type,
object_ptr_ty: Type,
@"addrspace": std.lang.AddressSpace,
result_ptr_ty_id: Id,
field_ty: Type,
object_ty: Type,
object_ptr: Id,
field_index: u32,
) !Id {
const result_ty_id = try cg.resolveType(result_ptr_ty, .direct);
const zcu = cg.zcu;
const object_ty = object_ptr_ty.childType(zcu);
switch (object_ty.zigTypeTag(zcu)) {
.pointer => {
assert(object_ty.isSlice(zcu));
return cg.accessChain(result_ty_id, object_ptr, &.{field_index});
return cg.accessChain(result_ptr_ty_id, object_ptr, &.{field_index});
},
.@"struct" => switch (object_ty.containerLayout(zcu)) {
.@"packed" => {
const byte_offset = codegen.fieldOffset(object_ptr_ty, result_ptr_ty, field_index, zcu);
if (byte_offset == 0) return object_ptr;
const usize_ty_id = try cg.resolveType(.usize, .direct);
const base_int = cg.allocId();
try cg.body.emit(cg.gpa, .OpConvertPtrToU, .{
.id_result_type = usize_ty_id,
.id_result = base_int,
.pointer = object_ptr,
});
const offset_id = try cg.constInt(.usize, byte_offset);
const adjusted = try cg.buildBinary(.OpIAdd, .{ .ty = .usize, .value = .{ .singleton = base_int } }, .{ .ty = .usize, .value = .{ .singleton = offset_id } });
const adjusted_id = try adjusted.materialize(cg);
const result_id = cg.allocId();
try cg.body.emit(cg.gpa, .OpConvertUToPtr, .{
.id_result_type = result_ty_id,
.id_result = result_id,
.integer_value = adjusted_id,
});
return result_id;
},
.@"packed" => unreachable,
.auto, .@"extern" => {
const member_index = cg.memberIndex(object_ty, field_index);
return try cg.accessChain(result_ty_id, object_ptr, &.{member_index});
return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{member_index});
},
},
.@"union" => switch (object_ty.containerLayout(zcu)) {
.@"packed" => return cg.todo("implement field access for packed unions", .{}),
.@"packed" => unreachable,
.auto => {
if (!result_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) return try cg.constUndef(result_ty_id);
return try cg.accessChain(result_ty_id, object_ptr, &.{field_index});
if (!field_ty.hasRuntimeBits(zcu)) return try cg.constUndef(result_ptr_ty_id);
return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{field_index});
},
.@"extern" => {
const layout = cg.unionLayout(object_ty);
if (!layout.has_payload) {
// Asked to get a pointer to a zero-sized field. Just lower this
// to undefined, there is no reason to make it be a valid pointer.
return try cg.constUndef(result_ty_id);
return try cg.constUndef(result_ptr_ty_id);
}
const storage_class = cg.storageClass(object_ptr_ty.ptrAddressSpace(zcu));
const field_ty = result_ptr_ty.childType(zcu);
const storage_class = cg.storageClass(@"addrspace");
if (field_ty.toIntern() == layout.payload_ty.toIntern()) {
if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr;
return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index});
return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{layout.payload_index});
}
switch (zcu.getTarget().os.tag) {
@@ -6913,7 +6935,7 @@ fn structFieldPtr(
// type is structurally identical to the payload type (dedup will
// unify them) the access chain typed as the field type is valid.
if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr;
return try cg.accessChain(result_ty_id, object_ptr, &.{layout.payload_index});
return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{layout.payload_index});
},
else => {},
}
@@ -6927,7 +6949,7 @@ fn structFieldPtr(
const active_pl_ptr_id = cg.allocId();
try cg.body.emit(cg.gpa, .OpBitcast, .{
.id_result_type = result_ty_id,
.id_result_type = result_ptr_ty_id,
.id_result = active_pl_ptr_id,
.operand = pl_ptr_id,
});
@@ -6971,7 +6993,14 @@ fn airStructFieldPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
const struct_ptr = try cg.resolve(struct_field.struct_operand);
const struct_ptr_ty = cg.typeOf(struct_field.struct_operand);
const result_ptr_ty = cg.typeOfIndex(inst);
return try cg.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, struct_field.field_index);
return try cg.structFieldPtr(
struct_ptr_ty.ptrAddressSpace(cg.zcu),
try cg.resolveType(result_ptr_ty, .direct),
result_ptr_ty.childType(cg.zcu),
struct_ptr_ty.childType(cg.zcu),
struct_ptr,
struct_field.field_index,
);
}
fn airStructFieldPtrIndex(cg: *CodeGen, inst: Air.Inst.Index, field_index: u32) !?Id {
@@ -6979,7 +7008,14 @@ fn airStructFieldPtrIndex(cg: *CodeGen, inst: Air.Inst.Index, field_index: u32)
const struct_ptr = try cg.resolve(ty_op.operand);
const struct_ptr_ty = cg.typeOf(ty_op.operand);
const result_ptr_ty = cg.typeOfIndex(inst);
return try cg.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index);
return try cg.structFieldPtr(
struct_ptr_ty.ptrAddressSpace(cg.zcu),
try cg.resolveType(result_ptr_ty, .direct),
result_ptr_ty.childType(cg.zcu),
struct_ptr_ty.childType(cg.zcu),
struct_ptr,
field_index,
);
}
fn alloc(cg: *CodeGen, ty_id: Id, initializer: ?Id) !Id {
+9 -9
View File
@@ -1154,7 +1154,7 @@ fn allocStack(cg: *CodeGen, ty: Type) !WValue {
const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
return cg.fail("Type {f} with ABI size of {d} exceeds stack frame size", .{
ty.fmt(pt), ty.abiSize(zcu),
ty.fmt(zcu), ty.abiSize(zcu),
});
};
const abi_align = ty.abiAlignment(zcu);
@@ -1195,7 +1195,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue {
const abi_alignment = ptr_ty.ptrAlignment(zcu);
const abi_size = std.math.cast(u32, pointee_ty.abiSize(zcu)) orelse {
return cg.fail("Type {f} with ABI size of {d} exceeds stack frame size", .{
pointee_ty.fmt(pt), pointee_ty.abiSize(zcu),
pointee_ty.fmt(zcu), pointee_ty.abiSize(zcu),
});
};
cg.stack_alignment = cg.stack_alignment.max(abi_alignment);
@@ -2108,7 +2108,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
if (!arg_ty.hasRuntimeBits(zcu)) continue;
const arg_size = std.math.cast(u32, arg_ty.abiSize(zcu)) orelse {
return cg.fail("argument type {f} too large for wasm varargs buffer", .{arg_ty.fmt(pt)});
return cg.fail("argument type {f} too large for wasm varargs buffer", .{arg_ty.fmt(zcu)});
};
const arg_align = arg_ty.abiAlignment(zcu);
@@ -2128,7 +2128,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
const arg_val = try cg.resolveInst(arg);
const arg_size = std.math.cast(u32, arg_ty.abiSize(zcu)) orelse {
return cg.fail("argument type {f} too large for wasm varargs buffer", .{arg_ty.fmt(pt)});
return cg.fail("argument type {f} too large for wasm varargs buffer", .{arg_ty.fmt(zcu)});
};
const arg_align = arg_ty.abiAlignment(zcu);
@@ -5189,7 +5189,7 @@ fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue {
return .{ .imm32 = @intFromBool(!val.isNull(zcu)) };
},
.aggregate => switch (ip.indexToKey(ty.ip_index)) {
.array_type => return cg.fail("Wasm TODO: LowerConstant for {f}", .{ty.fmt(pt)}),
.array_type => return cg.fail("Wasm TODO: LowerConstant for {f}", .{ty.fmt(zcu)}),
.vector_type => {
assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct);
var buf: [16]u8 = undefined;
@@ -5883,7 +5883,7 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
.@"packed" => unreachable, // legalize .expand_packed_agg_field_val
else => result: {
const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse {
return cg.fail("Field type '{f}' too big to fit into stack frame", .{field_ty.fmt(pt)});
return cg.fail("Field type '{f}' too big to fit into stack frame", .{field_ty.fmt(zcu)});
};
if (isByRef(field_ty, zcu, cg.target)) {
break :result try cg.offsetPointer(operand, offset);
@@ -6296,7 +6296,7 @@ fn isNull(cg: *CodeGen, operand: WValue, op_ty: Type, opcode: std.wasm.Opcode, o
// a pointer to the stack value
if (payload_ty.hasRuntimeBits(zcu)) {
const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)});
return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(zcu)});
};
try cg.emitMemBase(operand);
try cg.addMemArg(.i32_load8_u, .{ .offset = operand.memOffset() + offset, .alignment = .@"1" });
@@ -6381,7 +6381,7 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void
}
const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
return cg.fail("Optional type {f} too big to fit into stack frame", .{opt_ty.fmt(pt)});
return cg.fail("Optional type {f} too big to fit into stack frame", .{opt_ty.fmt(zcu)});
};
try cg.emitMemBase(operand);
@@ -6412,7 +6412,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
break :result operand;
}
const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse {
return cg.fail("Optional type {f} too big to fit into stack frame", .{op_ty.fmt(pt)});
return cg.fail("Optional type {f} too big to fit into stack frame", .{op_ty.fmt(zcu)});
};
// Create optional type, set the non-null bit, and store the operand inside the optional type
+133 -128
View File
@@ -1174,7 +1174,7 @@ const FormatAirData = struct {
inst: Air.Inst.Index,
};
fn formatAir(data: FormatAirData, w: *Writer) Writer.Error!void {
data.self.air.writeInst(w, data.inst, data.self.pt, data.self.liveness);
data.self.air.writeInst(w, data.inst, data.self.pt.zcu, data.self.liveness);
}
fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Alt(FormatAirData, formatAir) {
return .{ .data = .{ .self = self, .inst = inst } };
@@ -1185,14 +1185,15 @@ const FormatWipMirData = struct {
inst: Mir.Inst.Index,
};
fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
const zcu = data.self.pt.zcu;
var lower: Lower = .{
.target = data.self.target,
.allocator = data.self.gpa,
.mir = data.self.getTmpMir(),
.cc = .auto,
.src_loc = switch (data.self.owner) {
.nav_index => |nav| data.self.pt.zcu.navSrcLoc(nav),
.lazy_sym => |lazy_sym| Type.fromInterned(lazy_sym.ty).srcLocOrNull(data.self.pt.zcu) orelse .unneeded,
.nav_index => |nav| zcu.navSrcLoc(nav),
.lazy_sym => |lazy_sym| Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse .unneeded,
},
};
var first = true;
@@ -1215,7 +1216,7 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
first = false;
}
if (first) {
const ip = &data.self.pt.zcu.intern_pool;
const ip = &zcu.intern_pool;
const mir_inst = lower.mir.instructions.get(data.inst);
try w.print(" | .{s}", .{@tagName(mir_inst.ops)});
switch (mir_inst.ops) {
@@ -1264,7 +1265,7 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
try w.print(" {f}", .{mem_op.fmt(.m)});
},
.pseudo_dbg_arg_val, .pseudo_dbg_var_val => try w.print(" {f}", .{
Value.fromInterned(mir_inst.data.ip_index).fmtValue(data.self.pt),
Value.fromInterned(mir_inst.data.ip_index).fmtValue(zcu),
}),
}
}
@@ -4532,7 +4533,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -4544,7 +4545,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.add_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
res[0].tracking(cg),
}),
else => |e| return e,
@@ -13109,7 +13110,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -15283,7 +15284,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -15295,7 +15296,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.sub_wrap => res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
res[0].tracking(cg),
}),
else => |e| return e,
@@ -22130,7 +22131,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -25067,7 +25068,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -26865,7 +26866,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -26874,7 +26875,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
res[0].tracking(cg),
}),
else => |e| return e,
@@ -32090,7 +32091,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -33328,7 +33329,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -34785,7 +34786,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -36346,7 +36347,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -38038,7 +38039,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} })) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -39820,7 +39821,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -43333,7 +43334,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -43447,7 +43448,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -43576,7 +43577,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -47885,7 +47886,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -52188,7 +52189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -53037,7 +53038,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_pl.ty.fmt(pt),
ty_pl.ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -53942,7 +53943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_pl.ty.fmt(pt),
ty_pl.ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -57539,7 +57540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_pl.ty.fmt(pt),
ty_pl.ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -60884,7 +60885,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_pl.ty.fmt(pt),
ty_pl.ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -61279,7 +61280,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -61842,8 +61843,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
cg.typeOf(bin_op.rhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -62204,8 +62205,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
cg.typeOf(bin_op.rhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -62216,7 +62217,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.shl => res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
res[0].tracking(cg),
}),
else => |e| return e,
@@ -62383,7 +62384,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.rhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(zcu),
ops[1].tracking(cg),
}),
else => |e| return e,
@@ -65640,7 +65641,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
lhs_ty.fmt(pt),
lhs_ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -67425,7 +67426,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
ty_op.ty.fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -70586,7 +70587,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(ty_op.operand).fmt(pt),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -70983,7 +70984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(ty_op.operand).fmt(pt),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -71871,7 +71872,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(ty_op.operand).fmt(pt),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -72520,7 +72521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
ty_op.ty.fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -75622,7 +75623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
ty_op.ty.fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -76684,7 +76685,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -77534,7 +77535,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -79085,7 +79086,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(ty_op.operand).fmt(pt),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -80421,7 +80422,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -80961,7 +80962,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -81441,7 +81442,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -82016,7 +82017,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
for (&ops) |*op| op.wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
op.tracking(cg),
}),
else => |e| return e,
@@ -82028,7 +82029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty.fmt(pt),
ty.fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -89107,7 +89108,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
error.SelectFailed => return cg.fail("failed to select {s} {s} {f} {f} {f}", .{
@tagName(air_tag),
@tagName(vector_cmp.compareOperator()),
cg.typeOf(vector_cmp.lhs).fmt(pt),
cg.typeOf(vector_cmp.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -91699,8 +91700,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ty_op.ty.fmt(zcu),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -93374,8 +93375,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ty_op.ty.fmt(zcu),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -98132,8 +98133,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
dst_ty.fmt(pt),
src_ty.fmt(pt),
dst_ty.fmt(zcu),
src_ty.fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -103798,8 +103799,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ty_op.ty.fmt(zcu),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -115168,8 +115169,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ty_op.ty.fmt(zcu),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -127059,8 +127060,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ty_op.ty.fmt(zcu),
cg.typeOf(ty_op.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -161250,7 +161251,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
@tagName(air_tag),
@tagName(reduce.operation),
cg.typeOf(reduce.operand).fmt(pt),
cg.typeOf(reduce.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -161261,7 +161262,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
error.SelectFailed => return cg.fail("failed to select {s}.{s} wrap {f} {f}", .{
@tagName(air_tag),
@tagName(reduce.operation),
res_ty.fmt(pt),
res_ty.fmt(zcu),
res[0].tracking(cg),
}),
else => |e| return e,
@@ -168964,7 +168965,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
@tagName(air_tag),
@tagName(reduce.operation),
cg.typeOf(reduce.operand).fmt(pt),
cg.typeOf(reduce.operand).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -170804,7 +170805,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
ty_op.ty.fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -170820,8 +170821,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
ops[2] = ops[0].getByteLen(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
cg.typeOf(bin_op.rhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
}),
@@ -170861,8 +170862,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
cg.typeOf(bin_op.rhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
ops[2].tracking(cg),
@@ -171042,7 +171043,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -171208,7 +171209,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -171310,7 +171311,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(un_op).fmt(pt),
cg.typeOf(un_op).fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -171408,7 +171409,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
ty_op.ty.fmt(pt),
ty_op.ty.fmt(zcu),
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -171481,7 +171482,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
else => return cg.fail("failed to select {s} {f}", .{
@tagName(air_tag),
agg_ty.fmt(pt),
agg_ty.fmt(zcu),
}),
}
try res.finish(inst, &.{}, &.{}, cg);
@@ -172927,7 +172928,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.lhs).fmt(zcu),
ops[0].tracking(cg),
ops[1].tracking(cg),
ops[2].tracking(cg),
@@ -173765,7 +173766,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
switch (ip.indexToKey(lazy_sym.ty)) {
.enum_type => {
const enum_ty: Type = .fromInterned(lazy_sym.ty);
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(zcu)});
const ret_regs = abi.getCAbiIntReturnRegs(.auto)[0..2].*;
const ret_locks = cg.register_manager.lockRegsAssumeUnused(2, ret_regs);
@@ -173826,7 +173827,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
},
.error_set_type => |error_set_type| {
const err_ty: Type = .fromInterned(lazy_sym.ty);
wip_mir_log.debug("{f}.@errorCast:", .{err_ty.fmt(pt)});
wip_mir_log.debug("{f}.@errorCast:", .{err_ty.fmt(zcu)});
const ret_reg = abi.getCAbiIntReturnRegs(.auto)[0];
const ret_lock = cg.register_manager.lockRegAssumeUnused(ret_reg);
@@ -173871,7 +173872,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
},
else => return cg.fail(
"TODO implement {s} for {f}",
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(zcu) },
),
}
try cg.resetTemps(@fromBackingInt(@intCast(0)));
@@ -174080,7 +174081,7 @@ fn allocMemPtr(self: *CodeGen, inst: Air.Inst.Index) !FrameIndex {
const val_ty = ptr_ty.childType(zcu);
return self.allocFrameIndex(.init(.{
.size = std.math.cast(u32, val_ty.abiSize(zcu)) orelse {
return self.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(pt)});
return self.fail("type '{f}' too big to fit into stack frame", .{val_ty.fmt(zcu)});
},
.alignment = ptr_ty.ptrAlignment(zcu).max(.@"1"),
}));
@@ -174098,7 +174099,7 @@ fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok
const pt = self.pt;
const zcu = pt.zcu;
const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse {
return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(pt)});
return self.fail("type '{f}' too big to fit into stack frame", .{ty.fmt(zcu)});
};
if (reg_ok) need_mem: {
@@ -174592,9 +174593,9 @@ fn store(
}
fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {
const pt = self.pt;
const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu));
if (abi_size > 8) return self.fail("TODO implement {} for {f}", .{ mir_tag, dst_ty.fmt(pt) });
const zcu = self.pt.zcu;
const abi_size: u32 = @intCast(dst_ty.abiSize(zcu));
if (abi_size > 8) return self.fail("TODO implement {} for {f}", .{ mir_tag, dst_ty.fmt(zcu) });
switch (dst_mcv) {
.none,
.unreach,
@@ -176294,7 +176295,7 @@ fn genCall(cg: *CodeGen, info: union(enum) {
} });
dst.copyToMask(&src, cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select arg {f} {f} {f}", .{
arg_ty.fmt(pt),
arg_ty.fmt(zcu),
dst.tracking(cg),
src.tracking(cg),
}),
@@ -176515,7 +176516,7 @@ fn genCall(cg: *CodeGen, info: union(enum) {
var dst = try cg.tempInit(arg_ty, dst_arg);
dst.copyToMask(&src, cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select arg {f} {f} {f}", .{
arg_ty.fmt(pt),
arg_ty.fmt(zcu),
dst.tracking(cg),
src.tracking(cg),
}),
@@ -176640,9 +176641,10 @@ fn genCall(cg: *CodeGen, info: union(enum) {
}
fn airRet(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
const zcu = cg.pt.zcu;
const un_op = cg.air.instructions.items(.data)[@backingInt(inst)].un_op;
const ret_ty = cg.fn_type.fnReturnType(cg.pt.zcu);
const ret_ty = cg.fn_type.fnReturnType(zcu);
switch (cg.ret_mcv.short) {
.none => {},
.register => |reg| {
@@ -176660,7 +176662,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
var dst = try cg.tempInit(ret_ty, cg.ret_mcv.short);
dst.copyToMask(&src, cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select ret {f} {f} {f}", .{
ret_ty.fmt(cg.pt),
ret_ty.fmt(zcu),
dst.tracking(cg),
src.tracking(cg),
}),
@@ -176706,6 +176708,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
}
fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void {
const zcu = cg.pt.zcu;
const un_op = cg.air.instructions.items(.data)[@backingInt(inst)].un_op;
switch (cg.ret_mcv.short) {
.none => {},
@@ -176716,13 +176719,13 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void {
=> try cg.load(cg.ret_mcv.short, cg.typeOf(un_op), try cg.resolveInst(un_op)),
.register_mask => {
var ptr = try cg.tempFromOperand(un_op, true);
const ret_ty = ptr.typeOf(cg).childType(cg.pt.zcu);
const ret_ty = ptr.typeOf(cg).childType(zcu);
var src = try ptr.load(ret_ty, .{}, cg);
try ptr.die(cg);
var dst = try cg.tempInit(ret_ty, cg.ret_mcv.short);
dst.copyToMask(&src, cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select ret_load {f} {f} {f}", .{
ret_ty.fmt(cg.pt),
ret_ty.fmt(zcu),
dst.tracking(cg),
src.tracking(cg),
}),
@@ -176839,7 +176842,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !?Mir.Inst.Index {
return try self.asmJccReloc(.z, undefined);
},
else => return self.fail("TODO implement condbr when condition is {f} {s}", .{
ty.fmt(self.pt), @tagName(mcv),
ty.fmt(self.pt.zcu), @tagName(mcv),
}),
}
}
@@ -178721,7 +178724,7 @@ fn moveStrategy(cg: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !M
},
.ip, .cr, .dr => {},
}
return cg.fail("TODO moveStrategy for {f}", .{ty.fmt(pt)});
return cg.fail("TODO moveStrategy for {f}", .{ty.fmt(zcu)});
}
const CopyOptions = struct {
@@ -178729,7 +178732,7 @@ const CopyOptions = struct {
};
fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: CopyOptions) InnerError!void {
const pt = self.pt;
const zcu = self.pt.zcu;
const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
@@ -178790,7 +178793,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
.register => |src_reg| switch (dst_regs[0].class()) {
.general_purpose => switch (src_reg.class()) {
else => unreachable,
.sse => if (ty.abiSize(pt.zcu) <= 16) {
.sse => if (ty.abiSize(zcu) <= 16) {
if (self.hasFeature(.avx)) {
try self.asmRegisterRegister(.{ .v_q, .mov }, dst_regs[0].to64(), src_reg.to128());
try self.asmRegisterRegisterImmediate(.{ .vp_q, .extr }, dst_regs[1].to64(), src_reg.to128(), .u(1));
@@ -178865,7 +178868,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
},
.air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref), opts),
else => return self.fail("TODO implement genCopy for {s} of {f}", .{
@tagName(src_mcv), ty.fmt(pt),
@tagName(src_mcv), ty.fmt(zcu),
}),
};
defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
@@ -179249,7 +179252,7 @@ fn genSetReg(
80 => null,
else => unreachable,
},
}) orelse return cg.fail("TODO implement genSetReg for {f}", .{ty.fmt(pt)}),
}) orelse return cg.fail("TODO implement genSetReg for {f}", .{ty.fmt(zcu)}),
dst_alias,
registerAlias(src_reg, @intCast(cg.unalignedSize(ty))),
),
@@ -179360,7 +179363,7 @@ fn genSetReg(
assert(!ty.optionalReprIsPayload(zcu));
break :first_ty opt_child;
},
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, ty.fmt(pt) }),
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, ty.fmt(zcu) }),
});
const first_size: u31 = @intCast(first_ty.abiSize(zcu));
const frame_size = std.math.ceilPowerOfTwoAssert(u32, abi_size);
@@ -179769,7 +179772,7 @@ fn genSetMem(
);
},
else => return cg.fail("TODO implement genSetMem for {s} of {f}", .{
@tagName(src_mcv), ty.fmt(pt),
@tagName(src_mcv), ty.fmt(zcu),
}),
},
.register_offset => |reg_off| {
@@ -180329,7 +180332,7 @@ fn atomicOp(
},
else => unreachable,
}) orelse return self.fail("TODO implement atomicOp of {s} for {f}", .{
@tagName(op), val_ty.fmt(pt),
@tagName(op), val_ty.fmt(zcu),
});
try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});
switch (mir_tag[0]) {
@@ -180778,12 +180781,12 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
else
try self.copyToTmpRegister(pred_ty, pred_mcv)
else
return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)}),
return self.fail("TODO implement airSelect for {f}", .{ty.fmt(zcu)}),
else => unreachable,
},
.register_mask => |pred_reg_mask| {
if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
return self.fail("TODO implement airSelect for {f}", .{ty.fmt(zcu)});
const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
try self.register_manager.getKnownReg(.xmm0, null);
@@ -180857,7 +180860,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
else
null
else
null) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
null) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(zcu)});
if (has_avx) {
const rhs_alias = if (reuse_mcv.isRegister())
registerAlias(reuse_mcv.getReg().?, abi_size)
@@ -181010,7 +181013,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
else => unreachable,
}),
);
} else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
} else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(zcu)});
const elem_bits: u16 = @intCast(elem_abi_size * 8);
if (!pred_fits_in_elem) if (self.hasFeature(.ssse3)) {
const mask_len = elem_abi_size * vec_len;
@@ -181039,7 +181042,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
mask_alias,
mask_mem,
);
} else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
} else return self.fail("TODO implement airSelect for {f}", .{ty.fmt(zcu)});
{
const mask_elem_ty = try pt.intType(.unsigned, elem_bits);
const mask_ty = try pt.vectorType(.{ .len = vec_len, .child = mask_elem_ty.toIntern() });
@@ -181159,7 +181162,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
else => null,
},
},
}) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(pt)});
}) orelse return self.fail("TODO implement airSelect for {f}", .{ty.fmt(zcu)});
if (has_avx) {
const rhs_alias = if (rhs_mcv.isRegister())
registerAlias(rhs_mcv.getReg().?, abi_size)
@@ -181466,7 +181469,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
assert(classes.len == 1);
unreachable;
},
else => return self.fail("TODO implement c_va_arg for {f} on SysV", .{promote_ty.fmt(pt)}),
else => return self.fail("TODO implement c_va_arg for {f} on SysV", .{promote_ty.fmt(zcu)}),
}
if (unused) break :result .unreach;
@@ -181512,7 +181515,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
try self.genCopy(.usize, next_arg_ptr, .{ .register = next_arg_ptr_reg }, .{});
},
.memory => unreachable,
else => return self.fail("TODO implement c_va_arg for {f} on Win64", .{promote_ty.fmt(pt)}),
else => return self.fail("TODO implement c_va_arg for {f} on Win64", .{promote_ty.fmt(zcu)}),
}
if (unused) break :result .unreach;
@@ -182299,7 +182302,7 @@ fn splitType(self: *CodeGen, comptime parts_len: usize, ty: Type) ![parts_len]Ty
if (abi_size == parts_size) return parts;
if (classes[classes.len - 1] == .float and abi_size > parts_size and abi_size <= parts_size + 4) return parts;
};
return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(pt) });
return self.fail("TODO implement splitType({d}, {f})", .{ parts_len, ty.fmt(zcu) });
}
/// Truncates the value in the register in place.
@@ -183183,6 +183186,7 @@ const Temp = struct {
}
fn store(ptr: *Temp, val: *Temp, opts: AccessOptions, cg: *CodeGen) InnerError!void {
const zcu = cg.pt.zcu;
const val_ty = val.typeOf(cg);
try ptr.toOffset(opts.disp, cg);
while (try ptr.toLea(cg)) {}
@@ -183194,7 +183198,7 @@ const Temp = struct {
else => |mcv| std.debug.panic("{s}: {f}\n", .{ @src().fn_name, mcv }),
.undef => if (opts.safe) {
var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(zcu) });
try ptr.memset(&pat, &len, cg);
try pat.die(cg);
try len.die(cg);
@@ -183248,12 +183252,12 @@ const Temp = struct {
.register_offset => |val_reg_off| switch (val_reg_off.off) {
0 => try ptr.storeRegs(val_ty, &.{registerAlias(
val_reg_off.reg,
@intCast(val_ty.abiSize(cg.pt.zcu)),
@intCast(val_ty.abiSize(zcu)),
)}, cg),
else => continue :val_to_gpr,
},
.register_overflow => |val_reg_ov| {
const ip = &cg.pt.zcu.intern_pool;
const ip = &zcu.intern_pool;
const first_ty: Type = .fromInterned(first_ty: switch (ip.indexToKey(val_ty.toIntern())) {
.tuple_type => |tuple_type| {
const tuple_field_types = tuple_type.types.get(ip);
@@ -183261,12 +183265,12 @@ const Temp = struct {
break :first_ty tuple_field_types[0];
},
.opt_type => |opt_child| {
assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));
assert(!val_ty.optionalReprIsPayload(zcu));
break :first_ty opt_child;
},
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(zcu) }),
});
const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
const first_size: u31 = @intCast(first_ty.abiSize(zcu));
try ptr.storeRegs(first_ty, &.{registerAlias(val_reg_ov.reg, first_size)}, cg);
try ptr.toOffset(first_size, cg);
try cg.asmSetccMemory(
@@ -183277,7 +183281,7 @@ const Temp = struct {
.lea_frame, .lea_nav, .lea_uav, .lea_lazy_sym => continue :val_to_gpr,
.memory, .indirect, .load_frame, .load_nav, .load_uav, .load_lazy_sym => {
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
try ptr.memcpy(&val_ptr, val_ty.abiSize(cg.pt.zcu), cg);
try ptr.memcpy(&val_ptr, val_ty.abiSize(zcu), cg);
try val_ptr.die(cg);
},
}
@@ -183325,6 +183329,7 @@ const Temp = struct {
}
fn write(dst: *Temp, val: *Temp, opts: AccessOptions, cg: *CodeGen) InnerError!void {
const zcu = cg.pt.zcu;
const val_ty = val.typeOf(cg);
while (try dst.toBase(false, cg)) {}
val_to_gpr: while (true) : (while (try dst.toBase(false, cg) or
@@ -183337,7 +183342,7 @@ const Temp = struct {
.undef => if (opts.safe) {
var dst_ptr = try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
var pat = try cg.tempInit(.u8, .{ .immediate = 0xaa });
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(cg.pt.zcu) });
var len = try cg.tempInit(.usize, .{ .immediate = val_ty.abiSize(zcu) });
try dst_ptr.memset(&pat, &len, cg);
try dst_ptr.die(cg);
try pat.die(cg);
@@ -183364,7 +183369,7 @@ const Temp = struct {
),
.register => |val_reg| try dst.writeReg(opts.disp, val_ty, registerAlias(
val_reg,
@intCast(val_ty.abiSize(cg.pt.zcu)),
@intCast(val_ty.abiSize(zcu)),
), cg),
inline .register_pair,
.register_triple,
@@ -183373,12 +183378,12 @@ const Temp = struct {
.register_offset => |val_reg_off| switch (val_reg_off.off) {
0 => try dst.writeReg(opts.disp, val_ty, registerAlias(
val_reg_off.reg,
@intCast(val_ty.abiSize(cg.pt.zcu)),
@intCast(val_ty.abiSize(zcu)),
), cg),
else => continue :val_to_gpr,
},
.register_overflow => |val_reg_ov| {
const ip = &cg.pt.zcu.intern_pool;
const ip = &zcu.intern_pool;
const first_ty: Type = .fromInterned(first_ty: switch (ip.indexToKey(val_ty.toIntern())) {
.tuple_type => |tuple_type| {
const tuple_field_types = tuple_type.types.get(ip);
@@ -183386,12 +183391,12 @@ const Temp = struct {
break :first_ty tuple_field_types[0];
},
.opt_type => |opt_child| {
assert(!val_ty.optionalReprIsPayload(cg.pt.zcu));
assert(!val_ty.optionalReprIsPayload(zcu));
break :first_ty opt_child;
},
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(cg.pt) }),
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, val_ty.fmt(zcu) }),
});
const first_size: u31 = @intCast(first_ty.abiSize(cg.pt.zcu));
const first_size: u31 = @intCast(first_ty.abiSize(zcu));
try dst.writeReg(opts.disp, first_ty, registerAlias(val_reg_ov.reg, first_size), cg);
try cg.asmSetccMemory(
val_reg_ov.eflags,
@@ -183406,7 +183411,7 @@ const Temp = struct {
var dst_ptr =
try cg.tempInit(.usize, dst.tracking(cg).short.address().offset(opts.disp));
var val_ptr = try cg.tempInit(.usize, val_mcv.address());
try dst_ptr.memcpy(&val_ptr, val_ty.abiSize(cg.pt.zcu), cg);
try dst_ptr.memcpy(&val_ptr, val_ty.abiSize(zcu), cg);
try dst_ptr.die(cg);
try val_ptr.die(cg);
},
@@ -183444,7 +183449,7 @@ const Temp = struct {
assert(src_regs.len == @divCeil(int_info.bits, 64));
break :part_ty .u64;
} else part_ty: switch (ip.indexToKey(src_ty.toIntern())) {
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(zcu) }),
.ptr_type => |ptr_info| {
assert(ptr_info.flags.size == .slice);
assert(src_regs.len == 2);
@@ -183463,7 +183468,7 @@ const Temp = struct {
}),
},
.opt_type => |opt_child| switch (ip.indexToKey(opt_child)) {
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(cg.pt) }),
else => std.debug.panic("{s}: {f}\n", .{ @src().fn_name, src_ty.fmt(zcu) }),
.ptr_type => |ptr_info| {
assert(ptr_info.flags.size == .slice);
assert(src_regs.len == 2);
@@ -189637,7 +189642,7 @@ fn resetTemps(cg: *CodeGen, from_index: Temp.Index) InnerError!void {
any_valid = true;
tracking_log.err("failed to kill {f}: {f}", .{
temp.toIndex(),
cg.temp_type[temp_index].fmt(cg.pt),
cg.temp_type[temp_index].fmt(cg.pt.zcu),
});
}
cg.temp_type[temp_index] = undefined;
+22 -39
View File
@@ -5766,7 +5766,7 @@ fn flushImplib(
try file_writer.interface.flush();
}
fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
fn reportUndefs(coff: *Coff) !void {
const comp = coff.base.comp;
const gpa = comp.gpa;
const max_notes = 4;
@@ -5887,14 +5887,8 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
const ip = &comp.zcu.?.intern_pool;
break :format ip.getNav(val.navIndex(coff)).fqn.fmt(ip);
},
.uav => Value.fromInterned(val.uavValue(coff)).fmtValue(.{
.zcu = coff.base.comp.zcu.?,
.tid = tid,
}),
inline .lazy_code, .lazy_const_data => Type.fromInterned(val.lazySymbol(coff).ty).fmt(.{
.zcu = coff.base.comp.zcu.?,
.tid = tid,
}),
.uav => Value.fromInterned(val.uavValue(coff)).fmtValue(coff.base.comp.zcu.?),
inline .lazy_code, .lazy_const_data => Type.fromInterned(val.lazySymbol(coff).ty).fmt(coff.base.comp.zcu.?),
else => unreachable,
},
});
@@ -5927,7 +5921,7 @@ pub fn flush(
const comp = coff.base.comp;
while (try coff.resolve(tid)) {}
while (try coff.resolve()) {}
while (try coff.idle(tid)) {}
// This has to occur after all other flushMoved / flushResized have resolved,
@@ -5951,7 +5945,7 @@ pub fn flush(
while (try coff.idle(tid)) {}
if (coff.isImage())
try coff.reportUndefs(tid);
try coff.reportUndefs();
if (comp.emit_implib) |implib_file|
coff.flushImplib(implib_file) catch |err|
@@ -5970,7 +5964,7 @@ pub fn flush(
/// Runs a single "resolution" task.
/// These are tasks that need to modify the node structure in some way.
/// They must run in a defined order with respect to linker tasks.
fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
fn resolve(coff: *Coff) !bool {
const comp = coff.base.comp;
task: {
while (coff.section_merge_pending_index < coff.section_merges.count()) {
@@ -6046,7 +6040,6 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
const si = coff.symbol_table.symbols.keys()[coff.symbol_table.pending_symbol_index];
const sym = si.get(coff);
const sub_prog_node = coff.idleProgNode(
tid,
coff.symbol_prog_node,
if (sym.ni.unwrap()) |sym_ni|
coff.getNode(sym_ni)
@@ -6077,6 +6070,7 @@ fn resolve(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
}
pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
_ = tid;
// Idle tasks should not modify create / modify nodes, otherwise the output is not reproducible.
coff.mf.nodes_lock.lock();
defer coff.mf.nodes_lock.unlock();
@@ -6087,7 +6081,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
if (coff.input_section_pending_index < coff.input_sections.items.len) {
const isi: Node.InputSection.Index = @fromBackingInt(@intCast(coff.input_section_pending_index));
coff.input_section_pending_index += 1;
const sub_prog_node = coff.idleProgNode(tid, coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff)));
const sub_prog_node = coff.idleProgNode(coff.input_prog_node, coff.getNode(isi.symbol(coff).node(coff)));
defer sub_prog_node.end();
coff.flushInputSection(isi) catch |err| switch (err) {
else => |e| {
@@ -6112,7 +6106,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
const clean_next_moved = ni.cleanNextMoved(&coff.mf);
if (!clean_moved and !clean_resized and !clean_next_moved) continue;
const sub_prog_node =
coff.idleProgNode(tid, coff.mf.update_prog_node, coff.getNode(ni));
coff.idleProgNode(coff.mf.update_prog_node, coff.getNode(ni));
defer sub_prog_node.end();
if (clean_moved) try coff.flushMoved(ni);
if (clean_resized) try coff.flushResized(ni);
@@ -6120,7 +6114,6 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
}
while (coff.pending_members.pop()) |pending_mi| {
const sub_prog_node = coff.idleProgNode(
tid,
coff.symbol_prog_node,
coff.getNode(pending_mi.key.get(coff).content_ni),
);
@@ -6131,7 +6124,6 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
if (coff.exports_complete and coff.export_table.pending_sort) {
defer coff.export_table.pending_sort = false;
const sub_prog_node = coff.idleProgNode(
tid,
coff.synth_prog_node,
coff.getNode(coff.export_table.ni),
);
@@ -6150,7 +6142,6 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
fn idleProgNode(
coff: *Coff,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
node: Node,
) std.Progress.Node {
@@ -6173,10 +6164,7 @@ fn idleProgNode(
break :name ip.getNav(nmi.navIndex(coff)).fqn.toSlice(ip);
},
.uav => |umi| std.mem.print(&name, "{f}", .{
Value.fromInterned(umi.uavValue(coff)).fmtValue(.{
.zcu = coff.base.comp.zcu.?,
.tid = tid,
}),
Value.fromInterned(umi.uavValue(coff)).fmtValue(coff.base.comp.zcu.?),
}) catch &name,
.archive_member => |mi| &mi.get(coff).headerPtr(coff).name,
}, 0);
@@ -6185,7 +6173,7 @@ fn idleProgNode(
fn genPending(coff: *Coff, pt: Zcu.PerThread) Error!void {
const comp = pt.zcu.comp;
while (coff.pending_uavs.pop()) |pending_uav| {
const sub_prog_node = coff.idleProgNode(pt.tid, coff.const_prog_node, .{ .uav = pending_uav.key });
const sub_prog_node = coff.idleProgNode(coff.const_prog_node, .{ .uav = pending_uav.key });
defer sub_prog_node.end();
coff.genUav(pt, pending_uav.key, pending_uav.value.alignment) catch |err| switch (err) {
else => |e| return e,
@@ -6845,7 +6833,7 @@ fn genLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
const sub_prog_node = coff.synth_prog_node.start(
std.mem.print(&name, "lazy {s} for {f}", .{
kind,
Type.fromInterned(lazy.ty).fmt(pt),
Type.fromInterned(lazy.ty).fmt(coff.base.comp.zcu.?),
}) catch &name,
0,
);
@@ -7461,14 +7449,14 @@ fn updateExportInner(
switch (exp.exported) {
.nav => |nav| log.debug("updateExports({f}) = {d}", .{ ip.getNav(nav).fqn.fmt(ip), exported_si }),
.uav => |uav| log.debug("updateExports(@as({f}, {f})) = {d}", .{
Type.fromInterned(ip.typeOf(uav)).fmt(pt),
Value.fromInterned(uav).fmtValue(pt),
Type.fromInterned(ip.typeOf(uav)).fmt(zcu),
Value.fromInterned(uav).fmtValue(zcu),
exported_si,
}),
}
try coff.genPending(pt);
while (try coff.resolve(pt.tid)) {}
while (try coff.resolve()) {}
while (try coff.idle(pt.tid)) {}
const machine = coff.targetLoad(&coff.headerPtr().machine);
@@ -7627,7 +7615,7 @@ pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) Io.Writer.Error!l
try coff.printSection(w, name, sec.si);
try w.writeAll("Symbol table:\n");
for (1..coff.symbols.items.len) |si|
try coff.printSymbol(w, tid, @fromBackingInt(@intCast(si)));
try coff.printSymbol(w, @fromBackingInt(@intCast(si)));
return .enabled;
}
@@ -7648,7 +7636,6 @@ fn printSection(coff: *Coff, w: *Io.Writer, name: String, si: Symbol.Index) Io.W
fn printSymbol(
coff: *Coff,
w: *Io.Writer,
tid: Zcu.PerThread.Id,
si: Symbol.Index,
) Io.Writer.Error!void {
const sym = si.get(coff);
@@ -7687,7 +7674,7 @@ fn printSymbol(
try w.print("G {f}\n", .{fmtGlobalName(coff, sym.gmi)});
} else {
try w.writeAll("| ");
try coff.printNodeName(w, tid, coff.getNode(sym.ni.unwrap().?));
try coff.printNodeName(w, coff.getNode(sym.ni.unwrap().?));
if (sym.flags.extra_tag == .isli)
try w.print(" | {s}", .{sym.extra.isli.name(coff).toSlice(coff)});
try w.writeByte('\n');
@@ -7712,7 +7699,6 @@ fn globalNameEscape(data: FmtGlobalName, w: *std.Io.Writer) std.Io.Writer.Error!
fn printNodeName(
coff: *Coff,
w: *std.Io.Writer,
tid: Zcu.PerThread.Id,
node: Node,
) Io.Writer.Error!void {
switch (node) {
@@ -7754,7 +7740,7 @@ fn printNodeName(
const ip = &zcu.intern_pool;
const nav = ip.getNav(nmi.navIndex(coff));
try w.print("({f}, {f})", .{
Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }),
Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(zcu),
nav.fqn.fmt(ip),
});
},
@@ -7762,15 +7748,12 @@ fn printNodeName(
const zcu = coff.base.comp.zcu.?;
const val: Value = .fromInterned(umi.uavValue(coff));
try w.print("({f}, {f})", .{
val.typeOf(zcu).fmt(.{ .zcu = zcu, .tid = tid }),
val.fmtValue(.{ .zcu = zcu, .tid = tid }),
val.typeOf(zcu).fmt(zcu),
val.fmtValue(zcu),
});
},
inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{
Type.fromInterned(lmi.lazySymbol(coff).ty).fmt(.{
.zcu = coff.base.comp.zcu.?,
.tid = tid,
}),
Type.fromInterned(lmi.lazySymbol(coff).ty).fmt(coff.base.comp.zcu.?),
}),
.builtin => |si| {
const sym = si.get(coff);
@@ -7789,7 +7772,7 @@ pub fn printNode(
const node = coff.getNode(ni);
try w.splatByteAll(' ', indent);
try w.writeAll(@tagName(node));
try coff.printNodeName(w, tid, node);
try coff.printNodeName(w, node);
{
const mf_node = &coff.mf.nodes.items[@backingInt(ni)];
const off, const size = mf_node.location().resolve(&coff.mf);
+24 -23
View File
@@ -1036,7 +1036,7 @@ const Entry = struct {
const val_unit, const val_entry = unit_and_entry;
if (sec.getUnit(val_unit) == unit and unit.getEntry(val_entry) == entry)
log.err("missing Value({f}({d}))", .{
Value.fromInterned(val).fmtValue(.{ .tid = .main, .zcu = zcu }),
Value.fromInterned(val).fmtValue(zcu),
@backingInt(val),
});
}
@@ -2120,9 +2120,10 @@ pub const WipNav = struct {
wip_nav: *WipNav,
val: Value,
) (UpdateError || Writer.Error)!void {
const ty = val.typeOf(wip_nav.pt.zcu);
const zcu = wip_nav.pt.zcu;
const ty = val.typeOf(zcu);
const diw = &wip_nav.debug_info.writer;
const size = ty.abiSize(wip_nav.pt.zcu);
const size = ty.abiSize(zcu);
try diw.writeUleb128(size);
if (size == 0) return;
const old_end = diw.end;
@@ -2135,7 +2136,7 @@ pub const WipNav = struct {
);
if (old_end + size != diw.end) {
std.debug.print("{f} [{}]: {} != {}\n", .{
ty.fmt(wip_nav.pt),
ty.fmt(zcu),
ty.toIntern(),
size,
diw.end - old_end,
@@ -3340,8 +3341,8 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde
switch (value_index) {
.generic_poison_type => log.debug("updateValueIncomplete(anytype)", .{}),
else => log.debug("updateValueIncomplete(@as({f}, {f}))", .{
val.typeOf(zcu).fmt(pt),
val.fmtValue(pt),
val.typeOf(zcu).fmt(zcu),
val.fmtValue(zcu),
}),
}
@@ -3435,7 +3436,7 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde
else => |val_key| switch (val_key.typeOf()) {
.type_type => {
try wip_nav.abbrevCode(.generated_empty_struct_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
},
else => |ty| {
@@ -3509,8 +3510,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
switch (value_index) {
.generic_poison_type => log.debug("updateValue(anytype)", .{}),
else => log.debug("updateValue(@as({f}, {f}))", .{
val.typeOf(zcu).fmt(pt),
val.fmtValue(pt),
val.typeOf(zcu).fmt(zcu),
val.fmtValue(zcu),
}),
}
@@ -3551,7 +3552,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
.int_type => |int_type| {
try wip_nav.abbrevCode(.numeric_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try diw.writeByte(switch (int_type.signedness) {
inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)),
});
@@ -3566,7 +3567,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
.none => if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type,
else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type,
});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
if (ptr_type.sentinel != .none) try wip_nav.blockValue(.fromInterned(ptr_type.sentinel));
if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a);
try diw.writeByte(@backingInt(ptr_type.flags.address_space));
@@ -3592,7 +3593,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
},
.slice => {
try wip_nav.abbrevCode(.generated_struct_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try diw.writeUleb128(val.toType().abiSize(zcu));
try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
try wip_nav.abbrevCode(.generated_field);
@@ -3611,7 +3612,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
.array_type => |array_type| {
const array_child_type: Type = .fromInterned(array_type.child);
try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
if (array_type.sentinel != .none) try wip_nav.blockValue(.fromInterned(array_type.sentinel));
try wip_nav.refType(array_child_type);
try wip_nav.abbrevCode(.array_len);
@@ -3621,7 +3622,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
},
.vector_type => |vector_type| {
try wip_nav.abbrevCode(.vector_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try wip_nav.refType(.fromInterned(vector_type.child));
try wip_nav.abbrevCode(.array_len);
try wip_nav.refType(.usize);
@@ -3632,7 +3633,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
const opt_child_type: Type = .fromInterned(opt_child_type_index);
const opt_repr = optRepr(opt_child_type, zcu);
try wip_nav.abbrevCode(.generated_union_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try diw.writeUleb128(val.toType().abiSize(zcu));
try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
switch (opt_repr) {
@@ -3713,7 +3714,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
};
try wip_nav.abbrevCode(.generated_union_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
if (error_union_type.error_set_type != .generic_poison_type and
error_union_type.payload_type != .generic_poison_type)
{
@@ -3785,7 +3786,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
.bool,
=> {
try wip_nav.abbrevCode(.numeric_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try diw.writeByte(if (value_index == .bool_type)
DW.ATE.boolean
else if (val.toType().isRuntimeFloat())
@@ -3815,18 +3816,18 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
.enum_literal,
=> {
try wip_nav.abbrevCode(.void_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
},
.anyerror => unreachable, // already did early return above
.adhoc_inferred_error_set => unreachable,
},
.tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
try wip_nav.abbrevCode(.generated_empty_struct_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try diw.writeByte(@intFromBool(false));
} else {
try wip_nav.abbrevCode(.generated_struct_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try diw.writeUleb128(val.toType().abiSize(zcu));
try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?);
var field_byte_offset: u64 = 0;
@@ -4148,7 +4149,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
.func_type => |func_type| {
const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args;
try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
const cc: DW.CC = cc: {
if (zcu.getTarget().cCallingConvention()) |cc| {
if (@as(std.lang.CallingConvention.Tag, cc) == func_type.cc) {
@@ -4231,7 +4232,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
},
.error_set_type => |error_set_type| {
try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
.signedness = .unsigned,
.bits = zcu.errorSetBits(),
@@ -4247,7 +4248,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
},
.inferred_error_set_type => |func| {
try wip_nav.abbrevCode(.inferred_error_set_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
try wip_nav.strpFmt("{f}", .{val.toType().fmt(zcu)});
try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) {
.none => .anyerror_type,
else => |ies| ies,
+18 -17
View File
@@ -2516,7 +2516,7 @@ pub fn updateConst(
) link.Error!void {
switch (val) {
.generic_poison_type => log.debug("updateConst(anytype)", .{}),
else => log.debug("updateConst({f})", .{Value.fromInterned(val).fmtValue(pt)}),
else => log.debug("updateConst({f})", .{Value.fromInterned(val).fmtValue(pt.zcu)}),
}
dwarf.updateConstInner(pt, di_nw, val) catch |err| switch (err) {
else => |e| return e,
@@ -2538,7 +2538,7 @@ fn updateConstInner(
try dwarf.abbrevCode(di_nw, .numeric_type);
var name_buf: [std.fmt.count("i{d}", .{std.math.maxInt(u16)})]u8 = undefined;
try dwarf.strx(di_nw, std.mem.print(&name_buf, "{f}", .{
ty.fmt(pt),
ty.fmt(zcu),
}) catch unreachable);
try di_w.writeByte(switch (int_type.signedness) {
.signed => DW.ATE.signed,
@@ -2550,7 +2550,7 @@ fn updateConstInner(
},
.ptr_type => |ptr_type| switch (ptr_type.flags.size) {
.one, .many, .c => {
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, switch (ptr_type.sentinel) {
.none => .ptr_type,
@@ -2585,7 +2585,7 @@ fn updateConstInner(
},
.slice => {
const ty: Type = .fromInterned(@"const");
const name = try zcu.gpa.print("{f}", .{ty.fmt(pt)});
const name = try zcu.gpa.print("{f}", .{ty.fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, .generated_struct_type);
try dwarf.strx(di_nw, name);
@@ -2605,7 +2605,7 @@ fn updateConstInner(
},
},
.array_type => |array_type| {
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(
di_nw,
@@ -2621,7 +2621,7 @@ fn updateConstInner(
try di_w.writeUleb128(@backingInt(AbbrevCode.null));
},
.vector_type => |vector_type| {
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, .vector_type);
try dwarf.strx(di_nw, name);
@@ -2635,7 +2635,7 @@ fn updateConstInner(
const opt_ty: Type = .fromInterned(@"const");
const opt_child_ty: Type = .fromInterned(opt_child_type_index);
const opt_repr = optRepr(opt_child_ty, zcu);
const name = try zcu.gpa.print("{f}", .{opt_ty.fmt(pt)});
const name = try zcu.gpa.print("{f}", .{opt_ty.fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, .generated_union_type);
try dwarf.strx(di_nw, name);
@@ -2715,7 +2715,7 @@ fn updateConstInner(
codegen.errUnionPayloadOffset(eu_payload_ty, zcu),
},
};
const name = try zcu.gpa.print("{f}", .{eu_ty.fmt(pt)});
const name = try zcu.gpa.print("{f}", .{eu_ty.fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, .generated_union_type);
@@ -2819,7 +2819,7 @@ fn updateConstInner(
try dwarf.abbrevCode(di_nw, .void_type);
var name_buf: ["@TypeOf(undefined)".len]u8 = undefined;
try dwarf.strx(di_nw, std.mem.print(&name_buf, "{f}", .{
ty.fmt(pt),
ty.fmt(zcu),
}) catch unreachable);
},
.anyerror => {
@@ -2842,7 +2842,7 @@ fn updateConstInner(
},
.tuple_type => |tuple_type| {
const ty: Type = .fromInterned(@"const");
const name = try zcu.gpa.print("{f}", .{ty.fmt(pt)});
const name = try zcu.gpa.print("{f}", .{ty.fmt(zcu)});
defer zcu.gpa.free(name);
if (tuple_type.types.len == 0) {
try dwarf.abbrevCode(di_nw, .generated_empty_struct_type);
@@ -3255,7 +3255,7 @@ fn updateConstInner(
.spirv_type => unreachable,
.func_type => |func_type| {
const is_empty = func_type.param_types.len == 0 and !func_type.is_var_args;
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, if (is_empty) .empty_func_type else .func_type);
try dwarf.strx(di_nw, name);
@@ -3340,7 +3340,7 @@ fn updateConstInner(
if (!is_empty) try di_w.writeUleb128(@backingInt(AbbrevCode.null));
},
.error_set_type => |error_set_type| {
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(
di_nw,
@@ -3358,7 +3358,7 @@ fn updateConstInner(
if (error_set_type.names.len > 0) try di_w.writeUleb128(@backingInt(AbbrevCode.null));
},
.inferred_error_set_type => |func| {
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(@"const").fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, .inferred_error_set_type);
try dwarf.strx(di_nw, name);
@@ -3863,7 +3863,7 @@ pub fn updateConstIncomplete(
di_nw: *link.MappedFile.Node.Writer,
val: InternPool.Index,
) link.Error!void {
log.debug("updateConstIncomplete({f})", .{Value.fromInterned(val).fmtValue(pt)});
log.debug("updateConstIncomplete({f})", .{Value.fromInterned(val).fmtValue(pt.zcu)});
dwarf.updateConstIncompleteInner(pt, di_nw, val) catch |err| switch (err) {
else => |e| return e,
error.WriteFailed => return dwarf.reportWriteError(di_nw),
@@ -4021,7 +4021,7 @@ fn updateConstIncompleteInner(
},
else => |val_key| break :done switch (val_key.typeOf()) {
.type_type => {
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)});
const name = try zcu.gpa.print("{f}", .{Type.fromInterned(val).fmt(zcu)});
defer zcu.gpa.free(name);
try dwarf.abbrevCode(di_nw, .generated_empty_struct_type);
try dwarf.strx(di_nw, name);
@@ -4140,11 +4140,12 @@ pub fn genDecl(
di_nw: *link.MappedFile.Node.Writer,
instance: Decl.Instance,
) link.Error!void {
const zcu = pt.zcu;
switch (instance) {
.none => unreachable,
.@"const" => |@"const"| log.debug("genDecl({f})", .{Value.fromInterned(@"const").fmtValue(pt)}),
.@"const" => |@"const"| log.debug("genDecl({f})", .{Value.fromInterned(@"const").fmtValue(zcu)}),
.global => |global| log.debug("genDecl({f})", .{
pt.zcu.intern_pool.getNav(global).fqn.fmt(&pt.zcu.intern_pool),
zcu.intern_pool.getNav(global).fqn.fmt(&zcu.intern_pool),
}),
}
dwarf.genDeclInner(pt, di_nw, instance) catch |err| switch (err) {
+2 -2
View File
@@ -1720,7 +1720,7 @@ fn updateLazySymbol(
const name_str_index = blk: {
const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
@tagName(sym.kind),
Type.fromInterned(sym.ty).fmt(pt),
Type.fromInterned(sym.ty).fmt(zcu),
});
defer gpa.free(name);
break :blk try self.strtab.insert(gpa, name);
@@ -2349,7 +2349,7 @@ fn checkUavAllocated(pt: Zcu.PerThread, index: InternPool.Index, meta: AvMetadat
const uav = Value.fromInterned(index);
const ty = uav.typeOf(zcu);
log.err("UAV {f}({d}) assigned symbol {d} but not allocated!", .{
ty.fmt(pt),
ty.fmt(zcu),
index,
meta.symbol_index,
});
+23 -23
View File
@@ -10328,6 +10328,8 @@ fn flushInner(
}
pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
_ = tid;
// This function is called non-deterministically, and so must not affect the layout of any nodes.
elf.mf.nodes_lock.lock();
defer elf.mf.nodes_lock.unlock();
@@ -10343,7 +10345,7 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
const ii: Node.InputIndex = @fromBackingInt(elf.input_pending_index);
elf.input_pending_index += 1;
const idle_prog_node =
elf.startIdleProgress(tid, elf.input_prog_node, elf.getNode(ii.node(elf)));
elf.startIdleProgress(elf.input_prog_node, elf.getNode(ii.node(elf)));
defer idle_prog_node.end();
elf.flushInput(ii) catch |err| switch (err) {
else => |e| return e,
@@ -10355,7 +10357,7 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
const isi: InputSection.Index = @fromBackingInt(elf.input_section_pending_index);
elf.input_section_pending_index += 1;
const idle_prog_node =
elf.startIdleProgress(tid, elf.input_prog_node, elf.getNode(isi.node(elf)));
elf.startIdleProgress(elf.input_prog_node, elf.getNode(isi.node(elf)));
defer idle_prog_node.end();
elf.flushInputSection(isi) catch |err| switch (err) {
else => |e| return e,
@@ -10465,7 +10467,7 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
const clean_resized = ni.cleanResized(&elf.mf);
const clean_next_moved = ni.cleanNextMoved(&elf.mf);
if (!clean_moved and !clean_resized and !clean_next_moved) continue;
const idle_prog_node = elf.startIdleProgress(tid, elf.mf.update_prog_node, elf.getNode(ni));
const idle_prog_node = elf.startIdleProgress(elf.mf.update_prog_node, elf.getNode(ni));
defer idle_prog_node.end();
if (clean_moved) try elf.flushMoved(ni);
if (clean_resized) try elf.flushResized(ni);
@@ -10483,7 +10485,6 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
fn startIdleProgress(
elf: *Elf,
tid: Zcu.PerThread.Id,
prog_node: std.Progress.Node,
node: Node,
) std.Progress.Node {
@@ -10508,7 +10509,7 @@ fn startIdleProgress(
break :name ip.getNav(nmi.nav(elf)).fqn.toSlice(ip);
},
.uav => |umi| std.mem.print(&name, "{f}", .{
Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
Value.fromInterned(umi.uavValue(elf)).fmtValue(elf.base.comp.zcu.?),
}) catch &name,
.debug_shared => |ss| switch (ss) {
.debug_abbrev => "debug info abbrevs",
@@ -10539,7 +10540,7 @@ fn startIdleProgress(
.const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) {
.generic_poison_type => "anytype",
else => |val| std.mem.print(&name, "debug info for {f}", .{
Value.fromInterned(val).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
Value.fromInterned(val).fmtValue(elf.base.comp.zcu.?),
}) catch &name,
},
.global_debug_info => |gi| {
@@ -10571,10 +10572,11 @@ fn startIdleProgress(
}
fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
const zcu = elf.base.comp.zcu.?;
while (elf.pending_uavs.pop()) |umi| {
var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
const prog_name = std.mem.print(&prog_name_buf, "{f}", .{
Value.fromInterned(umi.uavValue(elf)).fmtValue(pt),
Value.fromInterned(umi.uavValue(elf)).fmtValue(zcu),
}) catch &prog_name_buf;
const prog_node = elf.const_prog_node.start(prog_name, 0);
defer prog_node.end();
@@ -10671,14 +10673,15 @@ fn genUav(
}
fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) link.Error!void {
const zcu = elf.base.comp.zcu.?;
const lazy = lmr.lazySymbol(elf);
if (lazy.ty == .anyerror_type) return;
const lazy_ty: Type = .fromInterned(lazy.ty);
var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(pt.zcu)) {
.@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(zcu)) {
.@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(zcu)}) catch &prog_name_buf,
.error_set => switch (lmr.kind) {
.code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
.code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(zcu)}) catch &prog_name_buf,
.const_data => "@errorName(anyerror)",
},
else => unreachable,
@@ -12143,8 +12146,8 @@ fn updateExportInner(
switch (@"export".exported) {
.nav => |nav| log.debug("updateExports({f})", .{ip.getNav(nav).fqn.fmt(ip)}),
.uav => |uav| log.debug("updateExports(@as({f}, {f}))", .{
Type.fromInterned(ip.typeOf(uav)).fmt(pt),
Value.fromInterned(uav).fmtValue(pt),
Type.fromInterned(ip.typeOf(uav)).fmt(zcu),
Value.fromInterned(uav).fmtValue(zcu),
}),
}
const exported_lsi: Symbol.LocalIndex = switch (@"export".exported) {
@@ -12277,7 +12280,7 @@ pub fn printNode(
const ip = &zcu.intern_pool;
const nav = ip.getNav(nmi.nav(elf));
try w.print("({f}, {f})", .{
Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
Type.fromInterned(nav.resolved.?.type).fmt(zcu),
nav.fqn.fmt(ip),
});
},
@@ -12285,15 +12288,12 @@ pub fn printNode(
const zcu = elf.base.comp.zcu.?;
const val: Value = .fromInterned(umi.uavValue(elf));
try w.print("({f}, {f})", .{
val.typeOf(zcu).fmt(.{ .zcu = zcu, .tid = tid }),
val.fmtValue(.{ .zcu = zcu, .tid = tid }),
val.typeOf(zcu).fmt(zcu),
val.fmtValue(zcu),
});
},
inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{
Type.fromInterned(lmi.lazySymbol(elf).ty).fmt(.{
.zcu = elf.base.comp.zcu.?,
.tid = tid,
}),
Type.fromInterned(lmi.lazySymbol(elf).ty).fmt(elf.base.comp.zcu.?),
}),
.debug_shared => |ss| try w.print("({})", .{ss}),
.unit_frame,
@@ -12308,7 +12308,7 @@ pub fn printNode(
.const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) {
.generic_poison_type => try w.writeAll("(anytype)"),
else => |val| try w.print("({f})", .{
Value.fromInterned(val).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
Value.fromInterned(val).fmtValue(elf.base.comp.zcu.?),
}),
},
.global_debug_info => |gi| {
@@ -12317,11 +12317,11 @@ pub fn printNode(
const nav = ip.getNav(gi.nav(&elf.dwarf));
try w.writeByte('(');
if (nav.resolved) |resolved| try w.print("{f}, ", .{
Type.fromInterned(resolved.type).fmt(.{ .zcu = zcu, .tid = tid }),
Type.fromInterned(resolved.type).fmt(zcu),
});
try w.print("{f}", .{nav.fqn.fmt(ip)});
if (nav.resolved) |resolved| try w.print(", {f}", .{
Value.fromInterned(resolved.value).fmtValue(.{ .zcu = zcu, .tid = tid }),
Value.fromInterned(resolved.value).fmtValue(zcu),
});
try w.writeByte(')');
},
@@ -12331,7 +12331,7 @@ pub fn printNode(
const nav = ip.getNav(fi.nav(&elf.dwarf));
try w.writeByte('(');
if (nav.resolved) |resolved| try w.print("{f}, ", .{
Type.fromInterned(resolved.type).fmt(.{ .zcu = zcu, .tid = tid }),
Type.fromInterned(resolved.type).fmt(zcu),
});
try w.print("{f})", .{nav.fqn.fmt(ip)});
},
+1 -1
View File
@@ -1330,7 +1330,7 @@ fn updateLazySymbol(
const name_str = blk: {
const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
@tagName(lazy_sym.kind),
Type.fromInterned(lazy_sym.ty).fmt(pt),
Type.fromInterned(lazy_sym.ty).fmt(zcu),
});
defer gpa.free(name);
break :blk try self.addString(gpa, name);
+122 -123
View File
@@ -10,28 +10,29 @@ const InternPool = @import("InternPool.zig");
const Allocator = std.mem.Allocator;
const Target = std.Target;
const Writer = std.Io.Writer;
const assert = std.debug.assert;
const max_aggregate_items = 100;
const max_string_len = 256;
pub const FormatContext = struct {
val: Value,
pt: Zcu.PerThread,
zcu: *Zcu,
opt_sema: ?*Sema,
depth: u8,
};
pub fn formatSema(ctx: FormatContext, writer: *Writer) Writer.Error!void {
const sema = ctx.opt_sema.?;
return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) {
return print(ctx.val, writer, ctx.depth, ctx.zcu, sema) catch |err| switch (err) {
error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
error.WriteFailed => |e| return e,
};
}
pub fn format(ctx: FormatContext, writer: *Writer) Writer.Error!void {
std.debug.assert(ctx.opt_sema == null);
return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) {
assert(ctx.opt_sema == null);
return print(ctx.val, writer, ctx.depth, ctx.zcu, null) catch |err| switch (err) {
error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
error.WriteFailed => |e| return e,
};
@@ -41,10 +42,9 @@ pub fn print(
val: Value,
writer: *Writer,
level: u8,
pt: Zcu.PerThread,
zcu: *Zcu,
opt_sema: ?*Sema,
) (Writer.Error || Allocator.Error)!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
switch (ip.indexToKey(val.toIntern())) {
.int_type,
@@ -64,7 +64,7 @@ pub fn print(
.func_type,
.error_set_type,
.inferred_error_set_type,
=> try Type.print(val.toType(), writer, pt, null),
=> try Type.print(val.toType(), writer, zcu, null),
.undef => try writer.writeAll("undefined"),
.simple_value => |simple_value| switch (simple_value) {
.void => try writer.writeAll("{}"),
@@ -88,7 +88,7 @@ pub fn print(
.err_name => |err_name| try writer.print("error.{f}", .{
err_name.fmt(ip),
}),
.payload => |payload| try print(Value.fromInterned(payload), writer, level, pt, opt_sema),
.payload => |payload| try print(Value.fromInterned(payload), writer, level, zcu, opt_sema),
},
.enum_literal => |enum_literal| try writer.print(".{f}", .{
enum_literal.fmt(ip),
@@ -101,7 +101,7 @@ pub fn print(
}
try writer.writeAll("@fromBackingInt(");
if (level == 0) return writer.writeAll("...)");
try print(.fromInterned(enum_tag.int), writer, level - 1, pt, opt_sema);
try print(.fromInterned(enum_tag.int), writer, level - 1, zcu, opt_sema);
try writer.writeAll(")");
},
.float => |float| switch (float.storage) {
@@ -112,7 +112,7 @@ pub fn print(
if (slice.len == .zero_usize) {
return writer.writeAll("&.{}");
}
try print(.fromInterned(slice.ptr), writer, level, pt, opt_sema);
try print(.fromInterned(slice.ptr), writer, level, zcu, opt_sema);
} else {
const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) {
.field, .arr_elem, .eu_payload, .opt_payload => unreachable,
@@ -123,13 +123,13 @@ pub fn print(
// TODO: eventually we want to load the slice as an array with `sema`, but that's
// currently not possible without e.g. triggering compile errors.
}
try printPtr(Value.fromInterned(slice.ptr), null, writer, level, pt, opt_sema);
try printPtr(Value.fromInterned(slice.ptr), null, writer, level, zcu, opt_sema);
}
try writer.writeAll("[0..");
if (level == 0) {
try writer.writeAll("(...)");
} else {
try print(Value.fromInterned(slice.len), writer, level - 1, pt, opt_sema);
try print(Value.fromInterned(slice.len), writer, level - 1, zcu, opt_sema);
}
try writer.writeAll("]");
},
@@ -143,28 +143,28 @@ pub fn print(
// TODO: eventually we want to load the pointer with `sema`, but that's
// currently not possible without e.g. triggering compile errors.
}
try printPtr(val, .rvalue, writer, level, pt, opt_sema);
try printPtr(val, .rvalue, writer, level, zcu, opt_sema);
},
.opt => |opt| switch (opt.val) {
.none => try writer.writeAll("null"),
else => |payload| try print(Value.fromInterned(payload), writer, level, pt, opt_sema),
else => |payload| try print(Value.fromInterned(payload), writer, level, zcu, opt_sema),
},
.aggregate => |aggregate| try printAggregate(val, aggregate, false, writer, level, pt, opt_sema),
.aggregate => |aggregate| try printAggregate(val, aggregate, false, writer, level, zcu, opt_sema),
.un => |un| {
if (level == 0) {
try writer.writeAll(".{ ... }");
return;
}
if (un.tag == .none) {
const backing_ty = try val.typeOf(zcu).externUnionBackingType(pt);
try writer.print("@bitCast(@as({f}, ", .{backing_ty.fmt(pt)});
try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema);
const backing_val: Value = .fromInterned(un.val);
try writer.print("@bitCast(@as({f}, ", .{backing_val.typeOf(zcu).fmt(zcu)});
try print(backing_val, writer, level - 1, zcu, opt_sema);
try writer.writeAll("))");
} else {
try writer.writeAll(".{ ");
try print(Value.fromInterned(un.tag), writer, level - 1, pt, opt_sema);
try print(Value.fromInterned(un.tag), writer, level - 1, zcu, opt_sema);
try writer.writeAll(" = ");
try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema);
try print(Value.fromInterned(un.val), writer, level - 1, zcu, opt_sema);
try writer.writeAll(" }");
}
},
@@ -173,35 +173,17 @@ pub fn print(
return writer.writeAll(".{ ... }");
}
const ty: Type = .fromInterned(bitpack.ty);
switch (ty.zigTypeTag(zcu)) {
.@"struct" => {
if (ty.structFieldCount(zcu) == 0) {
return writer.writeAll(".{}");
}
try writer.writeAll(".{ ");
const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items);
for (0..max_len) |i| {
if (i != 0) try writer.writeAll(", ");
const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;
try writer.print(".{f} = ", .{field_name.fmt(ip)});
try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);
}
try writer.writeAll(" }");
return;
switch (ty.backingIntMode(zcu)) {
.auto => {
try writer.print("@bitCast(@as({f}, ", .{ty.backingIntType(zcu).fmt(zcu)});
try print(.fromInterned(bitpack.backing_int_val), writer, level - 1, zcu, opt_sema);
try writer.writeAll("))");
},
.@"union" => switch (ty.backingIntMode(zcu)) {
.auto => {
try writer.print("@bitCast(@as({f}, ", .{ty.backingIntType(zcu).fmt(pt)});
try print(.fromInterned(bitpack.backing_int_val), writer, level - 1, pt, opt_sema);
try writer.writeAll("))");
},
.explicit => {
try writer.writeAll("@fromBackingInt(");
try print(.fromInterned(bitpack.backing_int_val), writer, level - 1, pt, opt_sema);
try writer.writeAll(")");
},
.explicit => {
try writer.writeAll("@fromBackingInt(");
try print(.fromInterned(bitpack.backing_int_val), writer, level - 1, zcu, opt_sema);
try writer.writeAll(")");
},
else => unreachable,
}
},
.memoized_call => unreachable,
@@ -214,14 +196,13 @@ fn printAggregate(
is_ref: bool,
writer: *Writer,
level: u8,
pt: Zcu.PerThread,
zcu: *Zcu,
opt_sema: ?*Sema,
) (Writer.Error || Allocator.Error)!void {
if (level == 0) {
if (is_ref) try writer.writeByte('&');
return writer.writeAll(".{ ... }");
}
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const ty = Type.fromInterned(aggregate.ty);
switch (ty.zigTypeTag(zcu)) {
@@ -236,7 +217,7 @@ fn printAggregate(
if (i != 0) try writer.writeAll(", ");
const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?;
try writer.print(".{f} = ", .{field_name.fmt(ip)});
try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);
try printFieldValue(val, i, writer, level - 1, zcu, opt_sema);
}
try writer.writeAll(" }");
return;
@@ -285,7 +266,7 @@ fn printAggregate(
0 => try writer.writeAll(".{}"),
1 => {
try writer.writeAll(".{");
try print(try val.fieldValue(pt, 0), writer, level - 1, pt, opt_sema);
try printFieldValue(val, 0, writer, level - 1, zcu, opt_sema);
try writer.writeByte('}');
},
else => {
@@ -293,7 +274,7 @@ fn printAggregate(
const max_len = @min(len, max_aggregate_items);
for (0..max_len) |i| {
if (i != 0) try writer.writeAll(", ");
try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema);
try printFieldValue(val, i, writer, level - 1, zcu, opt_sema);
}
if (len > max_aggregate_items) {
try writer.writeAll(", ...");
@@ -303,16 +284,40 @@ fn printAggregate(
}
}
/// We cannot use `aggregate_val.fieldValue(...)` here because for some representations of aggregate
/// values the individual field values may not yet be in the `InternPool`. So, this function is the
/// equivalent of doing `print(try aggregate_val.fieldValue(...))`, which understands the optimized
/// value representations so does not need to intern new values.
fn printFieldValue(
aggregate_val: Value,
field_index: usize,
writer: *Writer,
level: u8,
zcu: *Zcu,
opt_sema: ?*Sema,
) (Writer.Error || Allocator.Error)!void {
const ip = &zcu.intern_pool;
switch (ip.indexToKey(aggregate_val.toIntern())) {
.undef => try writer.writeAll("undefined"),
.aggregate => |aggregate| switch (aggregate.storage) {
.bytes => |bytes| try writer.print("{d}", .{bytes.at(field_index, ip)}),
.elems => |elems| try print(.fromInterned(elems[field_index]), writer, level, zcu, opt_sema),
.repeated_elem => |elem| try print(.fromInterned(elem), writer, level, zcu, opt_sema),
},
else => unreachable,
}
}
fn printPtr(
ptr_val: Value,
/// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
want_kind: ?PrintPtrKind,
writer: *Writer,
level: u8,
pt: Zcu.PerThread,
zcu: *Zcu,
opt_sema: ?*Sema,
) (Writer.Error || Allocator.Error)!void {
const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) {
const ptr = switch (zcu.intern_pool.indexToKey(ptr_val.toIntern())) {
.undef => return writer.writeAll("undefined"),
.ptr => |ptr| ptr,
else => unreachable,
@@ -320,25 +325,25 @@ fn printPtr(
if (ptr.base_addr == .uav) {
// If the value is an aggregate, we can potentially print it more nicely.
switch (pt.zcu.intern_pool.indexToKey(ptr.base_addr.uav.val)) {
switch (zcu.intern_pool.indexToKey(ptr.base_addr.uav.val)) {
.aggregate => |agg| return printAggregate(
Value.fromInterned(ptr.base_addr.uav.val),
agg,
true,
writer,
level,
pt,
zcu,
opt_sema,
),
else => {},
}
}
var arena = std.heap.ArenaAllocator.init(pt.zcu.gpa);
var arena = std.heap.ArenaAllocator.init(zcu.gpa);
defer arena.deinit();
const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt, opt_sema);
const derivation = try ptr_val.pointerDerivation(arena.allocator(), zcu, opt_sema);
_ = try printPtrDerivation(derivation, writer, pt, want_kind, .{ .print_val = .{
_ = try printPtrDerivation(derivation, writer, zcu, want_kind, .{ .print_val = .{
.level = level,
.opt_sema = opt_sema,
} }, 20);
@@ -349,9 +354,9 @@ const PrintPtrKind = enum { lvalue, rvalue };
/// Print the pointer defined by `derivation` as an lvalue or an rvalue.
/// Returns the root derivation, which may be ignored.
pub fn printPtrDerivation(
derivation: Value.PointerDeriveStep,
derivation: Value.PointerDerivation,
writer: *Writer,
pt: Zcu.PerThread,
zcu: *Zcu,
/// Whether to print `derivation` as an lvalue or rvalue. If `null`, the more concise option is chosen.
/// If this is `.rvalue`, the result may look like `&foo`, so it's not necessarily valid to treat it as
/// an atom -- e.g. `&foo.*` is distinct from `(&foo).*`.
@@ -368,33 +373,36 @@ pub fn printPtrDerivation(
/// The maximum recursion depth. We can never recurse infinitely here, but the depth can be arbitrary,
/// so at this depth we just write "..." to prevent stack overflow.
ptr_depth: u8,
) !Value.PointerDeriveStep {
const zcu = pt.zcu;
) !Value.PointerDerivation {
const ip = &zcu.intern_pool;
if (ptr_depth == 0) {
const root_step = root: switch (derivation) {
inline .eu_payload_ptr,
.opt_payload_ptr,
.field_ptr,
.elem_ptr,
.offset_and_cast,
=> |step| continue :root step.parent.*,
else => |step| break :root step,
};
var root_step = derivation;
while (true) {
switch (derivation.addr) {
inline .eu_payload,
.opt_payload,
.field,
.elem,
.offset_and_cast,
=> |derived| root_step = derived.parent.*,
.int, .nav, .uav, .comptime_alloc, .comptime_field => break,
}
}
try writer.writeAll("...");
return root_step;
}
const result_kind: PrintPtrKind = switch (derivation) {
.nav_ptr,
.uav_ptr,
.comptime_alloc_ptr,
.comptime_field_ptr,
.eu_payload_ptr,
.opt_payload_ptr,
.field_ptr,
.elem_ptr,
const result_kind: PrintPtrKind = switch (derivation.addr) {
.nav,
.uav,
.comptime_alloc,
.comptime_field,
.eu_payload,
.opt_payload,
.field,
.elem,
=> .lvalue,
.offset_and_cast,
@@ -409,33 +417,33 @@ pub fn printPtrDerivation(
}
// null if `derivation` is the root.
const root_or_null: ?Value.PointerDeriveStep = switch (derivation) {
.eu_payload_ptr => |info| root: {
const root_or_null: ?Value.PointerDerivation = switch (derivation.addr) {
.eu_payload => |info| root: {
try writer.writeByte('(');
const root = try printPtrDerivation(info.parent.*, writer, pt, .lvalue, root_strat, ptr_depth - 1);
const root = try printPtrDerivation(info.parent.*, writer, zcu, .lvalue, root_strat, ptr_depth - 1);
try writer.writeAll(" catch unreachable)");
break :root root;
},
.opt_payload_ptr => |info| root: {
const root = try printPtrDerivation(info.parent.*, writer, pt, .lvalue, root_strat, ptr_depth - 1);
.opt_payload => |info| root: {
const root = try printPtrDerivation(info.parent.*, writer, zcu, .lvalue, root_strat, ptr_depth - 1);
try writer.writeAll(".?");
break :root root;
},
.field_ptr => |field| root: {
const root = try printPtrDerivation(field.parent.*, writer, pt, null, root_strat, ptr_depth - 1);
const agg_ty = (try field.parent.ptrType(pt)).childType(zcu);
.field => |derived| root: {
const root = try printPtrDerivation(derived.parent.*, writer, zcu, null, root_strat, ptr_depth - 1);
const agg_ty = derived.parent.elem_ty;
switch (agg_ty.zigTypeTag(zcu)) {
.@"struct" => if (agg_ty.structFieldName(field.field_idx, zcu).unwrap()) |field_name| {
.@"struct" => if (agg_ty.structFieldName(derived.field_index, zcu).unwrap()) |field_name| {
try writer.print(".{f}", .{field_name.fmt(ip)});
} else {
try writer.print("[{d}]", .{field.field_idx});
try writer.print("[{d}]", .{derived.field_index});
},
.@"union" => {
const tag_ty = agg_ty.unionTagTypeHypothetical(zcu);
const field_name = tag_ty.enumFieldName(field.field_idx, zcu);
const field_name = tag_ty.enumFieldName(derived.field_index, zcu);
try writer.print(".{f}", .{field_name.fmt(ip)});
},
.pointer => switch (field.field_idx) {
.pointer => switch (derived.field_index) {
Value.slice_ptr_index => try writer.writeAll(".ptr"),
Value.slice_len_index => try writer.writeAll(".len"),
else => unreachable,
@@ -444,58 +452,49 @@ pub fn printPtrDerivation(
}
break :root root;
},
.elem_ptr => |elem| root: {
const root = try printPtrDerivation(elem.parent.*, writer, pt, null, root_strat, ptr_depth - 1);
try writer.print("[{d}]", .{elem.elem_idx});
.elem => |derived| root: {
const root = try printPtrDerivation(derived.parent.*, writer, zcu, null, root_strat, ptr_depth - 1);
try writer.print("[{d}]", .{derived.elem_index});
break :root root;
},
.offset_and_cast => |oac| if (oac.byte_offset == 0) root: {
try writer.print("@as({f}, @ptrCast(", .{oac.new_ptr_ty.fmt(pt)});
const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);
.offset_and_cast => |derived| if (derived.byte_offset == 0) root: {
try writer.print("@as({f}, @ptrCast(", .{derivation.fmtType(zcu)});
const root = try printPtrDerivation(derived.parent.*, writer, zcu, .rvalue, root_strat, ptr_depth - 1);
try writer.writeAll("))");
break :root root;
} else root: {
try writer.print("@as({f}, @ptrFromInt(@intFromPtr(", .{oac.new_ptr_ty.fmt(pt)});
const root = try printPtrDerivation(oac.parent.*, writer, pt, .rvalue, root_strat, ptr_depth - 1);
try writer.print(") + {d}))", .{oac.byte_offset});
try writer.print("@as({f}, @ptrFromInt(@intFromPtr(", .{derivation.fmtType(zcu)});
const root = try printPtrDerivation(derived.parent.*, writer, zcu, .rvalue, root_strat, ptr_depth - 1);
try writer.print(") + {d}))", .{derived.byte_offset});
break :root root;
},
.int, .nav_ptr, .uav_ptr, .comptime_alloc_ptr, .comptime_field_ptr => null,
.int, .nav, .uav, .comptime_alloc, .comptime_field => null,
};
if (root_or_null == null) switch (root_strat) {
.str => |x| try writer.writeAll(x),
.print_val => |x| switch (derivation) {
.int => |int| try writer.print("@as({f}, @ptrFromInt(0x{x}))", .{ int.ptr_ty.fmt(pt), int.addr }),
.nav_ptr => |nav| try writer.print("{f}", .{ip.getNav(nav).fqn.fmt(ip)}),
.uav_ptr => |uav| {
const ty = Value.fromInterned(uav.val).typeOf(zcu);
try writer.print("@as({f}, ", .{ty.fmt(pt)});
.print_val => |x| switch (derivation.addr) {
.int => |int| {
try writer.print("@as({f}, @ptrFromInt(0x{x}))", .{ derivation.fmtType(zcu), int });
},
.nav => |nav| try writer.print("{f}", .{ip.getNav(nav).fqn.fmt(ip)}),
.uav, .comptime_field => |val| {
try writer.print("@as({f}, ", .{derivation.elem_ty.fmt(zcu)});
if (x.level == 0) {
try writer.writeAll("...");
} else {
try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema);
try print(val, writer, x.level - 1, zcu, x.opt_sema);
}
try writer.writeByte(')');
},
.comptime_alloc_ptr => |info| {
try writer.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)});
.comptime_alloc => |info| {
try writer.print("@as({f}, ", .{derivation.elem_ty.fmt(zcu)});
if (x.level == 0) {
try writer.writeAll("...");
} else {
try print(info.val, writer, x.level - 1, pt, x.opt_sema);
}
try writer.writeByte(')');
},
.comptime_field_ptr => |val| {
const ty = val.typeOf(zcu);
try writer.print("@as({f}, ", .{ty.fmt(pt)});
if (x.level == 0) {
try writer.writeAll("...");
} else {
try print(val, writer, x.level - 1, pt, x.opt_sema);
try print(info.val, writer, x.level - 1, zcu, x.opt_sema);
}
try writer.writeByte(')');
},