authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-16 19:40:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-29 20:32:27-04:00
log01a4897da54d6c789b0a5232188bbafbbd660946
tree274bf44d509e19f832a1f5b8ab7048ce5ba64e66
parent4188faeac56d9c022fa33449aa4283b1f55395cf
signaturelock-open Commit is signed but in an unrecognized format.

improve the libc of wasm32-freestanding target

* introduce wasm32-freestanding-musl .h files to fix conflicts with stddef.h and errno.h * fix an issue with zig build system regarding installation of webassembly libraries * add implementations to zig's libc: - strcmp - strncmp - strerror - strlen See #514

5 files changed, 468 insertions(+), 1 deletions(-)

CMakeLists.txt+2
......@@ -6066,6 +6066,8 @@ set(ZIG_LIBC_FILES
60666066 "include/x86_64-linux-musl/bits/stat.h"
60676067 "include/x86_64-linux-musl/bits/syscall.h"
60686068 "include/x86_64-linux-musl/bits/user.h"
6069 "include/wasm32-freestanding-musl/bits/alltypes.h"
6070 "include/wasm32-freestanding-musl/errno.h"
60696071 "musl/arch/aarch64/atomic_arch.h"
60706072 "musl/arch/aarch64/bits/alltypes.h.in"
60716073 "musl/arch/aarch64/bits/endian.h"
libc/include/wasm32-freestanding-musl/bits/alltypes.h created+385
......@@ -0,0 +1,385 @@
1#define _Addr long
2#define _Int64 long long
3#define _Reg long
4
5#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
6typedef __builtin_va_list va_list;
7#define __DEFINED_va_list
8#endif
9
10#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
11typedef __builtin_va_list __isoc_va_list;
12#define __DEFINED___isoc_va_list
13#endif
14
15
16#ifndef __cplusplus
17#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
18typedef int wchar_t;
19#define __DEFINED_wchar_t
20#endif
21
22#endif
23
24#if defined(__NEED_float_t) && !defined(__DEFINED_float_t)
25typedef float float_t;
26#define __DEFINED_float_t
27#endif
28
29#if defined(__NEED_double_t) && !defined(__DEFINED_double_t)
30typedef double double_t;
31#define __DEFINED_double_t
32#endif
33
34
35#if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t)
36typedef struct { long long __ll; long double __ld; } max_align_t;
37#define __DEFINED_max_align_t
38#endif
39
40
41#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
42typedef long time_t;
43#define __DEFINED_time_t
44#endif
45
46#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
47typedef long suseconds_t;
48#define __DEFINED_suseconds_t
49#endif
50
51
52#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
53typedef struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
54#define __DEFINED_pthread_attr_t
55#endif
56
57#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
58typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
59#define __DEFINED_pthread_mutex_t
60#endif
61
62#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
63typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
64#define __DEFINED_mtx_t
65#endif
66
67#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
68typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
69#define __DEFINED_pthread_cond_t
70#endif
71
72#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
73typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
74#define __DEFINED_cnd_t
75#endif
76
77#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
78typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
79#define __DEFINED_pthread_rwlock_t
80#endif
81
82#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
83typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
84#define __DEFINED_pthread_barrier_t
85#endif
86
87#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
88typedef unsigned _Addr size_t;
89#define __DEFINED_size_t
90#endif
91
92#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t)
93typedef unsigned _Addr uintptr_t;
94#define __DEFINED_uintptr_t
95#endif
96
97#if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t)
98typedef _Addr ptrdiff_t;
99#define __DEFINED_ptrdiff_t
100#endif
101
102#if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t)
103typedef _Addr ssize_t;
104#define __DEFINED_ssize_t
105#endif
106
107#if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t)
108typedef _Addr intptr_t;
109#define __DEFINED_intptr_t
110#endif
111
112#if defined(__NEED_regoff_t) && !defined(__DEFINED_regoff_t)
113typedef _Addr regoff_t;
114#define __DEFINED_regoff_t
115#endif
116
117#if defined(__NEED_register_t) && !defined(__DEFINED_register_t)
118typedef _Reg register_t;
119#define __DEFINED_register_t
120#endif
121
122
123#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
124typedef signed char int8_t;
125#define __DEFINED_int8_t
126#endif
127
128#if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t)
129typedef signed short int16_t;
130#define __DEFINED_int16_t
131#endif
132
133#if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t)
134typedef signed int int32_t;
135#define __DEFINED_int32_t
136#endif
137
138#if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t)
139typedef signed _Int64 int64_t;
140#define __DEFINED_int64_t
141#endif
142
143#if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t)
144typedef signed _Int64 intmax_t;
145#define __DEFINED_intmax_t
146#endif
147
148#if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t)
149typedef unsigned char uint8_t;
150#define __DEFINED_uint8_t
151#endif
152
153#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t)
154typedef unsigned short uint16_t;
155#define __DEFINED_uint16_t
156#endif
157
158#if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t)
159typedef unsigned int uint32_t;
160#define __DEFINED_uint32_t
161#endif
162
163#if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t)
164typedef unsigned _Int64 uint64_t;
165#define __DEFINED_uint64_t
166#endif
167
168#if defined(__NEED_u_int64_t) && !defined(__DEFINED_u_int64_t)
169typedef unsigned _Int64 u_int64_t;
170#define __DEFINED_u_int64_t
171#endif
172
173#if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t)
174typedef unsigned _Int64 uintmax_t;
175#define __DEFINED_uintmax_t
176#endif
177
178
179#if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t)
180typedef unsigned mode_t;
181#define __DEFINED_mode_t
182#endif
183
184#if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t)
185typedef unsigned _Reg nlink_t;
186#define __DEFINED_nlink_t
187#endif
188
189#if defined(__NEED_off_t) && !defined(__DEFINED_off_t)
190typedef _Int64 off_t;
191#define __DEFINED_off_t
192#endif
193
194#if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t)
195typedef unsigned _Int64 ino_t;
196#define __DEFINED_ino_t
197#endif
198
199#if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t)
200typedef unsigned _Int64 dev_t;
201#define __DEFINED_dev_t
202#endif
203
204#if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t)
205typedef long blksize_t;
206#define __DEFINED_blksize_t
207#endif
208
209#if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t)
210typedef _Int64 blkcnt_t;
211#define __DEFINED_blkcnt_t
212#endif
213
214#if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t)
215typedef unsigned _Int64 fsblkcnt_t;
216#define __DEFINED_fsblkcnt_t
217#endif
218
219#if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t)
220typedef unsigned _Int64 fsfilcnt_t;
221#define __DEFINED_fsfilcnt_t
222#endif
223
224
225#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t)
226typedef unsigned wint_t;
227#define __DEFINED_wint_t
228#endif
229
230#if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t)
231typedef unsigned long wctype_t;
232#define __DEFINED_wctype_t
233#endif
234
235
236#if defined(__NEED_timer_t) && !defined(__DEFINED_timer_t)
237typedef void * timer_t;
238#define __DEFINED_timer_t
239#endif
240
241#if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t)
242typedef int clockid_t;
243#define __DEFINED_clockid_t
244#endif
245
246#if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t)
247typedef long clock_t;
248#define __DEFINED_clock_t
249#endif
250
251#if defined(__NEED_struct_timeval) && !defined(__DEFINED_struct_timeval)
252struct timeval { time_t tv_sec; suseconds_t tv_usec; };
253#define __DEFINED_struct_timeval
254#endif
255
256#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
257struct timespec { time_t tv_sec; long tv_nsec; };
258#define __DEFINED_struct_timespec
259#endif
260
261
262#if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t)
263typedef int pid_t;
264#define __DEFINED_pid_t
265#endif
266
267#if defined(__NEED_id_t) && !defined(__DEFINED_id_t)
268typedef unsigned id_t;
269#define __DEFINED_id_t
270#endif
271
272#if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t)
273typedef unsigned uid_t;
274#define __DEFINED_uid_t
275#endif
276
277#if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t)
278typedef unsigned gid_t;
279#define __DEFINED_gid_t
280#endif
281
282#if defined(__NEED_key_t) && !defined(__DEFINED_key_t)
283typedef int key_t;
284#define __DEFINED_key_t
285#endif
286
287#if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t)
288typedef unsigned useconds_t;
289#define __DEFINED_useconds_t
290#endif
291
292
293#ifdef __cplusplus
294#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
295typedef unsigned long pthread_t;
296#define __DEFINED_pthread_t
297#endif
298
299#else
300#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
301typedef struct __pthread * pthread_t;
302#define __DEFINED_pthread_t
303#endif
304
305#endif
306#if defined(__NEED_pthread_once_t) && !defined(__DEFINED_pthread_once_t)
307typedef int pthread_once_t;
308#define __DEFINED_pthread_once_t
309#endif
310
311#if defined(__NEED_pthread_key_t) && !defined(__DEFINED_pthread_key_t)
312typedef unsigned pthread_key_t;
313#define __DEFINED_pthread_key_t
314#endif
315
316#if defined(__NEED_pthread_spinlock_t) && !defined(__DEFINED_pthread_spinlock_t)
317typedef int pthread_spinlock_t;
318#define __DEFINED_pthread_spinlock_t
319#endif
320
321#if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t)
322typedef struct { unsigned __attr; } pthread_mutexattr_t;
323#define __DEFINED_pthread_mutexattr_t
324#endif
325
326#if defined(__NEED_pthread_condattr_t) && !defined(__DEFINED_pthread_condattr_t)
327typedef struct { unsigned __attr; } pthread_condattr_t;
328#define __DEFINED_pthread_condattr_t
329#endif
330
331#if defined(__NEED_pthread_barrierattr_t) && !defined(__DEFINED_pthread_barrierattr_t)
332typedef struct { unsigned __attr; } pthread_barrierattr_t;
333#define __DEFINED_pthread_barrierattr_t
334#endif
335
336#if defined(__NEED_pthread_rwlockattr_t) && !defined(__DEFINED_pthread_rwlockattr_t)
337typedef struct { unsigned __attr[2]; } pthread_rwlockattr_t;
338#define __DEFINED_pthread_rwlockattr_t
339#endif
340
341
342#if defined(__NEED_FILE) && !defined(__DEFINED_FILE)
343typedef struct _IO_FILE FILE;
344#define __DEFINED_FILE
345#endif
346
347
348#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
349typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
350#define __DEFINED_mbstate_t
351#endif
352
353
354#if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t)
355typedef struct __locale_struct * locale_t;
356#define __DEFINED_locale_t
357#endif
358
359
360#if defined(__NEED_sigset_t) && !defined(__DEFINED_sigset_t)
361typedef struct __sigset_t { unsigned long __bits[128/sizeof(long)]; } sigset_t;
362#define __DEFINED_sigset_t
363#endif
364
365
366#if defined(__NEED_struct_iovec) && !defined(__DEFINED_struct_iovec)
367struct iovec { void *iov_base; size_t iov_len; };
368#define __DEFINED_struct_iovec
369#endif
370
371
372#if defined(__NEED_socklen_t) && !defined(__DEFINED_socklen_t)
373typedef unsigned socklen_t;
374#define __DEFINED_socklen_t
375#endif
376
377#if defined(__NEED_sa_family_t) && !defined(__DEFINED_sa_family_t)
378typedef unsigned short sa_family_t;
379#define __DEFINED_sa_family_t
380#endif
381
382
383#undef _Addr
384#undef _Int64
385#undef _Reg
libc/include/wasm32-freestanding-musl/errno.h created+24
......@@ -0,0 +1,24 @@
1#ifndef _ERRNO_H
2#define _ERRNO_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#ifdef WASM_THREAD_MODEL_SINGLE
9extern int errno;
10#else
11#ifdef __cplusplus
12extern thread_local int errno;
13#else
14extern _Thread_local int errno;
15#endif
16#endif
17
18#define errno errno
19
20#ifdef __cplusplus
21}
22#endif
23
24#endif
std/build.zig+19-1
......@@ -877,6 +877,13 @@ pub const Target = union(enum) {
877877 };
878878 }
879879
880 pub fn getArch(self: Target) builtin.Arch {
881 switch (self) {
882 Target.Native => return builtin.arch,
883 Target.Cross => |t| return t.arch,
884 }
885 }
886
880887 pub fn isDarwin(self: Target) bool {
881888 return switch (self.getOs()) {
882889 .ios, .macosx, .watchos, .tvos => true,
......@@ -891,6 +898,13 @@ pub const Target = union(enum) {
891898 };
892899 }
893900
901 pub fn isWasm(self: Target) bool {
902 return switch (self.getArch()) {
903 .wasm32, .wasm64 => true,
904 else => false,
905 };
906 }
907
894908 pub fn isFreeBSD(self: Target) bool {
895909 return switch (self.getOs()) {
896910 .freebsd => true,
......@@ -1080,7 +1094,11 @@ pub const LibExeObjStep = struct {
10801094 self.out_filename = self.builder.fmt("{}.lib", self.name);
10811095 },
10821096 else => {
1083 self.out_filename = self.builder.fmt("lib{}.a", self.name);
1097 if (self.target.isWasm()) {
1098 self.out_filename = self.builder.fmt("{}.wasm", self.name);
1099 } else {
1100 self.out_filename = self.builder.fmt("lib{}.a", self.name);
1101 }
10841102 },
10851103 }
10861104 self.out_lib_filename = self.out_filename;
std/special/c.zig+38
......@@ -20,6 +20,12 @@ comptime {
2020 if (is_freestanding and is_wasm and builtin.link_libc) {
2121 @export("_start", wasm_start, .Strong);
2222 }
23 if (builtin.link_libc) {
24 @export("strcmp", strcmp, .Strong);
25 @export("strncmp", strncmp, .Strong);
26 @export("strerror", strerror, .Strong);
27 @export("strlen", strlen, .Strong);
28 }
2329}
2430
2531extern fn main(argc: c_int, argv: [*][*]u8) c_int;
......@@ -27,6 +33,38 @@ extern fn wasm_start() void {
2733 _ = main(0, undefined);
2834}
2935
36extern fn strcmp(s1: [*]const u8, s2: [*]const u8) c_int {
37 return std.cstr.cmp(s1, s2);
38}
39
40extern fn strlen(s: [*]const u8) usize {
41 return std.mem.len(u8, s);
42}
43
44extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int {
45 if (_n == 0) return 0;
46 var l = _l;
47 var r = _r;
48 var n = _n - 1;
49 while (l[0] != 0 and r[0] != 0 and n != 0 and l[0] == r[0]) {
50 l += 1;
51 r += 1;
52 n -= 1;
53 }
54 return c_int(l[0]) - c_int(r[0]);
55}
56
57extern fn strerror(errnum: c_int) [*]const u8 {
58 return c"TODO strerror implementation";
59}
60
61test "strncmp" {
62 std.testing.expect(strncmp(c"a", c"b", 1) == -1);
63 std.testing.expect(strncmp(c"a", c"c", 1) == -2);
64 std.testing.expect(strncmp(c"b", c"a", 1) == 1);
65 std.testing.expect(strncmp(c"\xff", c"\x02", 1) == 253);
66}
67
3068// Avoid dragging in the runtime safety mechanisms into this .o file,
3169// unless we're trying to test this file.
3270pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {