| ... | @@ -4796,7 +4796,7 @@ fn uavMapIndex( | ... | @@ -4796,7 +4796,7 @@ fn uavMapIndex( |
| 4796 | if (!uav_gop.found_existing) { | 4796 | if (!uav_gop.found_existing) { |
| 4797 | const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs | 4797 | const shndx: Section.Index = .data_rel_ro; // TODO: it would be better to use `.rodata` if the UAV value doesn't have relocs |
| 4798 | const node = try elf.mf.addLastChildNode(gpa, shndx.get(elf).ni, .{ | 4798 | 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` |
| 4800 | .alignment = resolved_align.toStdMem(), | 4800 | .alignment = resolved_align.toStdMem(), |
| 4801 | }); | 4801 | }); |
| 4802 | var name_buf: [32]u8 = undefined; | 4802 | var name_buf: [32]u8 = undefined; |
| ... | @@ -7005,22 +7005,27 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) | ... | @@ -7005,22 +7005,27 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 7005 | // called to apply the NAV's new relocations. | 7005 | // called to apply the NAV's new relocations. |
| 7006 | try ni.moved(gpa, &elf.mf); | 7006 | try ni.moved(gpa, &elf.mf); |
| 7007 | | 7007 | |
| 7008 | var nw: MappedFile.Node.Writer = undefined; | 7008 | { |
| 7009 | ni.writer(&elf.mf, gpa, &nw); | 7009 | var nw: MappedFile.Node.Writer = undefined; |
| 7010 | defer nw.deinit(); | 7010 | ni.writer(&elf.mf, gpa, &nw); |
| 7011 | codegen.generateSymbol( | 7011 | defer nw.deinit(); |
| 7012 | &elf.base, | 7012 | codegen.generateSymbol( |
| 7013 | pt, | 7013 | &elf.base, |
| 7014 | .fromInterned(nav.resolved.?.value), | 7014 | pt, |
| 7015 | &nw.interface, | 7015 | .fromInterned(nav.resolved.?.value), |
| 7016 | .{ .atom_index = Node.toAtom(ni) }, | 7016 | &nw.interface, |
| 7017 | ) catch |err| switch (err) { | 7017 | .{ .atom_index = Node.toAtom(ni) }, |
| 7018 | error.WriteFailed => return nw.err.?, | 7018 | ) catch |err| switch (err) { |
| 7019 | else => |e| return e, | 7019 | error.WriteFailed => return nw.err.?, |
| 7020 | }; | 7020 | else => |e| return e, |
| 7021 | switch (elf.symPtr(nmi.symbol(elf).index())) { | 7021 | }; |
| 7022 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 7022 | switch (elf.symPtr(nmi.symbol(elf).index())) { |
| | 7023 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), |
| | 7024 | } |
| 7023 | } | 7025 | } |
| | 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); |
| 7024 | } | 7029 | } |
| 7025 | | 7030 | |
| 7026 | pub fn updateFunc( | 7031 | pub fn updateFunc( |
| ... | @@ -7056,29 +7061,34 @@ fn updateFuncInner( | ... | @@ -7056,29 +7061,34 @@ fn updateFuncInner( |
| 7056 | // called to apply the NAV's new relocations. | 7061 | // called to apply the NAV's new relocations. |
| 7057 | try ni.moved(gpa, &elf.mf); | 7062 | try ni.moved(gpa, &elf.mf); |
| 7058 | | 7063 | |
| 7059 | var nw: MappedFile.Node.Writer = undefined; | 7064 | { |
| 7060 | ni.writer(&elf.mf, gpa, &nw); | 7065 | var nw: MappedFile.Node.Writer = undefined; |
| 7061 | defer nw.deinit(); | 7066 | ni.writer(&elf.mf, gpa, &nw); |
| 7062 | codegen.emitFunction( | 7067 | defer nw.deinit(); |
| 7063 | &elf.base, | 7068 | codegen.emitFunction( |
| 7064 | pt, | 7069 | &elf.base, |
| 7065 | func_index, | 7070 | pt, |
| 7066 | Node.toAtom(ni), | 7071 | func_index, |
| 7067 | mir, | 7072 | Node.toAtom(ni), |
| 7068 | &nw.interface, | 7073 | mir, |
| 7069 | .none, | 7074 | &nw.interface, |
| 7070 | ) catch |err| switch (err) { | 7075 | .none, |
| 7071 | error.WriteFailed => return nw.err.?, | 7076 | ) catch |err| switch (err) { |
| 7072 | else => |e| return e, | 7077 | error.WriteFailed => return nw.err.?, |
| 7073 | }; | 7078 | else => |e| return e, |
| 7074 | switch (elf.symPtr(nmi.symbol(elf).index())) { | 7079 | }; |
| 7075 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 7080 | switch (elf.symPtr(nmi.symbol(elf).index())) { |
| | 7081 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), |
| | 7082 | } |
| 7076 | } | 7083 | } |
| | 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); |
| 7077 | } | 7087 | } |
| 7078 | | 7088 | |
| 7079 | pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void { | 7089 | pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) link.Error!void { |
| 7080 | const diags = &elf.base.comp.link_diags; | 7090 | const diags = &elf.base.comp.link_diags; |
| 7081 | elf.flushLazy(pt, .{ | 7091 | elf.genLazy(pt, .{ |
| 7082 | .kind = .const_data, | 7092 | .kind = .const_data, |
| 7083 | .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return), | 7093 | .index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return), |
| 7084 | }) catch |err| switch (err) { | 7094 | }) catch |err| switch (err) { |
| ... | @@ -7183,40 +7193,13 @@ fn updateDynamicTextrel(elf: *Elf) Error!void { | ... | @@ -7183,40 +7193,13 @@ fn updateDynamicTextrel(elf: *Elf) Error!void { |
| 7183 | pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { | 7193 | pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7184 | const comp = elf.base.comp; | 7194 | const comp = elf.base.comp; |
| 7185 | const diags = &comp.link_diags; | 7195 | 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 | |
| 7186 | task: { | 7202 | 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 | }; | | |
| 7220 | if (elf.input_section_pending_index < elf.input_sections.items.len) { | 7203 | if (elf.input_section_pending_index < elf.input_sections.items.len) { |
| 7221 | const isi: InputSection.Index = @enumFromInt(elf.input_section_pending_index); | 7204 | const isi: InputSection.Index = @enumFromInt(elf.input_section_pending_index); |
| 7222 | elf.input_section_pending_index += 1; | 7205 | elf.input_section_pending_index += 1; |
| ... | @@ -7315,8 +7298,6 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { | ... | @@ -7315,8 +7298,6 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7315 | } else elf.mf.update_prog_node.completeOne(); | 7298 | } else elf.mf.update_prog_node.completeOne(); |
| 7316 | } | 7299 | } |
| 7317 | } | 7300 | } |
| 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; | | |
| 7320 | if (elf.input_sections.items.len > elf.input_section_pending_index) return true; | 7301 | if (elf.input_sections.items.len > elf.input_section_pending_index) return true; |
| 7321 | if (elf.changed_symtab_index.count() > 0) return true; | 7302 | if (elf.changed_symtab_index.count() > 0) return true; |
| 7322 | if (elf.mf.updates.items.len > 0) return true; | 7303 | if (elf.mf.updates.items.len > 0) return true; |
| ... | @@ -7351,7 +7332,43 @@ fn idleProgNode( | ... | @@ -7351,7 +7332,43 @@ fn idleProgNode( |
| 7351 | }, 0); | 7332 | }, 0); |
| 7352 | } | 7333 | } |
| 7353 | | 7334 | |
| 7354 | fn flushUav( | 7335 | fn 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 | |
| | 7371 | fn genUav( |
| 7355 | elf: *Elf, | 7372 | elf: *Elf, |
| 7356 | pt: Zcu.PerThread, | 7373 | pt: Zcu.PerThread, |
| 7357 | umi: Node.UavMapIndex, | 7374 | umi: Node.UavMapIndex, |
| ... | @@ -7380,11 +7397,11 @@ fn flushUav( | ... | @@ -7380,11 +7397,11 @@ fn flushUav( |
| 7380 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 7397 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), |
| 7381 | } | 7398 | } |
| 7382 | // The UAV should already be considered to have moved, because it is created as moved and | 7399 | // 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`. |
| 7384 | assert(ni.hasMoved(&elf.mf)); | 7401 | assert(ni.hasMoved(&elf.mf)); |
| 7385 | } | 7402 | } |
| 7386 | | 7403 | |
| 7387 | fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { | 7404 | fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { |
| 7388 | const zcu = pt.zcu; | 7405 | const zcu = pt.zcu; |
| 7389 | const gpa = zcu.gpa; | 7406 | const gpa = zcu.gpa; |
| 7390 | | 7407 | |
| ... | @@ -7497,6 +7514,10 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -7497,6 +7514,10 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 7497 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { | 7514 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 7498 | const trace = tracy.trace(@src()); | 7515 | const trace = tracy.trace(@src()); |
| 7499 | defer trace.end(); | 7516 | defer trace.end(); |
| | 7517 | |
| | 7518 | elf.mf.nodes_lock.lock(); |
| | 7519 | defer elf.mf.nodes_lock.unlock(); |
| | 7520 | |
| 7500 | switch (elf.getNode(ni)) { | 7521 | switch (elf.getNode(ni)) { |
| 7501 | .file => unreachable, | 7522 | .file => unreachable, |
| 7502 | .ehdr, .shdr => elf.flushFileOffset(ni), | 7523 | .ehdr, .shdr => elf.flushFileOffset(ni), |
| ... | @@ -7662,6 +7683,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -7662,6 +7683,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 7662 | fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { | 7683 | fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 7663 | const trace = tracy.trace(@src()); | 7684 | const trace = tracy.trace(@src()); |
| 7664 | defer trace.end(); | 7685 | defer trace.end(); |
| | 7686 | |
| | 7687 | elf.mf.nodes_lock.lock(); |
| | 7688 | defer elf.mf.nodes_lock.unlock(); |
| | 7689 | |
| 7665 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); | 7690 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); |
| 7666 | switch (elf.getNode(ni)) { | 7691 | switch (elf.getNode(ni)) { |
| 7667 | .file => {}, | 7692 | .file => {}, |