authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-01-13 06:00:24+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-01-13 06:00:24+01:00
log4fcf6507f9f96d1f341819dab89ded74cd3c7f7d
tree0bd071ef951b988f712f7679d431bf8f4af94c37
parent65092d6e4c33043fcd7025a1e8190dbeac943882
parent0a8e8e67d7e67e8381f2dcdb8e5ede8e42a71649

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>

9 files changed, 103 insertions(+), 4 deletions(-)

lib/libc/wasi/libc-top-half/musl/src/include/arpa/inet.h created+8
...@@ -0,0 +1,8 @@
1#ifndef ARPA_INET_H
2#define ARPA_INET_H
3
4#include "../../../include/arpa/inet.h"
5
6hidden int __inet_aton(const char *, struct in_addr *);
7
8#endif
lib/libc/wasi/libc-top-half/musl/src/include/stdlib.h created+19
...@@ -0,0 +1,19 @@
1#ifndef STDLIB_H
2#define STDLIB_H
3
4#include "../../include/stdlib.h"
5
6hidden int __putenv(char *, size_t, char *);
7hidden void __env_rm_add(char *, char *);
8hidden int __mkostemps(char *, int, int);
9hidden int __ptsname_r(int, char *, size_t);
10hidden char *__randname(char *);
11hidden void __qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *);
12
13hidden void *__libc_malloc(size_t);
14hidden void *__libc_malloc_impl(size_t);
15hidden void *__libc_calloc(size_t, size_t);
16hidden void *__libc_realloc(void *, size_t);
17hidden void __libc_free(void *);
18
19#endif
lib/libc/wasi/libc-top-half/musl/src/include/string.h created+11
...@@ -0,0 +1,11 @@
1#ifndef STRING_H
2#define STRING_H
3
4#include "../../include/string.h"
5
6hidden void *__memrchr(const void *, int, size_t);
7hidden char *__stpcpy(char *, const char *);
8hidden char *__stpncpy(char *, const char *, size_t);
9hidden char *__strchrnul(const char *, int);
10
11#endif
lib/libc/wasi/libc-top-half/musl/src/include/sys/mman.h created+20
...@@ -0,0 +1,20 @@
1#ifndef SYS_MMAN_H
2#define SYS_MMAN_H
3
4#include "../../../include/sys/mman.h"
5
6hidden void __vm_wait(void);
7hidden void __vm_lock(void);
8hidden void __vm_unlock(void);
9
10hidden void *__mmap(void *, size_t, int, int, int, off_t);
11hidden int __munmap(void *, size_t);
12hidden void *__mremap(void *, size_t, size_t, int, ...);
13hidden int __madvise(void *, size_t, int);
14hidden int __mprotect(void *, size_t, int);
15
16hidden const unsigned char *__map_file(const char *, size_t *);
17
18hidden char *__shm_mapname(const char *, char *);
19
20#endif
lib/libc/wasi/libc-top-half/musl/src/include/sys/stat.h created+9
...@@ -0,0 +1,9 @@
1#ifndef SYS_STAT_H
2#define SYS_STAT_H
3
4#include "../../../include/sys/stat.h"
5
6hidden int __fstat(int, struct stat *);
7hidden int __fstatat(int, const char *restrict, struct stat *restrict, int);
8
9#endif
lib/libc/wasi/libc-top-half/musl/src/include/sys/time.h created+8
...@@ -0,0 +1,8 @@
1#ifndef SYS_TIME_H
2#define SYS_TIME_H
3
4#include "../../../include/sys/time.h"
5
6hidden int __futimesat(int, const char *, const struct timeval [2]);
7
8#endif
lib/std/Io/Threaded.zig+6-2
...@@ -2024,6 +2024,7 @@ fn groupConcurrent(...@@ -2024,6 +2024,7 @@ fn groupConcurrent(
20242024
2025fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) Io.Cancelable!void {2025fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) Io.Cancelable!void {
2026 _ = initial_token; // we need to load `token` *after* the group finishes2026 _ = initial_token; // we need to load `token` *after* the group finishes
2027 if (builtin.single_threaded) unreachable; // nothing to await
2027 const t: *Threaded = @ptrCast(@alignCast(userdata));2028 const t: *Threaded = @ptrCast(@alignCast(userdata));
2028 const g: Group = .{ .ptr = type_erased };2029 const g: Group = .{ .ptr = type_erased };
20292030
...@@ -2082,6 +2083,7 @@ fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *any...@@ -2082,6 +2083,7 @@ fn groupAwait(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *any
20822083
2083fn groupCancel(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) void {2084fn groupCancel(userdata: ?*anyopaque, type_erased: *Io.Group, initial_token: *anyopaque) void {
2084 _ = initial_token;2085 _ = initial_token;
2086 if (builtin.single_threaded) unreachable; // nothing to cancel
2085 const t: *Threaded = @ptrCast(@alignCast(userdata));2087 const t: *Threaded = @ptrCast(@alignCast(userdata));
2086 const g: Group = .{ .ptr = type_erased };2088 const g: Group = .{ .ptr = type_erased };
20872089
...@@ -2152,6 +2154,7 @@ fn await(...@@ -2152,6 +2154,7 @@ fn await(
2152 result_alignment: Alignment,2154 result_alignment: Alignment,
2153) void {2155) void {
2154 _ = result_alignment;2156 _ = result_alignment;
2157 if (builtin.single_threaded) unreachable; // nothing to await
2155 const t: *Threaded = @ptrCast(@alignCast(userdata));2158 const t: *Threaded = @ptrCast(@alignCast(userdata));
2156 const future: *Future = @ptrCast(@alignCast(any_future));2159 const future: *Future = @ptrCast(@alignCast(any_future));
21572160
...@@ -2218,6 +2221,7 @@ fn cancel(...@@ -2218,6 +2221,7 @@ fn cancel(
2218 result_alignment: Alignment,2221 result_alignment: Alignment,
2219) void {2222) void {
2220 _ = result_alignment;2223 _ = result_alignment;
2224 if (builtin.single_threaded) unreachable; // nothing to cancel
2221 const t: *Threaded = @ptrCast(@alignCast(userdata));2225 const t: *Threaded = @ptrCast(@alignCast(userdata));
2222 const future: *Future = @ptrCast(@alignCast(any_future));2226 const future: *Future = @ptrCast(@alignCast(any_future));
22232227
...@@ -4959,7 +4963,7 @@ fn dirReadUnimplemented(userdata: ?*anyopaque, dir_reader: *Dir.Reader, buffer:...@@ -4959,7 +4963,7 @@ fn dirReadUnimplemented(userdata: ?*anyopaque, dir_reader: *Dir.Reader, buffer:
4959 _ = userdata;4963 _ = userdata;
4960 _ = dir_reader;4964 _ = dir_reader;
4961 _ = buffer;4965 _ = buffer;
4962 return error.Unimplemented;4966 return error.Unexpected;
4963}4967}
49644968
4965const dirRealPathFile = switch (native_os) {4969const dirRealPathFile = switch (native_os) {
...@@ -13224,7 +13228,7 @@ fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptio...@@ -13224,7 +13228,7 @@ fn processSpawnPath(userdata: ?*anyopaque, dir: Dir, options: process.SpawnOptio
13224}13228}
1322513229
13226const processSpawn = switch (native_os) {13230const processSpawn = switch (native_os) {
13227 .wasi, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported,13231 .wasi, .emscripten, .ios, .tvos, .visionos, .watchos => processSpawnUnsupported,
13228 .windows => processSpawnWindows,13232 .windows => processSpawnWindows,
13229 else => processSpawnPosix,13233 else => processSpawnPosix,
13230};13234};
lib/std/c.zig+6-2
...@@ -97,6 +97,7 @@ pub const off_t = switch (native_os) {...@@ -97,6 +97,7 @@ pub const off_t = switch (native_os) {
97pub const timespec = switch (native_os) {97pub const timespec = switch (native_os) {
98 .linux => linux.timespec,98 .linux => linux.timespec,
99 .emscripten => emscripten.timespec,99 .emscripten => emscripten.timespec,
100 // lib/libc/include/wasm-wasi-musl/__struct_timespec.h
100 .wasi => extern struct {101 .wasi => extern struct {
101 sec: time_t,102 sec: time_t,
102 nsec: isize,103 nsec: isize,
...@@ -115,16 +116,18 @@ pub const timespec = switch (native_os) {...@@ -115,16 +116,18 @@ pub const timespec = switch (native_os) {
115 @as(wasi.timestamp_t, @intCast(ts.nsec));116 @as(wasi.timestamp_t, @intCast(ts.nsec));
116 }117 }
117118
119 // lib/libc/include/wasm-wasi-musl/__header_sys_stat.h
120
118 /// For use with `utimensat` and `futimens`.121 /// For use with `utimensat` and `futimens`.
119 pub const NOW: timespec = .{122 pub const NOW: timespec = .{
120 .sec = 0,123 .sec = 0,
121 .nsec = 0x3fffffff,124 .nsec = -1,
122 };125 };
123126
124 /// For use with `utimensat` and `futimens`.127 /// For use with `utimensat` and `futimens`.
125 pub const OMIT: timespec = .{128 pub const OMIT: timespec = .{
126 .sec = 0,129 .sec = 0,
127 .nsec = 0x3ffffffe,130 .nsec = -2,
128 };131 };
129 },132 },
130 // https://github.com/SerenityOS/serenity/blob/0a78056453578c18e0a04a0b45ebfb1c96d59005/Kernel/API/POSIX/time.h#L17-L20133 // 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) {...@@ -7007,6 +7010,7 @@ pub const time_t = switch (native_os) {
7007 .linux => linux.time_t,7010 .linux => linux.time_t,
7008 .emscripten => emscripten.time_t,7011 .emscripten => emscripten.time_t,
7009 .haiku, .dragonfly => isize,7012 .haiku, .dragonfly => isize,
7013 // lib/libc/include/wasm-wasi-musl/__typedef_time_t.h
7010 // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L477014 // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L47
7011 else => i64,7015 else => i64,
7012};7016};
lib/std/os/emscripten.zig+16
...@@ -729,6 +729,7 @@ pub const sockaddr = c.sockaddr;...@@ -729,6 +729,7 @@ pub const sockaddr = c.sockaddr;
729729
730pub const blksize_t = i32;730pub const blksize_t = i32;
731pub const nlink_t = u32;731pub const nlink_t = u32;
732// https://github.com/emscripten-core/emscripten/blob/946ab574ae39401b51e75cd5257d894ae732ab54/system/lib/libc/musl/arch/emscripten/bits/alltypes.h#L140
732pub const time_t = i64;733pub const time_t = i64;
733pub const mode_t = u32;734pub const mode_t = u32;
734pub const off_t = i64;735pub const off_t = i64;
...@@ -765,9 +766,24 @@ pub const stack_t = extern struct {...@@ -765,9 +766,24 @@ pub const stack_t = extern struct {
765 size: usize,766 size: usize,
766};767};
767768
769// https://github.com/emscripten-core/emscripten/blob/946ab574ae39401b51e75cd5257d894ae732ab54/system/lib/libc/musl/arch/emscripten/bits/alltypes.h#L284
768pub const timespec = extern struct {770pub const timespec = extern struct {
769 sec: time_t,771 sec: time_t,
770 nsec: isize,772 nsec: isize,
773
774 // https://github.com/emscripten-core/emscripten/blob/d72d7226f4733af8ff993dec70198cf09a24142d/system/lib/libc/musl/include/sys/stat.h#L77-L78
775
776 /// For use with `utimensat` and `futimens`.
777 pub const NOW: timespec = .{
778 .sec = 0,
779 .nsec = 0x3fffffff,
780 };
781
782 /// For use with `utimensat` and `futimens`.
783 pub const OMIT: timespec = .{
784 .sec = 0,
785 .nsec = 0x3ffffffe,
786 };
771};787};
772788
773pub const timezone = extern struct {789pub const timezone = extern struct {