authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-08-12 14:42:47-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 12:59:38-04:00
log8530e997ea6673ebdeb2c90d6d2eb2d777a99fcb
treeb412bc2a28b5a0d64194fcc4fb9be75b55d01170
parentb9b1174d069fcf201df79cb2fbaecdfc1fc74206

Elf2: try deleting lost nodes which contain stale info


6 files changed, 638 insertions(+), 513 deletions(-)

src/Zcu/PerThread.zig+2-1
...@@ -861,6 +861,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {...@@ -861,6 +861,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {
861 log.debug("tracking failed for %{d}", .{old_inst});861 log.debug("tracking failed for %{d}", .{old_inst});
862 tracked_inst.inst = .lost;862 tracked_inst.inst = .lost;
863 try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index });863 try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index });
864 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .lost_tracking = tracked_inst_index });
864 continue;865 continue;
865 };866 };
866 tracked_inst.inst = InternPool.TrackedInst.MaybeLost.ZirIndex.wrap(new_inst);867 tracked_inst.inst = InternPool.TrackedInst.MaybeLost.ZirIndex.wrap(new_inst);
...@@ -981,7 +982,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {...@@ -981,7 +982,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void {
981/// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies982/// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies
982/// that the file's namespace is scanned, discovering declarations.983/// that the file's namespace is scanned, discovering declarations.
983///984///
984/// Typical Zig compilations begin by claling this function on the root source file of the standard985/// Typical Zig compilations begin by calling this function on the root source file of the standard
985/// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in986/// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in
986/// that file, which is queued for analysis, and everything goes from there.987/// that file, which is queued for analysis, and everything goes from there.
987pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void {988pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void {
src/link.zig+29-3
...@@ -878,12 +878,11 @@ pub const File = struct {...@@ -878,12 +878,11 @@ pub const File = struct {
878 const inst = file.zir.?.instructions.get(@backingInt(ti.inst));878 const inst = file.zir.?.instructions.get(@backingInt(ti.inst));
879 assert(inst.tag == .declaration);879 assert(inst.tag == .declaration);
880 }880 }
881
882 switch (base.tag) {881 switch (base.tag) {
883 .lld => unreachable,882 .lld => unreachable,
884 .spirv => {},
885 .plan9 => unreachable,883 .plan9 => unreachable,
886 .elf2, .coff2 => {},884 .spirv => {},
885 .coff2 => {},
887 inline else => |tag| {886 inline else => |tag| {
888 dev.check(tag.devFeature());887 dev.check(tag.devFeature());
889 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);888 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);
...@@ -891,6 +890,19 @@ pub const File = struct {...@@ -891,6 +890,19 @@ pub const File = struct {
891 }890 }
892 }891 }
893892
893 fn lostTracking(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) Error!void {
894 assert(base.comp.zcu.?.llvm_object == null);
895 switch (base.tag) {
896 .lld => unreachable,
897 .plan9 => unreachable,
898 else => {},
899 inline .elf2 => |tag| {
900 dev.check(tag.devFeature());
901 return @as(*tag.Type(), @fieldParentPtr("base", base)).lostTracking(pt, ti_id);
902 },
903 }
904 }
905
894 pub fn releaseLock(base: *File) void {906 pub fn releaseLock(base: *File) void {
895 const comp = base.comp;907 const comp = base.comp;
896 const io = comp.io;908 const io = comp.io;
...@@ -1441,6 +1453,7 @@ pub const ZcuTask = union(enum) {...@@ -1441,6 +1453,7 @@ pub const ZcuTask = union(enum) {
1441 success: bool,1453 success: bool,
1442 },1454 },
1443 debug_update_line_number: InternPool.TrackedInst.Index,1455 debug_update_line_number: InternPool.TrackedInst.Index,
1456 lost_tracking: InternPool.TrackedInst.Index,
1444};1457};
14451458
1446pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {1459pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
...@@ -1713,6 +1726,19 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1713,6 +1726,19 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1713 }1726 }
1714 break :nav null;1727 break :nav null;
1715 },1728 },
1729 .lost_tracking => |ti| nav: {
1730 const nav_prog_node = comp.link_prog_node.start("Lost tracking", 0);
1731 defer nav_prog_node.end();
1732 if (pt.zcu.llvm_object == null) {
1733 if (comp.bin_file) |lf| {
1734 lf.lostTracking(pt, ti) catch |err| switch (err) {
1735 error.OutOfMemory => diags.setAllocFailure(),
1736 else => |e| log.err("lost tracking failed: {s}", .{@errorName(e)}),
1737 };
1738 }
1739 }
1740 break :nav null;
1741 },
1716 };1742 };
17171743
1718 if (timer.finish(io)) |ns_link| report_time: {1744 if (timer.finish(io)) |ns_link| report_time: {
src/link/Coff.zig+71-70
...@@ -536,7 +536,7 @@ pub const Member = struct {...@@ -536,7 +536,7 @@ pub const Member = struct {
536 const new_size = Alignment.@"4".forward(old_size + name.len + 1);536 const new_size = Alignment.@"4".forward(old_size + name.len + 1);
537 assert(new_size < comptime try std.math.powi(u64, 10, max_name_len - 1));537 assert(new_size < comptime try std.math.powi(u64, 10, max_name_len - 1));
538538
539 try Node.known.longnames_member.resizeLeaf(&coff.mf, gpa, new_size);539 try Node.known.longnames_member.resizeLeaf(gpa, &coff.mf, new_size);
540 const name_table_slice = Node.known.longnames_member.slice(&coff.mf);540 const name_table_slice = Node.known.longnames_member.slice(&coff.mf);
541 const name_slice = name_table_slice[@intCast(old_size)..][0 .. name.len + 1];541 const name_slice = name_table_slice[@intCast(old_size)..][0 .. name.len + 1];
542 @memcpy(name_slice[0..name.len], name);542 @memcpy(name_slice[0..name.len], name);
...@@ -1840,13 +1840,13 @@ fn initHeaders(...@@ -1840,13 +1840,13 @@ fn initHeaders(
1840 coff.nodes.appendAssumeCapacity(.file);1840 coff.nodes.appendAssumeCapacity(.file);
18411841
1842 const header_ni = Node.known.header;1842 const header_ni = Node.known.header;
1843 assert(header_ni == try Node.known.file.addOnlyHeaderChild(&coff.mf, gpa, .{1843 assert(header_ni == try Node.known.file.addOnlyHeaderChild(gpa, &coff.mf, .{
1844 .alignment = coff.mf.flags.block_size,1844 .alignment = coff.mf.flags.block_size,
1845 }));1845 }));
1846 coff.nodes.appendAssumeCapacity(.header);1846 coff.nodes.appendAssumeCapacity(.header);
18471847
1848 const coff_parent_ni: MappedFile.Node.Index = if (is_archive) parent: {1848 const coff_parent_ni: MappedFile.Node.Index = if (is_archive) parent: {
1849 assert(try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, .wrap(header_ni), .{1849 assert(try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, .wrap(header_ni), .{
1850 .size = std.coff.archive_signature.len,1850 .size = std.coff.archive_signature.len,
1851 .alignment = .@"4",1851 .alignment = .@"4",
1852 }) == Node.known.signature);1852 }) == Node.known.signature);
...@@ -1879,7 +1879,7 @@ fn initHeaders(...@@ -1879,7 +1879,7 @@ fn initHeaders(
1879 const zcu_member = zcu_mi.get(coff);1879 const zcu_member = zcu_mi.get(coff);
1880 try zcu_member.initHeader(coff, zcu.main_mod.fully_qualified_name, timestamp);1880 try zcu_member.initHeader(coff, zcu.main_mod.fully_qualified_name, timestamp);
18811881
1882 assert(try zcu_member.content_ni.addOnlyHeaderChild(&coff.mf, gpa, .{1882 assert(try zcu_member.content_ni.addOnlyHeaderChild(gpa, &coff.mf, .{
1883 .size = @sizeOf(std.coff.Header),1883 .size = @sizeOf(std.coff.Header),
1884 .alignment = .@"4",1884 .alignment = .@"4",
1885 }) == Node.known.coff_header);1885 }) == Node.known.coff_header);
...@@ -1894,13 +1894,13 @@ fn initHeaders(...@@ -1894,13 +1894,13 @@ fn initHeaders(
1894 // no other members then the last linker member (longnames) needs to expand1894 // no other members then the last linker member (longnames) needs to expand
1895 // to fill the padding at the end of the file.1895 // to fill the padding at the end of the file.
1896 while (coff.nodes.len < Node.known_count) {1896 while (coff.nodes.len < Node.known_count) {
1897 _ = try Node.known.header.addHeaderChildAfter(&coff.mf, gpa, .none, .{});1897 _ = try Node.known.header.addHeaderChildAfter(gpa, &coff.mf, .none, .{});
1898 coff.nodes.appendAssumeCapacity(.placeholder);1898 coff.nodes.appendAssumeCapacity(.placeholder);
1899 }1899 }
19001900
1901 return;1901 return;
1902 } else parent: {1902 } else parent: {
1903 assert(try header_ni.addOnlyHeaderChild(&coff.mf, gpa, .{1903 assert(try header_ni.addOnlyHeaderChild(gpa, &coff.mf, .{
1904 .size = if (is_image) msdos_stub.len + std.coff.pe_signature.len else 0,1904 .size = if (is_image) msdos_stub.len + std.coff.pe_signature.len else 0,
1905 .alignment = .@"4",1905 .alignment = .@"4",
1906 }) == Node.known.signature);1906 }) == Node.known.signature);
...@@ -1913,12 +1913,12 @@ fn initHeaders(...@@ -1913,12 +1913,12 @@ fn initHeaders(
19131913
1914 // TODO: Not ideal to have this many placeholder nodes - use two distinct `Node.known` types?1914 // TODO: Not ideal to have this many placeholder nodes - use two distinct `Node.known` types?
1915 while (true) {1915 while (true) {
1916 const placeholder_ni = try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, .none, .{});1916 const placeholder_ni = try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, .none, .{});
1917 coff.nodes.appendAssumeCapacity(.placeholder);1917 coff.nodes.appendAssumeCapacity(.placeholder);
1918 if (placeholder_ni == Node.known.zcu_member) break;1918 if (placeholder_ni == Node.known.zcu_member) break;
1919 }1919 }
19201920
1921 assert(try header_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(Node.known.signature), .{1921 assert(try header_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(Node.known.signature), .{
1922 .size = @sizeOf(std.coff.Header),1922 .size = @sizeOf(std.coff.Header),
1923 .alignment = .@"4",1923 .alignment = .@"4",
1924 }) == Node.known.coff_header);1924 }) == Node.known.coff_header);
...@@ -1949,7 +1949,7 @@ fn initHeaders(...@@ -1949,7 +1949,7 @@ fn initHeaders(
1949 }1949 }
19501950
1951 const optional_header_ni = Node.known.optional_header;1951 const optional_header_ni = Node.known.optional_header;
1952 assert(optional_header_ni == try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(Node.known.coff_header), .{1952 assert(optional_header_ni == try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(Node.known.coff_header), .{
1953 .size = optional_header_size,1953 .size = optional_header_size,
1954 .alignment = .@"4",1954 .alignment = .@"4",
1955 }));1955 }));
...@@ -2060,7 +2060,7 @@ fn initHeaders(...@@ -2060,7 +2060,7 @@ fn initHeaders(
2060 }2060 }
20612061
2062 const data_directories_ni = Node.known.data_directories;2062 const data_directories_ni = Node.known.data_directories;
2063 assert(data_directories_ni == try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(optional_header_ni), .{2063 assert(data_directories_ni == try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(optional_header_ni), .{
2064 .size = data_directories_size,2064 .size = data_directories_size,
2065 .alignment = .@"4",2065 .alignment = .@"4",
2066 }));2066 }));
...@@ -2075,7 +2075,7 @@ fn initHeaders(...@@ -2075,7 +2075,7 @@ fn initHeaders(
2075 }2075 }
20762076
2077 const section_table_ni = Node.known.section_table;2077 const section_table_ni = Node.known.section_table;
2078 assert(section_table_ni == try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(data_directories_ni), .{2078 assert(section_table_ni == try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(data_directories_ni), .{
2079 .alignment = .@"4",2079 .alignment = .@"4",
2080 }));2080 }));
2081 coff.nodes.appendAssumeCapacity(.section_table);2081 coff.nodes.appendAssumeCapacity(.section_table);
...@@ -2084,13 +2084,13 @@ fn initHeaders(...@@ -2084,13 +2084,13 @@ fn initHeaders(
20842084
2085 if (!is_image) {2085 if (!is_image) {
2086 // TODO: These two nodes could be inside one movable node?2086 // TODO: These two nodes could be inside one movable node?
2087 coff.symbol_table.ni = try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(section_table_ni), .{2087 coff.symbol_table.ni = try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(section_table_ni), .{
2088 .alignment = .@"2",2088 .alignment = .@"2",
2089 .moved = true,2089 .moved = true,
2090 });2090 });
2091 coff.nodes.appendAssumeCapacity(.symbol_table);2091 coff.nodes.appendAssumeCapacity(.symbol_table);
20922092
2093 coff.symbol_table.strings_ni = try coff_parent_ni.addHeaderChildAfter(&coff.mf, gpa, .wrap(coff.symbol_table.ni), .{2093 coff.symbol_table.strings_ni = try coff_parent_ni.addHeaderChildAfter(gpa, &coff.mf, .wrap(coff.symbol_table.ni), .{
2094 .size = @sizeOf(u32),2094 .size = @sizeOf(u32),
2095 .resized = true,2095 .resized = true,
2096 });2096 });
...@@ -2143,7 +2143,7 @@ fn initHeaders(...@@ -2143,7 +2143,7 @@ fn initHeaders(
2143 coff.mf.flags.block_size,2143 coff.mf.flags.block_size,
2144 .{ .read = true, .initialized = true },2144 .{ .read = true, .initialized = true },
2145 )).symbol(coff).node(coff);2145 )).symbol(coff).node(coff);
2146 coff.import_table.ni = try import_table_parent_ni.addFloatingChild(&coff.mf, gpa, .{2146 coff.import_table.ni = try import_table_parent_ni.addFloatingChild(gpa, &coff.mf, .{
2147 .alignment = .@"4",2147 .alignment = .@"4",
2148 });2148 });
2149 coff.nodes.appendAssumeCapacity(.import_directory_table);2149 coff.nodes.appendAssumeCapacity(.import_directory_table);
...@@ -2154,7 +2154,7 @@ fn initHeaders(...@@ -2154,7 +2154,7 @@ fn initHeaders(
2154 .{ .read = true, .initialized = true },2154 .{ .read = true, .initialized = true },
2155 )).symbol(coff).node(coff);2155 )).symbol(coff).node(coff);
21562156
2157 coff.export_table.export_directory_table_ni = try coff.export_table.ni.addHeaderChildAfter(&coff.mf, gpa, coff.export_table.ni.last(&coff.mf), .{2157 coff.export_table.export_directory_table_ni = try coff.export_table.ni.addHeaderChildAfter(gpa, &coff.mf, coff.export_table.ni.last(&coff.mf), .{
2158 .size = @sizeOf(std.coff.ExportDirectoryTable) + file_name.len + 1,2158 .size = @sizeOf(std.coff.ExportDirectoryTable) + file_name.len + 1,
2159 .moved = true,2159 .moved = true,
2160 });2160 });
...@@ -2165,7 +2165,7 @@ fn initHeaders(...@@ -2165,7 +2165,7 @@ fn initHeaders(
2165 @memcpy(table_slice[name_index..][0..file_name.len], file_name[0..file_name.len]);2165 @memcpy(table_slice[name_index..][0..file_name.len], file_name[0..file_name.len]);
2166 @memset(table_slice[name_index + file_name.len ..], 0);2166 @memset(table_slice[name_index + file_name.len ..], 0);
21672167
2168 const export_address_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{2168 const export_address_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{
2169 .alignment = .of(std.coff.ExportAddressTableEntry),2169 .alignment = .of(std.coff.ExportAddressTableEntry),
2170 .moved = true,2170 .moved = true,
2171 });2171 });
...@@ -2181,19 +2181,19 @@ fn initHeaders(...@@ -2181,19 +2181,19 @@ fn initHeaders(
2181 export_address_table_sym.section_number =2181 export_address_table_sym.section_number =
2182 coff.getNode(coff.export_table.ni).pseudo_section.symbol(coff).get(coff).section_number;2182 coff.getNode(coff.export_table.ni).pseudo_section.symbol(coff).get(coff).section_number;
21832183
2184 coff.export_table.name_pointer_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{2184 coff.export_table.name_pointer_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{
2185 .alignment = .of(std.coff.ExportNamePointerTableEntry),2185 .alignment = .of(std.coff.ExportNamePointerTableEntry),
2186 .moved = true,2186 .moved = true,
2187 });2187 });
2188 coff.nodes.appendAssumeCapacity(.export_name_pointer_table);2188 coff.nodes.appendAssumeCapacity(.export_name_pointer_table);
21892189
2190 coff.export_table.ordinal_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{2190 coff.export_table.ordinal_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{
2191 .alignment = .of(std.coff.ExportOrdinalTableEntry),2191 .alignment = .of(std.coff.ExportOrdinalTableEntry),
2192 .moved = true,2192 .moved = true,
2193 });2193 });
2194 coff.nodes.appendAssumeCapacity(.export_ordinal_table);2194 coff.nodes.appendAssumeCapacity(.export_ordinal_table);
21952195
2196 coff.export_table.name_table_ni = try coff.export_table.ni.addFloatingChild(&coff.mf, gpa, .{2196 coff.export_table.name_table_ni = try coff.export_table.ni.addFloatingChild(gpa, &coff.mf, .{
2197 .alignment = .of(u8),2197 .alignment = .of(u8),
2198 .moved = true,2198 .moved = true,
2199 });2199 });
...@@ -2286,7 +2286,7 @@ pub fn initBuiltins(coff: *Coff) !void {...@@ -2286,7 +2286,7 @@ pub fn initBuiltins(coff: *Coff) !void {
2286 const list_len_si = try coff.globalSymbol(.{ .name = list.global, .type = .data });2286 const list_len_si = try coff.globalSymbol(.{ .name = list.global, .type = .data });
2287 const list_len_sym = list_len_si.get(coff);2287 const list_len_sym = list_len_si.get(coff);
2288 list_len_sym.setExtra(.{ .size = addr_info.size });2288 list_len_sym.setExtra(.{ .size = addr_info.size });
2289 list_len_sym.ni = .wrap(try start_sym.ni.unwrap().?.addHeaderChildAfter(&coff.mf, gpa, .none, .{2289 list_len_sym.ni = .wrap(try start_sym.ni.unwrap().?.addHeaderChildAfter(gpa, &coff.mf, .none, .{
2290 .size = addr_info.size,2290 .size = addr_info.size,
2291 }));2291 }));
2292 coff.nodes.appendAssumeCapacity(.{ .builtin = list_len_si });2292 coff.nodes.appendAssumeCapacity(.{ .builtin = list_len_si });
...@@ -2307,7 +2307,7 @@ pub fn initBuiltins(coff: *Coff) !void {...@@ -2307,7 +2307,7 @@ pub fn initBuiltins(coff: *Coff) !void {
2307 const list_end_si = coff.addSymbolAssumeCapacity();2307 const list_end_si = coff.addSymbolAssumeCapacity();
2308 const list_end_sym = list_end_si.get(coff);2308 const list_end_sym = list_end_si.get(coff);
2309 list_end_sym.setExtra(.{ .size = addr_info.size });2309 list_end_sym.setExtra(.{ .size = addr_info.size });
2310 list_end_sym.ni = .wrap(try end_sym.ni.unwrap().?.addHeaderChildAfter(&coff.mf, gpa, .none, .{2310 list_end_sym.ni = .wrap(try end_sym.ni.unwrap().?.addHeaderChildAfter(gpa, &coff.mf, .none, .{
2311 .size = addr_info.size,2311 .size = addr_info.size,
2312 }));2312 }));
2313 coff.nodes.appendAssumeCapacity(.{ .builtin = list_end_si });2313 coff.nodes.appendAssumeCapacity(.{ .builtin = list_end_si });
...@@ -2723,7 +2723,7 @@ fn getOrPutSymbolName(coff: *Coff, name: []const u8, opt_string: ?String) !Symbo...@@ -2723,7 +2723,7 @@ fn getOrPutSymbolName(coff: *Coff, name: []const u8, opt_string: ?String) !Symbo
2723 const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1];2723 const string_index = coff.symbol_table.strings_ni.location(&coff.mf).resolve(&coff.mf)[1];
2724 string_gop.value_ptr.* = @fromBackingInt(@intCast(string_index));2724 string_gop.value_ptr.* = @fromBackingInt(@intCast(string_index));
27252725
2726 try coff.symbol_table.strings_ni.resizeLeaf(&coff.mf, gpa, string_index + name.len + 1);2726 try coff.symbol_table.strings_ni.resizeLeaf(gpa, &coff.mf, string_index + name.len + 1);
2727 const slice = coff.symbol_table.strings_ni.slice(&coff.mf);2727 const slice = coff.symbol_table.strings_ni.slice(&coff.mf);
2728 @memcpy(slice[@intCast(string_index)..][0..name.len], name);2728 @memcpy(slice[@intCast(string_index)..][0..name.len], name);
2729 slice[@intCast(string_index + name.len)] = 0;2729 slice[@intCast(string_index + name.len)] = 0;
...@@ -2948,7 +2948,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind,...@@ -2948,7 +2948,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind,
2948 const comp = coff.base.comp;2948 const comp = coff.base.comp;
2949 const gpa = comp.gpa;2949 const gpa = comp.gpa;
29502950
2951 const header_ni = try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, Node.known.file.last(&coff.mf), .{2951 const header_ni = try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, Node.known.file.last(&coff.mf), .{
2952 .size = @sizeOf(std.coff.ArchiveMemberHeader),2952 .size = @sizeOf(std.coff.ArchiveMemberHeader),
2953 .alignment = .@"2",2953 .alignment = .@"2",
2954 .moved = true,2954 .moved = true,
...@@ -2960,7 +2960,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind,...@@ -2960,7 +2960,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind,
2960 .first_linker, .second_linker, .longnames, .coff => .@"4",2960 .first_linker, .second_linker, .longnames, .coff => .@"4",
2961 else => .@"2",2961 else => .@"2",
2962 };2962 };
2963 const content_ni = try Node.known.file.addHeaderChildAfter(&coff.mf, gpa, .wrap(header_ni), .{2963 const content_ni = try Node.known.file.addHeaderChildAfter(gpa, &coff.mf, .wrap(header_ni), .{
2964 .alignment = content_align,2964 .alignment = content_align,
2965 .size = content_align.forward(size),2965 .size = content_align.forward(size),
2966 .resized = size > 0,2966 .resized = size > 0,
...@@ -2989,7 +2989,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind,...@@ -2989,7 +2989,7 @@ fn addMemberAssumeCapacity(coff: *Coff, kind: std.coff.ArchiveMemberHeader.Kind,
2989 const old_size = Node.known.second_linker_member.location(&coff.mf).resolve(&coff.mf)[1];2989 const old_size = Node.known.second_linker_member.location(&coff.mf).resolve(&coff.mf)[1];
2990 const old_header_size = new_num_members * @sizeOf(u32);2990 const old_header_size = new_num_members * @sizeOf(u32);
2991 const trailing_size: usize = @intCast(old_size - old_header_size);2991 const trailing_size: usize = @intCast(old_size - old_header_size);
2992 try Node.known.second_linker_member.resizeLeaf(&coff.mf, gpa, old_size + @sizeOf(u32));2992 try Node.known.second_linker_member.resizeLeaf(gpa, &coff.mf, old_size + @sizeOf(u32));
29932993
2994 const slice = Node.known.second_linker_member.slice(&coff.mf);2994 const slice = Node.known.second_linker_member.slice(&coff.mf);
2995 @memmove(2995 @memmove(
...@@ -3060,7 +3060,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {...@@ -3060,7 +3060,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {
3060 {3060 {
3061 const old_header_size: usize = @intCast(@sizeOf(u32) + @backingInt(mfli) * @sizeOf(u32));3061 const old_header_size: usize = @intCast(@sizeOf(u32) + @backingInt(mfli) * @sizeOf(u32));
3062 const new_header_size: usize = @intCast(old_header_size + @sizeOf(u32));3062 const new_header_size: usize = @intCast(old_header_size + @sizeOf(u32));
3063 try Node.known.first_linker_member.resizeLeaf(&coff.mf, gpa, Alignment.@"4".forward(new_header_size + new_string_table_size));3063 try Node.known.first_linker_member.resizeLeaf(gpa, &coff.mf, Alignment.@"4".forward(new_header_size + new_string_table_size));
30643064
3065 const slice = Node.known.first_linker_member.slice(&coff.mf);3065 const slice = Node.known.first_linker_member.slice(&coff.mf);
3066 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);3066 @memmove(slice[new_header_size..][0..coff.lib_string_len], slice[old_header_size..][0..coff.lib_string_len]);
...@@ -3074,7 +3074,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {...@@ -3074,7 +3074,7 @@ fn ensureMemberSymbol(coff: *Coff, mi: Member.Index, name: String) !void {
3074 const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());3074 const num_members = coff.targetLoad(coff.secondLinkerMemberNumMembersPtr());
3075 const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + @backingInt(mfli) * @sizeOf(u16);3075 const old_header_size = 2 * @sizeOf(u32) + num_members * @sizeOf(u32) + @backingInt(mfli) * @sizeOf(u16);
3076 const new_header_size = old_header_size + @sizeOf(u16);3076 const new_header_size = old_header_size + @sizeOf(u16);
3077 try Node.known.second_linker_member.resizeLeaf(&coff.mf, gpa, Alignment.@"4".forward(new_header_size + new_string_table_size));3077 try Node.known.second_linker_member.resizeLeaf(gpa, &coff.mf, Alignment.@"4".forward(new_header_size + new_string_table_size));
30783078
3079 const old_needs_sort = coff.pending_members.get(Member.Index.second) != null;3079 const old_needs_sort = coff.pending_members.get(Member.Index.second) != null;
3080 const needs_sort = old_needs_sort or (if (coff.lib_string_table.items.len > 0)3080 const needs_sort = old_needs_sort or (if (coff.lib_string_table.items.len > 0)
...@@ -3181,7 +3181,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void {...@@ -3181,7 +3181,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32) !void {
3181 const new_num_symbols = old_num_symbols + 1 + num_aux_symbols;3181 const new_num_symbols = old_num_symbols + 1 + num_aux_symbols;
3182 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);3182 coff.targetStore(&coff.headerPtr().number_of_symbols, new_num_symbols);
31833183
3184 try coff.symbol_table.ni.resizeLeaf(&coff.mf, gpa, new_num_symbols * std.coff.Symbol.sizeOf());3184 try coff.symbol_table.ni.resizeLeaf(gpa, &coff.mf, new_num_symbols * std.coff.Symbol.sizeOf());
31853185
3186 sti.* = .wrap(old_num_symbols);3186 sti.* = .wrap(old_num_symbols);
3187 si.flushSymbolTableIndex(coff);3187 si.flushSymbolTableIndex(coff);
...@@ -3317,7 +3317,7 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void {...@@ -3317,7 +3317,7 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void {
3317 try fr.seekTo(file_loc.offset);3317 try fr.seekTo(file_loc.offset);
3318 var nw: MappedFile.Node.Writer = undefined;3318 var nw: MappedFile.Node.Writer = undefined;
3319 const si = isi.symbol(coff);3319 const si = isi.symbol(coff);
3320 si.node(coff).writer(&coff.mf, gpa, &nw);3320 si.node(coff).writer(gpa, &coff.mf, &nw);
3321 defer nw.deinit();3321 defer nw.deinit();
3322 log.debug("flushInputSection({f}{f}, {s}, {d}, n{d})", .{3322 log.debug("flushInputSection({f}{f}, {s}, {d}, n{d})", .{
3323 path,3323 path,
...@@ -3345,12 +3345,12 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S...@@ -3345,12 +3345,12 @@ fn addSection(coff: *Coff, name: String, flags: std.coff.SectionHeader.Flags) !S
3345 const section_table_len = section_index + 1;3345 const section_table_len = section_index + 1;
3346 coff.targetStore(&coff_header.number_of_sections, section_table_len);3346 coff.targetStore(&coff_header.number_of_sections, section_table_len);
3347 try Node.known.section_table.resizeLeaf(3347 try Node.known.section_table.resizeLeaf(
3348 &coff.mf,
3349 gpa,3348 gpa,
3349 &coff.mf,
3350 @sizeOf(std.coff.SectionHeader) * section_table_len,3350 @sizeOf(std.coff.SectionHeader) * section_table_len,
3351 );3351 );
33523352
3353 const ni = try coff.sectionParent().addFloatingChild(&coff.mf, gpa, .{3353 const ni = try coff.sectionParent().addFloatingChild(gpa, &coff.mf, .{
3354 .alignment = coff.mf.flags.block_size,3354 .alignment = coff.mf.flags.block_size,
3355 .moved = true,3355 .moved = true,
3356 .bubbles_moved = false,3356 .bubbles_moved = false,
...@@ -3486,7 +3486,7 @@ fn pseudoSectionMapIndex(...@@ -3486,7 +3486,7 @@ fn pseudoSectionMapIndex(
34863486
3487 try coff.nodes.ensureUnusedCapacity(gpa, 1);3487 try coff.nodes.ensureUnusedCapacity(gpa, 1);
3488 try coff.symbols.ensureUnusedCapacity(gpa, 1);3488 try coff.symbols.ensureUnusedCapacity(gpa, 1);
3489 const ni = try parent.node(coff).addFloatingChild(&coff.mf, gpa, .{ .alignment = alignment });3489 const ni = try parent.node(coff).addFloatingChild(gpa, &coff.mf, .{ .alignment = alignment });
3490 const si = coff.addSymbolAssumeCapacity();3490 const si = coff.addSymbolAssumeCapacity();
3491 pseudo_section_gop.value_ptr.* = si;3491 pseudo_section_gop.value_ptr.* = si;
3492 const sym = si.get(coff);3492 const sym = si.get(coff);
...@@ -3560,7 +3560,7 @@ fn objectSectionMapIndex(...@@ -3560,7 +3560,7 @@ fn objectSectionMapIndex(
3560 }3560 }
3561 }3561 }
3562 }3562 }
3563 const ni = try parent_ni.addHeaderChildAfter(&coff.mf, gpa, prev_oni, .{3563 const ni = try parent_ni.addHeaderChildAfter(gpa, &coff.mf, prev_oni, .{
3564 .alignment = alignment,3564 .alignment = alignment,
3565 });3565 });
3566 const si = coff.addSymbolAssumeCapacity();3566 const si = coff.addSymbolAssumeCapacity();
...@@ -3579,13 +3579,13 @@ fn objectSectionMapIndex(...@@ -3579,13 +3579,13 @@ fn objectSectionMapIndex(
3579 const parent_alignment = parent_ni.alignment(&coff.mf);3579 const parent_alignment = parent_ni.alignment(&coff.mf);
3580 if (alignment.compare(.gt, parent_alignment)) {3580 if (alignment.compare(.gt, parent_alignment)) {
3581 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });3581 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
3582 try parent_ni.realign(&coff.mf, gpa, alignment);3582 try parent_ni.realign(gpa, &coff.mf, alignment);
3583 }3583 }
35843584
3585 const old_alignment = sym.ni.unwrap().?.alignment(&coff.mf);3585 const old_alignment = sym.ni.unwrap().?.alignment(&coff.mf);
3586 if (alignment.compare(.gt, old_alignment)) {3586 if (alignment.compare(.gt, old_alignment)) {
3587 log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });3587 log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });
3588 try sym.ni.unwrap().?.realign(&coff.mf, gpa, alignment);3588 try sym.ni.unwrap().?.realign(gpa, &coff.mf, alignment);
3589 }3589 }
35903590
3591 try coff.verifyParentSectionAttributes(3591 try coff.verifyParentSectionAttributes(
...@@ -3742,9 +3742,9 @@ fn addRelocAssumeCapacity(...@@ -3742,9 +3742,9 @@ fn addRelocAssumeCapacity(
3742 coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);3742 coff.targetStore(&aux_ptr.number_of_relocations, new_num_relocations);
37433743
3744 if (section.relocation_table_ni.unwrap()) |relocation_table_ni| {3744 if (section.relocation_table_ni.unwrap()) |relocation_table_ni| {
3745 try relocation_table_ni.resizeLeaf(&coff.mf, gpa, new_size);3745 try relocation_table_ni.resizeLeaf(gpa, &coff.mf, new_size);
3746 } else {3746 } else {
3747 section.relocation_table_ni = .wrap(try coff.sectionParent().addFloatingChild(&coff.mf, gpa, .{3747 section.relocation_table_ni = .wrap(try coff.sectionParent().addFloatingChild(gpa, &coff.mf, .{
3748 .size = new_size,3748 .size = new_size,
3749 .alignment = .@"2",3749 .alignment = .@"2",
3750 .moved = true,3750 .moved = true,
...@@ -4094,7 +4094,7 @@ fn loadObject(...@@ -4094,7 +4094,7 @@ fn loadObject(
4094 {4094 {
4095 // TODO: This should be deferred to an idle task (but resize it here!)4095 // TODO: This should be deferred to an idle task (but resize it here!)
4096 var nw: MappedFile.Node.Writer = undefined;4096 var nw: MappedFile.Node.Writer = undefined;
4097 member.content_ni.writer(&coff.mf, gpa, &nw);4097 member.content_ni.writer(gpa, &coff.mf, &nw);
4098 defer nw.deinit();4098 defer nw.deinit();
40994099
4100 try fr.seekTo(fl.offset);4100 try fr.seekTo(fl.offset);
...@@ -4653,7 +4653,7 @@ fn loadObject(...@@ -4653,7 +4653,7 @@ fn loadObject(
4653 if (section.parent_si == .null) continue;4653 if (section.parent_si == .null) continue;
46544654
4655 const alignment: Alignment = .fromByteUnits(section.header.flags.ALIGN.toByteUnits() orelse 1);4655 const alignment: Alignment = .fromByteUnits(section.header.flags.ALIGN.toByteUnits() orelse 1);
4656 const ni = try section.parent_si.node(coff).addFloatingChild(&coff.mf, gpa, .{4656 const ni = try section.parent_si.node(coff).addFloatingChild(gpa, &coff.mf, .{
4657 .size = alignment.forward(section.header.size_of_raw_data),4657 .size = alignment.forward(section.header.size_of_raw_data),
4658 .alignment = alignment,4658 .alignment = alignment,
4659 .moved = true,4659 .moved = true,
...@@ -5447,7 +5447,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -5447,7 +5447,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
5447 const sec_si = try coff.navSection(zcu, nav.resolved.?);5447 const sec_si = try coff.navSection(zcu, nav.resolved.?);
5448 try coff.nodes.ensureUnusedCapacity(gpa, 1);5448 try coff.nodes.ensureUnusedCapacity(gpa, 1);
5449 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);5449 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
5450 const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{5450 const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{
5451 .alignment = .fromIp(zcu.navAlignment(nav_index)),5451 .alignment = .fromIp(zcu.navAlignment(nav_index)),
5452 .moved = true,5452 .moved = true,
5453 });5453 });
...@@ -5469,7 +5469,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -5469,7 +5469,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
54695469
5470 {5470 {
5471 var nw: MappedFile.Node.Writer = undefined;5471 var nw: MappedFile.Node.Writer = undefined;
5472 ni.writer(&coff.mf, gpa, &nw);5472 ni.writer(gpa, &coff.mf, &nw);
5473 defer nw.deinit();5473 defer nw.deinit();
5474 codegen.generateSymbol(5474 codegen.generateSymbol(
5475 &coff.base,5475 &coff.base,
...@@ -5486,7 +5486,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -5486,7 +5486,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
5486 }5486 }
54875487
5488 if (nav.resolved.?.@"linksection".unwrap()) |_| {5488 if (nav.resolved.?.@"linksection".unwrap()) |_| {
5489 try ni.resizeLeaf(&coff.mf, gpa, si.get(coff).extra.size);5489 try ni.resizeLeaf(gpa, &coff.mf, si.get(coff).extra.size);
5490 }5490 }
54915491
5492 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.5492 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
...@@ -5596,7 +5596,7 @@ fn updateFuncInner(...@@ -5596,7 +5596,7 @@ fn updateFuncInner(
5596 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);5596 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
5597 const mod = zcu.navFileScope(func.owner_nav).mod.?;5597 const mod = zcu.navFileScope(func.owner_nav).mod.?;
5598 const target = &mod.resolved_target.result;5598 const target = &mod.resolved_target.result;
5599 const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{5599 const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{
5600 .alignment = switch (nav.resolved.?.@"align") {5600 .alignment = switch (nav.resolved.?.@"align") {
5601 .none => switch (mod.optimize_mode) {5601 .none => switch (mod.optimize_mode) {
5602 .debug,5602 .debug,
...@@ -5625,7 +5625,7 @@ fn updateFuncInner(...@@ -5625,7 +5625,7 @@ fn updateFuncInner(
5625 };5625 };
56265626
5627 var nw: MappedFile.Node.Writer = undefined;5627 var nw: MappedFile.Node.Writer = undefined;
5628 ni.writer(&coff.mf, gpa, &nw);5628 ni.writer(gpa, &coff.mf, &nw);
5629 defer nw.deinit();5629 defer nw.deinit();
5630 codegen.emitFunction(5630 codegen.emitFunction(
5631 &coff.base,5631 &coff.base,
...@@ -5904,8 +5904,8 @@ pub fn flush(...@@ -5904,8 +5904,8 @@ pub fn flush(
59045904
5905 const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);5905 const number_of_symbols = coff.targetLoad(&coff.headerPtr().number_of_symbols);
5906 coff.symbol_table.ni.resizeLeaf(5906 coff.symbol_table.ni.resizeLeaf(
5907 &coff.mf,
5908 comp.gpa,5907 comp.gpa,
5908 &coff.mf,
5909 number_of_symbols * std.coff.Symbol.sizeOf(),5909 number_of_symbols * std.coff.Symbol.sizeOf(),
5910 ) catch |err| switch (err) {5910 ) catch |err| switch (err) {
5911 else => |e| return e,5911 else => |e| return e,
...@@ -6072,17 +6072,18 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -6072,17 +6072,18 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
6072 };6072 };
6073 break :task;6073 break :task;
6074 }6074 }
6075 while (coff.mf.updates.pop()) |ni| {6075 while (coff.mf.updates.pop()) |ni| : (coff.mf.update_prog_node.completeOne()) {
6076 if (ni.pendingDelete(&coff.mf)) continue;
6076 const clean_moved = ni.cleanMoved(&coff.mf);6077 const clean_moved = ni.cleanMoved(&coff.mf);
6077 const clean_resized = ni.cleanResized(&coff.mf);6078 const clean_resized = ni.cleanResized(&coff.mf);
6078 if (clean_moved or clean_resized) {6079 const clean_next_moved = ni.cleanNextMoved(&coff.mf);
6079 const sub_prog_node =6080 if (!clean_moved and !clean_resized and !clean_next_moved) continue;
6080 coff.idleProgNode(tid, coff.mf.update_prog_node, coff.getNode(ni));6081 const sub_prog_node =
6081 defer sub_prog_node.end();6082 coff.idleProgNode(tid, coff.mf.update_prog_node, coff.getNode(ni));
6082 if (clean_moved) try coff.flushMoved(ni);6083 defer sub_prog_node.end();
6083 if (clean_resized) try coff.flushResized(ni);6084 if (clean_moved) try coff.flushMoved(ni);
6084 break :task;6085 if (clean_resized) try coff.flushResized(ni);
6085 } else coff.mf.update_prog_node.completeOne();6086 break :task;
6086 }6087 }
6087 while (coff.pending_members.pop()) |pending_mi| {6088 while (coff.pending_members.pop()) |pending_mi| {
6088 const sub_prog_node = coff.idleProgNode(6089 const sub_prog_node = coff.idleProgNode(
...@@ -6210,7 +6211,7 @@ fn genUav(...@@ -6210,7 +6211,7 @@ fn genUav(
6210 try coff.nodes.ensureUnusedCapacity(gpa, 1);6211 try coff.nodes.ensureUnusedCapacity(gpa, 1);
6211 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);6212 if (!isImage(coff)) try coff.symbol_table.symbols.ensureUnusedCapacity(gpa, 1);
6212 const sym = si.get(coff);6213 const sym = si.get(coff);
6213 const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{6214 const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{
6214 .alignment = .fromIp(uav_align),6215 .alignment = .fromIp(uav_align),
6215 .moved = true,6216 .moved = true,
6216 });6217 });
...@@ -6239,7 +6240,7 @@ fn genUav(...@@ -6239,7 +6240,7 @@ fn genUav(
6239 };6240 };
62406241
6241 var nw: MappedFile.Node.Writer = undefined;6242 var nw: MappedFile.Node.Writer = undefined;
6242 ni.writer(&coff.mf, gpa, &nw);6243 ni.writer(gpa, &coff.mf, &nw);
6243 defer nw.deinit();6244 defer nw.deinit();
6244 codegen.generateSymbol(6245 codegen.generateSymbol(
6245 &coff.base,6246 &coff.base,
...@@ -6503,19 +6504,19 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6503,19 +6504,19 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6503 if (!gop.found_existing) {6504 if (!gop.found_existing) {
6504 errdefer _ = coff.import_table.entries.pop();6505 errdefer _ = coff.import_table.entries.pop();
6505 try coff.import_table.ni.resizeLeaf(6506 try coff.import_table.ni.resizeLeaf(
6506 &coff.mf,
6507 gpa,6507 gpa,
6508 &coff.mf,
6508 @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),6509 @sizeOf(std.coff.ImportDirectoryEntry) * (gop.index + 2),
6509 );6510 );
6510 const import_hint_name_table_len =6511 const import_hint_name_table_len =
6511 import_hint_name_align.forward(lib_name.len + ".dll".len + 1);6512 import_hint_name_align.forward(lib_name.len + ".dll".len + 1);
6512 const idata_section_ni = coff.import_table.ni.parent(&coff.mf).unwrap().?;6513 const idata_section_ni = coff.import_table.ni.parent(&coff.mf).unwrap().?;
6513 const import_lookup_table_ni = try idata_section_ni.addFloatingChild(&coff.mf, gpa, .{6514 const import_lookup_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{
6514 .size = addr_info.size * 2,6515 .size = addr_info.size * 2,
6515 .alignment = addr_info.alignment,6516 .alignment = addr_info.alignment,
6516 .moved = true,6517 .moved = true,
6517 });6518 });
6518 const import_address_table_ni = try idata_section_ni.addFloatingChild(&coff.mf, gpa, .{6519 const import_address_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{
6519 .size = addr_info.size * 2,6520 .size = addr_info.size * 2,
6520 .alignment = addr_info.alignment,6521 .alignment = addr_info.alignment,
6521 .moved = true,6522 .moved = true,
...@@ -6529,7 +6530,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6529,7 +6530,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6529 import_address_table_sym.section_number =6530 import_address_table_sym.section_number =
6530 coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;6531 coff.getNode(idata_section_ni).object_section.symbol(coff).get(coff).section_number;
6531 }6532 }
6532 const import_hint_name_table_ni = try idata_section_ni.addFloatingChild(&coff.mf, gpa, .{6533 const import_hint_name_table_ni = try idata_section_ni.addFloatingChild(gpa, &coff.mf, .{
6533 .size = import_hint_name_table_len,6534 .size = import_hint_name_table_len,
6534 .alignment = import_hint_name_align,6535 .alignment = import_hint_name_align,
6535 .moved = true,6536 .moved = true,
...@@ -6585,9 +6586,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6585,9 +6586,9 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6585 gop.value_ptr.len = import_symbol_index + 1;6586 gop.value_ptr.len = import_symbol_index + 1;
6586 const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);6587 const new_symbol_table_size = addr_info.size * (import_symbol_index + 2);
65876588
6588 try gop.value_ptr.import_lookup_table_ni.resizeLeaf(&coff.mf, gpa, new_symbol_table_size);6589 try gop.value_ptr.import_lookup_table_ni.resizeLeaf(gpa, &coff.mf, new_symbol_table_size);
6589 const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);6590 const import_address_table_ni = gop.value_ptr.import_address_table_si.node(coff);
6590 try import_address_table_ni.resizeLeaf(&coff.mf, gpa, new_symbol_table_size);6591 try import_address_table_ni.resizeLeaf(gpa, &coff.mf, new_symbol_table_size);
65916592
6592 const opt_imp_name = import.name.toSlice(coff);6593 const opt_imp_name = import.name.toSlice(coff);
6593 const opt_import_hint_name_index = if (opt_imp_name) |imp_name| blk: {6594 const opt_import_hint_name_index = if (opt_imp_name) |imp_name| blk: {
...@@ -6595,7 +6596,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6595,7 +6596,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6595 gop.value_ptr.hint_name_len = @intCast(6596 gop.value_ptr.hint_name_len = @intCast(
6596 import_hint_name_align.forward(import_hint_name_index + 2 + imp_name.len + 1),6597 import_hint_name_align.forward(import_hint_name_index + 2 + imp_name.len + 1),
6597 );6598 );
6598 try gop.value_ptr.import_hint_name_table_ni.resizeLeaf(&coff.mf, gpa, gop.value_ptr.hint_name_len);6599 try gop.value_ptr.import_hint_name_table_ni.resizeLeaf(gpa, &coff.mf, gop.value_ptr.hint_name_len);
6599 break :blk import_hint_name_index;6600 break :blk import_hint_name_index;
6600 } else null;6601 } else null;
66016602
...@@ -6670,7 +6671,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -6670,7 +6671,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
6670 else => |tag| @panic(@tagName(tag)),6671 else => |tag| @panic(@tagName(tag)),
6671 .AMD64 => {6672 .AMD64 => {
6672 const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };6673 const init = [_]u8{ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 };
6673 const ni = try parent_sym.ni.unwrap().?.addFloatingChild(&coff.mf, gpa, .{6674 const ni = try parent_sym.ni.unwrap().?.addFloatingChild(gpa, &coff.mf, .{
6674 .alignment = alignment,6675 .alignment = alignment,
6675 .size = alignment.forward(init.len),6676 .size = alignment.forward(init.len),
6676 });6677 });
...@@ -6823,7 +6824,7 @@ fn genLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {...@@ -6823,7 +6824,7 @@ fn genLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
6823 .code => .text,6824 .code => .text,
6824 .const_data => .rdata,6825 .const_data => .rdata,
6825 };6826 };
6826 const ni = try sec_si.node(coff).addFloatingChild(&coff.mf, gpa, .{ .moved = true });6827 const ni = try sec_si.node(coff).addFloatingChild(gpa, &coff.mf, .{ .moved = true });
6827 coff.nodes.appendAssumeCapacity(switch (lazy.kind) {6828 coff.nodes.appendAssumeCapacity(switch (lazy.kind) {
6828 .code => .{ .lazy_code = @fromBackingInt(@intCast(lmr.index)) },6829 .code => .{ .lazy_code = @fromBackingInt(@intCast(lmr.index)) },
6829 .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(lmr.index)) },6830 .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(lmr.index)) },
...@@ -6843,7 +6844,7 @@ fn genLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {...@@ -6843,7 +6844,7 @@ fn genLazy(coff: *Coff, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
68436844
6844 var required_alignment: InternPool.Alignment = .none;6845 var required_alignment: InternPool.Alignment = .none;
6845 var nw: MappedFile.Node.Writer = undefined;6846 var nw: MappedFile.Node.Writer = undefined;
6846 ni.writer(&coff.mf, gpa, &nw);6847 ni.writer(gpa, &coff.mf, &nw);
6847 defer nw.deinit();6848 defer nw.deinit();
6848 codegen.generateLazySymbol(6849 codegen.generateLazySymbol(
6849 &coff.base,6850 &coff.base,
...@@ -7479,7 +7480,7 @@ fn updateExportInner(...@@ -7479,7 +7480,7 @@ fn updateExportInner(
7479 if (new_name_table_size > std.math.maxInt(@FieldType(ExportTable.Entry, "name_index")))7480 if (new_name_table_size > std.math.maxInt(@FieldType(ExportTable.Entry, "name_index")))
7480 return coff.base.comp.link_diags.fail("exports name table limit reached", .{});7481 return coff.base.comp.link_diags.fail("exports name table limit reached", .{});
74817482
7482 try coff.export_table.name_table_ni.resizeLeaf(&coff.mf, gpa, new_name_table_size);7483 try coff.export_table.name_table_ni.resizeLeaf(gpa, &coff.mf, new_name_table_size);
74837484
7484 const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf);7485 const name_table_slice = coff.export_table.name_table_ni.slice(&coff.mf);
7485 @memcpy(name_table_slice[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]);7486 @memcpy(name_table_slice[name_index..][0 .. name.len + 1], name[0 .. name.len + 1]);
...@@ -7503,20 +7504,20 @@ fn updateExportInner(...@@ -7503,20 +7504,20 @@ fn updateExportInner(
7503 // TODO: These should all be resized ahead of time to fit all exports7504 // TODO: These should all be resized ahead of time to fit all exports
7504 // after https://github.com/ziglang/zig/issues/236167505 // after https://github.com/ziglang/zig/issues/23616
7505 try coff.export_table.export_address_table_si.node(coff).resizeLeaf(7506 try coff.export_table.export_address_table_si.node(coff).resizeLeaf(
7506 &coff.mf,
7507 gpa,7507 gpa,
7508 &coff.mf,
7508 export_count * @sizeOf(std.coff.ExportAddressTableEntry),7509 export_count * @sizeOf(std.coff.ExportAddressTableEntry),
7509 );7510 );
75107511
7511 try coff.export_table.name_pointer_table_ni.resizeLeaf(7512 try coff.export_table.name_pointer_table_ni.resizeLeaf(
7512 &coff.mf,
7513 gpa,7513 gpa,
7514 &coff.mf,
7514 export_count * @sizeOf(std.coff.ExportNamePointerTableEntry),7515 export_count * @sizeOf(std.coff.ExportNamePointerTableEntry),
7515 );7516 );
75167517
7517 try coff.export_table.ordinal_table_ni.resizeLeaf(7518 try coff.export_table.ordinal_table_ni.resizeLeaf(
7518 &coff.mf,
7519 gpa,7519 gpa,
7520 &coff.mf,
7520 export_count * @sizeOf(std.coff.ExportOrdinalTableEntry),7521 export_count * @sizeOf(std.coff.ExportOrdinalTableEntry),
7521 );7522 );
75227523
src/link/Dwarf2.zig+73-43
...@@ -8,7 +8,7 @@ units: std.array_hash_map.Auto(*Module, Unit),...@@ -8,7 +8,7 @@ units: std.array_hash_map.Auto(*Module, Unit),
8/// Indices are `link.ConstPool.Index`.8/// Indices are `link.ConstPool.Index`.
9values: std.ArrayList(Value),9values: std.ArrayList(Value),
10globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),10globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global),
11funcs: std.array_hash_map.Auto(InternPool.Nav.Index, Func),11funcs: std.array_hash_map.Auto(InternPool.TrackedInst.Index, Func),
1212
13debug_abbrev: Abbrev,13debug_abbrev: Abbrev,
14frame: Frame,14frame: Frame,
...@@ -123,6 +123,7 @@ pub const Global = struct {...@@ -123,6 +123,7 @@ pub const Global = struct {
123};123};
124124
125pub const Func = struct {125pub const Func = struct {
126 owner_nav: InternPool.Nav.Index,
126 fde_ni: MappedFile.Node.Index.Optional,127 fde_ni: MappedFile.Node.Index.Optional,
127 debug_info_ni: MappedFile.Node.Index.Optional,128 debug_info_ni: MappedFile.Node.Index.Optional,
128 debug_line_ni: MappedFile.Node.Index.Optional,129 debug_line_ni: MappedFile.Node.Index.Optional,
...@@ -130,7 +131,7 @@ pub const Func = struct {...@@ -130,7 +131,7 @@ pub const Func = struct {
130 pub const Index = enum(u32) {131 pub const Index = enum(u32) {
131 _,132 _,
132133
133 pub fn nav(fi: Func.Index, dwarf: *Dwarf) InternPool.Nav.Index {134 pub fn srcInst(fi: Func.Index, dwarf: *Dwarf) InternPool.TrackedInst.Index {
134 return dwarf.funcs.keys()[@backingInt(fi)];135 return dwarf.funcs.keys()[@backingInt(fi)];
135 }136 }
136137
...@@ -195,7 +196,7 @@ pub const Str = struct {...@@ -195,7 +196,7 @@ pub const Str = struct {
195 );196 );
196 if (!gop.found_existing) {197 if (!gop.found_existing) {
197 gop.key_ptr.* = s.offset;198 gop.key_ptr.* = s.offset;
198 try ni.ensureMinimumSize(mf, gpa, s.offset + str.len + 1);199 try ni.ensureMinimumSize(gpa, mf, s.offset + str.len + 1);
199 const slice_mut = ni.slice(mf);200 const slice_mut = ni.slice(mf);
200 @memcpy(slice_mut[s.offset..][0..str.len], str);201 @memcpy(slice_mut[s.offset..][0..str.len], str);
201 s.offset += str.len;202 s.offset += str.len;
...@@ -635,9 +636,15 @@ pub const WipNav = struct {...@@ -635,9 +636,15 @@ pub const WipNav = struct {
635 const dwarf = debug.wip_nav.dwarf;636 const dwarf = debug.wip_nav.dwarf;
636 const zcu = debug.pt.zcu;637 const zcu = debug.pt.zcu;
637 const ip = &zcu.intern_pool;638 const ip = &zcu.intern_pool;
638 const nav = ip.getNav(zcu.funcInfo(debug.wip_nav.func).owner_nav);639 const func = zcu.funcInfo(debug.wip_nav.func);
640 const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?;
641 const decl = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst);
642 const nav = ip.getNav(func.owner_nav);
639 const diw = &debug.info_writer.interface;643 const diw = &debug.info_writer.interface;
640 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));644 try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func));
645 try diw.writeInt(u32, decl.src_line + 1, dwarf.endian);
646 try diw.writeUleb128(decl.src_column + 1);
647 try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private);
641 try debug.strp(nav.name.toSlice(ip));648 try debug.strp(nav.name.toSlice(ip));
642 try debug.strp(nav.fqn.toSlice(ip));649 try debug.strp(nav.fqn.toSlice(ip));
643 try dwarf.symbolAddress(&debug.info_writer, debug.wip_nav.func_si, 0);650 try dwarf.symbolAddress(&debug.info_writer, debug.wip_nav.func_si, 0);
...@@ -657,9 +664,8 @@ pub const WipNav = struct {...@@ -657,9 +664,8 @@ pub const WipNav = struct {
657 const zcu = debug.pt.zcu;664 const zcu = debug.pt.zcu;
658 const ip = &zcu.intern_pool;665 const ip = &zcu.intern_pool;
659 const func = zcu.funcInfo(debug.wip_nav.func);666 const func = zcu.funcInfo(debug.wip_nav.func);
660 const zfi = zcu.navFileScopeIndex(func.owner_nav);
661 const zf = zcu.fileByIndex(zfi);
662 const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?;667 const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?;
668 const zf = zcu.fileByIndex(inst_info.file);
663 const decl = zf.zir.?.getDeclaration(inst_info.inst);669 const decl = zf.zir.?.getDeclaration(inst_info.inst);
664 const dlw = &debug.line_writer.interface;670 const dlw = &debug.line_writer.interface;
665 try dlw.writeByte(DW.LNS.extended_op);671 try dlw.writeByte(DW.LNS.extended_op);
...@@ -678,7 +684,7 @@ pub const WipNav = struct {...@@ -678,7 +684,7 @@ pub const WipNav = struct {
678 try dwarf.symbolAddress(&debug.line_writer, debug.wip_nav.func_si, 0);684 try dwarf.symbolAddress(&debug.line_writer, debug.wip_nav.func_si, 0);
679685
680 const unit = dwarf.getUnit(zf.mod.?);686 const unit = dwarf.getUnit(zf.mod.?);
681 _, const fi = try unit.get(dwarf).getFile(zcu.gpa, unit, zfi);687 _, const fi = try unit.get(dwarf).getFile(zcu.gpa, unit, inst_info.file);
682 try dlw.writeByte(DW.LNS.set_file);688 try dlw.writeByte(DW.LNS.set_file);
683 try dlw.writeUleb128(@backingInt(fi));689 try dlw.writeUleb128(@backingInt(fi));
684690
...@@ -928,7 +934,7 @@ pub const WipNav = struct {...@@ -928,7 +934,7 @@ pub const WipNav = struct {
928 }934 }
929 fn leaveBlockInner(debug: *Debug, code_off: usize) link.EmitError!void {935 fn leaveBlockInner(debug: *Debug, code_off: usize) link.EmitError!void {
930 const dwarf = debug.wip_nav.dwarf;936 const dwarf = debug.wip_nav.dwarf;
931 const block_bytes = comptime uleb128Bytes(@backingInt(AbbrevCode.block));937 const block_bytes = comptime uleb128Size(@backingInt(AbbrevCode.block));
932 const block = debug.blocks.pop().?;938 const block = debug.blocks.pop().?;
933 if (debug.any_children)939 if (debug.any_children)
934 try debug.info_writer.interface.writeUleb128(@backingInt(AbbrevCode.null))940 try debug.info_writer.interface.writeUleb128(@backingInt(AbbrevCode.null))
...@@ -1000,7 +1006,7 @@ pub const WipNav = struct {...@@ -1000,7 +1006,7 @@ pub const WipNav = struct {
1000 code_off: usize,1006 code_off: usize,
1001 ) link.EmitError!void {1007 ) link.EmitError!void {
1002 const dwarf = debug.wip_nav.dwarf;1008 const dwarf = debug.wip_nav.dwarf;
1003 const inlined_func_bytes = comptime uleb128Bytes(@backingInt(AbbrevCode.inlined_func));1009 const inlined_func_bytes = comptime uleb128Size(@backingInt(AbbrevCode.inlined_func));
1004 const block = debug.blocks.pop().?;1010 const block = debug.blocks.pop().?;
1005 const diw = &debug.info_writer.interface;1011 const diw = &debug.info_writer.interface;
1006 if (debug.any_children)1012 if (debug.any_children)
...@@ -1029,14 +1035,14 @@ pub const WipNav = struct {...@@ -1029,14 +1035,14 @@ pub const WipNav = struct {
1029 }1035 }
1030 fn setInlineFuncInner(debug: *Debug, func: InternPool.Index) link.EmitError!void {1036 fn setInlineFuncInner(debug: *Debug, func: InternPool.Index) link.EmitError!void {
1031 const zcu = debug.pt.zcu;1037 const zcu = debug.pt.zcu;
1038 const ip = &zcu.intern_pool;
1032 const dwarf = debug.wip_nav.dwarf;1039 const dwarf = debug.wip_nav.dwarf;
1033 if (debug.wip_nav.func == func) return;1040 if (debug.wip_nav.func == func) return;
10341041
1035 const new_func_info = zcu.funcInfo(func);1042 const new_owner_nav = zcu.funcInfo(func).owner_nav;
1036
1037 const dlw = &debug.line_writer.interface;1043 const dlw = &debug.line_writer.interface;
1038 if (zcu.comp.config.incremental) {1044 if (zcu.comp.config.incremental) {
1039 const new_func = try dwarf.getFunc(new_func_info.owner_nav);1045 const new_func = try dwarf.getFunc(new_owner_nav);
1040 try dlw.writeByte(DW.LNS.extended_op);1046 try dlw.writeByte(DW.LNS.extended_op);
1041 try dlw.writeUleb128(1 + dwarf.sectionOffsetSize());1047 try dlw.writeUleb128(1 + dwarf.sectionOffsetSize());
1042 try dlw.writeByte(DW.LNE.ZIG_set_decl);1048 try dlw.writeByte(DW.LNE.ZIG_set_decl);
...@@ -1048,19 +1054,22 @@ pub const WipNav = struct {...@@ -1048,19 +1054,22 @@ pub const WipNav = struct {
1048 return;1054 return;
1049 }1055 }
10501056
1051 const old_func_info = zcu.funcInfo(debug.wip_nav.func);1057 const old_owner_nav = zcu.funcInfo(debug.wip_nav.func).owner_nav;
1052 const old_zfi = zcu.navFileScopeIndex(old_func_info.owner_nav);1058 const old_inst_info = ip.getNav(old_owner_nav).srcInst(ip).resolveFull(ip).?;
1053 const new_zfi = zcu.navFileScopeIndex(new_func_info.owner_nav);1059 const old_file = zcu.fileByIndex(old_inst_info.file);
1054 if (old_zfi != new_zfi) {1060 const new_inst_info = ip.getNav(new_owner_nav).srcInst(ip).resolveFull(ip).?;
1055 const new_ui = dwarf.getUnit(zcu.fileByIndex(new_zfi).mod.?);1061 const new_file = zcu.fileByIndex(new_inst_info.file);
1056 _, const new_fi = try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_zfi);1062 if (old_inst_info.file != new_inst_info.file) {
1063 const new_ui = dwarf.getUnit(new_file.mod.?);
1064 _, const new_fi =
1065 try debug.wip_nav.unit.get(dwarf).getFile(zcu.gpa, new_ui, new_inst_info.file);
10571066
1058 try dlw.writeByte(DW.LNS.set_file);1067 try dlw.writeByte(DW.LNS.set_file);
1059 try dlw.writeUleb128(@backingInt(new_fi));1068 try dlw.writeUleb128(@backingInt(new_fi));
1060 }1069 }
10611070
1062 const old_src_line: i33 = zcu.navSrcLine(old_func_info.owner_nav);1071 const old_src_line: i33 = old_file.zir.?.getDeclaration(old_inst_info.inst).src_line;
1063 const new_src_line: i33 = zcu.navSrcLine(new_func_info.owner_nav);1072 const new_src_line: i33 = new_file.zir.?.getDeclaration(new_inst_info.inst).src_line;
1064 if (new_src_line != old_src_line) {1073 if (new_src_line != old_src_line) {
1065 try dlw.writeByte(DW.LNS.advance_line);1074 try dlw.writeByte(DW.LNS.advance_line);
1066 try dlw.writeSleb128(new_src_line - old_src_line);1075 try dlw.writeSleb128(new_src_line - old_src_line);
...@@ -1435,10 +1444,12 @@ pub fn deinit(dwarf: *Dwarf) void {...@@ -1435,10 +1444,12 @@ pub fn deinit(dwarf: *Dwarf) void {
1435}1444}
14361445
1437pub fn initUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!void {1446pub fn initUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!void {
1438 try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count());1447 try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count() - dwarf.units.count());
1439 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| if (root.unwrap()) |root_zfi| {1448 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| if (root.unwrap()) |root_zfi| {
1449 if (!zcu.alive_files.contains(root_zfi)) continue;
1450 assert(zcu.fileByIndex(root_zfi).mod != null);
1440 const unit_gop = dwarf.units.getOrPutAssumeCapacity(mod);1451 const unit_gop = dwarf.units.getOrPutAssumeCapacity(mod);
1441 assert(!unit_gop.found_existing);1452 if (unit_gop.found_existing) continue;
1442 unit_gop.value_ptr.* = .{1453 unit_gop.value_ptr.* = .{
1443 .dirs = .empty,1454 .dirs = .empty,
1444 .files = .empty,1455 .files = .empty,
...@@ -1468,8 +1479,12 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {...@@ -1468,8 +1479,12 @@ pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index {
1468pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) link.Error!Func.Index {1479pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) link.Error!Func.Index {
1469 const comp = dwarf.lf.comp;1480 const comp = dwarf.lf.comp;
1470 const gpa = comp.gpa;1481 const gpa = comp.gpa;
1471 const func_gop = try dwarf.funcs.getOrPut(gpa, owner_nav);1482 const zcu = comp.zcu.?;
1483 const ip = &zcu.intern_pool;
1484 const src_inst = ip.getNav(owner_nav).srcInst(ip);
1485 const func_gop = try dwarf.funcs.getOrPut(gpa, src_inst);
1472 if (!func_gop.found_existing) func_gop.value_ptr.* = .{1486 if (!func_gop.found_existing) func_gop.value_ptr.* = .{
1487 .owner_nav = owner_nav,
1473 .fde_ni = .none,1488 .fde_ni = .none,
1474 .debug_info_ni = .none,1489 .debug_info_ni = .none,
1475 .debug_line_ni = .none,1490 .debug_line_ni = .none,
...@@ -1479,17 +1494,18 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) link.Error!Func.I...@@ -1479,17 +1494,18 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) link.Error!Func.I
1479 const elf = dwarf.lf.cast(.elf2).?;1494 const elf = dwarf.lf.cast(.elf2).?;
1480 try elf.nodes.ensureUnusedCapacity(gpa, 1);1495 try elf.nodes.ensureUnusedCapacity(gpa, 1);
1481 try elf.dwarf_funcs.ensureUnusedCapacity(gpa, 1);1496 try elf.dwarf_funcs.ensureUnusedCapacity(gpa, 1);
1482 const unit = dwarf.getUnit(comp.zcu.?.navFileScope(owner_nav).mod.?).get(dwarf);1497 const unit = dwarf.getUnit(zcu.fileByIndex(src_inst.resolveFile(ip)).mod.?).get(dwarf);
1483 func_gop.value_ptr.debug_info_ni =1498 func_gop.value_ptr.debug_info_ni = .wrap(elf.addNodeAssumeCapacity(
1484 .wrap(unit.debug_info_ni.unwrap().?.addFloatingChild(&elf.mf, gpa, .{1499 unit.debug_info_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{
1485 .enable_next_moved = true,1500 .enable_next_moved = true,
1486 }) catch |err| switch (err) {1501 }) catch |err| switch (err) {
1487 else => |e| return e,1502 else => |e| return e,
1488 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{1503 error.MappedFileIo => return comp.link_diags.fail("failed to write output file: {t}", .{
1489 elf.mf.io_err.?,1504 elf.mf.io_err.?,
1490 }),1505 }),
1491 });1506 },
1492 elf.nodes.appendAssumeCapacity(.{ .func_debug_info = fi });1507 .{ .func_debug_info = fi },
1508 ));
1493 elf.dwarf_funcs.addOneAssumeCapacity().* = .{1509 elf.dwarf_funcs.addOneAssumeCapacity().* = .{
1494 .frame_fde_first_symbol_reloc = .none,1510 .frame_fde_first_symbol_reloc = .none,
1495 .frame_fde_first_node_reloc = .none,1511 .frame_fde_first_node_reloc = .none,
...@@ -1503,7 +1519,9 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) link.Error!Func.I...@@ -1503,7 +1519,9 @@ pub fn getFunc(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) link.Error!Func.I
1503 return fi;1519 return fi;
1504}1520}
1505pub fn getFuncIfExists(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) ?Func.Index {1521pub fn getFuncIfExists(dwarf: *Dwarf, owner_nav: InternPool.Nav.Index) ?Func.Index {
1506 return @fromBackingInt(@intCast(dwarf.funcs.getIndex(owner_nav) orelse return null));1522 const ip = &dwarf.lf.comp.zcu.?.intern_pool;
1523 return @fromBackingInt(@intCast(dwarf.funcs.getIndex(ip.getNav(owner_nav).srcInst(ip)) orelse
1524 return null));
1507}1525}
15081526
1509pub fn unitLengthSize(dwarf: *Dwarf) usize {1527pub fn unitLengthSize(dwarf: *Dwarf) usize {
...@@ -1797,20 +1815,20 @@ pub fn genDebugLineHeader(...@@ -1797,20 +1815,20 @@ pub fn genDebugLineHeader(
1797 try dlhw.writeUleb128(DW.FORM.line_strp);1815 try dlhw.writeUleb128(DW.FORM.line_strp);
1798 try dlhw.writeUleb128(unit.files.count());1816 try dlhw.writeUleb128(unit.files.count());
1799 for (unit.files.keys()) |zfi| {1817 for (unit.files.keys()) |zfi| {
1800 const zcu_file = zcu.fileByIndex(zfi);1818 const zf = zcu.fileByIndex(zfi);
1801 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zcu_file.sub_file_path);1819 try dwarf.strp(&dwarf.debug_line_str, dlh_nw, zf.sub_file_path);
1802 switch (directory_index_form) {1820 switch (directory_index_form) {
1803 else => unreachable,1821 else => unreachable,
1804 .data1 => try dlhw.writeByte(0),1822 .data1 => try dlhw.writeByte(0),
1805 .data2 => try dlhw.writeInt(u16, 0, dwarf.endian),1823 .data2 => try dlhw.writeInt(u16, 0, dwarf.endian),
1806 .udata => try dlhw.writeUleb128(0),1824 .udata => try dlhw.writeUleb128(0),
1807 }1825 }
1808 try dlhw.writeInt(i64, @truncate(zcu_file.stat.mtime.nanoseconds), dwarf.endian);1826 try dlhw.writeInt(i64, @truncate(zf.stat.mtime.nanoseconds), dwarf.endian);
1809 try dlhw.writeInt(u64, zcu_file.stat.size, dwarf.endian);1827 try dlhw.writeInt(u64, zf.stat.size, dwarf.endian);
1810 try dwarf.strp(1828 try dwarf.strp(
1811 &dwarf.debug_line_str,1829 &dwarf.debug_line_str,
1812 dlh_nw,1830 dlh_nw,
1813 if (zcu_file.is_builtin) zcu_file.source.? else "",1831 if (zf.is_builtin) zf.source.? else "",
1814 );1832 );
1815 }1833 }
1816 switch (dwarf.format) {1834 switch (dwarf.format) {
...@@ -1892,6 +1910,18 @@ pub fn genDebugRnglists(...@@ -1892,6 +1910,18 @@ pub fn genDebugRnglists(
1892 try drw.writeByte(DW.RLE.end_of_list);1910 try drw.writeByte(DW.RLE.end_of_list);
1893}1911}
18941912
1913pub fn updateLineNumber(
1914 dwarf: *Dwarf,
1915 zcu: *Zcu,
1916 src_inst: InternPool.TrackedInst.Index,
1917 debug_info: []u8,
1918) void {
1919 const inst_info = src_inst.resolveFull(&zcu.intern_pool).?;
1920 assert(inst_info.inst != .main_struct_inst);
1921 const src_line = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst).src_line;
1922 std.mem.writeInt(u32, debug_info[AbbrevCode.decl_bytes..][0..4], src_line + 1, dwarf.endian);
1923}
1924
1895fn refAbbrevCodeIfExists(1925fn refAbbrevCodeIfExists(
1896 dwarf: *Dwarf,1926 dwarf: *Dwarf,
1897 abbrev_code: AbbrevCode,1927 abbrev_code: AbbrevCode,
...@@ -1911,7 +1941,7 @@ fn refAbbrevCode(...@@ -1911,7 +1941,7 @@ fn refAbbrevCode(
1911 const elf = dwarf.lf.cast(.elf2).?;1941 const elf = dwarf.lf.cast(.elf2).?;
1912 const comp = elf.base.comp;1942 const comp = elf.base.comp;
1913 var nw: MappedFile.Node.Writer = undefined;1943 var nw: MappedFile.Node.Writer = undefined;
1914 dwarf.debug_abbrev.ni.unwrap().?.writer(&elf.mf, comp.gpa, &nw);1944 dwarf.debug_abbrev.ni.unwrap().?.writer(comp.gpa, &elf.mf, &nw);
1915 defer nw.deinit();1945 defer nw.deinit();
1916 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);1946 const abbrev = AbbrevCode.abbrevs.get(abbrev_code);
1917 const daw = &nw.interface;1947 const daw = &nw.interface;
...@@ -2133,11 +2163,11 @@ pub const AbbrevCode = enum {...@@ -2133,11 +2163,11 @@ pub const AbbrevCode = enum {
2133 comptime_value_elem_runtime_bits,2163 comptime_value_elem_runtime_bits,
2134 comptime_value_elem_comptime_state,2164 comptime_value_elem_comptime_state,
21352165
2136 const decl_bytes = uleb128Bytes(@backingInt(AbbrevCode.decl_instance_extern_func));2166 const decl_bytes = uleb128Size(@backingInt(AbbrevCode.decl_instance_extern_func));
2137 comptime {2167 comptime {
2138 assert(uleb128Bytes(@backingInt(AbbrevCode.pad_1)) == 1);2168 assert(uleb128Size(@backingInt(AbbrevCode.pad_1)) == 1);
2139 assert(uleb128Bytes(@backingInt(AbbrevCode.pad_n)) == 1);2169 assert(uleb128Size(@backingInt(AbbrevCode.pad_n)) == 1);
2140 assert(uleb128Bytes(@backingInt(AbbrevCode.decl_alias)) == decl_bytes);2170 assert(uleb128Size(@backingInt(AbbrevCode.decl_alias)) == decl_bytes);
2141 }2171 }
21422172
2143 const Attr = struct {2173 const Attr = struct {
...@@ -2145,7 +2175,7 @@ pub const AbbrevCode = enum {...@@ -2145,7 +2175,7 @@ pub const AbbrevCode = enum {
2145 DeclValEnum(DW.FORM),2175 DeclValEnum(DW.FORM),
2146 };2176 };
2147 const decl_abbrev_common_attrs = &[_]Attr{2177 const decl_abbrev_common_attrs = &[_]Attr{
2148 .{ .ZIG_parent, .ref_addr },2178 //.{ .ZIG_parent, .ref_addr },
2149 .{ .decl_line, .data4 },2179 .{ .decl_line, .data4 },
2150 .{ .decl_column, .udata },2180 .{ .decl_column, .udata },
2151 .{ .accessibility, .data1 },2181 .{ .accessibility, .data1 },
...@@ -2292,7 +2322,7 @@ pub const AbbrevCode = enum {...@@ -2292,7 +2322,7 @@ pub const AbbrevCode = enum {
2292 .decl_func = .{2322 .decl_func = .{
2293 .tag = .subprogram,2323 .tag = .subprogram,
2294 .children = true,2324 .children = true,
2295 .attrs = decl_abbrev_common_attrs[4..] ++ .{2325 .attrs = decl_abbrev_common_attrs ++ .{
2296 .{ .linkage_name, .strp },2326 .{ .linkage_name, .strp },
2297 //.{ .type, .ref_addr },2327 //.{ .type, .ref_addr },
2298 .{ .low_pc, .addr },2328 .{ .low_pc, .addr },
...@@ -3197,14 +3227,14 @@ pub const AbbrevCode = enum {...@@ -3197,14 +3227,14 @@ pub const AbbrevCode = enum {
3197 });3227 });
3198};3228};
31993229
3200pub fn uleb128Bytes(value: anytype) u32 {3230pub fn uleb128Size(value: anytype) u32 {
3201 var buf: [64]u8 = undefined;3231 var buf: [64]u8 = undefined;
3202 var dw: Writer.Discarding = .init(&buf);3232 var dw: Writer.Discarding = .init(&buf);
3203 dw.writer.writeUleb128(value) catch unreachable;3233 dw.writer.writeUleb128(value) catch unreachable;
3204 return @intCast(dw.fullCount());3234 return @intCast(dw.fullCount());
3205}3235}
32063236
3207pub fn sleb128Bytes(value: anytype) u32 {3237pub fn sleb128Size(value: anytype) u32 {
3208 var buf: [64]u8 = undefined;3238 var buf: [64]u8 = undefined;
3209 var dw: Writer.Discarding = .init(&buf);3239 var dw: Writer.Discarding = .init(&buf);
3210 dw.writer.writeSleb128(value) catch unreachable;3240 dw.writer.writeSleb128(value) catch unreachable;
src/link/Elf2.zig+394-340
...@@ -253,6 +253,8 @@ input_prog_node: std.Progress.Node,...@@ -253,6 +253,8 @@ input_prog_node: std.Progress.Node,
253const Error = link.Error || error{MappedFileIo};253const Error = link.Error || error{MappedFileIo};
254254
255const Node = union(enum) {255const Node = union(enum) {
256 deleted,
257
256 /// Only used when emitting a static library.258 /// Only used when emitting a static library.
257 ///259 ///
258 /// Contains a header node which is an `.archive_header`.260 /// Contains a header node which is an `.archive_header`.
...@@ -642,7 +644,7 @@ const Section = struct {...@@ -642,7 +644,7 @@ const Section = struct {
642 }644 }
643 const ni = shndx.get(elf).ni;645 const ni = shndx.get(elf).ni;
644 if (min_align.compare(.gt, ni.alignment(&elf.mf))) {646 if (min_align.compare(.gt, ni.alignment(&elf.mf))) {
645 try ni.realign(&elf.mf, elf.base.comp.gpa, min_align);647 try ni.realign(elf.base.comp.gpa, &elf.mf, min_align);
646 }648 }
647 switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) {649 switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) {
648 .elf => {},650 .elf => {},
...@@ -675,7 +677,7 @@ const Section = struct {...@@ -675,7 +677,7 @@ const Section = struct {
675 break :need_size cur_size + need_additional * ent_size;677 break :need_size cur_size + need_additional * ent_size;
676 },678 },
677 };679 };
678 try node.ensureMinimumSize(&elf.mf, elf.base.comp.gpa, need_size);680 try node.ensureMinimumSize(elf.base.comp.gpa, &elf.mf, need_size);
679 }681 }
680682
681 /// Asserts that `rela_shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at683 /// Asserts that `rela_shndx` is a `SHT_RELA` section and deletes the `ElfN.Rela` entry at
...@@ -2094,7 +2096,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe...@@ -2094,7 +2096,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe
2094 const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) {2096 const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) {
2095 inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),2097 inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym),
2096 };2098 };
2097 try Section.Index.symtab.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_node_size);2099 try Section.Index.symtab.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_node_size);
2098 }2100 }
20992101
2100 switch (kind) {2102 switch (kind) {
...@@ -2117,7 +2119,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe...@@ -2117,7 +2119,7 @@ fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe
2117 const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size));2119 const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size));
21182120
2119 const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size;2121 const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size;
2120 try elf.shndx.dynsym.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, dynsym_need_size);2122 try elf.shndx.dynsym.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, dynsym_need_size);
21212123
2122 try elf.ensureDynsymHashCapacity(dynsym_cur_len + len);2124 try elf.ensureDynsymHashCapacity(dynsym_cur_len + len);
21232125
...@@ -2150,7 +2152,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void {...@@ -2150,7 +2152,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void {
2150 // We don't need to add any buckets, but we still need to make sure the section is large2152 // We don't need to add any buckets, but we still need to make sure the section is large
2151 // enough to fit `max_dynsym_count` chains.2153 // enough to fit `max_dynsym_count` chains.
2152 const need_size = @sizeOf(info.Header()) + (nbucket + max_dynsym_count) * 4;2154 const need_size = @sizeOf(info.Header()) + (nbucket + max_dynsym_count) * 4;
2153 try elf.shndx.hash.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size);2155 try elf.shndx.hash.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size);
2154 return;2156 return;
2155 }2157 }
2156 // We need more buckets, so we'll have to rebuild the hash table.2158 // We need more buckets, so we'll have to rebuild the hash table.
...@@ -2162,7 +2164,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void {...@@ -2162,7 +2164,7 @@ fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void {
21622164
2163 {2165 {
2164 const need_size = @sizeOf(info.Header()) + (new_nbucket + max_dynsym_count) * 4;2166 const need_size = @sizeOf(info.Header()) + (new_nbucket + max_dynsym_count) * 4;
2165 try elf.shndx.hash.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size);2167 try elf.shndx.hash.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size);
2166 }2168 }
21672169
2168 elf.mf.nodes_lock.lock();2170 elf.mf.nodes_lock.lock();
...@@ -2306,19 +2308,19 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void {...@@ -2306,19 +2308,19 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void {
2306 // Ensure the `.plt` section's node is big enough:2308 // Ensure the `.plt` section's node is big enough:
2307 {2309 {
2308 const need_size: usize = plt.entry_size * (1 + need_plt_count);2310 const need_size: usize = plt.entry_size * (1 + need_plt_count);
2309 try elf.shndx.plt.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size);2311 try elf.shndx.plt.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size);
2310 }2312 }
23112313
2312 // If there is a `.got.plt` section, ensure its node is big enough2314 // If there is a `.got.plt` section, ensure its node is big enough
2313 if (plt.got_plt) |got_plt| {2315 if (plt.got_plt) |got_plt| {
2314 const need_size: usize = elf.targetPtrSize() * (got_plt.header_entries + need_plt_count);2316 const need_size: usize = elf.targetPtrSize() * (got_plt.header_entries + need_plt_count);
2315 try elf.shndx.got_plt.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size);2317 try elf.shndx.got_plt.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size);
2316 }2318 }
23172319
2318 // If there is a `.plt.sec` section, ensure its node is big enough2320 // If there is a `.plt.sec` section, ensure its node is big enough
2319 if (plt.plt_sec) |plt_sec| {2321 if (plt.plt_sec) |plt_sec| {
2320 const need_size: usize = plt_sec.entry_size * need_plt_count;2322 const need_size: usize = plt_sec.entry_size * need_plt_count;
2321 try elf.shndx.plt_sec.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_size);2323 try elf.shndx.plt_sec.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_size);
2322 }2324 }
2323}2325}
2324/// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at2326/// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at
...@@ -3244,6 +3246,7 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum {...@@ -3244,6 +3246,7 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum {
32443246
3245pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {3247pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
3246 const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) {3248 const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) {
3249 .deleted,
3247 .archive,3250 .archive,
3248 .archive_header,3251 .archive_header,
3249 .archive_input_member,3252 .archive_input_member,
...@@ -3305,7 +3308,13 @@ fn lazySymbolInner(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol) Err...@@ -3305,7 +3308,13 @@ fn lazySymbolInner(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol) Err
3305 .code => .{ .text, .FUNC },3308 .code => .{ .text, .FUNC },
3306 .const_data => .{ .rodata, .OBJECT },3309 .const_data => .{ .rodata, .OBJECT },
3307 };3310 };
3308 const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{});3311 const node = elf.addNodeAssumeCapacity(
3312 try shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}),
3313 switch (lazy.kind) {
3314 .code => .{ .lazy_code = @fromBackingInt(@intCast(gop.index)) },
3315 .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(gop.index)) },
3316 },
3317 );
3309 var name_buf: [std.fmt.count("__lazy_const_data_{d}", .{std.math.maxInt(u32)})]u8 = undefined;3318 var name_buf: [std.fmt.count("__lazy_const_data_{d}", .{std.math.maxInt(u32)})]u8 = undefined;
3310 const name = std.mem.print(&name_buf, "__lazy_{t}_{d}", .{ lazy.kind, gop.index }) catch3319 const name = std.mem.print(&name_buf, "__lazy_{t}_{d}", .{ lazy.kind, gop.index }) catch
3311 unreachable;3320 unreachable;
...@@ -3321,10 +3330,6 @@ fn lazySymbolInner(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol) Err...@@ -3321,10 +3330,6 @@ fn lazySymbolInner(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol) Err
3321 .first_symbol_reloc = .none,3330 .first_symbol_reloc = .none,
3322 .first_got_reloc = .none,3331 .first_got_reloc = .none,
3323 };3332 };
3324 elf.nodes.appendAssumeCapacity(switch (lazy.kind) {
3325 .code => .{ .lazy_code = @fromBackingInt(@intCast(gop.index)) },
3326 .const_data => .{ .lazy_const_data = @fromBackingInt(@intCast(gop.index)) },
3327 });
3328 elf.base.comp.link_prog_node.increaseEstimatedTotalItems(1);3333 elf.base.comp.link_prog_node.increaseEstimatedTotalItems(1);
3329 }3334 }
3330 const s: Symbol.Id = .local(gop.value_ptr.lsi);3335 const s: Symbol.Id = .local(gop.value_ptr.lsi);
...@@ -3583,7 +3588,7 @@ const StringTable = struct {...@@ -3583,7 +3588,7 @@ const StringTable = struct {
3583 break :size .{ old_size, new_size };3588 break :size .{ old_size, new_size };
3584 },3589 },
3585 };3590 };
3586 try ni.ensureMinimumSize(&elf.mf, gpa, new_size);3591 try ni.ensureMinimumSize(gpa, &elf.mf, new_size);
3587 const slice = ni.slice(&elf.mf)[old_size..];3592 const slice = ni.slice(&elf.mf)[old_size..];
3588 @memcpy(slice[0..key.len], key);3593 @memcpy(slice[0..key.len], key);
3589 slice[key.len] = 0;3594 slice[key.len] = 0;
...@@ -4014,21 +4019,21 @@ fn initHeaders(...@@ -4014,21 +4019,21 @@ fn initHeaders(
4014 try elf.symtab.ensureTotalCapacity(gpa, 1);4019 try elf.symtab.ensureTotalCapacity(gpa, 1);
40154020
4016 if (is_archive) {4021 if (is_archive) {
4017 elf.nodes.appendAssumeCapacity(.archive);4022 const archive_ni = elf.addNodeAssumeCapacity(.root, .archive);
40184023
4019 const archive_ni: MappedFile.Node.Index = .root;4024 const archive_header_ni = elf.addNodeAssumeCapacity(
40204025 try archive_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
4021 const archive_header_ni = try archive_ni.addOnlyHeaderChild(&elf.mf, gpa, .{4026 // We intentionally do not set `.alignment = .@"2"` here, because the string table data
4022 // We intentionally do not set `.alignment = .@"2"` here, because the string table data4027 // in this node does not need to have an aligned length. (This node's offset is aligned
4023 // in this node does not need to have an aligned length. (This node's offset is aligned4028 // regardless by virtue of it being a header.)
4024 // regardless by virtue of it being a header.)4029 .size = std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr),
4025 .size = std.elf.ARMAG.len + @sizeOf(std.elf.ar_hdr),4030 // The archive header uses 'next_moved' events to resize the "//" member, so that it
4026 // The archive header uses 'next_moved' events to resize the "//" member, so that it4031 // absorbs all padding between `archive_header_ni` and the actual object file members.
4027 // absorbs all padding between `archive_header_ni` and the actual object file members.4032 .enable_next_moved = true,
4028 .enable_next_moved = true,4033 .next_moved = true,
4029 .next_moved = true,4034 }),
4030 });4035 .archive_header,
4031 elf.nodes.appendAssumeCapacity(.archive_header);4036 );
4032 const archive_header_slice = archive_header_ni.slice(&elf.mf);4037 const archive_header_slice = archive_header_ni.slice(&elf.mf);
4033 @memcpy(archive_header_slice[0..std.elf.ARMAG.len], std.elf.ARMAG);4038 @memcpy(archive_header_slice[0..std.elf.ARMAG.len], std.elf.ARMAG);
4034 const strtab_ar_hdr: *std.elf.ar_hdr = @ptrCast(archive_header_slice[std.elf.ARMAG.len..]);4039 const strtab_ar_hdr: *std.elf.ar_hdr = @ptrCast(archive_header_slice[std.elf.ARMAG.len..]);
...@@ -4042,18 +4047,19 @@ fn initHeaders(...@@ -4042,18 +4047,19 @@ fn initHeaders(
4042 .ar_fmag = std.elf.ARFMAG.*,4047 .ar_fmag = std.elf.ARFMAG.*,
4043 };4048 };
40444049
4045 elf.ni.elf = try archive_ni.addOnlyFooterChild(&elf.mf, gpa, .{4050 elf.ni.elf = elf.addNodeAssumeCapacity(try archive_ni.addOnlyFooterChild(gpa, &elf.mf, .{
4046 .alignment = node_block_align.max(.@"2"),4051 .alignment = node_block_align.max(.@"2"),
4047 .bubbles_moved = false,4052 .bubbles_moved = false,
4048 .resized = true, // ensure that this node's `ar_hdr.ar_size` is updated at least once4053 .resized = true, // ensure that this node's `ar_hdr.ar_size` is updated at least once
4049 });4054 }), .elf);
4050 elf.nodes.appendAssumeCapacity(.elf);
40514055
4052 const elf_ar_hdr_ni = try archive_ni.addFooterChildBefore(&elf.mf, gpa, .wrap(elf.ni.elf), .{4056 const elf_ar_hdr_ni = elf.addNodeAssumeCapacity(
4053 .alignment = .@"2",4057 try archive_ni.addFooterChildBefore(gpa, &elf.mf, .wrap(elf.ni.elf), .{
4054 .size = @sizeOf(std.elf.ar_hdr),4058 .alignment = .@"2",
4055 });4059 .size = @sizeOf(std.elf.ar_hdr),
4056 elf.nodes.appendAssumeCapacity(.archive_elf_member_header);4060 }),
4061 .archive_elf_member_header,
4062 );
40574063
4058 // Must be populated before we call `populateArchiveMemberName` below.4064 // Must be populated before we call `populateArchiveMemberName` below.
4059 elf.archive = .{4065 elf.archive = .{
...@@ -4079,10 +4085,7 @@ fn initHeaders(...@@ -4079,10 +4085,7 @@ fn initHeaders(
4079 defer gpa.free(zcu_member_name);4085 defer gpa.free(zcu_member_name);
4080 // After this call returns, `elf_ar_hdr` is invalidated.4086 // After this call returns, `elf_ar_hdr` is invalidated.
4081 try elf.populateArchiveMemberName(elf_ar_hdr, zcu_member_name);4087 try elf.populateArchiveMemberName(elf_ar_hdr, zcu_member_name);
4082 } else {4088 } else elf.ni.elf = elf.addNodeAssumeCapacity(.root, .elf);
4083 elf.ni.elf = .root;
4084 elf.nodes.appendAssumeCapacity(.elf);
4085 }
40864089
4087 const entsize: struct { ph: u32, sh: u32 } = switch (class) {4090 const entsize: struct { ph: u32, sh: u32 } = switch (class) {
4088 .NONE, _ => unreachable,4091 .NONE, _ => unreachable,
...@@ -4098,69 +4101,65 @@ fn initHeaders(...@@ -4098,69 +4101,65 @@ fn initHeaders(
4098 if (@"type" != .REL) {4101 if (@"type" != .REL) {
4099 // This node will contain the ehdr, which must be at the start of the ELF file, so this4102 // This node will contain the ehdr, which must be at the start of the ELF file, so this
4100 // node must itself be a header of the `.elf` node.4103 // node must itself be a header of the `.elf` node.
4101 elf.ni.rodata = try elf.ni.elf.addOnlyHeaderChild(&elf.mf, gpa, .{4104 elf.ni.rodata = elf.addNodeAssumeCapacity(try elf.ni.elf.addOnlyHeaderChild(gpa, &elf.mf, .{
4102 // Must be at least `addr_align` for `elf.ni.phdr` to be placed inside this node4105 // Must be at least `addr_align` for `elf.ni.phdr` to be placed inside this node
4103 .alignment = node_block_align.max(addr_align),4106 .alignment = node_block_align.max(addr_align),
4104 .moved = true,4107 .moved = true,
4105 .bubbles_moved = false,4108 .bubbles_moved = false,
4106 });4109 }), .{ .segment = phndx.rodata });
4107 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata });
4108 elf.phdrs.items[phndx.rodata] = .wrap(elf.ni.rodata);4110 elf.phdrs.items[phndx.rodata] = .wrap(elf.ni.rodata);
41094111
4110 elf.ni.phdr = try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{4112 elf.ni.phdr = elf.addNodeAssumeCapacity(try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{
4111 .size = @as(u64, phnum) * entsize.ph,4113 .size = @as(u64, phnum) * entsize.ph,
4112 .alignment = addr_align, // keep in sync with `elf.ni.rodata` alignment above4114 .alignment = addr_align, // keep in sync with `elf.ni.rodata` alignment above
4113 .moved = true,4115 .moved = true,
4114 .resized = true,4116 .resized = true,
4115 .bubbles_moved = false,4117 .bubbles_moved = false,
4116 });4118 }), .{ .segment = phndx.phdr });
4117 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr });
4118 elf.phdrs.items[phndx.phdr] = .wrap(elf.ni.phdr);4119 elf.phdrs.items[phndx.phdr] = .wrap(elf.ni.phdr);
41194120
4120 elf.ni.text = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{4121 elf.ni.text = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{
4121 .alignment = node_block_align,4122 .alignment = node_block_align,
4122 .moved = true,4123 .moved = true,
4123 .bubbles_moved = false,4124 .bubbles_moved = false,
4124 });4125 }), .{ .segment = phndx.text });
4125 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text });
4126 elf.phdrs.items[phndx.text] = .wrap(elf.ni.text);4126 elf.phdrs.items[phndx.text] = .wrap(elf.ni.text);
41274127
4128 elf.ni.data = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{4128 elf.ni.data = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{
4129 // Must be at least `addr_align` for `elf.ni.data_rel_ro` to be placed inside this node4129 // Must be at least `addr_align` for `elf.ni.data_rel_ro` to be placed inside this node
4130 .alignment = node_block_align.max(addr_align),4130 .alignment = node_block_align.max(addr_align),
4131 .moved = true,4131 .moved = true,
4132 .bubbles_moved = false,4132 .bubbles_moved = false,
4133 });4133 }), .{ .segment = phndx.data });
4134 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data });
4135 elf.phdrs.items[phndx.data] = .wrap(elf.ni.data);4134 elf.phdrs.items[phndx.data] = .wrap(elf.ni.data);
41364135
4137 if (plt.got_plt == null) {4136 if (plt.got_plt == null) elf.phdrs.items[phndx.plt] = .wrap(elf.addNodeAssumeCapacity(
4138 const plt_ni = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{4137 try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{
4139 .alignment = node_block_align,4138 .alignment = node_block_align,
4140 .moved = true,4139 .moved = true,
4141 .bubbles_moved = false,4140 .bubbles_moved = false,
4142 });4141 }),
4143 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.plt });4142 .{ .segment = phndx.plt },
4144 elf.phdrs.items[phndx.plt] = .wrap(plt_ni);4143 ));
4145 }
41464144
4147 elf.ni.data_rel_ro = try elf.ni.data.addFloatingChild(&elf.mf, gpa, .{4145 elf.ni.data_rel_ro = elf.addNodeAssumeCapacity(try elf.ni.data.addFloatingChild(gpa, &elf.mf, .{
4148 // Must be at least `addr_align` for the `PT_DYNAMIC` node to be placed inside this one4146 // Must be at least `addr_align` for the `PT_DYNAMIC` node to be placed inside this one
4149 // later (if `have_dynamic_section`). Keep in sync with `elf.ni.data` alignment above.4147 // later (if `have_dynamic_section`). Keep in sync with `elf.ni.data` alignment above.
4150 .alignment = node_block_align.max(addr_align),4148 .alignment = node_block_align.max(addr_align),
4151 .moved = true,4149 .moved = true,
4152 .bubbles_moved = false,4150 .bubbles_moved = false,
4153 });4151 }), .{ .segment = phndx.relro });
4154 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });
4155 elf.phdrs.items[phndx.relro] = .wrap(elf.ni.data_rel_ro);4152 elf.phdrs.items[phndx.relro] = .wrap(elf.ni.data_rel_ro);
41564153
4157 if (comp.config.any_non_single_threaded) {4154 if (comp.config.any_non_single_threaded) {
4158 elf.ni.tls = .wrap(try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{4155 elf.ni.tls = .wrap(elf.addNodeAssumeCapacity(
4159 .alignment = node_block_align,4156 try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{
4160 .moved = true,4157 .alignment = node_block_align,
4161 .bubbles_moved = false,4158 .moved = true,
4162 }));4159 .bubbles_moved = false,
4163 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.tls });4160 }),
4161 .{ .segment = phndx.tls },
4162 ));
4164 elf.phdrs.items[phndx.tls] = elf.ni.tls;4163 elf.phdrs.items[phndx.tls] = elf.ni.tls;
4165 }4164 }
41664165
...@@ -4184,11 +4183,10 @@ fn initHeaders(...@@ -4184,11 +4183,10 @@ fn initHeaders(
4184 .REL => elf.ni.elf,4183 .REL => elf.ni.elf,
4185 .DYN, .EXEC => elf.ni.rodata,4184 .DYN, .EXEC => elf.ni.rodata,
4186 };4185 };
4187 elf.ni.ehdr = try parent_ni.addOnlyHeaderChild(&elf.mf, gpa, .{4186 elf.ni.ehdr = elf.addNodeAssumeCapacity(try parent_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
4188 .size = @sizeOf(ElfN.Ehdr),4187 .size = @sizeOf(ElfN.Ehdr),
4189 .alignment = addr_align,4188 .alignment = addr_align,
4190 });4189 }), .ehdr);
4191 elf.nodes.appendAssumeCapacity(.ehdr);
41924190
4193 const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf)));4191 const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf)));
4194 ehdr.ident = .{4192 ehdr.ident = .{
...@@ -4238,13 +4236,12 @@ fn initHeaders(...@@ -4238,13 +4236,12 @@ fn initHeaders(
4238 },4236 },
4239 }4237 }
42404238
4241 elf.ni.shdr = try elf.ni.elf.addFloatingChild(&elf.mf, gpa, .{4239 elf.ni.shdr = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{
4242 .size = node_block_align.forward(1 * entsize.sh), // as above, only the SHN_UNDEF initially4240 .size = node_block_align.forward(1 * entsize.sh), // as above, only the SHN_UNDEF initially
4243 .alignment = addr_align.max(node_block_align),4241 .alignment = addr_align.max(node_block_align),
4244 .moved = true,4242 .moved = true,
4245 .resized = true,4243 .resized = true,
4246 });4244 }), .shdr);
4247 elf.nodes.appendAssumeCapacity(.shdr);
42484245
4249 switch (class) {4246 switch (class) {
4250 .NONE, _ => unreachable,4247 .NONE, _ => unreachable,
...@@ -4298,18 +4295,16 @@ fn initHeaders(...@@ -4298,18 +4295,16 @@ fn initHeaders(
4298 .@"align" = @intCast(elf.ni.phdr.alignment(&elf.mf).toByteUnits()),4295 .@"align" = @intCast(elf.ni.phdr.alignment(&elf.mf).toByteUnits()),
4299 };4296 };
43004297
4301 if (maybe_interp) |_| {4298 if (maybe_interp) |_| phdr[phndx.interp] = .{
4302 phdr[phndx.interp] = .{4299 .type = .INTERP,
4303 .type = .INTERP,4300 .offset = 0,
4304 .offset = 0,4301 .vaddr = 0,
4305 .vaddr = 0,4302 .paddr = 0,
4306 .paddr = 0,4303 .filesz = 0,
4307 .filesz = 0,4304 .memsz = 0,
4308 .memsz = 0,4305 .flags = .{ .R = true },
4309 .flags = .{ .R = true },4306 .@"align" = 1,
4310 .@"align" = 1,4307 };
4311 };
4312 }
43134308
4314 phdr[phndx.rodata] = .{4309 phdr[phndx.rodata] = .{
4315 .type = .NULL,4310 .type = .NULL,
...@@ -4567,13 +4562,15 @@ fn initHeaders(...@@ -4567,13 +4562,15 @@ fn initHeaders(
4567 .node_align = node_block_align,4562 .node_align = node_block_align,
4568 });4563 });
4569 if (maybe_interp) |interp| {4564 if (maybe_interp) |interp| {
4570 const interp_ni = try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{4565 const interp_ni = elf.addNodeAssumeCapacity(
4571 .size = interp.len + 1,4566 try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{
4572 .moved = true,4567 .size = interp.len + 1,
4573 .resized = true,4568 .moved = true,
4574 .bubbles_moved = false,4569 .resized = true,
4575 });4570 .bubbles_moved = false,
4576 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.interp });4571 }),
4572 .{ .segment = phndx.interp },
4573 );
4577 elf.phdrs.items[phndx.interp] = .wrap(interp_ni);4574 elf.phdrs.items[phndx.interp] = .wrap(interp_ni);
45784575
4579 const sec_interp_shndx = try elf.addSection(interp_ni, .{4576 const sec_interp_shndx = try elf.addSection(interp_ni, .{
...@@ -4588,12 +4585,14 @@ fn initHeaders(...@@ -4588,12 +4585,14 @@ fn initHeaders(
4588 }4585 }
4589 if (have_dynamic) {4586 if (have_dynamic) {
4590 assert(elf.ni.data_rel_ro.alignment(&elf.mf).compare(.gte, addr_align));4587 assert(elf.ni.data_rel_ro.alignment(&elf.mf).compare(.gte, addr_align));
4591 const dynamic_ni = try elf.ni.data_rel_ro.addFloatingChild(&elf.mf, gpa, .{4588 const dynamic_ni = elf.addNodeAssumeCapacity(
4592 .alignment = addr_align,4589 try elf.ni.data_rel_ro.addFloatingChild(gpa, &elf.mf, .{
4593 .moved = true,4590 .alignment = addr_align,
4594 .bubbles_moved = false,4591 .moved = true,
4595 });4592 .bubbles_moved = false,
4596 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.dynamic });4593 }),
4594 .{ .segment = phndx.dynamic },
4595 );
4597 elf.phdrs.items[phndx.dynamic] = .wrap(dynamic_ni);4596 elf.phdrs.items[phndx.dynamic] = .wrap(dynamic_ni);
45984597
4599 const dynstr_shndx = try elf.addSection(elf.ni.rodata, .{4598 const dynstr_shndx = try elf.addSection(elf.ni.rodata, .{
...@@ -4778,13 +4777,15 @@ fn initHeaders(...@@ -4778,13 +4777,15 @@ fn initHeaders(
4778 }4777 }
4779 }4778 }
4780 if (have_eh_frame) {4779 if (have_eh_frame) {
4781 elf.ni.gnu_eh_frame = .wrap(try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{4780 elf.ni.gnu_eh_frame = .wrap(elf.addNodeAssumeCapacity(
4782 .size = @sizeOf(Dwarf.EhFrameHdr),4781 try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{
4783 .alignment = .@"4",4782 .size = @sizeOf(Dwarf.EhFrameHdr),
4784 .moved = true,4783 .alignment = .@"4",
4785 .bubbles_moved = false,4784 .moved = true,
4786 }));4785 .bubbles_moved = false,
4787 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.gnu_eh_frame });4786 }),
4787 .{ .segment = phndx.gnu_eh_frame },
4788 ));
4788 elf.phdrs.items[phndx.gnu_eh_frame] = elf.ni.gnu_eh_frame;4789 elf.phdrs.items[phndx.gnu_eh_frame] = elf.ni.gnu_eh_frame;
47894790
4790 elf.shndx.eh_frame_hdr = try elf.addSection(elf.ni.gnu_eh_frame.unwrap().?, .{4791 elf.shndx.eh_frame_hdr = try elf.addSection(elf.ni.gnu_eh_frame.unwrap().?, .{
...@@ -5106,6 +5107,7 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node {...@@ -5106,6 +5107,7 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node {
5106/// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data.5107/// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data.
5107fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {5108fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
5108 return switch (elf.getNode(ni)) {5109 return switch (elf.getNode(ni)) {
5110 .deleted,
5109 .archive,5111 .archive,
5110 .archive_header,5112 .archive_header,
5111 .archive_input_member,5113 .archive_input_member,
...@@ -5142,6 +5144,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {...@@ -5142,6 +5144,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
5142}5144}
5143fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {5145fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5144 return switch (elf.getNode(ni)) {5146 return switch (elf.getNode(ni)) {
5147 .deleted,
5145 .archive,5148 .archive,
5146 .archive_header,5149 .archive_header,
5147 .archive_input_member,5150 .archive_input_member,
...@@ -5179,7 +5182,12 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -5179,7 +5182,12 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5179fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {5182fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
5180 const parent_ni = ni.parent(&elf.mf).unwrap().?;5183 const parent_ni = ni.parent(&elf.mf).unwrap().?;
5181 const parent_vaddr = parent_vaddr: switch (elf.getNode(parent_ni)) {5184 const parent_vaddr = parent_vaddr: switch (elf.getNode(parent_ni)) {
5182 .archive, .archive_header, .archive_input_member, .archive_elf_member_header => unreachable,5185 .deleted,
5186 .archive,
5187 .archive_header,
5188 .archive_input_member,
5189 .archive_elf_member_header,
5190 => unreachable,
5183 .elf => return 0,5191 .elf => return 0,
5184 .ehdr, .shdr => unreachable,5192 .ehdr, .shdr => unreachable,
5185 .segment => |phndx| switch (elf.phdrSlice()) {5193 .segment => |phndx| switch (elf.phdrSlice()) {
...@@ -5229,6 +5237,7 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5229,6 +5237,7 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5229 skip_node_relocs: MappedFile.Node.Index.Optional = .none,5237 skip_node_relocs: MappedFile.Node.Index.Optional = .none,
5230 first_got_reloc: ?*GotReloc.Index = null,5238 first_got_reloc: ?*GotReloc.Index = null,
5231 } = switch (elf.getNode(ni)) {5239 } = switch (elf.getNode(ni)) {
5240 .deleted,
5232 .archive,5241 .archive,
5233 .archive_header,5242 .archive_header,
5234 .archive_input_member,5243 .archive_input_member,
...@@ -5284,8 +5293,8 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {...@@ -5284,8 +5293,8 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
5284 },5293 },
5285 .func_debug_info => |fi| .{5294 .func_debug_info => |fi| .{
5286 .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_symbol_reloc,5295 .first_symbol_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_symbol_reloc,
5287 .skip_symbol_relocs = if (elf.navs.getPtr(fi.nav(&elf.dwarf))) |nav|5296 .skip_symbol_relocs = if (elf.navs.getPtr(fi.get(&elf.dwarf).owner_nav)) |owner_nav|
5288 nav.lsi.index().ptr(elf).node5297 owner_nav.lsi.index().ptr(elf).node
5289 else5298 else
5290 .none,5299 .none,
5291 .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_node_reloc,5300 .first_node_reloc = &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_node_reloc,
...@@ -5875,9 +5884,9 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node...@@ -5875,9 +5884,9 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
5875 },5884 },
5876 };5885 };
5877 try shndx.ensureAligned(elf, alignment);5886 try shndx.ensureAligned(elf, alignment);
5878 const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{5887 const node = elf.addNodeAssumeCapacity(try shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
5879 .alignment = alignment,5888 .alignment = alignment,
5880 });5889 }), .{ .nav = nmi });
5881 nav_gop.value_ptr.* = .{5890 nav_gop.value_ptr.* = .{
5882 .lsi = elf.addLocalSymbolAssumeCapacity(.{5891 .lsi = elf.addLocalSymbolAssumeCapacity(.{
5883 .node = .wrap(node),5892 .node = .wrap(node),
...@@ -5890,7 +5899,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node...@@ -5890,7 +5899,6 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
5890 .first_symbol_reloc = .none,5899 .first_symbol_reloc = .none,
5891 .first_got_reloc = .none,5900 .first_got_reloc = .none,
5892 };5901 };
5893 elf.nodes.appendAssumeCapacity(.{ .nav = nmi });
5894 }5902 }
5895 return nmi;5903 return nmi;
5896}5904}
...@@ -5919,10 +5927,10 @@ fn uavMapIndex(...@@ -5919,10 +5927,10 @@ fn uavMapIndex(
5919 if (!uav_gop.found_existing) {5927 if (!uav_gop.found_existing) {
5920 const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs5928 const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs
5921 try shndx.ensureAligned(elf, resolved_align);5929 try shndx.ensureAligned(elf, resolved_align);
5922 const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{5930 const node = elf.addNodeAssumeCapacity(try shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
5923 .moved = true, // see assert at end of `genUav`5931 .moved = true, // see assert at end of `genUav`
5924 .alignment = resolved_align,5932 .alignment = resolved_align,
5925 });5933 }), .{ .uav = umi });
5926 var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined;5934 var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined;
5927 const name = std.mem.print(&name_buf, "__anon_{d}", .{umi}) catch unreachable;5935 const name = std.mem.print(&name_buf, "__anon_{d}", .{umi}) catch unreachable;
5928 uav_gop.value_ptr.* = .{5936 uav_gop.value_ptr.* = .{
...@@ -5936,7 +5944,6 @@ fn uavMapIndex(...@@ -5936,7 +5944,6 @@ fn uavMapIndex(
5936 }),5944 }),
5937 .first_symbol_reloc = .none,5945 .first_symbol_reloc = .none,
5938 };5946 };
5939 elf.nodes.appendAssumeCapacity(.{ .uav = umi });
5940 elf.const_prog_node.increaseEstimatedTotalItems(1);5947 elf.const_prog_node.increaseEstimatedTotalItems(1);
5941 elf.pending_uavs.appendAssumeCapacity(umi);5948 elf.pending_uavs.appendAssumeCapacity(umi);
5942 } else {5949 } else {
...@@ -5944,7 +5951,7 @@ fn uavMapIndex(...@@ -5944,7 +5951,7 @@ fn uavMapIndex(
5944 const shndx = elf.getNode(node.parent(&elf.mf).unwrap().?).section;5951 const shndx = elf.getNode(node.parent(&elf.mf).unwrap().?).section;
5945 try shndx.ensureAligned(elf, resolved_align);5952 try shndx.ensureAligned(elf, resolved_align);
5946 if (resolved_align.order(node.alignment(&elf.mf)).compare(.gt)) {5953 if (resolved_align.order(node.alignment(&elf.mf)).compare(.gt)) {
5947 try node.realign(&elf.mf, gpa, resolved_align);5954 try node.realign(gpa, &elf.mf, resolved_align);
5948 }5955 }
5949 }5956 }
5950 return umi;5957 return umi;
...@@ -6173,11 +6180,13 @@ fn loadObject(...@@ -6173,11 +6180,13 @@ fn loadObject(
6173 };6180 };
61746181
6175 try elf.nodes.ensureUnusedCapacity(gpa, 1);6182 try elf.nodes.ensureUnusedCapacity(gpa, 1);
6176 const new_member_ni = try archive.ni.addFooterChildBefore(&elf.mf, gpa, first_member_oni, .{6183 const new_member_ni = elf.addNodeAssumeCapacity(
6177 .size = Alignment.@"2".forward(@sizeOf(std.elf.ar_hdr) + fl.size),6184 try archive.ni.addFooterChildBefore(gpa, &elf.mf, first_member_oni, .{
6178 .alignment = .@"2",6185 .size = Alignment.@"2".forward(@sizeOf(std.elf.ar_hdr) + fl.size),
6179 });6186 .alignment = .@"2",
6180 elf.nodes.appendAssumeCapacity(.{ .archive_input_member = input_index });6187 }),
6188 .{ .archive_input_member = input_index },
6189 );
6181 input.extra = .{ .node = new_member_ni };6190 input.extra = .{ .node = new_member_ni };
6182 elf.input_prog_node.increaseEstimatedTotalItems(1);6191 elf.input_prog_node.increaseEstimatedTotalItems(1);
61836192
...@@ -6391,22 +6400,20 @@ fn loadObject(...@@ -6391,22 +6400,20 @@ fn loadObject(
6391 .alignment = need_align,6400 .alignment = need_align,
6392 .moved = true, // see assert at end of `flushInputSection`6401 .moved = true, // see assert at end of `flushInputSection`
6393 };6402 };
6394 const ni = if (opts.node_fixed) ni: {6403 const ni = elf.addNodeAssumeCapacity(
6395 const shndx_ni = opts.shndx.get(elf).ni;6404 if (opts.node_fixed) ni: {
6396 const after_oni: MappedFile.Node.Index.Optional = after: {6405 const shndx_ni = opts.shndx.get(elf).ni;
6397 const last_ni = shndx_ni.last(&elf.mf).unwrap() orelse break :after .none;6406 const after_oni: MappedFile.Node.Index.Optional = after: {
6398 break :after switch (last_ni.position(&elf.mf)) {6407 const last_ni = shndx_ni.last(&elf.mf).unwrap() orelse break :after .none;
6399 .header => .wrap(last_ni),6408 break :after switch (last_ni.position(&elf.mf)) {
6400 .footer, .floating => .none,6409 .header => .wrap(last_ni),
6410 .footer, .floating => .none,
6411 };
6401 };6412 };
6402 };6413 break :ni try shndx_ni.addHeaderChildAfter(gpa, &elf.mf, after_oni, add_node_opts);
6403 break :ni try shndx_ni.addHeaderChildAfter(&elf.mf, gpa, after_oni, add_node_opts);6414 } else try opts.shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, add_node_opts),
6404 } else ni: {6415 .{ .input_section = @fromBackingInt(@intCast(elf.input_sections.items.len)) },
6405 break :ni try opts.shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, add_node_opts);6416 );
6406 };
6407 elf.nodes.appendAssumeCapacity(.{
6408 .input_section = @fromBackingInt(@intCast(elf.input_sections.items.len)),
6409 });
6410 section.isi = @fromBackingInt(@intCast(elf.input_sections.items.len));6417 section.isi = @fromBackingInt(@intCast(elf.input_sections.items.len));
6411 elf.input_sections.addOneAssumeCapacity().* = .{6418 elf.input_sections.addOneAssumeCapacity().* = .{
6412 .input = input_index,6419 .input = input_index,
...@@ -6659,7 +6666,7 @@ fn populateArchiveMemberName(elf: *Elf, member_ar_hdr: *std.elf.ar_hdr, member_n...@@ -6659,7 +6666,7 @@ fn populateArchiveMemberName(elf: *Elf, member_ar_hdr: *std.elf.ar_hdr, member_n
6659 // We set the size of the archive header node exactly, because we want padding bytes to go into6666 // We set the size of the archive header node exactly, because we want padding bytes to go into
6660 // the root `.archive` node. That way, those bytes could still be used to grow the string table6667 // the root `.archive` node. That way, those bytes could still be used to grow the string table
6661 // if necessary, but they could also be used for new archive members.6668 // if necessary, but they could also be used for new archive members.
6662 try archive_header_ni.resizeLeaf(&elf.mf, gpa, old_archive_header_size + member_name.len + 2);6669 try archive_header_ni.resizeLeaf(gpa, &elf.mf, old_archive_header_size + member_name.len + 2);
66636670
6664 const dest_slice = archive_header_ni.slice(&elf.mf)[@intCast(old_archive_header_size)..];6671 const dest_slice = archive_header_ni.slice(&elf.mf)[@intCast(old_archive_header_size)..];
6665 @memcpy(dest_slice[0 .. dest_slice.len - 2], member_name);6672 @memcpy(dest_slice[0 .. dest_slice.len - 2], member_name);
...@@ -6811,8 +6818,12 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars...@@ -6811,8 +6818,12 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
6811 // We have a copy relocation for this global, but the amount of space we6818 // We have a copy relocation for this global, but the amount of space we
6812 // reserved for it could be too small or underaligned!6819 // reserved for it could be too small or underaligned!
6813 try Section.Index.data.ensureAligned(elf, gop.value_ptr.alignment);6820 try Section.Index.data.ensureAligned(elf, gop.value_ptr.alignment);
6814 try copied_global.node.resizeLeaf(&elf.mf, gpa, gop.value_ptr.alignment.forward(gop.value_ptr.size));6821 try copied_global.node.resizeLeaf(
6815 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment);6822 gpa,
6823 &elf.mf,
6824 gop.value_ptr.alignment.forward(gop.value_ptr.size),
6825 );
6826 try copied_global.node.realign(gpa, &elf.mf, gop.value_ptr.alignment);
6816 const global_ptr = elf.globalByName(name).?;6827 const global_ptr = elf.globalByName(name).?;
6817 switch (elf.symPtr(global_ptr.symtab_index)) {6828 switch (elf.symPtr(global_ptr.symtab_index)) {
6818 inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),6829 inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),
...@@ -7034,49 +7045,25 @@ fn prelinkInner(elf: *Elf) Error!void {...@@ -7034,49 +7045,25 @@ fn prelinkInner(elf: *Elf) Error!void {
7034 .extra = .{ .file_symbol = zcu_file_symbol },7045 .extra = .{ .file_symbol = zcu_file_symbol },
7035 };7046 };
7036 elf.input_pending_index += 1;7047 elf.input_pending_index += 1;
7037 }
7038}
7039
7040pub fn zcuFilesReady(elf: *Elf, zcu: *Zcu) link.Error!void {
7041 elf.zcuFilesReadyInner(zcu) catch |err| switch (err) {
7042 else => |e| return e,
7043 error.MappedFileIo => return elf.base.comp.link_diags.fail(
7044 "failed to write output file: {t}",
7045 .{elf.mf.io_err.?},
7046 ),
7047 };
7048}
7049fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
7050 const gpa = zcu.gpa;
70517048
7052 if (elf.dwarf.units.count() == 0) {7049 try elf.nodes.ensureUnusedCapacity(gpa, 4 + 5);
7053 try elf.dwarf.initUnits(zcu);7050
7054 try elf.nodes.ensureUnusedCapacity(gpa, 4 + 5 + 5 * elf.dwarf.units.count());7051 elf.dwarf.debug_abbrev.ni = .wrap(elf.addNodeAssumeCapacity(
7055 try elf.dwarf_units.appendNTimes(gpa, .{7052 try elf.shndx.debug_abbrev.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}),
7056 .frame_cie_first_target_reloc = .none,7053 .{ .debug_shared = .debug_abbrev },
7057 .debug_info_header_first_target_reloc = .none,7054 ));
7058 .debug_info_header_first_node_reloc = .none,7055 elf.dwarf.debug_line_str.ni = .wrap(elf.addNodeAssumeCapacity(
7059 .debug_line_header_first_target_reloc = .none,7056 try elf.shndx.debug_line_str.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}),
7060 .debug_line_header_first_node_reloc = .none,7057 .{ .debug_shared = .debug_line_str },
7061 .debug_rnglists_first_target_reloc = .none,7058 ));
7062 .debug_rnglists_symbol_relocs = .empty,7059 elf.dwarf.debug_str.ni = .wrap(elf.addNodeAssumeCapacity(
7063 }, elf.dwarf.units.count());7060 try elf.shndx.debug_str.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}),
70647061 .{ .debug_shared = .debug_str },
7065 elf.dwarf.debug_abbrev.ni =7062 ));
7066 .wrap(try elf.shndx.debug_abbrev.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));7063 elf.dwarf.debug_str_offsets.ni = .wrap(elf.addNodeAssumeCapacity(
7067 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_abbrev });7064 try elf.shndx.debug_str_offsets.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{}),
70687065 .{ .debug_shared = .debug_str_offsets },
7069 elf.dwarf.debug_line_str.ni =7066 ));
7070 .wrap(try elf.shndx.debug_line_str.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7071 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_line_str });
7072
7073 elf.dwarf.debug_str.ni =
7074 .wrap(try elf.shndx.debug_str.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7075 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_str });
7076
7077 elf.dwarf.debug_str_offsets.ni =
7078 .wrap(try elf.shndx.debug_str_offsets.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}));
7079 elf.nodes.appendAssumeCapacity(.{ .debug_shared = .debug_str_offsets });
70807067
7081 for ([5]Section.Index{7068 for ([5]Section.Index{
7082 elf.shndx.eh_frame,7069 elf.shndx.eh_frame,
...@@ -7089,18 +7076,20 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {...@@ -7089,18 +7076,20 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
7089 const debug_ni = debug_shndx.get(elf).ni;7076 const debug_ni = debug_shndx.get(elf).ni;
7090 _ = debug_ni.last(&elf.mf).unwrap() orelse continue;7077 _ = debug_ni.last(&elf.mf).unwrap() orelse continue;
7091 const frame_format = debug_shndx.debugFrameFormat(elf);7078 const frame_format = debug_shndx.debugFrameFormat(elf);
7092 const unit_padding_ni = try debug_ni.addFloatingChild(&elf.mf, gpa, .{7079 const unit_padding_ni = elf.addNodeAssumeCapacity(
7093 .alignment = if (frame_format) |_| switch (elf.identClass()) {7080 try debug_ni.addFloatingChild(gpa, &elf.mf, .{
7094 .NONE, _ => unreachable,7081 .alignment = if (frame_format) |_| switch (elf.identClass()) {
7095 .@"32" => .@"4",7082 .NONE, _ => unreachable,
7096 .@"64" => .@"8",7083 .@"32" => .@"4",
7097 } else .@"1",7084 .@"64" => .@"8",
7098 .next_moved = true,7085 } else .@"1",
7099 .enable_next_moved = true,7086 .next_moved = true,
7100 });7087 .enable_next_moved = true,
7101 elf.nodes.appendAssumeCapacity(.unit_padding);7088 }),
7089 .unit_padding,
7090 );
7102 var debug_nw: MappedFile.Node.Writer = undefined;7091 var debug_nw: MappedFile.Node.Writer = undefined;
7103 unit_padding_ni.writer(&elf.mf, gpa, &debug_nw);7092 unit_padding_ni.writer(gpa, &elf.mf, &debug_nw);
7104 defer debug_nw.deinit();7093 defer debug_nw.deinit();
7105 (if (frame_format) |format|7094 (if (frame_format) |format|
7106 elf.dwarf.genDebugFrameCie(&debug_nw.interface, null, format)7095 elf.dwarf.genDebugFrameCie(&debug_nw.interface, null, format)
...@@ -7109,88 +7098,121 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {...@@ -7109,88 +7098,121 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
7109 error.WriteFailed => return debug_nw.err.?,7098 error.WriteFailed => return debug_nw.err.?,
7110 };7099 };
7111 }7100 }
7101 }
7102}
71127103
7113 for (0.., elf.dwarf.units.values()) |unit_index, *unit| {7104pub fn zcuFilesReady(elf: *Elf, zcu: *Zcu) link.Error!void {
7114 const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index));7105 elf.zcuFilesReadyInner(zcu) catch |err| switch (err) {
7115 switch (elf.shndx.debug_info) {7106 else => |e| return e,
7116 .UNDEF => {},7107 error.MappedFileIo => return elf.base.comp.link_diags.fail(
7117 else => |debug_info_shndx| {7108 "failed to write output file: {t}",
7118 const debug_info_ni =7109 .{elf.mf.io_err.?},
7119 try debug_info_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{7110 ),
7120 .alignment = elf.mf.flags.block_size,7111 };
7121 .enable_next_moved = true,7112}
7122 });7113fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
7123 unit.debug_info_ni = .wrap(debug_info_ni);7114 const gpa = zcu.gpa;
7124 elf.nodes.appendAssumeCapacity(.{ .unit_debug_info = ui });7115
71257116 try elf.dwarf.initUnits(zcu);
7126 unit.debug_info_header_ni =7117 const old_units_len = elf.dwarf_units.items.len;
7127 .wrap(try debug_info_ni.addOnlyHeaderChild(&elf.mf, gpa, .{7118 const new_units_len = elf.dwarf.units.count();
7128 .next_moved = true,7119 try elf.dwarf_units.appendNTimes(gpa, .{
7129 .enable_next_moved = true,7120 .frame_cie_first_target_reloc = .none,
7130 }));7121 .debug_info_header_first_target_reloc = .none,
7131 elf.nodes.appendAssumeCapacity(.{ .unit_debug_info_header = ui });7122 .debug_info_header_first_node_reloc = .none,
7132 },7123 .debug_line_header_first_target_reloc = .none,
7133 }7124 .debug_line_header_first_node_reloc = .none,
7134 switch (elf.shndx.debug_line) {7125 .debug_rnglists_first_target_reloc = .none,
7135 .UNDEF => {},7126 .debug_rnglists_symbol_relocs = .empty,
7136 else => |debug_line_shndx| {7127 }, new_units_len - old_units_len);
7137 const debug_line_ni =7128 try elf.nodes.ensureUnusedCapacity(gpa, 5 * (new_units_len - old_units_len));
7138 try debug_line_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{7129
7139 .alignment = elf.mf.flags.block_size,7130 for (old_units_len.., elf.dwarf.units.values()[old_units_len..]) |unit_index, *unit| {
7140 .enable_next_moved = true,7131 const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index));
7141 });7132 switch (elf.shndx.debug_info) {
7142 unit.debug_line_ni = .wrap(debug_line_ni);7133 .UNDEF => {},
7143 elf.nodes.appendAssumeCapacity(.{ .unit_debug_line = ui });7134 else => |debug_info_shndx| {
71447135 const debug_info_ni = elf.addNodeAssumeCapacity(
7145 unit.debug_line_header_ni =7136 try debug_info_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
7146 .wrap(try debug_line_ni.addOnlyHeaderChild(&elf.mf, gpa, .{7137 .alignment = elf.mf.flags.block_size,
7147 // Idle tasks are going to try to keep this up to date before we are able to7138 .enable_next_moved = true,
7148 // write out the full header, so just reserve space for them to do so.7139 }),
7149 .size = elf.dwarf.unitLengthSize(),7140 .{ .unit_debug_info = ui },
7150 .enable_next_moved = true,7141 );
7151 }));7142 unit.debug_info_ni = .wrap(debug_info_ni);
7152 elf.nodes.appendAssumeCapacity(.{ .unit_debug_line_header = ui });7143
7153 },7144 unit.debug_info_header_ni = .wrap(elf.addNodeAssumeCapacity(
7154 }7145 try debug_info_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
7155 switch (elf.shndx.debug_rnglists) {7146 .next_moved = true,
7156 .UNDEF => {},7147 .enable_next_moved = true,
7157 else => |debug_rnglists_shndx| {7148 }),
7158 unit.debug_rnglists_ni =7149 .{ .unit_debug_info_header = ui },
7159 .wrap(try debug_rnglists_shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{7150 ));
7160 .next_moved = true,7151 },
7161 .enable_next_moved = true,
7162 }));
7163 elf.nodes.appendAssumeCapacity(.{ .unit_debug_rnglists = ui });
7164 },
7165 }
7166 }7152 }
7153 switch (elf.shndx.debug_line) {
7154 .UNDEF => {},
7155 else => |debug_line_shndx| {
7156 const debug_line_ni = elf.addNodeAssumeCapacity(
7157 try debug_line_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
7158 .alignment = elf.mf.flags.block_size,
7159 .enable_next_moved = true,
7160 }),
7161 .{ .unit_debug_line = ui },
7162 );
7163 unit.debug_line_ni = .wrap(debug_line_ni);
71677164
7168 for (elf.dwarf.units.keys(), elf.dwarf.units.values()) |mod, *unit| {7165 unit.debug_line_header_ni = .wrap(elf.addNodeAssumeCapacity(
7169 var drh_nw: MappedFile.Node.Writer = undefined;7166 try debug_line_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
7170 unit.debug_rnglists_ni.unwrap().?.writer(&elf.mf, gpa, &drh_nw);7167 // Idle tasks are going to try to keep this up to date before we are able to
7171 defer drh_nw.deinit();7168 // write out the full header, so just reserve space for them to do so.
7172 const debug_rnglists_offsets_table_offset =7169 .size = elf.dwarf.unitLengthSize(),
7173 elf.dwarf.genDebugRnglistsHeader(unit, &drh_nw) catch |err| switch (err) {7170 .enable_next_moved = true,
7174 else => |e| return e,7171 }),
7175 error.WriteFailed => return drh_nw.err.?,7172 .{ .unit_debug_line_header = ui },
7176 };7173 ));
7174 },
7175 }
7176 switch (elf.shndx.debug_rnglists) {
7177 .UNDEF => {},
7178 else => |debug_rnglists_shndx| unit.debug_rnglists_ni = .wrap(elf.addNodeAssumeCapacity(
7179 try debug_rnglists_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
7180 .next_moved = true,
7181 .enable_next_moved = true,
7182 }),
7183 .{ .unit_debug_rnglists = ui },
7184 )),
7185 }
7186 }
71777187
7178 var dih_nw: MappedFile.Node.Writer = undefined;7188 for (
7179 const debug_info_header_ni = unit.debug_info_header_ni.unwrap().?;7189 elf.dwarf.units.keys()[old_units_len..],
7180 debug_info_header_ni.writer(&elf.mf, gpa, &dih_nw);7190 elf.dwarf.units.values()[old_units_len..],
7181 defer dih_nw.deinit();7191 ) |mod, *unit| {
7182 elf.resetNodeRelocs(debug_info_header_ni);7192 var drh_nw: MappedFile.Node.Writer = undefined;
7183 elf.dwarf.genDebugInfoHeader(7193 unit.debug_rnglists_ni.unwrap().?.writer(gpa, &elf.mf, &drh_nw);
7184 mod,7194 defer drh_nw.deinit();
7185 unit,7195 const debug_rnglists_offsets_table_offset =
7186 &dih_nw,7196 elf.dwarf.genDebugRnglistsHeader(unit, &drh_nw) catch |err| switch (err) {
7187 debug_rnglists_offsets_table_offset,
7188 zcu,
7189 ) catch |err| switch (err) {
7190 else => |e| return e,7197 else => |e| return e,
7191 error.WriteFailed => return dih_nw.err.?,7198 error.WriteFailed => return drh_nw.err.?,
7192 };7199 };
7193 }7200
7201 var dih_nw: MappedFile.Node.Writer = undefined;
7202 const debug_info_header_ni = unit.debug_info_header_ni.unwrap().?;
7203 debug_info_header_ni.writer(gpa, &elf.mf, &dih_nw);
7204 defer dih_nw.deinit();
7205 elf.resetNodeRelocs(debug_info_header_ni);
7206 elf.dwarf.genDebugInfoHeader(
7207 mod,
7208 unit,
7209 &dih_nw,
7210 debug_rnglists_offsets_table_offset,
7211 zcu,
7212 ) catch |err| switch (err) {
7213 else => |e| return e,
7214 error.WriteFailed => return dih_nw.err.?,
7215 };
7194 }7216 }
7195}7217}
71967218
...@@ -7203,7 +7225,7 @@ fn flushFiles(elf: *Elf) Error!void {...@@ -7203,7 +7225,7 @@ fn flushFiles(elf: *Elf) Error!void {
7203 try debug_line_header_ni.moved(gpa, &elf.mf);7225 try debug_line_header_ni.moved(gpa, &elf.mf);
7204 try debug_line_header_ni.nextMoved(gpa, &elf.mf);7226 try debug_line_header_ni.nextMoved(gpa, &elf.mf);
7205 var dlh_nw: MappedFile.Node.Writer = undefined;7227 var dlh_nw: MappedFile.Node.Writer = undefined;
7206 debug_line_header_ni.writer(&elf.mf, gpa, &dlh_nw);7228 debug_line_header_ni.writer(gpa, &elf.mf, &dlh_nw);
7207 defer dlh_nw.deinit();7229 defer dlh_nw.deinit();
7208 elf.resetNodeRelocs(debug_line_header_ni);7230 elf.resetNodeRelocs(debug_line_header_ni);
7209 elf.dwarf.genDebugLineHeader(mod, unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {7231 elf.dwarf.genDebugLineHeader(mod, unit, &dlh_nw, elf.base.comp.zcu.?) catch |err| switch (err) {
...@@ -7235,7 +7257,7 @@ fn prepareDynamic(elf: *Elf) Error!void {...@@ -7235,7 +7257,7 @@ fn prepareDynamic(elf: *Elf) Error!void {
72357257
7236 const dynamic_size = dynamic_len * 2 * elf.targetPtrSize();7258 const dynamic_size = dynamic_len * 2 * elf.targetPtrSize();
72377259
7238 try elf.shndx.dynamic.get(elf).ni.resizeLeaf(&elf.mf, comp.gpa, dynamic_size);7260 try elf.shndx.dynamic.get(elf).ni.resizeLeaf(comp.gpa, &elf.mf, dynamic_size);
7239 switch (elf.shdrPtr(elf.shndx.dynamic)) {7261 switch (elf.shdrPtr(elf.shndx.dynamic)) {
7240 inline else => |shdr| elf.targetStore(&shdr.size, @intCast(dynamic_size)),7262 inline else => |shdr| elf.targetStore(&shdr.size, @intCast(dynamic_size)),
7241 }7263 }
...@@ -7405,17 +7427,20 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -7405,17 +7427,20 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
7405 break :shndx .{ @fromBackingInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };7427 break :shndx .{ @fromBackingInt(shndx), @as(u64, elf.targetLoad(&ehdr.shentsize)) * @as(u64, shnum) };
7406 },7428 },
7407 };7429 };
7408 try elf.ni.shdr.ensureMinimumSize(&elf.mf, gpa, new_shdr_size);7430 try elf.ni.shdr.ensureMinimumSize(gpa, &elf.mf, new_shdr_size);
7409 const parent_ni = switch (elf.ehdrType()) {7431 const parent_ni = switch (elf.ehdrType()) {
7410 .REL => elf.ni.elf,7432 .REL => elf.ni.elf,
7411 .EXEC, .DYN => segment_ni,7433 .EXEC, .DYN => segment_ni,
7412 };7434 };
7413 assert(opts.addralign.check(opts.size));7435 assert(opts.addralign.check(opts.size));
7414 const ni = try parent_ni.addFloatingChild(&elf.mf, gpa, .{7436 const ni = elf.addNodeAssumeCapacity(try parent_ni.addFloatingChild(gpa, &elf.mf, .{
7415 .size = opts.node_align.forward(opts.size),7437 .size = opts.node_align.forward(opts.size),
7416 .alignment = opts.addralign.max(opts.node_align),7438 .alignment = opts.addralign.max(opts.node_align),
7417 .resized = opts.size > 0,7439 .resized = opts.size > 0,
7418 .bubbles_moved = opts.flags.ALLOC,7440 .bubbles_moved = opts.flags.ALLOC,
7441 }), switch (opts.manual_size) {
7442 false => .{ .section = shndx },
7443 true => .{ .section_manual_size = shndx },
7419 });7444 });
7420 const addr = elf.computeNodeVAddr(ni);7445 const addr = elf.computeNodeVAddr(ni);
7421 const lsi: Symbol.LocalIndex = if (opts.flags.ALLOC) elf.addLocalSymbolAssumeCapacity(.{7446 const lsi: Symbol.LocalIndex = if (opts.flags.ALLOC) elf.addLocalSymbolAssumeCapacity(.{
...@@ -7431,10 +7456,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {...@@ -7431,10 +7456,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
7431 .RELA => .{ .free_head = .none },7456 .RELA => .{ .free_head = .none },
7432 else => .{ .shndx = .UNDEF },7457 else => .{ .shndx = .UNDEF },
7433 } });7458 } });
7434 elf.nodes.appendAssumeCapacity(switch (opts.manual_size) {
7435 false => .{ .section = shndx },
7436 true => .{ .section_manual_size = shndx },
7437 });
7438 switch (elf.shdrPtr(shndx)) {7459 switch (elf.shdrPtr(shndx)) {
7439 inline else => |shdr, class| {7460 inline else => |shdr, class| {
7440 shdr.* = .{7461 shdr.* = .{
...@@ -7505,7 +7526,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize)...@@ -7505,7 +7526,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize)
7505 .NONE, _ => unreachable,7526 .NONE, _ => unreachable,
7506 inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr),7527 inline else => |ct_class| (elf.got.count() + new_got_entries) * @sizeOf(ct_class.ElfN().Addr),
7507 };7528 };
7508 try elf.shndx.got.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_got_size);7529 try elf.shndx.got.get(elf).ni.ensureMinimumSize(gpa, &elf.mf, need_got_size);
75097530
7510 if (elf.shndx.dynamic != .UNDEF) {7531 if (elf.shndx.dynamic != .UNDEF) {
7511 try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries);7532 try elf.shndx.rela_dyn.relaEnsureAdditionalCapacity(elf, new_got_entries);
...@@ -8100,6 +8121,7 @@ fn addGotRelocAssumeCapacity(...@@ -8100,6 +8121,7 @@ fn addGotRelocAssumeCapacity(
8100) void {8121) void {
8101 assert(elf.ehdrType() != .REL);8122 assert(elf.ehdrType() != .REL);
8102 switch (elf.getNode(node)) {8123 switch (elf.getNode(node)) {
8124 .deleted,
8103 .archive,8125 .archive,
8104 .archive_header,8126 .archive_header,
8105 .archive_input_member,8127 .archive_input_member,
...@@ -8361,14 +8383,13 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool {...@@ -8361,14 +8383,13 @@ fn maybeAddCopyRelocation(elf: *Elf, global_name: String(.strtab)) Error!bool {
8361 try Section.Index.data.ensureAligned(elf, dso_global.alignment);8383 try Section.Index.data.ensureAligned(elf, dso_global.alignment);
83628384
8363 try elf.nodes.ensureUnusedCapacity(gpa, 1);8385 try elf.nodes.ensureUnusedCapacity(gpa, 1);
8364 const node = try Section.Index.data.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{8386 const node = try Section.Index.data.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
8365 .size = dso_global.alignment.forward(dso_global.size),8387 .size = dso_global.alignment.forward(dso_global.size),
8366 .alignment = dso_global.alignment,8388 .alignment = dso_global.alignment,
8367 });8389 });
8368 errdefer comptime unreachable;8390 errdefer comptime unreachable;
83698391
8370 const vaddr = elf.computeNodeVAddr(node);8392 const vaddr = elf.computeNodeVAddr(node);
8371 elf.nodes.appendAssumeCapacity(.{ .copied_global = global_name });
8372 const rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{8393 const rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{
8373 .type = .copy(elf),8394 .type = .copy(elf),
8374 .offset = vaddr,8395 .offset = vaddr,
...@@ -8423,7 +8444,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -8423,7 +8444,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
84238444
8424 {8445 {
8425 var nw: MappedFile.Node.Writer = undefined;8446 var nw: MappedFile.Node.Writer = undefined;
8426 ni.writer(&elf.mf, gpa, &nw);8447 ni.writer(gpa, &elf.mf, &nw);
8427 defer nw.deinit();8448 defer nw.deinit();
8428 elf.resetNodeRelocs(ni);8449 elf.resetNodeRelocs(ni);
8429 codegen.generateSymbol(8450 codegen.generateSymbol(
...@@ -8549,16 +8570,16 @@ fn updateFuncInner(...@@ -8549,16 +8570,16 @@ fn updateFuncInner(
85498570
8550 {8571 {
8551 var nw: MappedFile.Node.Writer = undefined;8572 var nw: MappedFile.Node.Writer = undefined;
8552 ni.writer(&elf.mf, gpa, &nw);8573 ni.writer(gpa, &elf.mf, &nw);
8553 defer nw.deinit();8574 defer nw.deinit();
8554 var debug_output_buf: Dwarf.WipNav.Debug = undefined;8575 var debug_output_buf: Dwarf.WipNav.Debug = undefined;
8555 const debug_output: link.File.DebugInfoOutput, const dwarf_func = debug_output: {8576 const debug_output: link.File.DebugInfoOutput, const dwarf_func = debug_output: {
8556 if (elf.ehdrMachine() != .X86_64) break :debug_output .{ .none, undefined };8577 if (elf.ehdrMachine() != .X86_64) break :debug_output .{ .none, undefined };
8557 const dwarf = &elf.dwarf;8578 const dwarf = &elf.dwarf;
8558 const mod = zcu.navFileScope(func.owner_nav).mod.?;8579 const mod = zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?;
8559 if (mod.strip and mod.unwind_tables == .none) break :debug_output .{ .none, undefined };8580 if (mod.strip and mod.unwind_tables == .none) break :debug_output .{ .none, undefined };
85608581
8561 try elf.nodes.ensureUnusedCapacity(gpa, 5);8582 try elf.nodes.ensureUnusedCapacity(gpa, 4);
8562 const dwarf_fi = try dwarf.getFunc(func.owner_nav);8583 const dwarf_fi = try dwarf.getFunc(func.owner_nav);
85638584
8564 const wip_nav = &debug_output_buf.wip_nav;8585 const wip_nav = &debug_output_buf.wip_nav;
...@@ -8586,27 +8607,28 @@ fn updateFuncInner(...@@ -8586,27 +8607,28 @@ fn updateFuncInner(
8586 .@"64" => .@"8",8607 .@"64" => .@"8",
8587 };8608 };
8588 const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: {8609 const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: {
8589 const frame_ni = try switch (wip_nav.frame_format) {8610 const frame_ni = elf.addNodeAssumeCapacity(try switch (wip_nav.frame_format) {
8590 .debug_frame => elf.shndx.debug_frame,8611 .debug_frame => elf.shndx.debug_frame,
8591 .eh_frame => elf.shndx.eh_frame,8612 .eh_frame => elf.shndx.eh_frame,
8592 }.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{8613 }.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{
8593 .alignment = frame_align.max(elf.mf.flags.block_size),8614 .alignment = frame_align.max(elf.mf.flags.block_size),
8594 .enable_next_moved = true,8615 .enable_next_moved = true,
8595 });8616 }), .{ .unit_frame = wip_nav.unit });
8596 unit.frame_ni = .wrap(frame_ni);8617 unit.frame_ni = .wrap(frame_ni);
8597 elf.nodes.appendAssumeCapacity(.{ .unit_frame = wip_nav.unit });
8598 break :frame_ni frame_ni;8618 break :frame_ni frame_ni;
8599 };8619 };
8600 _ = unit.cie_ni.unwrap() orelse {8620 _ = unit.cie_ni.unwrap() orelse {
8601 const cie_ni = try frame_ni.addOnlyHeaderChild(&elf.mf, gpa, .{8621 const cie_ni = elf.addNodeAssumeCapacity(
8602 .alignment = frame_align,8622 try frame_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
8603 .next_moved = true,8623 .alignment = frame_align,
8604 .enable_next_moved = true,8624 .next_moved = true,
8605 });8625 .enable_next_moved = true,
8626 }),
8627 .{ .unit_frame_cie = wip_nav.unit },
8628 );
8606 unit.cie_ni = .wrap(cie_ni);8629 unit.cie_ni = .wrap(cie_ni);
8607 elf.nodes.appendAssumeCapacity(.{ .unit_frame_cie = wip_nav.unit });
8608 var cie_nw: MappedFile.Node.Writer = undefined;8630 var cie_nw: MappedFile.Node.Writer = undefined;
8609 cie_ni.writer(&elf.mf, gpa, &cie_nw);8631 cie_ni.writer(gpa, &elf.mf, &cie_nw);
8610 defer cie_nw.deinit();8632 defer cie_nw.deinit();
8611 dwarf.genDebugFrameCie(&cie_nw.interface, switch (elf.ehdrMachine()) {8633 dwarf.genDebugFrameCie(&cie_nw.interface, switch (elf.ehdrMachine()) {
8612 else => unreachable,8634 else => unreachable,
...@@ -8621,7 +8643,7 @@ fn updateFuncInner(...@@ -8621,7 +8643,7 @@ fn updateFuncInner(
8621 try fde_ni.nextMoved(gpa, &elf.mf);8643 try fde_ni.nextMoved(gpa, &elf.mf);
8622 break :fde_ni fde_ni;8644 break :fde_ni fde_ni;
8623 } else fde_ni: {8645 } else fde_ni: {
8624 const fde_ni = try frame_ni.addFloatingChild(&elf.mf, gpa, .{8646 const fde_ni = try frame_ni.addFloatingChild(gpa, &elf.mf, .{
8625 .alignment = frame_align,8647 .alignment = frame_align,
8626 .moved = true,8648 .moved = true,
8627 .next_moved = true,8649 .next_moved = true,
...@@ -8630,7 +8652,7 @@ fn updateFuncInner(...@@ -8630,7 +8652,7 @@ fn updateFuncInner(
8630 dwarf_func.fde_ni = .wrap(fde_ni);8652 dwarf_func.fde_ni = .wrap(fde_ni);
8631 break :fde_ni fde_ni;8653 break :fde_ni fde_ni;
8632 };8654 };
8633 fde_ni.writer(&elf.mf, gpa, &wip_nav.fde_writer);8655 fde_ni.writer(gpa, &elf.mf, &wip_nav.fde_writer);
86348656
8635 if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_nav }, dwarf_func };8657 if (mod.strip) break :debug_output .{ .{ .eh_frame = wip_nav }, dwarf_func };
86368658
...@@ -8642,20 +8664,21 @@ fn updateFuncInner(...@@ -8642,20 +8664,21 @@ fn updateFuncInner(
8642 const debug_info_ni = dwarf_func.debug_info_ni.unwrap().?;8664 const debug_info_ni = dwarf_func.debug_info_ni.unwrap().?;
8643 try debug_info_ni.moved(gpa, &elf.mf);8665 try debug_info_ni.moved(gpa, &elf.mf);
8644 try debug_info_ni.nextMoved(gpa, &elf.mf);8666 try debug_info_ni.nextMoved(gpa, &elf.mf);
8645 debug_info_ni.writer(&elf.mf, gpa, &debug.info_writer);8667 debug_info_ni.writer(gpa, &elf.mf, &debug.info_writer);
86468668
8647 const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: {8669 const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: {
8648 const debug_line_ni =8670 const debug_line_ni = elf.addNodeAssumeCapacity(
8649 try unit.debug_line_ni.unwrap().?.addFloatingChild(&elf.mf, gpa, .{8671 try unit.debug_line_ni.unwrap().?.addFloatingChild(gpa, &elf.mf, .{
8650 .moved = true,8672 .moved = true,
8651 .next_moved = true,8673 .next_moved = true,
8652 .enable_next_moved = true,8674 .enable_next_moved = true,
8653 });8675 }),
8676 .{ .func_debug_line = dwarf_fi },
8677 );
8654 dwarf_func.debug_line_ni = .wrap(debug_line_ni);8678 dwarf_func.debug_line_ni = .wrap(debug_line_ni);
8655 elf.nodes.appendAssumeCapacity(.{ .func_debug_line = dwarf_fi });
8656 break :debug_line_ni debug_line_ni;8679 break :debug_line_ni debug_line_ni;
8657 };8680 };
8658 debug_line_ni.writer(&elf.mf, gpa, &debug.line_writer);8681 debug_line_ni.writer(gpa, &elf.mf, &debug.line_writer);
86598682
8660 break :debug_output .{ .{ .dwarf2 = debug }, dwarf_func };8683 break :debug_output .{ .{ .dwarf2 = debug }, dwarf_func };
8661 };8684 };
...@@ -8705,13 +8728,13 @@ fn updateFuncInner(...@@ -8705,13 +8728,13 @@ fn updateFuncInner(
8705 .debug_frame => elf.shndx.debug_frame,8728 .debug_frame => elf.shndx.debug_frame,
8706 .eh_frame => elf.shndx.eh_frame,8729 .eh_frame => elf.shndx.eh_frame,
8707 }.get(elf).ni;8730 }.get(elf).ni;
8708 try frame_ni.trimStart(&elf.mf, gpa);8731 try frame_ni.trimStart(gpa, &elf.mf);
8709 switch (wip_nav.frame_format) {8732 switch (wip_nav.frame_format) {
8710 .debug_frame => {},8733 .debug_frame => {},
8711 .eh_frame => {8734 .eh_frame => {
8712 const last_offset, const last_size =8735 const last_offset, const last_size =
8713 frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);8736 frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8714 try frame_ni.ensureMinimumSize(&elf.mf, gpa, last_offset + last_size + 4);8737 try frame_ni.ensureMinimumSize(gpa, &elf.mf, last_offset + last_size + 4);
8715 },8738 },
8716 }8739 }
8717 },8740 },
...@@ -8721,18 +8744,18 @@ fn updateFuncInner(...@@ -8721,18 +8744,18 @@ fn updateFuncInner(
8721 elf.shndx.debug_info,8744 elf.shndx.debug_info,
8722 elf.shndx.debug_line,8745 elf.shndx.debug_line,
8723 elf.shndx.debug_rnglists,8746 elf.shndx.debug_rnglists,
8724 }) |debug_shndx| try debug_shndx.get(elf).ni.trimStart(&elf.mf, gpa);8747 }) |debug_shndx| try debug_shndx.get(elf).ni.trimStart(gpa, &elf.mf);
8725 const unit = debug.wip_nav.unit.get(debug.wip_nav.dwarf);8748 const unit = debug.wip_nav.unit.get(debug.wip_nav.dwarf);
8726 {8749 {
8727 const debug_info_ni = unit.debug_info_ni.unwrap().?;8750 const debug_info_ni = unit.debug_info_ni.unwrap().?;
8728 const last_offset, const last_size =8751 const last_offset, const last_size =
8729 debug_info_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);8752 debug_info_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8730 try debug_info_ni.ensureMinimumSize(&elf.mf, gpa, last_offset + last_size +8753 try debug_info_ni.ensureMinimumSize(gpa, &elf.mf, last_offset + last_size +
8731 comptime Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) * 2);8754 comptime Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) * 2);
8732 }8755 }
8733 {8756 {
8734 var dr_nw: MappedFile.Node.Writer = undefined;8757 var dr_nw: MappedFile.Node.Writer = undefined;
8735 unit.debug_rnglists_ni.unwrap().?.writer(&elf.mf, gpa, &dr_nw);8758 unit.debug_rnglists_ni.unwrap().?.writer(gpa, &elf.mf, &dr_nw);
8736 defer dr_nw.deinit();8759 defer dr_nw.deinit();
8737 const first_symbol_reloc = elf.symbol_relocs.items.len;8760 const first_symbol_reloc = elf.symbol_relocs.items.len;
8738 debug.wip_nav.dwarf.genDebugRnglists(8761 debug.wip_nav.dwarf.genDebugRnglists(
...@@ -8764,6 +8787,25 @@ fn updateFuncInner(...@@ -8764,6 +8787,25 @@ fn updateFuncInner(
8764 try elf.genPending(pt);8787 try elf.genPending(pt);
8765}8788}
87668789
8790pub fn updateLineNumber(elf: *Elf, pt: Zcu.PerThread, src_inst: InternPool.TrackedInst.Index) void {
8791 const func = elf.dwarf.funcs.getPtr(src_inst) orelse return;
8792 elf.dwarf.updateLineNumber(pt.zcu, src_inst, func.debug_info_ni.unwrap().?.slice(&elf.mf));
8793}
8794
8795pub fn lostTracking(
8796 elf: *Elf,
8797 _: Zcu.PerThread,
8798 src_inst: InternPool.TrackedInst.Index,
8799) std.mem.Allocator.Error!void {
8800 const func = elf.dwarf.funcs.getPtr(src_inst) orelse return;
8801 elf.resetNodeRelocs(func.fde_ni.unwrap().?);
8802 elf.resetNodeRelocs(func.debug_info_ni.unwrap().?);
8803 elf.resetNodeRelocs(func.debug_line_ni.unwrap().?);
8804 try elf.deleteNode(&func.fde_ni);
8805 try elf.deleteNode(&func.debug_info_ni);
8806 try elf.deleteNode(&func.debug_line_ni);
8807}
8808
8767pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {8809pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
8768 try elf.updateConstInner(8810 try elf.updateConstInner(
8769 pt,8811 pt,
...@@ -8996,18 +9038,18 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {...@@ -8996,18 +9038,18 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
89969038
8997 break :task;9039 break :task;
8998 }9040 }
8999 while (elf.mf.updates.pop()) |ni| {9041 while (elf.mf.updates.pop()) |ni| : (elf.mf.update_prog_node.completeOne()) {
9042 if (ni.pendingDelete(&elf.mf)) continue;
9000 const clean_moved = ni.cleanMoved(&elf.mf);9043 const clean_moved = ni.cleanMoved(&elf.mf);
9001 const clean_resized = ni.cleanResized(&elf.mf);9044 const clean_resized = ni.cleanResized(&elf.mf);
9002 const clean_next_moved = ni.cleanNextMoved(&elf.mf);9045 const clean_next_moved = ni.cleanNextMoved(&elf.mf);
9003 if (clean_moved or clean_resized or clean_next_moved) {9046 if (!clean_moved and !clean_resized and !clean_next_moved) continue;
9004 const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni));9047 const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni));
9005 defer sub_prog_node.end();9048 defer sub_prog_node.end();
9006 if (clean_moved) try elf.flushMoved(ni);9049 if (clean_moved) try elf.flushMoved(ni);
9007 if (clean_resized) try elf.flushResized(ni);9050 if (clean_resized) try elf.flushResized(ni);
9008 if (clean_next_moved) try elf.flushNextMoved(ni);9051 if (clean_next_moved) try elf.flushNextMoved(ni);
9009 break :task;9052 break :task;
9010 } else elf.mf.update_prog_node.completeOne();
9011 }9053 }
9012 }9054 }
9013 if (elf.input_sections.items.len > elf.input_section_pending_index) return true;9055 if (elf.input_sections.items.len > elf.input_section_pending_index) return true;
...@@ -9085,7 +9127,7 @@ fn idleProgNode(...@@ -9085,7 +9127,7 @@ fn idleProgNode(
9085 .func_debug_info => "debug",9127 .func_debug_info => "debug",
9086 .func_debug_line => "line",9128 .func_debug_line => "line",
9087 },9129 },
9088 ip.getNav(fi.nav(&elf.dwarf)).fqn.fmt(ip),9130 ip.getNav(fi.get(&elf.dwarf).owner_nav).fqn.fmt(ip),
9089 }) catch &name;9131 }) catch &name;
9090 },9132 },
9091 }, 0);9133 }, 0);
...@@ -9109,14 +9151,13 @@ fn genUav(...@@ -9109,14 +9151,13 @@ fn genUav(
9109 pt: Zcu.PerThread,9151 pt: Zcu.PerThread,
9110 umi: Node.UavMapIndex,9152 umi: Node.UavMapIndex,
9111) Error!void {9153) Error!void {
9112 const comp = elf.base.comp;9154 const gpa = elf.base.comp.gpa;
9113 const gpa = comp.gpa;
91149155
9115 const uav_val = umi.uavValue(elf);9156 const uav_val = umi.uavValue(elf);
9116 const ni = umi.symbol(elf).index().ptr(elf).node.unwrap().?;9157 const ni = umi.symbol(elf).index().ptr(elf).node.unwrap().?;
91179158
9118 var nw: MappedFile.Node.Writer = undefined;9159 var nw: MappedFile.Node.Writer = undefined;
9119 ni.writer(&elf.mf, gpa, &nw);9160 ni.writer(gpa, &elf.mf, &nw);
9120 defer nw.deinit();9161 defer nw.deinit();
9121 elf.resetNodeRelocs(ni);9162 elf.resetNodeRelocs(ni);
9122 codegen.generateSymbol(9163 codegen.generateSymbol(
...@@ -9150,7 +9191,7 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {...@@ -9150,7 +9191,7 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
91509191
9151 var required_alignment: InternPool.Alignment = .none;9192 var required_alignment: InternPool.Alignment = .none;
9152 var nw: MappedFile.Node.Writer = undefined;9193 var nw: MappedFile.Node.Writer = undefined;
9153 ni.writer(&elf.mf, gpa, &nw);9194 ni.writer(gpa, &elf.mf, &nw);
9154 defer nw.deinit();9195 defer nw.deinit();
9155 elf.resetNodeRelocs(ni);9196 elf.resetNodeRelocs(ni);
9156 codegen.generateLazySymbol(9197 codegen.generateLazySymbol(
...@@ -9241,7 +9282,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {...@@ -9241,7 +9282,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
9241 }),9282 }),
9242 };9283 };
9243 var nw: MappedFile.Node.Writer = undefined;9284 var nw: MappedFile.Node.Writer = undefined;
9244 isi.node(elf).writer(&elf.mf, gpa, &nw);9285 isi.node(elf).writer(gpa, &elf.mf, &nw);
9245 defer nw.deinit();9286 defer nw.deinit();
9246 const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) {9287 const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) {
9247 error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{9288 error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
...@@ -9296,17 +9337,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9296,17 +9337,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9296 defer trace.end();9337 defer trace.end();
92979338
9298 switch (elf.getNode(ni)) {9339 switch (elf.getNode(ni)) {
9299 .archive => unreachable,9340 .deleted => unreachable,
9300 .archive_header => unreachable,9341 .archive, .archive_header => unreachable,
93019342 .archive_input_member, .archive_elf_member_header, .elf => {
9302 .archive_input_member,
9303 .archive_elf_member_header,
9304 .elf,
9305 => {
9306 assert(elf.archive != null);9343 assert(elf.archive != null);
9307 return;9344 return;
9308 },9345 },
9309
9310 .ehdr, .shdr => elf.flushElfOffset(ni),9346 .ehdr, .shdr => elf.flushElfOffset(ni),
9311 .segment => |phndx| {9347 .segment => |phndx| {
9312 elf.flushElfOffset(ni);9348 elf.flushElfOffset(ni);
...@@ -9570,7 +9606,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9570,7 +9606,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9570 },9606 },
9571 .func_frame_fde => |fi| {9607 .func_frame_fde => |fi| {
9572 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];9608 const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)];
9573 const mod = elf.base.comp.zcu.?.navFileScope(fi.nav(&elf.dwarf)).mod.?;9609 const zcu = elf.base.comp.zcu.?;
9610 const mod = zcu.fileByIndex(fi.srcInst(&elf.dwarf).resolveFile(&zcu.intern_pool)).mod.?;
9574 switch (mod.unwind_tables) {9611 switch (mod.unwind_tables) {
9575 .none => {},9612 .none => {},
9576 .sync, .async => {9613 .sync, .async => {
...@@ -9594,8 +9631,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -9594,8 +9631,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
9594 }9631 }
9595 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{9632 elf.flushMovedNodeRelocs(ni, elf.computeNodeVAddr(ni), .{
9596 .first_symbol_reloc = dwarf_func.debug_info_first_symbol_reloc,9633 .first_symbol_reloc = dwarf_func.debug_info_first_symbol_reloc,
9597 .skip_symbol_relocs = if (elf.navs.getPtr(fi.nav(&elf.dwarf))) |nav|9634 .skip_symbol_relocs = if (elf.navs.getPtr(fi.get(&elf.dwarf).owner_nav)) |owner_nav|
9598 nav.lsi.index().ptr(elf).node9635 owner_nav.lsi.index().ptr(elf).node
9599 else9636 else
9600 .none,9637 .none,
9601 .first_node_reloc = dwarf_func.debug_info_first_node_reloc,9638 .first_node_reloc = dwarf_func.debug_info_first_node_reloc,
...@@ -9770,6 +9807,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo...@@ -9770,6 +9807,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
97709807
9771 _, const size = ni.location(&elf.mf).resolve(&elf.mf);9808 _, const size = ni.location(&elf.mf).resolve(&elf.mf);
9772 switch (elf.getNode(ni)) {9809 switch (elf.getNode(ni)) {
9810 .deleted => unreachable,
9773 .archive, .archive_header => {},9811 .archive, .archive_header => {},
9774 .archive_input_member => unreachable,9812 .archive_input_member => unreachable,
9775 .archive_elf_member_header => unreachable,9813 .archive_elf_member_header => unreachable,
...@@ -9869,6 +9907,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -9869,6 +9907,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
9869 defer trace.end();9907 defer trace.end();
98709908
9871 switch (elf.getNode(ni)) {9909 switch (elf.getNode(ni)) {
9910 .deleted,
9872 .archive,9911 .archive,
9873 .archive_input_member,9912 .archive_input_member,
9874 .archive_elf_member_header,9913 .archive_elf_member_header,
...@@ -10002,7 +10041,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!...@@ -10002,7 +10041,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
10002 switch (tag) {10041 switch (tag) {
10003 else => unreachable,10042 else => unreachable,
10004 .unit_debug_info_header, .value_debug_info, .global_debug_info, .func_debug_info => {10043 .unit_debug_info_header, .value_debug_info, .global_debug_info, .func_debug_info => {
10005 comptime assert(Dwarf.uleb128Bytes(@backingInt(Dwarf.AbbrevCode.null)) == 1);10044 comptime assert(Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) == 1);
10006 @memset(fw.unusedCapacitySlice(), @backingInt(Dwarf.AbbrevCode.null));10045 @memset(fw.unusedCapacitySlice(), @backingInt(Dwarf.AbbrevCode.null));
10007 },10046 },
10008 .unit_debug_line_header, .func_debug_line => Dwarf.genDebugLinePadding(&fw, fw.unusedCapacityLen()) catch10047 .unit_debug_line_header, .func_debug_line => Dwarf.genDebugLinePadding(&fw, fw.unusedCapacityLen()) catch
...@@ -10591,10 +10630,10 @@ pub fn printNode(...@@ -10591,10 +10630,10 @@ pub fn printNode(
10591 .func_frame_fde, .func_debug_info, .func_debug_line => |fi| {10630 .func_frame_fde, .func_debug_info, .func_debug_line => |fi| {
10592 const zcu = elf.base.comp.zcu.?;10631 const zcu = elf.base.comp.zcu.?;
10593 const ip = &zcu.intern_pool;10632 const ip = &zcu.intern_pool;
10594 const nav = ip.getNav(fi.nav(&elf.dwarf));10633 const owner_nav = ip.getNav(fi.get(&elf.dwarf).owner_nav);
10595 try w.print("({f}, {f})", .{10634 try w.print("({f}, {f})", .{
10596 Type.fromInterned(nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),10635 Type.fromInterned(owner_nav.resolved.?.type).fmt(.{ .zcu = zcu, .tid = tid }),
10597 nav.fqn.fmt(ip),10636 owner_nav.fqn.fmt(ip),
10598 });10637 });
10599 },10638 },
10600 }10639 }
...@@ -10655,7 +10694,7 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error...@@ -10655,7 +10694,7 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error
10655 // Align the actual node10694 // Align the actual node
10656 const seg_ni = elf.phdrs.items[phndx].unwrap().?;10695 const seg_ni = elf.phdrs.items[phndx].unwrap().?;
10657 if (min_align.compare(.gt, seg_ni.alignment(&elf.mf))) {10696 if (min_align.compare(.gt, seg_ni.alignment(&elf.mf))) {
10658 try seg_ni.realign(&elf.mf, gpa, min_align);10697 try seg_ni.realign(gpa, &elf.mf, min_align);
10659 }10698 }
10660 // Update the phdr `@"align"` field if necessary10699 // Update the phdr `@"align"` field if necessary
10661 switch (elf.phdrSlice()) {10700 switch (elf.phdrSlice()) {
...@@ -10686,6 +10725,21 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error...@@ -10686,6 +10725,21 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error
10686 }10725 }
10687}10726}
1068810727
10728pub fn addNodeAssumeCapacity(elf: *Elf, ni: MappedFile.Node.Index, node: Node) MappedFile.Node.Index {
10729 if (elf.nodes.len - @backingInt(ni) > 0) {
10730 assert(elf.getNode(ni) == .deleted);
10731 elf.nodes.set(@backingInt(ni), node);
10732 } else elf.nodes.appendAssumeCapacity(node);
10733 return ni;
10734}
10735
10736fn deleteNode(elf: *Elf, node: *MappedFile.Node.Index.Optional) std.mem.Allocator.Error!void {
10737 const ni = node.unwrap().?;
10738 try ni.delete(elf.base.comp.gpa, &elf.mf);
10739 elf.nodes.set(@backingInt(ni), .deleted);
10740 node.* = .none;
10741}
10742
10689/// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a10743/// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a
10690/// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`.10744/// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`.
10691fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 {10745fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 {
src/link/MappedFile.zig+69-56
...@@ -362,7 +362,7 @@ pub const Node = extern struct {...@@ -362,7 +362,7 @@ pub const Node = extern struct {
362 }362 }
363363
364 /// Adds a floating child node to `parent_ni`. Returns the index of the new child.364 /// Adds a floating child node to `parent_ni`. Returns the index of the new child.
365 pub fn addFloatingChild(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, opts: AddOptions) Error!Node.Index {365 pub fn addFloatingChild(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, opts: AddOptions) Error!Node.Index {
366 return mf.addNode(gpa, .{366 return mf.addNode(gpa, .{
367 .add_options = opts,367 .add_options = opts,
368 .position = .floating,368 .position = .floating,
...@@ -373,11 +373,11 @@ pub const Node = extern struct {...@@ -373,11 +373,11 @@ pub const Node = extern struct {
373 /// Adds a header child node to `parent_ni`. Returns the index of the new child.373 /// Adds a header child node to `parent_ni`. Returns the index of the new child.
374 ///374 ///
375 /// Asserts that `parent_ni` has no existing header children.375 /// Asserts that `parent_ni` has no existing header children.
376 pub fn addOnlyHeaderChild(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, opts: AddOptions) Error!Node.Index {376 pub fn addOnlyHeaderChild(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, opts: AddOptions) Error!Node.Index {
377 if (parent_ni.first(mf).unwrap()) |first_ni| {377 if (parent_ni.first(mf).unwrap()) |first_ni| {
378 assert(first_ni.position(mf) != .header); // `parent_ni` already has a header child378 assert(first_ni.position(mf) != .header); // `parent_ni` already has a header child
379 }379 }
380 return parent_ni.addHeaderChildAfter(mf, gpa, .none, opts);380 return parent_ni.addHeaderChildAfter(gpa, mf, .none, opts);
381 }381 }
382 /// Adds a header child node to `parent_ni`. Returns the index of the new child.382 /// Adds a header child node to `parent_ni`. Returns the index of the new child.
383 ///383 ///
...@@ -386,7 +386,7 @@ pub const Node = extern struct {...@@ -386,7 +386,7 @@ pub const Node = extern struct {
386 ///386 ///
387 /// Otherwise, asserts that `prev_oni` is a header node and a child of `parent_ni`, and387 /// Otherwise, asserts that `prev_oni` is a header node and a child of `parent_ni`, and
388 /// places the new child node immediately after `prev_oni`.388 /// places the new child node immediately after `prev_oni`.
389 pub fn addHeaderChildAfter(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, prev_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index {389 pub fn addHeaderChildAfter(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, prev_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index {
390 return mf.addNode(gpa, .{390 return mf.addNode(gpa, .{
391 .add_options = opts,391 .add_options = opts,
392 .position = .header,392 .position = .header,
...@@ -397,11 +397,11 @@ pub const Node = extern struct {...@@ -397,11 +397,11 @@ pub const Node = extern struct {
397 /// Adds a footer child node to `parent_ni`. Returns the index of the new child.397 /// Adds a footer child node to `parent_ni`. Returns the index of the new child.
398 ///398 ///
399 /// Asserts that `parent_ni` has no existing footer children.399 /// Asserts that `parent_ni` has no existing footer children.
400 pub fn addOnlyFooterChild(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, opts: AddOptions) Error!Node.Index {400 pub fn addOnlyFooterChild(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, opts: AddOptions) Error!Node.Index {
401 if (parent_ni.last(mf).unwrap()) |last_ni| {401 if (parent_ni.last(mf).unwrap()) |last_ni| {
402 assert(last_ni.position(mf) != .footer); // `parent_ni` already has a footer child402 assert(last_ni.position(mf) != .footer); // `parent_ni` already has a footer child
403 }403 }
404 return parent_ni.addFooterChildBefore(mf, gpa, .none, opts);404 return parent_ni.addFooterChildBefore(gpa, mf, .none, opts);
405 }405 }
406 /// Adds a footer child node to `parent_ni`. Returns the index of the new child.406 /// Adds a footer child node to `parent_ni`. Returns the index of the new child.
407 ///407 ///
...@@ -410,7 +410,7 @@ pub const Node = extern struct {...@@ -410,7 +410,7 @@ pub const Node = extern struct {
410 ///410 ///
411 /// Otherwise, asserts that `next_oni` is a footer node and a child of `parent_ni`, and411 /// Otherwise, asserts that `next_oni` is a footer node and a child of `parent_ni`, and
412 /// places the new child node immediately before `next_oni`.412 /// places the new child node immediately before `next_oni`.
413 pub fn addFooterChildBefore(parent_ni: Node.Index, mf: *MappedFile, gpa: Allocator, next_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index {413 pub fn addFooterChildBefore(parent_ni: Node.Index, gpa: Allocator, mf: *MappedFile, next_oni: Node.Index.Optional, opts: AddOptions) Error!Node.Index {
414 const prev_oni: Node.Index.Optional = prev: {414 const prev_oni: Node.Index.Optional = prev: {
415 const next_ni = next_oni.unwrap() orelse {415 const next_ni = next_oni.unwrap() orelse {
416 break :prev parent_ni.last(mf);416 break :prev parent_ni.last(mf);
...@@ -473,8 +473,8 @@ pub const Node = extern struct {...@@ -473,8 +473,8 @@ pub const Node = extern struct {
473 fn setNext(473 fn setNext(
474 ni: Node.Index,474 ni: Node.Index,
475 gpa: Allocator,475 gpa: Allocator,
476 next_ni: Node.Index.Optional,
477 mf: *MappedFile,476 mf: *MappedFile,
477 next_ni: Node.Index.Optional,
478 ) Allocator.Error!void {478 ) Allocator.Error!void {
479 const next_ptr = &ni.get(mf).next;479 const next_ptr = &ni.get(mf).next;
480 if (next_ptr.* == next_ni) return;480 if (next_ptr.* == next_ni) return;
...@@ -571,7 +571,7 @@ pub const Node = extern struct {...@@ -571,7 +571,7 @@ pub const Node = extern struct {
571 return ni.get(mf).flags.alignment;571 return ni.get(mf).flags.alignment;
572 }572 }
573573
574 fn setLocation(ni: Node.Index, mf: *MappedFile, gpa: Allocator, offset: u64, size: u64) Allocator.Error!void {574 fn setLocation(ni: Node.Index, gpa: Allocator, mf: *MappedFile, offset: u64, size: u64) Allocator.Error!void {
575 try mf.large.ensureUnusedCapacity(gpa, 2);575 try mf.large.ensureUnusedCapacity(gpa, 2);
576 try mf.updates.ensureUnusedCapacity(gpa, 2);576 try mf.updates.ensureUnusedCapacity(gpa, 2);
577 const node = ni.get(mf);577 const node = ni.get(mf);
...@@ -646,19 +646,37 @@ pub const Node = extern struct {...@@ -646,19 +646,37 @@ pub const Node = extern struct {
646 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];646 return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)];
647 }647 }
648648
649 pub fn trimStart(ni: Node.Index, mf: *MappedFile, gpa: Allocator) Allocator.Error!void {649 pub fn delete(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
650 const node = ni.get(mf);
651 assert(node.first == .none and node.last == .none); // has children
652 mf.removeNodesFromChildList(gpa, ni, ni);
653 const updated = node.flags.moved or node.flags.resized or node.flags.next_moved;
654 node.* = undefined;
655 node.next = ni.toOptional();
656 if (!updated) assert(ni.pendingDelete(mf));
657 }
658
659 pub fn pendingDelete(ni: Node.Index, mf: *MappedFile) bool {
660 const node = ni.get(mf);
661 if (node.next != ni.toOptional()) return false;
662 node.next = mf.free_ni;
663 mf.free_ni = ni.toOptional();
664 return true;
665 }
666
667 pub fn trimStart(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void {
650 mf.nodes_lock.assertUnlocked();668 mf.nodes_lock.assertUnlocked();
651 const node = ni.get(mf);669 const node = ni.get(mf);
652 const first_ni = node.first.unwrap() orelse return;670 const first_ni = node.first.unwrap() orelse return;
653 const shift, _ = first_ni.location(mf).resolve(mf);671 const shift, _ = first_ni.location(mf).resolve(mf);
654 if (shift == 0) return;672 if (shift == 0) return;
655 const offset, const size = node.location().resolve(mf);673 const offset, const size = node.location().resolve(mf);
656 try ni.setLocation(mf, gpa, offset + shift, size - shift);674 try ni.setLocation(gpa, mf, offset + shift, size - shift);
657 var child_oni = node.first;675 var child_oni = node.first;
658 while (child_oni.unwrap()) |child_ni| {676 while (child_oni.unwrap()) |child_ni| {
659 const child_node = child_ni.get(mf);677 const child_node = child_ni.get(mf);
660 const child_offset, const child_size = child_node.location().resolve(mf);678 const child_offset, const child_size = child_node.location().resolve(mf);
661 try child_ni.setLocation(mf, gpa, child_offset - shift, child_size);679 try child_ni.setLocation(gpa, mf, child_offset - shift, child_size);
662 child_oni = child_node.next;680 child_oni = child_node.next;
663 }681 }
664 }682 }
...@@ -666,7 +684,7 @@ pub const Node = extern struct {...@@ -666,7 +684,7 @@ pub const Node = extern struct {
666 /// Ensures that the size of `ni` is at least `min_size`. Valid for any node.684 /// Ensures that the size of `ni` is at least `min_size`. Valid for any node.
667 ///685 ///
668 /// Applies `growth_factor` if necessary (so the caller should *not* apply `growth_factor`).686 /// Applies `growth_factor` if necessary (so the caller should *not* apply `growth_factor`).
669 pub fn ensureMinimumSize(ni: Node.Index, mf: *MappedFile, gpa: Allocator, min_size: u64) Error!void {687 pub fn ensureMinimumSize(ni: Node.Index, gpa: Allocator, mf: *MappedFile, min_size: u64) Error!void {
670 _, const current_size = ni.location(mf).resolve(mf);688 _, const current_size = ni.location(mf).resolve(mf);
671 if (current_size >= min_size) return;689 if (current_size >= min_size) return;
672 const new_size = ni.alignment(mf).forward(min_size +| min_size / growth_factor);690 const new_size = ni.alignment(mf).forward(min_size +| min_size / growth_factor);
...@@ -682,7 +700,7 @@ pub const Node = extern struct {...@@ -682,7 +700,7 @@ pub const Node = extern struct {
682 /// Asserts that `ni` is a leaf node, i.e. has no children.700 /// Asserts that `ni` is a leaf node, i.e. has no children.
683 ///701 ///
684 /// Asserts that `size` is aligned to `ni.alignment(mf)`.702 /// Asserts that `size` is aligned to `ni.alignment(mf)`.
685 pub fn resizeLeaf(ni: Node.Index, mf: *MappedFile, gpa: Allocator, size: u64) Error!void {703 pub fn resizeLeaf(ni: Node.Index, gpa: Allocator, mf: *MappedFile, size: u64) Error!void {
686 assert(ni.first(mf) == .none);704 assert(ni.first(mf) == .none);
687 // The alignment of `size` is asserted by `shrinkLeafNode` and `growNode`.705 // The alignment of `size` is asserted by `shrinkLeafNode` and `growNode`.
688 _, const old_size = ni.location(mf).resolve(mf);706 _, const old_size = ni.location(mf).resolve(mf);
...@@ -702,17 +720,12 @@ pub const Node = extern struct {...@@ -702,17 +720,12 @@ pub const Node = extern struct {
702 /// If the node's current offset or size is not sufficiently aligned, it will be moved720 /// If the node's current offset or size is not sufficiently aligned, it will be moved
703 /// and/or resized to match the new alignment. The node's size may be increased by any721 /// and/or resized to match the new alignment. The node's size may be increased by any
704 /// amount, as if `ensureMinimumSize` were used.722 /// amount, as if `ensureMinimumSize` were used.
705 pub fn realign(723 pub fn realign(ni: Node.Index, gpa: Allocator, mf: *MappedFile, new_alignment: Alignment) Error!void {
706 ni: Node.Index,
707 mf: *MappedFile,
708 gpa: Allocator,
709 new_alignment: Alignment,
710 ) Error!void {
711 try mf.realignNode(gpa, ni, new_alignment);724 try mf.realignNode(gpa, ni, new_alignment);
712 mf.updateWriters();725 mf.updateWriters();
713 }726 }
714727
715 pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: Allocator, w: *Writer) void {728 pub fn writer(ni: Node.Index, gpa: Allocator, mf: *MappedFile, w: *Writer) void {
716 w.* = .{729 w.* = .{
717 .gpa = gpa,730 .gpa = gpa,
718 .mf = mf,731 .mf = mf,
...@@ -842,7 +855,7 @@ pub const Node = extern struct {...@@ -842,7 +855,7 @@ pub const Node = extern struct {
842 ) Io.Writer.Error!void {855 ) Io.Writer.Error!void {
843 _ = preserve;856 _ = preserve;
844 const w: *Writer = @fieldParentPtr("interface", interface);857 const w: *Writer = @fieldParentPtr("interface", interface);
845 w.ni.ensureMinimumSize(w.mf, w.gpa, interface.end + unused_capacity) catch |err| {858 w.ni.ensureMinimumSize(w.gpa, w.mf, interface.end + unused_capacity) catch |err| {
846 w.err = err;859 w.err = err;
847 return error.WriteFailed;860 return error.WriteFailed;
848 };861 };
...@@ -1014,7 +1027,7 @@ fn shrinkLeafNode(...@@ -1014,7 +1027,7 @@ fn shrinkLeafNode(
1014 },1027 },
1015 };1028 };
1016 try mf.ensureTotalCapacityPrecise(@intCast(new_size));1029 try mf.ensureTotalCapacityPrecise(@intCast(new_size));
1017 try ni.setLocation(mf, gpa, old_offset, new_size);1030 try ni.setLocation(gpa, mf, old_offset, new_size);
1018 return;1031 return;
1019 };1032 };
10201033
...@@ -1022,7 +1035,7 @@ fn shrinkLeafNode(...@@ -1022,7 +1035,7 @@ fn shrinkLeafNode(
1022 .header => {1035 .header => {
1023 const shift = old_size - new_size;1036 const shift = old_size - new_size;
10241037
1025 try ni.setLocation(mf, gpa, old_offset, new_size);1038 try ni.setLocation(gpa, mf, old_offset, new_size);
10261039
1027 // We need to shift backwards all header nodes following us.1040 // We need to shift backwards all header nodes following us.
1028 const next_header_ni = ni.next(mf).unwrap() orelse return;1041 const next_header_ni = ni.next(mf).unwrap() orelse return;
...@@ -1031,7 +1044,7 @@ fn shrinkLeafNode(...@@ -1031,7 +1044,7 @@ fn shrinkLeafNode(
1031 var header_ni = next_header_ni;1044 var header_ni = next_header_ni;
1032 while (true) {1045 while (true) {
1033 const old_header_off, const old_header_size = header_ni.location(mf).resolve(mf);1046 const old_header_off, const old_header_size = header_ni.location(mf).resolve(mf);
1034 try header_ni.setLocation(mf, gpa, old_header_off - shift, old_header_size);1047 try header_ni.setLocation(gpa, mf, old_header_off - shift, old_header_size);
10351048
1036 const next_ni = header_ni.next(mf).unwrap() orelse break;1049 const next_ni = header_ni.next(mf).unwrap() orelse break;
1037 if (next_ni.position(mf) != .header) break;1050 if (next_ni.position(mf) != .header) break;
...@@ -1056,13 +1069,13 @@ fn shrinkLeafNode(...@@ -1056,13 +1069,13 @@ fn shrinkLeafNode(
1056 );1069 );
1057 },1070 },
1058 .floating => {1071 .floating => {
1059 try ni.setLocation(mf, gpa, old_offset, new_size);1072 try ni.setLocation(gpa, mf, old_offset, new_size);
1060 },1073 },
1061 .footer => {1074 .footer => {
1062 const shift = old_size - new_size;1075 const shift = old_size - new_size;
10631076
1064 const new_offset = old_offset + shift;1077 const new_offset = old_offset + shift;
1065 try ni.setLocation(mf, gpa, new_offset, new_size);1078 try ni.setLocation(gpa, mf, new_offset, new_size);
10661079
1067 const prev_footers_size = prev_footers_size: {1080 const prev_footers_size = prev_footers_size: {
1068 // We need to shift forwards all footer nodes preceding us.1081 // We need to shift forwards all footer nodes preceding us.
...@@ -1076,7 +1089,7 @@ fn shrinkLeafNode(...@@ -1076,7 +1089,7 @@ fn shrinkLeafNode(
1076 var footer_ni = prev_footer_ni;1089 var footer_ni = prev_footer_ni;
1077 while (true) {1090 while (true) {
1078 const old_footer_off, const old_footer_size = footer_ni.location(mf).resolve(mf);1091 const old_footer_off, const old_footer_size = footer_ni.location(mf).resolve(mf);
1079 try footer_ni.setLocation(mf, gpa, old_footer_off + shift, old_footer_size);1092 try footer_ni.setLocation(gpa, mf, old_footer_off + shift, old_footer_size);
10801093
1081 const prev_ni = footer_ni.prev(mf).unwrap() orelse break;1094 const prev_ni = footer_ni.prev(mf).unwrap() orelse break;
1082 if (prev_ni.position(mf) != .footer) break;1095 if (prev_ni.position(mf) != .footer) break;
...@@ -1159,7 +1172,7 @@ fn growNode(...@@ -1159,7 +1172,7 @@ fn growNode(
1159 },1172 },
1160 };1173 };
1161 try mf.ensureTotalCapacityPrecise(@intCast(new_size));1174 try mf.ensureTotalCapacityPrecise(@intCast(new_size));
1162 try ni.setLocation(mf, gpa, old_offset, new_size);1175 try ni.setLocation(gpa, mf, old_offset, new_size);
1163 if (grow_options.move_footers) {1176 if (grow_options.move_footers) {
1164 // We need to move any footers to be at the *new* end of the file.1177 // We need to move any footers to be at the *new* end of the file.
1165 if (ni.firstFooter(mf).unwrap()) |first_footer_ni| {1178 if (ni.firstFooter(mf).unwrap()) |first_footer_ni| {
...@@ -1174,7 +1187,7 @@ fn growNode(...@@ -1174,7 +1187,7 @@ fn growNode(
1174 var cur_ni = first_footer_ni;1187 var cur_ni = first_footer_ni;
1175 while (true) {1188 while (true) {
1176 const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf);1189 const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf);
1177 try cur_ni.setLocation(mf, gpa, old_footer_offset + (new_size - old_size), footer_size);1190 try cur_ni.setLocation(gpa, mf, old_footer_offset + (new_size - old_size), footer_size);
1178 cur_ni = cur_ni.next(mf).unwrap() orelse break;1191 cur_ni = cur_ni.next(mf).unwrap() orelse break;
1179 }1192 }
1180 }1193 }
...@@ -1233,8 +1246,8 @@ fn growNode(...@@ -1233,8 +1246,8 @@ fn growNode(
1233 while (true) {1246 while (true) {
1234 const old_sub_footer_offset, const sub_footer_size = cur_ni.location(mf).resolve(mf);1247 const old_sub_footer_offset, const sub_footer_size = cur_ni.location(mf).resolve(mf);
1235 try cur_ni.setLocation(1248 try cur_ni.setLocation(
1236 mf,
1237 gpa,1249 gpa,
1250 mf,
1238 old_sub_footer_offset + (new_size - old_size),1251 old_sub_footer_offset + (new_size - old_size),
1239 sub_footer_size,1252 sub_footer_size,
1240 );1253 );
...@@ -1249,8 +1262,8 @@ fn growNode(...@@ -1249,8 +1262,8 @@ fn growNode(
1249 assert(moved_header_ni.position(mf) == .header);1262 assert(moved_header_ni.position(mf) == .header);
1250 const moved_header_offset, const moved_header_size = moved_header_ni.location(mf).resolve(mf);1263 const moved_header_offset, const moved_header_size = moved_header_ni.location(mf).resolve(mf);
1251 try moved_header_ni.setLocation(1264 try moved_header_ni.setLocation(
1252 mf,
1253 gpa,1265 gpa,
1266 mf,
1254 moved_header_offset - old_size + new_size,1267 moved_header_offset - old_size + new_size,
1255 moved_header_size,1268 moved_header_size,
1256 );1269 );
...@@ -1259,7 +1272,7 @@ fn growNode(...@@ -1259,7 +1272,7 @@ fn growNode(
1259 }1272 }
12601273
1261 // Finally, update our own size:1274 // Finally, update our own size:
1262 try ni.setLocation(mf, gpa, old_offset, new_size);1275 try ni.setLocation(gpa, mf, old_offset, new_size);
1263 return;1276 return;
1264 },1277 },
1265 .floating => {1278 .floating => {
...@@ -1387,8 +1400,8 @@ fn growNode(...@@ -1387,8 +1400,8 @@ fn growNode(
13871400
1388 // Update our own offset and size:1401 // Update our own offset and size:
1389 try ni.setLocation(1402 try ni.setLocation(
1390 mf,
1391 gpa,1403 gpa,
1404 mf,
1392 node.location().resolve(mf)[0] - shift,1405 node.location().resolve(mf)[0] - shift,
1393 new_size,1406 new_size,
1394 );1407 );
...@@ -1399,7 +1412,7 @@ fn growNode(...@@ -1399,7 +1412,7 @@ fn growNode(
1399 var footer_oni = first_sub_footer_oni;1412 var footer_oni = first_sub_footer_oni;
1400 while (footer_oni.unwrap()) |footer_ni| : (footer_oni = footer_ni.next(mf)) {1413 while (footer_oni.unwrap()) |footer_ni| : (footer_oni = footer_ni.next(mf)) {
1401 const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf);1414 const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf);
1402 try footer_ni.setLocation(mf, gpa, old_footer_offset + shift, footer_size);1415 try footer_ni.setLocation(gpa, mf, old_footer_offset + shift, footer_size);
1403 }1416 }
1404 }1417 }
14051418
...@@ -1414,7 +1427,7 @@ fn growNode(...@@ -1414,7 +1427,7 @@ fn growNode(
1414 while (footer_ni != ni) : (footer_ni = footer_ni.next(mf).unwrap().?) {1427 while (footer_ni != ni) : (footer_ni = footer_ni.next(mf).unwrap().?) {
1415 moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content;1428 moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content;
1416 const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf);1429 const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf);
1417 try footer_ni.setLocation(mf, gpa, old_footer_offset - shift, footer_size);1430 try footer_ni.setLocation(gpa, mf, old_footer_offset - shift, footer_size);
1418 }1431 }
1419 }1432 }
14201433
...@@ -1466,8 +1479,8 @@ fn growNode(...@@ -1466,8 +1479,8 @@ fn growNode(
1466 }1479 }
14671480
1468 try ni.setLocation(1481 try ni.setLocation(
1469 mf,
1470 gpa,1482 gpa,
1483 mf,
1471 node.location().resolve(mf)[0],1484 node.location().resolve(mf)[0],
1472 actual_new_size,1485 actual_new_size,
1473 );1486 );
...@@ -1483,7 +1496,7 @@ fn growNode(...@@ -1483,7 +1496,7 @@ fn growNode(
1483 assert(footer_ni.position(mf) == .footer);1496 assert(footer_ni.position(mf) == .footer);
1484 moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content;1497 moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content;
1485 const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf);1498 const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf);
1486 try footer_ni.setLocation(mf, gpa, footer_old_offset + shift, footer_size);1499 try footer_ni.setLocation(gpa, mf, footer_old_offset + shift, footer_size);
1487 }1500 }
1488 }1501 }
14891502
...@@ -1494,7 +1507,7 @@ fn growNode(...@@ -1494,7 +1507,7 @@ fn growNode(
1494 assert(footer_ni.position(mf) == .footer);1507 assert(footer_ni.position(mf) == .footer);
1495 moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content;1508 moved_has_content = moved_has_content or footer_ni.get(mf).flags.has_content;
1496 const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf);1509 const footer_old_offset: u64, const footer_size: u64 = footer_ni.location(mf).resolve(mf);
1497 try footer_ni.setLocation(mf, gpa, footer_old_offset + shift, footer_size);1510 try footer_ni.setLocation(gpa, mf, footer_old_offset + shift, footer_size);
1498 }1511 }
1499 }1512 }
15001513
...@@ -1566,7 +1579,7 @@ fn growFloatingNodeWithAlignment(...@@ -1566,7 +1579,7 @@ fn growFloatingNodeWithAlignment(
1566 break :grow_in_place; // the parent is not big enough1579 break :grow_in_place; // the parent is not big enough
1567 }1580 }
1568 // Great, we can grow this node without changing its offset or moving any siblings.1581 // Great, we can grow this node without changing its offset or moving any siblings.
1569 try ni.setLocation(mf, gpa, old_offset, new_size);1582 try ni.setLocation(gpa, mf, old_offset, new_size);
1570 if (grow_options.move_footers) {1583 if (grow_options.move_footers) {
1571 // If we have any footers, we need to move them to the end of our new size, and update1584 // If we have any footers, we need to move them to the end of our new size, and update
1572 // their offsets accordingly.1585 // their offsets accordingly.
...@@ -1576,7 +1589,7 @@ fn growFloatingNodeWithAlignment(...@@ -1576,7 +1589,7 @@ fn growFloatingNodeWithAlignment(
1576 while (true) {1589 while (true) {
1577 footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content;1590 footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content;
1578 const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf);1591 const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf);
1579 try cur_ni.setLocation(mf, gpa, old_footer_offset + (new_size - old_size), footer_size);1592 try cur_ni.setLocation(gpa, mf, old_footer_offset + (new_size - old_size), footer_size);
1580 cur_ni = cur_ni.next(mf).unwrap() orelse break;1593 cur_ni = cur_ni.next(mf).unwrap() orelse break;
1581 }1594 }
1582 if (footers_have_content) {1595 if (footers_have_content) {
...@@ -1713,7 +1726,7 @@ fn growFloatingNodeWithAlignment(...@@ -1713,7 +1726,7 @@ fn growFloatingNodeWithAlignment(
1713 footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content;1726 footers_have_content = footers_have_content or cur_ni.get(mf).flags.has_content;
1714 const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf);1727 const old_footer_offset, const footer_size = cur_ni.location(mf).resolve(mf);
1715 // Our footers' offsets must change to be at the end of our new size.1728 // Our footers' offsets must change to be at the end of our new size.
1716 try cur_ni.setLocation(mf, gpa, old_footer_offset + (new_size - old_size), footer_size);1729 try cur_ni.setLocation(gpa, mf, old_footer_offset + (new_size - old_size), footer_size);
1717 cur_ni = cur_ni.next(mf).unwrap() orelse break;1730 cur_ni = cur_ni.next(mf).unwrap() orelse break;
1718 }1731 }
17191732
...@@ -1740,7 +1753,7 @@ fn growFloatingNodeWithAlignment(...@@ -1740,7 +1753,7 @@ fn growFloatingNodeWithAlignment(
1740 assert(!footers_have_content);1753 assert(!footers_have_content);
1741 }1754 }
17421755
1743 try ni.setLocation(mf, gpa, new_loc.offset, new_size);1756 try ni.setLocation(gpa, mf, new_loc.offset, new_size);
17441757
1745 if (new_loc.prev != ni.toOptional()) {1758 if (new_loc.prev != ni.toOptional()) {
1746 // We're potentially in a different place in `parent_ni`'s child list, so remove and re-add ourselves.1759 // We're potentially in a different place in `parent_ni`'s child list, so remove and re-add ourselves.
...@@ -1940,11 +1953,11 @@ fn growNodeViaInsertRange(...@@ -1940,11 +1953,11 @@ fn growNodeViaInsertRange(
1940 if (cur_ni == .root) {1953 if (cur_ni == .root) {
1941 try mf.ensureTotalCapacityPrecise(@intCast(this_old_size + range_size));1954 try mf.ensureTotalCapacityPrecise(@intCast(this_old_size + range_size));
1942 }1955 }
1943 try cur_ni.setLocation(mf, gpa, this_offset, this_old_size + range_size);1956 try cur_ni.setLocation(gpa, mf, this_offset, this_old_size + range_size);
19441957
1945 while (cur_ni.next(mf).unwrap()) |next_ni| {1958 while (cur_ni.next(mf).unwrap()) |next_ni| {
1946 const next_old_offset, const next_size = next_ni.location(mf).resolve(mf);1959 const next_old_offset, const next_size = next_ni.location(mf).resolve(mf);
1947 try next_ni.setLocation(mf, gpa, next_old_offset + range_size, next_size);1960 try next_ni.setLocation(gpa, mf, next_old_offset + range_size, next_size);
1948 cur_ni = next_ni;1961 cur_ni = next_ni;
1949 }1962 }
19501963
...@@ -1957,7 +1970,7 @@ fn growNodeViaInsertRange(...@@ -1957,7 +1970,7 @@ fn growNodeViaInsertRange(
1957 var footer_ni = first_footer_ni;1970 var footer_ni = first_footer_ni;
1958 while (true) {1971 while (true) {
1959 const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf);1972 const old_footer_offset, const footer_size = footer_ni.location(mf).resolve(mf);
1960 try footer_ni.setLocation(mf, gpa, old_footer_offset + range_size, footer_size);1973 try footer_ni.setLocation(gpa, mf, old_footer_offset + range_size, footer_size);
1961 footer_ni = footer_ni.next(mf).unwrap() orelse break;1974 footer_ni = footer_ni.next(mf).unwrap() orelse break;
1962 }1975 }
1963 }1976 }
...@@ -2125,7 +2138,7 @@ fn ensureAdditionalHeaderCapacity(...@@ -2125,7 +2138,7 @@ fn ensureAdditionalHeaderCapacity(
2125 const old_offset, const old_size = cur_ni.location(mf).resolve(mf);2138 const old_offset, const old_size = cur_ni.location(mf).resolve(mf);
2126 const new_offset = old_offset - moving_offset + dest_offset;2139 const new_offset = old_offset - moving_offset + dest_offset;
2127 assert(cur_ni.alignment(mf).check(new_offset));2140 assert(cur_ni.alignment(mf).check(new_offset));
2128 try cur_ni.setLocation(mf, gpa, new_offset, old_size);2141 try cur_ni.setLocation(gpa, mf, new_offset, old_size);
2129 if (cur_ni == last_moving_ni) break;2142 if (cur_ni == last_moving_ni) break;
2130 cur_ni = cur_ni.next(mf).unwrap().?;2143 cur_ni = cur_ni.next(mf).unwrap().?;
2131 }2144 }
...@@ -2168,7 +2181,7 @@ fn removeNodesFromChildList(...@@ -2168,7 +2181,7 @@ fn removeNodesFromChildList(
21682181
2169 if (prev_oni.unwrap()) |prev_ni| {2182 if (prev_oni.unwrap()) |prev_ni| {
2170 assert(prev_ni.next(mf).unwrap().? == first_remove_ni);2183 assert(prev_ni.next(mf).unwrap().? == first_remove_ni);
2171 try prev_ni.setNext(gpa, next_oni, mf);2184 try prev_ni.setNext(gpa, mf, next_oni);
2172 } else {2185 } else {
2173 assert(parent_ni.first(mf).unwrap().? == first_remove_ni);2186 assert(parent_ni.first(mf).unwrap().? == first_remove_ni);
2174 parent_ni.get(mf).first = next_oni;2187 parent_ni.get(mf).first = next_oni;
...@@ -2207,11 +2220,11 @@ fn addNodesToChildListBefore(...@@ -2207,11 +2220,11 @@ fn addNodesToChildListBefore(
2207 };2220 };
22082221
2209 first_add_ni.get(mf).prev = prev_oni;2222 first_add_ni.get(mf).prev = prev_oni;
2210 try last_add_ni.setNext(gpa, next_oni, mf);2223 try last_add_ni.setNext(gpa, mf, next_oni);
22112224
2212 if (prev_oni.unwrap()) |prev_ni| {2225 if (prev_oni.unwrap()) |prev_ni| {
2213 assert(prev_ni.next(mf) == next_oni);2226 assert(prev_ni.next(mf) == next_oni);
2214 try prev_ni.setNext(gpa, .wrap(first_add_ni), mf);2227 try prev_ni.setNext(gpa, mf, .wrap(first_add_ni));
2215 } else {2228 } else {
2216 assert(parent_ni.first(mf) == next_oni);2229 assert(parent_ni.first(mf) == next_oni);
2217 parent_ni.get(mf).first = .wrap(first_add_ni);2230 parent_ni.get(mf).first = .wrap(first_add_ni);
...@@ -2652,7 +2665,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {...@@ -2652,7 +2665,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {
2652 for (1..n) |_| cur_ni = cur_ni.next(&mf).unwrap().?;2665 for (1..n) |_| cur_ni = cur_ni.next(&mf).unwrap().?;
2653 break :prev_oni .wrap(cur_ni);2666 break :prev_oni .wrap(cur_ni);
2654 };2667 };
2655 const new_ni = try parent_ni.addHeaderChildAfter(&mf, gpa, prev_oni, .{2668 const new_ni = try parent_ni.addHeaderChildAfter(gpa, &mf, prev_oni, .{
2656 .size = size,2669 .size = size,
2657 .alignment = alignment,2670 .alignment = alignment,
2658 });2671 });
...@@ -2660,7 +2673,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {...@@ -2660,7 +2673,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {
2660 break :new_ni new_ni;2673 break :new_ni new_ni;
2661 },2674 },
26622675
2663 .floating => try parent_ni.addFloatingChild(&mf, gpa, .{2676 .floating => try parent_ni.addFloatingChild(gpa, &mf, .{
2664 .size = size,2677 .size = size,
2665 .alignment = alignment,2678 .alignment = alignment,
2666 }),2679 }),
...@@ -2674,7 +2687,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {...@@ -2674,7 +2687,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {
2674 for (1..n) |_| cur_ni = cur_ni.prev(&mf).unwrap().?;2687 for (1..n) |_| cur_ni = cur_ni.prev(&mf).unwrap().?;
2675 break :next_oni .wrap(cur_ni);2688 break :next_oni .wrap(cur_ni);
2676 };2689 };
2677 const new_ni = try parent_ni.addFooterChildBefore(&mf, gpa, next_oni, .{2690 const new_ni = try parent_ni.addFooterChildBefore(gpa, &mf, next_oni, .{
2678 .size = size,2691 .size = size,
2679 .alignment = alignment,2692 .alignment = alignment,
2680 });2693 });
...@@ -2708,13 +2721,13 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {...@@ -2708,13 +2721,13 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {
2708 if (ni.first(&mf) == .none and smith.value(bool)) {2721 if (ni.first(&mf) == .none and smith.value(bool)) {
2709 // Since this is a leaf node, we can use `resizeLeaf`.2722 // Since this is a leaf node, we can use `resizeLeaf`.
2710 const new_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights));2723 const new_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights));
2711 try ni.resizeLeaf(&mf, gpa, new_size);2724 try ni.resizeLeaf(gpa, &mf, new_size);
2712 if (new_size == 0) {2725 if (new_size == 0) {
2713 node_info.initialized = false;2726 node_info.initialized = false;
2714 }2727 }
2715 } else {2728 } else {
2716 const min_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights));2729 const min_size = alignment.forward(smith.valueWeighted(u64, initial_size_weights));
2717 try ni.ensureMinimumSize(&mf, gpa, min_size);2730 try ni.ensureMinimumSize(gpa, &mf, min_size);
2718 }2731 }
27192732
2720 if (ni.first(&mf) == .none) {2733 if (ni.first(&mf) == .none) {
...@@ -2740,7 +2753,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {...@@ -2740,7 +2753,7 @@ fn fuzzOneNodeOperations(_: void, smith: *std.testing.Smith) anyerror!void {
2740 const new_alignment = smith.valueWeighted(Alignment, alignment_weights);2753 const new_alignment = smith.valueWeighted(Alignment, alignment_weights);
2741 if (new_alignment.compare(.gt, ni.alignment(&mf))) {2754 if (new_alignment.compare(.gt, ni.alignment(&mf))) {
2742 _, const old_size = ni.location(&mf).resolve(&mf);2755 _, const old_size = ni.location(&mf).resolve(&mf);
2743 try ni.realign(&mf, gpa, new_alignment);2756 try ni.realign(gpa, &mf, new_alignment);
2744 if (ni.first(&mf) == .none and nodes.get(ni).?.initialized) {2757 if (ni.first(&mf) == .none and nodes.get(ni).?.initialized) {
2745 const slice = ni.slice(&mf);2758 const slice = ni.slice(&mf);
2746 @memmove(slice[slice.len - 4 ..][0..4], slice[old_size - 4 ..][0..4]);2759 @memmove(slice[slice.len - 4 ..][0..4], slice[old_size - 4 ..][0..4]);