commit 4fcf6507f9f96d1f341819dab89ded74cd3c7f7d (tree)
parent 65092d6e4c33043fcd7025a1e8190dbeac943882
Author: Alex Rønne Petersen <alex@alexrp.com>
Date: Tue, 13 Jan 2026 06:00:24 +0100
Merge pull request 'Fix wasi-libc miscompilations and make `std.Io` compile on Emscripten' (#30796) from castholm/zig:retrim-libc-fat into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30796
Reviewed-by: Alex Rønne Petersen <alex@alexrp.com>
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
Diffstat:
9 files changed, 103 insertions(+), 4 deletions(-)
diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h b/lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h
@@ -0,0 +1,8 @@
+#ifndef ARPA_INET_H
+#define ARPA_INET_H
+
+#include "../../../include/arpa/inet.h"
+
+hidden int __inet_aton(const char *, struct in_addr *);
+
+#endif
diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h b/lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h
@@ -0,0 +1,19 @@
+#ifndef STDLIB_H
+#define STDLIB_H
+
+#include "../../include/stdlib.h"
+
+hidden int __putenv(char *, size_t, char *);
+hidden void __env_rm_add(char *, char *);
+hidden int __mkostemps(char *, int, int);
+hidden int __ptsname_r(int, char *, size_t);
+hidden char *__randname(char *);
+hidden void __qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *);
+
+hidden void *__libc_malloc(size_t);
+hidden void *__libc_malloc_impl(size_t);
+hidden void *__libc_calloc(size_t, size_t);
+hidden void *__libc_realloc(void *, size_t);
+hidden void __libc_free(void *);
+
+#endif
diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/string.h b/lib/libc/wasi/libc-top-half/musl/src/include/string.h
@@ -0,0 +1,11 @@
+#ifndef STRING_H
+#define STRING_H
+
+#include "../../include/string.h"
+
+hidden void *__memrchr(const void *, int, size_t);
+hidden char *__stpcpy(char *, const char *);
+hidden char *__stpncpy(char *, const char *, size_t);
+hidden char *__strchrnul(const char *, int);
+
+#endif
diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h b/lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h
@@ -0,0 +1,20 @@
+#ifndef SYS_MMAN_H
+#define SYS_MMAN_H
+
+#include "../../../include/sys/mman.h"
+
+hidden void __vm_wait(void);
+hidden void __vm_lock(void);
+hidden void __vm_unlock(void);
+
+hidden void *__mmap(void *, size_t, int, int, int, off_t);
+hidden int __munmap(void *, size_t);
+hidden void *__mremap(void *, size_t, size_t, int, ...);
+hidden int __madvise(void *, size_t, int);
+hidden int __mprotect(void *, size_t, int);
+
+hidden const unsigned char *__map_file(const char *, size_t *);
+
+hidden char *__shm_mapname(const char *, char *);
+
+#endif
diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h b/lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h
@@ -0,0 +1,9 @@
+#ifndef SYS_STAT_H
+#define SYS_STAT_H
+
+#include "../../../include/sys/stat.h"
+
+hidden int __fstat(int, struct stat *);
+hidden int __fstatat(int, const char *restrict, struct stat *restrict, int);
+
+#endif
diff --git a/lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h b/lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h
@@ -0,0 +1,8 @@
+#ifndef SYS_TIME_H
+#define SYS_TIME_H
+
+#include "../../../include/sys/time.h"
+
+hidden int __futimesat(int, const char *, const struct timeval [2]);
+
+#endif
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
@@ -2024,6 +2024,7 @@ fn groupConcurrent(
fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) Io.Cancelable!void {
_ = initial_token; // we need to load `token` *after* the group finishes
+ if (builtin.single_threaded) unreachable; // nothing to await
const t: *Threaded = @ptrCast(@alignCast(userdata));
const g: Group = .{ .ptr = type_erased };
@@ -2082,6 +2083,7 @@ fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *any
fn groupCancel(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) void {
_ = initial_token;
+ if (builtin.single_threaded) unreachable; // nothing to cancel
const t: *Threaded = @ptrCast(@alignCast(userdata));
const g: Group = .{ .ptr = type_erased };
@@ -2152,6 +2154,7 @@ fn await(
result_alignment: Alignment,
) void {
_ = result_alignment;
+ if (builtin.single_threaded) unreachable; // nothing to await
const t: *Threaded = @ptrCast(@alignCast(userdata));
const future: *Future = @ptrCast(@alignCast(any_future));
@@ -2218,6 +2221,7 @@ fn cancel(
result_alignment: Alignment,
) void {
_ = result_alignment;
+ if (builtin.single_threaded) unreachable; // nothing to cancel
const t: *Threaded = @ptrCast(@alignCast(userdata));
const future: *Future = @ptrCast(@alignCast(any_future));
@@ -4959,7 +4963,7 @@ fn dirReadUnimplemented(userdata: ?*anyopaque, dir_reader: *Dir.Reader, buffer:
_ = userdata;
_ = dir_reader;
_ = buffer;
- return error.Unimplemented;
+ return error.Unexpected;
}
const dirRealPathFile = switch (native_os) {
@@ -13224,7 +13228,7 @@ fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptio
}
const processSpawn = switch (native_os) {
- .wasi, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported,
+ .wasi, .emscripten, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported,
.windows => processSpawnWindows,
else => processSpawnPosix,
};
diff --git a/lib/std/c.zig b/lib/std/c.zig
@@ -97,6 +97,7 @@ pub const off_t = switch (native_os) {
pub const timespec = switch (native_os) {
.linux => linux.timespec,
.emscripten => emscripten.timespec,
+ // lib/libc/include/wasm-wasi-musl/__struct_timespec.h
.wasi => extern struct {
sec: time_t,
nsec: isize,
@@ -115,16 +116,18 @@ pub const timespec = switch (native_os) {
@as(wasi.timestamp_t, @intCast(ts.nsec));
}
+ // lib/libc/include/wasm-wasi-musl/__header_sys_stat.h
+
/// For use with `utimensat` and `futimens`.
pub const NOW: timespec = .{
.sec = 0,
- .nsec = 0x3fffffff,
+ .nsec = -1,
};
/// For use with `utimensat` and `futimens`.
pub const OMIT: timespec = .{
.sec = 0,
- .nsec = 0x3ffffffe,
+ .nsec = -2,
};
},
// https://github.com/SerenityOS/serenity/blob/0a78056453578c18e0a04a0b45ebfb1c96d59005/Kernel/API/POSIX/time.h#L17-L20
@@ -7007,6 +7010,7 @@ pub const time_t = switch (native_os) {
.linux => linux.time_t,
.emscripten => emscripten.time_t,
.haiku, .dragonfly => isize,
+ // lib/libc/include/wasm-wasi-musl/__typedef_time_t.h
// https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L47
else => i64,
};
diff --git a/lib/std/os/emscripten.zig b/lib/std/os/emscripten.zig
@@ -729,6 +729,7 @@ pub const sockaddr = c.sockaddr;
pub const blksize_t = i32;
pub const nlink_t = u32;
+// https://github.com/emscripten-core/emscripten/blob/946ab574ae39401b51e75cd5257d894ae732ab54/system/lib/libc/musl/arch/emscripten/bits/alltypes.h#L140
pub const time_t = i64;
pub const mode_t = u32;
pub const off_t = i64;
@@ -765,9 +766,24 @@ pub const stack_t = extern struct {
size: usize,
};
+// https://github.com/emscripten-core/emscripten/blob/946ab574ae39401b51e75cd5257d894ae732ab54/system/lib/libc/musl/arch/emscripten/bits/alltypes.h#L284
pub const timespec = extern struct {
sec: time_t,
nsec: isize,
+
+ // https://github.com/emscripten-core/emscripten/blob/d72d7226f4733af8ff993dec70198cf09a24142d/system/lib/libc/musl/include/sys/stat.h#L77-L78
+
+ /// For use with `utimensat` and `futimens`.
+ pub const NOW: timespec = .{
+ .sec = 0,
+ .nsec = 0x3fffffff,
+ };
+
+ /// For use with `utimensat` and `futimens`.
+ pub const OMIT: timespec = .{
+ .sec = 0,
+ .nsec = 0x3ffffffe,
+ };
};
pub const timezone = extern struct {