diff --git a/src/InternPool.zig b/src/InternPool.zig index 1ad83911e41c9f8ed6907ae33133bae30b005ad8..447a6d9145d265dba91548096bd1327896777c46 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -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); } diff --git a/src/Type.zig b/src/Type.zig index ceb4b9705de2db0f18e249ed52bed17ef328ac59..5453b7f212f741bf0487523948f35d6681a7b26a 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -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, diff --git a/src/Zcu.zig b/src/Zcu.zig index fe44d076f5df5310361ec73286d0eac95ff978b5..1b78fce539565ea94dd46207375daef7244e96a0 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -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 { diff --git a/src/codegen.zig b/src/codegen.zig index 7c347002e0db3b8c8953bd715e28ee80ad58d2ea..94fcfd348380608fd2926ca6df2fef8c823428d6 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -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 => { diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index e06b846a611a4cd4715b556544e7d2ac9de88157..a47bbdc5915877488e3190363818acfe7b0bf78f 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -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)); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c093ee17b6dc87f993e2437bd42832d7778a89f0..d142e4e654030063212ab1d980fbe9a779b31a9d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -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; diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 3771107ccbab1bc241a8ad1a54162e1f05ebeab2..3cfeaeec7f00efb0fa3ce1b5fac7692ee2ba2e25 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -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 => { diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 5f038d0f7417a7cba07101d80e732d81574ab95a..5b730dfbeb04f7a714c857a5a1821c8408033b62 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -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, } } diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 20c4da678de19fd939f6a6ae2c39869a27454351..15085e3ee83e246d4ea3064722c49ee12640e7e5 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -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 { diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index fa3a665fe4c07025a9cf05ddc29256f212b73991..bb1fce670107093ee3b14684d6bcd17332499bef 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -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}); } diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 1301f19334cf22abe827570e41981cde10976298..c57ea3c049a384c05e3a62c18e933bfbeaa4de7a 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -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, diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig index c127d79446d9f657a3c4f14ea09dd26bc2c2f58e..d6425495a3af8e7338b327881fab06dd080fa6ff 100644 --- a/src/codegen/x86_64/Emit.zig +++ b/src/codegen/x86_64/Emit.zig @@ -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, diff --git a/src/codegen/x86_64/Mir.zig b/src/codegen/x86_64/Mir.zig index 1819ae384cd8fc1f61aaf448679ddd8e5b011d45..699b3ba8b484eaf9e2ff14c494f17d779be76f17 100644 --- a/src/codegen/x86_64/Mir.zig +++ b/src/codegen/x86_64/Mir.zig @@ -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, + }), + }, }; } diff --git a/src/codegen/x86_64/encoder.zig b/src/codegen/x86_64/encoder.zig index dd5229f3d349548caee9f6ab3f37bc82ef24e8b6..22033af6cdcd3cc6f23e86862dff208e1543d770 100644 --- a/src/codegen/x86_64/encoder.zig +++ b/src/codegen/x86_64/encoder.zig @@ -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(','); diff --git a/src/link.zig b/src/link.zig index 4ce9599023cd95a59b3ce0a21924175f598daf84..5c5f704f2448852a78175496b744520c71a87a55 100644 --- a/src/link.zig +++ b/src/link.zig @@ -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, diff --git a/src/link/C.zig b/src/link/C.zig index 9e0394659572582f6d504bc82e5dda23f653638f..a5048badeb4e35f08c2abfd051183aa4548536ce 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -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, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 565a6ece56e947c2b704d1546c84b15c336c879c..fbe4444162b595e97f138f1a1465b4a0a61402a2 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -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, ); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 674621d7e4ebbce5e109713f6eb2c4a687b1aaec..a089801f1050a964ef76ef9f10305facee25cbb8 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -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); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 2c035b6f07230872ca42bb4d93117de3489e211c..e6e16ff53fffb5faafdd2789562872f4de3e5e5a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -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; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 57677757b3cd643e8959a5e85b514a903cb91b90..b984225d79df3a14c8d65cf4f10f3b0e3b351e58 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -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 = .{}, - -/// TLS variables indexed by Atom.Index. -tls_variables: TlsTable = .{}, - /// Table of tracked `Uav`s. uavs: UavTable = .{}, +/// TLS variables indexed by Atom.Index. +tls_variables: TlsTable = .{}, + 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)); } diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index a5b4a9478b55599be5f8d4d8ce9ab3619527bbd1..581756698e777aff7894aa31968d5608e1702f65 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -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(), diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 66b686cd8a3c6b10c38606cc143482c6375a4be3..0ea3b2a23fefb773daace9a2e3d4b705cbc43bca 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -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); } diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index db3b51bc7f0f690727146472ac9733d54e7b930f..5fa63b1d30257e12be1dcc2de99e90ccb2f74b54 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -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; } diff --git a/src/target.zig b/src/target.zig index fc054186f2b4cff1d5f8c5d1de6de2645c4ddf89..1b49472b56791aed6933b9c5a5355734b7d20598 100644 --- a/src/target.zig +++ b/src/target.zig @@ -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, + }, }; }