mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge remote-tracking branch 'origin/master' into wrangle-writer-buffering
This commit is contained in:
commit
5e6b8e17ef
@ -708,7 +708,7 @@ fn runStepNames(
|
||||
|
||||
const total_count = success_count + failure_count + pending_count + skipped_count;
|
||||
ttyconf.setColor(w, .cyan) catch {};
|
||||
w.writeAll("Build Summary:") catch {};
|
||||
w.writeAll("\nBuild Summary:") catch {};
|
||||
ttyconf.setColor(w, .reset) catch {};
|
||||
w.print(" {d}/{d} steps succeeded", .{ success_count, total_count }) catch {};
|
||||
if (skipped_count > 0) w.print("; {d} skipped", .{skipped_count}) catch {};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1764,13 +1764,22 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
|
||||
child.stdin = null;
|
||||
},
|
||||
.lazy_path => |lazy_path| {
|
||||
const path = lazy_path.getPath2(b, &run.step);
|
||||
const file = b.build_root.handle.openFile(path, .{}) catch |err| {
|
||||
const path = lazy_path.getPath3(b, &run.step);
|
||||
const file = path.root_dir.handle.openFile(path.subPathOrDot(), .{}) catch |err| {
|
||||
return run.step.fail("unable to open stdin file: {s}", .{@errorName(err)});
|
||||
};
|
||||
defer file.close();
|
||||
child.stdin.?.writeFileAll(file, .{}) catch |err| {
|
||||
return run.step.fail("unable to write file to stdin: {s}", .{@errorName(err)});
|
||||
// TODO https://github.com/ziglang/zig/issues/23955
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var file_reader = file.reader(&buffer);
|
||||
var stdin_writer = child.stdin.?.writer(&.{});
|
||||
_ = stdin_writer.interface.sendFileAll(&file_reader, .unlimited) catch |err| switch (err) {
|
||||
error.ReadFailed => return run.step.fail("failed to read from {f}: {t}", .{
|
||||
path, file_reader.err.?,
|
||||
}),
|
||||
error.WriteFailed => return run.step.fail("failed to write to stdin: {t}", .{
|
||||
stdin_writer.err.?,
|
||||
}),
|
||||
};
|
||||
child.stdin.?.close();
|
||||
child.stdin = null;
|
||||
|
||||
@ -440,7 +440,8 @@ pub fn advance(w: *Writer, n: usize) void {
|
||||
/// After calling `writableVector`, this function tracks how many bytes were
|
||||
/// written to it.
|
||||
pub fn advanceVector(w: *Writer, n: usize) usize {
|
||||
return consume(w, n);
|
||||
if (w.vtable != VectorWrapper.vtable) advance(w, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/// The `data` parameter is mutable because this function needs to mutate the
|
||||
|
||||
@ -912,18 +912,9 @@ const WasiThreadImpl = struct {
|
||||
allocator.free(self.thread.memory);
|
||||
}
|
||||
|
||||
var spin: u8 = 10;
|
||||
while (true) {
|
||||
const tid = self.thread.tid.load(.seq_cst);
|
||||
if (tid == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (spin > 0) {
|
||||
spin -= 1;
|
||||
std.atomic.spinLoopHint();
|
||||
continue;
|
||||
}
|
||||
if (tid == 0) break;
|
||||
|
||||
const result = asm (
|
||||
\\ local.get %[ptr]
|
||||
@ -1515,18 +1506,9 @@ const LinuxThreadImpl = struct {
|
||||
fn join(self: Impl) void {
|
||||
defer posix.munmap(self.thread.mapped);
|
||||
|
||||
var spin: u8 = 10;
|
||||
while (true) {
|
||||
const tid = self.thread.child_tid.load(.seq_cst);
|
||||
if (tid == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (spin > 0) {
|
||||
spin -= 1;
|
||||
std.atomic.spinLoopHint();
|
||||
continue;
|
||||
}
|
||||
if (tid == 0) break;
|
||||
|
||||
switch (linux.E.init(linux.futex_4arg(
|
||||
&self.thread.child_tid.raw,
|
||||
@ -1617,7 +1599,6 @@ test "setName, getName" {
|
||||
}
|
||||
|
||||
test {
|
||||
// Doesn't use testing.refAllDecls() since that would pull in the compileError spinLoopHint.
|
||||
_ = Futex;
|
||||
_ = ResetEvent;
|
||||
_ = Mutex;
|
||||
|
||||
@ -10497,9 +10497,9 @@ pub const sysconf = switch (native_os) {
|
||||
|
||||
pub const sf_hdtr = switch (native_os) {
|
||||
.freebsd, .macos, .ios, .tvos, .watchos, .visionos => extern struct {
|
||||
headers: [*]const iovec_const,
|
||||
headers: ?[*]const iovec_const,
|
||||
hdr_cnt: c_int,
|
||||
trailers: [*]const iovec_const,
|
||||
trailers: ?[*]const iovec_const,
|
||||
trl_cnt: c_int,
|
||||
},
|
||||
else => void,
|
||||
|
||||
134
lib/std/elf.zig
134
lib/std/elf.zig
@ -482,6 +482,7 @@ pub const Header = struct {
|
||||
is_64: bool,
|
||||
endian: std.builtin.Endian,
|
||||
os_abi: OSABI,
|
||||
/// The meaning of this value depends on `os_abi`.
|
||||
abi_version: u8,
|
||||
type: ET,
|
||||
machine: EM,
|
||||
@ -508,75 +509,54 @@ pub const Header = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub const ReadError = std.io.Reader.Error || ParseError;
|
||||
|
||||
pub fn read(r: *std.io.Reader) ReadError!Header {
|
||||
const buf = try r.peek(@sizeOf(Elf64_Ehdr));
|
||||
const result = try parse(@ptrCast(buf));
|
||||
r.toss(if (result.is_64) @sizeOf(Elf64_Ehdr) else @sizeOf(Elf32_Ehdr));
|
||||
return result;
|
||||
}
|
||||
|
||||
pub const ParseError = error{
|
||||
pub const ReadError = std.Io.Reader.Error || error{
|
||||
InvalidElfMagic,
|
||||
InvalidElfVersion,
|
||||
InvalidElfClass,
|
||||
InvalidElfEndian,
|
||||
};
|
||||
|
||||
pub fn parse(hdr_buf: *align(@alignOf(Elf64_Ehdr)) const [@sizeOf(Elf64_Ehdr)]u8) ParseError!Header {
|
||||
const hdr32: *const Elf32_Ehdr = @ptrCast(hdr_buf);
|
||||
const hdr64: *const Elf64_Ehdr = @ptrCast(hdr_buf);
|
||||
if (!mem.eql(u8, hdr32.e_ident[0..4], MAGIC)) return error.InvalidElfMagic;
|
||||
if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion;
|
||||
pub fn read(r: *std.Io.Reader) ReadError!Header {
|
||||
const buf = try r.peek(@sizeOf(Elf64_Ehdr));
|
||||
|
||||
const is_64 = switch (hdr32.e_ident[EI_CLASS]) {
|
||||
ELFCLASS32 => false,
|
||||
ELFCLASS64 => true,
|
||||
else => return error.InvalidElfClass,
|
||||
};
|
||||
if (!mem.eql(u8, buf[0..4], MAGIC)) return error.InvalidElfMagic;
|
||||
if (buf[EI_VERSION] != 1) return error.InvalidElfVersion;
|
||||
|
||||
const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) {
|
||||
const endian: std.builtin.Endian = switch (buf[EI_DATA]) {
|
||||
ELFDATA2LSB => .little,
|
||||
ELFDATA2MSB => .big,
|
||||
else => return error.InvalidElfEndian,
|
||||
};
|
||||
const need_bswap = endian != native_endian;
|
||||
|
||||
return switch (buf[EI_CLASS]) {
|
||||
ELFCLASS32 => .init(try r.takeStruct(Elf32_Ehdr, endian), endian),
|
||||
ELFCLASS64 => .init(try r.takeStruct(Elf64_Ehdr, endian), endian),
|
||||
else => return error.InvalidElfClass,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init(hdr: anytype, endian: std.builtin.Endian) Header {
|
||||
// Converting integers to exhaustive enums using `@enumFromInt` could cause a panic.
|
||||
comptime assert(!@typeInfo(OSABI).@"enum".is_exhaustive);
|
||||
const os_abi: OSABI = @enumFromInt(hdr32.e_ident[EI_OSABI]);
|
||||
|
||||
// The meaning of this value depends on `os_abi` so just make it available as `u8`.
|
||||
const abi_version = hdr32.e_ident[EI_ABIVERSION];
|
||||
|
||||
const @"type": ET = if (need_bswap) blk: {
|
||||
comptime assert(!@typeInfo(ET).@"enum".is_exhaustive);
|
||||
const value = @intFromEnum(hdr32.e_type);
|
||||
break :blk @enumFromInt(@byteSwap(value));
|
||||
} else hdr32.e_type;
|
||||
|
||||
const machine: EM = if (need_bswap) blk: {
|
||||
comptime assert(!@typeInfo(EM).@"enum".is_exhaustive);
|
||||
const value = @intFromEnum(hdr32.e_machine);
|
||||
break :blk @enumFromInt(@byteSwap(value));
|
||||
} else hdr32.e_machine;
|
||||
|
||||
return .{
|
||||
.is_64 = is_64,
|
||||
.is_64 = switch (@TypeOf(hdr)) {
|
||||
Elf32_Ehdr => false,
|
||||
Elf64_Ehdr => true,
|
||||
else => @compileError("bad type"),
|
||||
},
|
||||
.endian = endian,
|
||||
.os_abi = os_abi,
|
||||
.abi_version = abi_version,
|
||||
.type = @"type",
|
||||
.machine = machine,
|
||||
.entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry),
|
||||
.phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff),
|
||||
.shoff = int(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff),
|
||||
.phentsize = int(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize),
|
||||
.phnum = int(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum),
|
||||
.shentsize = int(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize),
|
||||
.shnum = int(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum),
|
||||
.shstrndx = int(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx),
|
||||
.os_abi = @enumFromInt(hdr.e_ident[EI_OSABI]),
|
||||
.abi_version = hdr.e_ident[EI_ABIVERSION],
|
||||
.type = hdr.e_type,
|
||||
.machine = hdr.e_machine,
|
||||
.entry = hdr.e_entry,
|
||||
.phoff = hdr.e_phoff,
|
||||
.shoff = hdr.e_shoff,
|
||||
.phentsize = hdr.e_phentsize,
|
||||
.phnum = hdr.e_phnum,
|
||||
.shentsize = hdr.e_shentsize,
|
||||
.shnum = hdr.e_shnum,
|
||||
.shstrndx = hdr.e_shstrndx,
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -591,21 +571,15 @@ pub const ProgramHeaderIterator = struct {
|
||||
defer it.index += 1;
|
||||
|
||||
if (it.elf_header.is_64) {
|
||||
var phdr: Elf64_Phdr = undefined;
|
||||
const offset = it.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * it.index;
|
||||
const offset = it.elf_header.phoff + @sizeOf(Elf64_Phdr) * it.index;
|
||||
try it.file_reader.seekTo(offset);
|
||||
try it.file_reader.interface.readSlice(@ptrCast(&phdr));
|
||||
if (it.elf_header.endian != native_endian)
|
||||
mem.byteSwapAllFields(Elf64_Phdr, &phdr);
|
||||
const phdr = try it.file_reader.interface.takeStruct(Elf64_Phdr, it.elf_header.endian);
|
||||
return phdr;
|
||||
}
|
||||
|
||||
var phdr: Elf32_Phdr = undefined;
|
||||
const offset = it.elf_header.phoff + @sizeOf(@TypeOf(phdr)) * it.index;
|
||||
const offset = it.elf_header.phoff + @sizeOf(Elf32_Phdr) * it.index;
|
||||
try it.file_reader.seekTo(offset);
|
||||
try it.file_reader.interface.readSlice(@ptrCast(&phdr));
|
||||
if (it.elf_header.endian != native_endian)
|
||||
mem.byteSwapAllFields(Elf32_Phdr, &phdr);
|
||||
const phdr = try it.file_reader.interface.takeStruct(Elf32_Phdr, it.elf_header.endian);
|
||||
return .{
|
||||
.p_type = phdr.p_type,
|
||||
.p_offset = phdr.p_offset,
|
||||
@ -629,21 +603,13 @@ pub const SectionHeaderIterator = struct {
|
||||
defer it.index += 1;
|
||||
|
||||
if (it.elf_header.is_64) {
|
||||
var shdr: Elf64_Shdr = undefined;
|
||||
const offset = it.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * it.index;
|
||||
try it.file_reader.seekTo(offset);
|
||||
try it.file_reader.interface.readSlice(@ptrCast(&shdr));
|
||||
if (it.elf_header.endian != native_endian)
|
||||
mem.byteSwapAllFields(Elf64_Shdr, &shdr);
|
||||
try it.file_reader.seekTo(it.elf_header.shoff + @sizeOf(Elf64_Shdr) * it.index);
|
||||
const shdr = try it.file_reader.interface.takeStruct(Elf64_Shdr, it.elf_header.endian);
|
||||
return shdr;
|
||||
}
|
||||
|
||||
var shdr: Elf32_Shdr = undefined;
|
||||
const offset = it.elf_header.shoff + @sizeOf(@TypeOf(shdr)) * it.index;
|
||||
try it.file_reader.seekTo(offset);
|
||||
try it.file_reader.interface.readSlice(@ptrCast(&shdr));
|
||||
if (it.elf_header.endian != native_endian)
|
||||
mem.byteSwapAllFields(Elf32_Shdr, &shdr);
|
||||
try it.file_reader.seekTo(it.elf_header.shoff + @sizeOf(Elf32_Shdr) * it.index);
|
||||
const shdr = try it.file_reader.interface.takeStruct(Elf32_Shdr, it.elf_header.endian);
|
||||
return .{
|
||||
.sh_name = shdr.sh_name,
|
||||
.sh_type = shdr.sh_type,
|
||||
@ -659,26 +625,6 @@ pub const SectionHeaderIterator = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) {
|
||||
if (is_64) {
|
||||
if (need_bswap) {
|
||||
return @byteSwap(int_64);
|
||||
} else {
|
||||
return int_64;
|
||||
}
|
||||
} else {
|
||||
return int32(need_bswap, int_32, @TypeOf(int_64));
|
||||
}
|
||||
}
|
||||
|
||||
fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 {
|
||||
if (need_bswap) {
|
||||
return @byteSwap(int_32);
|
||||
} else {
|
||||
return int_32;
|
||||
}
|
||||
}
|
||||
|
||||
pub const ELFCLASSNONE = 0;
|
||||
pub const ELFCLASS32 = 1;
|
||||
pub const ELFCLASS64 = 2;
|
||||
|
||||
@ -1,3 +1,20 @@
|
||||
const Dir = @This();
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("../std.zig");
|
||||
const File = std.fs.File;
|
||||
const AtomicFile = std.fs.AtomicFile;
|
||||
const base64_encoder = fs.base64_encoder;
|
||||
const posix = std.posix;
|
||||
const mem = std.mem;
|
||||
const path = fs.path;
|
||||
const fs = std.fs;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const linux = std.os.linux;
|
||||
const windows = std.os.windows;
|
||||
const native_os = builtin.os.tag;
|
||||
const have_flock = @TypeOf(posix.system.flock) != void;
|
||||
|
||||
fd: Handle,
|
||||
|
||||
pub const Handle = posix.fd_t;
|
||||
@ -1862,9 +1879,10 @@ pub fn symLinkW(
|
||||
|
||||
/// Same as `symLink`, except tries to create the symbolic link until it
|
||||
/// succeeds or encounters an error other than `error.PathAlreadyExists`.
|
||||
/// On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
|
||||
/// On WASI, both paths should be encoded as valid UTF-8.
|
||||
/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
|
||||
///
|
||||
/// * On Windows, both paths should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
|
||||
/// * On WASI, both paths should be encoded as valid UTF-8.
|
||||
/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
|
||||
pub fn atomicSymLink(
|
||||
dir: Dir,
|
||||
target_path: []const u8,
|
||||
@ -1880,9 +1898,8 @@ pub fn atomicSymLink(
|
||||
|
||||
const dirname = path.dirname(sym_link_path) orelse ".";
|
||||
|
||||
var rand_buf: [AtomicFile.random_bytes_len]u8 = undefined;
|
||||
|
||||
const temp_path_len = dirname.len + 1 + base64_encoder.calcSize(rand_buf.len);
|
||||
const rand_len = @sizeOf(u64) * 2;
|
||||
const temp_path_len = dirname.len + 1 + rand_len;
|
||||
var temp_path_buf: [fs.max_path_bytes]u8 = undefined;
|
||||
|
||||
if (temp_path_len > temp_path_buf.len) return error.NameTooLong;
|
||||
@ -1892,8 +1909,8 @@ pub fn atomicSymLink(
|
||||
const temp_path = temp_path_buf[0..temp_path_len];
|
||||
|
||||
while (true) {
|
||||
crypto.random.bytes(rand_buf[0..]);
|
||||
_ = base64_encoder.encode(temp_path[dirname.len + 1 ..], rand_buf[0..]);
|
||||
const random_integer = std.crypto.random.int(u64);
|
||||
temp_path[dirname.len + 1 ..][0..rand_len].* = std.fmt.hex(random_integer);
|
||||
|
||||
if (dir.symLink(target_path, temp_path, flags)) {
|
||||
return dir.rename(temp_path, sym_link_path);
|
||||
@ -2623,8 +2640,9 @@ pub fn updateFile(
|
||||
return .stale;
|
||||
}
|
||||
|
||||
pub const CopyFileError = File.OpenError || File.StatError || File.ReadError || File.WriteError ||
|
||||
AtomicFile.InitError || AtomicFile.FinishError;
|
||||
pub const CopyFileError = File.OpenError || File.StatError ||
|
||||
AtomicFile.InitError || AtomicFile.FinishError ||
|
||||
File.ReadError || File.WriteError;
|
||||
|
||||
/// Atomically creates a new file at `dest_path` within `dest_dir` with the
|
||||
/// same contents as `source_path` within `source_dir`, overwriting any already
|
||||
@ -2655,7 +2673,7 @@ pub fn copyFile(
|
||||
break :blk st.mode;
|
||||
};
|
||||
|
||||
var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available.
|
||||
var buffer: [1024]u8 = undefined; // Used only when direct fd-to-fd is not available.
|
||||
var atomic_file = try dest_dir.atomicFile(dest_path, .{
|
||||
.mode = mode,
|
||||
.write_buffer = &buffer,
|
||||
@ -2666,6 +2684,7 @@ pub fn copyFile(
|
||||
error.ReadFailed => return file_reader.err.?,
|
||||
error.WriteFailed => return atomic_file.file_writer.err.?,
|
||||
};
|
||||
|
||||
try atomic_file.finish();
|
||||
}
|
||||
|
||||
@ -2790,21 +2809,3 @@ pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!v
|
||||
const file: File = .{ .handle = self.fd };
|
||||
try file.setPermissions(permissions);
|
||||
}
|
||||
|
||||
const Dir = @This();
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("../std.zig");
|
||||
const File = std.fs.File;
|
||||
const AtomicFile = std.fs.AtomicFile;
|
||||
const base64_encoder = fs.base64_encoder;
|
||||
const crypto = std.crypto;
|
||||
const posix = std.posix;
|
||||
const mem = std.mem;
|
||||
const path = fs.path;
|
||||
const fs = std.fs;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const linux = std.os.linux;
|
||||
const windows = std.os.windows;
|
||||
const native_os = builtin.os.tag;
|
||||
const have_flock = @TypeOf(posix.system.flock) != void;
|
||||
|
||||
@ -918,7 +918,7 @@ pub const Reader = struct {
|
||||
err: ?ReadError = null,
|
||||
mode: Reader.Mode = .positional,
|
||||
/// Tracks the true seek position in the file. To obtain the logical
|
||||
/// position, subtract the buffer size from this value.
|
||||
/// position, use `logicalPos`.
|
||||
pos: u64 = 0,
|
||||
size: ?u64 = null,
|
||||
size_err: ?GetEndPosError = null,
|
||||
@ -1011,14 +1011,12 @@ pub const Reader = struct {
|
||||
pub fn seekBy(r: *Reader, offset: i64) Reader.SeekError!void {
|
||||
switch (r.mode) {
|
||||
.positional, .positional_reading => {
|
||||
// TODO: make += operator allow any integer types
|
||||
r.pos = @intCast(@as(i64, @intCast(r.pos)) + offset);
|
||||
setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
|
||||
},
|
||||
.streaming, .streaming_reading => {
|
||||
const seek_err = r.seek_err orelse e: {
|
||||
if (posix.lseek_CUR(r.file.handle, offset)) |_| {
|
||||
// TODO: make += operator allow any integer types
|
||||
r.pos = @intCast(@as(i64, @intCast(r.pos)) + offset);
|
||||
setPosAdjustingBuffer(r, @intCast(@as(i64, @intCast(r.pos)) + offset));
|
||||
return;
|
||||
} else |err| {
|
||||
r.seek_err = err;
|
||||
@ -1034,6 +1032,8 @@ pub const Reader = struct {
|
||||
r.pos += n;
|
||||
remaining -= n;
|
||||
}
|
||||
r.interface.seek = 0;
|
||||
r.interface.end = 0;
|
||||
},
|
||||
.failure => return r.seek_err.?,
|
||||
}
|
||||
@ -1042,7 +1042,7 @@ pub const Reader = struct {
|
||||
pub fn seekTo(r: *Reader, offset: u64) Reader.SeekError!void {
|
||||
switch (r.mode) {
|
||||
.positional, .positional_reading => {
|
||||
r.pos = offset;
|
||||
setPosAdjustingBuffer(r, offset);
|
||||
},
|
||||
.streaming, .streaming_reading => {
|
||||
if (offset >= r.pos) return Reader.seekBy(r, @intCast(offset - r.pos));
|
||||
@ -1051,12 +1051,28 @@ pub const Reader = struct {
|
||||
r.seek_err = err;
|
||||
return err;
|
||||
};
|
||||
r.pos = offset;
|
||||
setPosAdjustingBuffer(r, offset);
|
||||
},
|
||||
.failure => return r.seek_err.?,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn logicalPos(r: *const Reader) u64 {
|
||||
return r.pos - r.interface.bufferedLen();
|
||||
}
|
||||
|
||||
fn setPosAdjustingBuffer(r: *Reader, offset: u64) void {
|
||||
const logical_pos = logicalPos(r);
|
||||
if (offset < logical_pos or offset >= r.pos) {
|
||||
r.interface.seek = 0;
|
||||
r.interface.end = 0;
|
||||
r.pos = offset;
|
||||
} else {
|
||||
const logical_delta: usize = @intCast(offset - logical_pos);
|
||||
r.interface.seek += logical_delta;
|
||||
}
|
||||
}
|
||||
|
||||
/// Number of slices to store on the stack, when trying to send as many byte
|
||||
/// vectors through the underlying read calls as possible.
|
||||
const max_buffers_len = 16;
|
||||
@ -1106,7 +1122,7 @@ pub const Reader = struct {
|
||||
return error.EndOfStream;
|
||||
}
|
||||
r.pos += n;
|
||||
return n;
|
||||
return w.advanceVector(n);
|
||||
},
|
||||
.streaming_reading => {
|
||||
if (is_windows) {
|
||||
@ -1129,7 +1145,7 @@ pub const Reader = struct {
|
||||
return error.EndOfStream;
|
||||
}
|
||||
r.pos += n;
|
||||
return n;
|
||||
return w.advanceVector(n);
|
||||
},
|
||||
.failure => return error.ReadFailed,
|
||||
}
|
||||
@ -1202,7 +1218,7 @@ pub const Reader = struct {
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
const n = @min(size - pos, std.math.maxInt(i64), @intFromEnum(limit));
|
||||
const n = @min(size - pos, maxInt(i64), @intFromEnum(limit));
|
||||
file.seekBy(n) catch |err| {
|
||||
r.seek_err = err;
|
||||
return 0;
|
||||
@ -1391,7 +1407,6 @@ pub const Writer = struct {
|
||||
const pattern = data[data.len - 1];
|
||||
if (pattern.len == 0 or splat == 0) return 0;
|
||||
const n = windows.WriteFile(handle, pattern, null) catch |err| {
|
||||
std.debug.print("windows write file failed3: {t}\n", .{err});
|
||||
w.err = err;
|
||||
return error.WriteFailed;
|
||||
};
|
||||
@ -1493,18 +1508,141 @@ pub const Writer = struct {
|
||||
file_reader: *Reader,
|
||||
limit: std.io.Limit,
|
||||
) std.io.Writer.FileError!usize {
|
||||
const reader_buffered = file_reader.interface.buffered();
|
||||
if (reader_buffered.len >= @intFromEnum(limit))
|
||||
return sendFileBuffered(io_w, file_reader, reader_buffered);
|
||||
const writer_buffered = io_w.buffered();
|
||||
const file_limit = @intFromEnum(limit) - reader_buffered.len;
|
||||
const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w));
|
||||
const out_fd = w.file.handle;
|
||||
const in_fd = file_reader.file.handle;
|
||||
// TODO try using copy_file_range on FreeBSD
|
||||
// TODO try using sendfile on macOS
|
||||
// TODO try using sendfile on FreeBSD
|
||||
|
||||
if (file_reader.size) |size| {
|
||||
if (size - file_reader.pos == 0) {
|
||||
if (reader_buffered.len != 0) {
|
||||
return sendFileBuffered(io_w, file_reader, reader_buffered);
|
||||
} else {
|
||||
return error.EndOfStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (native_os == .freebsd and w.mode == .streaming) sf: {
|
||||
// Try using sendfile on FreeBSD.
|
||||
if (w.sendfile_err != null) break :sf;
|
||||
const offset = std.math.cast(std.c.off_t, file_reader.pos) orelse break :sf;
|
||||
var hdtr_data: std.c.sf_hdtr = undefined;
|
||||
var headers: [2]posix.iovec_const = undefined;
|
||||
var headers_i: u8 = 0;
|
||||
if (writer_buffered.len != 0) {
|
||||
headers[headers_i] = .{ .base = writer_buffered.ptr, .len = writer_buffered.len };
|
||||
headers_i += 1;
|
||||
}
|
||||
if (reader_buffered.len != 0) {
|
||||
headers[headers_i] = .{ .base = reader_buffered.ptr, .len = reader_buffered.len };
|
||||
headers_i += 1;
|
||||
}
|
||||
const hdtr: ?*std.c.sf_hdtr = if (headers_i == 0) null else b: {
|
||||
hdtr_data = .{
|
||||
.headers = &headers,
|
||||
.hdr_cnt = headers_i,
|
||||
.trailers = null,
|
||||
.trl_cnt = 0,
|
||||
};
|
||||
break :b &hdtr_data;
|
||||
};
|
||||
var sbytes: std.c.off_t = undefined;
|
||||
const nbytes: usize = @min(file_limit, maxInt(usize));
|
||||
const flags = 0;
|
||||
switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, nbytes, hdtr, &sbytes, flags))) {
|
||||
.SUCCESS, .INTR => {},
|
||||
.INVAL, .OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation,
|
||||
.BADF => if (builtin.mode == .Debug) @panic("race condition") else {
|
||||
w.sendfile_err = error.Unexpected;
|
||||
},
|
||||
.FAULT => if (builtin.mode == .Debug) @panic("segmentation fault") else {
|
||||
w.sendfile_err = error.Unexpected;
|
||||
},
|
||||
.NOTCONN => w.sendfile_err = error.BrokenPipe,
|
||||
.AGAIN, .BUSY => if (sbytes == 0) {
|
||||
w.sendfile_err = error.WouldBlock;
|
||||
},
|
||||
.IO => w.sendfile_err = error.InputOutput,
|
||||
.PIPE => w.sendfile_err = error.BrokenPipe,
|
||||
.NOBUFS => w.sendfile_err = error.SystemResources,
|
||||
else => |err| w.sendfile_err = posix.unexpectedErrno(err),
|
||||
}
|
||||
if (sbytes == 0) {
|
||||
file_reader.size = file_reader.pos;
|
||||
return error.EndOfStream;
|
||||
}
|
||||
const consumed = io_w.consume(@intCast(sbytes));
|
||||
file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
if (native_os.isDarwin() and w.mode == .streaming) sf: {
|
||||
// Try using sendfile on macOS.
|
||||
if (w.sendfile_err != null) break :sf;
|
||||
const offset = std.math.cast(std.c.off_t, file_reader.pos) orelse break :sf;
|
||||
var hdtr_data: std.c.sf_hdtr = undefined;
|
||||
var headers: [2]posix.iovec_const = undefined;
|
||||
var headers_i: u8 = 0;
|
||||
if (writer_buffered.len != 0) {
|
||||
headers[headers_i] = .{ .base = writer_buffered.ptr, .len = writer_buffered.len };
|
||||
headers_i += 1;
|
||||
}
|
||||
if (reader_buffered.len != 0) {
|
||||
headers[headers_i] = .{ .base = reader_buffered.ptr, .len = reader_buffered.len };
|
||||
headers_i += 1;
|
||||
}
|
||||
const hdtr: ?*std.c.sf_hdtr = if (headers_i == 0) null else b: {
|
||||
hdtr_data = .{
|
||||
.headers = &headers,
|
||||
.hdr_cnt = headers_i,
|
||||
.trailers = null,
|
||||
.trl_cnt = 0,
|
||||
};
|
||||
break :b &hdtr_data;
|
||||
};
|
||||
const max_count = maxInt(i32); // Avoid EINVAL.
|
||||
var len: std.c.off_t = @min(file_limit, max_count);
|
||||
const flags = 0;
|
||||
switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, &len, hdtr, flags))) {
|
||||
.SUCCESS, .INTR => {},
|
||||
.OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation,
|
||||
.BADF => if (builtin.mode == .Debug) @panic("race condition") else {
|
||||
w.sendfile_err = error.Unexpected;
|
||||
},
|
||||
.FAULT => if (builtin.mode == .Debug) @panic("segmentation fault") else {
|
||||
w.sendfile_err = error.Unexpected;
|
||||
},
|
||||
.INVAL => if (builtin.mode == .Debug) @panic("invalid API usage") else {
|
||||
w.sendfile_err = error.Unexpected;
|
||||
},
|
||||
.NOTCONN => w.sendfile_err = error.BrokenPipe,
|
||||
.AGAIN => if (len == 0) {
|
||||
w.sendfile_err = error.WouldBlock;
|
||||
},
|
||||
.IO => w.sendfile_err = error.InputOutput,
|
||||
.PIPE => w.sendfile_err = error.BrokenPipe,
|
||||
else => |err| w.sendfile_err = posix.unexpectedErrno(err),
|
||||
}
|
||||
if (len == 0) {
|
||||
file_reader.size = file_reader.pos;
|
||||
return error.EndOfStream;
|
||||
}
|
||||
const consumed = io_w.consume(@bitCast(len));
|
||||
file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
if (native_os == .linux and w.mode == .streaming) sf: {
|
||||
// Try using sendfile on Linux.
|
||||
if (w.sendfile_err != null) break :sf;
|
||||
// Linux sendfile does not support headers.
|
||||
const buffered = limit.slice(file_reader.interface.buffer);
|
||||
if (io_w.end != 0 or buffered.len != 0) return drain(io_w, &.{buffered}, 1);
|
||||
if (writer_buffered.len != 0 or reader_buffered.len != 0)
|
||||
return sendFileBuffered(io_w, file_reader, reader_buffered);
|
||||
const max_count = 0x7ffff000; // Avoid EINVAL.
|
||||
var off: std.os.linux.off_t = undefined;
|
||||
const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) {
|
||||
@ -1551,6 +1689,7 @@ pub const Writer = struct {
|
||||
w.pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
const copy_file_range = switch (native_os) {
|
||||
.freebsd => std.os.freebsd.copy_file_range,
|
||||
.linux => if (std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })) std.os.linux.wrapped.copy_file_range else {},
|
||||
@ -1558,8 +1697,8 @@ pub const Writer = struct {
|
||||
};
|
||||
if (@TypeOf(copy_file_range) != void) cfr: {
|
||||
if (w.copy_file_range_err != null) break :cfr;
|
||||
const buffered = limit.slice(file_reader.interface.buffer);
|
||||
if (io_w.end != 0 or buffered.len != 0) return drain(io_w, &.{buffered}, 1);
|
||||
if (writer_buffered.len != 0 or reader_buffered.len != 0)
|
||||
return sendFileBuffered(io_w, file_reader, reader_buffered);
|
||||
var off_in: i64 = undefined;
|
||||
var off_out: i64 = undefined;
|
||||
const off_in_ptr: ?*i64 = switch (file_reader.mode) {
|
||||
@ -1598,6 +1737,9 @@ pub const Writer = struct {
|
||||
if (file_reader.pos != 0) break :fcf;
|
||||
if (w.pos != 0) break :fcf;
|
||||
if (limit != .unlimited) break :fcf;
|
||||
const size = file_reader.getSize() catch break :fcf;
|
||||
if (writer_buffered.len != 0 or reader_buffered.len != 0)
|
||||
return sendFileBuffered(io_w, file_reader, reader_buffered);
|
||||
const rc = std.c.fcopyfile(in_fd, out_fd, null, .{ .DATA = true });
|
||||
switch (posix.errno(rc)) {
|
||||
.SUCCESS => {},
|
||||
@ -1618,15 +1760,24 @@ pub const Writer = struct {
|
||||
return 0;
|
||||
},
|
||||
}
|
||||
const n = if (file_reader.size) |size| size else @panic("TODO figure out how much copied");
|
||||
file_reader.pos = n;
|
||||
w.pos = n;
|
||||
return n;
|
||||
file_reader.pos = size;
|
||||
w.pos = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
return error.Unimplemented;
|
||||
}
|
||||
|
||||
fn sendFileBuffered(
|
||||
io_w: *std.io.Writer,
|
||||
file_reader: *Reader,
|
||||
reader_buffered: []const u8,
|
||||
) std.io.Writer.FileError!usize {
|
||||
const n = try drain(io_w, &.{reader_buffered}, 1);
|
||||
file_reader.seekTo(file_reader.pos + n) catch return error.ReadFailed;
|
||||
return n;
|
||||
}
|
||||
|
||||
pub fn seekTo(w: *Writer, offset: u64) SeekError!void {
|
||||
switch (w.mode) {
|
||||
.positional, .positional_reading => {
|
||||
|
||||
@ -1499,32 +1499,18 @@ test "sendfile" {
|
||||
const header2 = "second header\n";
|
||||
const trailer1 = "trailer1\n";
|
||||
const trailer2 = "second trailer\n";
|
||||
var hdtr = [_]posix.iovec_const{
|
||||
.{
|
||||
.base = header1,
|
||||
.len = header1.len,
|
||||
},
|
||||
.{
|
||||
.base = header2,
|
||||
.len = header2.len,
|
||||
},
|
||||
.{
|
||||
.base = trailer1,
|
||||
.len = trailer1.len,
|
||||
},
|
||||
.{
|
||||
.base = trailer2,
|
||||
.len = trailer2.len,
|
||||
},
|
||||
};
|
||||
var headers: [2][]const u8 = .{ header1, header2 };
|
||||
var trailers: [2][]const u8 = .{ trailer1, trailer2 };
|
||||
|
||||
var written_buf: [100]u8 = undefined;
|
||||
try dest_file.writeFileAll(src_file, .{
|
||||
.in_offset = 1,
|
||||
.in_len = 10,
|
||||
.headers_and_trailers = &hdtr,
|
||||
.header_count = 2,
|
||||
});
|
||||
var file_reader = src_file.reader(&.{});
|
||||
var fallback_buffer: [50]u8 = undefined;
|
||||
var file_writer = dest_file.writer(&fallback_buffer);
|
||||
try file_writer.interface.writeVecAll(&headers);
|
||||
try file_reader.seekTo(1);
|
||||
try testing.expectEqual(10, try file_writer.interface.sendFileAll(&file_reader, .limited(10)));
|
||||
try file_writer.interface.writeVecAll(&trailers);
|
||||
try file_writer.interface.flush();
|
||||
const amt = try dest_file.preadAll(&written_buf, 0);
|
||||
try testing.expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]);
|
||||
}
|
||||
@ -1595,9 +1581,10 @@ test "AtomicFile" {
|
||||
;
|
||||
|
||||
{
|
||||
var af = try ctx.dir.atomicFile(test_out_file, .{});
|
||||
var buffer: [100]u8 = undefined;
|
||||
var af = try ctx.dir.atomicFile(test_out_file, .{ .write_buffer = &buffer });
|
||||
defer af.deinit();
|
||||
try af.file.writeAll(test_content);
|
||||
try af.file_writer.interface.writeAll(test_content);
|
||||
try af.finish();
|
||||
}
|
||||
const content = try ctx.dir.readFileAlloc(allocator, test_out_file, 9999);
|
||||
@ -2071,3 +2058,74 @@ test "invalid UTF-8/WTF-8 paths" {
|
||||
}
|
||||
}.impl);
|
||||
}
|
||||
|
||||
test "read file non vectored" {
|
||||
var tmp_dir = testing.tmpDir(.{});
|
||||
defer tmp_dir.cleanup();
|
||||
|
||||
const contents = "hello, world!\n";
|
||||
|
||||
const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true });
|
||||
defer file.close();
|
||||
{
|
||||
var file_writer: std.fs.File.Writer = .init(file, &.{});
|
||||
try file_writer.interface.writeAll(contents);
|
||||
try file_writer.interface.flush();
|
||||
}
|
||||
|
||||
var file_reader: std.fs.File.Reader = .init(file, &.{});
|
||||
|
||||
var write_buffer: [100]u8 = undefined;
|
||||
var w: std.Io.Writer = .fixed(&write_buffer);
|
||||
|
||||
var i: usize = 0;
|
||||
while (true) {
|
||||
i += file_reader.interface.stream(&w, .limited(3)) catch |err| switch (err) {
|
||||
error.EndOfStream => break,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
try testing.expectEqualStrings(contents, w.buffered());
|
||||
try testing.expectEqual(contents.len, i);
|
||||
}
|
||||
|
||||
test "seek keeping partial buffer" {
|
||||
var tmp_dir = testing.tmpDir(.{});
|
||||
defer tmp_dir.cleanup();
|
||||
|
||||
const contents = "0123456789";
|
||||
|
||||
const file = try tmp_dir.dir.createFile("input.txt", .{ .read = true });
|
||||
defer file.close();
|
||||
{
|
||||
var file_writer: std.fs.File.Writer = .init(file, &.{});
|
||||
try file_writer.interface.writeAll(contents);
|
||||
try file_writer.interface.flush();
|
||||
}
|
||||
|
||||
var read_buffer: [3]u8 = undefined;
|
||||
var file_reader: std.fs.File.Reader = .init(file, &read_buffer);
|
||||
|
||||
try testing.expectEqual(0, file_reader.logicalPos());
|
||||
|
||||
var buf: [4]u8 = undefined;
|
||||
try file_reader.interface.readSliceAll(&buf);
|
||||
|
||||
if (file_reader.interface.bufferedLen() != 3) {
|
||||
// Pass the test if the OS doesn't give us vectored reads.
|
||||
return;
|
||||
}
|
||||
|
||||
try testing.expectEqual(4, file_reader.logicalPos());
|
||||
try testing.expectEqual(7, file_reader.pos);
|
||||
try file_reader.seekTo(6);
|
||||
try testing.expectEqual(6, file_reader.logicalPos());
|
||||
try testing.expectEqual(7, file_reader.pos);
|
||||
|
||||
try testing.expectEqualStrings("0123", &buf);
|
||||
|
||||
const n = try file_reader.interface.readSliceShort(&buf);
|
||||
try testing.expectEqual(4, n);
|
||||
|
||||
try testing.expectEqualStrings("6789", &buf);
|
||||
}
|
||||
|
||||
@ -69,7 +69,6 @@ pub const ArrayHashMap = @import("json/hashmap.zig").ArrayHashMap;
|
||||
pub const Scanner = @import("json/Scanner.zig");
|
||||
pub const validate = Scanner.validate;
|
||||
pub const Error = Scanner.Error;
|
||||
pub const reader = Scanner.reader;
|
||||
pub const default_buffer_size = Scanner.default_buffer_size;
|
||||
pub const Token = Scanner.Token;
|
||||
pub const TokenType = Scanner.TokenType;
|
||||
|
||||
@ -6322,288 +6322,6 @@ pub fn send(
|
||||
};
|
||||
}
|
||||
|
||||
pub const SendFileError = PReadError || WriteError || SendError;
|
||||
|
||||
/// Transfer data between file descriptors, with optional headers and trailers.
|
||||
///
|
||||
/// Returns the number of bytes written, which can be zero.
|
||||
///
|
||||
/// The `sendfile` call copies `in_len` bytes from one file descriptor to another. When possible,
|
||||
/// this is done within the operating system kernel, which can provide better performance
|
||||
/// characteristics than transferring data from kernel to user space and back, such as with
|
||||
/// `read` and `write` calls. When `in_len` is `0`, it means to copy until the end of the input file has been
|
||||
/// reached. Note, however, that partial writes are still possible in this case.
|
||||
///
|
||||
/// `in_fd` must be a file descriptor opened for reading, and `out_fd` must be a file descriptor
|
||||
/// opened for writing. They may be any kind of file descriptor; however, if `in_fd` is not a regular
|
||||
/// file system file, it may cause this function to fall back to calling `read` and `write`, in which case
|
||||
/// atomicity guarantees no longer apply.
|
||||
///
|
||||
/// Copying begins reading at `in_offset`. The input file descriptor seek position is ignored and not updated.
|
||||
/// If the output file descriptor has a seek position, it is updated as bytes are written. When
|
||||
/// `in_offset` is past the end of the input file, it successfully reads 0 bytes.
|
||||
///
|
||||
/// `flags` has different meanings per operating system; refer to the respective man pages.
|
||||
///
|
||||
/// These systems support atomically sending everything, including headers and trailers:
|
||||
/// * macOS
|
||||
/// * FreeBSD
|
||||
///
|
||||
/// These systems support in-kernel data copying, but headers and trailers are not sent atomically:
|
||||
/// * Linux
|
||||
///
|
||||
/// Other systems fall back to calling `read` / `write`.
|
||||
///
|
||||
/// Linux has a limit on how many bytes may be transferred in one `sendfile` call, which is `0x7ffff000`
|
||||
/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
|
||||
/// well as stuffing the errno codes into the last `4096` values. This is noted on the `sendfile` man page.
|
||||
/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL.
|
||||
/// The corresponding POSIX limit on this is `maxInt(isize)`.
|
||||
pub fn sendfile(
|
||||
out_fd: fd_t,
|
||||
in_fd: fd_t,
|
||||
in_offset: u64,
|
||||
in_len: u64,
|
||||
headers: []const iovec_const,
|
||||
trailers: []const iovec_const,
|
||||
flags: u32,
|
||||
) SendFileError!usize {
|
||||
var header_done = false;
|
||||
var total_written: usize = 0;
|
||||
|
||||
// Prevents EOVERFLOW.
|
||||
const size_t = std.meta.Int(.unsigned, @typeInfo(usize).int.bits - 1);
|
||||
const max_count = switch (native_os) {
|
||||
.linux => 0x7ffff000,
|
||||
.macos, .ios, .watchos, .tvos, .visionos => maxInt(i32),
|
||||
else => maxInt(size_t),
|
||||
};
|
||||
|
||||
switch (native_os) {
|
||||
.linux => sf: {
|
||||
if (headers.len != 0) {
|
||||
const amt = try writev(out_fd, headers);
|
||||
total_written += amt;
|
||||
if (amt < count_iovec_bytes(headers)) return total_written;
|
||||
header_done = true;
|
||||
}
|
||||
|
||||
// Here we match BSD behavior, making a zero count value send as many bytes as possible.
|
||||
const adjusted_count = if (in_len == 0) max_count else @min(in_len, max_count);
|
||||
|
||||
const sendfile_sym = if (lfs64_abi) system.sendfile64 else system.sendfile;
|
||||
while (true) {
|
||||
var offset: off_t = @bitCast(in_offset);
|
||||
const rc = sendfile_sym(out_fd, in_fd, &offset, adjusted_count);
|
||||
switch (errno(rc)) {
|
||||
.SUCCESS => {
|
||||
const amt: usize = @bitCast(rc);
|
||||
total_written += amt;
|
||||
return total_written;
|
||||
},
|
||||
|
||||
.BADF => unreachable, // Always a race condition.
|
||||
.FAULT => unreachable, // Segmentation fault.
|
||||
.OVERFLOW => unreachable, // We avoid passing too large of a `count`.
|
||||
.NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
|
||||
|
||||
.INVAL => {
|
||||
// EINVAL could be any of the following situations:
|
||||
// * Descriptor is not valid or locked
|
||||
// * an mmap(2)-like operation is not available for in_fd
|
||||
// * count is negative
|
||||
// * out_fd has the APPEND flag set
|
||||
// Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write
|
||||
// manually.
|
||||
break :sf;
|
||||
},
|
||||
.AGAIN => return error.WouldBlock,
|
||||
.IO => return error.InputOutput,
|
||||
.PIPE => return error.BrokenPipe,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NXIO => return error.Unseekable,
|
||||
.SPIPE => return error.Unseekable,
|
||||
else => |err| {
|
||||
unexpectedErrno(err) catch {};
|
||||
break :sf;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (trailers.len != 0) {
|
||||
total_written += try writev(out_fd, trailers);
|
||||
}
|
||||
|
||||
return total_written;
|
||||
},
|
||||
.freebsd => sf: {
|
||||
var hdtr_data: std.c.sf_hdtr = undefined;
|
||||
var hdtr: ?*std.c.sf_hdtr = null;
|
||||
if (headers.len != 0 or trailers.len != 0) {
|
||||
// Here we carefully avoid `@intCast` by returning partial writes when
|
||||
// too many io vectors are provided.
|
||||
const hdr_cnt = cast(u31, headers.len) orelse maxInt(u31);
|
||||
if (headers.len > hdr_cnt) return writev(out_fd, headers);
|
||||
|
||||
const trl_cnt = cast(u31, trailers.len) orelse maxInt(u31);
|
||||
|
||||
hdtr_data = std.c.sf_hdtr{
|
||||
.headers = headers.ptr,
|
||||
.hdr_cnt = hdr_cnt,
|
||||
.trailers = trailers.ptr,
|
||||
.trl_cnt = trl_cnt,
|
||||
};
|
||||
hdtr = &hdtr_data;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var sbytes: off_t = undefined;
|
||||
const err = errno(system.sendfile(in_fd, out_fd, @bitCast(in_offset), @min(in_len, max_count), hdtr, &sbytes, flags));
|
||||
const amt: usize = @bitCast(sbytes);
|
||||
switch (err) {
|
||||
.SUCCESS => return amt,
|
||||
|
||||
.BADF => unreachable, // Always a race condition.
|
||||
.FAULT => unreachable, // Segmentation fault.
|
||||
.NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
|
||||
|
||||
.INVAL, .OPNOTSUPP, .NOTSOCK, .NOSYS => {
|
||||
// EINVAL could be any of the following situations:
|
||||
// * The fd argument is not a regular file.
|
||||
// * The s argument is not a SOCK.STREAM type socket.
|
||||
// * The offset argument is negative.
|
||||
// Because of some of these possibilities, we fall back to doing read/write
|
||||
// manually, the same as ENOSYS.
|
||||
break :sf;
|
||||
},
|
||||
|
||||
.INTR => if (amt != 0) return amt else continue,
|
||||
|
||||
.AGAIN => if (amt != 0) {
|
||||
return amt;
|
||||
} else {
|
||||
return error.WouldBlock;
|
||||
},
|
||||
|
||||
.BUSY => if (amt != 0) {
|
||||
return amt;
|
||||
} else {
|
||||
return error.WouldBlock;
|
||||
},
|
||||
|
||||
.IO => return error.InputOutput,
|
||||
.NOBUFS => return error.SystemResources,
|
||||
.PIPE => return error.BrokenPipe,
|
||||
|
||||
else => {
|
||||
unexpectedErrno(err) catch {};
|
||||
if (amt != 0) {
|
||||
return amt;
|
||||
} else {
|
||||
break :sf;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
.macos, .ios, .tvos, .watchos, .visionos => sf: {
|
||||
var hdtr_data: std.c.sf_hdtr = undefined;
|
||||
var hdtr: ?*std.c.sf_hdtr = null;
|
||||
if (headers.len != 0 or trailers.len != 0) {
|
||||
// Here we carefully avoid `@intCast` by returning partial writes when
|
||||
// too many io vectors are provided.
|
||||
const hdr_cnt = cast(u31, headers.len) orelse maxInt(u31);
|
||||
if (headers.len > hdr_cnt) return writev(out_fd, headers);
|
||||
|
||||
const trl_cnt = cast(u31, trailers.len) orelse maxInt(u31);
|
||||
|
||||
hdtr_data = std.c.sf_hdtr{
|
||||
.headers = headers.ptr,
|
||||
.hdr_cnt = hdr_cnt,
|
||||
.trailers = trailers.ptr,
|
||||
.trl_cnt = trl_cnt,
|
||||
};
|
||||
hdtr = &hdtr_data;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var sbytes: off_t = @min(in_len, max_count);
|
||||
const err = errno(system.sendfile(in_fd, out_fd, @bitCast(in_offset), &sbytes, hdtr, flags));
|
||||
const amt: usize = @bitCast(sbytes);
|
||||
switch (err) {
|
||||
.SUCCESS => return amt,
|
||||
|
||||
.BADF => unreachable, // Always a race condition.
|
||||
.FAULT => unreachable, // Segmentation fault.
|
||||
.INVAL => unreachable,
|
||||
.NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
|
||||
|
||||
.OPNOTSUPP, .NOTSOCK, .NOSYS => break :sf,
|
||||
|
||||
.INTR => if (amt != 0) return amt else continue,
|
||||
|
||||
.AGAIN => if (amt != 0) {
|
||||
return amt;
|
||||
} else {
|
||||
return error.WouldBlock;
|
||||
},
|
||||
|
||||
.IO => return error.InputOutput,
|
||||
.PIPE => return error.BrokenPipe,
|
||||
|
||||
else => {
|
||||
unexpectedErrno(err) catch {};
|
||||
if (amt != 0) {
|
||||
return amt;
|
||||
} else {
|
||||
break :sf;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {}, // fall back to read/write
|
||||
}
|
||||
|
||||
if (headers.len != 0 and !header_done) {
|
||||
const amt = try writev(out_fd, headers);
|
||||
total_written += amt;
|
||||
if (amt < count_iovec_bytes(headers)) return total_written;
|
||||
}
|
||||
|
||||
rw: {
|
||||
var buf: [8 * 4096]u8 = undefined;
|
||||
// Here we match BSD behavior, making a zero count value send as many bytes as possible.
|
||||
const adjusted_count = if (in_len == 0) buf.len else @min(buf.len, in_len);
|
||||
const amt_read = try pread(in_fd, buf[0..adjusted_count], in_offset);
|
||||
if (amt_read == 0) {
|
||||
if (in_len == 0) {
|
||||
// We have detected EOF from `in_fd`.
|
||||
break :rw;
|
||||
} else {
|
||||
return total_written;
|
||||
}
|
||||
}
|
||||
const amt_written = try write(out_fd, buf[0..amt_read]);
|
||||
total_written += amt_written;
|
||||
if (amt_written < in_len or in_len == 0) return total_written;
|
||||
}
|
||||
|
||||
if (trailers.len != 0) {
|
||||
total_written += try writev(out_fd, trailers);
|
||||
}
|
||||
|
||||
return total_written;
|
||||
}
|
||||
|
||||
fn count_iovec_bytes(iovs: []const iovec_const) usize {
|
||||
var count: usize = 0;
|
||||
for (iovs) |iov| {
|
||||
count += iov.len;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
pub const PollError = error{
|
||||
/// The network subsystem has failed.
|
||||
NetworkSubsystemFailed,
|
||||
|
||||
@ -342,9 +342,9 @@ pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
// `make_path` matters because the dir hasn't actually been created yet.
|
||||
var af = try root_dir.atomicFile(sub_path, .{ .make_path = true });
|
||||
var af = try root_dir.atomicFile(sub_path, .{ .make_path = true, .write_buffer = &.{} });
|
||||
defer af.deinit();
|
||||
try af.file.writeAll(file.source.?);
|
||||
try af.file_writer.interface.writeAll(file.source.?);
|
||||
af.finish() catch |err| switch (err) {
|
||||
error.AccessDenied => switch (builtin.os.tag) {
|
||||
.windows => {
|
||||
|
||||
@ -3382,7 +3382,7 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
|
||||
const gpa = comp.gpa;
|
||||
|
||||
var bufs = std.ArrayList(std.posix.iovec_const).init(gpa);
|
||||
var bufs = std.ArrayList([]const u8).init(gpa);
|
||||
defer bufs.deinit();
|
||||
|
||||
var pt_headers = std.ArrayList(Header.PerThread).init(gpa);
|
||||
@ -3421,50 +3421,50 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
|
||||
try bufs.ensureTotalCapacityPrecise(14 + 8 * pt_headers.items.len);
|
||||
addBuf(&bufs, mem.asBytes(&header));
|
||||
addBuf(&bufs, mem.sliceAsBytes(pt_headers.items));
|
||||
addBuf(&bufs, @ptrCast(pt_headers.items));
|
||||
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.src_hash_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.src_hash_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.nav_val_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.nav_val_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.nav_ty_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.interned_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.interned_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.zon_file_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.embed_file_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.embed_file_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.namespace_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.namespace_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.namespace_name_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.namespace_name_deps.values()));
|
||||
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.first_dependency.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.first_dependency.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.dep_entries.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items));
|
||||
addBuf(&bufs, @ptrCast(ip.first_dependency.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.first_dependency.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.dep_entries.items));
|
||||
addBuf(&bufs, @ptrCast(ip.free_dep_entries.items));
|
||||
|
||||
for (ip.locals, pt_headers.items) |*local, pt_header| {
|
||||
if (pt_header.intern_pool.limbs_len > 0) {
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));
|
||||
}
|
||||
if (pt_header.intern_pool.extra_len > 0) {
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));
|
||||
}
|
||||
if (pt_header.intern_pool.items_len > 0) {
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));
|
||||
}
|
||||
if (pt_header.intern_pool.string_bytes_len > 0) {
|
||||
addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);
|
||||
}
|
||||
if (pt_header.intern_pool.tracked_insts_len > 0) {
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));
|
||||
}
|
||||
if (pt_header.intern_pool.files_len > 0) {
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));
|
||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));
|
||||
addBuf(&bufs, @ptrCast(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3482,95 +3482,95 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
try bufs.ensureUnusedCapacity(85);
|
||||
addBuf(&bufs, wasm.string_bytes.items);
|
||||
// TODO make it well-defined memory layout
|
||||
//addBuf(&bufs, mem.sliceAsBytes(wasm.objects.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.func_types.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_function_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_function_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_functions.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_global_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_global_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_globals.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_table_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_table_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_tables.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_memory_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_memory_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_memories.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.tag)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.offset)));
|
||||
//addBuf(&bufs, @ptrCast(wasm.objects.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.func_types.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_function_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_function_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_functions.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_global_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_global_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_globals.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_table_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_table_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_tables.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_memory_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_memory_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_memories.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.tag)));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.offset)));
|
||||
// TODO handle the union safety field
|
||||
//addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.pointee)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations.items(.addend)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_init_funcs.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_segments.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_datas.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_data_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_custom_segments.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_custom_segments.values()));
|
||||
//addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.pointee)));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_relocations.items(.addend)));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_init_funcs.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_data_segments.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_datas.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_data_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_data_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_custom_segments.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_custom_segments.values()));
|
||||
// TODO make it well-defined memory layout
|
||||
// addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdats.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations_table.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_relocations_table.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdat_symbols.items(.kind)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_comdat_symbols.items(.index)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.tag)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.offset)));
|
||||
// addBuf(&bufs, @ptrCast(wasm.object_comdats.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_relocations_table.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind)));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index)));
|
||||
addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag)));
|
||||
addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset)));
|
||||
// TODO handle the union safety field
|
||||
//addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.pointee)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.out_relocs.items(.addend)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uav_fixups.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.nav_fixups.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.func_table_fixups.items));
|
||||
//addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee)));
|
||||
addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend)));
|
||||
addBuf(&bufs, @ptrCast(wasm.uav_fixups.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.nav_fixups.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items));
|
||||
if (is_obj) {
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.navs_obj.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.navs_obj.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_obj.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_obj.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.navs_obj.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.navs_obj.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.uavs_obj.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.uavs_obj.values()));
|
||||
} else {
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.navs_exe.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.navs_exe.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_exe.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uavs_exe.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.navs_exe.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.navs_exe.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.uavs_exe.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.uavs_exe.values()));
|
||||
}
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.overaligned_uavs.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.overaligned_uavs.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_funcs.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.overaligned_uavs.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.overaligned_uavs.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.zcu_funcs.keys()));
|
||||
// TODO handle the union safety field
|
||||
// addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_funcs.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.nav_exports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.nav_exports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uav_exports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.uav_exports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.missing_exports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.function_exports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.hidden_function_exports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.global_exports.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.functions.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.function_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.data_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.data_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.data_segments.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.globals.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.global_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.global_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.tables.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.table_imports.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.table_imports.values()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.zcu_indirect_function_set.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_indirect_function_import_set.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.object_indirect_function_set.keys()));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.tag)));
|
||||
// addBuf(&bufs, @ptrCast(wasm.zcu_funcs.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.nav_exports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.nav_exports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.uav_exports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.uav_exports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.missing_exports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.function_exports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.function_exports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.hidden_function_exports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.hidden_function_exports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.global_exports.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.functions.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.function_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.function_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.data_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.data_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.data_segments.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.globals.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.global_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.global_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.tables.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.table_imports.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.table_imports.values()));
|
||||
addBuf(&bufs, @ptrCast(wasm.zcu_indirect_function_set.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_indirect_function_import_set.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.object_indirect_function_set.keys()));
|
||||
addBuf(&bufs, @ptrCast(wasm.mir_instructions.items(.tag)));
|
||||
// TODO handle the union safety field
|
||||
//addBuf(&bufs, mem.sliceAsBytes(wasm.mir_instructions.items(.data)));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.mir_extra.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.mir_locals.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_bytes.items));
|
||||
addBuf(&bufs, mem.sliceAsBytes(wasm.tag_name_offs.items));
|
||||
//addBuf(&bufs, @ptrCast(wasm.mir_instructions.items(.data)));
|
||||
addBuf(&bufs, @ptrCast(wasm.mir_extra.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.mir_locals.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.tag_name_bytes.items));
|
||||
addBuf(&bufs, @ptrCast(wasm.tag_name_offs.items));
|
||||
|
||||
// TODO add as header fields
|
||||
// entry_resolution: FunctionImport.Resolution
|
||||
@ -3596,16 +3596,16 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
|
||||
// Using an atomic file prevents a crash or power failure from corrupting
|
||||
// the previous incremental compilation state.
|
||||
var af = try lf.emit.root_dir.handle.atomicFile(basename, .{});
|
||||
var write_buffer: [1024]u8 = undefined;
|
||||
var af = try lf.emit.root_dir.handle.atomicFile(basename, .{ .write_buffer = &write_buffer });
|
||||
defer af.deinit();
|
||||
try af.file.pwritevAll(bufs.items, 0);
|
||||
try af.file_writer.interface.writeVecAll(bufs.items);
|
||||
try af.finish();
|
||||
}
|
||||
|
||||
fn addBuf(list: *std.ArrayList(std.posix.iovec_const), buf: []const u8) void {
|
||||
// Even when len=0, the undefined pointer might cause EFAULT.
|
||||
fn addBuf(list: *std.ArrayList([]const u8), buf: []const u8) void {
|
||||
if (buf.len == 0) return;
|
||||
list.appendAssumeCapacity(.{ .base = buf.ptr, .len = buf.len });
|
||||
list.appendAssumeCapacity(buf);
|
||||
}
|
||||
|
||||
/// This function is temporally single-threaded.
|
||||
|
||||
39
src/Sema.zig
39
src/Sema.zig
@ -5000,9 +5000,11 @@ fn validateUnionInit(
|
||||
}
|
||||
if (init_ref) |v| try sema.validateRuntimeValue(block, block.nodeOffset(field_ptr_data.src_node), v);
|
||||
|
||||
const new_tag = Air.internedToRef(tag_val.toIntern());
|
||||
const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, new_tag);
|
||||
try sema.checkComptimeKnownStore(block, set_tag_inst, LazySrcLoc.unneeded); // `unneeded` since this isn't a "proper" store
|
||||
if ((try sema.typeHasOnePossibleValue(tag_ty)) == null) {
|
||||
const new_tag = Air.internedToRef(tag_val.toIntern());
|
||||
const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, new_tag);
|
||||
try sema.checkComptimeKnownStore(block, set_tag_inst, LazySrcLoc.unneeded); // `unneeded` since this isn't a "proper" store
|
||||
}
|
||||
}
|
||||
|
||||
fn validateStructInit(
|
||||
@ -6560,6 +6562,11 @@ fn resolveAnalyzedBlock(
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(resolved_ty)) |block_only_value| {
|
||||
return Air.internedToRef(block_only_value.toIntern());
|
||||
}
|
||||
|
||||
return merges.block_inst.toRef();
|
||||
}
|
||||
|
||||
@ -9056,6 +9063,10 @@ fn analyzeErrUnionPayload(
|
||||
try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
|
||||
}
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(payload_ty)) |payload_only_value| {
|
||||
return Air.internedToRef(payload_only_value.toIntern());
|
||||
}
|
||||
|
||||
return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand);
|
||||
}
|
||||
|
||||
@ -19690,8 +19701,10 @@ fn zirStructInit(
|
||||
const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);
|
||||
const field_ptr = try sema.unionFieldPtr(block, field_src, base_ptr, field_name, field_src, resolved_ty, true);
|
||||
try sema.storePtr(block, src, field_ptr, init_inst);
|
||||
const new_tag = Air.internedToRef(tag_val.toIntern());
|
||||
_ = try block.addBinOp(.set_union_tag, base_ptr, new_tag);
|
||||
if ((try sema.typeHasOnePossibleValue(tag_ty)) == null) {
|
||||
const new_tag = Air.internedToRef(tag_val.toIntern());
|
||||
_ = try block.addBinOp(.set_union_tag, base_ptr, new_tag);
|
||||
}
|
||||
return sema.makePtrConst(block, alloc);
|
||||
}
|
||||
|
||||
@ -28079,10 +28092,16 @@ fn unionFieldVal(
|
||||
const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_ty), union_byval);
|
||||
try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag);
|
||||
}
|
||||
|
||||
if (field_ty.zigTypeTag(zcu) == .noreturn) {
|
||||
_ = try block.addNoOp(.unreach);
|
||||
return .unreachable_value;
|
||||
}
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(field_ty)) |field_only_value| {
|
||||
return Air.internedToRef(field_only_value.toIntern());
|
||||
}
|
||||
|
||||
try field_ty.resolveLayout(pt);
|
||||
return block.addStructFieldVal(union_byval, field_index, field_ty);
|
||||
}
|
||||
@ -28214,12 +28233,12 @@ fn elemVal(
|
||||
.many, .c => {
|
||||
const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
|
||||
const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
|
||||
const elem_ty = indexable_ty.elemType2(zcu);
|
||||
|
||||
ct: {
|
||||
const indexable_val = maybe_indexable_val orelse break :ct;
|
||||
const index_val = maybe_index_val orelse break :ct;
|
||||
const index: usize = @intCast(try index_val.toUnsignedIntSema(pt));
|
||||
const elem_ty = indexable_ty.elemType2(zcu);
|
||||
const many_ptr_ty = try pt.manyConstPtrType(elem_ty);
|
||||
const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty);
|
||||
const elem_ptr_ty = try pt.singleConstPtrType(elem_ty);
|
||||
@ -28228,6 +28247,10 @@ fn elemVal(
|
||||
return Air.internedToRef((try pt.getCoerced(elem_val, elem_ty)).toIntern());
|
||||
}
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| {
|
||||
return Air.internedToRef(elem_only_value.toIntern());
|
||||
}
|
||||
|
||||
try sema.checkLogicalPtrOperation(block, src, indexable_ty);
|
||||
return block.addBinOp(.ptr_elem_val, indexable, elem_index);
|
||||
},
|
||||
@ -28578,6 +28601,10 @@ fn elemValSlice(
|
||||
}
|
||||
}
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| {
|
||||
return Air.internedToRef(elem_only_value.toIntern());
|
||||
}
|
||||
|
||||
try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src);
|
||||
try sema.validateRuntimeValue(block, slice_src, slice);
|
||||
|
||||
|
||||
@ -349,10 +349,10 @@ fn fmtPathFile(
|
||||
try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
|
||||
fmt.any_error = true;
|
||||
} else {
|
||||
var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });
|
||||
var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode, .write_buffer = &.{} });
|
||||
defer af.deinit();
|
||||
|
||||
try af.file.writeAll(fmt.out_buffer.getWritten());
|
||||
try af.file_writer.interface.writeAll(fmt.out_buffer.getWritten());
|
||||
try af.finish();
|
||||
try fmt.stdout_writer.interface.print("{s}\n", .{file_path});
|
||||
}
|
||||
|
||||
@ -613,7 +613,6 @@ pub fn flush(
|
||||
};
|
||||
const emit = self.base.emit;
|
||||
invalidateKernelCache(emit.root_dir.handle, emit.sub_path) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => |e| return diags.fail("failed to invalidate kernel cache: {s}", .{@errorName(e)}),
|
||||
};
|
||||
}
|
||||
|
||||
@ -4624,7 +4624,9 @@ fn cmdTranslateC(
|
||||
fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });
|
||||
};
|
||||
defer zig_file.close();
|
||||
try fs.File.stdout().writeFileAll(zig_file, .{});
|
||||
var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
|
||||
var file_reader = zig_file.reader(&.{});
|
||||
_ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited);
|
||||
return cleanExit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
#target=x86_64-linux-selfhosted
|
||||
#target=x86_64-linux-cbe
|
||||
#target=x86_64-windows-cbe
|
||||
#update=initial version
|
||||
#file=main.zig
|
||||
pub fn main() !void {}
|
||||
comptime { @compileError("c0"); }
|
||||
comptime { @compileError("c1"); }
|
||||
comptime { @compileError("c2"); }
|
||||
comptime { @compileError("c3"); }
|
||||
comptime { @compileError("c4"); }
|
||||
comptime { @compileError("c5"); }
|
||||
comptime { @compileError("c6"); }
|
||||
comptime { @compileError("c7"); }
|
||||
comptime { @compileError("c8"); }
|
||||
comptime { @compileError("c9"); }
|
||||
export fn f0() void { @compileError("f0"); }
|
||||
export fn f1() void { @compileError("f1"); }
|
||||
export fn f2() void { @compileError("f2"); }
|
||||
export fn f3() void { @compileError("f3"); }
|
||||
export fn f4() void { @compileError("f4"); }
|
||||
export fn f5() void { @compileError("f5"); }
|
||||
export fn f6() void { @compileError("f6"); }
|
||||
export fn f7() void { @compileError("f7"); }
|
||||
export fn f8() void { @compileError("f8"); }
|
||||
export fn f9() void { @compileError("f9"); }
|
||||
#expect_error=main.zig:2:12: error: c0
|
||||
#expect_error=main.zig:3:12: error: c1
|
||||
#expect_error=main.zig:4:12: error: c2
|
||||
#expect_error=main.zig:5:12: error: c3
|
||||
#expect_error=main.zig:6:12: error: c4
|
||||
#expect_error=main.zig:7:12: error: c5
|
||||
#expect_error=main.zig:8:12: error: c6
|
||||
#expect_error=main.zig:9:12: error: c7
|
||||
#expect_error=main.zig:10:12: error: c8
|
||||
#expect_error=main.zig:11:12: error: c9
|
||||
#expect_error=main.zig:12:23: error: f0
|
||||
#expect_error=main.zig:13:23: error: f1
|
||||
#expect_error=main.zig:14:23: error: f2
|
||||
#expect_error=main.zig:15:23: error: f3
|
||||
#expect_error=main.zig:16:23: error: f4
|
||||
#expect_error=main.zig:17:23: error: f5
|
||||
#expect_error=main.zig:18:23: error: f6
|
||||
#expect_error=main.zig:19:23: error: f7
|
||||
#expect_error=main.zig:20:23: error: f8
|
||||
#expect_error=main.zig:21:23: error: f9
|
||||
#update=fix all the errors
|
||||
#file=main.zig
|
||||
pub fn main() !void {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
comptime {}
|
||||
export fn f0() void {}
|
||||
export fn f1() void {}
|
||||
export fn f2() void {}
|
||||
export fn f3() void {}
|
||||
export fn f4() void {}
|
||||
export fn f5() void {}
|
||||
export fn f6() void {}
|
||||
export fn f7() void {}
|
||||
export fn f8() void {}
|
||||
export fn f9() void {}
|
||||
const std = @import("std");
|
||||
#expect_stdout=""
|
||||
@ -65,69 +65,70 @@ pub fn build(b: *std.Build) void {
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
// Unwinding through a C shared library without a frame pointer (libc)
|
||||
//
|
||||
// getcontext version: libc
|
||||
//
|
||||
// Unwind info type:
|
||||
// - ELF: DWARF .eh_frame + .debug_frame
|
||||
// - MachO: __unwind_info encodings:
|
||||
// - x86_64: STACK_IMMD, STACK_IND
|
||||
// - aarch64: FRAMELESS, DWARF
|
||||
{
|
||||
const c_shared_lib = b.addLibrary(.{
|
||||
.linkage = .dynamic,
|
||||
.name = "c_shared_lib",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = null,
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
.strip = false,
|
||||
}),
|
||||
});
|
||||
// https://github.com/ziglang/zig/issues/24522
|
||||
//// Unwinding through a C shared library without a frame pointer (libc)
|
||||
////
|
||||
//// getcontext version: libc
|
||||
////
|
||||
//// Unwind info type:
|
||||
//// - ELF: DWARF .eh_frame + .debug_frame
|
||||
//// - MachO: __unwind_info encodings:
|
||||
//// - x86_64: STACK_IMMD, STACK_IND
|
||||
//// - aarch64: FRAMELESS, DWARF
|
||||
//{
|
||||
// const c_shared_lib = b.addLibrary(.{
|
||||
// .linkage = .dynamic,
|
||||
// .name = "c_shared_lib",
|
||||
// .root_module = b.createModule(.{
|
||||
// .root_source_file = null,
|
||||
// .target = target,
|
||||
// .optimize = optimize,
|
||||
// .link_libc = true,
|
||||
// .strip = false,
|
||||
// }),
|
||||
// });
|
||||
|
||||
if (target.result.os.tag == .windows)
|
||||
c_shared_lib.root_module.addCMacro("LIB_API", "__declspec(dllexport)");
|
||||
// if (target.result.os.tag == .windows)
|
||||
// c_shared_lib.root_module.addCMacro("LIB_API", "__declspec(dllexport)");
|
||||
|
||||
c_shared_lib.root_module.addCSourceFile(.{
|
||||
.file = b.path("shared_lib.c"),
|
||||
.flags = &.{"-fomit-frame-pointer"},
|
||||
});
|
||||
// c_shared_lib.root_module.addCSourceFile(.{
|
||||
// .file = b.path("shared_lib.c"),
|
||||
// .flags = &.{"-fomit-frame-pointer"},
|
||||
// });
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "shared_lib_unwind",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("shared_lib_unwind.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.unwind_tables = if (target.result.os.tag.isDarwin()) .async else null,
|
||||
.omit_frame_pointer = true,
|
||||
}),
|
||||
// zig objcopy doesn't support incremental binaries
|
||||
.use_llvm = true,
|
||||
});
|
||||
// const exe = b.addExecutable(.{
|
||||
// .name = "shared_lib_unwind",
|
||||
// .root_module = b.createModule(.{
|
||||
// .root_source_file = b.path("shared_lib_unwind.zig"),
|
||||
// .target = target,
|
||||
// .optimize = optimize,
|
||||
// .unwind_tables = if (target.result.os.tag.isDarwin()) .async else null,
|
||||
// .omit_frame_pointer = true,
|
||||
// }),
|
||||
// // zig objcopy doesn't support incremental binaries
|
||||
// .use_llvm = true,
|
||||
// });
|
||||
|
||||
exe.linkLibrary(c_shared_lib);
|
||||
// exe.linkLibrary(c_shared_lib);
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
// const run_cmd = b.addRunArtifact(exe);
|
||||
// test_step.dependOn(&run_cmd.step);
|
||||
|
||||
// Separate debug info ELF file
|
||||
if (target.result.ofmt == .elf) {
|
||||
const filename = b.fmt("{s}_stripped", .{exe.out_filename});
|
||||
const stripped_exe = b.addObjCopy(exe.getEmittedBin(), .{
|
||||
.basename = filename, // set the name for the debuglink
|
||||
.compress_debug = true,
|
||||
.strip = .debug,
|
||||
.extract_to_separate_file = true,
|
||||
});
|
||||
// // Separate debug info ELF file
|
||||
// if (target.result.ofmt == .elf) {
|
||||
// const filename = b.fmt("{s}_stripped", .{exe.out_filename});
|
||||
// const stripped_exe = b.addObjCopy(exe.getEmittedBin(), .{
|
||||
// .basename = filename, // set the name for the debuglink
|
||||
// .compress_debug = true,
|
||||
// .strip = .debug,
|
||||
// .extract_to_separate_file = true,
|
||||
// });
|
||||
|
||||
const run_stripped = std.Build.Step.Run.create(b, b.fmt("run {s}", .{filename}));
|
||||
run_stripped.addFileArg(stripped_exe.getOutput());
|
||||
test_step.dependOn(&run_stripped.step);
|
||||
}
|
||||
}
|
||||
// const run_stripped = std.Build.Step.Run.create(b, b.fmt("run {s}", .{filename}));
|
||||
// run_stripped.addFileArg(stripped_exe.getOutput());
|
||||
// test_step.dependOn(&run_stripped.step);
|
||||
// }
|
||||
//}
|
||||
|
||||
// Unwinding without libc/posix
|
||||
//
|
||||
|
||||
@ -310,7 +310,8 @@ pub fn main() !void {
|
||||
build_all_path, libc_so_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
const header = try elf.Header.parse(elf_bytes[0..@sizeOf(elf.Elf64_Ehdr)]);
|
||||
var stream: std.Io.Reader = .fixed(elf_bytes);
|
||||
const header = try elf.Header.read(&stream);
|
||||
|
||||
const parse: Parse = .{
|
||||
.arena = arena,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user