implement linker and c backend support for restricted type safety check

This commit is contained in:
Jacob Young
2026-04-21 07:09:23 -04:00
parent a8428b777c
commit 14ae0638ff
24 changed files with 1123 additions and 585 deletions
+5 -1
View File
@@ -12358,7 +12358,11 @@ pub fn addFieldTagValue(
/// encoding instead of `Tag.ptr_uav_aligned` when possible.
fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty: Index) bool {
if (a_ty == b_ty) return true;
const b_info = ip.indexToKey(b_ty).ptr_type;
const b_info = switch (ip.indexToKey(b_ty)) {
else => unreachable,
.ptr_type => |ptr_type| ptr_type,
.restricted_ptr_type => |restricted_ptr_type| ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type,
};
return a_info.flags.alignment == b_info.flags.alignment and
(a_info.child == b_info.child or a_info.flags.alignment != .none);
}
+8 -4
View File
@@ -1350,14 +1350,17 @@ pub fn unrestrictedType(ty: Type, zcu: *const Zcu) ?Type {
};
}
const RestrictedRepr = enum { double_pointer, single_pointer };
const RestrictedRepr = enum { indirect, direct };
pub fn restrictedRepr(ty: Type, zcu: *const Zcu) RestrictedRepr {
return restrictedReprByZirIndex(zcu.intern_pool.indexToKey(ty.toIntern()).restricted_ptr_type.zir_index, zcu);
return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
.restricted_ptr_type => |restricted_ptr_type| restrictedReprByZirIndex(restricted_ptr_type.zir_index, zcu),
else => .direct,
};
}
pub fn restrictedReprByZirIndex(zir_index: InternPool.TrackedInst.Index, zcu: *const Zcu) RestrictedRepr {
return switch (zcu.fileByIndex(zir_index.resolveFile(&zcu.intern_pool)).mod.?.optimize_mode) {
.Debug, .ReleaseSafe => .double_pointer,
.ReleaseFast, .ReleaseSmall => .single_pointer,
.Debug, .ReleaseSafe => if (zcu.backendSupportsFeature(.restricted_types)) .indirect else .direct,
.ReleaseFast, .ReleaseSmall => .direct,
};
}
@@ -2670,6 +2673,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {
const ip = &zcu.intern_pool;
return .{
.base_node_inst = switch (ip.indexToKey(ty.toIntern())) {
.restricted_ptr_type => |restricted_ptr_type| restricted_ptr_type.zir_index,
.struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
.declared => |d| d.zir_index,
.reified => |r| r.zir_index,
+1
View File
@@ -3995,6 +3995,7 @@ pub const Feature = enum {
/// * With this feature disabled, semantic analysis, code generation, and linking all occur on the
/// same thread, and the "emit" stage has access to AIR.
separate_thread,
restricted_types,
};
pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {
+241 -73
View File
@@ -210,7 +210,7 @@ pub fn generateLazyFunction(
debug_output: link.File.DebugInfoOutput,
) (CodeGenError || std.Io.Writer.Error)!void {
const zcu = pt.zcu;
const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
const target = if (Type.fromInterned(lazy_sym.key).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
&zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result
else
zcu.getTarget();
@@ -223,13 +223,118 @@ pub fn generateLazyFunction(
}
}
const LazySymbolStructure = struct {
parent: ?link.File.LazySymbol = null,
modify: ?Modification = null,
pub const Modification = struct {
lazy_sym: link.File.LazySymbol,
operation: Operation,
pub const Operation = enum {
ptr_inc,
pub fn apply(operation: Operation, slice: []u8, endian: std.builtin.Endian) void {
switch (operation) {
.ptr_inc => switch (slice.len) {
else => unreachable,
2 => std.mem.writeInt(u16, slice[0..2], std.mem.readInt(u16, slice[0..2], endian) + 1, endian),
4 => std.mem.writeInt(u32, slice[0..4], std.mem.readInt(u32, slice[0..4], endian) + 1, endian),
8 => std.mem.writeInt(u64, slice[0..8], std.mem.readInt(u64, slice[0..8], endian) + 1, endian),
},
}
}
};
};
};
pub const LazySymbolAttributes = struct {
header: bool = false,
required_alignment: Alignment,
size: ?u64 = null,
};
pub fn getLazySymbolInfo(
comptime kind: enum { structure, attributes },
lazy_sym: link.File.LazySymbol,
zcu: *Zcu,
) switch (kind) {
.structure => LazySymbolStructure,
.attributes => LazySymbolAttributes,
} {
const ip = &zcu.intern_pool;
return switch (lazy_sym.kind) {
.code => switch (kind) {
.structure => .{},
.attributes => {
const comp = zcu.comp;
const target = &comp.root_mod.resolved_target.result;
return .{ .required_alignment = switch (comp.root_mod.optimize_mode) {
.Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
.ReleaseSmall => target_util.minFunctionAlignment(target),
} };
},
},
.const_data => switch (ip.indexToKey(lazy_sym.key)) {
else => unreachable,
.enum_type => switch (kind) {
.structure => .{},
.attributes => .{ .required_alignment = .@"1" },
},
.restricted_ptr_type => |restricted_ptr_type| switch (kind) {
.structure => .{},
.attributes => {
const restricted_ptr_ty: Type = .fromInterned(lazy_sym.key);
const unrestricted_ptr_ty: Type =
.fromInterned(restricted_ptr_type.unrestricted_ptr_type);
return .{ .required_alignment = restricted_ptr_ty.abiAlignment(zcu)
.maxStrict(unrestricted_ptr_ty.abiAlignment(zcu)) };
},
},
},
.deferred_const_data => switch (lazy_sym.key) {
else => unreachable,
.anyerror_type => switch (kind) {
.structure => .{},
.attributes => .{ .required_alignment = .@"4" },
},
_ => switch (ip.indexToKey(lazy_sym.key)) {
else => unreachable,
.ptr => |ptr| switch (ip.indexToKey(ptr.ty)) {
else => unreachable,
.restricted_ptr_type => |restricted_ptr_type| switch (kind) {
.structure => .{ .parent = .{ .kind = .const_data, .key = ptr.ty }, .modify = .{
.lazy_sym = .{ .kind = .deferred_const_data, .key = ptr.ty },
.operation = .ptr_inc,
} },
.attributes => {
const unrestricted_ptr_ty: Type =
.fromInterned(restricted_ptr_type.unrestricted_ptr_type);
return .{
.required_alignment = unrestricted_ptr_ty.abiAlignment(zcu),
.size = unrestricted_ptr_ty.abiSize(zcu),
};
},
},
},
.restricted_ptr_type => switch (kind) {
.structure => .{ .parent = .{ .kind = .const_data, .key = lazy_sym.key } },
.attributes => {
const restricted_ptr_ty: Type = .fromInterned(lazy_sym.key);
return .{
.header = true,
.required_alignment = restricted_ptr_ty.abiAlignment(zcu),
.size = restricted_ptr_ty.abiSize(zcu),
};
},
},
},
},
};
}
pub fn generateLazySymbol(
bin_file: *link.File,
pt: Zcu.PerThread,
src_loc: Zcu.LazySrcLoc,
lazy_sym: link.File.LazySymbol,
// TODO don't use an "out" parameter like this; put it in the result instead
alignment: *Alignment,
w: *std.Io.Writer,
debug_output: link.File.DebugInfoOutput,
reloc_parent: link.File.RelocInfo.Parent,
@@ -243,51 +348,81 @@ pub fn generateLazySymbol(
const target = &comp.root_mod.resolved_target.result;
const endian = target.cpu.arch.endian();
log.debug("generateLazySymbol: kind = {s}, ty = {f}", .{
log.debug("generateLazySymbol: kind = {s}, key = {f}", .{
@tagName(lazy_sym.kind),
Type.fromInterned(lazy_sym.ty).fmt(pt),
Value.fromInterned(lazy_sym.key).fmtValue(pt),
});
if (lazy_sym.kind == .code) {
alignment.* = target_util.defaultFunctionAlignment(target);
return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output);
switch (lazy_sym.kind) {
.code => return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output),
.const_data => switch (ip.indexToKey(lazy_sym.key)) {
.enum_type => {
const enum_ty: Type = .fromInterned(lazy_sym.key);
const tag_names = enum_ty.enumFields(zcu);
for (0..tag_names.len) |tag_index| {
const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
try w.rebase(w.end, tag_name.len + 1);
w.writeAll(tag_name) catch unreachable;
w.writeByte(0) catch unreachable;
}
return;
},
.restricted_ptr_type => return,
else => {},
},
.deferred_const_data => switch (lazy_sym.key) {
.anyerror_type => {
const err_names = ip.global_error_set.getNamesFromMainThread();
const strings_start: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0)));
var string_index = strings_start;
try w.rebase(w.end, string_index);
w.writeInt(u32, @intCast(err_names.len), endian) catch unreachable;
if (err_names.len > 0) {
for (err_names) |err_name_nts| {
w.writeInt(u32, string_index, endian) catch unreachable;
string_index += @intCast(err_name_nts.toSlice(ip).len + 1);
}
w.writeInt(u32, string_index, endian) catch unreachable;
try w.rebase(w.end, string_index - strings_start);
for (err_names) |err_name_nts| {
w.writeAll(err_name_nts.toSlice(ip)) catch unreachable;
w.writeByte(0) catch unreachable;
}
}
return;
},
_ => switch (ip.indexToKey(lazy_sym.key)) {
.ptr => |ptr| switch (ip.indexToKey(ptr.ty)) {
.restricted_ptr_type => |restricted_ptr_type| return lowerPtr(
bin_file,
pt,
src_loc,
try ip.getCoerced(
comp.gpa,
comp.io,
pt.tid,
lazy_sym.key,
restricted_ptr_type.unrestricted_ptr_type,
),
w,
reloc_parent,
0,
),
else => {},
},
.restricted_ptr_type => return w.splatByteAll(0, @divExact(zcu.getTarget().ptrBitWidth(), 8)),
else => {},
},
else => {},
},
}
if (lazy_sym.ty == .anyerror_type) {
alignment.* = .@"4";
const err_names = ip.global_error_set.getNamesFromMainThread();
const strings_start: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0)));
var string_index = strings_start;
try w.rebase(w.end, string_index);
w.writeInt(u32, @intCast(err_names.len), endian) catch unreachable;
if (err_names.len == 0) return;
for (err_names) |err_name_nts| {
w.writeInt(u32, string_index, endian) catch unreachable;
string_index += @intCast(err_name_nts.toSlice(ip).len + 1);
}
w.writeInt(u32, string_index, endian) catch unreachable;
try w.rebase(w.end, string_index - strings_start);
for (err_names) |err_name_nts| {
w.writeAll(err_name_nts.toSlice(ip)) catch unreachable;
w.writeByte(0) catch unreachable;
}
} else if (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu) == .@"enum") {
alignment.* = .@"1";
const enum_ty = Type.fromInterned(lazy_sym.ty);
const tag_names = enum_ty.enumFields(zcu);
for (0..tag_names.len) |tag_index| {
const tag_name = tag_names.get(ip)[tag_index].toSlice(ip);
try w.rebase(w.end, tag_name.len + 1);
w.writeAll(tag_name) catch unreachable;
w.writeByte(0) catch unreachable;
}
} else if (Type.fromInterned(lazy_sym.ty).unrestrictedType(zcu)) |unrestricted_ptr_ty| {
alignment.* = unrestricted_ptr_ty.abiAlignment(zcu);
try w.splatByteAll(0, @divExact(zcu.getTarget().ptrBitWidth(), 8)); // to be filled in later
} else {
return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{
@tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt),
});
switch (ip.typeOf(lazy_sym.key)) {
.type_type => return zcu.codegenFailType(lazy_sym.key, "TODO implement generateLazySymbol for {t} {f}", .{
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
}),
else => std.debug.panic("TODO implement generateLazySymbol for {t} {f}", .{
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
}),
}
}
@@ -441,7 +576,10 @@ pub fn generateSymbol(
128 => try w.writeInt(u128, @bitCast(f128_val), endian),
},
},
.ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),
.ptr => switch (ty.restrictedRepr(zcu)) {
.indirect => try lowerLazySymbolRef(bin_file, pt, .{ .kind = .deferred_const_data, .key = val.toIntern() }, w, reloc_parent, 0),
.direct => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0),
},
.slice => |slice| {
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), w, reloc_parent);
try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), w, reloc_parent);
@@ -838,7 +976,7 @@ fn lowerNavRef(
else => {},
}
const vaddr = lf.getNavVAddr(pt, nav_index, .{
const vaddr = lf.getNavVAddr(nav_index, .{
.parent = reloc_parent,
.offset = w.end,
.addend = @intCast(offset),
@@ -906,7 +1044,7 @@ pub fn genNavRef(
.link_once => unreachable,
}
} else if (lf.cast(.elf2)) |elf| {
return .{ .sym_index = @intFromEnum(elf.navSymbol(zcu, nav_index) catch |err| switch (err) {
return .{ .sym_index = @intFromEnum(elf.navSymbol(nav_index) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => |e| return .{ .fail = try ErrorMsg.create(
zcu.gpa,
@@ -937,13 +1075,38 @@ pub fn genNavRef(
.link_once => unreachable,
}
} else if (lf.cast(.coff2)) |coff| {
return .{ .sym_index = @intFromEnum(try coff.navSymbol(zcu, nav_index)) };
return .{ .sym_index = @intFromEnum(try coff.navSymbol(nav_index)) };
} else {
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
return .{ .fail = msg };
}
}
fn lowerLazySymbolRef(
lf: *link.File,
pt: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
w: *std.Io.Writer,
reloc_parent: link.File.RelocInfo.Parent,
offset: u64,
) (GenerateSymbolError || std.Io.Writer.Error)!void {
const vaddr = lf.getLazySymbolVAddr(pt, lazy_sym, .{
.parent = reloc_parent,
.offset = w.end,
.addend = @intCast(offset),
}) catch @panic("TODO rework getNavVAddr");
const target = &lf.comp.root_mod.resolved_target.result;
const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
const endian = target.cpu.arch.endian();
switch (ptr_width_bytes) {
2 => try w.writeInt(u16, @intCast(vaddr), endian),
4 => try w.writeInt(u32, @intCast(vaddr), endian),
8 => try w.writeInt(u64, vaddr, endian),
else => unreachable,
}
}
/// deprecated legacy type
pub const GenResult = union(enum) {
mcv: MCValue,
@@ -1006,6 +1169,7 @@ pub fn genTypedValue(
} },
.fail => |em| .{ .fail = em },
},
.lea_lazy_sym => unreachable, // `Zcu.Feature.restricted_types` is not supported by this code path
};
}
@@ -1018,6 +1182,7 @@ const LowerResult = union(enum) {
lea_nav: InternPool.Nav.Index,
load_uav: InternPool.Key.Ptr.BaseAddr.Uav,
lea_uav: InternPool.Key.Ptr.BaseAddr.Uav,
lea_lazy_sym: link.File.LazySymbol,
};
pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allocator.Error!LowerResult {
@@ -1034,38 +1199,41 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
.bool => return .{ .immediate = @intFromBool(val.toBool()) },
.pointer => switch (ty.ptrSize(zcu)) {
.slice => {},
.one, .many, .c => {
const ptr = ip.indexToKey(val.toIntern()).ptr;
if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };
if (ptr.byte_offset == 0) switch (ptr.base_addr) {
.int => unreachable, // handled above
.one, .many, .c => switch (ty.restrictedRepr(zcu)) {
.indirect => return .{ .lea_lazy_sym = .{ .kind = .deferred_const_data, .key = val.toIntern() } },
.direct => {
const ptr = ip.indexToKey(val.toIntern()).ptr;
if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset };
if (ptr.byte_offset == 0) switch (ptr.base_addr) {
.int => unreachable, // handled above
.nav => |nav_index| {
const nav = ip.getNav(nav_index);
const nav_ty: Type = .fromInterned(nav.resolved.?.type);
if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
return .{ .lea_nav = nav_index };
.nav => |nav_index| {
const nav = ip.getNav(nav_index);
const nav_ty: Type = .fromInterned(nav.resolved.?.type);
if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
return .{ .lea_nav = nav_index };
} else {
// Create the 0xaa bit pattern...
const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
// ...but align the pointer
const alignment = zcu.navAlignment(nav_index);
return .{ .immediate = alignment.forward(undef_ptr_bits) };
}
},
.uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) {
return .{ .lea_uav = uav };
} else {
// Create the 0xaa bit pattern...
const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
// ...but align the pointer
const alignment = zcu.navAlignment(nav_index);
const alignment = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
return .{ .immediate = alignment.forward(undef_ptr_bits) };
}
},
},
.uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) {
return .{ .lea_uav = uav };
} else {
// Create the 0xaa bit pattern...
const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3);
// ...but align the pointer
const alignment = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu);
return .{ .immediate = alignment.forward(undef_ptr_bits) };
},
else => {},
};
else => {},
};
},
},
},
.int => {
+8 -8
View File
@@ -663,8 +663,8 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
maybe_noop: {
switch (isel.air.typeOf(ty_op.operand, ip).restrictedRepr(zcu)) {
.double_pointer => break :maybe_noop,
.single_pointer => {},
.indirect => break :maybe_noop,
.direct => {},
}
if (true) break :maybe_noop;
if (ty_op.operand.toIndex()) |src_air_inst_index| {
@@ -5766,7 +5766,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
const unrestricted_ty = ty_op.ty.toType();
const restricted_ty = isel.air.typeOf(ty_op.operand, ip);
switch (restricted_ty.restrictedRepr(zcu)) {
.double_pointer => {
.indirect => {
switch (air_tag) {
else => unreachable,
.unwrap_restricted => {},
@@ -5777,7 +5777,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
_ = try dst_vi.value.load(isel, unrestricted_ty, ptr_mat.ra, .{});
try ptr_mat.finish(isel);
},
.single_pointer => try dst_vi.value.move(isel, ty_op.operand),
.direct => try dst_vi.value.move(isel, ty_op.operand),
}
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
@@ -6888,12 +6888,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
},
} }));
try isel.lazy_relocs.append(gpa, .{
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
try isel.lazy_relocs.append(gpa, .{
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.adrp(ptr_ra.x(), 0));
@@ -7231,12 +7231,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
defer isel.freeReg(ptr_ra);
try isel.emit(.subs(.wzr, error_mat.ra.w(), .{ .register = ptr_ra.w() }));
try isel.lazy_relocs.append(gpa, .{
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.ldr(ptr_ra.w(), .{ .base = ptr_ra.x() }));
try isel.lazy_relocs.append(gpa, .{
.symbol = .{ .kind = .const_data, .ty = .anyerror_type },
.symbol = .{ .kind = .deferred_const_data, .key = .anyerror_type },
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.adrp(ptr_ra.x(), 0));
+147 -14
View File
@@ -61,6 +61,8 @@ pub const Mir = struct {
/// less than the natural alignment.
need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
ctype_deps: CType.Dependencies,
/// Key is a restricted type or value for which we need generated supporting decls.
need_restricted: std.array_hash_map.Auto(InternPool.Index, void),
/// Key is an enum type for which we need a generated `@tagName` function.
need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
/// Key is a function Nav for which we need a generated `zig_never_tail` wrapper.
@@ -74,6 +76,7 @@ pub const Mir = struct {
gpa.free(mir.code);
mir.need_uavs.deinit(gpa);
mir.ctype_deps.deinit(gpa);
mir.need_restricted.deinit(gpa);
mir.need_tag_name_funcs.deinit(gpa);
mir.need_never_tail_funcs.deinit(gpa);
mir.need_never_inline_funcs.deinit(gpa);
@@ -549,6 +552,25 @@ pub const Function = struct {
try f.writeCValue(w, member, .other);
}
fn writePanic(f: *Function, panic_id: Zcu.SimplePanicId, w: *std.Io.Writer) !void {
const zcu = f.dg.pt.zcu;
const ip = &zcu.intern_pool;
try renderNavName(w, switch (ip.indexToKey(zcu.builtin_decl_values.get(panic_id.toBuiltin()))) {
inline .@"extern", .func => |func| func.owner_nav,
.ptr => |ptr| switch (ptr.byte_offset) {
0 => switch (ptr.base_addr) {
.nav => |nav| nav,
else => unreachable,
},
else => unreachable,
},
else => unreachable,
}, ip);
try w.writeAll("();");
try f.newline();
try airUnreach(f);
}
fn fail(f: *Function, comptime format: []const u8, args: anytype) Error {
return f.dg.fail(format, args);
}
@@ -645,6 +667,7 @@ pub const DeclGen = struct {
/// `.none` for natural alignment. The specified alignment is never
/// less than the natural alignment.
uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
need_restricted: std.array_hash_map.Auto(InternPool.Index, void),
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error {
@branchHint(.cold);
@@ -1055,11 +1078,24 @@ pub const DeclGen = struct {
try dg.renderValue(w, .fromInterned(slice.len), initializer_type);
try w.writeByte('}');
},
.ptr => {
const derivation = try val.pointerDerivation(dg.arena, pt, null);
try w.writeByte('(');
try dg.renderPointer(w, derivation, location);
try w.writeByte(')');
.ptr => switch (ty.restrictedRepr(zcu)) {
.indirect => {
try dg.need_restricted.ensureUnusedCapacity(zcu.gpa, 2);
dg.need_restricted.putAssumeCapacity(ty.toIntern(), {});
dg.need_restricted.putAssumeCapacity(val.toIntern(), {});
const restricted_ty_name = ty.containerTypeName(ip).toSlice(ip);
try w.print("&zig_restricted_{f}__{d}[zig_restricted_index_{f}__{d}]", .{
fmtIdentUnsolo(restricted_ty_name), ty.toIntern(),
fmtIdentUnsolo(restricted_ty_name), val.toIntern(),
});
},
.direct => {
const derivation = try val.pointerDerivation(dg.arena, pt, null);
try w.writeByte('(');
try dg.renderPointer(w, derivation, location);
try w.writeByte(')');
},
},
.opt => |opt| switch (CType.classifyOptional(ty, zcu)) {
.npv_payload => unreachable, // opv optional
@@ -2061,6 +2097,55 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void {
}
}
pub fn genRestricted(
dg: *DeclGen,
need_restricted: *const std.array_hash_map.Auto(InternPool.Index, std.array_hash_map.Auto(InternPool.Index, void)),
w: *Writer,
) Error!void {
const pt = dg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
for (need_restricted.keys(), need_restricted.values()) |restricted_ty, *restricted_vals| {
const unrestricted_ptr_type = ip.indexToKey(restricted_ty).restricted_ptr_type.unrestricted_ptr_type;
const unrestricted_cty: CType = try .lower(.fromInterned(unrestricted_ptr_type), &dg.ctype_deps, dg.arena, zcu);
const restricted_ty_name = Type.fromInterned(restricted_ty).containerTypeName(ip).toSlice(ip);
try w.print(
\\#define zig_restricted_len_{f}__{d} {d}u
\\static {f}const zig_restricted_{f}__{d}[zig_restricted_len_{f}__{d}]{f} = {{
\\
, .{
fmtIdentUnsolo(restricted_ty_name),
restricted_ty,
restricted_vals.count(),
unrestricted_cty.fmtDeclaratorPrefix(zcu),
fmtIdentUnsolo(restricted_ty_name),
restricted_ty,
fmtIdentUnsolo(restricted_ty_name),
restricted_ty,
unrestricted_cty.fmtDeclaratorSuffix(zcu),
});
for (restricted_vals.keys(), 0..) |restricted_val, restricted_index| {
try w.print(
\\#define zig_restricted_index_{f}__{d} {d}u
\\ [zig_restricted_index_{f}__{d}] =
, .{
fmtIdentUnsolo(restricted_ty_name),
restricted_val,
restricted_index,
fmtIdentUnsolo(restricted_ty_name),
restricted_val,
});
try dg.renderValue(w, .fromInterned(
try ip.getCoerced(zcu.gpa, zcu.comp.io, pt.tid, restricted_val, unrestricted_ptr_type),
), .static_initializer);
try w.writeAll(",\n");
}
try w.writeAll("};\n");
}
}
pub fn genErrDecls(
zcu: *const Zcu,
w: *Writer,
@@ -2220,6 +2305,7 @@ pub fn generate(
.expected_block = null,
.ctype_deps = .empty,
.uavs = .empty,
.need_restricted = .empty,
},
.code = .init(gpa),
.indent_counter = 0,
@@ -2231,6 +2317,7 @@ pub fn generate(
function.code.deinit();
function.dg.ctype_deps.deinit(gpa);
function.dg.uavs.deinit(gpa);
function.dg.need_restricted.deinit(gpa);
function.deinit();
}
@@ -2252,6 +2339,7 @@ pub fn generate(
.code = &.{},
.ctype_deps = function.dg.ctype_deps.move(),
.need_uavs = function.dg.uavs.move(),
.need_restricted = function.dg.need_restricted.move(),
.need_tag_name_funcs = function.need_tag_name_funcs.move(),
.need_never_tail_funcs = function.need_never_tail_funcs.move(),
.need_never_inline_funcs = function.need_never_inline_funcs.move(),
@@ -5541,8 +5629,8 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
}
fn airUnwrapRestricted(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
const pt = f.dg.pt;
const zcu = pt.zcu;
const zcu = f.dg.pt.zcu;
const ip = &zcu.intern_pool;
const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const unrestricted_ty = ty_op.ty.toType();
@@ -5553,14 +5641,57 @@ fn airUnwrapRestricted(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue
const w = &f.code.writer;
const local = try f.allocLocal(inst, unrestricted_ty);
try f.writeCValue(w, local, .other);
try w.writeAll(" = ");
switch (restricted_ty.restrictedRepr(zcu)) {
.double_pointer => {
_ = safety; // TODO
.indirect => {
if (safety) {
const target = &f.dg.mod.resolved_target.result;
const ptr_bits = target.ptrBitWidth();
const int_from_ptr = try f.allocLocal(inst, .usize);
try f.writeCValue(w, int_from_ptr, .other);
try w.print(" = zig_subw_u{d}(({f})", .{
ptr_bits,
CType.fmtTypeName(.{ .int = .uintptr_t }, zcu),
});
try f.writeCValue(w, operand, .other);
try w.print(", ({f})zig_restricted_{f}__{d}, {f});", .{
CType.fmtTypeName(.{ .int = .uintptr_t }, zcu),
fmtIdentUnsolo(restricted_ty.containerTypeName(ip).toSlice(ip)),
restricted_ty.toIntern(),
fmtUnsignedIntLiteralSmall(target, .uint8_t, ptr_bits, false, 10, .lower),
});
try f.newline();
const rotate_amount = std.math.log2_int(u16, @divExact(ptr_bits, 8));
try w.print("if ((zig_shr_u{d}(", .{ptr_bits});
try f.writeCValue(w, int_from_ptr, .other);
try w.print(", {f}) | zig_shlw_u{d}(", .{
fmtUnsignedIntLiteralSmall(target, .uint8_t, rotate_amount, false, 10, .lower),
ptr_bits,
});
try f.writeCValue(w, int_from_ptr, .other);
try w.print(", {f}, {f})) >= zig_restricted_len_{f}__{d}) {{", .{
fmtUnsignedIntLiteralSmall(target, .uint8_t, ptr_bits - rotate_amount, false, 10, .lower),
fmtUnsignedIntLiteralSmall(target, .uint8_t, ptr_bits, false, 10, .lower),
fmtIdentUnsolo(restricted_ty.containerTypeName(ip).toSlice(ip)),
restricted_ty.toIntern(),
});
f.indent();
try f.newline();
try f.writePanic(.corrupt_restricted_pointer, w);
try f.outdent();
try w.writeByte('}');
try f.newline();
}
try f.writeCValue(w, local, .other);
try w.writeAll(" = ");
try f.writeCValueDeref(w, operand);
},
.single_pointer => try f.writeCValue(w, operand, .other),
.direct => {
try f.writeCValue(w, local, .other);
try w.writeAll(" = ");
try f.writeCValue(w, operand, .other);
},
}
try w.writeByte(';');
try f.newline();
@@ -5849,7 +5980,8 @@ fn airBinBuiltinCall(
try f.writeCValue(w, rhs, .other);
if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
try f.dg.renderBuiltinInfo(w, scalar_ty, info);
try w.writeAll(");\n");
try w.writeAll(");");
try f.newline();
try v.end(f, inst, w);
return local;
@@ -6459,7 +6591,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue {
},
.value => |val| try f.dg.renderValue(w, .fromInterned(val), .other),
}
try w.writeAll(";\n");
try w.writeByte(';');
try f.newline();
}
return local;
+2 -2
View File
@@ -285,7 +285,7 @@ pub const CType = union(enum) {
.pointer => {
const ptr = cur_ty.ptrInfo(zcu);
if (cur_ty.unrestrictedType(zcu)) |unrestricted_ty| switch (cur_ty.restrictedRepr(zcu)) {
.double_pointer => {
.indirect => {
const unrestricted_cty = try lowerInner(unrestricted_ty, true, deps, arena, zcu);
const unrestricted_cty_buf = try arena.create(CType);
unrestricted_cty_buf.* = unrestricted_cty;
@@ -296,7 +296,7 @@ pub const CType = union(enum) {
.nonstring = false,
} };
},
.single_pointer => {},
.direct => {},
};
switch (ptr.flags.size) {
.slice => {
+5 -3
View File
@@ -3261,11 +3261,13 @@ fn airUnwrapRestricted(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Alloc
const restricted_ty = self.typeOf(ty_op.operand);
const operand = try self.resolveInst(ty_op.operand);
switch (restricted_ty.restrictedRepr(zcu)) {
.double_pointer => {
_ = safety; // TODO
.indirect => {
if (safety) {
// TODO
}
return self.wip.load(.normal, .ptr, operand, unrestricted_ty.abiAlignment(zcu).toLlvm(), "restricted.unwrap");
},
.single_pointer => return operand,
.direct => return operand,
}
}
+25 -19
View File
@@ -1282,9 +1282,9 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
const pt = func.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
switch (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu)) {
.@"enum" => {
const enum_ty = Type.fromInterned(lazy_sym.ty);
switch (ip.indexToKey(lazy_sym.key)) {
.enum_type => {
const enum_ty = Type.fromInterned(lazy_sym.key);
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
const param_regs = abi.Registers.Integer.function_arg_regs;
@@ -1301,9 +1301,9 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
const zo = elf_file.zigObjectPtr().?;
const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, .{
.kind = .const_data,
.ty = enum_ty.toIntern(),
.key = lazy_sym.key,
}) catch |err|
return func.fail("{s} creating lazy symbol", .{@errorName(err)});
return func.fail("{t} creating lazy symbol", .{err});
try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym_index } });
@@ -1367,8 +1367,8 @@ 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) },
"TODO implement {t} for {f}",
.{ lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt) },
),
}
}
@@ -8359,22 +8359,28 @@ fn wantSafety(func: *Func) bool {
fn fail(func: *const Func, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
@branchHint(.cold);
const zcu = func.pt.zcu;
switch (func.owner) {
.nav_index => |i| return zcu.codegenFail(i, format, args),
.lazy_sym => |s| return zcu.codegenFailType(s.ty, format, args),
}
return error.CodegenFail;
const pt = func.pt;
const zcu = pt.zcu;
return switch (func.owner) {
.nav_index => |i| zcu.codegenFail(i, format, args),
.lazy_sym => |s| switch (zcu.intern_pool.typeOf(s.key)) {
.type_type => zcu.codegenFailType(s.key, format, args),
else => std.debug.panic("{f}: " ++ format, .{Value.fromInterned(s.key).fmtValue(pt)} ++ args),
},
};
}
fn failMsg(func: *const Func, msg: *ErrorMsg) error{ OutOfMemory, CodegenFail } {
@branchHint(.cold);
const zcu = func.pt.zcu;
switch (func.owner) {
.nav_index => |i| return zcu.codegenFailMsg(i, msg),
.lazy_sym => |s| return zcu.codegenFailTypeMsg(s.ty, msg),
}
return error.CodegenFail;
const pt = func.pt;
const zcu = pt.zcu;
return switch (func.owner) {
.nav_index => |i| zcu.codegenFailMsg(i, msg),
.lazy_sym => |s| switch (zcu.intern_pool.typeOf(s.key)) {
.type_type => zcu.codegenFailTypeMsg(s.key, msg),
else => std.debug.panic("{f}: {s}", .{ Value.fromInterned(s.key).fmtValue(pt), msg.msg }),
},
};
}
fn parseRegName(name: []const u8) ?Register {
+2 -2
View File
@@ -6730,11 +6730,11 @@ fn airUnwrapRestricted(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerEr
const unrestricted_ty = ty_op.ty.toType();
const restricted_ty = cg.typeOf(ty_op.operand);
const result = result: switch (restricted_ty.restrictedRepr(zcu)) {
.double_pointer => {
.indirect => {
_ = safety; // TODO
break :result try cg.load(operand, unrestricted_ty, 0);
},
.single_pointer => cg.reuseOperand(ty_op.operand, operand),
.direct => cg.reuseOperand(ty_op.operand, operand),
};
return cg.finishAir(inst, result, &.{ty_op.operand});
}
+211 -244
View File
@@ -527,45 +527,38 @@ pub const MCValue = union(enum) {
pub fn format(mcv: MCValue, w: *Writer) Writer.Error!void {
switch (mcv) {
.none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}),
.none, .unreach, .dead, .undef => try w.print("({t})", .{mcv}),
.immediate => |pl| try w.print("0x{x}", .{pl}),
.memory => |pl| try w.print("[ds:0x{x}]", .{pl}),
inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}),
.register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }),
.register_triple => |pl| try w.print("{s}:{s}:{s}", .{
@tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
}),
.register_quadruple => |pl| try w.print("{s}:{s}:{s}:{s}", .{
@tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]),
}),
.register_offset => |pl| try w.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }),
.register_overflow => |pl| try w.print("{s}:{s}", .{
@tagName(pl.eflags),
@tagName(pl.reg),
}),
.register_mask => |pl| try w.print("mask({s},{f}):{c}{s}", .{
@tagName(pl.info.kind),
inline .eflags, .register => |pl| try w.print("{t}", .{pl}),
.register_pair => |pl| try w.print("{t}:{t}", .{ pl[1], pl[0] }),
.register_triple => |pl| try w.print("{t}:{t}:{t}", .{ pl[2], pl[1], pl[0] }),
.register_quadruple => |pl| try w.print("{t}:{t}:{t}:{t}", .{ pl[3], pl[2], pl[1], pl[0] }),
.register_offset => |pl| try w.print("{t} + 0x{x}", .{ pl.reg, pl.off }),
.register_overflow => |pl| try w.print("{t}:{t}", .{ pl.eflags, pl.reg }),
.register_mask => |pl| try w.print("mask({t},{f}):{c}{t}", .{
pl.info.kind,
pl.info.scalar,
@as(u8, if (pl.info.inverted) '!' else ' '),
@tagName(pl.reg),
pl.reg,
}),
.indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
.indirect => |pl| try w.print("[{t} + 0x{x}]", .{ pl.reg, pl.off }),
.indirect_load_frame => |pl| try w.print("[[{f} + 0x{x}]]", .{ pl.index, pl.off }),
.load_frame => |pl| try w.print("[{f} + 0x{x}]", .{ pl.index, pl.off }),
.lea_frame => |pl| try w.print("{f} + 0x{x}", .{ pl.index, pl.off }),
.load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}),
.lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}),
.load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}),
.lea_uav => |pl| try w.print("uav:{d}", .{@intFromEnum(pl.val)}),
.load_lazy_sym => |pl| try w.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
.lea_lazy_sym => |pl| try w.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }),
.load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}),
.lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}),
.load_nav => |pl| try w.print("[nav:{d}]", .{pl}),
.lea_nav => |pl| try w.print("nav:{d}", .{pl}),
.load_uav => |pl| try w.print("[uav:{d}]", .{pl.val}),
.lea_uav => |pl| try w.print("uav:{d}", .{pl.val}),
.load_lazy_sym => |pl| try w.print("[lazy:{t}:{d}]", .{ pl.kind, pl.key }),
.lea_lazy_sym => |pl| try w.print("lazy:{t}:{d}", .{ pl.kind, pl.key }),
.load_extern_func => |pl| try w.print("[extern:{d}]", .{pl}),
.lea_extern_func => |pl| try w.print("extern:{d}", .{pl}),
.elementwise_args => |pl| try w.print("elementwise:{d}:[{f} + 0x{x}]", .{
pl.regs, pl.frame_index, pl.frame_off,
}),
.reserved_frame => |pl| try w.print("(dead:{f})", .{pl}),
.air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}),
.air_ref => |pl| try w.print("(air:0x{x})", .{pl}),
}
}
};
@@ -1138,7 +1131,7 @@ fn formatWipMir(data: FormatWipMirData, w: *Writer) Writer.Error!void {
if (first) {
const ip = &data.self.pt.zcu.intern_pool;
const mir_inst = lower.mir.instructions.get(data.inst);
try w.print(" | .{s}", .{@tagName(mir_inst.ops)});
try w.print(" | .{t}", .{mir_inst.ops});
switch (mir_inst.ops) {
else => unreachable,
.pseudo_dbg_prologue_end_none,
@@ -2059,7 +2052,7 @@ fn gen(
.{},
);
},
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
else => |cc| return self.fail("{t} does not support var args", .{cc}),
};
if (!self.mod.strip) try self.asmPseudo(.pseudo_dbg_prologue_end_none);
@@ -4452,8 +4445,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -4464,8 +4457,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
else => unreachable,
.add, .add_optimized => {},
.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),
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
res[0].tracking(cg),
}),
@@ -13029,8 +13022,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -15203,8 +15196,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -15215,8 +15208,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
else => unreachable,
.sub, .sub_optimized => {},
.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),
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
res[0].tracking(cg),
}),
@@ -22050,8 +22043,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -24987,8 +24980,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -26785,8 +26778,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -26794,8 +26787,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
else => |e| return e,
};
res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
res[0].tracking(cg),
}),
@@ -32010,8 +32003,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp3q, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -33248,8 +33241,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
assert(air_tag == .div_exact);
res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -34705,8 +34698,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} }) else err: {
res[0] = ops[0].divTruncInts(&ops[1], cg) catch |err| break :err err;
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -36266,8 +36259,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),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -37958,8 +37951,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} })) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -39740,8 +39733,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -43253,8 +43246,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -43367,8 +43360,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -43496,8 +43489,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .lea, .dst0p, .leai(.src0, .dst0), ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -47805,8 +47798,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -52108,8 +52101,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -52957,8 +52950,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_pl.ty.toType().fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -53862,8 +53855,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .mov, .memad(.dst0q, .add_src0_size, -8), .tmp0q, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_pl.ty.toType().fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -57459,8 +57452,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .@"or", .tmp2q, .tmp1q, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_pl.ty.toType().fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -60804,8 +60797,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .@"or", .tmp4q, .tmp5q, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_pl.ty.toType().fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -61199,8 +61192,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),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -61762,8 +61755,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
ops[0].tracking(cg),
@@ -62124,8 +62117,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ns, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
ops[0].tracking(cg),
@@ -62136,8 +62129,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
switch (air_tag) {
else => unreachable,
.shl => res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} wrap {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
res[0].tracking(cg),
}),
@@ -62303,8 +62296,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .@"or", .dst0d, .tmp0d, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.rhs).fmt(pt),
ops[1].tracking(cg),
}),
@@ -65560,8 +65553,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .@"0:", ._, .mov, .memad(.dst0q, .add_size, -8), .tmp1q, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
lhs_ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -67345,8 +67338,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
ops[0].tracking(cg),
}),
@@ -70497,8 +70490,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
}),
@@ -70894,8 +70887,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .@"0:", ._, .lea, .dst0d, .leasia(.dst0, .@"8", .tmp0, .add_8_src0_size), ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
}),
@@ -71782,8 +71775,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
}),
@@ -72431,8 +72424,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
ops[0].tracking(cg),
}),
@@ -75533,8 +75526,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
ops[0].tracking(cg),
}),
@@ -76595,8 +76588,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -77445,8 +77438,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}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -78996,8 +78989,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
}),
@@ -80332,8 +80325,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}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -80872,8 +80865,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -81352,8 +81345,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} else err: {
res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -81927,8 +81920,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.@"struct", .@"union" => {
assert(ty.containerLayout(zcu) == .@"packed");
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),
error.SelectFailed => return cg.fail("failed to select {t} wrap {f} {f}", .{
air_tag,
ty.fmt(pt),
op.tracking(cg),
}),
@@ -81939,8 +81932,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err;
},
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty.fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -89017,9 +89010,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} },
}),
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {s} {f} {f} {f}", .{
@tagName(air_tag),
@tagName(vector_cmp.compareOperator()),
error.SelectFailed => return cg.fail("failed to select {t} {t} {f} {f} {f}", .{
air_tag,
vector_cmp.compareOperator(),
cg.typeOf(vector_cmp.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -91595,8 +91588,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
@@ -93270,8 +93263,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
@@ -98028,8 +98021,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
dst_ty.fmt(pt),
src_ty.fmt(pt),
ops[0].tracking(cg),
@@ -103694,8 +103687,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
@@ -103835,8 +103828,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
const restricted_ty = cg.typeOf(ty_op.operand);
var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
const res = res: switch (restricted_ty.restrictedRepr(zcu)) {
.double_pointer => {
switch (air_tag) {
.indirect => {
if (zcu.comp.config.use_new_linker) switch (air_tag) {
else => unreachable,
.unwrap_restricted => {},
.unwrap_restricted_safe => cg.select(&.{}, &.{}, &ops, &.{ .{
@@ -103848,7 +103841,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"32" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .const_data, .ref = .src0 } } },
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data, .ref = .src0 } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .panic_func = .corrupt_restricted_pointer } },
.unused,
@@ -103878,7 +103871,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"16" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .const_data, .ref = .src0 } } },
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data, .ref = .src0 } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .panic_func = .corrupt_restricted_pointer } },
.unused,
@@ -103907,7 +103900,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.call_frame = .{ .alignment = .@"8" },
.extra_temps = .{
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .const_data, .ref = .src0 } } },
.{ .type = .usize, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data, .ref = .src0 } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.{ .type = .usize, .kind = .{ .panic_func = .corrupt_restricted_pointer } },
.unused,
@@ -103929,18 +103922,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .call, .tmp3d, ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
unrestricted_ty.fmt(pt),
restricted_ty.fmt(pt),
ops[0].tracking(cg),
}),
else => |e| return e,
},
}
};
break :res try ops[0].load(unrestricted_ty, .{}, cg);
},
.single_pointer => ops[0],
.direct => ops[0],
};
try res.finish(inst, &.{ty_op.operand}, &ops, cg);
},
@@ -115178,8 +115171,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
@@ -127197,8 +127190,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
cg.typeOf(ty_op.operand).fmt(pt),
ops[0].tracking(cg),
@@ -161387,9 +161380,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} },
} },
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
@tagName(air_tag),
@tagName(reduce.operation),
error.SelectFailed => return cg.fail("failed to select {t}.{t} {f} {f}", .{
air_tag,
reduce.operation,
cg.typeOf(reduce.operand).fmt(pt),
ops[0].tracking(cg),
}),
@@ -161398,9 +161391,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
switch (reduce.operation) {
.And, .Or, .Xor, .Min, .Max => {},
.Add, .Mul => if (cg.intInfo(res_ty)) |_| res[0].wrapInt(cg) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s}.{s} wrap {f} {f}", .{
@tagName(air_tag),
@tagName(reduce.operation),
error.SelectFailed => return cg.fail("failed to select {t}.{t} wrap {f} {f}", .{
air_tag,
reduce.operation,
res_ty.fmt(pt),
res[0].tracking(cg),
}),
@@ -169101,9 +169094,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
} },
} },
}) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s}.{s} {f} {f}", .{
@tagName(air_tag),
@tagName(reduce.operation),
error.SelectFailed => return cg.fail("failed to select {t}.{t} {f} {f}", .{
air_tag,
reduce.operation,
cg.typeOf(reduce.operand).fmt(pt),
ops[0].tracking(cg),
}),
@@ -170898,8 +170891,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
ops[0].tracking(cg),
}),
@@ -170914,8 +170907,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
const bin_op = air_datas[@intFromEnum(inst)].bin_op;
var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }) ++ .{undefined};
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),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
ops[0].tracking(cg),
@@ -170955,8 +170948,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),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
cg.typeOf(bin_op.rhs).fmt(pt),
ops[0].tracking(cg),
@@ -171136,8 +171129,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .@"test", .tmp0p, .tmp0p, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -171302,8 +171295,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .call, .tmp0d, ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -171323,7 +171316,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
.unused,
.unused,
@@ -171352,7 +171345,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
.unused,
.unused,
@@ -171381,7 +171374,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
.{ .type = .u32, .kind = .{ .mut_rc = .{ .ref = .src0, .rc = .general_purpose } } },
.unused,
.unused,
@@ -171404,8 +171397,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .lea, .dst1d, .leai(.dst1, .tmp1), ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
cg.typeOf(un_op).fmt(pt),
ops[0].tracking(cg),
}),
@@ -171422,6 +171415,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
},
.error_set_has_value => |air_tag| {
const ty_op = air_datas[@intFromEnum(inst)].ty_op;
assert(ty_op.ty != .anyerror_type); // das a constant
var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}) ++ .{try cg.tempInit(ty_op.ty.toType(), .none)};
var res: [1]Temp = undefined;
cg.select(&res, &.{.bool}, &ops, comptime &.{ .{
@@ -171502,8 +171496,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .@"test", .src0d, .src0d, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f}", .{
air_tag,
ty_op.ty.toType().fmt(pt),
ops[0].tracking(cg),
}),
@@ -171575,8 +171569,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
}
}
},
else => return cg.fail("failed to select {s} {f}", .{
@tagName(air_tag),
else => return cg.fail("failed to select {t} {f}", .{
air_tag,
agg_ty.fmt(pt),
}),
}
@@ -173021,8 +173015,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._ae, .j, .@"0b", ._, ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f} {f} {f} {f}", .{
air_tag,
cg.typeOf(bin_op.lhs).fmt(pt),
ops[0].tracking(cg),
ops[1].tracking(cg),
@@ -173055,7 +173049,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -173079,7 +173073,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -173103,7 +173097,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ .src = .{ .to_gpr, .none, .none } },
},
.extra_temps = .{
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .const_data } } },
.{ .type = .anyerror, .kind = .{ .lazy_sym = .{ .kind = .deferred_const_data } } },
.{ .type = .usize, .kind = .{ .rc = .general_purpose } },
.unused,
.unused,
@@ -173122,8 +173116,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.{ ._, ._, .cmp, .src0d, .lea(.tmp1d), ._, ._ },
} },
} }) catch |err| switch (err) {
error.SelectFailed => return cg.fail("failed to select {s} {f}", .{
@tagName(air_tag),
error.SelectFailed => return cg.fail("failed to select {t} {f}", .{
air_tag,
ops[0].tracking(cg),
}),
else => |e| return e,
@@ -173856,9 +173850,9 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
const pt = cg.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
switch (ip.indexToKey(lazy_sym.ty)) {
switch (ip.indexToKey(lazy_sym.key)) {
.enum_type => {
const enum_ty: Type = .fromInterned(lazy_sym.ty);
const enum_ty: Type = .fromInterned(lazy_sym.key);
wip_mir_log.debug("{f}.@tagName:", .{enum_ty.fmt(pt)});
const ret_regs = abi.getCAbiIntReturnRegs(.auto)[0..2].*;
@@ -173875,12 +173869,12 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
const data_lock = cg.register_manager.lockRegAssumeUnused(data_reg);
defer cg.register_manager.unlockReg(data_lock);
try cg.asmRegisterMemory(.{ ._, .lea }, data_reg.to64(), .{
.base = .{ .lazy_sym = .{ .kind = .const_data, .ty = lazy_sym.ty } },
.base = .{ .lazy_sym = .{ .kind = .const_data, .key = lazy_sym.key } },
});
var data_off: i32 = 0;
const reset_index = cg.next_temp_index;
const tag_names = ip.loadEnumType(lazy_sym.ty).field_names;
const tag_names = ip.loadEnumType(lazy_sym.key).field_names;
for (0..tag_names.len) |tag_index| {
var enum_temp = try cg.tempInit(enum_ty, if (enum_ty.abiSize(zcu) <= @as(u4, switch (cg.target.cpu.arch) {
else => unreachable,
@@ -173919,7 +173913,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
try cg.asmOpOnly(.{ ._, .ret });
},
.error_set_type => |error_set_type| {
const err_ty: Type = .fromInterned(lazy_sym.ty);
const err_ty: Type = .fromInterned(lazy_sym.key);
wip_mir_log.debug("{f}.@errorCast:", .{err_ty.fmt(pt)});
const ret_reg = abi.getCAbiIntReturnRegs(.auto)[0];
@@ -173964,8 +173958,8 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void {
try cg.asmOpOnly(.{ ._, .ret });
},
else => return cg.fail(
"TODO implement {s} for {f}",
.{ @tagName(lazy_sym.kind), Type.fromInterned(lazy_sym.ty).fmt(pt) },
"TODO implement {t} for {f}",
.{ lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt) },
),
}
try cg.resetTemps(@enumFromInt(0));
@@ -175315,10 +175309,7 @@ fn genShiftBinOpMir(
.mod = .{ .rm = .{
.size = .fromSize(abi_size),
.disp = std.math.cast(i32, @as(i64, @bitCast(addr))) orelse
return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
@tagName(lhs_mcv),
@tagName(shift_mcv),
}),
return self.fail("TODO genShiftBinOpMir between {t} and {t}", .{ lhs_mcv, shift_mcv }),
} },
},
.indirect => |reg_off| .{
@@ -175349,10 +175340,7 @@ fn genShiftBinOpMir(
},
else => {},
}
return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
@tagName(lhs_mcv),
@tagName(shift_mcv),
});
return self.fail("TODO genShiftBinOpMir between {t} and {t}", .{ lhs_mcv, shift_mcv });
}
fn genBinOpMir(
@@ -175401,9 +175389,7 @@ fn genBinOpMir(
.add => .{ ._, .adc },
.sub, .cmp => .{ ._, .sbb },
.@"or", .@"and", .xor => mir_tag,
else => return self.fail("TODO genBinOpMir implement large ABI for {s}", .{
@tagName(mir_tag[1]),
}),
else => return self.fail("TODO genBinOpMir implement large ABI for {t}", .{mir_tag[1]}),
},
else => unreachable,
};
@@ -175652,9 +175638,7 @@ fn genBinOpMir(
.add => .{ ._, .adc },
.sub, .cmp => .{ ._, .sbb },
.@"or", .@"and", .xor => mir_tag,
else => return self.fail("TODO genBinOpMir implement large ABI for {s}", .{
@tagName(mir_tag[1]),
}),
else => return self.fail("TODO genBinOpMir implement large ABI for {t}", .{mir_tag[1]}),
},
};
const dst_limb_mem: Memory = switch (dst_mcv) {
@@ -176527,7 +176511,7 @@ fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index {
}
return self.fail("TODO implement condbr when condition is {f} with abi larger than 8 bytes", .{mcv});
},
else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),
else => return self.fail("TODO implement condbr when condition is {t}", .{mcv}),
}
}
@@ -177551,10 +177535,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
label_gop.value_ptr.target = @intCast(self.mir_instructions.len);
} else continue;
if (mnem_str[0] == '.') {
if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{
@tagName(prefix),
mnem_str,
});
if (prefix != .none) return self.fail("prefixed directive: '{t} {s}'", .{ prefix, mnem_str });
prefix = .directive;
}
@@ -177871,8 +177852,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
inline for (@typeInfo(encoder.Instruction.Mnemonic).@"enum".fields) |mnem|
max_mnem_len = @max(mnem.name.len, max_mnem_len);
var intel_mnem_buf: [max_mnem_len + 1]u8 = undefined;
const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{s}{c}", .{
@tagName(mnem_tag),
const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{t}{c}", .{
mnem_tag,
@as(u8, switch (mnem_size.size) {
.byte => 'b',
.word => 'w',
@@ -177908,9 +177889,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
) orelse continue };
} else {
assert(prefix != .none); // no combination of fixes produced a known mnemonic
return self.fail("invalid prefix for mnemonic: '{s} {s}'", .{
@tagName(prefix), mnem_name,
});
return self.fail("invalid prefix for mnemonic: '{t} {s}'", .{ prefix, mnem_name });
};
(if (prefix == .directive) switch (mnem_tag) {
@@ -177969,12 +177948,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
.@".cfi_escape" => error.InvalidInstruction,
else => unreachable,
} else self.asmOps(mnem_fixed_tag, ops)) catch |err| switch (err) {
error.InvalidInstruction => return self.fail("invalid instruction: '{s} {s} {s} {s} {s}'", .{
mnem_str,
@tagName(ops[0]),
@tagName(ops[1]),
@tagName(ops[2]),
@tagName(ops[3]),
error.InvalidInstruction => return self.fail("invalid instruction: '{s} {t} {t} {t} {t}'", .{
mnem_str, ops[0], ops[1], ops[2], ops[3],
}),
else => |e| return e,
};
@@ -178537,9 +178512,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C
break :src_info .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
},
.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),
}),
else => return self.fail("TODO implement genCopy for {t} of {f}", .{ src_mcv, ty.fmt(pt) }),
};
defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
@@ -179347,9 +179320,7 @@ fn genSetMem(
opts,
);
},
else => return self.fail("TODO implement genSetMem for {s} of {f}", .{
@tagName(src_mcv), ty.fmt(pt),
}),
else => return self.fail("TODO implement genSetMem for {t} of {f}", .{ src_mcv, ty.fmt(pt) }),
},
.register_offset => |reg_off| {
const src_reg = self.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) {
@@ -179705,7 +179676,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
};
switch (ptr_mem.mod) {
.rm => {},
.off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
.off => return self.fail("TODO airCmpxchg with {t}", .{ptr_mcv}),
}
const ptr_lock = switch (ptr_mem.base) {
.none, .frame, .nav, .uav => null,
@@ -179788,7 +179759,7 @@ fn atomicOp(
};
switch (ptr_mem.mod) {
.rm => {},
.off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}),
.off => return self.fail("TODO airCmpxchg with {t}", .{ptr_mcv}),
}
const mem_lock = switch (ptr_mem.base) {
.none, .frame, .nav, .uav => null,
@@ -179883,8 +179854,8 @@ fn atomicOp(
else => null,
},
else => unreachable,
}) orelse return self.fail("TODO implement atomicOp of {s} for {f}", .{
@tagName(op), val_ty.fmt(pt),
}) orelse return self.fail("TODO implement atomicOp of {t} for {f}", .{
op, val_ty.fmt(pt),
});
try self.genSetReg(sse_reg, val_ty, .{ .register = .rax }, .{});
switch (mir_tag[0]) {
@@ -180952,7 +180923,7 @@ fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void {
);
break :result .{ .load_frame = .{ .index = dst_fi } };
},
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
else => |cc| return self.fail("{t} does not support var args", .{cc}),
};
return self.finishAir(inst, result, .{ .none, .none, .none });
}
@@ -181139,7 +181110,7 @@ fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void {
try self.convertFloatVarArg(inst, ty, promote_ty, promote_mcv);
break :result promote_mcv;
},
else => |cc| return self.fail("{s} does not support var args", .{@tagName(cc)}),
else => |cc| return self.fail("{t} does not support var args", .{cc}),
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
@@ -181236,6 +181207,7 @@ fn lowerValue(cg: *CodeGen, val: Value) Allocator.Error!MCValue {
.lea_nav => |nav| .{ .lea_nav = nav },
.lea_uav => |uav| .{ .lea_uav = uav },
.load_uav => |uav| .{ .load_uav = uav },
.lea_lazy_sym => |lazy_sym| .{ .lea_lazy_sym = lazy_sym },
};
}
@@ -181630,10 +181602,14 @@ fn resolveCallingConventionValues(
fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
@branchHint(.cold);
const zcu = cg.pt.zcu;
const pt = cg.pt;
const zcu = pt.zcu;
return switch (cg.owner) {
.nav_index => |i| zcu.codegenFail(i, format, args),
.lazy_sym => |s| zcu.codegenFailType(s.ty, format, args),
.lazy_sym => |s| switch (zcu.intern_pool.typeOf(s.key)) {
.type_type => zcu.codegenFailType(s.key, format, args),
else => std.debug.panic("{f}: " ++ format, .{Value.fromInterned(s.key).fmtValue(pt)} ++ args),
},
};
}
@@ -187899,14 +187875,14 @@ const Select = struct {
error.InvalidInstruction => {
const fixes = @tagName(mir_tag[0]);
const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{
return s.cg.fail("invalid instruction: '{s}{t}{s} {t} {t} {t} {t}'", .{
fixes[0..fixes_blank],
@tagName(mir_tag[1]),
mir_tag[1],
fixes[fixes_blank + 1 ..],
@tagName(mir_ops[0]),
@tagName(mir_ops[1]),
@tagName(mir_ops[2]),
@tagName(mir_ops[3]),
mir_ops[0],
mir_ops[1],
mir_ops[2],
mir_ops[3],
});
},
else => |e| return e,
@@ -187976,16 +187952,7 @@ const Select = struct {
},
.f_p => switch (mir_tag[1]) {
.add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1,
else => {
const fixes = @tagName(mir_tag[0]);
const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?;
std.debug.panic("{s}: {s}{s}{s}\n", .{
@src().fn_name,
fixes[0..fixes_blank],
@tagName(mir_tag[1]),
fixes[fixes_blank + 1 ..],
});
},
else => unreachable,
},
.f_pp => switch (mir_tag[1]) {
.com, .ucom => s.top +%= 2,
@@ -189095,7 +189062,7 @@ const Select = struct {
const ty = if (lazy_symbol_spec.ref == .none) spec.type else lazy_symbol_spec.ref.typeOf(s);
return .{ try cg.tempInit(.usize, .{ .lea_lazy_sym = .{
.kind = lazy_symbol_spec.kind,
.ty = switch (ip.indexToKey(ty.toIntern())) {
.key = switch (ip.indexToKey(ty.toIntern())) {
.inferred_error_set_type => |func_index| switch (ip.funcIesResolvedUnordered(func_index)) {
.none => unreachable,
else => |ty_index| ty_index,
+2 -2
View File
@@ -163,8 +163,8 @@ pub fn emitMir(emit: *Emit) Error!void {
else if (emit.bin_file.cast(.macho)) |macho_file|
macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
else if (emit.bin_file.cast(.coff2)) |elf|
@intFromEnum(try elf.lazySymbol(lazy_sym))
else if (emit.bin_file.cast(.coff2)) |coff|
@intFromEnum(try coff.lazySymbol(lazy_sym))
else
return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
.is_extern = false,
+28 -7
View File
@@ -1867,7 +1867,7 @@ pub const Memory = struct {
size: bits.Memory.Size,
index: Register,
scale: bits.Memory.Scale,
_: u13 = undefined,
unused: u13 = 0,
};
pub fn encode(mem: bits.Memory) Memory {
@@ -1895,7 +1895,7 @@ pub const Memory = struct {
.rip_inst => |inst_index| inst_index,
.nav => |nav| @intFromEnum(nav),
.uav => |uav| @intFromEnum(uav.val),
.lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.ty),
.lazy_sym => |lazy_sym| @intFromEnum(lazy_sym.key),
.extern_func => |extern_func| @intFromEnum(extern_func),
},
.off = switch (mem.mod) {
@@ -1933,7 +1933,10 @@ pub const Memory = struct {
.rip_inst => .{ .rip_inst = mem.base },
.nav => .{ .nav = @enumFromInt(mem.base) },
.uav => .{ .uav = .{ .val = @enumFromInt(mem.base), .orig_ty = @enumFromInt(mem.extra) } },
.lazy_sym => .{ .lazy_sym = .{ .kind = @enumFromInt(mem.extra), .ty = @enumFromInt(mem.base) } },
.lazy_sym => .{ .lazy_sym = .{
.kind = @enumFromInt(mem.extra),
.key = @enumFromInt(mem.base),
} },
.extern_func => .{ .extern_func = @enumFromInt(mem.base) },
},
.scale_index = switch (mem.info.index) {
@@ -2061,10 +2064,28 @@ pub fn emitLazy(
.table_relocs = .empty,
};
defer e.deinit();
e.emitMir() catch |err| switch (err) {
error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.ty, e.lower.err_msg.?),
error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s} (Zig compiler bug)", .{@errorName(err)}),
else => return zcu.codegenFailType(lazy_sym.ty, "emit MIR failed: {s}", .{@errorName(err)}),
e.emitMir() catch |err| switch (zcu.intern_pool.typeOf(lazy_sym.key)) {
.type_type => switch (err) {
error.LowerFail, error.EmitFail => return zcu.codegenFailTypeMsg(lazy_sym.key, e.lower.err_msg.?),
error.InvalidInstruction, error.CannotEncode => return zcu.codegenFailType(
lazy_sym.key,
"emit MIR failed: {t} (Zig compiler bug)",
.{err},
),
else => return zcu.codegenFailType(lazy_sym.key, "emit MIR failed: {t}", .{err}),
},
else => switch (err) {
error.LowerFail, error.EmitFail => std.debug.panic("{f}: {s}", .{
@import("../../Value.zig").fromInterned(lazy_sym.key).fmtValue(pt), e.lower.err_msg.?.msg,
}),
error.InvalidInstruction, error.CannotEncode => std.debug.panic(
"{f}: emit MIR failed: {t} (Zig compiler bug)",
.{ @import("../../Value.zig").fromInterned(lazy_sym.key).fmtValue(pt), err },
),
else => std.debug.panic("{f}: emit MIR failed: {t}", .{
@import("../../Value.zig").fromInterned(lazy_sym.key).fmtValue(pt), err,
}),
},
};
}
+10 -16
View File
@@ -238,7 +238,7 @@ pub const Instruction = struct {
try w.print("{f} ", .{sib.ptr_size});
if (mem.isSegmentRegister()) {
return w.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });
return w.print("{t}:0x{x}", .{ sib.base.reg, sib.disp });
}
try w.writeByte('[');
@@ -246,21 +246,18 @@ pub const Instruction = struct {
var any = true;
switch (sib.base) {
.none => any = false,
.reg => |reg| try w.print("{s}", .{@tagName(reg)}),
.reg => |reg| try w.print("{t}", .{reg}),
.frame => |frame_index| try w.print("{f}", .{frame_index}),
.table => try w.print("Table", .{}),
.rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}),
.nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}),
.uav => |uav| try w.print("Uav({d})", .{@intFromEnum(uav.val)}),
.lazy_sym => |lazy_sym| try w.print("LazySym({s}, {d})", .{
@tagName(lazy_sym.kind),
@intFromEnum(lazy_sym.ty),
}),
.extern_func => |extern_func| try w.print("ExternFunc({d})", .{@intFromEnum(extern_func)}),
.nav => |nav| try w.print("Nav({d})", .{nav}),
.uav => |uav| try w.print("Uav({d})", .{uav.val}),
.lazy_sym => |lazy_sym| try w.print("LazySym({t}, {d})", .{ lazy_sym.kind, lazy_sym.key }),
.extern_func => |extern_func| try w.print("ExternFunc({d})", .{extern_func}),
}
if (mem.scaleIndex()) |si| {
if (any) try w.writeAll(" + ");
try w.print("{s} * {d}", .{ @tagName(si.index), si.scale });
try w.print("{t} * {d}", .{ si.index, si.scale });
any = true;
}
if (sib.disp != 0 or !any) {
@@ -274,10 +271,7 @@ pub const Instruction = struct {
try w.writeByte(']');
},
.moffs => |moffs| try w.print("{s}:0x{x}", .{
@tagName(moffs.seg),
moffs.offset,
}),
.moffs => |moffs| try w.print("{t}:0x{x}", .{ moffs.seg, moffs.offset }),
},
.imm => |imm| if (enc_op.isSigned()) {
const imms = imm.asSigned(enc_op.immBitSize());
@@ -344,9 +338,9 @@ pub const Instruction = struct {
pub fn format(inst: Instruction, w: *Writer) Writer.Error!void {
switch (inst.prefix) {
.none, .directive => {},
else => try w.print("{s} ", .{@tagName(inst.prefix)}),
else => try w.print("{t} ", .{inst.prefix}),
}
try w.print("{s}", .{@tagName(inst.encoding.mnemonic)});
try w.print("{t}", .{inst.encoding.mnemonic});
for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| {
if (op == .none) break;
if (i > 0) try w.writeByte(',');
+18 -4
View File
@@ -1019,7 +1019,7 @@ pub const File = struct {
/// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
/// the block/atom.
/// Never called when LLVM is codegenning the ZCU.
pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
pub fn getNavVAddr(base: *File, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
@@ -1029,7 +1029,7 @@ pub const File = struct {
.plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info);
return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(nav_index, reloc_info);
},
}
}
@@ -1290,11 +1290,25 @@ pub const File = struct {
};
pub const LazySymbol = struct {
pub const Kind = enum { code, const_data };
pub const Kind = enum(u2) { code, const_data, deferred_const_data };
kind: Kind,
ty: InternPool.Index,
key: InternPool.Index,
};
pub fn getLazySymbolVAddr(base: *File, pt: Zcu.PerThread, lazy_symbol: LazySymbol, reloc_info: RelocInfo) !u64 {
assert(base.comp.zcu.?.llvm_object == null);
switch (base.tag) {
.lld => unreachable,
.c => unreachable,
.spirv => unreachable,
.wasm => unreachable,
.plan9 => unreachable,
inline else => |tag| {
dev.check(tag.devFeature());
return @as(*tag.Type(), @fieldParentPtr("base", base)).getLazySymbolVAddr(pt, lazy_symbol, reloc_info);
},
}
}
pub fn determinePermissions(
output_mode: std.builtin.OutputMode,
+50 -3
View File
@@ -134,6 +134,7 @@ const RenderedDecl = struct {
code: String,
ctype_deps: CTypeDependencies,
need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
need_restricted: std.array_hash_map.Auto(InternPool.Index, void),
need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void),
@@ -143,6 +144,7 @@ const RenderedDecl = struct {
.code = .empty,
.ctype_deps = .empty,
.need_uavs = .empty,
.need_restricted = .empty,
.need_tag_name_funcs = .empty,
.need_never_tail_funcs = .empty,
.need_never_inline_funcs = .empty,
@@ -150,6 +152,7 @@ const RenderedDecl = struct {
fn deinit(rd: *RenderedDecl, gpa: Allocator) void {
rd.need_uavs.deinit(gpa);
rd.need_restricted.deinit(gpa);
rd.need_tag_name_funcs.deinit(gpa);
rd.need_never_tail_funcs.deinit(gpa);
rd.need_never_inline_funcs.deinit(gpa);
@@ -162,6 +165,7 @@ const RenderedDecl = struct {
fn clearRetainingCapacity(rd: *RenderedDecl) void {
rd.fwd_decl = undefined;
rd.code = undefined;
rd.need_restricted.clearRetainingCapacity();
rd.need_uavs.clearRetainingCapacity();
rd.need_tag_name_funcs.clearRetainingCapacity();
rd.need_never_tail_funcs.clearRetainingCapacity();
@@ -501,6 +505,7 @@ pub fn updateFunc(
.code = try c.addString(&.{ mir.c.code_header, mir.c.code }),
.ctype_deps = try c.addCTypeDependencies(pt, &mir.c.ctype_deps),
.need_uavs = mir.c.need_uavs.move(),
.need_restricted = mir.c.need_restricted.move(),
.need_tag_name_funcs = mir.c.need_tag_name_funcs.move(),
.need_never_tail_funcs = mir.c.need_never_tail_funcs.move(),
.need_never_inline_funcs = mir.c.need_never_inline_funcs.move(),
@@ -576,11 +581,13 @@ pub fn updateNav(
.expected_block = null,
.ctype_deps = .empty,
.uavs = rendered_decl.need_uavs.move(),
.need_restricted = .empty,
};
defer {
rendered_decl.need_uavs = dg.uavs.move();
dg.ctype_deps.deinit(gpa);
dg.need_restricted.deinit(gpa);
}
rendered_decl.fwd_decl = fwd_decl: {
@@ -618,6 +625,7 @@ pub fn updateNav(
};
rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps);
rendered_decl.need_restricted = dg.need_restricted.move();
}
const old_uavs_len = c.uavs.count();
@@ -667,10 +675,12 @@ fn updateUav(
.expected_block = null,
.ctype_deps = .empty,
.uavs = .empty,
.need_restricted = .empty,
};
defer {
rendered_decl.need_uavs = dg.uavs.move();
dg.ctype_deps.deinit(gpa);
dg.need_restricted.deinit(gpa);
}
rendered_decl.fwd_decl = fwd_decl: {
@@ -716,6 +726,7 @@ fn updateUav(
};
rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps);
rendered_decl.need_restricted = dg.need_restricted.move();
}
pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) error{}!void {
@@ -795,6 +806,10 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
var need_aligned_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64) = .empty;
defer need_aligned_types.deinit(gpa);
var need_restricted: std.array_hash_map.Auto(InternPool.Index, std.array_hash_map.Auto(InternPool.Index, void)) = .empty;
defer need_restricted.deinit(gpa);
defer for (need_restricted.values()) |*values| values.deinit(gpa);
var need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty;
defer need_tag_name_funcs.deinit(gpa);
@@ -816,7 +831,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
if (!gop.found_existing) gop.value_ptr.* = .none;
}
// For every referenced NAV, some UAVs, C types, and lazy functions may be referenced.
// For every referenced NAV, some UAVs, restricted types, C types, and lazy functions may be referenced.
for (need_navs.keys()) |nav| {
const rendered = c.navs.getPtr(nav).?;
try mergeNeededCTypes(
@@ -827,6 +842,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
&rendered.ctype_deps,
);
try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs);
try mergeNeededRestricted(zcu, &need_restricted, &rendered.need_restricted);
try need_tag_name_funcs.ensureUnusedCapacity(gpa, rendered.need_tag_name_funcs.count());
for (rendered.need_tag_name_funcs.keys()) |enum_type| {
@@ -844,7 +860,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
}
}
// UAVs may reference other UAVs or C types.
// UAVs may reference other UAVs, restricted types, or C types.
{
var index: usize = 0;
while (need_uavs.count() > index) : (index += 1) {
@@ -858,6 +874,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
&rendered.ctype_deps,
);
try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs);
try mergeNeededRestricted(zcu, &need_restricted, &rendered.need_restricted);
}
}
@@ -962,7 +979,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
// * NAV exports
// * UAV forward declarations
// * NAV forward declarations
// * Lazy declarations (error names; @tagName functions; never_tail/never_inline wrappers)
// * Lazy declarations (restricted decls; error names; @tagName functions; never_tail/never_inline wrappers)
// * UAV definitions
// * NAV definitions
//
@@ -1115,11 +1132,18 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
.error_msg = null,
.ctype_deps = .empty,
.uavs = .empty,
.need_restricted = .empty,
};
defer {
assert(lazy_dg.uavs.count() == 0);
lazy_dg.ctype_deps.deinit(gpa);
assert(lazy_dg.need_restricted.count() == 0);
}
codegen.genRestricted(&lazy_dg, &need_restricted, &lazy_decls_aw.writer) catch |err| switch (err) {
error.WriteFailed => return error.OutOfMemory,
error.OutOfMemory => |e| return e,
error.AnalysisFail => unreachable,
};
const slice_const_u8_sentinel_0_cty: codegen.CType = try .lower(
.slice_const_u8_sentinel_0,
&lazy_dg.ctype_deps,
@@ -1259,10 +1283,12 @@ pub fn updateExports(
.error_msg = null,
.ctype_deps = .empty,
.uavs = .empty,
.need_restricted = .empty,
};
defer {
assert(dg.uavs.count() == 0);
dg.ctype_deps.deinit(gpa);
assert(dg.need_restricted.count() == 0);
}
const code: String = code: {
@@ -1347,6 +1373,27 @@ fn mergeNeededUavs(
}
}
fn mergeNeededRestricted(
zcu: *const Zcu,
global: *std.array_hash_map.Auto(InternPool.Index, std.array_hash_map.Auto(InternPool.Index, void)),
new: *const std.array_hash_map.Auto(InternPool.Index, void),
) Allocator.Error!void {
const gpa = zcu.comp.gpa;
const ip = &zcu.intern_pool;
try global.ensureUnusedCapacity(gpa, new.count());
for (new.keys()) |restricted_key| {
const restricted_ty = switch (ip.indexToKey(restricted_key)) {
else => unreachable,
.restricted_ptr_type => restricted_key,
.ptr => |ptr| ptr.ty,
};
const gop = global.getOrPutAssumeCapacity(restricted_ty);
if (!gop.found_existing) gop.value_ptr.* = .empty;
if (restricted_ty != restricted_key) try gop.value_ptr.put(gpa, restricted_key, {});
}
}
fn addCTypeDependencies(
c: *C,
pt: Zcu.PerThread,
+77 -36
View File
@@ -138,6 +138,7 @@ pub const Node = union(enum) {
uav: UavMapIndex,
lazy_code: LazyMapRef.Index(.code),
lazy_const_data: LazyMapRef.Index(.const_data),
lazy_deferred_const_data: LazyMapRef.Index(.deferred_const_data),
pub const PseudoSectionMapIndex = enum(u32) {
_,
@@ -222,7 +223,7 @@ pub const Node = union(enum) {
}
pub fn lazySymbol(lmr: LazyMapRef, coff: *const Coff) link.File.LazySymbol {
return .{ .kind = lmr.kind, .ty = coff.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
return .{ .kind = lmr.kind, .key = coff.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
}
pub fn symbol(lmr: LazyMapRef, coff: *const Coff) Symbol.Index {
@@ -1053,6 +1054,7 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
.uav,
.lazy_code,
.lazy_const_data,
.lazy_deferred_const_data,
=> |mi| mi.symbol(coff),
};
break :parent_rva parent_si.get(coff).rva;
@@ -1259,7 +1261,8 @@ fn navMapIndex(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.Na
if (!sym_gop.found_existing) sym_gop.value_ptr.* = coff.addSymbolAssumeCapacity();
return @enumFromInt(sym_gop.index);
}
pub fn navSymbol(coff: *Coff, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
pub fn navSymbol(coff: *Coff, nav_index: InternPool.Nav.Index) !Symbol.Index {
const zcu = coff.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
if (nav.getExtern(ip)) |@"extern"| return coff.globalSymbol(
@@ -1282,24 +1285,38 @@ pub fn uavSymbol(coff: *Coff, uav_val: InternPool.Index) !Symbol.Index {
return umi.symbol(coff);
}
pub fn lazySymbol(coff: *Coff, lazy: link.File.LazySymbol) !Symbol.Index {
const gpa = coff.base.comp.gpa;
try coff.symbol_table.ensureUnusedCapacity(gpa, 1);
const sym_gop = try coff.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
if (!sym_gop.found_existing) {
sym_gop.value_ptr.* = try coff.initSymbolAssumeCapacity();
coff.synth_prog_node.increaseEstimatedTotalItems(1);
}
return sym_gop.value_ptr.*;
fn lazySymbolIfExists(coff: *Coff, lazy_sym: link.File.LazySymbol) ?Symbol.Index {
return coff.lazy.getPtr(lazy_sym.kind).map.get(lazy_sym.key);
}
fn lazySymbolAssumeCapacity(coff: *Coff, lazy_sym: link.File.LazySymbol) !struct { Symbol.Index, usize } {
const gop = try coff.lazy.getPtr(lazy_sym.kind).map.getOrPut(coff.base.comp.gpa, lazy_sym.key);
if (gop.found_existing) return .{ gop.value_ptr.*, gop.index };
const si = try coff.initSymbolAssumeCapacity();
gop.value_ptr.* = si;
coff.synth_prog_node.increaseEstimatedTotalItems(1);
return .{ si, gop.index };
}
pub fn lazySymbol(coff: *Coff, lazy_sym: link.File.LazySymbol) !Symbol.Index {
// optimize for future lookups, at the cost of an extra initial key lookup
if (coff.lazySymbolIfExists(lazy_sym)) |si| return si;
const comp = coff.base.comp;
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, comp.zcu.?);
try coff.symbol_table.ensureUnusedCapacity(
comp.gpa,
@as(usize, @intFromBool(structure.parent != null)) + 1,
);
if (structure.parent) |parent_lazy_sym| _ = try coff.lazySymbolAssumeCapacity(parent_lazy_sym);
if (structure.modify) |modification| _ = try coff.lazySymbolAssumeCapacity(modification.lazy_sym);
const si, _ = try coff.lazySymbolAssumeCapacity(lazy_sym);
return si;
}
pub fn getNavVAddr(
coff: *Coff,
pt: Zcu.PerThread,
nav: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
return coff.getVAddr(reloc_info, try coff.navSymbol(pt.zcu, nav));
return coff.getVAddr(reloc_info, try coff.navSymbol(nav));
}
pub fn getUavVAddr(
@@ -1310,6 +1327,15 @@ pub fn getUavVAddr(
return coff.getVAddr(reloc_info, try coff.uavSymbol(uav));
}
pub fn getLazySymbolVAddr(
coff: *Coff,
_: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
reloc_info: link.File.RelocInfo,
) !u64 {
return coff.getVAddr(reloc_info, try coff.lazySymbol(lazy_sym));
}
pub fn getVAddr(coff: *Coff, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 {
try coff.addReloc(
@enumFromInt(reloc_info.parent.atom_index),
@@ -1713,7 +1739,7 @@ fn updateFuncInner(
pub fn updateErrorData(coff: *Coff, pt: Zcu.PerThread) !void {
coff.flushLazy(pt, .{
.kind = .const_data,
.kind = .deferred_const_data,
.index = @intCast(coff.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
}) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
@@ -1798,13 +1824,13 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
lazy.value.pending_index += 1;
const kind = switch (lmr.kind) {
.code => "code",
.const_data => "data",
.const_data, .deferred_const_data => "data",
};
var name: [std.Progress.Node.max_name_len]u8 = undefined;
const sub_prog_node = coff.synth_prog_node.start(
std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
kind,
Type.fromInterned(lmr.lazySymbol(coff).ty).fmt(pt),
Value.fromInterned(lmr.lazySymbol(coff).key).fmtValue(pt),
}) catch &name,
0,
);
@@ -2092,24 +2118,36 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const lazy = lmr.lazySymbol(coff);
const lazy_sym = lmr.lazySymbol(coff);
const si = lmr.symbol(coff);
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, zcu);
const ni = ni: {
const sym = si.get(coff);
switch (sym.ni) {
.none => {
try coff.nodes.ensureUnusedCapacity(gpa, 1);
const sec_si: Symbol.Index = switch (lazy.kind) {
const attrs = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu);
const parent_si: Symbol.Index = if (structure.parent) |parent_lazy_sym|
coff.lazySymbolIfExists(parent_lazy_sym).?
else switch (lazy_sym.kind) {
.code => .text,
.const_data => .rdata,
.const_data, .deferred_const_data => .rdata,
};
const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ .moved = true });
coff.nodes.appendAssumeCapacity(switch (lazy.kind) {
const addChildNode =
if (attrs.header) &MappedFile.addOnlyChildNode else &MappedFile.addLastChildNode;
const ni = try addChildNode(&coff.mf, coff.base.comp.gpa, parent_si.node(coff), .{
.size = attrs.size orelse 0,
.alignment = attrs.required_alignment.toStdMem(),
.fixed = attrs.header,
.moved = true,
});
coff.nodes.appendAssumeCapacity(switch (lazy_sym.kind) {
.code => .{ .lazy_code = @enumFromInt(lmr.index) },
.const_data => .{ .lazy_const_data = @enumFromInt(lmr.index) },
.deferred_const_data => .{ .lazy_deferred_const_data = @enumFromInt(lmr.index) },
});
sym.ni = ni;
sym.section_number = sec_si.get(coff).section_number;
sym.section_number = parent_si.get(coff).section_number;
},
else => si.deleteLocationRelocs(coff),
}
@@ -2118,22 +2156,25 @@ fn flushLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
break :ni sym.ni;
};
var required_alignment: InternPool.Alignment = .none;
var nw: MappedFile.Node.Writer = undefined;
ni.writer(&coff.mf, gpa, &nw);
defer nw.deinit();
try codegen.generateLazySymbol(
&coff.base,
pt,
Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
lazy,
&required_alignment,
Type.fromInterned(lazy_sym.key).srcLocOrNull(pt.zcu) orelse .unneeded,
lazy_sym,
&nw.interface,
.none,
.{ .atom_index = @intFromEnum(si) },
);
si.get(coff).size = @intCast(nw.interface.end);
si.applyLocationRelocs(coff);
if (structure.modify) |modification| modification.operation.apply(
coff.lazySymbolIfExists(modification.lazy_sym).?.node(coff).slice(&coff.mf),
coff.targetEndian(),
);
}
fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
@@ -2219,6 +2260,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void {
.uav,
.lazy_code,
.lazy_const_data,
.lazy_deferred_const_data,
=> |mi| mi.symbol(coff).flushMoved(coff),
}
try ni.childrenMoved(coff.base.comp.gpa, &coff.mf);
@@ -2269,7 +2311,7 @@ fn flushResized(coff: *Coff, ni: MappedFile.Node.Index) !void {
inline .pseudo_section,
.object_section,
=> |smi| smi.symbol(coff).get(coff).size = @intCast(size),
.global, .nav, .uav, .lazy_code, .lazy_const_data => {},
.global, .nav, .uav, .lazy_code, .lazy_const_data, .lazy_deferred_const_data => {},
}
}
fn virtualSlide(coff: *Coff, start_section_index: usize, start_rva: u32) !void {
@@ -2322,7 +2364,7 @@ fn updateExportsInner(
}
try coff.symbol_table.ensureUnusedCapacity(gpa, export_indices.len);
const exported_si: Symbol.Index = switch (exported) {
.nav => |nav| try coff.navSymbol(zcu, nav),
.nav => |nav| try coff.navSymbol(nav),
.uav => |uav| @enumFromInt(switch (try coff.lowerUav(
pt,
uav,
@@ -2365,7 +2407,7 @@ pub fn deleteExport(coff: *Coff, exported: Zcu.Exported, name: InternPool.NullTe
_ = name;
}
pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) !void {
const comp = coff.base.comp;
const io = comp.io;
var buffer: [512]u8 = undefined;
@@ -2373,7 +2415,7 @@ pub fn dump(coff: *Coff, tid: Zcu.PerThread.Id) Io.Cancelable!void {
defer io.unlockStderr();
const w = &stderr.file_writer.interface;
coff.printNode(tid, w, .root, 0) catch |err| switch (err) {
error.WriteFailed => return stderr.err.?,
error.WriteFailed => return stderr.file_writer.err.?,
};
}
@@ -2412,7 +2454,7 @@ pub fn printNode(
const ip = &zcu.intern_pool;
const nav = ip.getNav(nmi.navIndex(coff));
try w.print("({f}, {f})", .{
Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
nav.fqn.fmt(ip),
});
},
@@ -2425,10 +2467,9 @@ pub fn printNode(
});
},
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,
}),
Value.fromInterned(lmi.lazySymbol(coff).key).fmtValue(
.{ .zcu = coff.base.comp.zcu.?, .tid = tid },
),
}),
}
{
@@ -2458,7 +2499,7 @@ pub fn printNode(
const line_len = 0x10;
var line_it = std.mem.window(
u8,
coff.mf.contents[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
coff.mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)],
line_len,
line_len,
);
+2 -2
View File
@@ -3631,11 +3631,11 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
},
},
.restricted_ptr_type => |restricted_ptr_type| switch (Type.restrictedReprByZirIndex(restricted_ptr_type.zir_index, zcu)) {
.double_pointer => continue :key .{ .ptr_type = .{
.indirect => continue :key .{ .ptr_type = .{
.child = restricted_ptr_type.unrestricted_ptr_type,
.flags = .{ .is_const = true },
} },
.single_pointer => continue :key .{ .ptr_type = ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type },
.direct => continue :key .{ .ptr_type = ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type },
},
.array_type => |array_type| {
const array_child_type: Type = .fromInterned(array_type.child);
+6 -2
View File
@@ -467,8 +467,8 @@ pub fn deinit(self: *Elf) void {
self.dump_argv_list.deinit(gpa);
}
pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);
pub fn getNavVAddr(self: *Elf, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
return self.zigObjectPtr().?.getNavVAddr(self, nav_index, reloc_info);
}
pub fn lowerUav(
@@ -485,6 +485,10 @@ pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.Relo
return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
}
pub fn getLazySymbolVAddr(self: *Elf, pt: Zcu.PerThread, lazy_sym: link.File.LazySymbol, reloc_info: link.File.RelocInfo) !u64 {
return self.zigObjectPtr().?.getLazySymbolVAddr(self, pt, lazy_sym, reloc_info);
}
/// Returns end pos of collision, if any.
fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
const comp = self.base.comp;
+87 -53
View File
@@ -31,16 +31,17 @@ dwarf: ?Dwarf = null,
/// Table of tracked LazySymbols.
lazy_syms: LazySymbolTable = .{},
/// Table of tracked LazySymbols that are deferred until flush.
deferred_lazy_syms: LazySymbolTable = .{},
/// Table of tracked `Nav`s.
navs: NavTable = .{},
/// Table of tracked `Uav`s.
uavs: UavTable = .{},
/// TLS variables indexed by Atom.Index.
tls_variables: TlsTable = .{},
/// Table of tracked `Uav`s.
uavs: UavTable = .{},
debug_info_section_dirty: bool = false,
debug_abbrev_section_dirty: bool = false,
debug_aranges_section_dirty: bool = false,
@@ -246,13 +247,14 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
}
self.relocs.deinit(allocator);
self.lazy_syms.deinit(allocator);
self.deferred_lazy_syms.deinit(allocator);
for (self.navs.values()) |*meta| {
meta.exports.deinit(allocator);
}
self.navs.deinit(allocator);
self.lazy_syms.deinit(allocator);
for (self.uavs.values()) |*meta| {
meta.exports.deinit(allocator);
}
@@ -266,30 +268,22 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
// Handle any lazy symbols that were emitted by incremental compilation.
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
{
const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
defer pt.deactivate();
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
if (metadata.text_state != .unused) self.updateLazySymbol(
elf_file,
pt,
.{ .kind = .code, .ty = .anyerror_type },
metadata.text_symbol_index,
) catch |err| switch (err) {
error.CodegenFail => return error.LinkFailure,
else => |e| return e,
};
if (metadata.rodata_state != .unused) self.updateLazySymbol(
elf_file,
pt,
.{ .kind = .const_data, .ty = .anyerror_type },
metadata.rodata_symbol_index,
) catch |err| switch (err) {
error.CodegenFail => return error.LinkFailure,
else => |e| return e,
};
for (self.deferred_lazy_syms.values(), self.deferred_lazy_syms.keys()) |*metadata, key| {
assert(metadata.text_state == .unused);
if (metadata.rodata_state != .unused) self.updateLazySymbol(
elf_file,
pt,
.{ .kind = .deferred_const_data, .key = key },
metadata.rodata_symbol_index,
) catch |err| switch (err) {
error.CodegenFail => return error.LinkFailure,
else => |e| return e,
};
}
}
for (self.lazy_syms.values()) |*metadata| {
if (metadata.text_state != .unused) metadata.text_state = .flushed;
@@ -923,11 +917,10 @@ pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8
pub fn getNavVAddr(
self: *ZigObject,
elf_file: *Elf,
pt: Zcu.PerThread,
nav_index: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
const zcu = pt.zcu;
const zcu = elf_file.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
@@ -993,6 +986,44 @@ pub fn getUavVAddr(
return @intCast(vaddr);
}
pub fn getLazySymbolVAddr(
self: *ZigObject,
elf_file: *Elf,
pt: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
reloc_info: link.File.RelocInfo,
) !u64 {
log.debug("getLazySymbolVAddr {t} {f}({d})", .{
lazy_sym.kind,
Value.fromInterned(lazy_sym.key).fmtValue(pt),
lazy_sym.key,
});
const this_sym_index = try self.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym);
const this_sym = self.symbol(this_sym_index);
const vaddr = this_sym.address(.{}, elf_file);
switch (reloc_info.parent) {
.none => unreachable,
.atom_index => |atom_index| {
const parent_atom = self.symbol(atom_index).atom(elf_file).?;
const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
try parent_atom.addReloc(elf_file.base.comp.gpa, .{
.r_offset = reloc_info.offset,
.r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,
.r_addend = reloc_info.addend,
}, self);
},
.debug_output => |debug_output| switch (debug_output) {
.dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
.source_off = @intCast(reloc_info.offset),
.target_sym = this_sym_index,
.target_off = reloc_info.addend,
}),
.none => unreachable,
},
}
return @bitCast(vaddr);
}
pub fn lowerUav(
self: *ZigObject,
elf_file: *Elf,
@@ -1063,12 +1094,16 @@ pub fn getOrCreateMetadataForLazySymbol(
pt: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
) !Symbol.Index {
const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty);
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
const lazy_syms = switch (lazy_sym.kind) {
.code, .const_data => &self.lazy_syms,
.deferred_const_data => &self.deferred_lazy_syms,
};
const gop = try lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.key);
errdefer _ = if (!gop.found_existing) lazy_syms.pop();
if (!gop.found_existing) gop.value_ptr.* = .{};
const symbol_index_ptr, const state_ptr = switch (lazy_sym.kind) {
.code => .{ &gop.value_ptr.text_symbol_index, &gop.value_ptr.text_state },
.const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state },
.const_data, .deferred_const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state },
};
switch (state_ptr.*) {
.unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, 0),
@@ -1077,8 +1112,10 @@ pub fn getOrCreateMetadataForLazySymbol(
}
state_ptr.* = .pending_flush;
const symbol_index = symbol_index_ptr.*;
// anyerror needs to be deferred until flush
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);
switch (lazy_sym.kind) {
.code, .const_data => try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index),
.deferred_const_data => {},
}
return symbol_index;
}
@@ -1726,20 +1763,18 @@ fn updateLazySymbol(
self: *ZigObject,
elf_file: *Elf,
pt: Zcu.PerThread,
sym: link.File.LazySymbol,
lazy_sym: link.File.LazySymbol,
symbol_index: Symbol.Index,
) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
var required_alignment: InternPool.Alignment = .none;
var aw: std.Io.Writer.Allocating = .init(gpa);
defer aw.deinit();
const name_str_index = blk: {
const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{
@tagName(sym.kind),
Type.fromInterned(sym.ty).fmt(pt),
const name = try std.fmt.allocPrint(gpa, "__lazy_{t}_{f}", .{
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
});
defer gpa.free(name);
break :blk try self.strtab.insert(gpa, name);
@@ -1748,9 +1783,8 @@ fn updateLazySymbol(
codegen.generateLazySymbol(
&elf_file.base,
pt,
Type.fromInterned(sym.ty).srcLocOrNull(zcu) orelse .unneeded,
sym,
&required_alignment,
Type.fromInterned(lazy_sym.key).srcLocOrNull(zcu) orelse .unneeded,
lazy_sym,
&aw.writer,
.none,
.{ .atom_index = symbol_index },
@@ -1760,7 +1794,7 @@ fn updateLazySymbol(
};
const code = aw.written();
const output_section_index = switch (sym.kind) {
const output_section_index = switch (lazy_sym.kind) {
.code => if (self.text_index) |sym_index|
self.symbol(sym_index).outputShndx(elf_file).?
else osec: {
@@ -1773,7 +1807,7 @@ fn updateLazySymbol(
self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
break :osec osec;
},
.const_data => if (self.rodata_index) |sym_index|
.const_data, .deferred_const_data => if (self.rodata_index) |sym_index|
self.symbol(sym_index).outputShndx(elf_file).?
else osec: {
const osec = try elf_file.addSection(.{
@@ -1786,24 +1820,24 @@ fn updateLazySymbol(
break :osec osec;
},
};
const local_sym = self.symbol(symbol_index);
local_sym.name_offset = name_str_index;
const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index];
local_esym.st_name = name_str_index;
local_esym.st_info |= elf.STT_OBJECT;
local_esym.st_size = code.len;
const atom_ptr = local_sym.atom(elf_file).?;
const sym = self.symbol(symbol_index);
sym.name_offset = name_str_index;
const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
esym.st_name = name_str_index;
esym.st_info |= elf.STT_OBJECT;
esym.st_size = code.len;
const atom_ptr = sym.atom(elf_file).?;
atom_ptr.alive = true;
atom_ptr.name_offset = name_str_index;
atom_ptr.alignment = required_alignment;
atom_ptr.alignment = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu).required_alignment;
atom_ptr.size = code.len;
atom_ptr.output_section_index = output_section_index;
try self.allocateAtom(atom_ptr, true, elf_file);
errdefer self.freeNavMetadata(elf_file, symbol_index);
local_sym.value = 0;
local_esym.st_value = 0;
sym.value = 0;
esym.st_value = 0;
try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
}
+92 -46
View File
@@ -75,6 +75,7 @@ pub const Node = union(enum) {
uav: UavMapIndex,
lazy_code: LazyMapRef.Index(.code),
lazy_const_data: LazyMapRef.Index(.const_data),
lazy_deferred_const_data: LazyMapRef.Index(.deferred_const_data),
pub const InputIndex = enum(u32) {
_,
@@ -163,7 +164,7 @@ pub const Node = union(enum) {
}
pub fn lazySymbol(lmr: LazyMapRef, elf: *const Elf) link.File.LazySymbol {
return .{ .kind = lmr.kind, .ty = elf.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
return .{ .kind = lmr.kind, .key = elf.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
}
pub fn symbol(lmr: LazyMapRef, elf: *const Elf) Symbol.Index {
@@ -1680,7 +1681,12 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
},
.section => |si| si,
.input_section => unreachable,
inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf),
inline .nav,
.uav,
.lazy_code,
.lazy_const_data,
.lazy_deferred_const_data,
=> |mi| mi.symbol(elf),
};
break :parent_vaddr if (parent_si == elf.si.tdata) 0 else switch (elf.symPtr(parent_si)) {
inline else => |sym| elf.targetLoad(&sym.value),
@@ -1927,7 +1933,8 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM
});
return @enumFromInt(nav_gop.index);
}
pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !Symbol.Index {
const zcu = elf.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{
@@ -1963,20 +1970,35 @@ pub fn uavSymbol(elf: *Elf, uav_val: InternPool.Index) !Symbol.Index {
return umi.symbol(elf);
}
pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index {
const gpa = elf.base.comp.gpa;
try elf.symtab.ensureUnusedCapacity(gpa, 1);
const lazy_gop = try elf.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
if (!lazy_gop.found_existing) {
lazy_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
.type = switch (lazy.kind) {
.code => .FUNC,
.const_data => .OBJECT,
},
});
elf.synth_prog_node.increaseEstimatedTotalItems(1);
}
return lazy_gop.value_ptr.*;
fn lazySymbolIfExists(elf: *Elf, lazy_sym: link.File.LazySymbol) ?Symbol.Index {
return elf.lazy.getPtr(lazy_sym.kind).map.get(lazy_sym.key);
}
fn lazySymbolAssumeCapacity(elf: *Elf, lazy_sym: link.File.LazySymbol) !struct { Symbol.Index, usize } {
const gop = try elf.lazy.getPtr(lazy_sym.kind).map.getOrPut(elf.base.comp.gpa, lazy_sym.key);
if (gop.found_existing) return .{ gop.value_ptr.*, gop.index };
const si = try elf.initSymbolAssumeCapacity(.{
.type = switch (lazy_sym.kind) {
.code => .FUNC,
.const_data, .deferred_const_data => .OBJECT,
},
});
gop.value_ptr.* = si;
elf.synth_prog_node.increaseEstimatedTotalItems(1);
return .{ si, gop.index };
}
pub fn lazySymbol(elf: *Elf, lazy_sym: link.File.LazySymbol) !Symbol.Index {
// optimize for future lookups, at the cost of an extra initial key lookup
if (elf.lazySymbolIfExists(lazy_sym)) |si| return si;
const comp = elf.base.comp;
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, comp.zcu.?);
try elf.symtab.ensureUnusedCapacity(
comp.gpa,
@as(usize, @intFromBool(structure.parent != null)) + @intFromBool(structure.modify != null) + 1,
);
if (structure.parent) |parent_lazy_sym| _ = try elf.lazySymbolAssumeCapacity(parent_lazy_sym);
if (structure.modify) |modification| _ = try elf.lazySymbolAssumeCapacity(modification.lazy_sym);
const si, _ = try elf.lazySymbolAssumeCapacity(lazy_sym);
return si;
}
pub fn loadInput(elf: *Elf, input: link.Input) (Io.File.Reader.SizeError ||
@@ -2531,11 +2553,10 @@ fn prelinkInner(elf: *Elf) !void {
pub fn getNavVAddr(
elf: *Elf,
pt: Zcu.PerThread,
nav: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
return elf.getVAddr(reloc_info, try elf.navSymbol(pt.zcu, nav));
return elf.getVAddr(reloc_info, try elf.navSymbol(nav));
}
pub fn getUavVAddr(
@@ -2546,6 +2567,15 @@ pub fn getUavVAddr(
return elf.getVAddr(reloc_info, try elf.uavSymbol(uav));
}
pub fn getLazySymbolVAddr(
elf: *Elf,
_: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
reloc_info: link.File.RelocInfo,
) !u64 {
return elf.getVAddr(reloc_info, try elf.lazySymbol(lazy_sym));
}
pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 {
try elf.addReloc(
@enumFromInt(reloc_info.parent.atom_index),
@@ -3106,13 +3136,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
lazy.value.pending_index += 1;
const kind = switch (lmr.kind) {
.code => "code",
.const_data => "data",
.const_data, .deferred_const_data => "data",
};
var name: [std.Progress.Node.max_name_len]u8 = undefined;
const sub_prog_node = elf.synth_prog_node.start(
std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
kind,
Type.fromInterned(lmr.lazySymbol(elf).ty).fmt(pt),
Value.fromInterned(lmr.lazySymbol(elf).key).fmtValue(pt),
}) catch &name,
0,
);
@@ -3259,26 +3289,38 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const lazy = lmr.lazySymbol(elf);
const lazy_sym = lmr.lazySymbol(elf);
const si = lmr.symbol(elf);
const structure = codegen.getLazySymbolInfo(.structure, lazy_sym, zcu);
const ni = ni: {
const sym = si.get(elf);
switch (sym.ni) {
.none => {
try elf.nodes.ensureUnusedCapacity(gpa, 1);
const sec_si: Symbol.Index = switch (lazy.kind) {
const attrs = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu);
const parent_si: Symbol.Index = if (structure.parent) |parent_lazy_sym|
elf.lazySymbolIfExists(parent_lazy_sym).?
else switch (lazy_sym.kind) {
.code => .text,
.const_data => .rodata,
.const_data, .deferred_const_data => .rodata,
};
const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ .moved = true });
elf.nodes.appendAssumeCapacity(switch (lazy.kind) {
const addChildNode =
if (attrs.header) &MappedFile.addOnlyChildNode else &MappedFile.addLastChildNode;
const ni = try addChildNode(&elf.mf, elf.base.comp.gpa, parent_si.node(elf), .{
.size = attrs.size orelse 0,
.alignment = attrs.required_alignment.toStdMem(),
.fixed = attrs.header,
.moved = true,
});
elf.nodes.appendAssumeCapacity(switch (lazy_sym.kind) {
.code => .{ .lazy_code = @enumFromInt(lmr.index) },
.const_data => .{ .lazy_const_data = @enumFromInt(lmr.index) },
.deferred_const_data => .{ .lazy_deferred_const_data = @enumFromInt(lmr.index) },
});
sym.ni = ni;
switch (elf.symPtr(si)) {
inline else => |sym_ptr, class| sym_ptr.shndx =
@field(elf.symPtr(sec_si), @tagName(class)).shndx,
@field(elf.symPtr(parent_si), @tagName(class)).shndx,
}
},
else => si.deleteLocationRelocs(elf),
@@ -3288,16 +3330,14 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
break :ni sym.ni;
};
var required_alignment: InternPool.Alignment = .none;
var nw: MappedFile.Node.Writer = undefined;
ni.writer(&elf.mf, gpa, &nw);
defer nw.deinit();
try codegen.generateLazySymbol(
&elf.base,
pt,
Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded,
lazy,
&required_alignment,
Type.fromInterned(lazy_sym.key).srcLocOrNull(pt.zcu) orelse .unneeded,
lazy_sym,
&nw.interface,
.none,
.{ .atom_index = @intFromEnum(si) },
@@ -3306,6 +3346,11 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
}
si.applyLocationRelocs(elf);
if (structure.modify) |modification| modification.operation.apply(
elf.lazySymbolIfExists(modification.lazy_sym).?.node(elf).slice(&elf.mf),
elf.targetEndian(),
);
}
fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void {
@@ -3501,10 +3546,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
} - old_addr + new_addr);
}
},
inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf).flushMoved(
elf,
elf.computeNodeVAddr(ni),
),
inline .nav,
.uav,
.lazy_code,
.lazy_const_data,
.lazy_deferred_const_data,
=> |mi| mi.symbol(elf).flushMoved(elf, elf.computeNodeVAddr(ni)),
}
try ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
}
@@ -3614,7 +3661,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
elf.targetStore(&shdr.size, @intCast(size));
},
},
.input_section, .nav, .uav, .lazy_code, .lazy_const_data => {},
.input_section, .nav, .uav, .lazy_code, .lazy_const_data, .lazy_deferred_const_data => {},
}
}
@@ -3655,7 +3702,7 @@ fn updateExportsInner(
try elf.symtab.ensureUnusedCapacity(gpa, export_indices.len);
const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) {
.nav => |nav| .{
try elf.navSymbol(zcu, nav),
try elf.navSymbol(nav),
navType(ip, ip.getNav(nav).resolved.?, elf.base.comp.config.any_non_single_threaded),
},
.uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav(
@@ -3715,15 +3762,15 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm
_ = name;
}
pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) Io.Cancelable!void {
pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) !void {
const comp = elf.base.comp;
const io = comp.io;
var buffer: [512]u8 = undefined;
const stderr = try io.lockStderr(&buffer, null);
defer io.lockStderr();
defer io.unlockStderr();
const w = &stderr.file_writer.interface;
elf.printNode(tid, w, .root, 0) catch |err| switch (err) {
error.WriteFailed => return stderr.err.?,
error.WriteFailed => return stderr.file_writer.err.?,
};
}
@@ -3773,7 +3820,7 @@ pub fn printNode(
const ip = &zcu.intern_pool;
const nav = ip.getNav(nmi.navIndex(elf));
try w.print("({f}, {f})", .{
Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
nav.fqn.fmt(ip),
});
},
@@ -3786,17 +3833,16 @@ pub fn printNode(
});
},
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,
}),
Value.fromInterned(lmi.lazySymbol(elf).key).fmtValue(
.{ .zcu = elf.base.comp.zcu.?, .tid = tid },
),
}),
}
{
const mf_node = &elf.mf.nodes.items[@intFromEnum(ni)];
const off, const size = mf_node.location().resolve(&elf.mf);
try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{
@intFromEnum(ni),
ni,
off,
size,
mf_node.flags.alignment.toByteUnits(),
+6 -2
View File
@@ -3116,8 +3116,8 @@ pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
return self.getZigObject().?.freeNav(nav);
}
pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);
pub fn getNavVAddr(self: *MachO, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
return self.getZigObject().?.getNavVAddr(self, nav_index, reloc_info);
}
pub fn lowerUav(
@@ -3134,6 +3134,10 @@ pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.Re
return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
}
pub fn getLazySymbolVAddr(self: *MachO, pt: Zcu.PerThread, lazy_sym: link.File.LazySymbol, reloc_info: link.File.RelocInfo) !u64 {
return self.getZigObject().?.getLazySymbolVAddr(self, pt, lazy_sym, reloc_info);
}
pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 {
return self.getZigObject().?.getGlobalSymbol(self, name, lib_name);
}
+86 -42
View File
@@ -18,10 +18,11 @@ atoms_extra: std.ArrayList(u32) = .empty,
/// Table of tracked LazySymbols.
lazy_syms: LazySymbolTable = .{},
/// Table of tracked LazySymbols that are deferred until flush.
deferred_lazy_syms: LazySymbolTable = .{},
/// Table of tracked Navs.
navs: NavTable = .{},
/// Table of tracked Uavs.
uavs: UavTable = .{},
@@ -78,13 +79,14 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
self.atoms_indexes.deinit(allocator);
self.atoms_extra.deinit(allocator);
self.lazy_syms.deinit(allocator);
self.deferred_lazy_syms.deinit(allocator);
for (self.navs.values()) |*meta| {
meta.exports.deinit(allocator);
}
self.navs.deinit(allocator);
self.lazy_syms.deinit(allocator);
for (self.uavs.values()) |*meta| {
meta.exports.deinit(allocator);
}
@@ -559,30 +561,23 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F
const diags = &macho_file.base.comp.link_diags;
// Handle any lazy symbols that were emitted by incremental compilation.
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
{
const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
defer pt.deactivate();
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
if (metadata.text_state != .unused) self.updateLazySymbol(
macho_file,
pt,
.{ .kind = .code, .ty = .anyerror_type },
metadata.text_symbol_index,
) catch |err| switch (err) {
error.OutOfMemory, error.LinkFailure => |e| return e,
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
};
if (metadata.const_state != .unused) self.updateLazySymbol(
macho_file,
pt,
.{ .kind = .const_data, .ty = .anyerror_type },
metadata.const_symbol_index,
) catch |err| switch (err) {
error.OutOfMemory, error.LinkFailure => |e| return e,
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
};
for (self.deferred_lazy_syms.values(), self.deferred_lazy_syms.keys()) |*metadata, key| {
assert(metadata.text_state == .unused);
if (metadata.const_state != .unused) self.updateLazySymbol(
macho_file,
pt,
.{ .kind = .deferred_const_data, .key = key },
metadata.const_symbol_index,
) catch |err| switch (err) {
error.LinkFailure, error.CodegenFail => return error.LinkFailure,
error.OutOfMemory => |e| return e,
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
};
}
}
for (self.lazy_syms.values()) |*metadata| {
if (metadata.text_state != .unused) metadata.text_state = .flushed;
@@ -614,11 +609,10 @@ pub fn flush(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.F
pub fn getNavVAddr(
self: *ZigObject,
macho_file: *MachO,
pt: Zcu.PerThread,
nav_index: InternPool.Nav.Index,
reloc_info: link.File.RelocInfo,
) !u64 {
const zcu = pt.zcu;
const zcu = macho_file.base.comp.zcu.?;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
log.debug("getNavVAddr {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
@@ -698,6 +692,51 @@ pub fn getUavVAddr(
return vaddr;
}
pub fn getLazySymbolVAddr(
self: *ZigObject,
macho_file: *MachO,
pt: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
reloc_info: link.File.RelocInfo,
) !u64 {
log.debug("getLazySymbolVAddr {t} {f}({d})", .{
lazy_sym.kind,
Value.fromInterned(lazy_sym.key).fmtValue(pt),
lazy_sym.key,
});
const sym_index = try self.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym);
const sym = self.symbols.items[sym_index];
const vaddr = sym.getAddress(.{}, macho_file);
switch (reloc_info.parent) {
.none => unreachable,
.atom_index => |atom_index| {
const parent_atom = self.symbols.items[atom_index].getAtom(macho_file).?;
try parent_atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = @intCast(reloc_info.offset),
.target = sym_index,
.addend = reloc_info.addend,
.type = .unsigned,
.meta = .{
.pcrel = false,
.has_subtractor = false,
.length = 3,
.symbolnum = @intCast(sym.nlist_idx),
},
});
},
.debug_output => |debug_output| switch (debug_output) {
.dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
.source_off = @intCast(reloc_info.offset),
.target_sym = sym_index,
.target_off = reloc_info.addend,
}),
.none => unreachable,
},
}
return vaddr;
}
pub fn lowerUav(
self: *ZigObject,
macho_file: *MachO,
@@ -1355,35 +1394,34 @@ fn updateLazySymbol(
const zcu = pt.zcu;
const gpa = zcu.gpa;
var required_alignment: Atom.Alignment = .none;
var aw: std.Io.Writer.Allocating = .init(gpa);
defer aw.deinit();
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),
const name = try std.fmt.allocPrint(gpa, "__lazy_{t}_{f}", .{
lazy_sym.kind, Value.fromInterned(lazy_sym.key).fmtValue(pt),
});
defer gpa.free(name);
break :blk try self.addString(gpa, name);
};
const src = Type.fromInterned(lazy_sym.ty).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded;
try codegen.generateLazySymbol(
codegen.generateLazySymbol(
&macho_file.base,
pt,
src,
Type.fromInterned(lazy_sym.key).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded,
lazy_sym,
&required_alignment,
&aw.writer,
.none,
.{ .atom_index = symbol_index },
);
) catch |err| switch (err) {
error.WriteFailed => return error.OutOfMemory,
else => |e| return e,
};
const code = aw.written();
const output_section_index = switch (lazy_sym.kind) {
.code => macho_file.zig_text_sect_index.?,
.const_data => macho_file.zig_const_sect_index.?,
.const_data, .deferred_const_data => macho_file.zig_const_sect_index.?,
};
const sym = &self.symbols.items[symbol_index];
sym.name = name_str;
@@ -1398,7 +1436,7 @@ fn updateLazySymbol(
const atom = sym.getAtom(macho_file).?;
atom.setAlive(true);
atom.name = name_str;
atom.alignment = required_alignment;
atom.alignment = codegen.getLazySymbolInfo(.attributes, lazy_sym, zcu).required_alignment;
atom.size = code.len;
atom.out_n_sect = output_section_index;
@@ -1516,12 +1554,16 @@ pub fn getOrCreateMetadataForLazySymbol(
pt: Zcu.PerThread,
lazy_sym: link.File.LazySymbol,
) !Symbol.Index {
const gop = try self.lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.ty);
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
const lazy_syms = switch (lazy_sym.kind) {
.code, .const_data => &self.lazy_syms,
.deferred_const_data => &self.deferred_lazy_syms,
};
const gop = try lazy_syms.getOrPut(pt.zcu.gpa, lazy_sym.key);
errdefer _ = if (!gop.found_existing) lazy_syms.pop();
if (!gop.found_existing) gop.value_ptr.* = .{};
const symbol_index_ptr, const state_ptr = switch (lazy_sym.kind) {
.code => .{ &gop.value_ptr.text_symbol_index, &gop.value_ptr.text_state },
.const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state },
.const_data, .deferred_const_data => .{ &gop.value_ptr.const_symbol_index, &gop.value_ptr.const_state },
};
switch (state_ptr.*) {
.unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, .{}, macho_file),
@@ -1530,8 +1572,10 @@ pub fn getOrCreateMetadataForLazySymbol(
}
state_ptr.* = .pending_flush;
const symbol_index = symbol_index_ptr.*;
// anyerror needs to be deferred until flush
if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);
switch (lazy_sym.kind) {
.code, .const_data => try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index),
.deferred_const_data => {},
}
return symbol_index;
}
+4
View File
@@ -948,5 +948,9 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
// being run in a separate thread from now on.
else => true,
},
.restricted_types => switch (backend) {
.stage2_c, .stage2_x86_64 => true,
else => false,
},
};
}