authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-07-12 13:27:57+02:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-07-12 13:27:57+02:00
log452ec646f90e43d516768d43cf8581d68a9ba776
treea91487513afa81dca000e17e5553ecf324e8eb33
parentcc5dbff35fc8024cff0a1559de12ffbf7b809107
parent30713514345f4416f7e68342be5555734e55410e

Merge pull request 'Elf2: fixes' (#36114) from jacobly/elf2-fixes into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36114 Reviewed-by: mlugg <mlugg@noreply.codeberg.org>

3 files changed, 168 insertions(+), 139 deletions(-)

src/link/Coff.zig+2-2
......@@ -3602,13 +3602,13 @@ fn objectSectionMapIndex(
36023602 const parent_alignment = parent_ni.alignment(&coff.mf);
36033603 if (alignment.compare(.gt, parent_alignment)) {
36043604 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
3605 try parent_ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
3605 try parent_ni.realign(&coff.mf, gpa, alignment, .{ .try_backwards = true });
36063606 }
36073607
36083608 const old_alignment = sym.ni.alignment(&coff.mf);
36093609 if (alignment.compare(.gt, old_alignment)) {
36103610 log.debug("realignObject({s}) {d}->{d}", .{ name.toSlice(coff), old_alignment, alignment });
3611 try sym.ni.realign(&coff.mf, gpa, alignment, .{ .set_alignment = true });
3611 try sym.ni.realign(&coff.mf, gpa, alignment, .{ .try_backwards = true });
36123612 }
36133613
36143614 try coff.verifyParentSectionAttributes(
src/link/Elf2.zig+100-75
......@@ -4659,7 +4659,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
46594659 const new_alignment: std.mem.Alignment = .fromByteUnits(
46604660 std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)),
46614661 );
4662 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{ .set_alignment = true });
4662 try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment, .{});
46634663 }
46644664 // ...and update the shdr as needed.
46654665 switch (elf.shdrPtr(existing_shndx)) {
......@@ -4796,7 +4796,7 @@ fn uavMapIndex(
47964796 if (!uav_gop.found_existing) {
47974797 const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs
47984798 const node = try elf.mf.addLastChildNode(gpa, shndx.get(elf).ni, .{
4799 .moved = true, // see assert at end of `flushUav`
4799 .moved = true, // see assert at end of `genUav`
48004800 .alignment = resolved_align.toStdMem(),
48014801 });
48024802 var name_buf: [32]u8 = undefined;
......@@ -4822,7 +4822,7 @@ fn uavMapIndex(
48224822 } else {
48234823 const node = uav_gop.value_ptr.lsi.index().ptr(elf).node;
48244824 if (resolved_align.toStdMem().order(node.alignment(&elf.mf)).compare(.gt)) {
4825 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{ .set_alignment = true });
4825 try node.realign(&elf.mf, gpa, resolved_align.toStdMem(), .{});
48264826 }
48274827 }
48284828 return umi;
......@@ -5551,7 +5551,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars
55515551 // We have a copy relocation for this global, but the amount of space we
55525552 // reserved for it could be too small or underaligned!
55535553 try copied_global.node.resize(&elf.mf, gpa, gop.value_ptr.size);
5554 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{ .set_alignment = true });
5554 try copied_global.node.realign(&elf.mf, gpa, gop.value_ptr.alignment, .{});
55555555 const global_ptr = elf.globalByName(name).?;
55565556 switch (elf.symPtr(global_ptr.symtab_index)) {
55575557 inline else => |sym_ptr| elf.targetStore(&sym_ptr.size, @intCast(gop.value_ptr.size)),
......@@ -7005,22 +7005,27 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
70057005 // called to apply the NAV's new relocations.
70067006 try ni.moved(gpa, &elf.mf);
70077007
7008 var nw: MappedFile.Node.Writer = undefined;
7009 ni.writer(&elf.mf, gpa, &nw);
7010 defer nw.deinit();
7011 codegen.generateSymbol(
7012 &elf.base,
7013 pt,
7014 .fromInterned(nav.resolved.?.value),
7015 &nw.interface,
7016 .{ .atom_index = Node.toAtom(ni) },
7017 ) catch |err| switch (err) {
7018 error.WriteFailed => return nw.err.?,
7019 else => |e| return e,
7020 };
7021 switch (elf.symPtr(nmi.symbol(elf).index())) {
7022 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
7008 {
7009 var nw: MappedFile.Node.Writer = undefined;
7010 ni.writer(&elf.mf, gpa, &nw);
7011 defer nw.deinit();
7012 codegen.generateSymbol(
7013 &elf.base,
7014 pt,
7015 .fromInterned(nav.resolved.?.value),
7016 &nw.interface,
7017 .{ .atom_index = Node.toAtom(ni) },
7018 ) catch |err| switch (err) {
7019 error.WriteFailed => return nw.err.?,
7020 else => |e| return e,
7021 };
7022 switch (elf.symPtr(nmi.symbol(elf).index())) {
7023 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
7024 }
70237025 }
7026
7027 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
7028 try elf.genPending(pt);
70247029}
70257030
70267031pub fn updateFunc(
......@@ -7056,29 +7061,34 @@ fn updateFuncInner(
70567061 // called to apply the NAV's new relocations.
70577062 try ni.moved(gpa, &elf.mf);
70587063
7059 var nw: MappedFile.Node.Writer = undefined;
7060 ni.writer(&elf.mf, gpa, &nw);
7061 defer nw.deinit();
7062 codegen.emitFunction(
7063 &elf.base,
7064 pt,
7065 func_index,
7066 Node.toAtom(ni),
7067 mir,
7068 &nw.interface,
7069 .none,
7070 ) catch |err| switch (err) {
7071 error.WriteFailed => return nw.err.?,
7072 else => |e| return e,
7073 };
7074 switch (elf.symPtr(nmi.symbol(elf).index())) {
7075 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
7064 {
7065 var nw: MappedFile.Node.Writer = undefined;
7066 ni.writer(&elf.mf, gpa, &nw);
7067 defer nw.deinit();
7068 codegen.emitFunction(
7069 &elf.base,
7070 pt,
7071 func_index,
7072 Node.toAtom(ni),
7073 mir,
7074 &nw.interface,
7075 .none,
7076 ) catch |err| switch (err) {
7077 error.WriteFailed => return nw.err.?,
7078 else => |e| return e,
7079 };
7080 switch (elf.symPtr(nmi.symbol(elf).index())) {
7081 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
7082 }
70767083 }
7084
7085 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
7086 try elf.genPending(pt);
70777087}
70787088
70797089pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
70807090 const diags = &elf.base.comp.link_diags;
7081 elf.flushLazy(pt, .{
7091 elf.genLazy(pt, .{
70827092 .kind = .const_data,
70837093 .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
70847094 }) catch |err| switch (err) {
......@@ -7183,40 +7193,13 @@ fn updateDynamicTextrel(elf: *Elf) Error!void {
71837193pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
71847194 const comp = elf.base.comp;
71857195 const diags = &comp.link_diags;
7196
7197 assert(elf.pending_uavs.items.len == 0);
7198 for (&elf.lazy.values) |*lazy| {
7199 assert(lazy.pending_index == lazy.map.count());
7200 }
7201
71867202 task: {
7187 while (elf.pending_uavs.pop()) |umi| {
7188 const sub_prog_node = elf.idleProgNode(tid, elf.const_prog_node, .{ .uav = umi });
7189 defer sub_prog_node.end();
7190 elf.flushUav(.{ .zcu = comp.zcu.?, .tid = tid }, umi) catch |err| switch (err) {
7191 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7192 else => |e| return e,
7193 };
7194 break :task;
7195 }
7196 var lazy_it = elf.lazy.iterator();
7197 while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) {
7198 const pt: Zcu.PerThread = .{ .zcu = comp.zcu.?, .tid = tid };
7199 const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };
7200 lazy.value.pending_index += 1;
7201 const kind = switch (lmr.kind) {
7202 .code => "code",
7203 .const_data => "data",
7204 };
7205 var name: [std.Progress.Node.max_name_len]u8 = undefined;
7206 const sub_prog_node = elf.synth_prog_node.start(
7207 std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
7208 kind,
7209 Type.fromInterned(lmr.lazySymbol(elf).ty).fmt(pt),
7210 }) catch &name,
7211 0,
7212 );
7213 defer sub_prog_node.end();
7214 elf.flushLazy(pt, lmr) catch |err| switch (err) {
7215 error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
7216 else => |e| return e,
7217 };
7218 break :task;
7219 };
72207203 if (elf.input_section_pending_index < elf.input_sections.items.len) {
72217204 const isi: InputSection.Index = @enumFromInt(elf.input_section_pending_index);
72227205 elf.input_section_pending_index += 1;
......@@ -7315,8 +7298,6 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
73157298 } else elf.mf.update_prog_node.completeOne();
73167299 }
73177300 }
7318 if (elf.pending_uavs.items.len > 0) return true;
7319 for (&elf.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true;
73207301 if (elf.input_sections.items.len > elf.input_section_pending_index) return true;
73217302 if (elf.changed_symtab_index.count() > 0) return true;
73227303 if (elf.mf.updates.items.len > 0) return true;
......@@ -7351,7 +7332,43 @@ fn idleProgNode(
73517332 }, 0);
73527333}
73537334
7354fn flushUav(
7335fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void {
7336 const zcu = elf.base.comp.zcu.?;
7337 pending: while (true) {
7338 if (elf.pending_uavs.pop()) |umi| {
7339 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
7340 const prog_name = std.mem.print(&prog_name_buf, "{f}", .{
7341 Value.fromInterned(umi.uavValue(elf)).fmtValue(pt),
7342 }) catch &prog_name_buf;
7343 const prog_node = elf.const_prog_node.start(prog_name, 0);
7344 defer prog_node.end();
7345 try elf.genUav(pt, umi);
7346 continue :pending;
7347 }
7348 var lazy_it = elf.lazy.iterator();
7349 while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) {
7350 const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };
7351 lazy.value.pending_index += 1;
7352 const lazy_ty: Type = .fromInterned(lmr.lazySymbol(elf).ty);
7353 var prog_name_buf: [std.Progress.Node.max_name_len]u8 = undefined;
7354 const prog_name: []const u8 = switch (lazy_ty.zigTypeTag(zcu)) {
7355 .@"enum" => std.mem.print(&prog_name_buf, "@tagName({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
7356 .error_set => switch (lmr.kind) {
7357 .code => std.mem.print(&prog_name_buf, "@errorCast({f})", .{lazy_ty.fmt(pt)}) catch &prog_name_buf,
7358 .const_data => "@errorName",
7359 },
7360 else => unreachable,
7361 };
7362 const prog_node = elf.synth_prog_node.start(prog_name, 0);
7363 defer prog_node.end();
7364 try elf.genLazy(pt, lmr);
7365 continue :pending;
7366 };
7367 break;
7368 }
7369}
7370
7371fn genUav(
73557372 elf: *Elf,
73567373 pt: Zcu.PerThread,
73577374 umi: Node.UavMapIndex,
......@@ -7380,11 +7397,11 @@ fn flushUav(
73807397 inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)),
73817398 }
73827399 // The UAV should already be considered to have moved, because it is created as moved and
7383 // pending calls to `flushUav` always happen before pending calls to `flushMoved`.
7400 // pending calls to `genUav` always happen before pending calls to `flushMoved`.
73847401 assert(ni.hasMoved(&elf.mf));
73857402}
73867403
7387fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
7404fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void {
73887405 const zcu = pt.zcu;
73897406 const gpa = zcu.gpa;
73907407
......@@ -7497,6 +7514,10 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void {
74977514fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
74987515 const trace = tracy.trace(@src());
74997516 defer trace.end();
7517
7518 elf.mf.nodes_lock.lock();
7519 defer elf.mf.nodes_lock.unlock();
7520
75007521 switch (elf.getNode(ni)) {
75017522 .file => unreachable,
75027523 .ehdr, .shdr => elf.flushFileOffset(ni),
......@@ -7662,6 +7683,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
76627683fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void {
76637684 const trace = tracy.trace(@src());
76647685 defer trace.end();
7686
7687 elf.mf.nodes_lock.lock();
7688 defer elf.mf.nodes_lock.unlock();
7689
76657690 _, const size = ni.location(&elf.mf).resolve(&elf.mf);
76667691 switch (elf.getNode(ni)) {
76677692 .file => {},
src/link/MappedFile.zig+66-62
......@@ -95,14 +95,11 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I
9595 .fallocate_punch_hole_unsupported = false,
9696 };
9797 try mf.nodes.ensureUnusedCapacity(gpa, 1);
98 const root_ni = mf.addNode(gpa, .{ .add_node = .{
98 const root_ni = try mf.addNode(gpa, .{ .add_node = .{
9999 .size = size,
100100 .alignment = mf.flags.block_size,
101101 .fixed = true,
102 } }) catch |err| switch (err) {
103 error.MappedFileIo => return mf.io_err.?,
104 else => |e| return e,
105 };
102 } });
106103 assert(root_ni == Node.Index.root);
107104 try mf.ensureTotalCapacityInner(@intCast(size));
108105 return mf;
......@@ -355,9 +352,7 @@ pub const Node = extern struct {
355352
356353 pub const RealignNodeOptions = struct {
357354 /// Shift the node backwards if possible
358 try_backwards: bool = true,
359 /// If `set, persists `new_alignment` as the node's alignment for future operations.
360 set_alignment: bool = true,
355 try_backwards: bool = false,
361356 };
362357
363358 /// Moves and expands a node such that its offset and size are aligned to `new_alignment`.
......@@ -378,11 +373,7 @@ pub const Node = extern struct {
378373 return error.MappedFileIo;
379374 },
380375 };
381 var writers_it = mf.writers.first;
382 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
383 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
384 w.interface.buffer = w.ni.slice(mf);
385 }
376 mf.updateWriters();
386377 }
387378
388379 /// Shrink a node to `size`, exactly.
......@@ -398,11 +389,7 @@ pub const Node = extern struct {
398389 shift_next: bool,
399390 ) Error!void {
400391 try mf.shrinkNode(gpa, ni, size, shift_next);
401 var writers_it = mf.writers.first;
402 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
403 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
404 w.interface.buffer = w.ni.slice(mf);
405 }
392 mf.updateWriters();
406393 }
407394
408395 pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, w: *Writer) void {
......@@ -562,34 +549,15 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
562549 next: Node.Index = .none,
563550 offset: u64 = 0,
564551 add_node: AddNodeOptions,
565}) Error!Node.Index {
552}) (Allocator.Error || Io.Cancelable || IoError)!Node.Index {
566553 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
567554 mf.nodes_lock.assertUnlocked();
568 const offset = opts.add_node.alignment.forward(@intCast(opts.offset));
569 if (opts.parent != .none) {
570 const new_end = offset + opts.add_node.size;
571 switch (opts.next) {
572 .none => {
573 _, const parent_size = opts.parent.location(mf).resolve(mf);
574 if (new_end > parent_size)
575 try opts.parent.resize(mf, gpa, new_end);
576 },
577 else => |next_ni| {
578 const next_offset, _ = next_ni.location(mf).resolve(mf);
579 if (new_end > next_offset)
580 try next_ni.realign(mf, gpa, opts.add_node.alignment, .{
581 .try_backwards = false,
582 .set_alignment = false,
583 });
584 },
585 }
586 }
587555 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
588 if (std.math.cast(u32, offset)) |small_offset| break :location .{ .small, .{
556 if (std.math.cast(u32, opts.offset)) |small_offset| break :location .{ .small, .{
589557 .small = .{ .offset = small_offset, .size = 0 },
590558 } };
591559 try mf.large.ensureUnusedCapacity(gpa, 2);
592 defer mf.large.appendSliceAssumeCapacity(&.{ offset, 0 });
560 defer mf.large.appendSliceAssumeCapacity(&.{ opts.offset, 0 });
593561 break :location .{ .large, .{ .large = .{ .index = mf.large.items.len } } };
594562 };
595563 const free_ni: Node.Index, const free_node = free: switch (mf.free_ni) {
......@@ -616,7 +584,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
616584 .last = .none,
617585 .flags = .{
618586 .location_tag = location_tag,
619 .alignment = opts.add_node.alignment,
587 .alignment = .@"1",
620588 .fixed = opts.add_node.fixed,
621589 .moved = true,
622590 .resized = true,
......@@ -627,13 +595,15 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
627595 };
628596
629597 {
630 try free_ni.resize(mf, gpa, opts.add_node.size);
598 try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{});
599 try mf.resizeNode(gpa, free_ni, opts.add_node.size);
631600 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
632601 free_node.flags.moved = false;
633602 free_node.flags.resized = false;
634603 }
635604 if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);
636605 if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);
606 mf.updateWriters();
637607 return free_ni;
638608}
639609
......@@ -658,7 +628,15 @@ pub fn addOnlyChildNode(
658628 return mf.addNode(gpa, .{
659629 .parent = parent_ni,
660630 .add_node = opts,
661 });
631 }) catch |err| switch (err) {
632 error.OutOfMemory,
633 error.Canceled,
634 => |e| return e,
635 else => |e| {
636 mf.io_err = e;
637 return error.MappedFileIo;
638 },
639 };
662640}
663641
664642pub fn addFirstChildNode(
......@@ -673,7 +651,15 @@ pub fn addFirstChildNode(
673651 .parent = parent_ni,
674652 .next = parent.first,
675653 .add_node = opts,
676 });
654 }) catch |err| switch (err) {
655 error.OutOfMemory,
656 error.Canceled,
657 => |e| return e,
658 else => |e| {
659 mf.io_err = e;
660 return error.MappedFileIo;
661 },
662 };
677663}
678664
679665pub fn addLastChildNode(
......@@ -695,7 +681,15 @@ pub fn addLastChildNode(
695681 },
696682 },
697683 .add_node = opts,
698 });
684 }) catch |err| switch (err) {
685 error.OutOfMemory,
686 error.Canceled,
687 => |e| return e,
688 else => |e| {
689 mf.io_err = e;
690 return error.MappedFileIo;
691 },
692 };
699693}
700694
701695pub fn addNodeAfter(
......@@ -714,7 +708,15 @@ pub fn addNodeAfter(
714708 .next = prev.next,
715709 .offset = prev_offset + prev_size,
716710 .add_node = opts,
717 });
711 }) catch |err| switch (err) {
712 error.OutOfMemory,
713 error.Canceled,
714 => |e| return e,
715 else => |e| {
716 mf.io_err = e;
717 return error.MappedFileIo;
718 },
719 };
718720}
719721
720722fn shrinkNode(
......@@ -1043,26 +1045,20 @@ fn realignNode(
10431045 new_alignment: std.mem.Alignment,
10441046 opts: Node.Index.RealignNodeOptions,
10451047) (Allocator.Error || Io.Cancelable || IoError)!void {
1046 assert(ni != Node.Index.root); // currently unsupported
10471048 mf.nodes_lock.assertUnlocked();
10481049
10491050 const node = ni.get(mf);
1050 const old_offset, const size = node.location().resolve(mf);
1051
1052 assert(new_alignment.compare(.gt, node.flags.alignment));
1053
1054 const prev_alignment = node.flags.alignment;
1055 node.flags.alignment = new_alignment;
1056 defer {
1057 // alignment needs to be temporarily set for the resizes below
1058 if (!opts.set_alignment) node.flags.alignment = prev_alignment;
1051 {
1052 const prev_alignment = node.flags.alignment;
1053 node.flags.alignment = new_alignment;
1054 if (new_alignment.compare(.lte, prev_alignment)) return;
10591055 }
10601056
1061 const new_size = node.flags.alignment.forward(@intCast(size));
1062 if (new_alignment.check(@intCast(old_offset))) {
1063 if (new_size > size) try mf.resizeNode(gpa, ni, new_size);
1064 return;
1065 }
1057 const old_offset, const size = node.location().resolve(mf);
1058 if (ni == Node.Index.root) return mf.resizeNode(gpa, ni, size);
1059
1060 const new_size = new_alignment.forward(@intCast(size));
1061 if (new_alignment.check(@intCast(old_offset))) return mf.resizeNode(gpa, ni, new_size);
10661062
10671063 _, const parent_size = node.parent.location(mf).resolve(mf);
10681064 const trailing_end = trailing_end: switch (node.next) {
......@@ -1122,7 +1118,7 @@ fn realignNode(
11221118
11231119 ni.setLocationAssumeCapacity(mf, forward_offset, new_size);
11241120 } else {
1125 const temp_size = node.flags.alignment.forward(@intCast(new_size + 1));
1121 const temp_size = new_alignment.forward(@intCast(new_size + 1));
11261122 try mf.resizeNode(gpa, ni, temp_size);
11271123 const new_offset, _ = ni.location(mf).resolve(mf);
11281124
......@@ -1148,6 +1144,14 @@ fn realignNode(
11481144 }
11491145}
11501146
1147fn updateWriters(mf: *MappedFile) void {
1148 var writers_it = mf.writers.first;
1149 while (writers_it) |writer_node| : (writers_it = writer_node.next) {
1150 const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node);
1151 w.interface.buffer = w.ni.slice(mf);
1152 }
1153}
1154
11511155fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) (Io.Cancelable || IoError)!void {
11521156 // make a copy of this node at the new location
11531157 try mf.copyRange(old_file_offset, new_file_offset, size);