| author | |
| committer | |
| log | e1811f72eb1bae11934dfd423baa5b26efd99afd |
| tree | ce10147303417f00af370e9fdbdfd616e98c6f88 |
| parent | 7b8cede61fc20c137aca4e02425536bfc9a5a400 |
2 files changed, 47 insertions(+), 19 deletions(-)
lib/std/fs/file.zig+8| ... | ... | @@ -459,6 +459,7 @@ pub const File = struct { |
| 459 | 459 | return index; |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 462 | 463 | pub fn readv(self: File, iovecs: []const os.iovec) ReadError!usize { |
| 463 | 464 | if (is_windows) { |
| 464 | 465 | // TODO improve this to use ReadFileScatter |
| ... | ... | @@ -479,6 +480,7 @@ pub const File = struct { |
| 479 | 480 | /// is not an error condition. |
| 480 | 481 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in |
| 481 | 482 | /// order to handle partial reads from the underlying OS layer. |
| 483 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 482 | 484 | pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize { |
| 483 | 485 | if (iovecs.len == 0) return; |
| 484 | 486 | |
| ... | ... | @@ -500,6 +502,7 @@ pub const File = struct { |
| 500 | 502 | } |
| 501 | 503 | } |
| 502 | 504 | |
| 505 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 503 | 506 | pub fn preadv(self: File, iovecs: []const os.iovec, offset: u64) PReadError!usize { |
| 504 | 507 | if (is_windows) { |
| 505 | 508 | // TODO improve this to use ReadFileScatter |
| ... | ... | @@ -520,6 +523,7 @@ pub const File = struct { |
| 520 | 523 | /// is not an error condition. |
| 521 | 524 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in |
| 522 | 525 | /// order to handle partial reads from the underlying OS layer. |
| 526 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 523 | 527 | pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void { |
| 524 | 528 | if (iovecs.len == 0) return; |
| 525 | 529 | |
| ... | ... | @@ -582,6 +586,7 @@ pub const File = struct { |
| 582 | 586 | } |
| 583 | 587 | } |
| 584 | 588 | |
| 589 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 585 | 590 | pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize { |
| 586 | 591 | if (is_windows) { |
| 587 | 592 | // TODO improve this to use WriteFileScatter |
| ... | ... | @@ -599,6 +604,7 @@ pub const File = struct { |
| 599 | 604 | |
| 600 | 605 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in |
| 601 | 606 | /// order to handle partial writes from the underlying OS layer. |
| 607 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 602 | 608 | pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void { |
| 603 | 609 | if (iovecs.len == 0) return; |
| 604 | 610 | |
| ... | ... | @@ -615,6 +621,7 @@ pub const File = struct { |
| 615 | 621 | } |
| 616 | 622 | } |
| 617 | 623 | |
| 624 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 618 | 625 | pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize { |
| 619 | 626 | if (is_windows) { |
| 620 | 627 | // TODO improve this to use WriteFileScatter |
| ... | ... | @@ -632,6 +639,7 @@ pub const File = struct { |
| 632 | 639 | |
| 633 | 640 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in |
| 634 | 641 | /// order to handle partial writes from the underlying OS layer. |
| 642 | /// See https://github.com/ziglang/zig/issues/7699 | |
| 635 | 643 | pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void { |
| 636 | 644 | if (iovecs.len == 0) return; |
| 637 | 645 |
src/link/C.zig+39-19| ... | ... | @@ -41,13 +41,12 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 41 | 41 | if (options.use_lld) return error.LLDHasNoCBackend; |
| 42 | 42 | |
| 43 | 43 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 44 | .truncate = true, | |
| 44 | // Truncation is done on `flush`. | |
| 45 | .truncate = false, | |
| 45 | 46 | .mode = link.determineMode(options), |
| 46 | 47 | }); |
| 47 | 48 | errdefer file.close(); |
| 48 | 49 | |
| 49 | try file.writeAll(zig_h); | |
| 50 | ||
| 51 | 50 | var c_file = try allocator.create(C); |
| 52 | 51 | errdefer allocator.destroy(c_file); |
| 53 | 52 | |
| ... | ... | @@ -133,40 +132,61 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { |
| 133 | 132 | const tracy = trace(@src()); |
| 134 | 133 | defer tracy.end(); |
| 135 | 134 | |
| 136 | const file = self.base.file.?; | |
| 135 | const module = self.base.options.module orelse | |
| 136 | return error.LinkingWithoutZigSourceUnimplemented; | |
| 137 | 137 | |
| 138 | // The header is written upon opening; here we truncate and seek to after the header. | |
| 139 | // TODO: use writev | |
| 140 | try file.seekTo(zig_h.len); | |
| 141 | try file.setEndPos(zig_h.len); | |
| 138 | // We collect a list of buffers to write, and write them all at once with pwritev 😎 | |
| 139 | var all_buffers = std.ArrayList(std.os.iovec_const).init(comp.gpa); | |
| 140 | defer all_buffers.deinit(); | |
| 142 | 141 | |
| 143 | var buffered_writer = std.io.bufferedWriter(file.writer()); | |
| 144 | const writer = buffered_writer.writer(); | |
| 142 | // This is at least enough until we get to the function bodies without error handling. | |
| 143 | try all_buffers.ensureCapacity(module.decl_table.count() + 1); | |
| 144 | ||
| 145 | var file_size: u64 = zig_h.len; | |
| 146 | all_buffers.appendAssumeCapacity(.{ | |
| 147 | .iov_base = zig_h, | |
| 148 | .iov_len = zig_h.len, | |
| 149 | }); | |
| 145 | 150 | |
| 146 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | |
| 151 | var fn_count: usize = 0; | |
| 147 | 152 | |
| 148 | 153 | // Forward decls and non-functions first. |
| 149 | // TODO: use writev | |
| 150 | 154 | for (module.decl_table.items()) |kv| { |
| 151 | 155 | const decl = kv.value; |
| 152 | 156 | const decl_tv = decl.typed_value.most_recent.typed_value; |
| 153 | if (decl_tv.val.castTag(.function)) |_| { | |
| 154 | try writer.writeAll(decl.fn_link.c.fwd_decl.items); | |
| 155 | } else { | |
| 156 | try writer.writeAll(decl.link.c.code.items); | |
| 157 | } | |
| 157 | const buf = buf: { | |
| 158 | if (decl_tv.val.castTag(.function)) |_| { | |
| 159 | fn_count += 1; | |
| 160 | break :buf decl.fn_link.c.fwd_decl.items; | |
| 161 | } else { | |
| 162 | break :buf decl.link.c.code.items; | |
| 163 | } | |
| 164 | }; | |
| 165 | all_buffers.appendAssumeCapacity(.{ | |
| 166 | .iov_base = buf.ptr, | |
| 167 | .iov_len = buf.len, | |
| 168 | }); | |
| 169 | file_size += buf.len; | |
| 158 | 170 | } |
| 159 | 171 | |
| 160 | 172 | // Now the function bodies. |
| 173 | try all_buffers.ensureCapacity(all_buffers.items.len + fn_count); | |
| 161 | 174 | for (module.decl_table.items()) |kv| { |
| 162 | 175 | const decl = kv.value; |
| 163 | 176 | const decl_tv = decl.typed_value.most_recent.typed_value; |
| 164 | 177 | if (decl_tv.val.castTag(.function)) |_| { |
| 165 | try writer.writeAll(decl.link.c.code.items); | |
| 178 | const buf = decl.link.c.code.items; | |
| 179 | all_buffers.appendAssumeCapacity(.{ | |
| 180 | .iov_base = buf.ptr, | |
| 181 | .iov_len = buf.len, | |
| 182 | }); | |
| 183 | file_size += buf.len; | |
| 166 | 184 | } |
| 167 | 185 | } |
| 168 | 186 | |
| 169 | try buffered_writer.flush(); | |
| 187 | const file = self.base.file.?; | |
| 188 | try file.setEndPos(file_size); | |
| 189 | try file.pwritevAll(all_buffers.items, 0); | |
| 170 | 190 | } |
| 171 | 191 | |
| 172 | 192 | pub fn updateDeclExports( |