authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:35-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:26:54-04:00
log22a22ceaeb3f693207fc4821b55959ba0732d7ed
treefeb6df740e4d0a2fbe767b48d92518484bb57619
parent2be291c98773e25d4a47e5c35744084627d11f15

Prelink tasks for MingGW implibs and MappedFile fixes

- Add MappedFile.realign - Fix the case of MappedFile.addNode adding a node in between nodes that have lower alignment than it (by realigning the following node) - Fixup the capacity reservation in addNode to occur after the resize (which may have consumed that capacity) - Remove incorrect path in `.load_host_libc` that was loading mingw libs, they were already being loaded via their build tasks - Generate mingw implibs as a prelink task, so they can be supplied to the linker before prelink() - Any other libraries discovered during Sema are have their implibs generated after, but the self-hosted linker is not passed these. Lld can still use this path. - mingw implib generation now interacts with the progress system - Supply `__ImageBase` for mingw

6 files changed, 161 insertions(+), 61 deletions(-)

src/Compilation.zig+40-11
...@@ -4475,18 +4475,10 @@ fn performAllTheWork(...@@ -4475,18 +4475,10 @@ fn performAllTheWork(
44754475
4476 comp.link_queue.finishZcuQueue(comp);4476 comp.link_queue.finishZcuQueue(comp);
44774477
4478 // This has to happen after the main semantic analysis loop because it is possible for Sema to4478 // This has to happen again after the main semantic analysis loop because it is possible for Sema to
4479 // call `addLinkLib` and hence add more items to `comp.windows_libs`.4479 // call `addLinkLib` and hence add more items to `comp.windows_libs`.
4480 for (comp.windows_libs.keys()[comp.windows_libs_num_done..]) |link_lib| {4480 for (comp.windows_libs.keys()[comp.windows_libs_num_done..]) |lib_name|
4481 mingw.buildImportLib(comp, link_lib) catch |err| {4481 comp.buildMingwImportLib(lib_name, false, main_progress_node);
4482 // TODO Surface more error details.
4483 comp.lockAndSetMiscFailure(
4484 .windows_import_lib,
4485 "unable to generate DLL import .lib file for {s}: {t}",
4486 .{ link_lib, err },
4487 );
4488 };
4489 }
4490 comp.windows_libs_num_done = @intCast(comp.windows_libs.count());4482 comp.windows_libs_num_done = @intCast(comp.windows_libs.count());
44914483
4492 // Main thread work is all done, now just wait for all async work.4484 // Main thread work is all done, now just wait for all async work.
...@@ -4692,6 +4684,15 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node...@@ -4692,6 +4684,15 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node
4692 });4684 });
4693 }4685 }
46944686
4687 while (comp.windows_libs_num_done < comp.windows_libs.count()) {
4688 prelink_group.async(
4689 io,
4690 buildMingwImportLib,
4691 .{ comp, comp.windows_libs.keys()[comp.windows_libs_num_done], true, main_progress_node },
4692 );
4693 comp.windows_libs_num_done += 1;
4694 }
4695
4695 prelink_group.await(io) catch |err| switch (err) {4696 prelink_group.await(io) catch |err| switch (err) {
4696 error.Canceled => unreachable, // see swapCancelProtection above4697 error.Canceled => unreachable, // see swapCancelProtection above
4697 };4698 };
...@@ -5377,6 +5378,34 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std...@@ -5377,6 +5378,34 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
5377 }5378 }
5378}5379}
53795380
5381fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: bool, prog_node: std.Progress.Node) void {
5382 const crt_file_path = mingw.buildImportLib(comp, lib_name, prog_node) catch |err| switch (err) {
5383 // TODO: This isn't actually true for self-hosted
5384 // In the non-prelink case we will end up putting foo.lib onto the linker line and letting the linker
5385 // use its library paths to look for libraries and report any problems.
5386 error.DefNotFound => return if (is_prelink) {
5387 comp.lockAndSetMiscFailure(
5388 .windows_import_lib,
5389 "definition not found for required mingw DLL import .lib {s}",
5390 .{lib_name},
5391 );
5392 },
5393 // TODO Surface more error details.
5394 else => |e| return comp.lockAndSetMiscFailure(
5395 .windows_import_lib,
5396 "unable to generate mingw DLL import .lib file for {s}: {t}",
5397 .{ lib_name, e },
5398 ),
5399 };
5400
5401 if (is_prelink)
5402 comp.queuePrelinkTasks(&.{.{ .load_archive = crt_file_path }}) catch |err| comp.lockAndSetMiscFailure(
5403 .windows_import_lib,
5404 "unable to queue prelink task for mingw import lib {f}: {t}",
5405 .{ crt_file_path, err },
5406 );
5407}
5408
5380fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {5409fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {
5381 if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {5410 if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {
5382 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;5411 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;
src/libs/mingw.zig+21-16
...@@ -207,9 +207,12 @@ fn addCrtCcArgs(...@@ -207,9 +207,12 @@ fn addCrtCcArgs(
207 });207 });
208}208}
209209
210pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {210pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.Progress.Node) !Cache.Path {
211 dev.check(.build_import_lib);211 dev.check(.build_import_lib);
212212
213 const sub_node = prog_node.start(lib_name, 0);
214 defer sub_node.end();
215
213 const gpa = comp.gpa;216 const gpa = comp.gpa;
214 const io = comp.io;217 const io = comp.io;
215218
...@@ -218,12 +221,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -218,12 +221,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
218 const arena = arena_allocator.allocator();221 const arena = arena_allocator.allocator();
219222
220 const def_file_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) {223 const def_file_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) {
221 error.FileNotFound => {224 error.FileNotFound => return error.DefNotFound,
222 log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name });
223 // In this case we will end up putting foo.lib onto the linker line and letting the linker
224 // use its library paths to look for libraries and report any problems.
225 return;
226 },
227 else => |e| return e,225 else => |e| return e,
228 };226 };
229 // Only .def.in files need preprocessing227 // Only .def.in files need preprocessing
...@@ -263,14 +261,16 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -263,14 +261,16 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
263 comp.mutex.lockUncancelable(io);261 comp.mutex.lockUncancelable(io);
264 defer comp.mutex.unlock(io);262 defer comp.mutex.unlock(io);
265 try comp.crt_files.ensureUnusedCapacity(gpa, 1);263 try comp.crt_files.ensureUnusedCapacity(gpa, 1);
264
265 const crt_file_path: Cache.Path = .{
266 .root_dir = comp.dirs.global_cache,
267 .sub_path = sub_path,
268 };
266 comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{269 comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{
267 .full_object_path = .{270 .full_object_path = crt_file_path,
268 .root_dir = comp.dirs.global_cache,
269 .sub_path = sub_path,
270 },
271 .lock = man.toOwnedLock(),271 .lock = man.toOwnedLock(),
272 });272 });
273 return;273 return crt_file_path;
274 }274 }
275275
276 const digest = man.final();276 const digest = man.final();
...@@ -294,6 +294,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -294,6 +294,9 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
294 }294 }
295295
296 const members = members: {296 const members = members: {
297 const members_node = sub_node.start("Members", 0);
298 defer members_node.end();
299
297 const input = switch (def_needs_preprocessing) {300 const input = switch (def_needs_preprocessing) {
298 true => pp: {301 true => pp: {
299 var aw: Io.Writer.Allocating = .init(gpa);302 var aw: Io.Writer.Allocating = .init(gpa);
...@@ -357,13 +360,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -357,13 +360,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
357360
358 comp.mutex.lockUncancelable(io);361 comp.mutex.lockUncancelable(io);
359 defer comp.mutex.unlock(io);362 defer comp.mutex.unlock(io);
363 const crt_file_path: Cache.Path = .{
364 .root_dir = comp.dirs.global_cache,
365 .sub_path = lib_final_path,
366 };
360 try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{367 try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{
361 .full_object_path = .{368 .full_object_path = crt_file_path,
362 .root_dir = comp.dirs.global_cache,
363 .sub_path = lib_final_path,
364 },
365 .lock = man.toOwnedLock(),369 .lock = man.toOwnedLock(),
366 });370 });
371 return crt_file_path;
367}372}
368373
369pub fn libExists(374pub fn libExists(
src/link.zig+3-12
...@@ -482,7 +482,7 @@ pub const File = struct {...@@ -482,7 +482,7 @@ pub const File = struct {
482 rpath_list: []const []const u8,482 rpath_list: []const []const u8,
483483
484 /// Zig compiler development linker flags.484 /// Zig compiler development linker flags.
485 /// Enable dumping of linker's state as JSON.485 /// Enable dumping of linker's state.
486 enable_link_snapshots: bool,486 enable_link_snapshots: bool,
487487
488 /// Darwin-specific linker flags:488 /// Darwin-specific linker flags:
...@@ -1527,20 +1527,11 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1527,20 +1527,11 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1527 }1527 }
1528 }1528 }
15291529
1530 if (target.os.tag == .windows) {1530 if (target.os.tag == .windows and target.abi == .msvc) {
1531 const inputs: []const struct {1531 const inputs: []const struct {
1532 dir: enum { crt, msvc_lib, kernel32_lib },1532 dir: enum { crt, msvc_lib, kernel32_lib },
1533 name: []const u8,1533 name: []const u8,
1534 } = if (target.abi.isGnu()) switch (comp.config.link_mode) {1534 } = switch (comp.config.link_mode) {
1535 .dynamic => &.{
1536 .{ .dir = .crt, .name = "dllcrt2.obj" },
1537 .{ .dir = .crt, .name = "libmingw32.lib" },
1538 },
1539 .static => &.{
1540 .{ .dir = .crt, .name = "crt2.obj" },
1541 .{ .dir = .crt, .name = "libmingw32.lib" },
1542 },
1543 } else switch (comp.config.link_mode) {
1544 .dynamic => &.{1535 .dynamic => &.{
1545 .{ .dir = .msvc_lib, .name = "msvcrt.lib" },1536 .{ .dir = .msvc_lib, .name = "msvcrt.lib" },
1546 .{ .dir = .msvc_lib, .name = "vcruntime.lib" },1537 .{ .dir = .msvc_lib, .name = "vcruntime.lib" },
src/link/Coff.zig+29-8
...@@ -2017,6 +2017,16 @@ fn initHeaders(...@@ -2017,6 +2017,16 @@ fn initHeaders(
2017 .{ .read = true, .write = !is_image },2017 .{ .read = true, .write = !is_image },
2018 );2018 );
2019 }2019 }
2020
2021 // Linker-supplied symbols
2022 {
2023 const target = &comp.root_mod.resolved_target.result;
2024 if (is_image and target.isMinGW()) {
2025 const si = try coff.globalSymbol(.{ .name = "__ImageBase", .type = .data });
2026 const sym = si.get(coff);
2027 sym.ni = Node.known.header;
2028 }
2029 }
2020}2030}
20212031
2022pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void {2032pub fn startProgress(coff: *Coff, prog_node: std.Progress.Node) void {
...@@ -2044,7 +2054,7 @@ pub fn endProgress(coff: *Coff) void {...@@ -2044,7 +2054,7 @@ pub fn endProgress(coff: *Coff) void {
2044 coff.mf.update_prog_node = .none;2054 coff.mf.update_prog_node = .none;
2045 coff.input_prog_node.end();2055 coff.input_prog_node.end();
2046 coff.input_prog_node = .none;2056 coff.input_prog_node = .none;
2047 if (!isImage(coff)) {2057 if (!coff.isImage()) {
2048 coff.member_prog_node.end();2058 coff.member_prog_node.end();
2049 coff.member_prog_node = .none;2059 coff.member_prog_node = .none;
2050 coff.symbol_prog_node.end();2060 coff.symbol_prog_node.end();
...@@ -3103,7 +3113,7 @@ fn objectSectionMapIndex(...@@ -3103,7 +3113,7 @@ fn objectSectionMapIndex(
31033113
3104 const object_section_gop = try coff.object_section_table.getOrPut(gpa, name);3114 const object_section_gop = try coff.object_section_table.getOrPut(gpa, name);
3105 const osmi: Node.ObjectSectionMapIndex = @enumFromInt(object_section_gop.index);3115 const osmi: Node.ObjectSectionMapIndex = @enumFromInt(object_section_gop.index);
3106 const sn = if (!object_section_gop.found_existing) sn: {3116 const sym = if (!object_section_gop.found_existing) sn: {
3107 try coff.ensureUnusedStringCapacity(name_slice.len);3117 try coff.ensureUnusedStringCapacity(name_slice.len);
3108 const parent_name = coff.getOrPutStringAssumeCapacity(coff.objectSectionParentName(name_slice));3118 const parent_name = coff.getOrPutStringAssumeCapacity(coff.objectSectionParentName(name_slice));
3109 const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, effective_attributes)).symbol(coff);3119 const parent = (try coff.pseudoSectionMapIndex(parent_name, alignment, effective_attributes)).symbol(coff);
...@@ -3140,14 +3150,24 @@ fn objectSectionMapIndex(...@@ -3140,14 +3150,24 @@ fn objectSectionMapIndex(
3140 assert(sym.loc_relocs == .none);3150 assert(sym.loc_relocs == .none);
3141 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);3151 sym.loc_relocs = @enumFromInt(coff.relocs.items.len);
3142 coff.nodes.appendAssumeCapacity(.{ .object_section = osmi });3152 coff.nodes.appendAssumeCapacity(.{ .object_section = osmi });
3143 break :sn sym.section_number;3153 break :sn sym;
3144 } else object_section_gop.value_ptr.get(coff).section_number;3154 } else object_section_gop.value_ptr.get(coff);
3155
3156 const parent_ni = sym.ni.parent(&coff.mf);
3157 const parent_alignment = parent_ni.alignment(&coff.mf);
3158 if (alignment.compare(.gt, parent_alignment)) {
3159 log.debug("realignParent({s}, {d}) {d}->{d}", .{ name.toSlice(coff), parent_ni, parent_alignment, alignment });
3160 parent_ni.realign(&coff.mf, gpa, alignment, true) catch |err| switch (err) {
3161 error.Unimplemented => unreachable,
3162 else => |e| return e,
3163 };
3164 }
31453165
3146 try coff.verifyParentSectionAttributes(3166 try coff.verifyParentSectionAttributes(
3147 .object,3167 .object,
3148 sn.name(coff),3168 sym.section_number.name(coff),
3149 name,3169 name,
3150 .fromFlags(sn.header(coff).flags),3170 .fromFlags(sym.section_number.header(coff).flags),
3151 effective_attributes,3171 effective_attributes,
3152 );3172 );
31533173
...@@ -4135,7 +4155,7 @@ fn loadObject(...@@ -4135,7 +4155,7 @@ fn loadObject(
4135 },4155 },
4136 .weak_external => unreachable,4156 .weak_external => unreachable,
4137 });4157 });
4138 sym.section_number = symbol.section_number;4158 sym.section_number = section.si.get(coff).section_number;
4139 }4159 }
41404160
4141 log.debug("addInputSymbol({s}, 0x{x}, {t}=0x{x}) = {d}@{d}", .{4161 log.debug("addInputSymbol({s}, 0x{x}, {t}=0x{x}) = {d}@{d}", .{
...@@ -4988,7 +5008,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {...@@ -4988,7 +5008,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void {
4988 const other_ioi = isi.input(coff);5008 const other_ioi = isi.input(coff);
4989 if (loc_sym.gmi == .none) {5009 if (loc_sym.gmi == .none) {
4990 // TODO: We could report the name here if we interned it in loadObject5010 // TODO: We could report the name here if we interned it in loadObject
4991 err.addNote("referenced internally by input '{f}{f}'", .{5011 err.addNote("referenced by input '{f}{f}'", .{
4992 other_ioi.path(coff).fmtEscapeString(),5012 other_ioi.path(coff).fmtEscapeString(),
4993 fmtMemberNameString(other_ioi.memberName(coff)),5013 fmtMemberNameString(other_ioi.memberName(coff)),
4994 });5014 });
...@@ -5430,6 +5450,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {...@@ -5430,6 +5450,7 @@ fn flushGlobal(coff: *Coff, gmi: Node.GlobalMapIndex) !bool {
5430 return true;5450 return true;
5431 }5451 }
54325452
5453 // TODO: Only do this if actually referenced? Might have to do on-demand?
5433 {5454 {
5434 // Resolve unresolved .WEAK_EXTERNAL symbols to their aliases5455 // Resolve unresolved .WEAK_EXTERNAL symbols to their aliases
5435 const alias_si = sym.weakAlias();5456 const alias_si = sym.weakAlias();
src/link/MappedFile.zig+68-12
...@@ -351,15 +351,17 @@ pub const Node = extern struct {...@@ -351,15 +351,17 @@ pub const Node = extern struct {
351 }351 }
352352
353 /// Moves and expands a node such that its offset and size are aligned to `new_alignment`.353 /// Moves and expands a node such that its offset and size are aligned to `new_alignment`.
354 ///354 /// If it is possible to move the node backwards, this will be done instead of moving it forward.
355 /// If `set_alignment` is set, persists `new_alignment` as the node's alignment for future operations.
355 /// Asserts that `ni` is not `Node.Index.root`.356 /// Asserts that `ni` is not `Node.Index.root`.
356 pub fn realign(357 pub fn realign(
357 ni: Node.Index,358 ni: Node.Index,
358 mf: *MappedFile,359 mf: *MappedFile,
359 gpa: std.mem.Allocator,360 gpa: std.mem.Allocator,
360 new_alignment: std.mem.Alignment,361 new_alignment: std.mem.Alignment,
362 set_alignment: bool,
361 ) Error!void {363 ) Error!void {
362 mf.realignNode(gpa, ni, new_alignment) catch |err| switch (err) {364 mf.realignNode(gpa, ni, new_alignment, true, set_alignment) catch |err| switch (err) {
363 error.OutOfMemory,365 error.OutOfMemory,
364 error.Canceled,366 error.Canceled,
365 => |e| return e,367 => |e| return e,
...@@ -554,6 +556,24 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {...@@ -554,6 +556,24 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
554}) Error!Node.Index {556}) Error!Node.Index {
555 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);557 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
556 const offset = opts.add_node.alignment.forward(@intCast(opts.offset));558 const offset = opts.add_node.alignment.forward(@intCast(opts.offset));
559 if (opts.parent != .none) {
560 const new_end = offset + opts.add_node.size;
561 switch (opts.next) {
562 .none => {
563 _, const parent_size = opts.parent.location(mf).resolve(mf);
564 if (new_end > parent_size)
565 try opts.parent.resize(mf, gpa, new_end);
566 },
567 else => |next_ni| {
568 const next_offset, _ = next_ni.location(mf).resolve(mf);
569 if (new_end > next_offset)
570 mf.realignNode(gpa, next_ni, opts.add_node.alignment, false, false) catch |err| switch (err) {
571 error.Unimplemented => unreachable,
572 else => |e| return e,
573 };
574 },
575 }
576 }
557 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {577 const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: {
558 if (std.math.cast(u32, offset)) |small_offset| break :location .{ .small, .{578 if (std.math.cast(u32, offset)) |small_offset| break :location .{ .small, .{
559 .small = .{ .offset = small_offset, .size = 0 },579 .small = .{ .offset = small_offset, .size = 0 },
...@@ -595,16 +615,12 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {...@@ -595,16 +615,12 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
595 },615 },
596 .location_payload = location_payload,616 .location_payload = location_payload,
597 };617 };
618
598 {619 {
599 defer {
600 free_node.flags.moved = false;
601 free_node.flags.resized = false;
602 }
603 _, const parent_size = opts.parent.location(mf).resolve(mf);
604 const required_parent_size = offset + opts.add_node.size;
605 if (required_parent_size > parent_size)
606 try opts.parent.resize(mf, gpa, required_parent_size);
607 try free_ni.resize(mf, gpa, opts.add_node.size);620 try free_ni.resize(mf, gpa, opts.add_node.size);
621 if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1);
622 free_node.flags.moved = false;
623 free_node.flags.resized = false;
608 }624 }
609 if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);625 if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf);
610 if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);626 if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf);
...@@ -703,6 +719,7 @@ fn shrinkNode(...@@ -703,6 +719,7 @@ fn shrinkNode(
703719
704 // This would require unmapping first720 // This would require unmapping first
705 if (ni == Node.Index.root) return error.Unimplemented;721 if (ni == Node.Index.root) return error.Unimplemented;
722 defer if (std.debug.runtime_safety) mf.verify();
706723
707 if (node.last != .none) {724 if (node.last != .none) {
708 const last = node.last.get(mf);725 const last = node.last.get(mf);
...@@ -725,9 +742,10 @@ fn shrinkNode(...@@ -725,9 +742,10 @@ fn shrinkNode(
725 const old_file_offset = node.next.fileLocation(mf, false).offset;742 const old_file_offset = node.next.fileLocation(mf, false).offset;
726 const new_file_offset = (old_file_offset - old_next_offset) + new_next_offset;743 const new_file_offset = (old_file_offset - old_next_offset) + new_next_offset;
727 @memmove(744 @memmove(
728 mf.memory_map.memory[new_file_offset..][0..next_size],745 mf.memory_map.memory[@intCast(new_file_offset)..][0..@intCast(next_size)],
729 mf.memory_map.memory[old_file_offset..][0..next_size],746 mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(next_size)],
730 );747 );
748 @memset(mf.memory_map.memory[@intCast(new_file_offset + next_size)..@intCast(old_file_offset + next_size)], 0);
731 }749 }
732750
733 node.next.setLocationAssumeCapacity(mf, new_next_offset, next_size);751 node.next.setLocationAssumeCapacity(mf, new_next_offset, next_size);
...@@ -999,6 +1017,8 @@ fn realignNode(...@@ -999,6 +1017,8 @@ fn realignNode(
999 gpa: std.mem.Allocator,1017 gpa: std.mem.Allocator,
1000 ni: Node.Index,1018 ni: Node.Index,
1001 new_alignment: std.mem.Alignment,1019 new_alignment: std.mem.Alignment,
1020 try_backward: bool,
1021 set_alignment: bool,
1002) (Allocator.Error || Io.Cancelable || IoError)!void {1022) (Allocator.Error || Io.Cancelable || IoError)!void {
1003 assert(ni != Node.Index.root); // currently unsupported1023 assert(ni != Node.Index.root); // currently unsupported
10041024
...@@ -1009,7 +1029,12 @@ fn realignNode(...@@ -1009,7 +1029,12 @@ fn realignNode(
10091029
1010 defer if (std.debug.runtime_safety) mf.verify();1030 defer if (std.debug.runtime_safety) mf.verify();
10111031
1032 const prev_alignment = node.flags.alignment;
1012 node.flags.alignment = new_alignment;1033 node.flags.alignment = new_alignment;
1034 defer {
1035 // alignment needs to be temporarily set for the resizes below
1036 if (!set_alignment) node.flags.alignment = prev_alignment;
1037 }
10131038
1014 const new_size = node.flags.alignment.forward(@intCast(size));1039 const new_size = node.flags.alignment.forward(@intCast(size));
1015 if (new_alignment.check(@intCast(old_offset))) {1040 if (new_alignment.check(@intCast(old_offset))) {
...@@ -1026,6 +1051,37 @@ fn realignNode(...@@ -1026,6 +1051,37 @@ fn realignNode(
1026 },1051 },
1027 };1052 };
10281053
1054 if (try_backward) {
1055 const backward_offset = new_alignment.backward(old_offset);
1056 const prev_end = if (node.prev == .none) 0 else prev: {
1057 const prev_offset, const prev_size = node.prev.location(mf).resolve(mf);
1058 break :prev prev_offset + prev_size;
1059 };
1060
1061 if (backward_offset >= prev_end) {
1062 try mf.ensureCapacityForSetLocation(gpa);
1063
1064 if (node.flags.has_content) {
1065 const old_file_offset = ni.fileLocation(mf, false).offset;
1066 const new_file_offset = (old_file_offset - old_offset) + backward_offset;
1067 @memmove(
1068 mf.memory_map.memory[@intCast(new_file_offset)..][0..@intCast(size)],
1069 mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)],
1070 );
1071 @memset(mf.memory_map.memory[@intCast(new_file_offset + size)..@intCast(old_file_offset + size)], 0);
1072 }
1073
1074 if (backward_offset + new_size <= trailing_end) {
1075 ni.setLocationAssumeCapacity(mf, backward_offset, new_size);
1076 } else {
1077 ni.setLocationAssumeCapacity(mf, backward_offset, size);
1078 try mf.resizeNode(gpa, ni, new_size);
1079 }
1080
1081 return;
1082 }
1083 }
1084
1029 const forward_offset = new_alignment.forward(@intCast(old_offset));1085 const forward_offset = new_alignment.forward(@intCast(old_offset));
1030 if (forward_offset + new_size <= trailing_end) {1086 if (forward_offset + new_size <= trailing_end) {
1031 // Shift into the free space if possible1087 // Shift into the free space if possible
test/standalone/shared_library/build.zig-2
...@@ -20,8 +20,6 @@ pub fn build(b: *std.Build) void {...@@ -20,8 +20,6 @@ pub fn build(b: *std.Build) void {
20 if (!use_llvm and target.result.cpu.arch == .loongarch64) continue; // TODO20 if (!use_llvm and target.result.cpu.arch == .loongarch64) continue; // TODO
21 if (!use_llvm and target.result.cpu.arch == .powerpc64le) continue; // TODO21 if (!use_llvm and target.result.cpu.arch == .powerpc64le) continue; // TODO
22 if (!use_llvm and target.result.cpu.arch == .s390x) continue; // TODO22 if (!use_llvm and target.result.cpu.arch == .s390x) continue; // TODO
23 if (!use_llvm and target.result.os.tag == .windows and target.result.abi == .gnu and dyn_libc)
24 continue; // TODO: sub-compilation of compiler_rt failed (failed to link with LLD: LibCInstallationNotAvailable)
2523
26 const lib = b.addLibrary(.{24 const lib = b.addLibrary(.{
27 .linkage = .dynamic,25 .linkage = .dynamic,