stage2: link.C: use pwritev

This commit is contained in:
Andrew Kelley 2021-01-05 13:04:51 -07:00
parent 7b8cede61f
commit e1811f72eb
2 changed files with 47 additions and 19 deletions

View File

@ -459,6 +459,7 @@ pub const File = struct {
return index;
}
/// See https://github.com/ziglang/zig/issues/7699
pub fn readv(self: File, iovecs: []const os.iovec) ReadError!usize {
if (is_windows) {
// TODO improve this to use ReadFileScatter
@ -479,6 +480,7 @@ pub const File = struct {
/// is not an error condition.
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize {
if (iovecs.len == 0) return;
@ -500,6 +502,7 @@ pub const File = struct {
}
}
/// See https://github.com/ziglang/zig/issues/7699
pub fn preadv(self: File, iovecs: []const os.iovec, offset: u64) PReadError!usize {
if (is_windows) {
// TODO improve this to use ReadFileScatter
@ -520,6 +523,7 @@ pub const File = struct {
/// is not an error condition.
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void {
if (iovecs.len == 0) return;
@ -582,6 +586,7 @@ pub const File = struct {
}
}
/// See https://github.com/ziglang/zig/issues/7699
pub fn writev(self: File, iovecs: []const os.iovec_const) WriteError!usize {
if (is_windows) {
// TODO improve this to use WriteFileScatter
@ -599,6 +604,7 @@ pub const File = struct {
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial writes from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void {
if (iovecs.len == 0) return;
@ -615,6 +621,7 @@ pub const File = struct {
}
}
/// See https://github.com/ziglang/zig/issues/7699
pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize {
if (is_windows) {
// TODO improve this to use WriteFileScatter
@ -632,6 +639,7 @@ pub const File = struct {
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial writes from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void {
if (iovecs.len == 0) return;

View File

@ -41,13 +41,12 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
if (options.use_lld) return error.LLDHasNoCBackend;
const file = try options.emit.?.directory.handle.createFile(sub_path, .{
.truncate = true,
// Truncation is done on `flush`.
.truncate = false,
.mode = link.determineMode(options),
});
errdefer file.close();
try file.writeAll(zig_h);
var c_file = try allocator.create(C);
errdefer allocator.destroy(c_file);
@ -133,40 +132,61 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
const tracy = trace(@src());
defer tracy.end();
const file = self.base.file.?;
const module = self.base.options.module orelse
return error.LinkingWithoutZigSourceUnimplemented;
// The header is written upon opening; here we truncate and seek to after the header.
// TODO: use writev
try file.seekTo(zig_h.len);
try file.setEndPos(zig_h.len);
// We collect a list of buffers to write, and write them all at once with pwritev 😎
var all_buffers = std.ArrayList(std.os.iovec_const).init(comp.gpa);
defer all_buffers.deinit();
var buffered_writer = std.io.bufferedWriter(file.writer());
const writer = buffered_writer.writer();
// This is at least enough until we get to the function bodies without error handling.
try all_buffers.ensureCapacity(module.decl_table.count() + 1);
const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
var file_size: u64 = zig_h.len;
all_buffers.appendAssumeCapacity(.{
.iov_base = zig_h,
.iov_len = zig_h.len,
});
var fn_count: usize = 0;
// Forward decls and non-functions first.
// TODO: use writev
for (module.decl_table.items()) |kv| {
const decl = kv.value;
const decl_tv = decl.typed_value.most_recent.typed_value;
if (decl_tv.val.castTag(.function)) |_| {
try writer.writeAll(decl.fn_link.c.fwd_decl.items);
} else {
try writer.writeAll(decl.link.c.code.items);
}
const buf = buf: {
if (decl_tv.val.castTag(.function)) |_| {
fn_count += 1;
break :buf decl.fn_link.c.fwd_decl.items;
} else {
break :buf decl.link.c.code.items;
}
};
all_buffers.appendAssumeCapacity(.{
.iov_base = buf.ptr,
.iov_len = buf.len,
});
file_size += buf.len;
}
// Now the function bodies.
try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);
for (module.decl_table.items()) |kv| {
const decl = kv.value;
const decl_tv = decl.typed_value.most_recent.typed_value;
if (decl_tv.val.castTag(.function)) |_| {
try writer.writeAll(decl.link.c.code.items);
const buf = decl.link.c.code.items;
all_buffers.appendAssumeCapacity(.{
.iov_base = buf.ptr,
.iov_len = buf.len,
});
file_size += buf.len;
}
}
try buffered_writer.flush();
const file = self.base.file.?;
try file.setEndPos(file_size);
try file.pwritevAll(all_buffers.items, 0);
}
pub fn updateDeclExports(