authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-12 18:05:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-12 18:05:27-07:00
log1f34c03ac14ac352ec03267ca8592dadfbd5e4bc
treeebcb851922636b7dd2b17acb72187836c86180ec
parent868253a9c94d9907fae81e5e3108c7d10a85f5c3
parent8ebb18d9da0bfbe6a974636fd36e3391d1de253b

Merge remote-tracking branch 'origin/master' into llvm12


67 files changed, 5444 insertions(+), 491 deletions(-)

ci/srht/update-download-page.zig+2-1
...@@ -73,7 +73,8 @@ fn render(...@@ -73,7 +73,8 @@ fn render(
73 if (vars.get(var_name)) |value| {73 if (vars.get(var_name)) |value| {
74 const trimmed = mem.trim(u8, value, " \r\n");74 const trimmed = mem.trim(u8, value, " \r\n");
75 if (fmt == .html and mem.endsWith(u8, var_name, "BYTESIZE")) {75 if (fmt == .html and mem.endsWith(u8, var_name, "BYTESIZE")) {
76 try writer.print("{Bi:.1}", .{try std.fmt.parseInt(u64, trimmed, 10)});76 const size = try std.fmt.parseInt(u64, trimmed, 10);
77 try writer.print("{:.1}", .{std.fmt.fmtIntSizeDec(size)});
77 } else {78 } else {
78 try writer.writeAll(trimmed);79 try writer.writeAll(trimmed);
79 }80 }
doc/docgen.zig+20-6
...@@ -34,6 +34,15 @@ pub fn main() !void {...@@ -34,6 +34,15 @@ pub fn main() !void {
34 const out_file_name = try (args_it.next(allocator) orelse @panic("expected output arg"));34 const out_file_name = try (args_it.next(allocator) orelse @panic("expected output arg"));
35 defer allocator.free(out_file_name);35 defer allocator.free(out_file_name);
3636
37 var do_code_tests = true;
38 if (args_it.next(allocator)) |arg| {
39 if (mem.eql(u8, try arg, "--skip-code-tests")) {
40 do_code_tests = false;
41 } else {
42 @panic("unrecognized arg");
43 }
44 }
45
37 var in_file = try fs.cwd().openFile(in_file_name, .{ .read = true });46 var in_file = try fs.cwd().openFile(in_file_name, .{ .read = true });
38 defer in_file.close();47 defer in_file.close();
3948
...@@ -50,7 +59,7 @@ pub fn main() !void {...@@ -50,7 +59,7 @@ pub fn main() !void {
50 try fs.cwd().makePath(tmp_dir_name);59 try fs.cwd().makePath(tmp_dir_name);
51 defer fs.cwd().deleteTree(tmp_dir_name) catch {};60 defer fs.cwd().deleteTree(tmp_dir_name) catch {};
5261
53 try genHtml(allocator, &tokenizer, &toc, buffered_writer.writer(), zig_exe);62 try genHtml(allocator, &tokenizer, &toc, buffered_writer.writer(), zig_exe, do_code_tests);
54 try buffered_writer.flush();63 try buffered_writer.flush();
55}64}
5665
...@@ -564,8 +573,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -564,8 +573,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
564 );573 );
565 }574 }
566 _ = try eatToken(tokenizer, Token.Id.BracketClose);575 _ = try eatToken(tokenizer, Token.Id.BracketClose);
567 } else576 } else unreachable; // TODO issue #707
568 unreachable; // TODO issue #707
569 try nodes.append(Node{577 try nodes.append(Node{
570 .Code = Code{578 .Code = Code{
571 .id = code_kind_id,579 .id = code_kind_id,
...@@ -784,12 +792,12 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token:...@@ -784,12 +792,12 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token:
784 if (mem.indexOf(u8, src[index..token.loc.start], "//")) |comment_start_off| {792 if (mem.indexOf(u8, src[index..token.loc.start], "//")) |comment_start_off| {
785 // render one comment793 // render one comment
786 const comment_start = index + comment_start_off;794 const comment_start = index + comment_start_off;
787 const comment_end_off = mem.indexOf(u8, src[comment_start .. token.loc.start], "\n");795 const comment_end_off = mem.indexOf(u8, src[comment_start..token.loc.start], "\n");
788 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;796 const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
789797
790 try writeEscaped(out, src[index..comment_start]);798 try writeEscaped(out, src[index..comment_start]);
791 try out.writeAll("<span class=\"tok-comment\">");799 try out.writeAll("<span class=\"tok-comment\">");
792 try writeEscaped(out, src[comment_start .. comment_end]);800 try writeEscaped(out, src[comment_start..comment_end]);
793 try out.writeAll("</span>");801 try out.writeAll("</span>");
794 index = comment_end;802 index = comment_end;
795 tokenizer.index = index;803 tokenizer.index = index;
...@@ -1002,7 +1010,7 @@ fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: anytype, source_token: To...@@ -1002,7 +1010,7 @@ fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: anytype, source_token: To
1002 return tokenizeAndPrintRaw(docgen_tokenizer, out, source_token, raw_src);1010 return tokenizeAndPrintRaw(docgen_tokenizer, out, source_token, raw_src);
1003}1011}
10041012
1005fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: anytype, zig_exe: []const u8) !void {1013fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: anytype, zig_exe: []const u8, do_code_tests: bool) !void {
1006 var code_progress_index: usize = 0;1014 var code_progress_index: usize = 0;
10071015
1008 var env_map = try process.getEnvMap(allocator);1016 var env_map = try process.getEnvMap(allocator);
...@@ -1061,6 +1069,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1061,6 +1069,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1061 try out.writeAll("<pre>");1069 try out.writeAll("<pre>");
1062 try tokenizeAndPrint(tokenizer, out, code.source_token);1070 try tokenizeAndPrint(tokenizer, out, code.source_token);
1063 try out.writeAll("</pre>");1071 try out.writeAll("</pre>");
1072
1073 if (!do_code_tests) {
1074 print("SKIP\n", .{});
1075 continue;
1076 }
1077
1064 const name_plus_ext = try std.fmt.allocPrint(allocator, "{s}.zig", .{code.name});1078 const name_plus_ext = try std.fmt.allocPrint(allocator, "{s}.zig", .{code.name});
1065 const tmp_source_file_name = try fs.path.join(1079 const tmp_source_file_name = try fs.path.join(
1066 allocator,1080 allocator,
lib/libc/include/aarch64-macos-gnu/AvailabilityInternal.h+5-5
...@@ -55,7 +55,7 @@...@@ -55,7 +55,7 @@
55 #ifdef __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__55 #ifdef __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
56 /* compiler sets __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ when -mtvos-version-min is used */56 /* compiler sets __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ when -mtvos-version-min is used */
57 #define __TV_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__57 #define __TV_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
58 #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_14_258 #define __TV_OS_VERSION_MAX_ALLOWED __TVOS_14_3
59 /* for compatibility with existing code. New code should use platform specific checks */59 /* for compatibility with existing code. New code should use platform specific checks */
60 #define __IPHONE_OS_VERSION_MIN_REQUIRED 9000060 #define __IPHONE_OS_VERSION_MIN_REQUIRED 90000
61 #endif61 #endif
...@@ -65,7 +65,7 @@...@@ -65,7 +65,7 @@
65 #ifdef __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__65 #ifdef __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__
66 /* compiler sets __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ when -mwatchos-version-min is used */66 /* compiler sets __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ when -mwatchos-version-min is used */
67 #define __WATCH_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__67 #define __WATCH_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__
68 #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_7_168 #define __WATCH_OS_VERSION_MAX_ALLOWED __WATCHOS_7_2
69 /* for compatibility with existing code. New code should use platform specific checks */69 /* for compatibility with existing code. New code should use platform specific checks */
70 #define __IPHONE_OS_VERSION_MIN_REQUIRED 9000070 #define __IPHONE_OS_VERSION_MIN_REQUIRED 90000
71 #endif71 #endif
...@@ -75,7 +75,7 @@...@@ -75,7 +75,7 @@
75 #ifdef __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__75 #ifdef __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__
76 76
77 #define __BRIDGE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__77 #define __BRIDGE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_BRIDGE_OS_VERSION_MIN_REQUIRED__
78 #define __BRIDGE_OS_VERSION_MAX_ALLOWED 5000078 #define __BRIDGE_OS_VERSION_MAX_ALLOWED 50100
79 /* for compatibility with existing code. New code should use platform specific checks */79 /* for compatibility with existing code. New code should use platform specific checks */
80 #define __IPHONE_OS_VERSION_MIN_REQUIRED 11000080 #define __IPHONE_OS_VERSION_MIN_REQUIRED 110000
81 #endif81 #endif
...@@ -90,14 +90,14 @@...@@ -90,14 +90,14 @@
90#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED90#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
91 /* make sure a default max version is set */91 /* make sure a default max version is set */
92 #ifndef __MAC_OS_X_VERSION_MAX_ALLOWED92 #ifndef __MAC_OS_X_VERSION_MAX_ALLOWED
93 #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_11_093 #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_11_1
94 #endif94 #endif
95#endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */95#endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */
9696
97#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED97#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
98 /* make sure a default max version is set */98 /* make sure a default max version is set */
99 #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED99 #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED
100 #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_14_2100 #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_14_3
101 #endif101 #endif
102 /* make sure a valid min is set */102 /* make sure a valid min is set */
103 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_0103 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_0
lib/libc/include/aarch64-macos-gnu/AvailabilityMacros.h+3-2
...@@ -118,6 +118,7 @@...@@ -118,6 +118,7 @@
118#define MAC_OS_X_VERSION_10_14_4 101404118#define MAC_OS_X_VERSION_10_14_4 101404
119#define MAC_OS_X_VERSION_10_15 101500119#define MAC_OS_X_VERSION_10_15 101500
120#define MAC_OS_VERSION_11_0 110000120#define MAC_OS_VERSION_11_0 110000
121#define MAC_OS_VERSION_11_1 110100
121122
122/* 123/*
123 * If min OS not specified, assume 10.4 for intel124 * If min OS not specified, assume 10.4 for intel
...@@ -144,10 +145,10 @@...@@ -144,10 +145,10 @@
144 * if max OS not specified, assume larger of (10.15, min)145 * if max OS not specified, assume larger of (10.15, min)
145 */146 */
146#ifndef MAC_OS_X_VERSION_MAX_ALLOWED147#ifndef MAC_OS_X_VERSION_MAX_ALLOWED
147 #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_VERSION_11_0148 #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_VERSION_11_1
148 #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_MIN_REQUIRED149 #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_MIN_REQUIRED
149 #else150 #else
150 #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_VERSION_11_0151 #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_VERSION_11_1
151 #endif152 #endif
152#endif153#endif
153154
lib/libc/include/aarch64-macos-gnu/AvailabilityVersions.h+4
...@@ -58,6 +58,7 @@...@@ -58,6 +58,7 @@
58#define __MAC_10_15_4 10150458#define __MAC_10_15_4 101504
59#define __MAC_10_16 10160059#define __MAC_10_16 101600
60#define __MAC_11_0 11000060#define __MAC_11_0 110000
61#define __MAC_11_1 110100
61/* __MAC_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */62/* __MAC_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */
6263
63#define __IPHONE_2_0 2000064#define __IPHONE_2_0 20000
...@@ -110,6 +111,7 @@...@@ -110,6 +111,7 @@
110#define __IPHONE_14_0 140000111#define __IPHONE_14_0 140000
111#define __IPHONE_14_1 140100112#define __IPHONE_14_1 140100
112#define __IPHONE_14_2 140200113#define __IPHONE_14_2 140200
114#define __IPHONE_14_3 140300
113/* __IPHONE_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */115/* __IPHONE_NA is not defined to a value but is used as a token by macros to indicate that the API is unavailable */
114116
115#define __TVOS_9_0 90000117#define __TVOS_9_0 90000
...@@ -136,6 +138,7 @@...@@ -136,6 +138,7 @@
136#define __TVOS_14_0 140000138#define __TVOS_14_0 140000
137#define __TVOS_14_1 140100139#define __TVOS_14_1 140100
138#define __TVOS_14_2 140200140#define __TVOS_14_2 140200
141#define __TVOS_14_3 140300
139142
140#define __WATCHOS_1_0 10000143#define __WATCHOS_1_0 10000
141#define __WATCHOS_2_0 20000144#define __WATCHOS_2_0 20000
...@@ -158,6 +161,7 @@...@@ -158,6 +161,7 @@
158#define __WATCHOS_6_2 60200161#define __WATCHOS_6_2 60200
159#define __WATCHOS_7_0 70000162#define __WATCHOS_7_0 70000
160#define __WATCHOS_7_1 70100163#define __WATCHOS_7_1 70100
164#define __WATCHOS_7_2 70200
161165
162/*166/*
163 * Set up standard Mac OS X versions167 * Set up standard Mac OS X versions
lib/libc/include/aarch64-macos-gnu/libproc.h created+187
...@@ -0,0 +1,187 @@
1/*
2 * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#ifndef _LIBPROC_H_
24#define _LIBPROC_H_
25
26#include <sys/cdefs.h>
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/mount.h>
31#include <sys/resource.h>
32#include <stdint.h>
33#include <stdbool.h>
34#include <mach/message.h> /* for audit_token_t */
35
36#include <sys/proc_info.h>
37
38#include <Availability.h>
39#include <os/availability.h>
40
41/*
42 * This header file contains private interfaces to obtain process information.
43 * These interfaces are subject to change in future releases.
44 */
45
46/*!
47 * @define PROC_LISTPIDSPATH_PATH_IS_VOLUME
48 * @discussion This flag indicates that all processes that hold open
49 * file references on the volume associated with the specified
50 * path should be returned.
51 */
52#define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1
53
54
55/*!
56 * @define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY
57 * @discussion This flag indicates that file references that were opened
58 * with the O_EVTONLY flag should be excluded from the matching
59 * criteria.
60 */
61#define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2
62
63__BEGIN_DECLS
64
65
66/*!
67 * @function proc_listpidspath
68 * @discussion A function which will search through the current
69 * processes looking for open file references which match
70 * a specified path or volume.
71 * @param type types of processes to be searched (see proc_listpids)
72 * @param typeinfo adjunct information for type
73 * @param path file or volume path
74 * @param pathflags flags to control which files should be considered
75 * during the process search.
76 * @param buffer a C array of int-sized values to be filled with
77 * process identifiers that hold an open file reference
78 * matching the specified path or volume. Pass NULL to
79 * obtain the minimum buffer size needed to hold the
80 * currently active processes.
81 * @param buffersize the size (in bytes) of the provided buffer.
82 * @result the number of bytes of data returned in the provided buffer;
83 * -1 if an error was encountered;
84 */
85int proc_listpidspath(uint32_t type,
86 uint32_t typeinfo,
87 const char *path,
88 uint32_t pathflags,
89 void *buffer,
90 int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
91
92int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
93int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
94int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
95int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
96int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
97int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
98int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
99int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
100int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
101int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
102int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
103int proc_pidpath_audittoken(audit_token_t *audittoken, void * buffer, uint32_t buffersize) API_AVAILABLE(macos(11.0), ios(14.0), watchos(7.0), tvos(14.0));
104int proc_libversion(int *major, int * minor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
105
106/*
107 * Return resource usage information for the given pid, which can be a live process or a zombie.
108 *
109 * Returns 0 on success; or -1 on failure, with errno set to indicate the specific error.
110 */
111int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
112
113/*
114 * A process can use the following api to set its own process control
115 * state on resoure starvation. The argument can have one of the PROC_SETPC_XX values
116 */
117#define PROC_SETPC_NONE 0
118#define PROC_SETPC_THROTTLEMEM 1
119#define PROC_SETPC_SUSPEND 2
120#define PROC_SETPC_TERMINATE 3
121
122int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
123int proc_setpcontrol(const int control);
124
125int proc_track_dirty(pid_t pid, uint32_t flags);
126int proc_set_dirty(pid_t pid, bool dirty);
127int proc_get_dirty(pid_t pid, uint32_t *flags);
128int proc_clear_dirty(pid_t pid, uint32_t flags);
129
130int proc_terminate(pid_t pid, int *sig);
131
132/*
133 * NO_SMT means that on an SMT CPU, this thread must be scheduled alone,
134 * with the paired CPU idle.
135 *
136 * Set NO_SMT on the current proc (all existing and future threads)
137 * This attribute is inherited on fork and exec
138 */
139int proc_set_no_smt(void) __API_AVAILABLE(macos(11.0));
140
141/* Set NO_SMT on the current thread */
142int proc_setthread_no_smt(void) __API_AVAILABLE(macos(11.0));
143
144/*
145 * CPU Security Mitigation APIs
146 *
147 * Set CPU security mitigation on the current proc (all existing and future threads)
148 * This attribute is inherited on fork and exec
149 */
150int proc_set_csm(uint32_t flags) __API_AVAILABLE(macos(11.0));
151
152/* Set CPU security mitigation on the current thread */
153int proc_setthread_csm(uint32_t flags) __API_AVAILABLE(macos(11.0));
154
155/*
156 * flags for CPU Security Mitigation APIs
157 * PROC_CSM_ALL should be used in most cases,
158 * the individual flags are provided only for performance evaluation etc
159 */
160#define PROC_CSM_ALL 0x0001 /* Set all available mitigations */
161#define PROC_CSM_NOSMT 0x0002 /* Set NO_SMT - see above */
162#define PROC_CSM_TECS 0x0004 /* Execute VERW on every return to user mode */
163
164#ifdef PRIVATE
165#include <sys/event.h>
166/*
167 * Enumerate potential userspace pointers embedded in kernel data structures.
168 * Currently inspects kqueues only.
169 *
170 * NOTE: returned "pointers" are opaque user-supplied values and thus not
171 * guaranteed to address valid objects or be pointers at all.
172 *
173 * Returns the number of pointers found (which may exceed buffersize), or -1 on
174 * failure and errno set appropriately.
175 */
176int proc_list_uptrs(pid_t pid, uint64_t *buffer, uint32_t buffersize);
177
178int proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz);
179int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer,
180 int buffersize);
181#endif /* PRIVATE */
182
183int proc_udata_info(int pid, int flavor, void *buffer, int buffersize);
184
185__END_DECLS
186
187#endif /*_LIBPROC_H_ */
\ No newline at end of file
lib/libc/include/aarch64-macos-gnu/mach/arm/vm_param.h+4
...@@ -87,6 +87,10 @@...@@ -87,6 +87,10 @@
87#define MACH_VM_MIN_ADDRESS ((mach_vm_offset_t) MACH_VM_MIN_ADDRESS_RAW)87#define MACH_VM_MIN_ADDRESS ((mach_vm_offset_t) MACH_VM_MIN_ADDRESS_RAW)
88#define MACH_VM_MAX_ADDRESS ((mach_vm_offset_t) MACH_VM_MAX_ADDRESS_RAW)88#define MACH_VM_MAX_ADDRESS ((mach_vm_offset_t) MACH_VM_MAX_ADDRESS_RAW)
8989
90#define MACH_VM_MIN_GPU_CARVEOUT_ADDRESS_RAW 0x0000001000000000ULL
91#define MACH_VM_MAX_GPU_CARVEOUT_ADDRESS_RAW 0x0000007000000000ULL
92#define MACH_VM_MIN_GPU_CARVEOUT_ADDRESS ((mach_vm_offset_t) MACH_VM_MIN_GPU_CARVEOUT_ADDRESS_RAW)
93#define MACH_VM_MAX_GPU_CARVEOUT_ADDRESS ((mach_vm_offset_t) MACH_VM_MAX_GPU_CARVEOUT_ADDRESS_RAW)
9094
91#else /* defined(__arm64__) */95#else /* defined(__arm64__) */
92#error architecture not supported96#error architecture not supported
lib/libc/include/aarch64-macos-gnu/net/route.h created+257
...@@ -0,0 +1,257 @@
1/*
2 * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright (c) 1980, 1986, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)route.h 8.3 (Berkeley) 4/19/94
61 * $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
62 */
63
64#ifndef _NET_ROUTE_H_
65#define _NET_ROUTE_H_
66#include <sys/appleapiopts.h>
67#include <stdint.h>
68#include <sys/types.h>
69#include <sys/socket.h>
70
71/*
72 * These numbers are used by reliable protocols for determining
73 * retransmission behavior and are included in the routing structure.
74 */
75struct rt_metrics {
76 u_int32_t rmx_locks; /* Kernel leaves these values alone */
77 u_int32_t rmx_mtu; /* MTU for this path */
78 u_int32_t rmx_hopcount; /* max hops expected */
79 int32_t rmx_expire; /* lifetime for route, e.g. redirect */
80 u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */
81 u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */
82 u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */
83 u_int32_t rmx_rtt; /* estimated round trip time */
84 u_int32_t rmx_rttvar; /* estimated rtt variance */
85 u_int32_t rmx_pksent; /* packets sent using this route */
86 u_int32_t rmx_state; /* route state */
87 u_int32_t rmx_filler[3]; /* will be used for TCP's peer-MSS cache */
88};
89
90/*
91 * rmx_rtt and rmx_rttvar are stored as microseconds;
92 */
93#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
94
95
96
97#define RTF_UP 0x1 /* route usable */
98#define RTF_GATEWAY 0x2 /* destination is a gateway */
99#define RTF_HOST 0x4 /* host entry (net otherwise) */
100#define RTF_REJECT 0x8 /* host or net unreachable */
101#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
102#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
103#define RTF_DONE 0x40 /* message confirmed */
104#define RTF_DELCLONE 0x80 /* delete cloned route */
105#define RTF_CLONING 0x100 /* generate new routes on use */
106#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
107#define RTF_LLINFO 0x400 /* DEPRECATED - exists ONLY for backward
108 * compatibility */
109#define RTF_LLDATA 0x400 /* used by apps to add/del L2 entries */
110#define RTF_STATIC 0x800 /* manually added */
111#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
112#define RTF_NOIFREF 0x2000 /* not eligible for RTF_IFREF */
113#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
114#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
115
116#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
117#define RTF_WASCLONED 0x20000 /* route generated through cloning */
118#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
119 /* 0x80000 unused */
120#define RTF_PINNED 0x100000 /* future use */
121#define RTF_LOCAL 0x200000 /* route represents a local address */
122#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
123#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
124#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */
125#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */
126#define RTF_IFREF 0x4000000 /* route holds a ref to interface */
127#define RTF_PROXY 0x8000000 /* proxying, no interface scope */
128#define RTF_ROUTER 0x10000000 /* host is a router */
129#define RTF_DEAD 0x20000000 /* Route entry is being freed */
130 /* 0x40000000 and up unassigned */
131
132#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
133#define RTF_BITS \
134 "\020\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" \
135 "\10DELCLONE\11CLONING\12XRESOLVE\13LLINFO\14STATIC\15BLACKHOLE" \
136 "\16NOIFREF\17PROTO2\20PROTO1\21PRCLONING\22WASCLONED\23PROTO3" \
137 "\25PINNED\26LOCAL\27BROADCAST\30MULTICAST\31IFSCOPE\32CONDEMNED" \
138 "\33IFREF\34PROXY\35ROUTER"
139
140#define IS_DIRECT_HOSTROUTE(rt) \
141 (((rt)->rt_flags & (RTF_HOST | RTF_GATEWAY)) == RTF_HOST)
142/*
143 * Routing statistics.
144 */
145struct rtstat {
146 short rts_badredirect; /* bogus redirect calls */
147 short rts_dynamic; /* routes created by redirects */
148 short rts_newgateway; /* routes modified by redirects */
149 short rts_unreach; /* lookups which failed */
150 short rts_wildcard; /* lookups satisfied by a wildcard */
151 short rts_badrtgwroute; /* route to gateway is not direct */
152};
153
154/*
155 * Structures for routing messages.
156 */
157struct rt_msghdr {
158 u_short rtm_msglen; /* to skip over non-understood messages */
159 u_char rtm_version; /* future binary compatibility */
160 u_char rtm_type; /* message type */
161 u_short rtm_index; /* index for associated ifp */
162 int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
163 int rtm_addrs; /* bitmask identifying sockaddrs in msg */
164 pid_t rtm_pid; /* identify sender */
165 int rtm_seq; /* for sender to identify action */
166 int rtm_errno; /* why failed */
167 int rtm_use; /* from rtentry */
168 u_int32_t rtm_inits; /* which metrics we are initializing */
169 struct rt_metrics rtm_rmx; /* metrics themselves */
170};
171
172struct rt_msghdr2 {
173 u_short rtm_msglen; /* to skip over non-understood messages */
174 u_char rtm_version; /* future binary compatibility */
175 u_char rtm_type; /* message type */
176 u_short rtm_index; /* index for associated ifp */
177 int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
178 int rtm_addrs; /* bitmask identifying sockaddrs in msg */
179 int32_t rtm_refcnt; /* reference count */
180 int rtm_parentflags; /* flags of the parent route */
181 int rtm_reserved; /* reserved field set to 0 */
182 int rtm_use; /* from rtentry */
183 u_int32_t rtm_inits; /* which metrics we are initializing */
184 struct rt_metrics rtm_rmx; /* metrics themselves */
185};
186
187
188#define RTM_VERSION 5 /* Up the ante and ignore older versions */
189
190/*
191 * Message types.
192 */
193#define RTM_ADD 0x1 /* Add Route */
194#define RTM_DELETE 0x2 /* Delete Route */
195#define RTM_CHANGE 0x3 /* Change Metrics or flags */
196#define RTM_GET 0x4 /* Report Metrics */
197#define RTM_LOSING 0x5 /* RTM_LOSING is no longer generated by xnu
198 * and is deprecated */
199#define RTM_REDIRECT 0x6 /* Told to use different route */
200#define RTM_MISS 0x7 /* Lookup failed on this address */
201#define RTM_LOCK 0x8 /* fix specified metrics */
202#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
203#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
204#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
205#define RTM_NEWADDR 0xc /* address being added to iface */
206#define RTM_DELADDR 0xd /* address being removed from iface */
207#define RTM_IFINFO 0xe /* iface going up/down etc. */
208#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
209#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
210#define RTM_IFINFO2 0x12 /* */
211#define RTM_NEWMADDR2 0x13 /* */
212#define RTM_GET2 0x14 /* */
213
214/*
215 * Bitmask values for rtm_inits and rmx_locks.
216 */
217#define RTV_MTU 0x1 /* init or lock _mtu */
218#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
219#define RTV_EXPIRE 0x4 /* init or lock _expire */
220#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
221#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
222#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
223#define RTV_RTT 0x40 /* init or lock _rtt */
224#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
225
226/*
227 * Bitmask values for rtm_addrs.
228 */
229#define RTA_DST 0x1 /* destination sockaddr present */
230#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
231#define RTA_NETMASK 0x4 /* netmask sockaddr present */
232#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
233#define RTA_IFP 0x10 /* interface name sockaddr present */
234#define RTA_IFA 0x20 /* interface addr sockaddr present */
235#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
236#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
237
238/*
239 * Index offsets for sockaddr array for alternate internal encoding.
240 */
241#define RTAX_DST 0 /* destination sockaddr present */
242#define RTAX_GATEWAY 1 /* gateway sockaddr present */
243#define RTAX_NETMASK 2 /* netmask sockaddr present */
244#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
245#define RTAX_IFP 4 /* interface name sockaddr present */
246#define RTAX_IFA 5 /* interface addr sockaddr present */
247#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
248#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
249#define RTAX_MAX 8 /* size of array to allocate */
250
251struct rt_addrinfo {
252 int rti_addrs;
253 struct sockaddr *rti_info[RTAX_MAX];
254};
255
256
257#endif /* _NET_ROUTE_H_ */
\ No newline at end of file
lib/libc/include/aarch64-macos-gnu/sys/_symbol_aliasing.h+12
...@@ -329,6 +329,12 @@...@@ -329,6 +329,12 @@
329#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_14_2(x)329#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_14_2(x)
330#endif330#endif
331331
332#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140300
333#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_14_3(x) x
334#else
335#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_14_3(x)
336#endif
337
332#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1000338#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1000
333#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_0(x) x339#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_0(x) x
334#else340#else
...@@ -531,4 +537,10 @@...@@ -531,4 +537,10 @@
531#define __DARWIN_ALIAS_STARTING_MAC___MAC_11_0(x) x537#define __DARWIN_ALIAS_STARTING_MAC___MAC_11_0(x) x
532#else538#else
533#define __DARWIN_ALIAS_STARTING_MAC___MAC_11_0(x)539#define __DARWIN_ALIAS_STARTING_MAC___MAC_11_0(x)
540#endif
541
542#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110100
543#define __DARWIN_ALIAS_STARTING_MAC___MAC_11_1(x) x
544#else
545#define __DARWIN_ALIAS_STARTING_MAC___MAC_11_1(x)
534#endif546#endif
\ No newline at end of file
lib/libc/include/aarch64-macos-gnu/sys/kern_control.h created+151
...@@ -0,0 +1,151 @@
1/*
2 * Copyright (c) 2000-2004, 2012-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*!
29 * @header kern_control.h
30 * This header defines an API to communicate between a kernel
31 * extension and a process outside of the kernel.
32 */
33
34#ifndef KPI_KERN_CONTROL_H
35#define KPI_KERN_CONTROL_H
36
37
38#include <sys/appleapiopts.h>
39#include <sys/_types/_u_char.h>
40#include <sys/_types/_u_int16_t.h>
41#include <sys/_types/_u_int32_t.h>
42
43/*
44 * Define Controller event subclass, and associated events.
45 * Subclass of KEV_SYSTEM_CLASS
46 */
47
48/*!
49 * @defined KEV_CTL_SUBCLASS
50 * @discussion The kernel event subclass for kernel control events.
51 */
52#define KEV_CTL_SUBCLASS 2
53
54/*!
55 * @defined KEV_CTL_REGISTERED
56 * @discussion The event code indicating a new controller was
57 * registered. The data portion will contain a ctl_event_data.
58 */
59#define KEV_CTL_REGISTERED 1 /* a new controller appears */
60
61/*!
62 * @defined KEV_CTL_DEREGISTERED
63 * @discussion The event code indicating a controller was unregistered.
64 * The data portion will contain a ctl_event_data.
65 */
66#define KEV_CTL_DEREGISTERED 2 /* a controller disappears */
67
68/*!
69 * @struct ctl_event_data
70 * @discussion This structure is used for KEV_CTL_SUBCLASS kernel
71 * events.
72 * @field ctl_id The kernel control id.
73 * @field ctl_unit The kernel control unit.
74 */
75struct ctl_event_data {
76 u_int32_t ctl_id; /* Kernel Controller ID */
77 u_int32_t ctl_unit;
78};
79
80/*
81 * Controls destined to the Controller Manager.
82 */
83
84/*!
85 * @defined CTLIOCGCOUNT
86 * @discussion The CTLIOCGCOUNT ioctl can be used to determine the
87 * number of kernel controllers registered.
88 */
89#define CTLIOCGCOUNT _IOR('N', 2, int) /* get number of control structures registered */
90
91/*!
92 * @defined CTLIOCGINFO
93 * @discussion The CTLIOCGINFO ioctl can be used to convert a kernel
94 * control name to a kernel control id.
95 */
96#define CTLIOCGINFO _IOWR('N', 3, struct ctl_info) /* get id from name */
97
98
99/*!
100 * @defined MAX_KCTL_NAME
101 * @discussion Kernel control names must be no longer than
102 * MAX_KCTL_NAME.
103 */
104#define MAX_KCTL_NAME 96
105
106/*
107 * Controls destined to the Controller Manager.
108 */
109
110/*!
111 * @struct ctl_info
112 * @discussion This structure is used with the CTLIOCGINFO ioctl to
113 * translate from a kernel control name to a control id.
114 * @field ctl_id The kernel control id, filled out upon return.
115 * @field ctl_name The kernel control name to find.
116 */
117struct ctl_info {
118 u_int32_t ctl_id; /* Kernel Controller ID */
119 char ctl_name[MAX_KCTL_NAME]; /* Kernel Controller Name (a C string) */
120};
121
122
123/*!
124 * @struct sockaddr_ctl
125 * @discussion The controller address structure is used to establish
126 * contact between a user client and a kernel controller. The
127 * sc_id/sc_unit uniquely identify each controller. sc_id is a
128 * unique identifier assigned to the controller. The identifier can
129 * be assigned by the system at registration time or be a 32-bit
130 * creator code obtained from Apple Computer. sc_unit is a unit
131 * number for this sc_id, and is privately used by the kernel
132 * controller to identify several instances of the controller.
133 * @field sc_len The length of the structure.
134 * @field sc_family AF_SYSTEM.
135 * @field ss_sysaddr AF_SYS_KERNCONTROL.
136 * @field sc_id Controller unique identifier.
137 * @field sc_unit Kernel controller private unit number.
138 * @field sc_reserved Reserved, must be set to zero.
139 */
140struct sockaddr_ctl {
141 u_char sc_len; /* depends on size of bundle ID string */
142 u_char sc_family; /* AF_SYSTEM */
143 u_int16_t ss_sysaddr; /* AF_SYS_KERNCONTROL */
144 u_int32_t sc_id; /* Controller unique identifier */
145 u_int32_t sc_unit; /* Developer private unit number */
146 u_int32_t sc_reserved[5];
147};
148
149
150
151#endif /* KPI_KERN_CONTROL_H */
\ No newline at end of file
lib/libc/include/aarch64-macos-gnu/sys/proc_info.h created+799
...@@ -0,0 +1,799 @@
1/*
2 * Copyright (c) 2005-2020 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _SYS_PROC_INFO_H
30#define _SYS_PROC_INFO_H
31
32#include <sys/cdefs.h>
33#include <sys/param.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <sys/mount.h>
37#include <sys/socket.h>
38#include <sys/un.h>
39#include <sys/kern_control.h>
40#include <sys/event.h>
41#include <net/if.h>
42#include <net/route.h>
43#include <netinet/in.h>
44#include <netinet/tcp.h>
45#include <mach/machine.h>
46#include <uuid/uuid.h>
47
48
49__BEGIN_DECLS
50
51
52#define PROC_ALL_PIDS 1
53#define PROC_PGRP_ONLY 2
54#define PROC_TTY_ONLY 3
55#define PROC_UID_ONLY 4
56#define PROC_RUID_ONLY 5
57#define PROC_PPID_ONLY 6
58#define PROC_KDBG_ONLY 7
59
60struct proc_bsdinfo {
61 uint32_t pbi_flags; /* 64bit; emulated etc */
62 uint32_t pbi_status;
63 uint32_t pbi_xstatus;
64 uint32_t pbi_pid;
65 uint32_t pbi_ppid;
66 uid_t pbi_uid;
67 gid_t pbi_gid;
68 uid_t pbi_ruid;
69 gid_t pbi_rgid;
70 uid_t pbi_svuid;
71 gid_t pbi_svgid;
72 uint32_t rfu_1; /* reserved */
73 char pbi_comm[MAXCOMLEN];
74 char pbi_name[2 * MAXCOMLEN]; /* empty if no name is registered */
75 uint32_t pbi_nfiles;
76 uint32_t pbi_pgid;
77 uint32_t pbi_pjobc;
78 uint32_t e_tdev; /* controlling tty dev */
79 uint32_t e_tpgid; /* tty process group id */
80 int32_t pbi_nice;
81 uint64_t pbi_start_tvsec;
82 uint64_t pbi_start_tvusec;
83};
84
85
86struct proc_bsdshortinfo {
87 uint32_t pbsi_pid; /* process id */
88 uint32_t pbsi_ppid; /* process parent id */
89 uint32_t pbsi_pgid; /* process perp id */
90 uint32_t pbsi_status; /* p_stat value, SZOMB, SRUN, etc */
91 char pbsi_comm[MAXCOMLEN]; /* upto 16 characters of process name */
92 uint32_t pbsi_flags; /* 64bit; emulated etc */
93 uid_t pbsi_uid; /* current uid on process */
94 gid_t pbsi_gid; /* current gid on process */
95 uid_t pbsi_ruid; /* current ruid on process */
96 gid_t pbsi_rgid; /* current tgid on process */
97 uid_t pbsi_svuid; /* current svuid on process */
98 gid_t pbsi_svgid; /* current svgid on process */
99 uint32_t pbsi_rfu; /* reserved for future use*/
100};
101
102
103
104
105/* pbi_flags values */
106#define PROC_FLAG_SYSTEM 1 /* System process */
107#define PROC_FLAG_TRACED 2 /* process currently being traced, possibly by gdb */
108#define PROC_FLAG_INEXIT 4 /* process is working its way in exit() */
109#define PROC_FLAG_PPWAIT 8
110#define PROC_FLAG_LP64 0x10 /* 64bit process */
111#define PROC_FLAG_SLEADER 0x20 /* The process is the session leader */
112#define PROC_FLAG_CTTY 0x40 /* process has a control tty */
113#define PROC_FLAG_CONTROLT 0x80 /* Has a controlling terminal */
114#define PROC_FLAG_THCWD 0x100 /* process has a thread with cwd */
115/* process control bits for resource starvation */
116#define PROC_FLAG_PC_THROTTLE 0x200 /* In resource starvation situations, this process is to be throttled */
117#define PROC_FLAG_PC_SUSP 0x400 /* In resource starvation situations, this process is to be suspended */
118#define PROC_FLAG_PC_KILL 0x600 /* In resource starvation situations, this process is to be terminated */
119#define PROC_FLAG_PC_MASK 0x600
120/* process action bits for resource starvation */
121#define PROC_FLAG_PA_THROTTLE 0x800 /* The process is currently throttled due to resource starvation */
122#define PROC_FLAG_PA_SUSP 0x1000 /* The process is currently suspended due to resource starvation */
123#define PROC_FLAG_PSUGID 0x2000 /* process has set privileges since last exec */
124#define PROC_FLAG_EXEC 0x4000 /* process has called exec */
125
126
127struct proc_taskinfo {
128 uint64_t pti_virtual_size; /* virtual memory size (bytes) */
129 uint64_t pti_resident_size; /* resident memory size (bytes) */
130 uint64_t pti_total_user; /* total time */
131 uint64_t pti_total_system;
132 uint64_t pti_threads_user; /* existing threads only */
133 uint64_t pti_threads_system;
134 int32_t pti_policy; /* default policy for new threads */
135 int32_t pti_faults; /* number of page faults */
136 int32_t pti_pageins; /* number of actual pageins */
137 int32_t pti_cow_faults; /* number of copy-on-write faults */
138 int32_t pti_messages_sent; /* number of messages sent */
139 int32_t pti_messages_received; /* number of messages received */
140 int32_t pti_syscalls_mach; /* number of mach system calls */
141 int32_t pti_syscalls_unix; /* number of unix system calls */
142 int32_t pti_csw; /* number of context switches */
143 int32_t pti_threadnum; /* number of threads in the task */
144 int32_t pti_numrunning; /* number of running threads */
145 int32_t pti_priority; /* task priority*/
146};
147
148struct proc_taskallinfo {
149 struct proc_bsdinfo pbsd;
150 struct proc_taskinfo ptinfo;
151};
152
153#define MAXTHREADNAMESIZE 64
154
155struct proc_threadinfo {
156 uint64_t pth_user_time; /* user run time */
157 uint64_t pth_system_time; /* system run time */
158 int32_t pth_cpu_usage; /* scaled cpu usage percentage */
159 int32_t pth_policy; /* scheduling policy in effect */
160 int32_t pth_run_state; /* run state (see below) */
161 int32_t pth_flags; /* various flags (see below) */
162 int32_t pth_sleep_time; /* number of seconds that thread */
163 int32_t pth_curpri; /* cur priority*/
164 int32_t pth_priority; /* priority*/
165 int32_t pth_maxpriority; /* max priority*/
166 char pth_name[MAXTHREADNAMESIZE]; /* thread name, if any */
167};
168
169struct proc_regioninfo {
170 uint32_t pri_protection;
171 uint32_t pri_max_protection;
172 uint32_t pri_inheritance;
173 uint32_t pri_flags; /* shared, external pager, is submap */
174 uint64_t pri_offset;
175 uint32_t pri_behavior;
176 uint32_t pri_user_wired_count;
177 uint32_t pri_user_tag;
178 uint32_t pri_pages_resident;
179 uint32_t pri_pages_shared_now_private;
180 uint32_t pri_pages_swapped_out;
181 uint32_t pri_pages_dirtied;
182 uint32_t pri_ref_count;
183 uint32_t pri_shadow_depth;
184 uint32_t pri_share_mode;
185 uint32_t pri_private_pages_resident;
186 uint32_t pri_shared_pages_resident;
187 uint32_t pri_obj_id;
188 uint32_t pri_depth;
189 uint64_t pri_address;
190 uint64_t pri_size;
191};
192
193#define PROC_REGION_SUBMAP 1
194#define PROC_REGION_SHARED 2
195
196#define SM_COW 1
197#define SM_PRIVATE 2
198#define SM_EMPTY 3
199#define SM_SHARED 4
200#define SM_TRUESHARED 5
201#define SM_PRIVATE_ALIASED 6
202#define SM_SHARED_ALIASED 7
203#define SM_LARGE_PAGE 8
204
205
206/*
207 * Thread run states (state field).
208 */
209
210#define TH_STATE_RUNNING 1 /* thread is running normally */
211#define TH_STATE_STOPPED 2 /* thread is stopped */
212#define TH_STATE_WAITING 3 /* thread is waiting normally */
213#define TH_STATE_UNINTERRUPTIBLE 4 /* thread is in an uninterruptible
214 * wait */
215#define TH_STATE_HALTED 5 /* thread is halted at a
216 * clean point */
217
218/*
219 * Thread flags (flags field).
220 */
221#define TH_FLAGS_SWAPPED 0x1 /* thread is swapped out */
222#define TH_FLAGS_IDLE 0x2 /* thread is an idle thread */
223
224
225struct proc_workqueueinfo {
226 uint32_t pwq_nthreads; /* total number of workqueue threads */
227 uint32_t pwq_runthreads; /* total number of running workqueue threads */
228 uint32_t pwq_blockedthreads; /* total number of blocked workqueue threads */
229 uint32_t pwq_state;
230};
231
232/*
233 * workqueue state (pwq_state field)
234 */
235#define WQ_EXCEEDED_CONSTRAINED_THREAD_LIMIT 0x1
236#define WQ_EXCEEDED_TOTAL_THREAD_LIMIT 0x2
237#define WQ_FLAGS_AVAILABLE 0x4
238
239struct proc_fileinfo {
240 uint32_t fi_openflags;
241 uint32_t fi_status;
242 off_t fi_offset;
243 int32_t fi_type;
244 uint32_t fi_guardflags;
245};
246
247/* stats flags in proc_fileinfo */
248#define PROC_FP_SHARED 1 /* shared by more than one fd */
249#define PROC_FP_CLEXEC 2 /* close on exec */
250#define PROC_FP_GUARDED 4 /* guarded fd */
251#define PROC_FP_CLFORK 8 /* close on fork */
252
253#define PROC_FI_GUARD_CLOSE (1u << 0)
254#define PROC_FI_GUARD_DUP (1u << 1)
255#define PROC_FI_GUARD_SOCKET_IPC (1u << 2)
256#define PROC_FI_GUARD_FILEPORT (1u << 3)
257
258struct proc_exitreasonbasicinfo {
259 uint32_t beri_namespace;
260 uint64_t beri_code;
261 uint64_t beri_flags;
262 uint32_t beri_reason_buf_size;
263} __attribute__((packed));
264
265struct proc_exitreasoninfo {
266 uint32_t eri_namespace;
267 uint64_t eri_code;
268 uint64_t eri_flags;
269 uint32_t eri_reason_buf_size;
270 uint64_t eri_kcd_buf;
271} __attribute__((packed));
272
273/*
274 * A copy of stat64 with static sized fields.
275 */
276struct vinfo_stat {
277 uint32_t vst_dev; /* [XSI] ID of device containing file */
278 uint16_t vst_mode; /* [XSI] Mode of file (see below) */
279 uint16_t vst_nlink; /* [XSI] Number of hard links */
280 uint64_t vst_ino; /* [XSI] File serial number */
281 uid_t vst_uid; /* [XSI] User ID of the file */
282 gid_t vst_gid; /* [XSI] Group ID of the file */
283 int64_t vst_atime; /* [XSI] Time of last access */
284 int64_t vst_atimensec; /* nsec of last access */
285 int64_t vst_mtime; /* [XSI] Last data modification time */
286 int64_t vst_mtimensec; /* last data modification nsec */
287 int64_t vst_ctime; /* [XSI] Time of last status change */
288 int64_t vst_ctimensec; /* nsec of last status change */
289 int64_t vst_birthtime; /* File creation time(birth) */
290 int64_t vst_birthtimensec; /* nsec of File creation time */
291 off_t vst_size; /* [XSI] file size, in bytes */
292 int64_t vst_blocks; /* [XSI] blocks allocated for file */
293 int32_t vst_blksize; /* [XSI] optimal blocksize for I/O */
294 uint32_t vst_flags; /* user defined flags for file */
295 uint32_t vst_gen; /* file generation number */
296 uint32_t vst_rdev; /* [XSI] Device ID */
297 int64_t vst_qspare[2]; /* RESERVED: DO NOT USE! */
298};
299
300struct vnode_info {
301 struct vinfo_stat vi_stat;
302 int vi_type;
303 int vi_pad;
304 fsid_t vi_fsid;
305};
306
307struct vnode_info_path {
308 struct vnode_info vip_vi;
309 char vip_path[MAXPATHLEN]; /* tail end of it */
310};
311
312struct vnode_fdinfo {
313 struct proc_fileinfo pfi;
314 struct vnode_info pvi;
315};
316
317struct vnode_fdinfowithpath {
318 struct proc_fileinfo pfi;
319 struct vnode_info_path pvip;
320};
321
322struct proc_regionwithpathinfo {
323 struct proc_regioninfo prp_prinfo;
324 struct vnode_info_path prp_vip;
325};
326
327struct proc_regionpath {
328 uint64_t prpo_addr;
329 uint64_t prpo_regionlength;
330 char prpo_path[MAXPATHLEN];
331};
332
333struct proc_vnodepathinfo {
334 struct vnode_info_path pvi_cdir;
335 struct vnode_info_path pvi_rdir;
336};
337
338struct proc_threadwithpathinfo {
339 struct proc_threadinfo pt;
340 struct vnode_info_path pvip;
341};
342
343/*
344 * Socket
345 */
346
347
348/*
349 * IPv4 and IPv6 Sockets
350 */
351
352#define INI_IPV4 0x1
353#define INI_IPV6 0x2
354
355struct in4in6_addr {
356 u_int32_t i46a_pad32[3];
357 struct in_addr i46a_addr4;
358};
359
360struct in_sockinfo {
361 int insi_fport; /* foreign port */
362 int insi_lport; /* local port */
363 uint64_t insi_gencnt; /* generation count of this instance */
364 uint32_t insi_flags; /* generic IP/datagram flags */
365 uint32_t insi_flow;
366
367 uint8_t insi_vflag; /* ini_IPV4 or ini_IPV6 */
368 uint8_t insi_ip_ttl; /* time to live proto */
369 uint32_t rfu_1; /* reserved */
370 /* protocol dependent part */
371 union {
372 struct in4in6_addr ina_46;
373 struct in6_addr ina_6;
374 } insi_faddr; /* foreign host table entry */
375 union {
376 struct in4in6_addr ina_46;
377 struct in6_addr ina_6;
378 } insi_laddr; /* local host table entry */
379 struct {
380 u_char in4_tos; /* type of service */
381 } insi_v4;
382 struct {
383 uint8_t in6_hlim;
384 int in6_cksum;
385 u_short in6_ifindex;
386 short in6_hops;
387 } insi_v6;
388};
389
390/*
391 * TCP Sockets
392 */
393
394#define TSI_T_REXMT 0 /* retransmit */
395#define TSI_T_PERSIST 1 /* retransmit persistence */
396#define TSI_T_KEEP 2 /* keep alive */
397#define TSI_T_2MSL 3 /* 2*msl quiet time timer */
398#define TSI_T_NTIMERS 4
399
400#define TSI_S_CLOSED 0 /* closed */
401#define TSI_S_LISTEN 1 /* listening for connection */
402#define TSI_S_SYN_SENT 2 /* active, have sent syn */
403#define TSI_S_SYN_RECEIVED 3 /* have send and received syn */
404#define TSI_S_ESTABLISHED 4 /* established */
405#define TSI_S__CLOSE_WAIT 5 /* rcvd fin, waiting for close */
406#define TSI_S_FIN_WAIT_1 6 /* have closed, sent fin */
407#define TSI_S_CLOSING 7 /* closed xchd FIN; await FIN ACK */
408#define TSI_S_LAST_ACK 8 /* had fin and close; await FIN ACK */
409#define TSI_S_FIN_WAIT_2 9 /* have closed, fin is acked */
410#define TSI_S_TIME_WAIT 10 /* in 2*msl quiet wait after close */
411#define TSI_S_RESERVED 11 /* pseudo state: reserved */
412
413struct tcp_sockinfo {
414 struct in_sockinfo tcpsi_ini;
415 int tcpsi_state;
416 int tcpsi_timer[TSI_T_NTIMERS];
417 int tcpsi_mss;
418 uint32_t tcpsi_flags;
419 uint32_t rfu_1; /* reserved */
420 uint64_t tcpsi_tp; /* opaque handle of TCP protocol control block */
421};
422
423/*
424 * Unix Domain Sockets
425 */
426
427
428struct un_sockinfo {
429 uint64_t unsi_conn_so; /* opaque handle of connected socket */
430 uint64_t unsi_conn_pcb; /* opaque handle of connected protocol control block */
431 union {
432 struct sockaddr_un ua_sun;
433 char ua_dummy[SOCK_MAXADDRLEN];
434 } unsi_addr; /* bound address */
435 union {
436 struct sockaddr_un ua_sun;
437 char ua_dummy[SOCK_MAXADDRLEN];
438 } unsi_caddr; /* address of socket connected to */
439};
440
441/*
442 * PF_NDRV Sockets
443 */
444
445struct ndrv_info {
446 uint32_t ndrvsi_if_family;
447 uint32_t ndrvsi_if_unit;
448 char ndrvsi_if_name[IF_NAMESIZE];
449};
450
451/*
452 * Kernel Event Sockets
453 */
454
455struct kern_event_info {
456 uint32_t kesi_vendor_code_filter;
457 uint32_t kesi_class_filter;
458 uint32_t kesi_subclass_filter;
459};
460
461/*
462 * Kernel Control Sockets
463 */
464
465struct kern_ctl_info {
466 uint32_t kcsi_id;
467 uint32_t kcsi_reg_unit;
468 uint32_t kcsi_flags; /* support flags */
469 uint32_t kcsi_recvbufsize; /* request more than the default buffer size */
470 uint32_t kcsi_sendbufsize; /* request more than the default buffer size */
471 uint32_t kcsi_unit;
472 char kcsi_name[MAX_KCTL_NAME]; /* unique nke identifier, provided by DTS */
473};
474
475/*
476 * VSock Sockets
477 */
478
479struct vsock_sockinfo {
480 uint32_t local_cid;
481 uint32_t local_port;
482 uint32_t remote_cid;
483 uint32_t remote_port;
484};
485
486/* soi_state */
487
488#define SOI_S_NOFDREF 0x0001 /* no file table ref any more */
489#define SOI_S_ISCONNECTED 0x0002 /* socket connected to a peer */
490#define SOI_S_ISCONNECTING 0x0004 /* in process of connecting to peer */
491#define SOI_S_ISDISCONNECTING 0x0008 /* in process of disconnecting */
492#define SOI_S_CANTSENDMORE 0x0010 /* can't send more data to peer */
493#define SOI_S_CANTRCVMORE 0x0020 /* can't receive more data from peer */
494#define SOI_S_RCVATMARK 0x0040 /* at mark on input */
495#define SOI_S_PRIV 0x0080 /* privileged for broadcast, raw... */
496#define SOI_S_NBIO 0x0100 /* non-blocking ops */
497#define SOI_S_ASYNC 0x0200 /* async i/o notify */
498#define SOI_S_INCOMP 0x0800 /* Unaccepted, incomplete connection */
499#define SOI_S_COMP 0x1000 /* unaccepted, complete connection */
500#define SOI_S_ISDISCONNECTED 0x2000 /* socket disconnected from peer */
501#define SOI_S_DRAINING 0x4000 /* close waiting for blocked system calls to drain */
502
503struct sockbuf_info {
504 uint32_t sbi_cc;
505 uint32_t sbi_hiwat; /* SO_RCVBUF, SO_SNDBUF */
506 uint32_t sbi_mbcnt;
507 uint32_t sbi_mbmax;
508 uint32_t sbi_lowat;
509 short sbi_flags;
510 short sbi_timeo;
511};
512
513enum {
514 SOCKINFO_GENERIC = 0,
515 SOCKINFO_IN = 1,
516 SOCKINFO_TCP = 2,
517 SOCKINFO_UN = 3,
518 SOCKINFO_NDRV = 4,
519 SOCKINFO_KERN_EVENT = 5,
520 SOCKINFO_KERN_CTL = 6,
521 SOCKINFO_VSOCK = 7,
522};
523
524struct socket_info {
525 struct vinfo_stat soi_stat;
526 uint64_t soi_so; /* opaque handle of socket */
527 uint64_t soi_pcb; /* opaque handle of protocol control block */
528 int soi_type;
529 int soi_protocol;
530 int soi_family;
531 short soi_options;
532 short soi_linger;
533 short soi_state;
534 short soi_qlen;
535 short soi_incqlen;
536 short soi_qlimit;
537 short soi_timeo;
538 u_short soi_error;
539 uint32_t soi_oobmark;
540 struct sockbuf_info soi_rcv;
541 struct sockbuf_info soi_snd;
542 int soi_kind;
543 uint32_t rfu_1; /* reserved */
544 union {
545 struct in_sockinfo pri_in; /* SOCKINFO_IN */
546 struct tcp_sockinfo pri_tcp; /* SOCKINFO_TCP */
547 struct un_sockinfo pri_un; /* SOCKINFO_UN */
548 struct ndrv_info pri_ndrv; /* SOCKINFO_NDRV */
549 struct kern_event_info pri_kern_event; /* SOCKINFO_KERN_EVENT */
550 struct kern_ctl_info pri_kern_ctl; /* SOCKINFO_KERN_CTL */
551 struct vsock_sockinfo pri_vsock; /* SOCKINFO_VSOCK */
552 } soi_proto;
553};
554
555struct socket_fdinfo {
556 struct proc_fileinfo pfi;
557 struct socket_info psi;
558};
559
560
561
562struct psem_info {
563 struct vinfo_stat psem_stat;
564 char psem_name[MAXPATHLEN];
565};
566
567struct psem_fdinfo {
568 struct proc_fileinfo pfi;
569 struct psem_info pseminfo;
570};
571
572
573
574struct pshm_info {
575 struct vinfo_stat pshm_stat;
576 uint64_t pshm_mappaddr;
577 char pshm_name[MAXPATHLEN];
578};
579
580struct pshm_fdinfo {
581 struct proc_fileinfo pfi;
582 struct pshm_info pshminfo;
583};
584
585
586struct pipe_info {
587 struct vinfo_stat pipe_stat;
588 uint64_t pipe_handle;
589 uint64_t pipe_peerhandle;
590 int pipe_status;
591 int rfu_1; /* reserved */
592};
593
594struct pipe_fdinfo {
595 struct proc_fileinfo pfi;
596 struct pipe_info pipeinfo;
597};
598
599
600struct kqueue_info {
601 struct vinfo_stat kq_stat;
602 uint32_t kq_state;
603 uint32_t rfu_1; /* reserved */
604};
605
606struct kqueue_dyninfo {
607 struct kqueue_info kqdi_info;
608 uint64_t kqdi_servicer;
609 uint64_t kqdi_owner;
610 uint32_t kqdi_sync_waiters;
611 uint8_t kqdi_sync_waiter_qos;
612 uint8_t kqdi_async_qos;
613 uint16_t kqdi_request_state;
614 uint8_t kqdi_events_qos;
615 uint8_t kqdi_pri;
616 uint8_t kqdi_pol;
617 uint8_t kqdi_cpupercent;
618 uint8_t _kqdi_reserved0[4];
619 uint64_t _kqdi_reserved1[4];
620};
621
622/* keep in sync with KQ_* in sys/eventvar.h */
623#define PROC_KQUEUE_SELECT 0x01
624#define PROC_KQUEUE_SLEEP 0x02
625#define PROC_KQUEUE_32 0x08
626#define PROC_KQUEUE_64 0x10
627#define PROC_KQUEUE_QOS 0x20
628
629
630struct kqueue_fdinfo {
631 struct proc_fileinfo pfi;
632 struct kqueue_info kqueueinfo;
633};
634
635struct appletalk_info {
636 struct vinfo_stat atalk_stat;
637};
638
639struct appletalk_fdinfo {
640 struct proc_fileinfo pfi;
641 struct appletalk_info appletalkinfo;
642};
643
644typedef uint64_t proc_info_udata_t;
645
646/* defns of process file desc type */
647#define PROX_FDTYPE_ATALK 0
648#define PROX_FDTYPE_VNODE 1
649#define PROX_FDTYPE_SOCKET 2
650#define PROX_FDTYPE_PSHM 3
651#define PROX_FDTYPE_PSEM 4
652#define PROX_FDTYPE_KQUEUE 5
653#define PROX_FDTYPE_PIPE 6
654#define PROX_FDTYPE_FSEVENTS 7
655#define PROX_FDTYPE_NETPOLICY 9
656
657struct proc_fdinfo {
658 int32_t proc_fd;
659 uint32_t proc_fdtype;
660};
661
662struct proc_fileportinfo {
663 uint32_t proc_fileport;
664 uint32_t proc_fdtype;
665};
666
667
668/* Flavors for proc_pidinfo() */
669#define PROC_PIDLISTFDS 1
670#define PROC_PIDLISTFD_SIZE (sizeof(struct proc_fdinfo))
671
672#define PROC_PIDTASKALLINFO 2
673#define PROC_PIDTASKALLINFO_SIZE (sizeof(struct proc_taskallinfo))
674
675#define PROC_PIDTBSDINFO 3
676#define PROC_PIDTBSDINFO_SIZE (sizeof(struct proc_bsdinfo))
677
678#define PROC_PIDTASKINFO 4
679#define PROC_PIDTASKINFO_SIZE (sizeof(struct proc_taskinfo))
680
681#define PROC_PIDTHREADINFO 5
682#define PROC_PIDTHREADINFO_SIZE (sizeof(struct proc_threadinfo))
683
684#define PROC_PIDLISTTHREADS 6
685#define PROC_PIDLISTTHREADS_SIZE (2* sizeof(uint32_t))
686
687#define PROC_PIDREGIONINFO 7
688#define PROC_PIDREGIONINFO_SIZE (sizeof(struct proc_regioninfo))
689
690#define PROC_PIDREGIONPATHINFO 8
691#define PROC_PIDREGIONPATHINFO_SIZE (sizeof(struct proc_regionwithpathinfo))
692
693#define PROC_PIDVNODEPATHINFO 9
694#define PROC_PIDVNODEPATHINFO_SIZE (sizeof(struct proc_vnodepathinfo))
695
696#define PROC_PIDTHREADPATHINFO 10
697#define PROC_PIDTHREADPATHINFO_SIZE (sizeof(struct proc_threadwithpathinfo))
698
699#define PROC_PIDPATHINFO 11
700#define PROC_PIDPATHINFO_SIZE (MAXPATHLEN)
701#define PROC_PIDPATHINFO_MAXSIZE (4*MAXPATHLEN)
702
703#define PROC_PIDWORKQUEUEINFO 12
704#define PROC_PIDWORKQUEUEINFO_SIZE (sizeof(struct proc_workqueueinfo))
705
706#define PROC_PIDT_SHORTBSDINFO 13
707#define PROC_PIDT_SHORTBSDINFO_SIZE (sizeof(struct proc_bsdshortinfo))
708
709#define PROC_PIDLISTFILEPORTS 14
710#define PROC_PIDLISTFILEPORTS_SIZE (sizeof(struct proc_fileportinfo))
711
712#define PROC_PIDTHREADID64INFO 15
713#define PROC_PIDTHREADID64INFO_SIZE (sizeof(struct proc_threadinfo))
714
715#define PROC_PID_RUSAGE 16
716#define PROC_PID_RUSAGE_SIZE 0
717
718/* Flavors for proc_pidfdinfo */
719
720#define PROC_PIDFDVNODEINFO 1
721#define PROC_PIDFDVNODEINFO_SIZE (sizeof(struct vnode_fdinfo))
722
723#define PROC_PIDFDVNODEPATHINFO 2
724#define PROC_PIDFDVNODEPATHINFO_SIZE (sizeof(struct vnode_fdinfowithpath))
725
726#define PROC_PIDFDSOCKETINFO 3
727#define PROC_PIDFDSOCKETINFO_SIZE (sizeof(struct socket_fdinfo))
728
729#define PROC_PIDFDPSEMINFO 4
730#define PROC_PIDFDPSEMINFO_SIZE (sizeof(struct psem_fdinfo))
731
732#define PROC_PIDFDPSHMINFO 5
733#define PROC_PIDFDPSHMINFO_SIZE (sizeof(struct pshm_fdinfo))
734
735#define PROC_PIDFDPIPEINFO 6
736#define PROC_PIDFDPIPEINFO_SIZE (sizeof(struct pipe_fdinfo))
737
738#define PROC_PIDFDKQUEUEINFO 7
739#define PROC_PIDFDKQUEUEINFO_SIZE (sizeof(struct kqueue_fdinfo))
740
741#define PROC_PIDFDATALKINFO 8
742#define PROC_PIDFDATALKINFO_SIZE (sizeof(struct appletalk_fdinfo))
743
744
745
746/* Flavors for proc_pidfileportinfo */
747
748#define PROC_PIDFILEPORTVNODEPATHINFO 2 /* out: vnode_fdinfowithpath */
749#define PROC_PIDFILEPORTVNODEPATHINFO_SIZE \
750 PROC_PIDFDVNODEPATHINFO_SIZE
751
752#define PROC_PIDFILEPORTSOCKETINFO 3 /* out: socket_fdinfo */
753#define PROC_PIDFILEPORTSOCKETINFO_SIZE PROC_PIDFDSOCKETINFO_SIZE
754
755#define PROC_PIDFILEPORTPSHMINFO 5 /* out: pshm_fdinfo */
756#define PROC_PIDFILEPORTPSHMINFO_SIZE PROC_PIDFDPSHMINFO_SIZE
757
758#define PROC_PIDFILEPORTPIPEINFO 6 /* out: pipe_fdinfo */
759#define PROC_PIDFILEPORTPIPEINFO_SIZE PROC_PIDFDPIPEINFO_SIZE
760
761/* used for proc_setcontrol */
762#define PROC_SELFSET_PCONTROL 1
763
764#define PROC_SELFSET_THREADNAME 2
765#define PROC_SELFSET_THREADNAME_SIZE (MAXTHREADNAMESIZE -1)
766
767#define PROC_SELFSET_VMRSRCOWNER 3
768
769#define PROC_SELFSET_DELAYIDLESLEEP 4
770
771/* used for proc_dirtycontrol */
772#define PROC_DIRTYCONTROL_TRACK 1
773#define PROC_DIRTYCONTROL_SET 2
774#define PROC_DIRTYCONTROL_GET 3
775#define PROC_DIRTYCONTROL_CLEAR 4
776
777/* proc_track_dirty() flags */
778#define PROC_DIRTY_TRACK 0x1
779#define PROC_DIRTY_ALLOW_IDLE_EXIT 0x2
780#define PROC_DIRTY_DEFER 0x4
781#define PROC_DIRTY_LAUNCH_IN_PROGRESS 0x8
782#define PROC_DIRTY_DEFER_ALWAYS 0x10
783
784/* proc_get_dirty() flags */
785#define PROC_DIRTY_TRACKED 0x1
786#define PROC_DIRTY_ALLOWS_IDLE_EXIT 0x2
787#define PROC_DIRTY_IS_DIRTY 0x4
788#define PROC_DIRTY_LAUNCH_IS_IN_PROGRESS 0x8
789
790/* Flavors for proc_udata_info */
791#define PROC_UDATA_INFO_GET 1
792#define PROC_UDATA_INFO_SET 2
793
794
795
796
797__END_DECLS
798
799#endif /*_SYS_PROC_INFO_H */
\ No newline at end of file
lib/libc/include/aarch64-macos-gnu/sys/ucontext.h created+41
...@@ -0,0 +1,41 @@
1/*
2 * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _SYS_UCONTEXT_H_
30#define _SYS_UCONTEXT_H_
31
32#include <sys/cdefs.h>
33#include <sys/_types.h>
34
35#include <machine/_mcontext.h>
36#include <sys/_types/_ucontext.h>
37
38#include <sys/_types/_sigset_t.h>
39
40
41#endif /* _SYS_UCONTEXT_H_ */
\ No newline at end of file
lib/libc/include/aarch64-macos-gnu/ucontext.h created+54
...@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 2002, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * These routines are DEPRECATED and should not be used.
26 */
27#ifndef _UCONTEXT_H_
28#define _UCONTEXT_H_
29
30#include <sys/cdefs.h>
31
32#ifdef _XOPEN_SOURCE
33#include <sys/ucontext.h>
34#include <Availability.h>
35
36__BEGIN_DECLS
37__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
38int getcontext(ucontext_t *);
39
40__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
41void makecontext(ucontext_t *, void (*)(), int, ...);
42
43__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
44int setcontext(const ucontext_t *);
45
46__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
47int swapcontext(ucontext_t * __restrict, const ucontext_t * __restrict);
48
49__END_DECLS
50#else /* !_XOPEN_SOURCE */
51#error The deprecated ucontext routines require _XOPEN_SOURCE to be defined
52#endif /* _XOPEN_SOURCE */
53
54#endif /* _UCONTEXT_H_ */
\ No newline at end of file
lib/libc/include/x86_64-macos-gnu/libproc.h created+187
...@@ -0,0 +1,187 @@
1/*
2 * Copyright (c) 2006, 2007, 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#ifndef _LIBPROC_H_
24#define _LIBPROC_H_
25
26#include <sys/cdefs.h>
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/mount.h>
31#include <sys/resource.h>
32#include <stdint.h>
33#include <stdbool.h>
34#include <mach/message.h> /* for audit_token_t */
35
36#include <sys/proc_info.h>
37
38#include <Availability.h>
39#include <os/availability.h>
40
41/*
42 * This header file contains private interfaces to obtain process information.
43 * These interfaces are subject to change in future releases.
44 */
45
46/*!
47 * @define PROC_LISTPIDSPATH_PATH_IS_VOLUME
48 * @discussion This flag indicates that all processes that hold open
49 * file references on the volume associated with the specified
50 * path should be returned.
51 */
52#define PROC_LISTPIDSPATH_PATH_IS_VOLUME 1
53
54
55/*!
56 * @define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY
57 * @discussion This flag indicates that file references that were opened
58 * with the O_EVTONLY flag should be excluded from the matching
59 * criteria.
60 */
61#define PROC_LISTPIDSPATH_EXCLUDE_EVTONLY 2
62
63__BEGIN_DECLS
64
65
66/*!
67 * @function proc_listpidspath
68 * @discussion A function which will search through the current
69 * processes looking for open file references which match
70 * a specified path or volume.
71 * @param type types of processes to be searched (see proc_listpids)
72 * @param typeinfo adjunct information for type
73 * @param path file or volume path
74 * @param pathflags flags to control which files should be considered
75 * during the process search.
76 * @param buffer a C array of int-sized values to be filled with
77 * process identifiers that hold an open file reference
78 * matching the specified path or volume. Pass NULL to
79 * obtain the minimum buffer size needed to hold the
80 * currently active processes.
81 * @param buffersize the size (in bytes) of the provided buffer.
82 * @result the number of bytes of data returned in the provided buffer;
83 * -1 if an error was encountered;
84 */
85int proc_listpidspath(uint32_t type,
86 uint32_t typeinfo,
87 const char *path,
88 uint32_t pathflags,
89 void *buffer,
90 int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
91
92int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
93int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
94int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
95int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1);
96int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
97int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
98int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
99int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
100int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
101int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
102int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
103int proc_pidpath_audittoken(audit_token_t *audittoken, void * buffer, uint32_t buffersize) API_AVAILABLE(macos(11.0), ios(14.0), watchos(7.0), tvos(14.0));
104int proc_libversion(int *major, int * minor) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
105
106/*
107 * Return resource usage information for the given pid, which can be a live process or a zombie.
108 *
109 * Returns 0 on success; or -1 on failure, with errno set to indicate the specific error.
110 */
111int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
112
113/*
114 * A process can use the following api to set its own process control
115 * state on resoure starvation. The argument can have one of the PROC_SETPC_XX values
116 */
117#define PROC_SETPC_NONE 0
118#define PROC_SETPC_THROTTLEMEM 1
119#define PROC_SETPC_SUSPEND 2
120#define PROC_SETPC_TERMINATE 3
121
122int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
123int proc_setpcontrol(const int control);
124
125int proc_track_dirty(pid_t pid, uint32_t flags);
126int proc_set_dirty(pid_t pid, bool dirty);
127int proc_get_dirty(pid_t pid, uint32_t *flags);
128int proc_clear_dirty(pid_t pid, uint32_t flags);
129
130int proc_terminate(pid_t pid, int *sig);
131
132/*
133 * NO_SMT means that on an SMT CPU, this thread must be scheduled alone,
134 * with the paired CPU idle.
135 *
136 * Set NO_SMT on the current proc (all existing and future threads)
137 * This attribute is inherited on fork and exec
138 */
139int proc_set_no_smt(void) __API_AVAILABLE(macos(11.0));
140
141/* Set NO_SMT on the current thread */
142int proc_setthread_no_smt(void) __API_AVAILABLE(macos(11.0));
143
144/*
145 * CPU Security Mitigation APIs
146 *
147 * Set CPU security mitigation on the current proc (all existing and future threads)
148 * This attribute is inherited on fork and exec
149 */
150int proc_set_csm(uint32_t flags) __API_AVAILABLE(macos(11.0));
151
152/* Set CPU security mitigation on the current thread */
153int proc_setthread_csm(uint32_t flags) __API_AVAILABLE(macos(11.0));
154
155/*
156 * flags for CPU Security Mitigation APIs
157 * PROC_CSM_ALL should be used in most cases,
158 * the individual flags are provided only for performance evaluation etc
159 */
160#define PROC_CSM_ALL 0x0001 /* Set all available mitigations */
161#define PROC_CSM_NOSMT 0x0002 /* Set NO_SMT - see above */
162#define PROC_CSM_TECS 0x0004 /* Execute VERW on every return to user mode */
163
164#ifdef PRIVATE
165#include <sys/event.h>
166/*
167 * Enumerate potential userspace pointers embedded in kernel data structures.
168 * Currently inspects kqueues only.
169 *
170 * NOTE: returned "pointers" are opaque user-supplied values and thus not
171 * guaranteed to address valid objects or be pointers at all.
172 *
173 * Returns the number of pointers found (which may exceed buffersize), or -1 on
174 * failure and errno set appropriately.
175 */
176int proc_list_uptrs(pid_t pid, uint64_t *buffer, uint32_t buffersize);
177
178int proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz);
179int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer,
180 int buffersize);
181#endif /* PRIVATE */
182
183int proc_udata_info(int pid, int flavor, void *buffer, int buffersize);
184
185__END_DECLS
186
187#endif /*_LIBPROC_H_ */
lib/libc/include/x86_64-macos-gnu/net/route.h created+257
...@@ -0,0 +1,257 @@
1/*
2 * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright (c) 1980, 1986, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)route.h 8.3 (Berkeley) 4/19/94
61 * $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
62 */
63
64#ifndef _NET_ROUTE_H_
65#define _NET_ROUTE_H_
66#include <sys/appleapiopts.h>
67#include <stdint.h>
68#include <sys/types.h>
69#include <sys/socket.h>
70
71/*
72 * These numbers are used by reliable protocols for determining
73 * retransmission behavior and are included in the routing structure.
74 */
75struct rt_metrics {
76 u_int32_t rmx_locks; /* Kernel leaves these values alone */
77 u_int32_t rmx_mtu; /* MTU for this path */
78 u_int32_t rmx_hopcount; /* max hops expected */
79 int32_t rmx_expire; /* lifetime for route, e.g. redirect */
80 u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */
81 u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */
82 u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */
83 u_int32_t rmx_rtt; /* estimated round trip time */
84 u_int32_t rmx_rttvar; /* estimated rtt variance */
85 u_int32_t rmx_pksent; /* packets sent using this route */
86 u_int32_t rmx_state; /* route state */
87 u_int32_t rmx_filler[3]; /* will be used for TCP's peer-MSS cache */
88};
89
90/*
91 * rmx_rtt and rmx_rttvar are stored as microseconds;
92 */
93#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
94
95
96
97#define RTF_UP 0x1 /* route usable */
98#define RTF_GATEWAY 0x2 /* destination is a gateway */
99#define RTF_HOST 0x4 /* host entry (net otherwise) */
100#define RTF_REJECT 0x8 /* host or net unreachable */
101#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
102#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
103#define RTF_DONE 0x40 /* message confirmed */
104#define RTF_DELCLONE 0x80 /* delete cloned route */
105#define RTF_CLONING 0x100 /* generate new routes on use */
106#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
107#define RTF_LLINFO 0x400 /* DEPRECATED - exists ONLY for backward
108 * compatibility */
109#define RTF_LLDATA 0x400 /* used by apps to add/del L2 entries */
110#define RTF_STATIC 0x800 /* manually added */
111#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
112#define RTF_NOIFREF 0x2000 /* not eligible for RTF_IFREF */
113#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
114#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
115
116#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
117#define RTF_WASCLONED 0x20000 /* route generated through cloning */
118#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
119 /* 0x80000 unused */
120#define RTF_PINNED 0x100000 /* future use */
121#define RTF_LOCAL 0x200000 /* route represents a local address */
122#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
123#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
124#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */
125#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */
126#define RTF_IFREF 0x4000000 /* route holds a ref to interface */
127#define RTF_PROXY 0x8000000 /* proxying, no interface scope */
128#define RTF_ROUTER 0x10000000 /* host is a router */
129#define RTF_DEAD 0x20000000 /* Route entry is being freed */
130 /* 0x40000000 and up unassigned */
131
132#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
133#define RTF_BITS \
134 "\020\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" \
135 "\10DELCLONE\11CLONING\12XRESOLVE\13LLINFO\14STATIC\15BLACKHOLE" \
136 "\16NOIFREF\17PROTO2\20PROTO1\21PRCLONING\22WASCLONED\23PROTO3" \
137 "\25PINNED\26LOCAL\27BROADCAST\30MULTICAST\31IFSCOPE\32CONDEMNED" \
138 "\33IFREF\34PROXY\35ROUTER"
139
140#define IS_DIRECT_HOSTROUTE(rt) \
141 (((rt)->rt_flags & (RTF_HOST | RTF_GATEWAY)) == RTF_HOST)
142/*
143 * Routing statistics.
144 */
145struct rtstat {
146 short rts_badredirect; /* bogus redirect calls */
147 short rts_dynamic; /* routes created by redirects */
148 short rts_newgateway; /* routes modified by redirects */
149 short rts_unreach; /* lookups which failed */
150 short rts_wildcard; /* lookups satisfied by a wildcard */
151 short rts_badrtgwroute; /* route to gateway is not direct */
152};
153
154/*
155 * Structures for routing messages.
156 */
157struct rt_msghdr {
158 u_short rtm_msglen; /* to skip over non-understood messages */
159 u_char rtm_version; /* future binary compatibility */
160 u_char rtm_type; /* message type */
161 u_short rtm_index; /* index for associated ifp */
162 int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
163 int rtm_addrs; /* bitmask identifying sockaddrs in msg */
164 pid_t rtm_pid; /* identify sender */
165 int rtm_seq; /* for sender to identify action */
166 int rtm_errno; /* why failed */
167 int rtm_use; /* from rtentry */
168 u_int32_t rtm_inits; /* which metrics we are initializing */
169 struct rt_metrics rtm_rmx; /* metrics themselves */
170};
171
172struct rt_msghdr2 {
173 u_short rtm_msglen; /* to skip over non-understood messages */
174 u_char rtm_version; /* future binary compatibility */
175 u_char rtm_type; /* message type */
176 u_short rtm_index; /* index for associated ifp */
177 int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
178 int rtm_addrs; /* bitmask identifying sockaddrs in msg */
179 int32_t rtm_refcnt; /* reference count */
180 int rtm_parentflags; /* flags of the parent route */
181 int rtm_reserved; /* reserved field set to 0 */
182 int rtm_use; /* from rtentry */
183 u_int32_t rtm_inits; /* which metrics we are initializing */
184 struct rt_metrics rtm_rmx; /* metrics themselves */
185};
186
187
188#define RTM_VERSION 5 /* Up the ante and ignore older versions */
189
190/*
191 * Message types.
192 */
193#define RTM_ADD 0x1 /* Add Route */
194#define RTM_DELETE 0x2 /* Delete Route */
195#define RTM_CHANGE 0x3 /* Change Metrics or flags */
196#define RTM_GET 0x4 /* Report Metrics */
197#define RTM_LOSING 0x5 /* RTM_LOSING is no longer generated by xnu
198 * and is deprecated */
199#define RTM_REDIRECT 0x6 /* Told to use different route */
200#define RTM_MISS 0x7 /* Lookup failed on this address */
201#define RTM_LOCK 0x8 /* fix specified metrics */
202#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
203#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
204#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
205#define RTM_NEWADDR 0xc /* address being added to iface */
206#define RTM_DELADDR 0xd /* address being removed from iface */
207#define RTM_IFINFO 0xe /* iface going up/down etc. */
208#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
209#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
210#define RTM_IFINFO2 0x12 /* */
211#define RTM_NEWMADDR2 0x13 /* */
212#define RTM_GET2 0x14 /* */
213
214/*
215 * Bitmask values for rtm_inits and rmx_locks.
216 */
217#define RTV_MTU 0x1 /* init or lock _mtu */
218#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
219#define RTV_EXPIRE 0x4 /* init or lock _expire */
220#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
221#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
222#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
223#define RTV_RTT 0x40 /* init or lock _rtt */
224#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
225
226/*
227 * Bitmask values for rtm_addrs.
228 */
229#define RTA_DST 0x1 /* destination sockaddr present */
230#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
231#define RTA_NETMASK 0x4 /* netmask sockaddr present */
232#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
233#define RTA_IFP 0x10 /* interface name sockaddr present */
234#define RTA_IFA 0x20 /* interface addr sockaddr present */
235#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
236#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
237
238/*
239 * Index offsets for sockaddr array for alternate internal encoding.
240 */
241#define RTAX_DST 0 /* destination sockaddr present */
242#define RTAX_GATEWAY 1 /* gateway sockaddr present */
243#define RTAX_NETMASK 2 /* netmask sockaddr present */
244#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
245#define RTAX_IFP 4 /* interface name sockaddr present */
246#define RTAX_IFA 5 /* interface addr sockaddr present */
247#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
248#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
249#define RTAX_MAX 8 /* size of array to allocate */
250
251struct rt_addrinfo {
252 int rti_addrs;
253 struct sockaddr *rti_info[RTAX_MAX];
254};
255
256
257#endif /* _NET_ROUTE_H_ */
lib/libc/include/x86_64-macos-gnu/os/clock.h created+18
...@@ -0,0 +1,18 @@
1#ifndef __OS_CLOCK__
2#define __OS_CLOCK__
3
4#include <os/base.h>
5#include <stdint.h>
6
7/*
8 * @typedef os_clockid_t
9 *
10 * @abstract
11 * Describes the kind of clock that the workgroup timestamp parameters are
12 * specified in
13 */
14OS_ENUM(os_clockid, uint32_t,
15 OS_CLOCK_MACH_ABSOLUTE_TIME = 32,
16);
17
18#endif /* __OS_CLOCK__ */
lib/libc/include/x86_64-macos-gnu/os/workgroup.h created+37
...@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __OS_WORKGROUP__
22#define __OS_WORKGROUP__
23
24#ifndef __DISPATCH_BUILDING_DISPATCH__
25#ifndef __OS_WORKGROUP_INDIRECT__
26#define __OS_WORKGROUP_INDIRECT__
27#endif /* __OS_WORKGROUP_INDIRECT__ */
28
29#include <os/workgroup_base.h>
30#include <os/workgroup_object.h>
31#include <os/workgroup_interval.h>
32#include <os/workgroup_parallel.h>
33
34#undef __OS_WORKGROUP_INDIRECT__
35#endif /* __DISPATCH_BUILDING_DISPATCH__ */
36
37#endif /* __OS_WORKGROUP__ */
lib/libc/include/x86_64-macos-gnu/os/workgroup_base.h created+78
...@@ -0,0 +1,78 @@
1#ifndef __OS_WORKGROUP_BASE__
2#define __OS_WORKGROUP_BASE__
3
4#ifndef __OS_WORKGROUP_INDIRECT__
5#error "Please #include <os/workgroup.h> instead of this file directly."
6#endif
7
8#include <sys/types.h>
9#include <stddef.h>
10#include <stdint.h>
11#include <stdbool.h>
12#include <string.h>
13#include <stdlib.h>
14
15#include <mach/port.h>
16
17#include <Availability.h>
18#include <os/base.h>
19#include <os/object.h>
20#include <os/clock.h>
21
22#if __has_feature(assume_nonnull)
23#define OS_WORKGROUP_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
24#define OS_WORKGROUP_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
25#else
26#define OS_WORKGROUP_ASSUME_NONNULL_BEGIN
27#define OS_WORKGROUP_ASSUME_NONNULL_END
28#endif
29#define OS_WORKGROUP_WARN_RESULT __attribute__((__warn_unused_result__))
30#define OS_WORKGROUP_EXPORT OS_EXPORT
31#define OS_WORKGROUP_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED
32
33#define OS_WORKGROUP_DECL(name, swift_name) \
34 OS_SWIFT_NAME(swift_name) \
35 OS_OBJECT_SHOW_CLASS(name, OS_OBJECT_CLASS(object))
36
37#if OS_OBJECT_USE_OBJC
38#define OS_WORKGROUP_SUBCLASS_DECL_PROTO(name, swift_name, ...) \
39 OS_SWIFT_NAME(swift_name) \
40 OS_OBJECT_DECL_PROTOCOL(name ## __VA_ARGS__ )
41#else
42#define OS_WORKGROUP_SUBCLASS_DECL_PROTO(name, swift_name, ...)
43#endif
44
45#define OS_WORKGROUP_SUBCLASS_DECL(name, super, swift_name, ...) \
46 OS_SWIFT_NAME(swift_name) \
47 OS_OBJECT_SHOW_SUBCLASS(name, super, name, ## __VA_ARGS__)
48
49#if defined(__LP64__)
50#define __OS_WORKGROUP_ATTR_SIZE__ 60
51#define __OS_WORKGROUP_INTERVAL_DATA_SIZE__ 56
52#define __OS_WORKGROUP_JOIN_TOKEN_SIZE__ 36
53#else
54#define __OS_WORKGROUP_ATTR_SIZE__ 60
55#define __OS_WORKGROUP_INTERVAL_DATA_SIZE__ 56
56#define __OS_WORKGROUP_JOIN_TOKEN_SIZE__ 28
57#endif
58
59#define _OS_WORKGROUP_ATTR_SIG_DEFAULT_INIT 0x2FA863B4
60#define _OS_WORKGROUP_ATTR_SIG_EMPTY_INIT 0x2FA863C4
61
62struct OS_REFINED_FOR_SWIFT os_workgroup_attr_opaque_s {
63 uint32_t sig;
64 char opaque[__OS_WORKGROUP_ATTR_SIZE__];
65};
66
67#define _OS_WORKGROUP_INTERVAL_DATA_SIG_INIT 0x52A74C4D
68struct OS_REFINED_FOR_SWIFT os_workgroup_interval_data_opaque_s {
69 uint32_t sig;
70 char opaque[__OS_WORKGROUP_INTERVAL_DATA_SIZE__];
71};
72
73struct OS_REFINED_FOR_SWIFT os_workgroup_join_token_opaque_s {
74 uint32_t sig;
75 char opaque[__OS_WORKGROUP_JOIN_TOKEN_SIZE__];
76};
77
78#endif /* __OS_WORKGROUP_BASE__ */
lib/libc/include/x86_64-macos-gnu/os/workgroup_interval.h created+155
...@@ -0,0 +1,155 @@
1/*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __OS_WORKGROUP_INTERVAL__
22#define __OS_WORKGROUP_INTERVAL__
23
24#ifndef __OS_WORKGROUP_INDIRECT__
25#error "Please #include <os/workgroup.h> instead of this file directly."
26#include <os/workgroup_base.h> // For header doc
27#endif
28
29__BEGIN_DECLS
30
31OS_WORKGROUP_ASSUME_NONNULL_BEGIN
32
33/*!
34 * @typedef os_workgroup_interval_t
35 *
36 * @abstract
37 * A subclass of an os_workgroup_t for tracking work performed as part of
38 * a repeating interval-driven workload.
39 */
40OS_WORKGROUP_SUBCLASS_DECL_PROTO(os_workgroup_interval, Repeatable);
41OS_WORKGROUP_SUBCLASS_DECL(os_workgroup_interval, os_workgroup, WorkGroupInterval);
42
43/* During the first instance of this API, the only supported interval
44 * workgroups are for audio workloads. Please refer to the AudioToolbox
45 * framework for more information.
46 */
47
48/*
49 * @typedef os_workgroup_interval_data, os_workgroup_interval_data_t
50 *
51 * @abstract
52 * An opaque structure containing additional configuration for the workgroup
53 * interval.
54 */
55typedef struct os_workgroup_interval_data_opaque_s os_workgroup_interval_data_s;
56typedef struct os_workgroup_interval_data_opaque_s *os_workgroup_interval_data_t;
57#define OS_WORKGROUP_INTERVAL_DATA_INITIALIZER \
58 { .sig = _OS_WORKGROUP_INTERVAL_DATA_SIG_INIT }
59
60/*!
61 * @function os_workgroup_interval_start
62 *
63 * @abstract
64 * Indicates to the system that the member threads of this
65 * os_workgroup_interval_t have begun working on an instance of the repeatable
66 * interval workload with the specified timestamps. This function is real time
67 * safe.
68 *
69 * This function will set and return an errno in the following cases:
70 *
71 * - The current thread is not a member of the os_workgroup_interval_t
72 * - The os_workgroup_interval_t has been cancelled
73 * - The timestamps passed in are malformed
74 * - os_workgroup_interval_start() was previously called on the
75 * os_workgroup_interval_t without an intervening os_workgroup_interval_finish()
76 * - A concurrent workgroup interval configuration operation is taking place.
77 *
78 * @param start
79 * Start timestamp specified in the os_clockid_t with which the
80 * os_workgroup_interval_t was created. This is generally a time in the past and
81 * indicates when the workgroup started working on an interval period
82 *
83 * @param deadline
84 * Deadline timestamp specified in the os_clockid_t with which the
85 * os_workgroup_interval_t was created. This specifies the deadline which the
86 * interval period would like to meet.
87 *
88 * @param data
89 * This field is currently unused and should be NULL
90 */
91API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
92OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
93int
94os_workgroup_interval_start(os_workgroup_interval_t wg, uint64_t start, uint64_t
95 deadline, os_workgroup_interval_data_t _Nullable data);
96
97/*!
98 * @function os_workgroup_interval_update
99 *
100 * @abstract
101 * Updates an already started interval workgroup to have the new
102 * deadline specified. This function is real time safe.
103 *
104 * This function will return an error in the following cases:
105 * - The current thread is not a member of the os_workgroup_interval_t
106 * - The os_workgroup_interval_t has been cancelled
107 * - The timestamp passed in is malformed
108 * - os_workgroup_interval_start() was not previously called on the
109 * os_workgroup_interval_t or was already matched with an
110 * os_workgroup_interval_finish()
111 * - A concurrent workgroup interval configuration operation is taking place
112 *
113 * @param deadline
114 * Timestamp specified in the os_clockid_t with
115 * which the os_workgroup_interval_t was created.
116 *
117 * @param data
118 * This field is currently unused and should be NULL
119 */
120API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
121OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
122int
123os_workgroup_interval_update(os_workgroup_interval_t wg, uint64_t deadline,
124 os_workgroup_interval_data_t _Nullable data);
125
126/*!
127 * @function os_workgroup_interval_finish
128 *
129 * @abstract
130 * Indicates to the system that the member threads of
131 * this os_workgroup_interval_t have finished working on the current instance
132 * of the interval workload. This function is real time safe.
133 *
134 * This function will return an error in the following cases:
135 * - The current thread is not a member of the os_workgroup_interval_t
136 * - os_workgroup_interval_start() was not previously called on the
137 * os_workgroup_interval_t or was already matched with an
138 * os_workgroup_interval_finish()
139 * - A concurrent workgroup interval configuration operation is taking place.
140 *
141 * @param data
142 * This field is currently unused and should be NULL
143 *
144 */
145API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
146OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
147int
148os_workgroup_interval_finish(os_workgroup_interval_t wg,
149 os_workgroup_interval_data_t _Nullable data);
150
151OS_WORKGROUP_ASSUME_NONNULL_END
152
153__END_DECLS
154
155#endif /* __OS_WORKGROUP_INTERVAL__ */
lib/libc/include/x86_64-macos-gnu/os/workgroup_object.h created+357
...@@ -0,0 +1,357 @@
1/*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __OS_WORKGROUP_OBJECT__
22#define __OS_WORKGROUP_OBJECT__
23
24#ifndef __OS_WORKGROUP_INDIRECT__
25#error "Please #include <os/workgroup.h> instead of this file directly."
26#include <os/workgroup_base.h> // For header doc
27#endif
28
29__BEGIN_DECLS
30
31OS_WORKGROUP_ASSUME_NONNULL_BEGIN
32
33/*!
34 * @typedef os_workgroup_t
35 *
36 * @abstract
37 * A reference counted os object representing a workload that needs to
38 * be distinctly recognized and tracked by the system. The workgroup
39 * tracks a collection of threads all working cooperatively. An os_workgroup
40 * object - when not an instance of a specific os_workgroup_t subclass -
41 * represents a generic workload and makes no assumptions about the kind of
42 * work done.
43 *
44 * @discussion
45 * Threads can explicitly join an os_workgroup_t to mark themselves as
46 * participants in the workload.
47 */
48OS_WORKGROUP_DECL(os_workgroup, WorkGroup);
49
50
51/* Attribute creation and specification */
52
53/*!
54 * @typedef os_workgroup_attr_t
55 *
56 * @abstract
57 * Pointer to an opaque structure for describing attributes that can be
58 * configured on a workgroup at creation.
59 */
60typedef struct os_workgroup_attr_opaque_s os_workgroup_attr_s;
61typedef struct os_workgroup_attr_opaque_s *os_workgroup_attr_t;
62
63/* os_workgroup_t attributes need to be initialized before use. This initializer
64 * allows you to create a workgroup with the system default attributes. */
65#define OS_WORKGROUP_ATTR_INITIALIZER_DEFAULT \
66 { .sig = _OS_WORKGROUP_ATTR_SIG_DEFAULT_INIT }
67
68
69
70/* The main use of the workgroup API is through instantiations of the concrete
71 * subclasses - please refer to os/workgroup_interval.h and
72 * os/workgroup_parallel.h for more information on creating workgroups.
73 *
74 * The functions below operate on all subclasses of os_workgroup_t.
75 */
76
77/*!
78 * @function os_workgroup_copy_port
79 *
80 * @abstract
81 * Returns a reference to a send right representing this workgroup that is to be
82 * sent to other processes. This port is to be passed to
83 * os_workgroup_create_with_port() to create a workgroup object.
84 *
85 * It is the client's responsibility to release the send right reference.
86 *
87 * If an error is encountered, errno is set and returned.
88 */
89API_AVAILABLE(macos(11.0))
90API_UNAVAILABLE(ios, tvos, watchos)
91OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
92int
93os_workgroup_copy_port(os_workgroup_t wg, mach_port_t *mach_port_out);
94
95/*!
96 * @function os_workgroup_create_with_port
97 *
98 * @abstract
99 * Create an os_workgroup_t object from a send right returned by a previous
100 * call to os_workgroup_copy_port, potentially in a different process.
101 *
102 * A newly created os_workgroup_t has no initial member threads - in particular
103 * the creating thread does not join the os_workgroup_t implicitly.
104 *
105 * @param name
106 * A client specified string for labelling the workgroup. This parameter is
107 * optional and can be NULL.
108 *
109 * @param mach_port
110 * The send right to create the workgroup from. No reference is consumed
111 * on the specified send right.
112 */
113API_AVAILABLE(macos(11.0))
114API_UNAVAILABLE(ios, tvos, watchos)
115OS_SWIFT_NAME(WorkGroup.init(__name:port:)) OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED
116os_workgroup_t _Nullable
117os_workgroup_create_with_port(const char *_Nullable name, mach_port_t mach_port);
118
119/*!
120 * @function os_workgroup_create_with_workgroup
121 *
122 * @abstract
123 * Create a new os_workgroup object from an existing os_workgroup.
124 *
125 * The newly created os_workgroup has no initial member threads - in particular
126 * the creating threaad does not join the os_workgroup_t implicitly.
127 *
128 * @param name
129 * A client specified string for labelling the workgroup. This parameter is
130 * optional and can be NULL.
131 *
132 * @param wg
133 * The existing workgroup to create a new workgroup object from.
134 */
135API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
136OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED
137os_workgroup_t _Nullable
138os_workgroup_create_with_workgroup(const char * _Nullable name, os_workgroup_t wg);
139
140/*!
141 * @typedef os_workgroup_join_token, os_workgroup_join_token_t
142 *
143 * @abstract
144 * An opaque join token which the client needs to pass to os_workgroup_join
145 * and os_workgroup_leave
146 */
147OS_REFINED_FOR_SWIFT
148typedef struct os_workgroup_join_token_opaque_s os_workgroup_join_token_s;
149OS_REFINED_FOR_SWIFT
150typedef struct os_workgroup_join_token_opaque_s *os_workgroup_join_token_t;
151
152
153/*!
154 * @function os_workgroup_join
155 *
156 * @abstract
157 * Joins the current thread to the specified workgroup and populates the join
158 * token that has been passed in. This API is real-time safe.
159 *
160 * @param wg
161 * The workgroup that the current thread would like to join
162 *
163 * @param token_out
164 * Pointer to a client allocated struct which the function will populate
165 * with the join token. This token must be passed in by the thread when it calls
166 * os_workgroup_leave().
167 *
168 * Errors will be returned in the following cases:
169 *
170 * EALREADY The thread is already part of a workgroup that the specified
171 * workgroup does not nest with
172 * EINVAL The workgroup has been cancelled
173 */
174API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
175OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
176int
177os_workgroup_join(os_workgroup_t wg, os_workgroup_join_token_t token_out);
178
179/*!
180 * @function os_workgroup_leave
181 *
182 * @abstract
183 * This removes the current thread from a workgroup it has previously
184 * joined. Threads must leave all workgroups in the reverse order that they
185 * have joined them. Failing to do so before exiting will result in undefined
186 * behavior.
187 *
188 * If the join token is malformed, the process will be aborted.
189 *
190 * This API is real time safe.
191 *
192 * @param wg
193 * The workgroup that the current thread would like to leave.
194 *
195 * @param token
196 * This is the join token populated by the most recent call to
197 * os_workgroup_join().
198 */
199API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
200OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
201void
202os_workgroup_leave(os_workgroup_t wg, os_workgroup_join_token_t token);
203
204/* Working Arena index of a thread in a workgroup */
205typedef uint32_t os_workgroup_index;
206/* Destructor for Working Arena */
207typedef void (*os_workgroup_working_arena_destructor_t)(void * _Nullable);
208
209/*!
210 * @function os_workgroup_set_working_arena
211 *
212 * @abstract
213 * Associates a client defined working arena with the workgroup. The arena
214 * is local to the workgroup object in the process. This is intended for
215 * distributing a manually managed memory allocation between member threads
216 * of the workgroup.
217 *
218 * This function can be called multiple times and the client specified
219 * destructor will be called on the previously assigned arena, if any. This
220 * function can only be called when no threads have currently joined the
221 * workgroup and all workloops associated with the workgroup are idle.
222 *
223 * @param wg
224 * The workgroup to associate the working arena with
225 *
226 * @param arena
227 * The client managed arena to associate with the workgroup. This value can
228 * be NULL.
229 *
230 * @param max_workers
231 * The maximum number of threads that will ever query the workgroup for the
232 * arena and request an index into it. If the arena is not used to partition
233 * work amongst member threads, then this field can be 0.
234 *
235 * @param destructor
236 * A destructor to call on the previously assigned working arena, if any
237 */
238API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
239OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
240int
241os_workgroup_set_working_arena(os_workgroup_t wg, void * _Nullable arena,
242 uint32_t max_workers, os_workgroup_working_arena_destructor_t destructor);
243
244/*!
245 * @function os_workgroup_get_working_arena
246 *
247 * @abstract
248 * Returns the working arena associated with the workgroup and the current
249 * thread's index in the workgroup. This function can only be called by a member
250 * of the workgroup. Multiple calls to this API by a member thread will return
251 * the same arena and index until the thread leaves the workgroup.
252 *
253 * For workloops with an associated workgroup, every work item on the workloop
254 * will receive the same index in the arena.
255 *
256 * This method returns NULL if no arena is set on the workgroup. The index
257 * returned by this function is zero-based and is namespaced per workgroup
258 * object in the process. The indices provided are strictly monotonic and never
259 * reused until a future call to os_workgroup_set_working_arena.
260 *
261 * @param wg
262 * The workgroup to get the working arena from.
263 *
264 * @param index_out
265 * A pointer to a os_workgroup_index which will be populated by the caller's
266 * index in the workgroup.
267 */
268API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
269OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
270void * _Nullable
271os_workgroup_get_working_arena(os_workgroup_t wg,
272 os_workgroup_index * _Nullable index_out);
273
274/*!
275 * @function os_workgroup_cancel
276 *
277 * @abstract
278 * This API invalidates a workgroup and indicates to the system that the
279 * workload is no longer relevant to the caller.
280 *
281 * No new work should be initiated for a cancelled workgroup and
282 * work that is already underway should periodically check for
283 * cancellation with os_workgroup_testcancel and initiate cleanup if needed.
284 *
285 * Threads currently in the workgroup continue to be tracked together but no
286 * new threads may join this workgroup - the only possible operation allowed is
287 * to leave the workgroup. Other actions may have undefined behavior or
288 * otherwise fail.
289 *
290 * This API is idempotent. Cancellation is local to the workgroup object
291 * it is called on and does not affect other workgroups.
292 *
293 * @param wg
294 * The workgroup that that the thread would like to cancel
295 */
296API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
297OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
298void
299os_workgroup_cancel(os_workgroup_t wg);
300
301/*!
302 * @function os_workgroup_testcancel
303 *
304 * @abstract
305 * Returns true if the workgroup object has been cancelled. See also
306 * os_workgroup_cancel
307 */
308API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
309OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
310bool
311os_workgroup_testcancel(os_workgroup_t wg);
312
313/*!
314 * @typedef os_workgroup_max_parallel_threads_attr_t
315 *
316 * @abstract
317 * A pointer to a structure describing the set of properties of a workgroup to
318 * override with the explicitly specified values in the structure.
319 *
320 * See also os_workgroup_max_parallel_threads.
321 */
322OS_REFINED_FOR_SWIFT
323typedef struct os_workgroup_max_parallel_threads_attr_s os_workgroup_mpt_attr_s;
324OS_REFINED_FOR_SWIFT
325typedef struct os_workgroup_max_parallel_threads_attr_s *os_workgroup_mpt_attr_t;
326
327/*!
328 * @function os_workgroup_max_parallel_threads
329 *
330 * @abstract
331 * Returns the system's recommendation for maximum number of threads the client
332 * should make for a multi-threaded workload in a given workgroup.
333 *
334 * This API takes into consideration the current hardware the code is running on
335 * and the attributes of the workgroup. It does not take into consideration the
336 * current load of the system and therefore always provides the most optimal
337 * recommendation for the workload.
338 *
339 * @param wg
340 * The workgroup in which the multi-threaded workload will be performed in. The
341 * threads performing the multi-threaded workload are expected to join this
342 * workgroup.
343 *
344 * @param attr
345 * This value is currently unused and should be NULL.
346 */
347API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
348OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
349int
350os_workgroup_max_parallel_threads(os_workgroup_t wg, os_workgroup_mpt_attr_t
351 _Nullable attr);
352
353OS_WORKGROUP_ASSUME_NONNULL_END
354
355__END_DECLS
356
357#endif /* __OS_WORKGROUP_OBJECT__ */
lib/libc/include/x86_64-macos-gnu/os/workgroup_parallel.h created+74
...@@ -0,0 +1,74 @@
1/*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __OS_WORKGROUP_PARALLEL__
22#define __OS_WORKGROUP_PARALLEL__
23
24#ifndef __OS_WORKGROUP_INDIRECT__
25#error "Please #include <os/workgroup.h> instead of this file directly."
26#include <os/workgroup_base.h> // For header doc
27#endif
28
29#include <os/workgroup_object.h>
30
31__BEGIN_DECLS
32
33OS_WORKGROUP_ASSUME_NONNULL_BEGIN
34
35/*!
36 * @typedef os_workgroup_parallel_t
37 *
38 * @abstract
39 * A subclass of an os_workgroup_t for tracking parallel work.
40 */
41OS_WORKGROUP_SUBCLASS_DECL_PROTO(os_workgroup_parallel, Parallelizable);
42OS_WORKGROUP_SUBCLASS_DECL(os_workgroup_parallel, os_workgroup, WorkGroupParallel);
43
44/*!
45 * @function os_workgroup_parallel_create
46 *
47 * @abstract
48 * Creates an os_workgroup_t which tracks a parallel workload.
49 * A newly created os_workgroup_interval_t has no initial member threads -
50 * in particular the creating thread does not join the os_workgroup_parallel_t
51 * implicitly.
52 *
53 * See also os_workgroup_max_parallel_threads().
54 *
55 * @param name
56 * A client specified string for labelling the workgroup. This parameter is
57 * optional and can be NULL.
58 *
59 * @param attr
60 * The requested set of workgroup attributes. NULL is to be specified for the
61 * default set of attributes.
62 */
63API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
64OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED
65OS_SWIFT_NAME(WorkGroupParallel.init(__name:attr:))
66os_workgroup_parallel_t _Nullable
67os_workgroup_parallel_create(const char * _Nullable name,
68 os_workgroup_attr_t _Nullable attr);
69
70OS_WORKGROUP_ASSUME_NONNULL_END
71
72__END_DECLS
73
74#endif /* __OS_WORKGROUP_PARALLEL__ */
lib/libc/include/x86_64-macos-gnu/sys/kern_control.h created+151
...@@ -0,0 +1,151 @@
1/*
2 * Copyright (c) 2000-2004, 2012-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*!
29 * @header kern_control.h
30 * This header defines an API to communicate between a kernel
31 * extension and a process outside of the kernel.
32 */
33
34#ifndef KPI_KERN_CONTROL_H
35#define KPI_KERN_CONTROL_H
36
37
38#include <sys/appleapiopts.h>
39#include <sys/_types/_u_char.h>
40#include <sys/_types/_u_int16_t.h>
41#include <sys/_types/_u_int32_t.h>
42
43/*
44 * Define Controller event subclass, and associated events.
45 * Subclass of KEV_SYSTEM_CLASS
46 */
47
48/*!
49 * @defined KEV_CTL_SUBCLASS
50 * @discussion The kernel event subclass for kernel control events.
51 */
52#define KEV_CTL_SUBCLASS 2
53
54/*!
55 * @defined KEV_CTL_REGISTERED
56 * @discussion The event code indicating a new controller was
57 * registered. The data portion will contain a ctl_event_data.
58 */
59#define KEV_CTL_REGISTERED 1 /* a new controller appears */
60
61/*!
62 * @defined KEV_CTL_DEREGISTERED
63 * @discussion The event code indicating a controller was unregistered.
64 * The data portion will contain a ctl_event_data.
65 */
66#define KEV_CTL_DEREGISTERED 2 /* a controller disappears */
67
68/*!
69 * @struct ctl_event_data
70 * @discussion This structure is used for KEV_CTL_SUBCLASS kernel
71 * events.
72 * @field ctl_id The kernel control id.
73 * @field ctl_unit The kernel control unit.
74 */
75struct ctl_event_data {
76 u_int32_t ctl_id; /* Kernel Controller ID */
77 u_int32_t ctl_unit;
78};
79
80/*
81 * Controls destined to the Controller Manager.
82 */
83
84/*!
85 * @defined CTLIOCGCOUNT
86 * @discussion The CTLIOCGCOUNT ioctl can be used to determine the
87 * number of kernel controllers registered.
88 */
89#define CTLIOCGCOUNT _IOR('N', 2, int) /* get number of control structures registered */
90
91/*!
92 * @defined CTLIOCGINFO
93 * @discussion The CTLIOCGINFO ioctl can be used to convert a kernel
94 * control name to a kernel control id.
95 */
96#define CTLIOCGINFO _IOWR('N', 3, struct ctl_info) /* get id from name */
97
98
99/*!
100 * @defined MAX_KCTL_NAME
101 * @discussion Kernel control names must be no longer than
102 * MAX_KCTL_NAME.
103 */
104#define MAX_KCTL_NAME 96
105
106/*
107 * Controls destined to the Controller Manager.
108 */
109
110/*!
111 * @struct ctl_info
112 * @discussion This structure is used with the CTLIOCGINFO ioctl to
113 * translate from a kernel control name to a control id.
114 * @field ctl_id The kernel control id, filled out upon return.
115 * @field ctl_name The kernel control name to find.
116 */
117struct ctl_info {
118 u_int32_t ctl_id; /* Kernel Controller ID */
119 char ctl_name[MAX_KCTL_NAME]; /* Kernel Controller Name (a C string) */
120};
121
122
123/*!
124 * @struct sockaddr_ctl
125 * @discussion The controller address structure is used to establish
126 * contact between a user client and a kernel controller. The
127 * sc_id/sc_unit uniquely identify each controller. sc_id is a
128 * unique identifier assigned to the controller. The identifier can
129 * be assigned by the system at registration time or be a 32-bit
130 * creator code obtained from Apple Computer. sc_unit is a unit
131 * number for this sc_id, and is privately used by the kernel
132 * controller to identify several instances of the controller.
133 * @field sc_len The length of the structure.
134 * @field sc_family AF_SYSTEM.
135 * @field ss_sysaddr AF_SYS_KERNCONTROL.
136 * @field sc_id Controller unique identifier.
137 * @field sc_unit Kernel controller private unit number.
138 * @field sc_reserved Reserved, must be set to zero.
139 */
140struct sockaddr_ctl {
141 u_char sc_len; /* depends on size of bundle ID string */
142 u_char sc_family; /* AF_SYSTEM */
143 u_int16_t ss_sysaddr; /* AF_SYS_KERNCONTROL */
144 u_int32_t sc_id; /* Controller unique identifier */
145 u_int32_t sc_unit; /* Developer private unit number */
146 u_int32_t sc_reserved[5];
147};
148
149
150
151#endif /* KPI_KERN_CONTROL_H */
lib/libc/include/x86_64-macos-gnu/sys/proc_info.h created+799
...@@ -0,0 +1,799 @@
1/*
2 * Copyright (c) 2005-2020 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _SYS_PROC_INFO_H
30#define _SYS_PROC_INFO_H
31
32#include <sys/cdefs.h>
33#include <sys/param.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <sys/mount.h>
37#include <sys/socket.h>
38#include <sys/un.h>
39#include <sys/kern_control.h>
40#include <sys/event.h>
41#include <net/if.h>
42#include <net/route.h>
43#include <netinet/in.h>
44#include <netinet/tcp.h>
45#include <mach/machine.h>
46#include <uuid/uuid.h>
47
48
49__BEGIN_DECLS
50
51
52#define PROC_ALL_PIDS 1
53#define PROC_PGRP_ONLY 2
54#define PROC_TTY_ONLY 3
55#define PROC_UID_ONLY 4
56#define PROC_RUID_ONLY 5
57#define PROC_PPID_ONLY 6
58#define PROC_KDBG_ONLY 7
59
60struct proc_bsdinfo {
61 uint32_t pbi_flags; /* 64bit; emulated etc */
62 uint32_t pbi_status;
63 uint32_t pbi_xstatus;
64 uint32_t pbi_pid;
65 uint32_t pbi_ppid;
66 uid_t pbi_uid;
67 gid_t pbi_gid;
68 uid_t pbi_ruid;
69 gid_t pbi_rgid;
70 uid_t pbi_svuid;
71 gid_t pbi_svgid;
72 uint32_t rfu_1; /* reserved */
73 char pbi_comm[MAXCOMLEN];
74 char pbi_name[2 * MAXCOMLEN]; /* empty if no name is registered */
75 uint32_t pbi_nfiles;
76 uint32_t pbi_pgid;
77 uint32_t pbi_pjobc;
78 uint32_t e_tdev; /* controlling tty dev */
79 uint32_t e_tpgid; /* tty process group id */
80 int32_t pbi_nice;
81 uint64_t pbi_start_tvsec;
82 uint64_t pbi_start_tvusec;
83};
84
85
86struct proc_bsdshortinfo {
87 uint32_t pbsi_pid; /* process id */
88 uint32_t pbsi_ppid; /* process parent id */
89 uint32_t pbsi_pgid; /* process perp id */
90 uint32_t pbsi_status; /* p_stat value, SZOMB, SRUN, etc */
91 char pbsi_comm[MAXCOMLEN]; /* upto 16 characters of process name */
92 uint32_t pbsi_flags; /* 64bit; emulated etc */
93 uid_t pbsi_uid; /* current uid on process */
94 gid_t pbsi_gid; /* current gid on process */
95 uid_t pbsi_ruid; /* current ruid on process */
96 gid_t pbsi_rgid; /* current tgid on process */
97 uid_t pbsi_svuid; /* current svuid on process */
98 gid_t pbsi_svgid; /* current svgid on process */
99 uint32_t pbsi_rfu; /* reserved for future use*/
100};
101
102
103
104
105/* pbi_flags values */
106#define PROC_FLAG_SYSTEM 1 /* System process */
107#define PROC_FLAG_TRACED 2 /* process currently being traced, possibly by gdb */
108#define PROC_FLAG_INEXIT 4 /* process is working its way in exit() */
109#define PROC_FLAG_PPWAIT 8
110#define PROC_FLAG_LP64 0x10 /* 64bit process */
111#define PROC_FLAG_SLEADER 0x20 /* The process is the session leader */
112#define PROC_FLAG_CTTY 0x40 /* process has a control tty */
113#define PROC_FLAG_CONTROLT 0x80 /* Has a controlling terminal */
114#define PROC_FLAG_THCWD 0x100 /* process has a thread with cwd */
115/* process control bits for resource starvation */
116#define PROC_FLAG_PC_THROTTLE 0x200 /* In resource starvation situations, this process is to be throttled */
117#define PROC_FLAG_PC_SUSP 0x400 /* In resource starvation situations, this process is to be suspended */
118#define PROC_FLAG_PC_KILL 0x600 /* In resource starvation situations, this process is to be terminated */
119#define PROC_FLAG_PC_MASK 0x600
120/* process action bits for resource starvation */
121#define PROC_FLAG_PA_THROTTLE 0x800 /* The process is currently throttled due to resource starvation */
122#define PROC_FLAG_PA_SUSP 0x1000 /* The process is currently suspended due to resource starvation */
123#define PROC_FLAG_PSUGID 0x2000 /* process has set privileges since last exec */
124#define PROC_FLAG_EXEC 0x4000 /* process has called exec */
125
126
127struct proc_taskinfo {
128 uint64_t pti_virtual_size; /* virtual memory size (bytes) */
129 uint64_t pti_resident_size; /* resident memory size (bytes) */
130 uint64_t pti_total_user; /* total time */
131 uint64_t pti_total_system;
132 uint64_t pti_threads_user; /* existing threads only */
133 uint64_t pti_threads_system;
134 int32_t pti_policy; /* default policy for new threads */
135 int32_t pti_faults; /* number of page faults */
136 int32_t pti_pageins; /* number of actual pageins */
137 int32_t pti_cow_faults; /* number of copy-on-write faults */
138 int32_t pti_messages_sent; /* number of messages sent */
139 int32_t pti_messages_received; /* number of messages received */
140 int32_t pti_syscalls_mach; /* number of mach system calls */
141 int32_t pti_syscalls_unix; /* number of unix system calls */
142 int32_t pti_csw; /* number of context switches */
143 int32_t pti_threadnum; /* number of threads in the task */
144 int32_t pti_numrunning; /* number of running threads */
145 int32_t pti_priority; /* task priority*/
146};
147
148struct proc_taskallinfo {
149 struct proc_bsdinfo pbsd;
150 struct proc_taskinfo ptinfo;
151};
152
153#define MAXTHREADNAMESIZE 64
154
155struct proc_threadinfo {
156 uint64_t pth_user_time; /* user run time */
157 uint64_t pth_system_time; /* system run time */
158 int32_t pth_cpu_usage; /* scaled cpu usage percentage */
159 int32_t pth_policy; /* scheduling policy in effect */
160 int32_t pth_run_state; /* run state (see below) */
161 int32_t pth_flags; /* various flags (see below) */
162 int32_t pth_sleep_time; /* number of seconds that thread */
163 int32_t pth_curpri; /* cur priority*/
164 int32_t pth_priority; /* priority*/
165 int32_t pth_maxpriority; /* max priority*/
166 char pth_name[MAXTHREADNAMESIZE]; /* thread name, if any */
167};
168
169struct proc_regioninfo {
170 uint32_t pri_protection;
171 uint32_t pri_max_protection;
172 uint32_t pri_inheritance;
173 uint32_t pri_flags; /* shared, external pager, is submap */
174 uint64_t pri_offset;
175 uint32_t pri_behavior;
176 uint32_t pri_user_wired_count;
177 uint32_t pri_user_tag;
178 uint32_t pri_pages_resident;
179 uint32_t pri_pages_shared_now_private;
180 uint32_t pri_pages_swapped_out;
181 uint32_t pri_pages_dirtied;
182 uint32_t pri_ref_count;
183 uint32_t pri_shadow_depth;
184 uint32_t pri_share_mode;
185 uint32_t pri_private_pages_resident;
186 uint32_t pri_shared_pages_resident;
187 uint32_t pri_obj_id;
188 uint32_t pri_depth;
189 uint64_t pri_address;
190 uint64_t pri_size;
191};
192
193#define PROC_REGION_SUBMAP 1
194#define PROC_REGION_SHARED 2
195
196#define SM_COW 1
197#define SM_PRIVATE 2
198#define SM_EMPTY 3
199#define SM_SHARED 4
200#define SM_TRUESHARED 5
201#define SM_PRIVATE_ALIASED 6
202#define SM_SHARED_ALIASED 7
203#define SM_LARGE_PAGE 8
204
205
206/*
207 * Thread run states (state field).
208 */
209
210#define TH_STATE_RUNNING 1 /* thread is running normally */
211#define TH_STATE_STOPPED 2 /* thread is stopped */
212#define TH_STATE_WAITING 3 /* thread is waiting normally */
213#define TH_STATE_UNINTERRUPTIBLE 4 /* thread is in an uninterruptible
214 * wait */
215#define TH_STATE_HALTED 5 /* thread is halted at a
216 * clean point */
217
218/*
219 * Thread flags (flags field).
220 */
221#define TH_FLAGS_SWAPPED 0x1 /* thread is swapped out */
222#define TH_FLAGS_IDLE 0x2 /* thread is an idle thread */
223
224
225struct proc_workqueueinfo {
226 uint32_t pwq_nthreads; /* total number of workqueue threads */
227 uint32_t pwq_runthreads; /* total number of running workqueue threads */
228 uint32_t pwq_blockedthreads; /* total number of blocked workqueue threads */
229 uint32_t pwq_state;
230};
231
232/*
233 * workqueue state (pwq_state field)
234 */
235#define WQ_EXCEEDED_CONSTRAINED_THREAD_LIMIT 0x1
236#define WQ_EXCEEDED_TOTAL_THREAD_LIMIT 0x2
237#define WQ_FLAGS_AVAILABLE 0x4
238
239struct proc_fileinfo {
240 uint32_t fi_openflags;
241 uint32_t fi_status;
242 off_t fi_offset;
243 int32_t fi_type;
244 uint32_t fi_guardflags;
245};
246
247/* stats flags in proc_fileinfo */
248#define PROC_FP_SHARED 1 /* shared by more than one fd */
249#define PROC_FP_CLEXEC 2 /* close on exec */
250#define PROC_FP_GUARDED 4 /* guarded fd */
251#define PROC_FP_CLFORK 8 /* close on fork */
252
253#define PROC_FI_GUARD_CLOSE (1u << 0)
254#define PROC_FI_GUARD_DUP (1u << 1)
255#define PROC_FI_GUARD_SOCKET_IPC (1u << 2)
256#define PROC_FI_GUARD_FILEPORT (1u << 3)
257
258struct proc_exitreasonbasicinfo {
259 uint32_t beri_namespace;
260 uint64_t beri_code;
261 uint64_t beri_flags;
262 uint32_t beri_reason_buf_size;
263} __attribute__((packed));
264
265struct proc_exitreasoninfo {
266 uint32_t eri_namespace;
267 uint64_t eri_code;
268 uint64_t eri_flags;
269 uint32_t eri_reason_buf_size;
270 uint64_t eri_kcd_buf;
271} __attribute__((packed));
272
273/*
274 * A copy of stat64 with static sized fields.
275 */
276struct vinfo_stat {
277 uint32_t vst_dev; /* [XSI] ID of device containing file */
278 uint16_t vst_mode; /* [XSI] Mode of file (see below) */
279 uint16_t vst_nlink; /* [XSI] Number of hard links */
280 uint64_t vst_ino; /* [XSI] File serial number */
281 uid_t vst_uid; /* [XSI] User ID of the file */
282 gid_t vst_gid; /* [XSI] Group ID of the file */
283 int64_t vst_atime; /* [XSI] Time of last access */
284 int64_t vst_atimensec; /* nsec of last access */
285 int64_t vst_mtime; /* [XSI] Last data modification time */
286 int64_t vst_mtimensec; /* last data modification nsec */
287 int64_t vst_ctime; /* [XSI] Time of last status change */
288 int64_t vst_ctimensec; /* nsec of last status change */
289 int64_t vst_birthtime; /* File creation time(birth) */
290 int64_t vst_birthtimensec; /* nsec of File creation time */
291 off_t vst_size; /* [XSI] file size, in bytes */
292 int64_t vst_blocks; /* [XSI] blocks allocated for file */
293 int32_t vst_blksize; /* [XSI] optimal blocksize for I/O */
294 uint32_t vst_flags; /* user defined flags for file */
295 uint32_t vst_gen; /* file generation number */
296 uint32_t vst_rdev; /* [XSI] Device ID */
297 int64_t vst_qspare[2]; /* RESERVED: DO NOT USE! */
298};
299
300struct vnode_info {
301 struct vinfo_stat vi_stat;
302 int vi_type;
303 int vi_pad;
304 fsid_t vi_fsid;
305};
306
307struct vnode_info_path {
308 struct vnode_info vip_vi;
309 char vip_path[MAXPATHLEN]; /* tail end of it */
310};
311
312struct vnode_fdinfo {
313 struct proc_fileinfo pfi;
314 struct vnode_info pvi;
315};
316
317struct vnode_fdinfowithpath {
318 struct proc_fileinfo pfi;
319 struct vnode_info_path pvip;
320};
321
322struct proc_regionwithpathinfo {
323 struct proc_regioninfo prp_prinfo;
324 struct vnode_info_path prp_vip;
325};
326
327struct proc_regionpath {
328 uint64_t prpo_addr;
329 uint64_t prpo_regionlength;
330 char prpo_path[MAXPATHLEN];
331};
332
333struct proc_vnodepathinfo {
334 struct vnode_info_path pvi_cdir;
335 struct vnode_info_path pvi_rdir;
336};
337
338struct proc_threadwithpathinfo {
339 struct proc_threadinfo pt;
340 struct vnode_info_path pvip;
341};
342
343/*
344 * Socket
345 */
346
347
348/*
349 * IPv4 and IPv6 Sockets
350 */
351
352#define INI_IPV4 0x1
353#define INI_IPV6 0x2
354
355struct in4in6_addr {
356 u_int32_t i46a_pad32[3];
357 struct in_addr i46a_addr4;
358};
359
360struct in_sockinfo {
361 int insi_fport; /* foreign port */
362 int insi_lport; /* local port */
363 uint64_t insi_gencnt; /* generation count of this instance */
364 uint32_t insi_flags; /* generic IP/datagram flags */
365 uint32_t insi_flow;
366
367 uint8_t insi_vflag; /* ini_IPV4 or ini_IPV6 */
368 uint8_t insi_ip_ttl; /* time to live proto */
369 uint32_t rfu_1; /* reserved */
370 /* protocol dependent part */
371 union {
372 struct in4in6_addr ina_46;
373 struct in6_addr ina_6;
374 } insi_faddr; /* foreign host table entry */
375 union {
376 struct in4in6_addr ina_46;
377 struct in6_addr ina_6;
378 } insi_laddr; /* local host table entry */
379 struct {
380 u_char in4_tos; /* type of service */
381 } insi_v4;
382 struct {
383 uint8_t in6_hlim;
384 int in6_cksum;
385 u_short in6_ifindex;
386 short in6_hops;
387 } insi_v6;
388};
389
390/*
391 * TCP Sockets
392 */
393
394#define TSI_T_REXMT 0 /* retransmit */
395#define TSI_T_PERSIST 1 /* retransmit persistence */
396#define TSI_T_KEEP 2 /* keep alive */
397#define TSI_T_2MSL 3 /* 2*msl quiet time timer */
398#define TSI_T_NTIMERS 4
399
400#define TSI_S_CLOSED 0 /* closed */
401#define TSI_S_LISTEN 1 /* listening for connection */
402#define TSI_S_SYN_SENT 2 /* active, have sent syn */
403#define TSI_S_SYN_RECEIVED 3 /* have send and received syn */
404#define TSI_S_ESTABLISHED 4 /* established */
405#define TSI_S__CLOSE_WAIT 5 /* rcvd fin, waiting for close */
406#define TSI_S_FIN_WAIT_1 6 /* have closed, sent fin */
407#define TSI_S_CLOSING 7 /* closed xchd FIN; await FIN ACK */
408#define TSI_S_LAST_ACK 8 /* had fin and close; await FIN ACK */
409#define TSI_S_FIN_WAIT_2 9 /* have closed, fin is acked */
410#define TSI_S_TIME_WAIT 10 /* in 2*msl quiet wait after close */
411#define TSI_S_RESERVED 11 /* pseudo state: reserved */
412
413struct tcp_sockinfo {
414 struct in_sockinfo tcpsi_ini;
415 int tcpsi_state;
416 int tcpsi_timer[TSI_T_NTIMERS];
417 int tcpsi_mss;
418 uint32_t tcpsi_flags;
419 uint32_t rfu_1; /* reserved */
420 uint64_t tcpsi_tp; /* opaque handle of TCP protocol control block */
421};
422
423/*
424 * Unix Domain Sockets
425 */
426
427
428struct un_sockinfo {
429 uint64_t unsi_conn_so; /* opaque handle of connected socket */
430 uint64_t unsi_conn_pcb; /* opaque handle of connected protocol control block */
431 union {
432 struct sockaddr_un ua_sun;
433 char ua_dummy[SOCK_MAXADDRLEN];
434 } unsi_addr; /* bound address */
435 union {
436 struct sockaddr_un ua_sun;
437 char ua_dummy[SOCK_MAXADDRLEN];
438 } unsi_caddr; /* address of socket connected to */
439};
440
441/*
442 * PF_NDRV Sockets
443 */
444
445struct ndrv_info {
446 uint32_t ndrvsi_if_family;
447 uint32_t ndrvsi_if_unit;
448 char ndrvsi_if_name[IF_NAMESIZE];
449};
450
451/*
452 * Kernel Event Sockets
453 */
454
455struct kern_event_info {
456 uint32_t kesi_vendor_code_filter;
457 uint32_t kesi_class_filter;
458 uint32_t kesi_subclass_filter;
459};
460
461/*
462 * Kernel Control Sockets
463 */
464
465struct kern_ctl_info {
466 uint32_t kcsi_id;
467 uint32_t kcsi_reg_unit;
468 uint32_t kcsi_flags; /* support flags */
469 uint32_t kcsi_recvbufsize; /* request more than the default buffer size */
470 uint32_t kcsi_sendbufsize; /* request more than the default buffer size */
471 uint32_t kcsi_unit;
472 char kcsi_name[MAX_KCTL_NAME]; /* unique nke identifier, provided by DTS */
473};
474
475/*
476 * VSock Sockets
477 */
478
479struct vsock_sockinfo {
480 uint32_t local_cid;
481 uint32_t local_port;
482 uint32_t remote_cid;
483 uint32_t remote_port;
484};
485
486/* soi_state */
487
488#define SOI_S_NOFDREF 0x0001 /* no file table ref any more */
489#define SOI_S_ISCONNECTED 0x0002 /* socket connected to a peer */
490#define SOI_S_ISCONNECTING 0x0004 /* in process of connecting to peer */
491#define SOI_S_ISDISCONNECTING 0x0008 /* in process of disconnecting */
492#define SOI_S_CANTSENDMORE 0x0010 /* can't send more data to peer */
493#define SOI_S_CANTRCVMORE 0x0020 /* can't receive more data from peer */
494#define SOI_S_RCVATMARK 0x0040 /* at mark on input */
495#define SOI_S_PRIV 0x0080 /* privileged for broadcast, raw... */
496#define SOI_S_NBIO 0x0100 /* non-blocking ops */
497#define SOI_S_ASYNC 0x0200 /* async i/o notify */
498#define SOI_S_INCOMP 0x0800 /* Unaccepted, incomplete connection */
499#define SOI_S_COMP 0x1000 /* unaccepted, complete connection */
500#define SOI_S_ISDISCONNECTED 0x2000 /* socket disconnected from peer */
501#define SOI_S_DRAINING 0x4000 /* close waiting for blocked system calls to drain */
502
503struct sockbuf_info {
504 uint32_t sbi_cc;
505 uint32_t sbi_hiwat; /* SO_RCVBUF, SO_SNDBUF */
506 uint32_t sbi_mbcnt;
507 uint32_t sbi_mbmax;
508 uint32_t sbi_lowat;
509 short sbi_flags;
510 short sbi_timeo;
511};
512
513enum {
514 SOCKINFO_GENERIC = 0,
515 SOCKINFO_IN = 1,
516 SOCKINFO_TCP = 2,
517 SOCKINFO_UN = 3,
518 SOCKINFO_NDRV = 4,
519 SOCKINFO_KERN_EVENT = 5,
520 SOCKINFO_KERN_CTL = 6,
521 SOCKINFO_VSOCK = 7,
522};
523
524struct socket_info {
525 struct vinfo_stat soi_stat;
526 uint64_t soi_so; /* opaque handle of socket */
527 uint64_t soi_pcb; /* opaque handle of protocol control block */
528 int soi_type;
529 int soi_protocol;
530 int soi_family;
531 short soi_options;
532 short soi_linger;
533 short soi_state;
534 short soi_qlen;
535 short soi_incqlen;
536 short soi_qlimit;
537 short soi_timeo;
538 u_short soi_error;
539 uint32_t soi_oobmark;
540 struct sockbuf_info soi_rcv;
541 struct sockbuf_info soi_snd;
542 int soi_kind;
543 uint32_t rfu_1; /* reserved */
544 union {
545 struct in_sockinfo pri_in; /* SOCKINFO_IN */
546 struct tcp_sockinfo pri_tcp; /* SOCKINFO_TCP */
547 struct un_sockinfo pri_un; /* SOCKINFO_UN */
548 struct ndrv_info pri_ndrv; /* SOCKINFO_NDRV */
549 struct kern_event_info pri_kern_event; /* SOCKINFO_KERN_EVENT */
550 struct kern_ctl_info pri_kern_ctl; /* SOCKINFO_KERN_CTL */
551 struct vsock_sockinfo pri_vsock; /* SOCKINFO_VSOCK */
552 } soi_proto;
553};
554
555struct socket_fdinfo {
556 struct proc_fileinfo pfi;
557 struct socket_info psi;
558};
559
560
561
562struct psem_info {
563 struct vinfo_stat psem_stat;
564 char psem_name[MAXPATHLEN];
565};
566
567struct psem_fdinfo {
568 struct proc_fileinfo pfi;
569 struct psem_info pseminfo;
570};
571
572
573
574struct pshm_info {
575 struct vinfo_stat pshm_stat;
576 uint64_t pshm_mappaddr;
577 char pshm_name[MAXPATHLEN];
578};
579
580struct pshm_fdinfo {
581 struct proc_fileinfo pfi;
582 struct pshm_info pshminfo;
583};
584
585
586struct pipe_info {
587 struct vinfo_stat pipe_stat;
588 uint64_t pipe_handle;
589 uint64_t pipe_peerhandle;
590 int pipe_status;
591 int rfu_1; /* reserved */
592};
593
594struct pipe_fdinfo {
595 struct proc_fileinfo pfi;
596 struct pipe_info pipeinfo;
597};
598
599
600struct kqueue_info {
601 struct vinfo_stat kq_stat;
602 uint32_t kq_state;
603 uint32_t rfu_1; /* reserved */
604};
605
606struct kqueue_dyninfo {
607 struct kqueue_info kqdi_info;
608 uint64_t kqdi_servicer;
609 uint64_t kqdi_owner;
610 uint32_t kqdi_sync_waiters;
611 uint8_t kqdi_sync_waiter_qos;
612 uint8_t kqdi_async_qos;
613 uint16_t kqdi_request_state;
614 uint8_t kqdi_events_qos;
615 uint8_t kqdi_pri;
616 uint8_t kqdi_pol;
617 uint8_t kqdi_cpupercent;
618 uint8_t _kqdi_reserved0[4];
619 uint64_t _kqdi_reserved1[4];
620};
621
622/* keep in sync with KQ_* in sys/eventvar.h */
623#define PROC_KQUEUE_SELECT 0x01
624#define PROC_KQUEUE_SLEEP 0x02
625#define PROC_KQUEUE_32 0x08
626#define PROC_KQUEUE_64 0x10
627#define PROC_KQUEUE_QOS 0x20
628
629
630struct kqueue_fdinfo {
631 struct proc_fileinfo pfi;
632 struct kqueue_info kqueueinfo;
633};
634
635struct appletalk_info {
636 struct vinfo_stat atalk_stat;
637};
638
639struct appletalk_fdinfo {
640 struct proc_fileinfo pfi;
641 struct appletalk_info appletalkinfo;
642};
643
644typedef uint64_t proc_info_udata_t;
645
646/* defns of process file desc type */
647#define PROX_FDTYPE_ATALK 0
648#define PROX_FDTYPE_VNODE 1
649#define PROX_FDTYPE_SOCKET 2
650#define PROX_FDTYPE_PSHM 3
651#define PROX_FDTYPE_PSEM 4
652#define PROX_FDTYPE_KQUEUE 5
653#define PROX_FDTYPE_PIPE 6
654#define PROX_FDTYPE_FSEVENTS 7
655#define PROX_FDTYPE_NETPOLICY 9
656
657struct proc_fdinfo {
658 int32_t proc_fd;
659 uint32_t proc_fdtype;
660};
661
662struct proc_fileportinfo {
663 uint32_t proc_fileport;
664 uint32_t proc_fdtype;
665};
666
667
668/* Flavors for proc_pidinfo() */
669#define PROC_PIDLISTFDS 1
670#define PROC_PIDLISTFD_SIZE (sizeof(struct proc_fdinfo))
671
672#define PROC_PIDTASKALLINFO 2
673#define PROC_PIDTASKALLINFO_SIZE (sizeof(struct proc_taskallinfo))
674
675#define PROC_PIDTBSDINFO 3
676#define PROC_PIDTBSDINFO_SIZE (sizeof(struct proc_bsdinfo))
677
678#define PROC_PIDTASKINFO 4
679#define PROC_PIDTASKINFO_SIZE (sizeof(struct proc_taskinfo))
680
681#define PROC_PIDTHREADINFO 5
682#define PROC_PIDTHREADINFO_SIZE (sizeof(struct proc_threadinfo))
683
684#define PROC_PIDLISTTHREADS 6
685#define PROC_PIDLISTTHREADS_SIZE (2* sizeof(uint32_t))
686
687#define PROC_PIDREGIONINFO 7
688#define PROC_PIDREGIONINFO_SIZE (sizeof(struct proc_regioninfo))
689
690#define PROC_PIDREGIONPATHINFO 8
691#define PROC_PIDREGIONPATHINFO_SIZE (sizeof(struct proc_regionwithpathinfo))
692
693#define PROC_PIDVNODEPATHINFO 9
694#define PROC_PIDVNODEPATHINFO_SIZE (sizeof(struct proc_vnodepathinfo))
695
696#define PROC_PIDTHREADPATHINFO 10
697#define PROC_PIDTHREADPATHINFO_SIZE (sizeof(struct proc_threadwithpathinfo))
698
699#define PROC_PIDPATHINFO 11
700#define PROC_PIDPATHINFO_SIZE (MAXPATHLEN)
701#define PROC_PIDPATHINFO_MAXSIZE (4*MAXPATHLEN)
702
703#define PROC_PIDWORKQUEUEINFO 12
704#define PROC_PIDWORKQUEUEINFO_SIZE (sizeof(struct proc_workqueueinfo))
705
706#define PROC_PIDT_SHORTBSDINFO 13
707#define PROC_PIDT_SHORTBSDINFO_SIZE (sizeof(struct proc_bsdshortinfo))
708
709#define PROC_PIDLISTFILEPORTS 14
710#define PROC_PIDLISTFILEPORTS_SIZE (sizeof(struct proc_fileportinfo))
711
712#define PROC_PIDTHREADID64INFO 15
713#define PROC_PIDTHREADID64INFO_SIZE (sizeof(struct proc_threadinfo))
714
715#define PROC_PID_RUSAGE 16
716#define PROC_PID_RUSAGE_SIZE 0
717
718/* Flavors for proc_pidfdinfo */
719
720#define PROC_PIDFDVNODEINFO 1
721#define PROC_PIDFDVNODEINFO_SIZE (sizeof(struct vnode_fdinfo))
722
723#define PROC_PIDFDVNODEPATHINFO 2
724#define PROC_PIDFDVNODEPATHINFO_SIZE (sizeof(struct vnode_fdinfowithpath))
725
726#define PROC_PIDFDSOCKETINFO 3
727#define PROC_PIDFDSOCKETINFO_SIZE (sizeof(struct socket_fdinfo))
728
729#define PROC_PIDFDPSEMINFO 4
730#define PROC_PIDFDPSEMINFO_SIZE (sizeof(struct psem_fdinfo))
731
732#define PROC_PIDFDPSHMINFO 5
733#define PROC_PIDFDPSHMINFO_SIZE (sizeof(struct pshm_fdinfo))
734
735#define PROC_PIDFDPIPEINFO 6
736#define PROC_PIDFDPIPEINFO_SIZE (sizeof(struct pipe_fdinfo))
737
738#define PROC_PIDFDKQUEUEINFO 7
739#define PROC_PIDFDKQUEUEINFO_SIZE (sizeof(struct kqueue_fdinfo))
740
741#define PROC_PIDFDATALKINFO 8
742#define PROC_PIDFDATALKINFO_SIZE (sizeof(struct appletalk_fdinfo))
743
744
745
746/* Flavors for proc_pidfileportinfo */
747
748#define PROC_PIDFILEPORTVNODEPATHINFO 2 /* out: vnode_fdinfowithpath */
749#define PROC_PIDFILEPORTVNODEPATHINFO_SIZE \
750 PROC_PIDFDVNODEPATHINFO_SIZE
751
752#define PROC_PIDFILEPORTSOCKETINFO 3 /* out: socket_fdinfo */
753#define PROC_PIDFILEPORTSOCKETINFO_SIZE PROC_PIDFDSOCKETINFO_SIZE
754
755#define PROC_PIDFILEPORTPSHMINFO 5 /* out: pshm_fdinfo */
756#define PROC_PIDFILEPORTPSHMINFO_SIZE PROC_PIDFDPSHMINFO_SIZE
757
758#define PROC_PIDFILEPORTPIPEINFO 6 /* out: pipe_fdinfo */
759#define PROC_PIDFILEPORTPIPEINFO_SIZE PROC_PIDFDPIPEINFO_SIZE
760
761/* used for proc_setcontrol */
762#define PROC_SELFSET_PCONTROL 1
763
764#define PROC_SELFSET_THREADNAME 2
765#define PROC_SELFSET_THREADNAME_SIZE (MAXTHREADNAMESIZE -1)
766
767#define PROC_SELFSET_VMRSRCOWNER 3
768
769#define PROC_SELFSET_DELAYIDLESLEEP 4
770
771/* used for proc_dirtycontrol */
772#define PROC_DIRTYCONTROL_TRACK 1
773#define PROC_DIRTYCONTROL_SET 2
774#define PROC_DIRTYCONTROL_GET 3
775#define PROC_DIRTYCONTROL_CLEAR 4
776
777/* proc_track_dirty() flags */
778#define PROC_DIRTY_TRACK 0x1
779#define PROC_DIRTY_ALLOW_IDLE_EXIT 0x2
780#define PROC_DIRTY_DEFER 0x4
781#define PROC_DIRTY_LAUNCH_IN_PROGRESS 0x8
782#define PROC_DIRTY_DEFER_ALWAYS 0x10
783
784/* proc_get_dirty() flags */
785#define PROC_DIRTY_TRACKED 0x1
786#define PROC_DIRTY_ALLOWS_IDLE_EXIT 0x2
787#define PROC_DIRTY_IS_DIRTY 0x4
788#define PROC_DIRTY_LAUNCH_IS_IN_PROGRESS 0x8
789
790/* Flavors for proc_udata_info */
791#define PROC_UDATA_INFO_GET 1
792#define PROC_UDATA_INFO_SET 2
793
794
795
796
797__END_DECLS
798
799#endif /*_SYS_PROC_INFO_H */
lib/libc/include/x86_64-macos-gnu/sys/ucontext.h created+41
...@@ -0,0 +1,41 @@
1/*
2 * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _SYS_UCONTEXT_H_
30#define _SYS_UCONTEXT_H_
31
32#include <sys/cdefs.h>
33#include <sys/_types.h>
34
35#include <machine/_mcontext.h>
36#include <sys/_types/_ucontext.h>
37
38#include <sys/_types/_sigset_t.h>
39
40
41#endif /* _SYS_UCONTEXT_H_ */
lib/libc/include/x86_64-macos-gnu/ucontext.h created+54
...@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 2002, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * These routines are DEPRECATED and should not be used.
26 */
27#ifndef _UCONTEXT_H_
28#define _UCONTEXT_H_
29
30#include <sys/cdefs.h>
31
32#ifdef _XOPEN_SOURCE
33#include <sys/ucontext.h>
34#include <Availability.h>
35
36__BEGIN_DECLS
37__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
38int getcontext(ucontext_t *);
39
40__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
41void makecontext(ucontext_t *, void (*)(), int, ...);
42
43__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
44int setcontext(const ucontext_t *);
45
46__API_DEPRECATED("No longer supported", macos(10.5, 10.6))
47int swapcontext(ucontext_t * __restrict, const ucontext_t * __restrict);
48
49__END_DECLS
50#else /* !_XOPEN_SOURCE */
51#error The deprecated ucontext routines require _XOPEN_SOURCE to be defined
52#endif /* _XOPEN_SOURCE */
53
54#endif /* _UCONTEXT_H_ */
lib/std/Progress.zig+70-60
...@@ -59,10 +59,6 @@ done: bool = true,...@@ -59,10 +59,6 @@ done: bool = true,
59/// while it was still being accessed by the `refresh` function.59/// while it was still being accessed by the `refresh` function.
60update_lock: std.Thread.Mutex = .{},60update_lock: std.Thread.Mutex = .{},
6161
62/// Keeps track of how many columns in the terminal have been output, so that
63/// we can move the cursor back later.
64columns_written: usize = undefined,
65
66/// Represents one unit of progress. Each node can have children nodes, or62/// Represents one unit of progress. Each node can have children nodes, or
67/// one can use integers with `update`.63/// one can use integers with `update`.
68pub const Node = struct {64pub const Node = struct {
...@@ -159,7 +155,6 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !*...@@ -159,7 +155,6 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !*
159 .unprotected_estimated_total_items = estimated_total_items,155 .unprotected_estimated_total_items = estimated_total_items,
160 .unprotected_completed_items = 0,156 .unprotected_completed_items = 0,
161 };157 };
162 self.columns_written = 0;
163 self.prev_refresh_timestamp = 0;158 self.prev_refresh_timestamp = 0;
164 self.timer = try std.time.Timer.start();159 self.timer = try std.time.Timer.start();
165 self.done = false;160 self.done = false;
...@@ -187,64 +182,67 @@ pub fn refresh(self: *Progress) void {...@@ -187,64 +182,67 @@ pub fn refresh(self: *Progress) void {
187 return self.refreshWithHeldLock();182 return self.refreshWithHeldLock();
188}183}
189184
185// ED -- Clear screen
186const ED = "\x1b[J";
187// DECSC -- Save cursor position
188const DECSC = "\x1b7";
189// DECRC -- Restore cursor position
190const DECRC = "\x1b8";
191// Note that ESC7/ESC8 are used instead of CSI s/CSI u as the latter are not
192// supported by some terminals (eg. Terminal.app).
193
190fn refreshWithHeldLock(self: *Progress) void {194fn refreshWithHeldLock(self: *Progress) void {
191 const is_dumb = !self.supports_ansi_escape_codes and !(std.builtin.os.tag == .windows);195 const is_dumb = !self.supports_ansi_escape_codes and !(std.builtin.os.tag == .windows);
192 if (is_dumb and self.dont_print_on_dumb) return;196 if (is_dumb and self.dont_print_on_dumb) return;
193 const file = self.terminal orelse return;197 const file = self.terminal orelse return;
194198
195 const prev_columns_written = self.columns_written;
196 var end: usize = 0;199 var end: usize = 0;
197 if (self.columns_written > 0) {200 // Save the cursor position and clear the part of the screen below.
198 // restore the cursor position by moving the cursor201 // Clearing only the line is not enough as the terminal may wrap the line
199 // `columns_written` cells to the left, then clear the rest of the202 // when it becomes too long.
200 // line203 var saved_cursor_pos: windows.COORD = undefined;
201 if (self.supports_ansi_escape_codes) {204 if (self.supports_ansi_escape_codes) {
202 end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{d}D", .{self.columns_written}) catch unreachable).len;205 const seq_before = DECSC ++ ED;
203 end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;206 std.mem.copy(u8, self.output_buffer[end..], seq_before);
204 } else if (std.builtin.os.tag == .windows) winapi: {207 end += seq_before.len;
205 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;208 } else if (std.builtin.os.tag == .windows) winapi: {
206 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE)209 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
207 unreachable;210 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE)
208211 unreachable;
209 var cursor_pos = windows.COORD{212
210 .X = info.dwCursorPosition.X - @intCast(windows.SHORT, self.columns_written),213 saved_cursor_pos = info.dwCursorPosition;
211 .Y = info.dwCursorPosition.Y,214
212 };215 const window_height = @intCast(windows.DWORD, info.srWindow.Bottom - info.srWindow.Top + 1);
213216 const window_width = @intCast(windows.DWORD, info.srWindow.Right - info.srWindow.Left + 1);
214 if (cursor_pos.X < 0)217 // Number of terminal cells to clear, starting from the cursor position
215 cursor_pos.X = 0;218 // and ending at the window bottom right corner.
216219 const fill_chars = if (window_width == 0 or window_height == 0) 0 else chars: {
217 const fill_chars = @intCast(windows.DWORD, info.dwSize.X - cursor_pos.X);220 break :chars window_width * (window_height -
218221 @intCast(windows.DWORD, info.dwCursorPosition.Y - info.srWindow.Top)) -
219 var written: windows.DWORD = undefined;222 @intCast(windows.DWORD, info.dwCursorPosition.X - info.srWindow.Left);
220 if (windows.kernel32.FillConsoleOutputAttribute(223 };
221 file.handle,
222 info.wAttributes,
223 fill_chars,
224 cursor_pos,
225 &written,
226 ) != windows.TRUE) {
227 // Stop trying to write to this file.
228 self.terminal = null;
229 break :winapi;
230 }
231 if (windows.kernel32.FillConsoleOutputCharacterA(
232 file.handle,
233 ' ',
234 fill_chars,
235 cursor_pos,
236 &written,
237 ) != windows.TRUE) unreachable;
238
239 if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE)
240 unreachable;
241 } else {
242 // we are in a "dumb" terminal like in acme or writing to a file
243 self.output_buffer[end] = '\n';
244 end += 1;
245 }
246224
247 self.columns_written = 0;225 var written: windows.DWORD = undefined;
226 if (windows.kernel32.FillConsoleOutputAttribute(
227 file.handle,
228 info.wAttributes,
229 fill_chars,
230 saved_cursor_pos,
231 &written,
232 ) != windows.TRUE) {
233 // Stop trying to write to this file.
234 self.terminal = null;
235 break :winapi;
236 }
237 if (windows.kernel32.FillConsoleOutputCharacterA(
238 file.handle,
239 ' ',
240 fill_chars,
241 saved_cursor_pos,
242 &written,
243 ) != windows.TRUE) {
244 unreachable;
245 }
248 }246 }
249247
250 if (!self.done) {248 if (!self.done) {
...@@ -279,10 +277,26 @@ fn refreshWithHeldLock(self: *Progress) void {...@@ -279,10 +277,26 @@ fn refreshWithHeldLock(self: *Progress) void {
279 }277 }
280 }278 }
281279
280 // We're done printing the updated message, restore the cursor position.
281 if (self.supports_ansi_escape_codes) {
282 const seq_after = DECRC;
283 std.mem.copy(u8, self.output_buffer[end..], seq_after);
284 end += seq_after.len;
285 } else if (std.builtin.os.tag != .windows) {
286 self.output_buffer[end] = '\n';
287 end += 1;
288 }
289
282 _ = file.write(self.output_buffer[0..end]) catch |e| {290 _ = file.write(self.output_buffer[0..end]) catch |e| {
283 // Stop trying to write to this file once it errors.291 // Stop trying to write to this file once it errors.
284 self.terminal = null;292 self.terminal = null;
285 };293 };
294
295 if (std.builtin.os.tag == .windows) {
296 if (windows.kernel32.SetConsoleCursorPosition(file.handle, saved_cursor_pos) != windows.TRUE)
297 unreachable;
298 }
299
286 self.prev_refresh_timestamp = self.timer.read();300 self.prev_refresh_timestamp = self.timer.read();
287}301}
288302
...@@ -293,17 +307,14 @@ pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void {...@@ -293,17 +307,14 @@ pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void {
293 self.terminal = null;307 self.terminal = null;
294 return;308 return;
295 };309 };
296 self.columns_written = 0;
297}310}
298311
299fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: anytype) void {312fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: anytype) void {
300 if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| {313 if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
301 const amt = written.len;314 const amt = written.len;
302 end.* += amt;315 end.* += amt;
303 self.columns_written += amt;
304 } else |err| switch (err) {316 } else |err| switch (err) {
305 error.NoSpaceLeft => {317 error.NoSpaceLeft => {
306 self.columns_written += self.output_buffer.len - end.*;
307 end.* = self.output_buffer.len;318 end.* = self.output_buffer.len;
308 },319 },
309 }320 }
...@@ -311,7 +322,6 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any...@@ -311,7 +322,6 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any
311 const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end;322 const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end;
312 if (end.* > max_end) {323 if (end.* > max_end) {
313 const suffix = "... ";324 const suffix = "... ";
314 self.columns_written = self.columns_written - (end.* - max_end) + suffix.len;
315 std.mem.copy(u8, self.output_buffer[max_end..], suffix);325 std.mem.copy(u8, self.output_buffer[max_end..], suffix);
316 end.* = max_end + suffix.len;326 end.* = max_end + suffix.len;
317 }327 }
lib/std/Thread.zig+1-1
...@@ -362,7 +362,7 @@ pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startF...@@ -362,7 +362,7 @@ pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startF
362 os.EAGAIN => return error.SystemResources,362 os.EAGAIN => return error.SystemResources,
363 os.EPERM => unreachable,363 os.EPERM => unreachable,
364 os.EINVAL => unreachable,364 os.EINVAL => unreachable,
365 else => return os.unexpectedErrno(@intCast(usize, err)),365 else => return os.unexpectedErrno(err),
366 }366 }
367367
368 return thread_obj;368 return thread_obj;
lib/std/c.zig+2-2
...@@ -37,9 +37,9 @@ pub usingnamespace switch (std.Target.current.os.tag) {...@@ -37,9 +37,9 @@ pub usingnamespace switch (std.Target.current.os.tag) {
37 else => struct {},37 else => struct {},
38};38};
3939
40pub fn getErrno(rc: anytype) u16 {40pub fn getErrno(rc: anytype) c_int {
41 if (rc == -1) {41 if (rc == -1) {
42 return @intCast(u16, _errno().*);42 return _errno().*;
43 } else {43 } else {
44 return 0;44 return 0;
45 }45 }
lib/std/elf.zig+32-20
...@@ -337,6 +337,7 @@ pub const ET = extern enum(u16) {...@@ -337,6 +337,7 @@ pub const ET = extern enum(u16) {
337/// All integers are native endian.337/// All integers are native endian.
338pub const Header = struct {338pub const Header = struct {
339 endian: builtin.Endian,339 endian: builtin.Endian,
340 machine: EM,
340 is_64: bool,341 is_64: bool,
341 entry: u64,342 entry: u64,
342 phoff: u64,343 phoff: u64,
...@@ -387,8 +388,14 @@ pub const Header = struct {...@@ -387,8 +388,14 @@ pub const Header = struct {
387 else => return error.InvalidElfClass,388 else => return error.InvalidElfClass,
388 };389 };
389390
391 const machine = if (need_bswap) blk: {
392 const value = @enumToInt(hdr32.e_machine);
393 break :blk @intToEnum(EM, @byteSwap(@TypeOf(value), value));
394 } else hdr32.e_machine;
395
390 return @as(Header, .{396 return @as(Header, .{
391 .endian = endian,397 .endian = endian,
398 .machine = machine,
392 .is_64 = is_64,399 .is_64 = is_64,
393 .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry),400 .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry),
394 .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff),401 .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff),
...@@ -422,16 +429,8 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {...@@ -422,16 +429,8 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {
422 if (self.elf_header.endian == std.builtin.endian) return phdr;429 if (self.elf_header.endian == std.builtin.endian) return phdr;
423430
424 // Convert fields to native endianness.431 // Convert fields to native endianness.
425 return Elf64_Phdr{432 bswapAllFields(Elf64_Phdr, &phdr);
426 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),433 return phdr;
427 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
428 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
429 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
430 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
431 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
432 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
433 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
434 };
435 }434 }
436435
437 var phdr: Elf32_Phdr = undefined;436 var phdr: Elf32_Phdr = undefined;
...@@ -442,16 +441,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {...@@ -442,16 +441,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type {
442 // ELF endianness does NOT match native endianness.441 // ELF endianness does NOT match native endianness.
443 if (self.elf_header.endian != std.builtin.endian) {442 if (self.elf_header.endian != std.builtin.endian) {
444 // Convert fields to native endianness.443 // Convert fields to native endianness.
445 phdr = .{444 bswapAllFields(Elf32_Phdr, &phdr);
446 .p_type = @byteSwap(@TypeOf(phdr.p_type), phdr.p_type),
447 .p_offset = @byteSwap(@TypeOf(phdr.p_offset), phdr.p_offset),
448 .p_vaddr = @byteSwap(@TypeOf(phdr.p_vaddr), phdr.p_vaddr),
449 .p_paddr = @byteSwap(@TypeOf(phdr.p_paddr), phdr.p_paddr),
450 .p_filesz = @byteSwap(@TypeOf(phdr.p_filesz), phdr.p_filesz),
451 .p_memsz = @byteSwap(@TypeOf(phdr.p_memsz), phdr.p_memsz),
452 .p_flags = @byteSwap(@TypeOf(phdr.p_flags), phdr.p_flags),
453 .p_align = @byteSwap(@TypeOf(phdr.p_align), phdr.p_align),
454 };
455 }445 }
456446
457 // Convert 32-bit header to 64-bit.447 // Convert 32-bit header to 64-bit.
...@@ -562,6 +552,26 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 {...@@ -562,6 +552,26 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 {
562 }552 }
563}553}
564554
555pub fn bswapAllFields(comptime S: type, ptr: *S) void {
556 if (@typeInfo(S) != .Struct) @compileError("bswapAllFields expects a struct as the first argument");
557 inline for (std.meta.fields(S)) |f| {
558 @field(ptr, f.name) = @byteSwap(f.field_type, @field(ptr, f.name));
559 }
560}
561test "bswapAllFields" {
562 var s: Elf32_Chdr = .{
563 .ch_type = 0x12341234,
564 .ch_size = 0x56785678,
565 .ch_addralign = 0x12124242,
566 };
567 bswapAllFields(Elf32_Chdr, &s);
568 std.testing.expectEqual(Elf32_Chdr{
569 .ch_type = 0x34123412,
570 .ch_size = 0x78567856,
571 .ch_addralign = 0x42421212,
572 }, s);
573}
574
565pub const EI_NIDENT = 16;575pub const EI_NIDENT = 16;
566576
567pub const EI_CLASS = 4;577pub const EI_CLASS = 4;
...@@ -1515,6 +1525,8 @@ pub const EM = extern enum(u16) {...@@ -1515,6 +1525,8 @@ pub const EM = extern enum(u16) {
15151525
1516 /// Linux kernel bpf virtual machine1526 /// Linux kernel bpf virtual machine
1517 _BPF = 247,1527 _BPF = 247,
1528
1529 _,
1518};1530};
15191531
1520/// Section data should be writable during execution.1532/// Section data should be writable during execution.
lib/std/fmt.zig+83-78
...@@ -35,11 +35,11 @@ pub const FormatOptions = struct {...@@ -35,11 +35,11 @@ pub const FormatOptions = struct {
35///35///
36/// The format string must be comptime known and may contain placeholders following36/// The format string must be comptime known and may contain placeholders following
37/// this format:37/// this format:
38/// `{[position][specifier]:[fill][alignment][width].[precision]}`38/// `{[argument][specifier]:[fill][alignment][width].[precision]}`
39///39///
40/// Each word between `[` and `]` is a parameter you have to replace with something:40/// Each word between `[` and `]` is a parameter you have to replace with something:
41///41///
42/// - *position* is the index of the argument that should be inserted42/// - *argument* is either the index or the name of the argument that should be inserted
43/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)43/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
44/// - *fill* is a single character which is used to pad the formatted text44/// - *fill* is a single character which is used to pad the formatted text
45/// - *alignment* is one of the three characters `<`, `^` or `>`. they define if the text is *left*, *center*, or *right* aligned45/// - *alignment* is one of the three characters `<`, `^` or `>`. they define if the text is *left*, *center*, or *right* aligned
...@@ -52,16 +52,10 @@ pub const FormatOptions = struct {...@@ -52,16 +52,10 @@ pub const FormatOptions = struct {
52/// the digits after `:` is interpreted as *width*, not *fill*.52/// the digits after `:` is interpreted as *width*, not *fill*.
53///53///
54/// The *specifier* has several options for types:54/// The *specifier* has several options for types:
55/// - `x` and `X`:55/// - `x` and `X`: output numeric value in hexadecimal notation
56/// - format the non-numeric value as a string of bytes in hexadecimal notation ("binary dump") in either lower case or upper case
57/// - output numeric value in hexadecimal notation
58/// - `s`:56/// - `s`:
59/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination57/// - for pointer-to-many and C pointers of u8, print as a C-string using zero-termination
60/// - for slices of u8, print the entire slice as a string without zero-termination58/// - for slices of u8, print the entire slice as a string without zero-termination
61/// - `z`: escape the string with @"" syntax if it is not a valid Zig identifier.
62/// - `Z`: print the string escaping non-printable characters using Zig escape sequences.
63/// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values.
64/// - `e` and `E`: if printing a string, escape non-printable characters
65/// - `e`: output floating point value in scientific notation59/// - `e`: output floating point value in scientific notation
66/// - `d`: output numeric value in decimal notation60/// - `d`: output numeric value in decimal notation
67/// - `b`: output integer value in binary notation61/// - `b`: output integer value in binary notation
...@@ -620,9 +614,9 @@ fn formatValue(...@@ -620,9 +614,9 @@ fn formatValue(
620 writer: anytype,614 writer: anytype,
621) !void {615) !void {
622 if (comptime std.mem.eql(u8, fmt, "B")) {616 if (comptime std.mem.eql(u8, fmt, "B")) {
623 return formatBytes(value, options, 1000, writer);617 @compileError("specifier 'B' has been deprecated, wrap your argument in std.fmt.fmtIntSizeDec instead");
624 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {618 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
625 return formatBytes(value, options, 1024, writer);619 @compileError("specifier 'Bi' has been deprecated, wrap your argument in std.fmt.fmtIntSizeBin instead");
626 }620 }
627621
628 const T = @TypeOf(value);622 const T = @TypeOf(value);
...@@ -790,6 +784,67 @@ pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscap...@@ -790,6 +784,67 @@ pub fn fmtSliceEscapeUpper(bytes: []const u8) std.fmt.Formatter(formatSliceEscap
790 return .{ .data = bytes };784 return .{ .data = bytes };
791}785}
792786
787fn formatSizeImpl(comptime radix: comptime_int) type {
788 return struct {
789 fn f(
790 value: u64,
791 comptime fmt: []const u8,
792 options: FormatOptions,
793 writer: anytype,
794 ) !void {
795 if (value == 0) {
796 return writer.writeAll("0B");
797 }
798
799 const mags_si = " kMGTPEZY";
800 const mags_iec = " KMGTPEZY";
801
802 const log2 = math.log2(value);
803 const magnitude = switch (radix) {
804 1000 => math.min(log2 / comptime math.log2(1000), mags_si.len - 1),
805 1024 => math.min(log2 / 10, mags_iec.len - 1),
806 else => unreachable,
807 };
808 const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
809 const suffix = switch (radix) {
810 1000 => mags_si[magnitude],
811 1024 => mags_iec[magnitude],
812 else => unreachable,
813 };
814
815 try formatFloatDecimal(new_value, options, writer);
816
817 if (suffix == ' ') {
818 return writer.writeAll("B");
819 }
820
821 const buf = switch (radix) {
822 1000 => &[_]u8{ suffix, 'B' },
823 1024 => &[_]u8{ suffix, 'i', 'B' },
824 else => unreachable,
825 };
826 return writer.writeAll(buf);
827 }
828 };
829}
830
831const formatSizeDec = formatSizeImpl(1000).f;
832const formatSizeBin = formatSizeImpl(1024).f;
833
834/// Return a Formatter for a u64 value representing a file size.
835/// This formatter represents the number as multiple of 1000 and uses the SI
836/// measurement units (kB, MB, GB, ...).
837pub fn fmtIntSizeDec(value: u64) std.fmt.Formatter(formatSizeDec) {
838 return .{ .data = value };
839}
840
841/// Return a Formatter for a u64 value representing a file size.
842/// This formatter represents the number as multiple of 1024 and uses the IEC
843/// measurement units (KiB, MiB, GiB, ...).
844pub fn fmtIntSizeBin(value: u64) std.fmt.Formatter(formatSizeBin) {
845 return .{ .data = value };
846}
847
793pub fn formatText(848pub fn formatText(
794 bytes: []const u8,849 bytes: []const u8,
795 comptime fmt: []const u8,850 comptime fmt: []const u8,
...@@ -1111,47 +1166,6 @@ pub fn formatFloatDecimal(...@@ -1111,47 +1166,6 @@ pub fn formatFloatDecimal(
1111 }1166 }
1112}1167}
11131168
1114pub fn formatBytes(
1115 value: anytype,
1116 options: FormatOptions,
1117 comptime radix: usize,
1118 writer: anytype,
1119) !void {
1120 if (value == 0) {
1121 return writer.writeAll("0B");
1122 }
1123
1124 const is_float = comptime std.meta.trait.is(.Float)(@TypeOf(value));
1125 const mags_si = " kMGTPEZY";
1126 const mags_iec = " KMGTPEZY";
1127
1128 const log2 = if (is_float) @floatToInt(usize, math.log2(value)) else math.log2(value);
1129 const magnitude = switch (radix) {
1130 1000 => math.min(log2 / comptime math.log2(1000), mags_si.len - 1),
1131 1024 => math.min(log2 / 10, mags_iec.len - 1),
1132 else => unreachable,
1133 };
1134 const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
1135 const suffix = switch (radix) {
1136 1000 => mags_si[magnitude],
1137 1024 => mags_iec[magnitude],
1138 else => unreachable,
1139 };
1140
1141 try formatFloatDecimal(new_value, options, writer);
1142
1143 if (suffix == ' ') {
1144 return writer.writeAll("B");
1145 }
1146
1147 const buf = switch (radix) {
1148 1000 => &[_]u8{ suffix, 'B' },
1149 1024 => &[_]u8{ suffix, 'i', 'B' },
1150 else => unreachable,
1151 };
1152 return writer.writeAll(buf);
1153}
1154
1155pub fn formatInt(1169pub fn formatInt(
1156 value: anytype,1170 value: anytype,
1157 base: u8,1171 base: u8,
...@@ -1210,11 +1224,7 @@ pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, uppercase: bool, op...@@ -1210,11 +1224,7 @@ pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, uppercase: bool, op
1210 return fbs.pos;1224 return fbs.pos;
1211}1225}
12121226
1213/// Formats a number of nanoseconds according to its magnitude:1227fn formatDuration(ns: u64, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
1214///
1215/// - #ns
1216/// - [#y][#w][#d][#h][#m]#[.###][u|m]s
1217pub fn formatDuration(ns: u64, writer: anytype) !void {
1218 var ns_remaining = ns;1228 var ns_remaining = ns;
1219 inline for (.{1229 inline for (.{
1220 .{ .ns = 365 * std.time.ns_per_day, .sep = 'y' },1230 .{ .ns = 365 * std.time.ns_per_day, .sep = 'y' },
...@@ -1256,12 +1266,18 @@ pub fn formatDuration(ns: u64, writer: anytype) !void {...@@ -1256,12 +1266,18 @@ pub fn formatDuration(ns: u64, writer: anytype) !void {
1256 }1266 }
1257 }1267 }
12581268
1259 try formatInt(ns, 10, false, .{}, writer);1269 try formatInt(ns_remaining, 10, false, .{}, writer);
1260 try writer.writeAll("ns");1270 try writer.writeAll("ns");
1261 return;1271 return;
1262}1272}
12631273
1264test "formatDuration" {1274/// Return a Formatter for number of nanoseconds according to its magnitude:
1275/// [#y][#w][#d][#h][#m]#[.###][n|u|m]s
1276pub fn fmtDuration(ns: u64) Formatter(formatDuration) {
1277 return .{ .data = ns };
1278}
1279
1280test "fmtDuration" {
1265 var buf: [24]u8 = undefined;1281 var buf: [24]u8 = undefined;
1266 inline for (.{1282 inline for (.{
1267 .{ .s = "0ns", .d = 0 },1283 .{ .s = "0ns", .d = 0 },
...@@ -1287,26 +1303,13 @@ test "formatDuration" {...@@ -1287,26 +1303,13 @@ test "formatDuration" {
1287 .{ .s = "1y1h999.999us", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1 },1303 .{ .s = "1y1h999.999us", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1 },
1288 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms },1304 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms },
1289 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1 },1305 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1 },
1306 .{ .s = "1y1m999ns", .d = 365 * std.time.ns_per_day + std.time.ns_per_min + 999 },
1290 }) |tc| {1307 }) |tc| {
1291 const slice = try bufPrint(&buf, "{}", .{duration(tc.d)});1308 const slice = try bufPrint(&buf, "{}", .{fmtDuration(tc.d)});
1292 std.testing.expectEqualStrings(tc.s, slice);1309 std.testing.expectEqualStrings(tc.s, slice);
1293 }1310 }
1294}1311}
12951312
1296/// Wraps a `u64` to format with `formatDuration`.
1297const Duration = struct {
1298 ns: u64,
1299
1300 pub fn format(self: Duration, comptime fmt: []const u8, options: FormatOptions, writer: anytype) !void {
1301 return formatDuration(self.ns, writer);
1302 }
1303};
1304
1305/// Formats a number of nanoseconds according to its magnitude. See `formatDuration`.
1306pub fn duration(ns: u64) Duration {
1307 return Duration{ .ns = ns };
1308}
1309
1310pub const ParseIntError = error{1313pub const ParseIntError = error{
1311 /// The result cannot fit in the type specified1314 /// The result cannot fit in the type specified
1312 Overflow,1315 Overflow,
...@@ -1806,8 +1809,12 @@ test "cstr" {...@@ -1806,8 +1809,12 @@ test "cstr" {
1806}1809}
18071810
1808test "filesize" {1811test "filesize" {
1809 try expectFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});1812 try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeDec(42)});
1810 try expectFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});1813 try expectFmt("file size: 42B\n", "file size: {}\n", .{fmtIntSizeBin(42)});
1814 try expectFmt("file size: 63MB\n", "file size: {}\n", .{fmtIntSizeDec(63 * 1000 * 1000)});
1815 try expectFmt("file size: 63MiB\n", "file size: {}\n", .{fmtIntSizeBin(63 * 1024 * 1024)});
1816 try expectFmt("file size: 66.06MB\n", "file size: {:.2}\n", .{fmtIntSizeDec(63 * 1024 * 1024)});
1817 try expectFmt("file size: 60.08MiB\n", "file size: {:.2}\n", .{fmtIntSizeBin(63 * 1000 * 1000)});
1811}1818}
18121819
1813test "struct" {1820test "struct" {
...@@ -2213,8 +2220,6 @@ test "vector" {...@@ -2213,8 +2220,6 @@ test "vector" {
2213 try expectFmt("{ -2, -1, +0, +1 }", "{d:5}", .{vi64});2220 try expectFmt("{ -2, -1, +0, +1 }", "{d:5}", .{vi64});
2214 try expectFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});2221 try expectFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
2215 try expectFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});2222 try expectFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
2216 try expectFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
2217 try expectFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
2218}2223}
22192224
2220test "enum-literal" {2225test "enum-literal" {
lib/std/fmt/parse_float.zig+3-1
...@@ -339,7 +339,7 @@ fn caseInEql(a: []const u8, b: []const u8) bool {...@@ -339,7 +339,7 @@ fn caseInEql(a: []const u8, b: []const u8) bool {
339}339}
340340
341pub fn parseFloat(comptime T: type, s: []const u8) !T {341pub fn parseFloat(comptime T: type, s: []const u8) !T {
342 if (s.len == 0) {342 if (s.len == 0 or (s.len == 1 and (s[0] == '+' or s[0] == '-'))) {
343 return error.InvalidCharacter;343 return error.InvalidCharacter;
344 }344 }
345345
...@@ -379,6 +379,8 @@ test "fmt.parseFloat" {...@@ -379,6 +379,8 @@ test "fmt.parseFloat" {
379 testing.expectError(error.InvalidCharacter, parseFloat(T, ""));379 testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
380 testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));380 testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
381 testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc"));381 testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc"));
382 testing.expectError(error.InvalidCharacter, parseFloat(T, "+"));
383 testing.expectError(error.InvalidCharacter, parseFloat(T, "-"));
382384
383 expectEqual(try parseFloat(T, "0"), 0.0);385 expectEqual(try parseFloat(T, "0"), 0.0);
384 expectEqual(try parseFloat(T, "0"), 0.0);386 expectEqual(try parseFloat(T, "0"), 0.0);
lib/std/hash_map.zig+24-21
...@@ -50,20 +50,20 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) {...@@ -50,20 +50,20 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) {
50}50}
5151
52pub fn AutoHashMap(comptime K: type, comptime V: type) type {52pub fn AutoHashMap(comptime K: type, comptime V: type) type {
53 return HashMap(K, V, getAutoHashFn(K), getAutoEqlFn(K), DefaultMaxLoadPercentage);53 return HashMap(K, V, getAutoHashFn(K), getAutoEqlFn(K), default_max_load_percentage);
54}54}
5555
56pub fn AutoHashMapUnmanaged(comptime K: type, comptime V: type) type {56pub fn AutoHashMapUnmanaged(comptime K: type, comptime V: type) type {
57 return HashMapUnmanaged(K, V, getAutoHashFn(K), getAutoEqlFn(K), DefaultMaxLoadPercentage);57 return HashMapUnmanaged(K, V, getAutoHashFn(K), getAutoEqlFn(K), default_max_load_percentage);
58}58}
5959
60/// Builtin hashmap for strings as keys.60/// Builtin hashmap for strings as keys.
61pub fn StringHashMap(comptime V: type) type {61pub fn StringHashMap(comptime V: type) type {
62 return HashMap([]const u8, V, hashString, eqlString, DefaultMaxLoadPercentage);62 return HashMap([]const u8, V, hashString, eqlString, default_max_load_percentage);
63}63}
6464
65pub fn StringHashMapUnmanaged(comptime V: type) type {65pub fn StringHashMapUnmanaged(comptime V: type) type {
66 return HashMapUnmanaged([]const u8, V, hashString, eqlString, DefaultMaxLoadPercentage);66 return HashMapUnmanaged([]const u8, V, hashString, eqlString, default_max_load_percentage);
67}67}
6868
69pub fn eqlString(a: []const u8, b: []const u8) bool {69pub fn eqlString(a: []const u8, b: []const u8) bool {
...@@ -74,7 +74,10 @@ pub fn hashString(s: []const u8) u64 {...@@ -74,7 +74,10 @@ pub fn hashString(s: []const u8) u64 {
74 return std.hash.Wyhash.hash(0, s);74 return std.hash.Wyhash.hash(0, s);
75}75}
7676
77pub const DefaultMaxLoadPercentage = 80;77/// Deprecated use `default_max_load_percentage`
78pub const DefaultMaxLoadPercentage = default_max_load_percentage;
79
80pub const default_max_load_percentage = 80;
7881
79/// General purpose hash table.82/// General purpose hash table.
80/// No order is guaranteed and any modification invalidates live iterators.83/// No order is guaranteed and any modification invalidates live iterators.
...@@ -89,13 +92,13 @@ pub fn HashMap(...@@ -89,13 +92,13 @@ pub fn HashMap(
89 comptime V: type,92 comptime V: type,
90 comptime hashFn: fn (key: K) u64,93 comptime hashFn: fn (key: K) u64,
91 comptime eqlFn: fn (a: K, b: K) bool,94 comptime eqlFn: fn (a: K, b: K) bool,
92 comptime MaxLoadPercentage: u64,95 comptime max_load_percentage: u64,
93) type {96) type {
94 return struct {97 return struct {
95 unmanaged: Unmanaged,98 unmanaged: Unmanaged,
96 allocator: *Allocator,99 allocator: *Allocator,
97100
98 pub const Unmanaged = HashMapUnmanaged(K, V, hashFn, eqlFn, MaxLoadPercentage);101 pub const Unmanaged = HashMapUnmanaged(K, V, hashFn, eqlFn, max_load_percentage);
99 pub const Entry = Unmanaged.Entry;102 pub const Entry = Unmanaged.Entry;
100 pub const Hash = Unmanaged.Hash;103 pub const Hash = Unmanaged.Hash;
101 pub const Iterator = Unmanaged.Iterator;104 pub const Iterator = Unmanaged.Iterator;
...@@ -251,9 +254,9 @@ pub fn HashMapUnmanaged(...@@ -251,9 +254,9 @@ pub fn HashMapUnmanaged(
251 comptime V: type,254 comptime V: type,
252 hashFn: fn (key: K) u64,255 hashFn: fn (key: K) u64,
253 eqlFn: fn (a: K, b: K) bool,256 eqlFn: fn (a: K, b: K) bool,
254 comptime MaxLoadPercentage: u64,257 comptime max_load_percentage: u64,
255) type {258) type {
256 comptime assert(MaxLoadPercentage > 0 and MaxLoadPercentage < 100);259 comptime assert(max_load_percentage > 0 and max_load_percentage < 100);
257260
258 return struct {261 return struct {
259 const Self = @This();262 const Self = @This();
...@@ -274,12 +277,12 @@ pub fn HashMapUnmanaged(...@@ -274,12 +277,12 @@ pub fn HashMapUnmanaged(
274 // Having a countdown to grow reduces the number of instructions to277 // Having a countdown to grow reduces the number of instructions to
275 // execute when determining if the hashmap has enough capacity already.278 // execute when determining if the hashmap has enough capacity already.
276 /// Number of available slots before a grow is needed to satisfy the279 /// Number of available slots before a grow is needed to satisfy the
277 /// `MaxLoadPercentage`.280 /// `max_load_percentage`.
278 available: Size = 0,281 available: Size = 0,
279282
280 // This is purely empirical and not a /very smart magic constant™/.283 // This is purely empirical and not a /very smart magic constant™/.
281 /// Capacity of the first grow when bootstrapping the hashmap.284 /// Capacity of the first grow when bootstrapping the hashmap.
282 const MinimalCapacity = 8;285 const minimal_capacity = 8;
283286
284 // This hashmap is specially designed for sizes that fit in a u32.287 // This hashmap is specially designed for sizes that fit in a u32.
285 const Size = u32;288 const Size = u32;
...@@ -382,7 +385,7 @@ pub fn HashMapUnmanaged(...@@ -382,7 +385,7 @@ pub fn HashMapUnmanaged(
382 found_existing: bool,385 found_existing: bool,
383 };386 };
384387
385 pub const Managed = HashMap(K, V, hashFn, eqlFn, MaxLoadPercentage);388 pub const Managed = HashMap(K, V, hashFn, eqlFn, max_load_percentage);
386389
387 pub fn promote(self: Self, allocator: *Allocator) Managed {390 pub fn promote(self: Self, allocator: *Allocator) Managed {
388 return .{391 return .{
...@@ -392,7 +395,7 @@ pub fn HashMapUnmanaged(...@@ -392,7 +395,7 @@ pub fn HashMapUnmanaged(
392 }395 }
393396
394 fn isUnderMaxLoadPercentage(size: Size, cap: Size) bool {397 fn isUnderMaxLoadPercentage(size: Size, cap: Size) bool {
395 return size * 100 < MaxLoadPercentage * cap;398 return size * 100 < max_load_percentage * cap;
396 }399 }
397400
398 pub fn init(allocator: *Allocator) Self {401 pub fn init(allocator: *Allocator) Self {
...@@ -425,7 +428,7 @@ pub fn HashMapUnmanaged(...@@ -425,7 +428,7 @@ pub fn HashMapUnmanaged(
425 }428 }
426429
427 fn capacityForSize(size: Size) Size {430 fn capacityForSize(size: Size) Size {
428 var new_cap = @truncate(u32, (@as(u64, size) * 100) / MaxLoadPercentage + 1);431 var new_cap = @truncate(u32, (@as(u64, size) * 100) / max_load_percentage + 1);
429 new_cap = math.ceilPowerOfTwo(u32, new_cap) catch unreachable;432 new_cap = math.ceilPowerOfTwo(u32, new_cap) catch unreachable;
430 return new_cap;433 return new_cap;
431 }434 }
...@@ -439,7 +442,7 @@ pub fn HashMapUnmanaged(...@@ -439,7 +442,7 @@ pub fn HashMapUnmanaged(
439 if (self.metadata) |_| {442 if (self.metadata) |_| {
440 self.initMetadatas();443 self.initMetadatas();
441 self.size = 0;444 self.size = 0;
442 self.available = @truncate(u32, (self.capacity() * MaxLoadPercentage) / 100);445 self.available = @truncate(u32, (self.capacity() * max_load_percentage) / 100);
443 }446 }
444 }447 }
445448
...@@ -712,9 +715,9 @@ pub fn HashMapUnmanaged(...@@ -712,9 +715,9 @@ pub fn HashMapUnmanaged(
712 }715 }
713716
714 // This counts the number of occupied slots, used + tombstones, which is717 // This counts the number of occupied slots, used + tombstones, which is
715 // what has to stay under the MaxLoadPercentage of capacity.718 // what has to stay under the max_load_percentage of capacity.
716 fn load(self: *const Self) Size {719 fn load(self: *const Self) Size {
717 const max_load = (self.capacity() * MaxLoadPercentage) / 100;720 const max_load = (self.capacity() * max_load_percentage) / 100;
718 assert(max_load >= self.available);721 assert(max_load >= self.available);
719 return @truncate(Size, max_load - self.available);722 return @truncate(Size, max_load - self.available);
720 }723 }
...@@ -733,7 +736,7 @@ pub fn HashMapUnmanaged(...@@ -733,7 +736,7 @@ pub fn HashMapUnmanaged(
733 const new_cap = capacityForSize(self.size);736 const new_cap = capacityForSize(self.size);
734 try other.allocate(allocator, new_cap);737 try other.allocate(allocator, new_cap);
735 other.initMetadatas();738 other.initMetadatas();
736 other.available = @truncate(u32, (new_cap * MaxLoadPercentage) / 100);739 other.available = @truncate(u32, (new_cap * max_load_percentage) / 100);
737740
738 var i: Size = 0;741 var i: Size = 0;
739 var metadata = self.metadata.?;742 var metadata = self.metadata.?;
...@@ -751,7 +754,7 @@ pub fn HashMapUnmanaged(...@@ -751,7 +754,7 @@ pub fn HashMapUnmanaged(
751 }754 }
752755
753 fn grow(self: *Self, allocator: *Allocator, new_capacity: Size) !void {756 fn grow(self: *Self, allocator: *Allocator, new_capacity: Size) !void {
754 const new_cap = std.math.max(new_capacity, MinimalCapacity);757 const new_cap = std.math.max(new_capacity, minimal_capacity);
755 assert(new_cap > self.capacity());758 assert(new_cap > self.capacity());
756 assert(std.math.isPowerOfTwo(new_cap));759 assert(std.math.isPowerOfTwo(new_cap));
757760
...@@ -759,7 +762,7 @@ pub fn HashMapUnmanaged(...@@ -759,7 +762,7 @@ pub fn HashMapUnmanaged(
759 defer map.deinit(allocator);762 defer map.deinit(allocator);
760 try map.allocate(allocator, new_cap);763 try map.allocate(allocator, new_cap);
761 map.initMetadatas();764 map.initMetadatas();
762 map.available = @truncate(u32, (new_cap * MaxLoadPercentage) / 100);765 map.available = @truncate(u32, (new_cap * max_load_percentage) / 100);
763766
764 if (self.size != 0) {767 if (self.size != 0) {
765 const old_capacity = self.capacity();768 const old_capacity = self.capacity();
...@@ -943,7 +946,7 @@ test "std.hash_map ensureCapacity with existing elements" {...@@ -943,7 +946,7 @@ test "std.hash_map ensureCapacity with existing elements" {
943946
944 try map.put(0, 0);947 try map.put(0, 0);
945 expectEqual(map.count(), 1);948 expectEqual(map.count(), 1);
946 expectEqual(map.capacity(), @TypeOf(map).Unmanaged.MinimalCapacity);949 expectEqual(map.capacity(), @TypeOf(map).Unmanaged.minimal_capacity);
947950
948 try map.ensureCapacity(65);951 try map.ensureCapacity(65);
949 expectEqual(map.count(), 1);952 expectEqual(map.count(), 1);
lib/std/io/c_writer.zig+1-1
...@@ -30,7 +30,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u...@@ -30,7 +30,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u
30 os.ENOSPC => return error.NoSpaceLeft,30 os.ENOSPC => return error.NoSpaceLeft,
31 os.EPERM => return error.AccessDenied,31 os.EPERM => return error.AccessDenied,
32 os.EPIPE => return error.BrokenPipe,32 os.EPIPE => return error.BrokenPipe,
33 else => |err| return os.unexpectedErrno(@intCast(usize, err)),33 else => |err| return os.unexpectedErrno(err),
34 }34 }
35}35}
3636
lib/std/mem.zig+8-2
...@@ -647,7 +647,10 @@ pub fn len(value: anytype) usize {...@@ -647,7 +647,10 @@ pub fn len(value: anytype) usize {
647 indexOfSentinel(info.child, sentinel, value)647 indexOfSentinel(info.child, sentinel, value)
648 else648 else
649 @compileError("length of pointer with no sentinel"),649 @compileError("length of pointer with no sentinel"),
650 .C => indexOfSentinel(info.child, 0, value),650 .C => {
651 assert(value != null);
652 return indexOfSentinel(info.child, 0, value);
653 },
651 .Slice => value.len,654 .Slice => value.len,
652 },655 },
653 .Struct => |info| if (info.is_tuple) {656 .Struct => |info| if (info.is_tuple) {
...@@ -708,7 +711,10 @@ pub fn lenZ(ptr: anytype) usize {...@@ -708,7 +711,10 @@ pub fn lenZ(ptr: anytype) usize {
708 indexOfSentinel(info.child, sentinel, ptr)711 indexOfSentinel(info.child, sentinel, ptr)
709 else712 else
710 @compileError("length of pointer with no sentinel"),713 @compileError("length of pointer with no sentinel"),
711 .C => indexOfSentinel(info.child, 0, ptr),714 .C => {
715 assert(ptr != null);
716 return indexOfSentinel(info.child, 0, ptr);
717 },
712 .Slice => if (info.sentinel) |sentinel|718 .Slice => if (info.sentinel) |sentinel|
713 indexOfSentinel(info.child, sentinel, ptr.ptr)719 indexOfSentinel(info.child, sentinel, ptr.ptr)
714 else720 else
lib/std/meta.zig+52
...@@ -1094,6 +1094,58 @@ test "sizeof" {...@@ -1094,6 +1094,58 @@ test "sizeof" {
1094 testing.expect(sizeof(c_void) == 1);1094 testing.expect(sizeof(c_void) == 1);
1095}1095}
10961096
1097pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal };
1098
1099fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type {
1100 const signed_decimal = [_]type{ c_int, c_long, c_longlong };
1101 const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong };
1102 const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
1103
1104 const list: []const type = if (@typeInfo(SuffixType).Int.signedness == .unsigned)
1105 &unsigned
1106 else if (radix == .decimal)
1107 &signed_decimal
1108 else
1109 &signed_oct_hex;
1110
1111 var pos = mem.indexOfScalar(type, list, SuffixType).?;
1112
1113 while (pos < list.len) : (pos += 1) {
1114 if (number >= math.minInt(list[pos]) and number <= math.maxInt(list[pos])) {
1115 return list[pos];
1116 }
1117 }
1118 @compileError("Integer literal is too large");
1119}
1120
1121/// Promote the type of an integer literal until it fits as C would.
1122/// This is for translate-c and is not intended for general use.
1123pub fn promoteIntLiteral(
1124 comptime SuffixType: type,
1125 comptime number: comptime_int,
1126 comptime radix: CIntLiteralRadix,
1127) PromoteIntLiteralReturnType(SuffixType, number, radix) {
1128 return number;
1129}
1130
1131test "promoteIntLiteral" {
1132 const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hexadecimal);
1133 testing.expectEqual(c_uint, @TypeOf(signed_hex));
1134
1135 if (math.maxInt(c_longlong) == math.maxInt(c_int)) return;
1136
1137 const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal);
1138 const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hexadecimal);
1139
1140 if (math.maxInt(c_long) > math.maxInt(c_int)) {
1141 testing.expectEqual(c_long, @TypeOf(signed_decimal));
1142 testing.expectEqual(c_ulong, @TypeOf(unsigned));
1143 } else {
1144 testing.expectEqual(c_longlong, @TypeOf(signed_decimal));
1145 testing.expectEqual(c_ulonglong, @TypeOf(unsigned));
1146 }
1147}
1148
1097/// For a given function type, returns a tuple type which fields will1149/// For a given function type, returns a tuple type which fields will
1098/// correspond to the argument types.1150/// correspond to the argument types.
1099///1151///
lib/std/multi_array_list.zig+75-34
...@@ -8,6 +8,7 @@ const assert = std.debug.assert;...@@ -8,6 +8,7 @@ const assert = std.debug.assert;
8const meta = std.meta;8const meta = std.meta;
9const mem = std.mem;9const mem = std.mem;
10const Allocator = mem.Allocator;10const Allocator = mem.Allocator;
11const testing = std.testing;
1112
12pub fn MultiArrayList(comptime S: type) type {13pub fn MultiArrayList(comptime S: type) type {
13 return struct {14 return struct {
...@@ -27,8 +28,11 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -27,8 +28,11 @@ pub fn MultiArrayList(comptime S: type) type {
27 capacity: usize,28 capacity: usize,
2829
29 pub fn items(self: Slice, comptime field: Field) []FieldType(field) {30 pub fn items(self: Slice, comptime field: Field) []FieldType(field) {
30 const byte_ptr = self.ptrs[@enumToInt(field)];
31 const F = FieldType(field);31 const F = FieldType(field);
32 if (self.len == 0) {
33 return &[_]F{};
34 }
35 const byte_ptr = self.ptrs[@enumToInt(field)];
32 const casted_ptr = @ptrCast([*]F, @alignCast(@alignOf(F), byte_ptr));36 const casted_ptr = @ptrCast([*]F, @alignCast(@alignOf(F), byte_ptr));
33 return casted_ptr[0..self.len];37 return casted_ptr[0..self.len];
34 }38 }
...@@ -247,6 +251,7 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -247,6 +251,7 @@ pub fn MultiArrayList(comptime S: type) type {
247 .exact,251 .exact,
248 );252 );
249 if (self.len == 0) {253 if (self.len == 0) {
254 gpa.free(self.allocatedBytes());
250 self.bytes = new_bytes.ptr;255 self.bytes = new_bytes.ptr;
251 self.capacity = new_capacity;256 self.capacity = new_capacity;
252 return;257 return;
...@@ -287,7 +292,6 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -287,7 +292,6 @@ pub fn MultiArrayList(comptime S: type) type {
287}292}
288293
289test "basic usage" {294test "basic usage" {
290 const testing = std.testing;
291 const ally = testing.allocator;295 const ally = testing.allocator;
292296
293 const Foo = struct {297 const Foo = struct {
...@@ -299,6 +303,8 @@ test "basic usage" {...@@ -299,6 +303,8 @@ test "basic usage" {
299 var list = MultiArrayList(Foo){};303 var list = MultiArrayList(Foo){};
300 defer list.deinit(ally);304 defer list.deinit(ally);
301305
306 testing.expectEqual(@as(usize, 0), list.items(.a).len);
307
302 try list.ensureCapacity(ally, 2);308 try list.ensureCapacity(ally, 2);
303309
304 list.appendAssumeCapacity(.{310 list.appendAssumeCapacity(.{
...@@ -369,7 +375,7 @@ test "basic usage" {...@@ -369,7 +375,7 @@ test "basic usage" {
369// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes375// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes
370// function used the @reduce code path.376// function used the @reduce code path.
371test "regression test for @reduce bug" {377test "regression test for @reduce bug" {
372 const ally = std.testing.allocator;378 const ally = testing.allocator;
373 var list = MultiArrayList(struct {379 var list = MultiArrayList(struct {
374 tag: std.zig.Token.Tag,380 tag: std.zig.Token.Tag,
375 start: u32,381 start: u32,
...@@ -412,35 +418,70 @@ test "regression test for @reduce bug" {...@@ -412,35 +418,70 @@ test "regression test for @reduce bug" {
412 try list.append(ally, .{ .tag = .eof, .start = 123 });418 try list.append(ally, .{ .tag = .eof, .start = 123 });
413419
414 const tags = list.items(.tag);420 const tags = list.items(.tag);
415 std.testing.expectEqual(tags[1], .identifier);421 testing.expectEqual(tags[1], .identifier);
416 std.testing.expectEqual(tags[2], .equal);422 testing.expectEqual(tags[2], .equal);
417 std.testing.expectEqual(tags[3], .builtin);423 testing.expectEqual(tags[3], .builtin);
418 std.testing.expectEqual(tags[4], .l_paren);424 testing.expectEqual(tags[4], .l_paren);
419 std.testing.expectEqual(tags[5], .string_literal);425 testing.expectEqual(tags[5], .string_literal);
420 std.testing.expectEqual(tags[6], .r_paren);426 testing.expectEqual(tags[6], .r_paren);
421 std.testing.expectEqual(tags[7], .semicolon);427 testing.expectEqual(tags[7], .semicolon);
422 std.testing.expectEqual(tags[8], .keyword_pub);428 testing.expectEqual(tags[8], .keyword_pub);
423 std.testing.expectEqual(tags[9], .keyword_fn);429 testing.expectEqual(tags[9], .keyword_fn);
424 std.testing.expectEqual(tags[10], .identifier);430 testing.expectEqual(tags[10], .identifier);
425 std.testing.expectEqual(tags[11], .l_paren);431 testing.expectEqual(tags[11], .l_paren);
426 std.testing.expectEqual(tags[12], .r_paren);432 testing.expectEqual(tags[12], .r_paren);
427 std.testing.expectEqual(tags[13], .identifier);433 testing.expectEqual(tags[13], .identifier);
428 std.testing.expectEqual(tags[14], .bang);434 testing.expectEqual(tags[14], .bang);
429 std.testing.expectEqual(tags[15], .identifier);435 testing.expectEqual(tags[15], .identifier);
430 std.testing.expectEqual(tags[16], .l_brace);436 testing.expectEqual(tags[16], .l_brace);
431 std.testing.expectEqual(tags[17], .identifier);437 testing.expectEqual(tags[17], .identifier);
432 std.testing.expectEqual(tags[18], .period);438 testing.expectEqual(tags[18], .period);
433 std.testing.expectEqual(tags[19], .identifier);439 testing.expectEqual(tags[19], .identifier);
434 std.testing.expectEqual(tags[20], .period);440 testing.expectEqual(tags[20], .period);
435 std.testing.expectEqual(tags[21], .identifier);441 testing.expectEqual(tags[21], .identifier);
436 std.testing.expectEqual(tags[22], .l_paren);442 testing.expectEqual(tags[22], .l_paren);
437 std.testing.expectEqual(tags[23], .string_literal);443 testing.expectEqual(tags[23], .string_literal);
438 std.testing.expectEqual(tags[24], .comma);444 testing.expectEqual(tags[24], .comma);
439 std.testing.expectEqual(tags[25], .period);445 testing.expectEqual(tags[25], .period);
440 std.testing.expectEqual(tags[26], .l_brace);446 testing.expectEqual(tags[26], .l_brace);
441 std.testing.expectEqual(tags[27], .r_brace);447 testing.expectEqual(tags[27], .r_brace);
442 std.testing.expectEqual(tags[28], .r_paren);448 testing.expectEqual(tags[28], .r_paren);
443 std.testing.expectEqual(tags[29], .semicolon);449 testing.expectEqual(tags[29], .semicolon);
444 std.testing.expectEqual(tags[30], .r_brace);450 testing.expectEqual(tags[30], .r_brace);
445 std.testing.expectEqual(tags[31], .eof);451 testing.expectEqual(tags[31], .eof);
452}
453
454test "ensure capacity on empty list" {
455 const ally = testing.allocator;
456
457 const Foo = struct {
458 a: u32,
459 b: u8,
460 };
461
462 var list = MultiArrayList(Foo){};
463 defer list.deinit(ally);
464
465 try list.ensureCapacity(ally, 2);
466 list.appendAssumeCapacity(.{ .a = 1, .b = 2 });
467 list.appendAssumeCapacity(.{ .a = 3, .b = 4 });
468
469 testing.expectEqualSlices(u32, &[_]u32{ 1, 3 }, list.items(.a));
470 testing.expectEqualSlices(u8, &[_]u8{ 2, 4 }, list.items(.b));
471
472 list.len = 0;
473 list.appendAssumeCapacity(.{ .a = 5, .b = 6 });
474 list.appendAssumeCapacity(.{ .a = 7, .b = 8 });
475
476 testing.expectEqualSlices(u32, &[_]u32{ 5, 7 }, list.items(.a));
477 testing.expectEqualSlices(u8, &[_]u8{ 6, 8 }, list.items(.b));
478
479 list.len = 0;
480 try list.ensureCapacity(ally, 16);
481
482 list.appendAssumeCapacity(.{ .a = 9, .b = 10 });
483 list.appendAssumeCapacity(.{ .a = 11, .b = 12 });
484
485 testing.expectEqualSlices(u32, &[_]u32{ 9, 11 }, list.items(.a));
486 testing.expectEqualSlices(u8, &[_]u8{ 10, 12 }, list.items(.b));
446}487}
lib/std/os.zig+20-14
...@@ -144,25 +144,27 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {...@@ -144,25 +144,27 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
144 std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;144 std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;
145145
146 while (buf.len != 0) {146 while (buf.len != 0) {
147 var err: u16 = undefined;147 const res = if (use_c) blk: {
148
149 const num_read = if (use_c) blk: {
150 const rc = std.c.getrandom(buf.ptr, buf.len, 0);148 const rc = std.c.getrandom(buf.ptr, buf.len, 0);
151 err = std.c.getErrno(rc);149 break :blk .{
152 break :blk @bitCast(usize, rc);150 .num_read = @bitCast(usize, rc),
151 .err = std.c.getErrno(rc),
152 };
153 } else blk: {153 } else blk: {
154 const rc = linux.getrandom(buf.ptr, buf.len, 0);154 const rc = linux.getrandom(buf.ptr, buf.len, 0);
155 err = linux.getErrno(rc);155 break :blk .{
156 break :blk rc;156 .num_read = rc,
157 .err = linux.getErrno(rc),
158 };
157 };159 };
158160
159 switch (err) {161 switch (res.err) {
160 0 => buf = buf[num_read..],162 0 => buf = buf[res.num_read..],
161 EINVAL => unreachable,163 EINVAL => unreachable,
162 EFAULT => unreachable,164 EFAULT => unreachable,
163 EINTR => continue,165 EINTR => continue,
164 ENOSYS => return getRandomBytesDevURandom(buf),166 ENOSYS => return getRandomBytesDevURandom(buf),
165 else => return unexpectedErrno(err),167 else => return unexpectedErrno(res.err),
166 }168 }
167 }169 }
168 return;170 return;
...@@ -1500,7 +1502,7 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {...@@ -1500,7 +1502,7 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
1500 EINVAL => unreachable,1502 EINVAL => unreachable,
1501 ENOENT => return error.CurrentWorkingDirectoryUnlinked,1503 ENOENT => return error.CurrentWorkingDirectoryUnlinked,
1502 ERANGE => return error.NameTooLong,1504 ERANGE => return error.NameTooLong,
1503 else => return unexpectedErrno(@intCast(usize, err)),1505 else => return unexpectedErrno(err),
1504 }1506 }
1505}1507}
15061508
...@@ -3661,7 +3663,7 @@ pub fn mmap(...@@ -3661,7 +3663,7 @@ pub fn mmap(
3661 const err = if (builtin.link_libc) blk: {3663 const err = if (builtin.link_libc) blk: {
3662 const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);3664 const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
3663 if (rc != std.c.MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];3665 if (rc != std.c.MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
3664 break :blk @intCast(usize, system._errno().*);3666 break :blk system._errno().*;
3665 } else blk: {3667 } else blk: {
3666 const rc = system.mmap(ptr, length, prot, flags, fd, offset);3668 const rc = system.mmap(ptr, length, prot, flags, fd, offset);
3667 const err = errno(rc);3669 const err = errno(rc);
...@@ -4321,7 +4323,7 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP...@@ -4321,7 +4323,7 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
4321 ENAMETOOLONG => return error.NameTooLong,4323 ENAMETOOLONG => return error.NameTooLong,
4322 ELOOP => return error.SymLinkLoop,4324 ELOOP => return error.SymLinkLoop,
4323 EIO => return error.InputOutput,4325 EIO => return error.InputOutput,
4324 else => |err| return unexpectedErrno(@intCast(usize, err)),4326 else => |err| return unexpectedErrno(err),
4325 };4327 };
4326 return mem.spanZ(result_path);4328 return mem.spanZ(result_path);
4327}4329}
...@@ -4622,7 +4624,11 @@ pub const UnexpectedError = error{...@@ -4622,7 +4624,11 @@ pub const UnexpectedError = error{
46224624
4623/// Call this when you made a syscall or something that sets errno4625/// Call this when you made a syscall or something that sets errno
4624/// and you get an unexpected error.4626/// and you get an unexpected error.
4625pub fn unexpectedErrno(err: usize) UnexpectedError {4627pub fn unexpectedErrno(err: anytype) UnexpectedError {
4628 if (@typeInfo(@TypeOf(err)) != .Int) {
4629 @compileError("err is expected to be an integer");
4630 }
4631
4626 if (unexpected_error_tracing) {4632 if (unexpected_error_tracing) {
4627 std.debug.warn("unexpected errno: {d}\n", .{err});4633 std.debug.warn("unexpected errno: {d}\n", .{err});
4628 std.debug.dumpCurrentStackTrace(null);4634 std.debug.dumpCurrentStackTrace(null);
lib/std/os/linux/io_uring.zig+4-4
...@@ -163,9 +163,9 @@ pub const IO_Uring = struct {...@@ -163,9 +163,9 @@ pub const IO_Uring = struct {
163 /// Returns the number of SQEs submitted.163 /// Returns the number of SQEs submitted.
164 /// Matches the implementation of io_uring_submit_and_wait() in liburing.164 /// Matches the implementation of io_uring_submit_and_wait() in liburing.
165 pub fn submit_and_wait(self: *IO_Uring, wait_nr: u32) !u32 {165 pub fn submit_and_wait(self: *IO_Uring, wait_nr: u32) !u32 {
166 var submitted = self.flush_sq();166 const submitted = self.flush_sq();
167 var flags: u32 = 0;167 var flags: u32 = 0;
168 if (self.sq_ring_needs_enter(submitted, &flags) or wait_nr > 0) {168 if (self.sq_ring_needs_enter(&flags) or wait_nr > 0) {
169 if (wait_nr > 0 or (self.flags & linux.IORING_SETUP_IOPOLL) != 0) {169 if (wait_nr > 0 or (self.flags & linux.IORING_SETUP_IOPOLL) != 0) {
170 flags |= linux.IORING_ENTER_GETEVENTS;170 flags |= linux.IORING_ENTER_GETEVENTS;
171 }171 }
...@@ -236,9 +236,9 @@ pub const IO_Uring = struct {...@@ -236,9 +236,9 @@ pub const IO_Uring = struct {
236 /// or if IORING_SQ_NEED_WAKEUP is set and the SQ thread must be explicitly awakened.236 /// or if IORING_SQ_NEED_WAKEUP is set and the SQ thread must be explicitly awakened.
237 /// For the latter case, we set the SQ thread wakeup flag.237 /// For the latter case, we set the SQ thread wakeup flag.
238 /// Matches the implementation of sq_ring_needs_enter() in liburing.238 /// Matches the implementation of sq_ring_needs_enter() in liburing.
239 pub fn sq_ring_needs_enter(self: *IO_Uring, submitted: u32, flags: *u32) bool {239 pub fn sq_ring_needs_enter(self: *IO_Uring, flags: *u32) bool {
240 assert(flags.* == 0);240 assert(flags.* == 0);
241 if ((self.flags & linux.IORING_SETUP_SQPOLL) == 0 and submitted > 0) return true;241 if ((self.flags & linux.IORING_SETUP_SQPOLL) == 0) return true;
242 if ((@atomicLoad(u32, self.sq.flags, .Unordered) & linux.IORING_SQ_NEED_WAKEUP) != 0) {242 if ((@atomicLoad(u32, self.sq.flags, .Unordered) & linux.IORING_SQ_NEED_WAKEUP) != 0) {
243 flags.* |= linux.IORING_ENTER_SQ_WAKEUP;243 flags.* |= linux.IORING_ENTER_SQ_WAKEUP;
244 return true;244 return true;
lib/std/special/init-exe/build.zig+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const Builder = @import("std").build.Builder;1const std = @import("std");
22
3pub fn build(b: *Builder) void {3pub fn build(b: *std.build.Builder) void {
4 // Standard target options allows the person running `zig build` to choose4 // Standard target options allows the person running `zig build` to choose
5 // what target to build for. Here we do not override the defaults, which5 // what target to build for. Here we do not override the defaults, which
6 // means any target is allowed, and the default is native. Other options6 // means any target is allowed, and the default is native. Other options
lib/std/special/init-lib/build.zig+5-2
...@@ -1,7 +1,10 @@...@@ -1,7 +1,10 @@
1const Builder = @import("std").build.Builder;1const std = @import("std");
22
3pub fn build(b: *Builder) void {3pub fn build(b: *std.build.Builder) void {
4 // Standard release options allow the person running `zig build` to select
5 // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
4 const mode = b.standardReleaseOptions();6 const mode = b.standardReleaseOptions();
7
5 const lib = b.addStaticLibrary("$", "src/main.zig");8 const lib = b.addStaticLibrary("$", "src/main.zig");
6 lib.setBuildMode(mode);9 lib.setBuildMode(mode);
7 lib.install();10 lib.install();
lib/std/zig/ast.zig+12-7
...@@ -275,8 +275,10 @@ pub const Tree = struct {...@@ -275,8 +275,10 @@ pub const Tree = struct {
275 .extra_volatile_qualifier => {275 .extra_volatile_qualifier => {
276 return stream.writeAll("extra volatile qualifier");276 return stream.writeAll("extra volatile qualifier");
277 },277 },
278 .invalid_align => {278 .ptr_mod_on_array_child_type => {
279 return stream.writeAll("alignment not allowed on arrays");279 return stream.print("pointer modifier '{s}' not allowed on array child type", .{
280 token_tags[parse_error.token].symbol(),
281 });
280 },282 },
281 .invalid_and => {283 .invalid_and => {
282 return stream.writeAll("`&&` is invalid; note that `and` is boolean AND");284 return stream.writeAll("`&&` is invalid; note that `and` is boolean AND");
...@@ -525,7 +527,9 @@ pub const Tree = struct {...@@ -525,7 +527,9 @@ pub const Tree = struct {
525 => {527 => {
526 // Look for a label.528 // Look for a label.
527 const lbrace = main_tokens[n];529 const lbrace = main_tokens[n];
528 if (token_tags[lbrace - 1] == .colon) {530 if (token_tags[lbrace - 1] == .colon and
531 token_tags[lbrace - 2] == .identifier)
532 {
529 end_offset += 2;533 end_offset += 2;
530 }534 }
531 return lbrace - end_offset;535 return lbrace - end_offset;
...@@ -766,7 +770,7 @@ pub const Tree = struct {...@@ -766,7 +770,7 @@ pub const Tree = struct {
766 .container_decl_arg => {770 .container_decl_arg => {
767 const members = tree.extraData(datas[n].rhs, Node.SubRange);771 const members = tree.extraData(datas[n].rhs, Node.SubRange);
768 if (members.end - members.start == 0) {772 if (members.end - members.start == 0) {
769 end_offset += 1; // for the rparen773 end_offset += 3; // for the rparen + lbrace + rbrace
770 n = datas[n].lhs;774 n = datas[n].lhs;
771 } else {775 } else {
772 end_offset += 1; // for the rbrace776 end_offset += 1; // for the rbrace
...@@ -989,13 +993,13 @@ pub const Tree = struct {...@@ -989,13 +993,13 @@ pub const Tree = struct {
989 },993 },
990 .slice => {994 .slice => {
991 const extra = tree.extraData(datas[n].rhs, Node.Slice);995 const extra = tree.extraData(datas[n].rhs, Node.Slice);
992 assert(extra.end != 0); // should have used SliceOpen996 assert(extra.end != 0); // should have used slice_open
993 end_offset += 1; // rbracket997 end_offset += 1; // rbracket
994 n = extra.end;998 n = extra.end;
995 },999 },
996 .slice_sentinel => {1000 .slice_sentinel => {
997 const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);1001 const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);
998 assert(extra.sentinel != 0); // should have used Slice1002 assert(extra.sentinel != 0); // should have used slice
999 end_offset += 1; // rbracket1003 end_offset += 1; // rbracket
1000 n = extra.sentinel;1004 n = extra.sentinel;
1001 },1005 },
...@@ -2386,7 +2390,7 @@ pub const Error = struct {...@@ -2386,7 +2390,7 @@ pub const Error = struct {
2386 extra_allowzero_qualifier,2390 extra_allowzero_qualifier,
2387 extra_const_qualifier,2391 extra_const_qualifier,
2388 extra_volatile_qualifier,2392 extra_volatile_qualifier,
2389 invalid_align,2393 ptr_mod_on_array_child_type,
2390 invalid_and,2394 invalid_and,
2391 invalid_bit_range,2395 invalid_bit_range,
2392 invalid_token,2396 invalid_token,
...@@ -2925,6 +2929,7 @@ pub const Node = struct {...@@ -2925,6 +2929,7 @@ pub const Node = struct {
29252929
2926 pub const SliceSentinel = struct {2930 pub const SliceSentinel = struct {
2927 start: Index,2931 start: Index,
2932 /// May be 0 if the slice is "open"
2928 end: Index,2933 end: Index,
2929 sentinel: Index,2934 sentinel: Index,
2930 };2935 };
lib/std/zig/parse.zig+44-38
...@@ -937,14 +937,17 @@ const Parser = struct {...@@ -937,14 +937,17 @@ const Parser = struct {
937 /// If a parse error occurs, reports an error, but then finds the next statement937 /// If a parse error occurs, reports an error, but then finds the next statement
938 /// and returns that one instead. If a parse error occurs but there is no following938 /// and returns that one instead. If a parse error occurs but there is no following
939 /// statement, returns 0.939 /// statement, returns 0.
940 fn expectStatementRecoverable(p: *Parser) error{OutOfMemory}!Node.Index {940 fn expectStatementRecoverable(p: *Parser) Error!Node.Index {
941 while (true) {941 while (true) {
942 return p.expectStatement() catch |err| switch (err) {942 return p.expectStatement() catch |err| switch (err) {
943 error.OutOfMemory => return error.OutOfMemory,943 error.OutOfMemory => return error.OutOfMemory,
944 error.ParseError => {944 error.ParseError => {
945 p.findNextStmt(); // Try to skip to the next statement.945 p.findNextStmt(); // Try to skip to the next statement.
946 if (p.token_tags[p.tok_i] == .r_brace) return null_node;946 switch (p.token_tags[p.tok_i]) {
947 continue;947 .r_brace => return null_node,
948 .eof => return error.ParseError,
949 else => continue,
950 }
948 },951 },
949 };952 };
950 }953 }
...@@ -1609,13 +1612,15 @@ const Parser = struct {...@@ -1609,13 +1612,15 @@ const Parser = struct {
1609 /// PrefixTypeOp1612 /// PrefixTypeOp
1610 /// <- QUESTIONMARK1613 /// <- QUESTIONMARK
1611 /// / KEYWORD_anyframe MINUSRARROW1614 /// / KEYWORD_anyframe MINUSRARROW
1612 /// / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*1615 /// / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1613 /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*1616 /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1617 /// / ArrayTypeStart
1618 /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
1614 /// PtrTypeStart1619 /// PtrTypeStart
1615 /// <- ASTERISK1620 /// <- ASTERISK
1616 /// / ASTERISK21621 /// / ASTERISK2
1617 /// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET1622 /// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
1618 /// ArrayTypeStart <- LBRACKET Expr? (COLON Expr)? RBRACKET1623 /// ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET
1619 fn parseTypeExpr(p: *Parser) Error!Node.Index {1624 fn parseTypeExpr(p: *Parser) Error!Node.Index {
1620 switch (p.token_tags[p.tok_i]) {1625 switch (p.token_tags[p.tok_i]) {
1621 .question_mark => return p.addNode(.{1626 .question_mark => return p.addNode(.{
...@@ -1782,15 +1787,15 @@ const Parser = struct {...@@ -1782,15 +1787,15 @@ const Parser = struct {
1782 else1787 else
1783 0;1788 0;
1784 _ = try p.expectToken(.r_bracket);1789 _ = try p.expectToken(.r_bracket);
1785 const mods = try p.parsePtrModifiers();
1786 const elem_type = try p.expectTypeExpr();
1787 if (mods.bit_range_start != 0) {
1788 try p.warnMsg(.{
1789 .tag = .invalid_bit_range,
1790 .token = p.nodes.items(.main_token)[mods.bit_range_start],
1791 });
1792 }
1793 if (len_expr == 0) {1790 if (len_expr == 0) {
1791 const mods = try p.parsePtrModifiers();
1792 const elem_type = try p.expectTypeExpr();
1793 if (mods.bit_range_start != 0) {
1794 try p.warnMsg(.{
1795 .tag = .invalid_bit_range,
1796 .token = p.nodes.items(.main_token)[mods.bit_range_start],
1797 });
1798 }
1794 if (sentinel == 0) {1799 if (sentinel == 0) {
1795 return p.addNode(.{1800 return p.addNode(.{
1796 .tag = .ptr_type_aligned,1801 .tag = .ptr_type_aligned,
...@@ -1823,12 +1828,15 @@ const Parser = struct {...@@ -1823,12 +1828,15 @@ const Parser = struct {
1823 });1828 });
1824 }1829 }
1825 } else {1830 } else {
1826 if (mods.align_node != 0) {1831 switch (p.token_tags[p.tok_i]) {
1827 try p.warnMsg(.{1832 .keyword_align,
1828 .tag = .invalid_align,1833 .keyword_const,
1829 .token = p.nodes.items(.main_token)[mods.align_node],1834 .keyword_volatile,
1830 });1835 .keyword_allowzero,
1836 => return p.fail(.ptr_mod_on_array_child_type),
1837 else => {},
1831 }1838 }
1839 const elem_type = try p.expectTypeExpr();
1832 if (sentinel == 0) {1840 if (sentinel == 0) {
1833 return p.addNode(.{1841 return p.addNode(.{
1834 .tag = .array_type,1842 .tag = .array_type,
...@@ -1978,7 +1986,7 @@ const Parser = struct {...@@ -1978,7 +1986,7 @@ const Parser = struct {
1978 }1986 }
1979 },1987 },
1980 .keyword_inline => {1988 .keyword_inline => {
1981 p.tok_i += 2;1989 p.tok_i += 1;
1982 switch (p.token_tags[p.tok_i]) {1990 switch (p.token_tags[p.tok_i]) {
1983 .keyword_for => return p.parseForExpr(),1991 .keyword_for => return p.parseForExpr(),
1984 .keyword_while => return p.parseWhileExpr(),1992 .keyword_while => return p.parseWhileExpr(),
...@@ -3438,7 +3446,7 @@ const Parser = struct {...@@ -3438,7 +3446,7 @@ const Parser = struct {
3438 }3446 }
34393447
3440 /// SuffixOp3448 /// SuffixOp
3441 /// <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET3449 /// <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET
3442 /// / DOT IDENTIFIER3450 /// / DOT IDENTIFIER
3443 /// / DOTASTERISK3451 /// / DOTASTERISK
3444 /// / DOTQUESTIONMARK3452 /// / DOTQUESTIONMARK
...@@ -3450,17 +3458,6 @@ const Parser = struct {...@@ -3450,17 +3458,6 @@ const Parser = struct {
34503458
3451 if (p.eatToken(.ellipsis2)) |_| {3459 if (p.eatToken(.ellipsis2)) |_| {
3452 const end_expr = try p.parseExpr();3460 const end_expr = try p.parseExpr();
3453 if (end_expr == 0) {
3454 _ = try p.expectToken(.r_bracket);
3455 return p.addNode(.{
3456 .tag = .slice_open,
3457 .main_token = lbracket,
3458 .data = .{
3459 .lhs = lhs,
3460 .rhs = index_expr,
3461 },
3462 });
3463 }
3464 if (p.eatToken(.colon)) |_| {3461 if (p.eatToken(.colon)) |_| {
3465 const sentinel = try p.parseExpr();3462 const sentinel = try p.parseExpr();
3466 _ = try p.expectToken(.r_bracket);3463 _ = try p.expectToken(.r_bracket);
...@@ -3476,20 +3473,29 @@ const Parser = struct {...@@ -3476,20 +3473,29 @@ const Parser = struct {
3476 }),3473 }),
3477 },3474 },
3478 });3475 });
3479 } else {3476 }
3480 _ = try p.expectToken(.r_bracket);3477 _ = try p.expectToken(.r_bracket);
3478 if (end_expr == 0) {
3481 return p.addNode(.{3479 return p.addNode(.{
3482 .tag = .slice,3480 .tag = .slice_open,
3483 .main_token = lbracket,3481 .main_token = lbracket,
3484 .data = .{3482 .data = .{
3485 .lhs = lhs,3483 .lhs = lhs,
3486 .rhs = try p.addExtra(Node.Slice{3484 .rhs = index_expr,
3487 .start = index_expr,
3488 .end = end_expr,
3489 }),
3490 },3485 },
3491 });3486 });
3492 }3487 }
3488 return p.addNode(.{
3489 .tag = .slice,
3490 .main_token = lbracket,
3491 .data = .{
3492 .lhs = lhs,
3493 .rhs = try p.addExtra(Node.Slice{
3494 .start = index_expr,
3495 .end = end_expr,
3496 }),
3497 },
3498 });
3493 }3499 }
3494 _ = try p.expectToken(.r_bracket);3500 _ = try p.expectToken(.r_bracket);
3495 return p.addNode(.{3501 return p.addNode(.{
lib/std/zig/parser_test.zig+54-3
...@@ -852,6 +852,7 @@ test "zig fmt: slices" {...@@ -852,6 +852,7 @@ test "zig fmt: slices" {
852 try testCanonical(852 try testCanonical(
853 \\const a = b[0..];853 \\const a = b[0..];
854 \\const c = d[0..1];854 \\const c = d[0..1];
855 \\const d = f[0.. :0];
855 \\const e = f[0..1 :0];856 \\const e = f[0..1 :0];
856 \\857 \\
857 );858 );
...@@ -861,6 +862,7 @@ test "zig fmt: slices with spaces in bounds" {...@@ -861,6 +862,7 @@ test "zig fmt: slices with spaces in bounds" {
861 try testCanonical(862 try testCanonical(
862 \\const a = b[0 + 0 ..];863 \\const a = b[0 + 0 ..];
863 \\const c = d[0 + 0 .. 1];864 \\const c = d[0 + 0 .. 1];
865 \\const c = d[0 + 0 .. :0];
864 \\const e = f[0 .. 1 + 1 :0];866 \\const e = f[0 .. 1 + 1 :0];
865 \\867 \\
866 );868 );
...@@ -963,6 +965,27 @@ test "zig fmt: allowzero pointer" {...@@ -963,6 +965,27 @@ test "zig fmt: allowzero pointer" {
963 );965 );
964}966}
965967
968test "zig fmt: empty enum decls" {
969 try testCanonical(
970 \\const A = enum {};
971 \\const B = enum(u32) {};
972 \\const C = extern enum(c_int) {};
973 \\const D = packed enum(u8) {};
974 \\
975 );
976}
977
978test "zig fmt: empty union decls" {
979 try testCanonical(
980 \\const A = union {};
981 \\const B = union(enum) {};
982 \\const C = union(Foo) {};
983 \\const D = extern union {};
984 \\const E = packed union {};
985 \\
986 );
987}
988
966test "zig fmt: enum literal" {989test "zig fmt: enum literal" {
967 try testCanonical(990 try testCanonical(
968 \\const x = .hi;991 \\const x = .hi;
...@@ -4276,6 +4299,18 @@ test "zig fmt: respect extra newline between switch items" {...@@ -4276,6 +4299,18 @@ test "zig fmt: respect extra newline between switch items" {
4276 );4299 );
4277}4300}
42784301
4302test "zig fmt: assignment with inline for and inline while" {
4303 try testCanonical(
4304 \\const tmp = inline for (items) |item| {};
4305 \\
4306 );
4307
4308 try testCanonical(
4309 \\const tmp2 = inline while (true) {};
4310 \\
4311 );
4312}
4313
4279test "zig fmt: insert trailing comma if there are comments between switch values" {4314test "zig fmt: insert trailing comma if there are comments between switch values" {
4280 try testTransform(4315 try testTransform(
4281 \\const a = switch (b) {4316 \\const a = switch (b) {
...@@ -4315,11 +4350,17 @@ test "zig fmt: error for invalid bit range" {...@@ -4315,11 +4350,17 @@ test "zig fmt: error for invalid bit range" {
4315 });4350 });
4316}4351}
43174352
4318test "zig fmt: error for invalid align" {4353test "zig fmt: error for ptr mod on array child type" {
4319 try testError(4354 try testError(
4320 \\var x: [10]align(10)u8 = bar;4355 \\var a: [10]align(10) u8 = e;
4356 \\var b: [10]const u8 = f;
4357 \\var c: [10]volatile u8 = g;
4358 \\var d: [10]allowzero u8 = h;
4321 , &[_]Error{4359 , &[_]Error{
4322 .invalid_align,4360 .ptr_mod_on_array_child_type,
4361 .ptr_mod_on_array_child_type,
4362 .ptr_mod_on_array_child_type,
4363 .ptr_mod_on_array_child_type,
4323 });4364 });
4324}4365}
43254366
...@@ -4580,6 +4621,16 @@ test "recovery: missing comma in params" {...@@ -4580,6 +4621,16 @@ test "recovery: missing comma in params" {
4580 });4621 });
4581}4622}
45824623
4624test "recovery: missing while rbrace" {
4625 try testError(
4626 \\fn a() b {
4627 \\ while (d) {
4628 \\}
4629 , &[_]Error{
4630 .expected_statement,
4631 });
4632}
4633
4583const std = @import("std");4634const std = @import("std");
4584const mem = std.mem;4635const mem = std.mem;
4585const warn = std.debug.warn;4636const warn = std.debug.warn;
lib/std/zig/render.zig+15-14
...@@ -470,9 +470,9 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I...@@ -470,9 +470,9 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I
470 return renderToken(ais, tree, rbracket, space); // ]470 return renderToken(ais, tree, rbracket, space); // ]
471 },471 },
472472
473 .slice_open => return renderSlice(gpa, ais, tree, tree.sliceOpen(node), space),473 .slice_open => return renderSlice(gpa, ais, tree, node, tree.sliceOpen(node), space),
474 .slice => return renderSlice(gpa, ais, tree, tree.slice(node), space),474 .slice => return renderSlice(gpa, ais, tree, node, tree.slice(node), space),
475 .slice_sentinel => return renderSlice(gpa, ais, tree, tree.sliceSentinel(node), space),475 .slice_sentinel => return renderSlice(gpa, ais, tree, node, tree.sliceSentinel(node), space),
476476
477 .deref => {477 .deref => {
478 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);478 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
...@@ -815,6 +815,7 @@ fn renderSlice(...@@ -815,6 +815,7 @@ fn renderSlice(
815 gpa: *Allocator,815 gpa: *Allocator,
816 ais: *Ais,816 ais: *Ais,
817 tree: ast.Tree,817 tree: ast.Tree,
818 slice_node: ast.Node.Index,
818 slice: ast.full.Slice,819 slice: ast.full.Slice,
819 space: Space,820 space: Space,
820) Error!void {821) Error!void {
...@@ -822,7 +823,9 @@ fn renderSlice(...@@ -822,7 +823,9 @@ fn renderSlice(
822 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or823 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or
823 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;824 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
824 const after_start_space = if (after_start_space_bool) Space.space else Space.none;825 const after_start_space = if (after_start_space_bool) Space.space else Space.none;
825 const after_dots_space = if (slice.ast.end != 0) after_start_space else Space.none;826 const after_dots_space = if (slice.ast.end != 0)
827 after_start_space
828 else if (slice.ast.sentinel != 0) Space.space else Space.none;
826829
827 try renderExpression(gpa, ais, tree, slice.ast.sliced, .none);830 try renderExpression(gpa, ais, tree, slice.ast.sliced, .none);
828 try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket831 try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket
...@@ -830,20 +833,18 @@ fn renderSlice(...@@ -830,20 +833,18 @@ fn renderSlice(
830 const start_last = tree.lastToken(slice.ast.start);833 const start_last = tree.lastToken(slice.ast.start);
831 try renderExpression(gpa, ais, tree, slice.ast.start, after_start_space);834 try renderExpression(gpa, ais, tree, slice.ast.start, after_start_space);
832 try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")835 try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")
833 if (slice.ast.end == 0) {836
834 return renderToken(ais, tree, start_last + 2, space); // rbracket837 if (slice.ast.end != 0) {
838 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;
839 try renderExpression(gpa, ais, tree, slice.ast.end, after_end_space);
835 }840 }
836841
837 const end_last = tree.lastToken(slice.ast.end);842 if (slice.ast.sentinel != 0) {
838 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;843 try renderToken(ais, tree, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon
839 try renderExpression(gpa, ais, tree, slice.ast.end, after_end_space);844 try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none);
840 if (slice.ast.sentinel == 0) {
841 return renderToken(ais, tree, end_last + 1, space); // rbracket
842 }845 }
843846
844 try renderToken(ais, tree, end_last + 1, .none); // colon847 try renderToken(ais, tree, tree.lastToken(slice_node), space); // rbracket
845 try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none);
846 try renderToken(ais, tree, tree.lastToken(slice.ast.sentinel) + 1, space); // rbracket
847}848}
848849
849fn renderAsmOutput(850fn renderAsmOutput(
src/Compilation.zig+2
...@@ -1653,6 +1653,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1653,6 +1653,8 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1653 .error_msg = null,1653 .error_msg = null,
1654 .decl = decl,1654 .decl = decl,
1655 .fwd_decl = fwd_decl.toManaged(module.gpa),1655 .fwd_decl = fwd_decl.toManaged(module.gpa),
1656 // we don't want to emit optionals and error unions to headers since they have no ABI
1657 .typedefs = undefined,
1656 };1658 };
1657 defer dg.fwd_decl.deinit();1659 defer dg.fwd_decl.deinit();
16581660
src/Module.zig+123-16
...@@ -370,6 +370,8 @@ pub const Scope = struct {...@@ -370,6 +370,8 @@ pub const Scope = struct {
370 .gen_zir => return self.cast(GenZIR).?.arena,370 .gen_zir => return self.cast(GenZIR).?.arena,
371 .local_val => return self.cast(LocalVal).?.gen_zir.arena,371 .local_val => return self.cast(LocalVal).?.gen_zir.arena,
372 .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena,372 .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena,
373 .gen_suspend => return self.cast(GenZIR).?.arena,
374 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.arena,
373 .file => unreachable,375 .file => unreachable,
374 .container => unreachable,376 .container => unreachable,
375 }377 }
...@@ -385,6 +387,8 @@ pub const Scope = struct {...@@ -385,6 +387,8 @@ pub const Scope = struct {
385 .gen_zir => self.cast(GenZIR).?.decl,387 .gen_zir => self.cast(GenZIR).?.decl,
386 .local_val => self.cast(LocalVal).?.gen_zir.decl,388 .local_val => self.cast(LocalVal).?.gen_zir.decl,
387 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,389 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
390 .gen_suspend => return self.cast(GenZIR).?.decl,
391 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl,
388 .file => null,392 .file => null,
389 .container => null,393 .container => null,
390 };394 };
...@@ -396,6 +400,8 @@ pub const Scope = struct {...@@ -396,6 +400,8 @@ pub const Scope = struct {
396 .gen_zir => self.cast(GenZIR).?.decl,400 .gen_zir => self.cast(GenZIR).?.decl,
397 .local_val => self.cast(LocalVal).?.gen_zir.decl,401 .local_val => self.cast(LocalVal).?.gen_zir.decl,
398 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,402 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
403 .gen_suspend => return self.cast(GenZIR).?.decl,
404 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl,
399 .file => null,405 .file => null,
400 .container => null,406 .container => null,
401 };407 };
...@@ -410,6 +416,8 @@ pub const Scope = struct {...@@ -410,6 +416,8 @@ pub const Scope = struct {
410 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container,416 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container,
411 .file => return &self.cast(File).?.root_container,417 .file => return &self.cast(File).?.root_container,
412 .container => return self.cast(Container).?,418 .container => return self.cast(Container).?,
419 .gen_suspend => return self.cast(GenZIR).?.decl.container,
420 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl.container,
413 }421 }
414 }422 }
415423
...@@ -422,6 +430,8 @@ pub const Scope = struct {...@@ -422,6 +430,8 @@ pub const Scope = struct {
422 .gen_zir => unreachable,430 .gen_zir => unreachable,
423 .local_val => unreachable,431 .local_val => unreachable,
424 .local_ptr => unreachable,432 .local_ptr => unreachable,
433 .gen_suspend => unreachable,
434 .gen_nosuspend => unreachable,
425 .file => unreachable,435 .file => unreachable,
426 .container => return self.cast(Container).?.fullyQualifiedNameHash(name),436 .container => return self.cast(Container).?.fullyQualifiedNameHash(name),
427 }437 }
...@@ -436,6 +446,8 @@ pub const Scope = struct {...@@ -436,6 +446,8 @@ pub const Scope = struct {
436 .local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree,446 .local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree,
437 .local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree,447 .local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree,
438 .container => return &self.cast(Container).?.file_scope.tree,448 .container => return &self.cast(Container).?.file_scope.tree,
449 .gen_suspend => return &self.cast(GenZIR).?.decl.container.file_scope.tree,
450 .gen_nosuspend => return &self.cast(Nosuspend).?.gen_zir.decl.container.file_scope.tree,
439 }451 }
440 }452 }
441453
...@@ -443,9 +455,10 @@ pub const Scope = struct {...@@ -443,9 +455,10 @@ pub const Scope = struct {
443 pub fn getGenZIR(self: *Scope) *GenZIR {455 pub fn getGenZIR(self: *Scope) *GenZIR {
444 return switch (self.tag) {456 return switch (self.tag) {
445 .block => unreachable,457 .block => unreachable,
446 .gen_zir => self.cast(GenZIR).?,458 .gen_zir, .gen_suspend => self.cast(GenZIR).?,
447 .local_val => return self.cast(LocalVal).?.gen_zir,459 .local_val => return self.cast(LocalVal).?.gen_zir,
448 .local_ptr => return self.cast(LocalPtr).?.gen_zir,460 .local_ptr => return self.cast(LocalPtr).?.gen_zir,
461 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir,
449 .file => unreachable,462 .file => unreachable,
450 .container => unreachable,463 .container => unreachable,
451 };464 };
...@@ -461,6 +474,8 @@ pub const Scope = struct {...@@ -461,6 +474,8 @@ pub const Scope = struct {
461 .gen_zir => unreachable,474 .gen_zir => unreachable,
462 .local_val => unreachable,475 .local_val => unreachable,
463 .local_ptr => unreachable,476 .local_ptr => unreachable,
477 .gen_suspend => unreachable,
478 .gen_nosuspend => unreachable,
464 }479 }
465 }480 }
466481
...@@ -472,6 +487,8 @@ pub const Scope = struct {...@@ -472,6 +487,8 @@ pub const Scope = struct {
472 .local_val => unreachable,487 .local_val => unreachable,
473 .local_ptr => unreachable,488 .local_ptr => unreachable,
474 .block => unreachable,489 .block => unreachable,
490 .gen_suspend => unreachable,
491 .gen_nosuspend => unreachable,
475 }492 }
476 }493 }
477494
...@@ -486,6 +503,36 @@ pub const Scope = struct {...@@ -486,6 +503,36 @@ pub const Scope = struct {
486 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,503 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
487 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,504 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
488 .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope,505 .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope,
506 .gen_suspend => @fieldParentPtr(GenZIR, "base", cur).parent,
507 .gen_nosuspend => @fieldParentPtr(Nosuspend, "base", cur).parent,
508 };
509 }
510 }
511
512 pub fn getSuspend(base: *Scope) ?*Scope.GenZIR {
513 var cur = base;
514 while (true) {
515 cur = switch (cur.tag) {
516 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
517 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
518 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
519 .gen_nosuspend => @fieldParentPtr(Nosuspend, "base", cur).parent,
520 .gen_suspend => return @fieldParentPtr(GenZIR, "base", cur),
521 else => return null,
522 };
523 }
524 }
525
526 pub fn getNosuspend(base: *Scope) ?*Scope.Nosuspend {
527 var cur = base;
528 while (true) {
529 cur = switch (cur.tag) {
530 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
531 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
532 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
533 .gen_suspend => @fieldParentPtr(GenZIR, "base", cur).parent,
534 .gen_nosuspend => return @fieldParentPtr(Nosuspend, "base", cur),
535 else => return null,
489 };536 };
490 }537 }
491 }538 }
...@@ -507,6 +554,8 @@ pub const Scope = struct {...@@ -507,6 +554,8 @@ pub const Scope = struct {
507 gen_zir,554 gen_zir,
508 local_val,555 local_val,
509 local_ptr,556 local_ptr,
557 gen_suspend,
558 gen_nosuspend,
510 };559 };
511560
512 pub const Container = struct {561 pub const Container = struct {
...@@ -740,6 +789,8 @@ pub const Scope = struct {...@@ -740,6 +789,8 @@ pub const Scope = struct {
740 /// so they can possibly be elided later if the labeled block ends up not needing789 /// so they can possibly be elided later if the labeled block ends up not needing
741 /// a result location pointer.790 /// a result location pointer.
742 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{},791 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{},
792 /// for suspend error notes
793 src: usize = 0,
743794
744 pub const Label = struct {795 pub const Label = struct {
745 token: ast.TokenIndex,796 token: ast.TokenIndex,
...@@ -773,6 +824,16 @@ pub const Scope = struct {...@@ -773,6 +824,16 @@ pub const Scope = struct {
773 name: []const u8,824 name: []const u8,
774 ptr: *zir.Inst,825 ptr: *zir.Inst,
775 };826 };
827
828 pub const Nosuspend = struct {
829 pub const base_tag: Tag = .gen_nosuspend;
830
831 base: Scope = Scope{ .tag = base_tag },
832 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZIR`.
833 parent: *Scope,
834 gen_zir: *GenZIR,
835 src: usize,
836 };
776};837};
777838
778/// This struct holds data necessary to construct API-facing `AllErrors.Message`.839/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
...@@ -1122,7 +1183,8 @@ fn astgenAndSemaFn(...@@ -1122,7 +1183,8 @@ fn astgenAndSemaFn(
1122 const param_count = blk: {1183 const param_count = blk: {
1123 var count: usize = 0;1184 var count: usize = 0;
1124 var it = fn_proto.iterate(tree);1185 var it = fn_proto.iterate(tree);
1125 while (it.next()) |_| {1186 while (it.next()) |param| {
1187 if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break;
1126 count += 1;1188 count += 1;
1127 }1189 }
1128 break :blk count;1190 break :blk count;
...@@ -1135,6 +1197,7 @@ fn astgenAndSemaFn(...@@ -1135,6 +1197,7 @@ fn astgenAndSemaFn(
1135 });1197 });
1136 const type_type_rl: astgen.ResultLoc = .{ .ty = type_type };1198 const type_type_rl: astgen.ResultLoc = .{ .ty = type_type };
11371199
1200 var is_var_args = false;
1138 {1201 {
1139 var param_type_i: usize = 0;1202 var param_type_i: usize = 0;
1140 var it = fn_proto.iterate(tree);1203 var it = fn_proto.iterate(tree);
...@@ -1147,12 +1210,10 @@ fn astgenAndSemaFn(...@@ -1147,12 +1210,10 @@ fn astgenAndSemaFn(
1147 "TODO implement anytype parameter",1210 "TODO implement anytype parameter",
1148 .{},1211 .{},
1149 ),1212 ),
1150 .ellipsis3 => return mod.failTok(1213 .ellipsis3 => {
1151 &fn_type_scope.base,1214 is_var_args = true;
1152 token,1215 break;
1153 "TODO implement var args",1216 },
1154 .{},
1155 ),
1156 else => unreachable,1217 else => unreachable,
1157 }1218 }
1158 }1219 }
...@@ -1234,7 +1295,13 @@ fn astgenAndSemaFn(...@@ -1234,7 +1295,13 @@ fn astgenAndSemaFn(
1234 type_type_rl,1295 type_type_rl,
1235 fn_proto.ast.return_type,1296 fn_proto.ast.return_type,
1236 );1297 );
1237 const fn_type_inst = if (fn_proto.ast.callconv_expr != 0) cc: {1298
1299 const is_extern = if (fn_proto.extern_export_token) |maybe_export_token|
1300 token_tags[maybe_export_token] == .keyword_extern
1301 else
1302 false;
1303
1304 const cc_inst = if (fn_proto.ast.callconv_expr != 0) cc: {
1238 // TODO instead of enum literal type, this needs to be the1305 // TODO instead of enum literal type, this needs to be the
1239 // std.builtin.CallingConvention enum. We need to implement importing other files1306 // std.builtin.CallingConvention enum. We need to implement importing other files
1240 // and enums in order to fix this.1307 // and enums in order to fix this.
...@@ -1243,18 +1310,31 @@ fn astgenAndSemaFn(...@@ -1243,18 +1310,31 @@ fn astgenAndSemaFn(
1243 .ty = Type.initTag(.type),1310 .ty = Type.initTag(.type),
1244 .val = Value.initTag(.enum_literal_type),1311 .val = Value.initTag(.enum_literal_type),
1245 });1312 });
1246 const cc = try astgen.comptimeExpr(mod, &fn_type_scope.base, .{1313 break :cc try astgen.comptimeExpr(mod, &fn_type_scope.base, .{
1247 .ty = enum_lit_ty,1314 .ty = enum_lit_ty,
1248 }, fn_proto.ast.callconv_expr);1315 }, fn_proto.ast.callconv_expr);
1249 break :cc try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type_cc, .{1316 } else if (is_extern) cc: {
1317 // note: https://github.com/ziglang/zig/issues/5269
1318 const src = token_starts[fn_proto.extern_export_token.?];
1319 break :cc try astgen.addZIRInst(mod, &fn_type_scope.base, src, zir.Inst.EnumLiteral, .{ .name = "C" }, .{});
1320 } else null;
1321
1322 const fn_type_inst = if (cc_inst) |cc| fn_type: {
1323 var fn_type = try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type_cc, .{
1250 .return_type = return_type_inst,1324 .return_type = return_type_inst,
1251 .param_types = param_types,1325 .param_types = param_types,
1252 .cc = cc,1326 .cc = cc,
1253 });1327 });
1254 } else try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type, .{1328 if (is_var_args) fn_type.tag = .fn_type_cc_var_args;
1255 .return_type = return_type_inst,1329 break :fn_type fn_type;
1256 .param_types = param_types,1330 } else fn_type: {
1257 });1331 var fn_type = try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type, .{
1332 .return_type = return_type_inst,
1333 .param_types = param_types,
1334 });
1335 if (is_var_args) fn_type.tag = .fn_type_var_args;
1336 break :fn_type fn_type;
1337 };
12581338
1259 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {1339 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
1260 zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_scope.instructions.items) catch {};1340 zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_scope.instructions.items) catch {};
...@@ -1287,7 +1367,12 @@ fn astgenAndSemaFn(...@@ -1287,7 +1367,12 @@ fn astgenAndSemaFn(
1287 const fn_type = try zir_sema.analyzeBodyValueAsType(mod, &block_scope, fn_type_inst, .{1367 const fn_type = try zir_sema.analyzeBodyValueAsType(mod, &block_scope, fn_type_inst, .{
1288 .instructions = fn_type_scope.instructions.items,1368 .instructions = fn_type_scope.instructions.items,
1289 });1369 });
1370
1290 if (body_node == 0) {1371 if (body_node == 0) {
1372 if (!is_extern) {
1373 return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function has no body", .{});
1374 }
1375
1291 // Extern function.1376 // Extern function.
1292 var type_changed = true;1377 var type_changed = true;
1293 if (decl.typedValueManaged()) |tvm| {1378 if (decl.typedValueManaged()) |tvm| {
...@@ -1317,6 +1402,10 @@ fn astgenAndSemaFn(...@@ -1317,6 +1402,10 @@ fn astgenAndSemaFn(
1317 return type_changed;1402 return type_changed;
1318 }1403 }
13191404
1405 if (fn_type.fnIsVarArgs()) {
1406 return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function is variadic", .{});
1407 }
1408
1320 const new_func = try decl_arena.allocator.create(Fn);1409 const new_func = try decl_arena.allocator.create(Fn);
1321 const fn_payload = try decl_arena.allocator.create(Value.Payload.Function);1410 const fn_payload = try decl_arena.allocator.create(Value.Payload.Function);
13221411
...@@ -3295,6 +3384,9 @@ pub fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Ty...@@ -3295,6 +3384,9 @@ pub fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Ty
3295}3384}
32963385
3297pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) InnerError!*Inst {3386pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) InnerError!*Inst {
3387 if (dest_type.tag() == .var_args_param) {
3388 return self.coerceVarArgParam(scope, inst);
3389 }
3298 // If the types are the same, we can return the operand.3390 // If the types are the same, we can return the operand.
3299 if (dest_type.eql(inst.ty))3391 if (dest_type.eql(inst.ty))
3300 return inst;3392 return inst;
...@@ -3447,6 +3539,15 @@ pub fn coerceNum(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) Inn...@@ -3447,6 +3539,15 @@ pub fn coerceNum(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) Inn
3447 return null;3539 return null;
3448}3540}
34493541
3542pub fn coerceVarArgParam(mod: *Module, scope: *Scope, inst: *Inst) !*Inst {
3543 switch (inst.ty.zigTypeTag()) {
3544 .ComptimeInt, .ComptimeFloat => return mod.fail(scope, inst.src, "integer and float literals in var args function must be casted", .{}),
3545 else => {},
3546 }
3547 // TODO implement more of this function.
3548 return inst;
3549}
3550
3450pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {3551pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {
3451 if (ptr.ty.isConstPtr())3552 if (ptr.ty.isConstPtr())
3452 return self.fail(scope, src, "cannot assign to constant", .{});3553 return self.fail(scope, src, "cannot assign to constant", .{});
...@@ -3586,7 +3687,7 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I...@@ -3586,7 +3687,7 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I
3586 }3687 }
3587 self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg);3688 self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg);
3588 },3689 },
3589 .gen_zir => {3690 .gen_zir, .gen_suspend => {
3590 const gen_zir = scope.cast(Scope.GenZIR).?;3691 const gen_zir = scope.cast(Scope.GenZIR).?;
3591 gen_zir.decl.analysis = .sema_failure;3692 gen_zir.decl.analysis = .sema_failure;
3592 gen_zir.decl.generation = self.generation;3693 gen_zir.decl.generation = self.generation;
...@@ -3604,6 +3705,12 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I...@@ -3604,6 +3705,12 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I
3604 gen_zir.decl.generation = self.generation;3705 gen_zir.decl.generation = self.generation;
3605 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);3706 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
3606 },3707 },
3708 .gen_nosuspend => {
3709 const gen_zir = scope.cast(Scope.Nosuspend).?.gen_zir;
3710 gen_zir.decl.analysis = .sema_failure;
3711 gen_zir.decl.generation = self.generation;
3712 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
3713 },
3607 .file => unreachable,3714 .file => unreachable,
3608 .container => unreachable,3715 .container => unreachable,
3609 }3716 }
src/astgen.zig+113-6
...@@ -626,10 +626,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In...@@ -626,10 +626,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
626 .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs),626 .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs),
627 .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node),627 .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node),
628628
629 .@"nosuspend" => return nosuspendExpr(mod, scope, rl, node),
630 .@"suspend" => return rvalue(mod, scope, rl, try suspendExpr(mod, scope, node)),
631 .@"await" => return awaitExpr(mod, scope, rl, node),
632 .@"resume" => return rvalue(mod, scope, rl, try resumeExpr(mod, scope, node)),
633
629 .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}),634 .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}),
630 .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}),635 .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}),
631 .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}),
632 .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}),
633 .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),636 .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
634637
635 .array_init_one,638 .array_init_one,
...@@ -652,15 +655,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In...@@ -652,15 +655,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
652 .struct_init_comma,655 .struct_init_comma,
653 => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}),656 => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}),
654657
655 .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}),
656 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),658 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),
657 .fn_proto_simple,659 .fn_proto_simple,
658 .fn_proto_multi,660 .fn_proto_multi,
659 .fn_proto_one,661 .fn_proto_one,
660 .fn_proto,662 .fn_proto,
661 => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),663 => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),
662
663 .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}),
664 }664 }
665}665}
666666
...@@ -766,6 +766,8 @@ fn breakExpr(...@@ -766,6 +766,8 @@ fn breakExpr(
766 },766 },
767 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,767 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
768 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,768 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
769 .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent,
770 .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent,
769 else => if (break_label != 0) {771 else => if (break_label != 0) {
770 const label_name = try mod.identifierTokenString(parent_scope, break_label);772 const label_name = try mod.identifierTokenString(parent_scope, break_label);
771 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});773 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
...@@ -819,6 +821,8 @@ fn continueExpr(...@@ -819,6 +821,8 @@ fn continueExpr(
819 },821 },
820 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,822 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
821 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,823 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
824 .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent,
825 .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent,
822 else => if (break_label != 0) {826 else => if (break_label != 0) {
823 const label_name = try mod.identifierTokenString(parent_scope, break_label);827 const label_name = try mod.identifierTokenString(parent_scope, break_label);
824 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});828 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
...@@ -844,7 +848,9 @@ pub fn blockExpr(...@@ -844,7 +848,9 @@ pub fn blockExpr(
844 const token_tags = tree.tokens.items(.tag);848 const token_tags = tree.tokens.items(.tag);
845849
846 const lbrace = main_tokens[block_node];850 const lbrace = main_tokens[block_node];
847 if (token_tags[lbrace - 1] == .colon) {851 if (token_tags[lbrace - 1] == .colon and
852 token_tags[lbrace - 2] == .identifier)
853 {
848 return labeledBlockExpr(mod, scope, rl, block_node, statements, .block);854 return labeledBlockExpr(mod, scope, rl, block_node, statements, .block);
849 }855 }
850856
...@@ -893,6 +899,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn...@@ -893,6 +899,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn
893 },899 },
894 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,900 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
895 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,901 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
902 .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent,
903 .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent,
896 else => return,904 else => return,
897 }905 }
898 }906 }
...@@ -1100,6 +1108,8 @@ fn varDecl(...@@ -1100,6 +1108,8 @@ fn varDecl(
1100 s = local_ptr.parent;1108 s = local_ptr.parent;
1101 },1109 },
1102 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,1110 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,
1111 .gen_suspend => s = s.cast(Scope.GenZIR).?.parent,
1112 .gen_nosuspend => s = s.cast(Scope.Nosuspend).?.parent,
1103 else => break,1113 else => break,
1104 };1114 };
1105 }1115 }
...@@ -3021,6 +3031,8 @@ fn identifier(...@@ -3021,6 +3031,8 @@ fn identifier(
3021 s = local_ptr.parent;3031 s = local_ptr.parent;
3022 },3032 },
3023 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,3033 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,
3034 .gen_suspend => s = s.cast(Scope.GenZIR).?.parent,
3035 .gen_nosuspend => s = s.cast(Scope.Nosuspend).?.parent,
3024 else => break,3036 else => break,
3025 };3037 };
3026 }3038 }
...@@ -3633,14 +3645,109 @@ fn callExpr(...@@ -3633,14 +3645,109 @@ fn callExpr(
3633 }3645 }
36343646
3635 const src = token_starts[call.ast.lparen];3647 const src = token_starts[call.ast.lparen];
3648 var modifier: std.builtin.CallOptions.Modifier = .auto;
3649 if (call.async_token) |_| modifier = .async_kw;
3650
3636 const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{3651 const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{
3637 .func = lhs,3652 .func = lhs,
3638 .args = args,3653 .args = args,
3654 .modifier = modifier,
3639 }, .{});3655 }, .{});
3640 // TODO function call with result location3656 // TODO function call with result location
3641 return rvalue(mod, scope, rl, result);3657 return rvalue(mod, scope, rl, result);
3642}3658}
36433659
3660fn suspendExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst {
3661 const tree = scope.tree();
3662 const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]];
3663
3664 if (scope.getNosuspend()) |some| {
3665 const msg = msg: {
3666 const msg = try mod.errMsg(scope, src, "suspend in nosuspend block", .{});
3667 errdefer msg.destroy(mod.gpa);
3668 try mod.errNote(scope, some.src, msg, "nosuspend block here", .{});
3669 break :msg msg;
3670 };
3671 return mod.failWithOwnedErrorMsg(scope, msg);
3672 }
3673
3674 if (scope.getSuspend()) |some| {
3675 const msg = msg: {
3676 const msg = try mod.errMsg(scope, src, "cannot suspend inside suspend block", .{});
3677 errdefer msg.destroy(mod.gpa);
3678 try mod.errNote(scope, some.src, msg, "other suspend block here", .{});
3679 break :msg msg;
3680 };
3681 return mod.failWithOwnedErrorMsg(scope, msg);
3682 }
3683
3684 var suspend_scope: Scope.GenZIR = .{
3685 .base = .{ .tag = .gen_suspend },
3686 .parent = scope,
3687 .decl = scope.ownerDecl().?,
3688 .arena = scope.arena(),
3689 .force_comptime = scope.isComptime(),
3690 .instructions = .{},
3691 };
3692 defer suspend_scope.instructions.deinit(mod.gpa);
3693
3694 const operand = tree.nodes.items(.data)[node].lhs;
3695 if (operand != 0) {
3696 const possibly_unused_result = try expr(mod, &suspend_scope.base, .none, operand);
3697 if (!possibly_unused_result.tag.isNoReturn()) {
3698 _ = try addZIRUnOp(mod, &suspend_scope.base, src, .ensure_result_used, possibly_unused_result);
3699 }
3700 } else {
3701 return addZIRNoOp(mod, scope, src, .@"suspend");
3702 }
3703
3704 const block = try addZIRInstBlock(mod, scope, src, .suspend_block, .{
3705 .instructions = try scope.arena().dupe(*zir.Inst, suspend_scope.instructions.items),
3706 });
3707 return &block.base;
3708}
3709
3710fn nosuspendExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst {
3711 const tree = scope.tree();
3712 var child_scope = Scope.Nosuspend{
3713 .parent = scope,
3714 .gen_zir = scope.getGenZIR(),
3715 .src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]],
3716 };
3717
3718 return expr(mod, &child_scope.base, rl, tree.nodes.items(.data)[node].lhs);
3719}
3720
3721fn awaitExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst {
3722 const tree = scope.tree();
3723 const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]];
3724 const is_nosuspend = scope.getNosuspend() != null;
3725
3726 // TODO some @asyncCall stuff
3727
3728 if (scope.getSuspend()) |some| {
3729 const msg = msg: {
3730 const msg = try mod.errMsg(scope, src, "cannot await inside suspend block", .{});
3731 errdefer msg.destroy(mod.gpa);
3732 try mod.errNote(scope, some.src, msg, "suspend block here", .{});
3733 break :msg msg;
3734 };
3735 return mod.failWithOwnedErrorMsg(scope, msg);
3736 }
3737
3738 const operand = try expr(mod, scope, .ref, tree.nodes.items(.data)[node].lhs);
3739 // TODO pass result location
3740 return addZIRUnOp(mod, scope, src, if (is_nosuspend) .nosuspend_await else .@"await", operand);
3741}
3742
3743fn resumeExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst {
3744 const tree = scope.tree();
3745 const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]];
3746
3747 const operand = try expr(mod, scope, .ref, tree.nodes.items(.data)[node].lhs);
3748 return addZIRUnOp(mod, scope, src, .@"resume", operand);
3749}
3750
3644pub const simple_types = std.ComptimeStringMap(Value.Tag, .{3751pub const simple_types = std.ComptimeStringMap(Value.Tag, .{
3645 .{ "u8", .u8_type },3752 .{ "u8", .u8_type },
3646 .{ "i8", .i8_type },3753 .{ "i8", .i8_type },
src/clang.zig+5
...@@ -271,6 +271,11 @@ pub const CompoundAssignOperator = opaque {...@@ -271,6 +271,11 @@ pub const CompoundAssignOperator = opaque {
271 extern fn ZigClangCompoundAssignOperator_getRHS(*const CompoundAssignOperator) *const Expr;271 extern fn ZigClangCompoundAssignOperator_getRHS(*const CompoundAssignOperator) *const Expr;
272};272};
273273
274pub const CompoundLiteralExpr = opaque {
275 pub const getInitializer = ZigClangCompoundLiteralExpr_getInitializer;
276 extern fn ZigClangCompoundLiteralExpr_getInitializer(*const CompoundLiteralExpr) *const Expr;
277};
278
274pub const CompoundStmt = opaque {279pub const CompoundStmt = opaque {
275 pub const body_begin = ZigClangCompoundStmt_body_begin;280 pub const body_begin = ZigClangCompoundStmt_body_begin;
276 extern fn ZigClangCompoundStmt_body_begin(*const CompoundStmt) ConstBodyIterator;281 extern fn ZigClangCompoundStmt_body_begin(*const CompoundStmt) ConstBodyIterator;
src/codegen.zig+32
...@@ -865,6 +865,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -865,6 +865,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
865 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {865 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {
866 switch (inst.tag) {866 switch (inst.tag) {
867 .add => return self.genAdd(inst.castTag(.add).?),867 .add => return self.genAdd(inst.castTag(.add).?),
868 .addwrap => return self.genAddWrap(inst.castTag(.addwrap).?),
868 .alloc => return self.genAlloc(inst.castTag(.alloc).?),869 .alloc => return self.genAlloc(inst.castTag(.alloc).?),
869 .arg => return self.genArg(inst.castTag(.arg).?),870 .arg => return self.genArg(inst.castTag(.arg).?),
870 .assembly => return self.genAsm(inst.castTag(.assembly).?),871 .assembly => return self.genAsm(inst.castTag(.assembly).?),
...@@ -900,12 +901,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -900,12 +901,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
900 .loop => return self.genLoop(inst.castTag(.loop).?),901 .loop => return self.genLoop(inst.castTag(.loop).?),
901 .not => return self.genNot(inst.castTag(.not).?),902 .not => return self.genNot(inst.castTag(.not).?),
902 .mul => return self.genMul(inst.castTag(.mul).?),903 .mul => return self.genMul(inst.castTag(.mul).?),
904 .mulwrap => return self.genMulWrap(inst.castTag(.mulwrap).?),
903 .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?),905 .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?),
904 .ref => return self.genRef(inst.castTag(.ref).?),906 .ref => return self.genRef(inst.castTag(.ref).?),
905 .ret => return self.genRet(inst.castTag(.ret).?),907 .ret => return self.genRet(inst.castTag(.ret).?),
906 .retvoid => return self.genRetVoid(inst.castTag(.retvoid).?),908 .retvoid => return self.genRetVoid(inst.castTag(.retvoid).?),
907 .store => return self.genStore(inst.castTag(.store).?),909 .store => return self.genStore(inst.castTag(.store).?),
908 .sub => return self.genSub(inst.castTag(.sub).?),910 .sub => return self.genSub(inst.castTag(.sub).?),
911 .subwrap => return self.genSubWrap(inst.castTag(.subwrap).?),
909 .switchbr => return self.genSwitch(inst.castTag(.switchbr).?),912 .switchbr => return self.genSwitch(inst.castTag(.switchbr).?),
910 .unreach => return MCValue{ .unreach = {} },913 .unreach => return MCValue{ .unreach = {} },
911 .optional_payload => return self.genOptionalPayload(inst.castTag(.optional_payload).?),914 .optional_payload => return self.genOptionalPayload(inst.castTag(.optional_payload).?),
...@@ -1129,6 +1132,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1129,6 +1132,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1129 }1132 }
1130 }1133 }
11311134
1135 fn genAddWrap(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1136 // No side effects, so if it's unreferenced, do nothing.
1137 if (inst.base.isUnused())
1138 return MCValue.dead;
1139 switch (arch) {
1140 else => return self.fail(inst.base.src, "TODO implement addwrap for {}", .{self.target.cpu.arch}),
1141 }
1142 }
1143
1132 fn genMul(self: *Self, inst: *ir.Inst.BinOp) !MCValue {1144 fn genMul(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1133 // No side effects, so if it's unreferenced, do nothing.1145 // No side effects, so if it's unreferenced, do nothing.
1134 if (inst.base.isUnused())1146 if (inst.base.isUnused())
...@@ -1139,6 +1151,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1139,6 +1151,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1139 }1151 }
1140 }1152 }
11411153
1154 fn genMulWrap(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1155 // No side effects, so if it's unreferenced, do nothing.
1156 if (inst.base.isUnused())
1157 return MCValue.dead;
1158 switch (arch) {
1159 else => return self.fail(inst.base.src, "TODO implement mulwrap for {}", .{self.target.cpu.arch}),
1160 }
1161 }
1162
1142 fn genBitAnd(self: *Self, inst: *ir.Inst.BinOp) !MCValue {1163 fn genBitAnd(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1143 // No side effects, so if it's unreferenced, do nothing.1164 // No side effects, so if it's unreferenced, do nothing.
1144 if (inst.base.isUnused())1165 if (inst.base.isUnused())
...@@ -1392,6 +1413,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1392,6 +1413,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1392 }1413 }
1393 }1414 }
13941415
1416 fn genSubWrap(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
1417 // No side effects, so if it's unreferenced, do nothing.
1418 if (inst.base.isUnused())
1419 return MCValue.dead;
1420 switch (arch) {
1421 else => return self.fail(inst.base.src, "TODO implement subwrap for {}", .{self.target.cpu.arch}),
1422 }
1423 }
1424
1395 fn genArmBinOp(self: *Self, inst: *ir.Inst, op_lhs: *ir.Inst, op_rhs: *ir.Inst, op: ir.Inst.Tag) !MCValue {1425 fn genArmBinOp(self: *Self, inst: *ir.Inst, op_lhs: *ir.Inst, op_rhs: *ir.Inst, op: ir.Inst.Tag) !MCValue {
1396 const lhs = try self.resolveInst(op_lhs);1426 const lhs = try self.resolveInst(op_lhs);
1397 const rhs = try self.resolveInst(op_rhs);1427 const rhs = try self.resolveInst(op_rhs);
...@@ -2237,6 +2267,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2237,6 +2267,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2237 // No side effects, so if it's unreferenced, do nothing.2267 // No side effects, so if it's unreferenced, do nothing.
2238 if (inst.base.isUnused())2268 if (inst.base.isUnused())
2239 return MCValue{ .dead = {} };2269 return MCValue{ .dead = {} };
2270 if (inst.lhs.ty.zigTypeTag() == .ErrorSet or inst.rhs.ty.zigTypeTag() == .ErrorSet)
2271 return self.fail(inst.base.src, "TODO implement cmp for errors", .{});
2240 switch (arch) {2272 switch (arch) {
2241 .x86_64 => {2273 .x86_64 => {
2242 try self.code.ensureCapacity(self.code.items.len + 8);2274 try self.code.ensureCapacity(self.code.items.len + 8);
src/codegen/c.zig+278-3
...@@ -32,6 +32,34 @@ pub const CValue = union(enum) {...@@ -32,6 +32,34 @@ pub const CValue = union(enum) {
32};32};
3333
34pub const CValueMap = std.AutoHashMap(*Inst, CValue);34pub const CValueMap = std.AutoHashMap(*Inst, CValue);
35pub const TypedefMap = std.HashMap(Type, struct { name: []const u8, rendered: []u8 }, Type.hash, Type.eql, std.hash_map.default_max_load_percentage);
36
37fn formatTypeAsCIdentifier(
38 data: Type,
39 comptime fmt: []const u8,
40 options: std.fmt.FormatOptions,
41 writer: anytype,
42) !void {
43 var buffer = [1]u8{0} ** 128;
44 // We don't care if it gets cut off, it's still more unique than a number
45 var buf = std.fmt.bufPrint(&buffer, "{}", .{data}) catch &buffer;
46
47 for (buf) |c, i| {
48 switch (c) {
49 0 => return writer.writeAll(buf[0..i]),
50 'a'...'z', 'A'...'Z', '_', '$' => {},
51 '0'...'9' => if (i == 0) {
52 buf[i] = '_';
53 },
54 else => buf[i] = '_',
55 }
56 }
57 return writer.writeAll(buf);
58}
59
60pub fn typeToCIdentifier(t: Type) std.fmt.Formatter(formatTypeAsCIdentifier) {
61 return .{ .data = t };
62}
3563
36/// This data is available when outputting .c code for a Module.64/// This data is available when outputting .c code for a Module.
37/// It is not available when generating .h file.65/// It is not available when generating .h file.
...@@ -115,6 +143,7 @@ pub const DeclGen = struct {...@@ -115,6 +143,7 @@ pub const DeclGen = struct {
115 decl: *Decl,143 decl: *Decl,
116 fwd_decl: std.ArrayList(u8),144 fwd_decl: std.ArrayList(u8),
117 error_msg: ?*Module.ErrorMsg,145 error_msg: ?*Module.ErrorMsg,
146 typedefs: TypedefMap,
118147
119 fn fail(dg: *DeclGen, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {148 fn fail(dg: *DeclGen, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
120 dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, .{149 dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, .{
...@@ -140,7 +169,7 @@ pub const DeclGen = struct {...@@ -140,7 +169,7 @@ pub const DeclGen = struct {
140 return writer.print("{d}", .{val.toUnsignedInt()});169 return writer.print("{d}", .{val.toUnsignedInt()});
141 },170 },
142 .Pointer => switch (val.tag()) {171 .Pointer => switch (val.tag()) {
143 .undef, .zero => try writer.writeAll("0"),172 .null_value, .zero => try writer.writeAll("NULL"),
144 .one => try writer.writeAll("1"),173 .one => try writer.writeAll("1"),
145 .decl_ref => {174 .decl_ref => {
146 const decl = val.castTag(.decl_ref).?.data;175 const decl = val.castTag(.decl_ref).?.data;
...@@ -201,6 +230,52 @@ pub const DeclGen = struct {...@@ -201,6 +230,52 @@ pub const DeclGen = struct {
201 }230 }
202 },231 },
203 .Bool => return writer.print("{}", .{val.toBool()}),232 .Bool => return writer.print("{}", .{val.toBool()}),
233 .Optional => {
234 var opt_buf: Type.Payload.ElemType = undefined;
235 const child_type = t.optionalChild(&opt_buf);
236 if (t.isPtrLikeOptional()) {
237 return dg.renderValue(writer, child_type, val);
238 }
239 try writer.writeByte('(');
240 try dg.renderType(writer, t);
241 if (val.tag() == .null_value) {
242 try writer.writeAll("){ .is_null = true }");
243 } else {
244 try writer.writeAll("){ .is_null = false, .payload = ");
245 try dg.renderValue(writer, child_type, val);
246 try writer.writeAll(" }");
247 }
248 },
249 .ErrorSet => {
250 const payload = val.castTag(.@"error").?;
251 // error values will be #defined at the top of the file
252 return writer.print("zig_error_{s}", .{payload.data.name});
253 },
254 .ErrorUnion => {
255 const error_type = t.errorUnionSet();
256 const payload_type = t.errorUnionChild();
257 const data = val.castTag(.error_union).?.data;
258 try writer.writeByte('(');
259 try dg.renderType(writer, t);
260 try writer.writeAll("){");
261 if (val.getError()) |_| {
262 try writer.writeAll(" .error = ");
263 try dg.renderValue(
264 writer,
265 error_type,
266 data,
267 );
268 try writer.writeAll(" }");
269 } else {
270 try writer.writeAll(" .payload = ");
271 try dg.renderValue(
272 writer,
273 payload_type,
274 data,
275 );
276 try writer.writeAll(", .error = 0 }");
277 }
278 },
204 else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{279 else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{
205 @tagName(e),280 @tagName(e),
206 }),281 }),
...@@ -215,8 +290,9 @@ pub const DeclGen = struct {...@@ -215,8 +290,9 @@ pub const DeclGen = struct {
215 try dg.renderType(w, tv.ty.fnReturnType());290 try dg.renderType(w, tv.ty.fnReturnType());
216 const decl_name = mem.span(dg.decl.name);291 const decl_name = mem.span(dg.decl.name);
217 try w.print(" {s}(", .{decl_name});292 try w.print(" {s}(", .{decl_name});
218 var param_len = tv.ty.fnParamLen();293 const param_len = tv.ty.fnParamLen();
219 if (param_len == 0)294 const is_var_args = tv.ty.fnIsVarArgs();
295 if (param_len == 0 and !is_var_args)
220 try w.writeAll("void")296 try w.writeAll("void")
221 else {297 else {
222 var index: usize = 0;298 var index: usize = 0;
...@@ -228,6 +304,10 @@ pub const DeclGen = struct {...@@ -228,6 +304,10 @@ pub const DeclGen = struct {
228 try w.print(" a{d}", .{index});304 try w.print(" a{d}", .{index});
229 }305 }
230 }306 }
307 if (is_var_args) {
308 if (param_len != 0) try w.writeAll(", ");
309 try w.writeAll("...");
310 }
231 try w.writeByte(')');311 try w.writeByte(')');
232 }312 }
233313
...@@ -294,6 +374,62 @@ pub const DeclGen = struct {...@@ -294,6 +374,62 @@ pub const DeclGen = struct {
294 try dg.renderType(w, t.elemType());374 try dg.renderType(w, t.elemType());
295 try w.writeAll(" *");375 try w.writeAll(" *");
296 },376 },
377 .Optional => {
378 var opt_buf: Type.Payload.ElemType = undefined;
379 const child_type = t.optionalChild(&opt_buf);
380 if (t.isPtrLikeOptional()) {
381 return dg.renderType(w, child_type);
382 } else if (dg.typedefs.get(t)) |some| {
383 return w.writeAll(some.name);
384 }
385
386 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
387 defer buffer.deinit();
388 const bw = buffer.writer();
389
390 try bw.writeAll("typedef struct { ");
391 try dg.renderType(bw, child_type);
392 try bw.writeAll(" payload; bool is_null; } ");
393 const name_index = buffer.items.len;
394 try bw.print("zig_opt_{s}_t;\n", .{typeToCIdentifier(child_type)});
395
396 const rendered = buffer.toOwnedSlice();
397 errdefer dg.typedefs.allocator.free(rendered);
398 const name = rendered[name_index .. rendered.len - 2];
399
400 try dg.typedefs.ensureCapacity(dg.typedefs.capacity() + 1);
401 try w.writeAll(name);
402 dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered });
403 },
404 .ErrorSet => {
405 comptime std.debug.assert(Type.initTag(.anyerror).abiSize(std.Target.current) == 2);
406 try w.writeAll("uint16_t");
407 },
408 .ErrorUnion => {
409 if (dg.typedefs.get(t)) |some| {
410 return w.writeAll(some.name);
411 }
412 const child_type = t.errorUnionChild();
413 const set_type = t.errorUnionSet();
414
415 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
416 defer buffer.deinit();
417 const bw = buffer.writer();
418
419 try bw.writeAll("typedef struct { ");
420 try dg.renderType(bw, child_type);
421 try bw.writeAll(" payload; uint16_t error; } ");
422 const name_index = buffer.items.len;
423 try bw.print("zig_err_union_{s}_{s}_t;\n", .{ typeToCIdentifier(set_type), typeToCIdentifier(child_type) });
424
425 const rendered = buffer.toOwnedSlice();
426 errdefer dg.typedefs.allocator.free(rendered);
427 const name = rendered[name_index .. rendered.len - 2];
428
429 try dg.typedefs.ensureCapacity(dg.typedefs.capacity() + 1);
430 try w.writeAll(name);
431 dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered });
432 },
297 .Null, .Undefined => unreachable, // must be const or comptime433 .Null, .Undefined => unreachable, // must be const or comptime
298 else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{434 else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{
299 @tagName(e),435 @tagName(e),
...@@ -424,6 +560,21 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi...@@ -424,6 +560,21 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
424 .bit_or => try genBinOp(o, inst.castTag(.bit_or).?, " | "),560 .bit_or => try genBinOp(o, inst.castTag(.bit_or).?, " | "),
425 .xor => try genBinOp(o, inst.castTag(.xor).?, " ^ "),561 .xor => try genBinOp(o, inst.castTag(.xor).?, " ^ "),
426 .not => try genUnOp(o, inst.castTag(.not).?, "!"),562 .not => try genUnOp(o, inst.castTag(.not).?, "!"),
563 .is_null => try genIsNull(o, inst.castTag(.is_null).?),
564 .is_non_null => try genIsNull(o, inst.castTag(.is_non_null).?),
565 .is_null_ptr => try genIsNull(o, inst.castTag(.is_null_ptr).?),
566 .is_non_null_ptr => try genIsNull(o, inst.castTag(.is_non_null_ptr).?),
567 .wrap_optional => try genWrapOptional(o, inst.castTag(.wrap_optional).?),
568 .optional_payload => try genOptionalPayload(o, inst.castTag(.optional_payload).?),
569 .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload_ptr).?),
570 .is_err => try genIsErr(o, inst.castTag(.is_err).?),
571 .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?),
572 .unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?),
573 .unwrap_errunion_err => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err).?),
574 .unwrap_errunion_payload_ptr => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload_ptr).?),
575 .unwrap_errunion_err_ptr => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err_ptr).?),
576 .wrap_errunion_payload => try genWrapErrUnionPay(o, inst.castTag(.wrap_errunion_payload).?),
577 .wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),
427 else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),578 else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
428 };579 };
429 switch (result_value) {580 switch (result_value) {
...@@ -797,6 +948,130 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {...@@ -797,6 +948,130 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
797 return o.dg.fail(o.dg.decl.src(), "TODO: C backend: inline asm expression result used", .{});948 return o.dg.fail(o.dg.decl.src(), "TODO: C backend: inline asm expression result used", .{});
798}949}
799950
951fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {
952 const writer = o.writer();
953 const invert_logic = inst.base.tag == .is_non_null or inst.base.tag == .is_non_null_ptr;
954 const operator = if (invert_logic) "!=" else "==";
955 const maybe_deref = if (inst.base.tag == .is_null_ptr or inst.base.tag == .is_non_null_ptr) "[0]" else "";
956 const operand = try o.resolveInst(inst.operand);
957
958 const local = try o.allocLocal(Type.initTag(.bool), .Const);
959 try writer.writeAll(" = (");
960 try o.writeCValue(writer, operand);
961
962 if (inst.operand.ty.isPtrLikeOptional()) {
963 // operand is a regular pointer, test `operand !=/== NULL`
964 try writer.print("){s} {s} NULL;\n", .{ maybe_deref, operator });
965 } else {
966 try writer.print("){s}.is_null {s} true;\n", .{ maybe_deref, operator });
967 }
968 return local;
969}
970
971fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue {
972 const writer = o.writer();
973 const operand = try o.resolveInst(inst.operand);
974
975 const opt_ty = if (inst.operand.ty.zigTypeTag() == .Pointer)
976 inst.operand.ty.elemType()
977 else
978 inst.operand.ty;
979
980 if (opt_ty.isPtrLikeOptional()) {
981 // the operand is just a regular pointer, no need to do anything special.
982 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
983 return operand;
984 }
985
986 const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else ".";
987 const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else "";
988
989 const local = try o.allocLocal(inst.base.ty, .Const);
990 try writer.print(" = {s}(", .{maybe_addrof});
991 try o.writeCValue(writer, operand);
992
993 try writer.print("){s}payload;\n", .{maybe_deref});
994 return local;
995}
996
997// *(E!T) -> E NOT *E
998fn genUnwrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue {
999 const writer = o.writer();
1000 const operand = try o.resolveInst(inst.operand);
1001
1002 const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else ".";
1003
1004 const local = try o.allocLocal(inst.base.ty, .Const);
1005 try writer.writeAll(" = (");
1006 try o.writeCValue(writer, operand);
1007
1008 try writer.print("){s}error;\n", .{maybe_deref});
1009 return local;
1010}
1011fn genUnwrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue {
1012 const writer = o.writer();
1013 const operand = try o.resolveInst(inst.operand);
1014
1015 const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else ".";
1016 const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else "";
1017
1018 const local = try o.allocLocal(inst.base.ty, .Const);
1019 try writer.print(" = {s}(", .{maybe_addrof});
1020 try o.writeCValue(writer, operand);
1021
1022 try writer.print("){s}payload;\n", .{maybe_deref});
1023 return local;
1024}
1025
1026fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue {
1027 const writer = o.writer();
1028 const operand = try o.resolveInst(inst.operand);
1029
1030 if (inst.base.ty.isPtrLikeOptional()) {
1031 // the operand is just a regular pointer, no need to do anything special.
1032 return operand;
1033 }
1034
1035 // .wrap_optional is used to convert non-optionals into optionals so it can never be null.
1036 const local = try o.allocLocal(inst.base.ty, .Const);
1037 try writer.writeAll(" = { .is_null = false, .payload =");
1038 try o.writeCValue(writer, operand);
1039 try writer.writeAll("};\n");
1040 return local;
1041}
1042fn genWrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue {
1043 const writer = o.writer();
1044 const operand = try o.resolveInst(inst.operand);
1045
1046 const local = try o.allocLocal(inst.base.ty, .Const);
1047 try writer.writeAll(" = { .error = ");
1048 try o.writeCValue(writer, operand);
1049 try writer.writeAll(" };\n");
1050 return local;
1051}
1052fn genWrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue {
1053 const writer = o.writer();
1054 const operand = try o.resolveInst(inst.operand);
1055
1056 const local = try o.allocLocal(inst.base.ty, .Const);
1057 try writer.writeAll(" = { .error = 0, .payload = ");
1058 try o.writeCValue(writer, operand);
1059 try writer.writeAll(" };\n");
1060 return local;
1061}
1062
1063fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue {
1064 const writer = o.writer();
1065 const maybe_deref = if (inst.base.tag == .is_err_ptr) "[0]" else "";
1066 const operand = try o.resolveInst(inst.operand);
1067
1068 const local = try o.allocLocal(Type.initTag(.bool), .Const);
1069 try writer.writeAll(" = (");
1070 try o.writeCValue(writer, operand);
1071 try writer.print("){s}.error != 0;\n", .{maybe_deref});
1072 return local;
1073}
1074
800fn IndentWriter(comptime UnderlyingWriter: type) type {1075fn IndentWriter(comptime UnderlyingWriter: type) type {
801 return struct {1076 return struct {
802 const Self = @This();1077 const Self = @This();
src/glibc.zig+14-1
...@@ -453,7 +453,20 @@ fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) !...@@ -453,7 +453,20 @@ fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) !
453 } else if (arch.isARM()) {453 } else if (arch.isARM()) {
454 try result.appendSlice("arm");454 try result.appendSlice("arm");
455 } else if (arch.isMIPS()) {455 } else if (arch.isMIPS()) {
456 try result.appendSlice("mips");456 if (!mem.eql(u8, basename, "crti.S") and !mem.eql(u8, basename, "crtn.S")) {
457 try result.appendSlice("mips");
458 } else {
459 if (is_64) {
460 const abi_dir = if (comp.getTarget().abi == .gnuabin32)
461 "n32"
462 else
463 "n64";
464 try result.appendSlice("mips" ++ s ++ "mips64" ++ s);
465 try result.appendSlice(abi_dir);
466 } else {
467 try result.appendSlice("mips" ++ s ++ "mips32");
468 }
469 }
457 } else if (arch == .x86_64) {470 } else if (arch == .x86_64) {
458 try result.appendSlice("x86_64");471 try result.appendSlice("x86_64");
459 } else if (arch == .i386) {472 } else if (arch == .i386) {
src/ir.zig+6
...@@ -53,6 +53,7 @@ pub const Inst = struct {...@@ -53,6 +53,7 @@ pub const Inst = struct {
5353
54 pub const Tag = enum {54 pub const Tag = enum {
55 add,55 add,
56 addwrap,
56 alloc,57 alloc,
57 arg,58 arg,
58 assembly,59 assembly,
...@@ -105,8 +106,10 @@ pub const Inst = struct {...@@ -105,8 +106,10 @@ pub const Inst = struct {
105 /// Write a value to a pointer. LHS is pointer, RHS is value.106 /// Write a value to a pointer. LHS is pointer, RHS is value.
106 store,107 store,
107 sub,108 sub,
109 subwrap,
108 unreach,110 unreach,
109 mul,111 mul,
112 mulwrap,
110 not,113 not,
111 floatcast,114 floatcast,
112 intcast,115 intcast,
...@@ -165,8 +168,11 @@ pub const Inst = struct {...@@ -165,8 +168,11 @@ pub const Inst = struct {
165 => UnOp,168 => UnOp,
166169
167 .add,170 .add,
171 .addwrap,
168 .sub,172 .sub,
173 .subwrap,
169 .mul,174 .mul,
175 .mulwrap,
170 .cmp_lt,176 .cmp_lt,
171 .cmp_lte,177 .cmp_lte,
172 .cmp_eq,178 .cmp_eq,
src/link/C.zig+64-5
...@@ -9,6 +9,7 @@ const codegen = @import("../codegen/c.zig");...@@ -9,6 +9,7 @@ const codegen = @import("../codegen/c.zig");
9const link = @import("../link.zig");9const link = @import("../link.zig");
10const trace = @import("../tracy.zig").trace;10const trace = @import("../tracy.zig").trace;
11const C = @This();11const C = @This();
12const Type = @import("../type.zig").Type;
1213
13pub const base_tag: link.File.Tag = .c;14pub const base_tag: link.File.Tag = .c;
14pub const zig_h = @embedFile("C/zig.h");15pub const zig_h = @embedFile("C/zig.h");
...@@ -28,9 +29,11 @@ pub const DeclBlock = struct {...@@ -28,9 +29,11 @@ pub const DeclBlock = struct {
28/// Per-function data.29/// Per-function data.
29pub const FnBlock = struct {30pub const FnBlock = struct {
30 fwd_decl: std.ArrayListUnmanaged(u8),31 fwd_decl: std.ArrayListUnmanaged(u8),
32 typedefs: codegen.TypedefMap.Unmanaged,
3133
32 pub const empty: FnBlock = .{34 pub const empty: FnBlock = .{
33 .fwd_decl = .{},35 .fwd_decl = .{},
36 .typedefs = .{},
34 };37 };
35};38};
3639
...@@ -74,6 +77,11 @@ pub fn allocateDeclIndexes(self: *C, decl: *Module.Decl) !void {}...@@ -74,6 +77,11 @@ pub fn allocateDeclIndexes(self: *C, decl: *Module.Decl) !void {}
74pub fn freeDecl(self: *C, decl: *Module.Decl) void {77pub fn freeDecl(self: *C, decl: *Module.Decl) void {
75 decl.link.c.code.deinit(self.base.allocator);78 decl.link.c.code.deinit(self.base.allocator);
76 decl.fn_link.c.fwd_decl.deinit(self.base.allocator);79 decl.fn_link.c.fwd_decl.deinit(self.base.allocator);
80 var it = decl.fn_link.c.typedefs.iterator();
81 while (it.next()) |some| {
82 self.base.allocator.free(some.value.rendered);
83 }
84 decl.fn_link.c.typedefs.deinit(self.base.allocator);
77}85}
7886
79pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {87pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
...@@ -81,8 +89,16 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {...@@ -81,8 +89,16 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
81 defer tracy.end();89 defer tracy.end();
8290
83 const fwd_decl = &decl.fn_link.c.fwd_decl;91 const fwd_decl = &decl.fn_link.c.fwd_decl;
92 const typedefs = &decl.fn_link.c.typedefs;
84 const code = &decl.link.c.code;93 const code = &decl.link.c.code;
85 fwd_decl.shrinkRetainingCapacity(0);94 fwd_decl.shrinkRetainingCapacity(0);
95 {
96 var it = typedefs.iterator();
97 while (it.next()) |entry| {
98 module.gpa.free(entry.value.rendered);
99 }
100 }
101 typedefs.clearRetainingCapacity();
86 code.shrinkRetainingCapacity(0);102 code.shrinkRetainingCapacity(0);
87103
88 var object: codegen.Object = .{104 var object: codegen.Object = .{
...@@ -91,6 +107,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {...@@ -91,6 +107,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
91 .error_msg = null,107 .error_msg = null,
92 .decl = decl,108 .decl = decl,
93 .fwd_decl = fwd_decl.toManaged(module.gpa),109 .fwd_decl = fwd_decl.toManaged(module.gpa),
110 .typedefs = typedefs.promote(module.gpa),
94 },111 },
95 .gpa = module.gpa,112 .gpa = module.gpa,
96 .code = code.toManaged(module.gpa),113 .code = code.toManaged(module.gpa),
...@@ -98,9 +115,16 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {...@@ -98,9 +115,16 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
98 .indent_writer = undefined, // set later so we can get a pointer to object.code115 .indent_writer = undefined, // set later so we can get a pointer to object.code
99 };116 };
100 object.indent_writer = .{ .underlying_writer = object.code.writer() };117 object.indent_writer = .{ .underlying_writer = object.code.writer() };
101 defer object.value_map.deinit();118 defer {
102 defer object.code.deinit();119 object.value_map.deinit();
103 defer object.dg.fwd_decl.deinit();120 object.code.deinit();
121 object.dg.fwd_decl.deinit();
122 var it = object.dg.typedefs.iterator();
123 while (it.next()) |some| {
124 module.gpa.free(some.value.rendered);
125 }
126 object.dg.typedefs.deinit();
127 }
104128
105 codegen.genDecl(&object) catch |err| switch (err) {129 codegen.genDecl(&object) catch |err| switch (err) {
106 error.AnalysisFail => {130 error.AnalysisFail => {
...@@ -111,6 +135,8 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {...@@ -111,6 +135,8 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
111 };135 };
112136
113 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();137 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
138 typedefs.* = object.dg.typedefs.unmanaged;
139 object.dg.typedefs.unmanaged = .{};
114 code.* = object.code.moveToUnmanaged();140 code.* = object.code.moveToUnmanaged();
115141
116 // Free excess allocated memory for this Decl.142 // Free excess allocated memory for this Decl.
...@@ -142,7 +168,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -142,7 +168,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
142 defer all_buffers.deinit();168 defer all_buffers.deinit();
143169
144 // This is at least enough until we get to the function bodies without error handling.170 // This is at least enough until we get to the function bodies without error handling.
145 try all_buffers.ensureCapacity(module.decl_table.count() + 1);171 try all_buffers.ensureCapacity(module.decl_table.count() + 2);
146172
147 var file_size: u64 = zig_h.len;173 var file_size: u64 = zig_h.len;
148 all_buffers.appendAssumeCapacity(.{174 all_buffers.appendAssumeCapacity(.{
...@@ -150,9 +176,26 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -150,9 +176,26 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
150 .iov_len = zig_h.len,176 .iov_len = zig_h.len,
151 });177 });
152178
179 var err_typedef_buf = std.ArrayList(u8).init(comp.gpa);
180 defer err_typedef_buf.deinit();
181 const err_typedef_writer = err_typedef_buf.writer();
182 const err_typedef_item = all_buffers.addOneAssumeCapacity();
183
184 render_errors: {
185 if (module.global_error_set.size == 0) break :render_errors;
186 var it = module.global_error_set.iterator();
187 while (it.next()) |entry| {
188 // + 1 because 0 represents no error
189 try err_typedef_writer.print("#define zig_error_{s} {d}\n", .{ entry.key, entry.value + 1 });
190 }
191 try err_typedef_writer.writeByte('\n');
192 }
193
153 var fn_count: usize = 0;194 var fn_count: usize = 0;
195 var typedefs = std.HashMap(Type, []const u8, Type.hash, Type.eql, std.hash_map.default_max_load_percentage).init(comp.gpa);
196 defer typedefs.deinit();
154197
155 // Forward decls and non-functions first.198 // Typedefs, forward decls and non-functions first.
156 // TODO: performance investigation: would keeping a list of Decls that we should199 // TODO: performance investigation: would keeping a list of Decls that we should
157 // generate, rather than querying here, be faster?200 // generate, rather than querying here, be faster?
158 for (module.decl_table.items()) |kv| {201 for (module.decl_table.items()) |kv| {
...@@ -161,6 +204,16 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -161,6 +204,16 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
161 .most_recent => |tvm| {204 .most_recent => |tvm| {
162 const buf = buf: {205 const buf = buf: {
163 if (tvm.typed_value.val.castTag(.function)) |_| {206 if (tvm.typed_value.val.castTag(.function)) |_| {
207 var it = decl.fn_link.c.typedefs.iterator();
208 while (it.next()) |new| {
209 if (typedefs.get(new.key)) |previous| {
210 try err_typedef_writer.print("typedef {s} {s};\n", .{ previous, new.value.name });
211 } else {
212 try typedefs.ensureCapacity(typedefs.capacity() + 1);
213 try err_typedef_writer.writeAll(new.value.rendered);
214 typedefs.putAssumeCapacityNoClobber(new.key, new.value.name);
215 }
216 }
164 fn_count += 1;217 fn_count += 1;
165 break :buf decl.fn_link.c.fwd_decl.items;218 break :buf decl.fn_link.c.fwd_decl.items;
166 } else {219 } else {
...@@ -177,6 +230,12 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -177,6 +230,12 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
177 }230 }
178 }231 }
179232
233 err_typedef_item.* = .{
234 .iov_base = err_typedef_buf.items.ptr,
235 .iov_len = err_typedef_buf.items.len,
236 };
237 file_size += err_typedef_buf.items.len;
238
180 // Now the function bodies.239 // Now the function bodies.
181 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);240 try all_buffers.ensureCapacity(all_buffers.items.len + fn_count);
182 for (module.decl_table.items()) |kv| {241 for (module.decl_table.items()) |kv| {
src/link/Coff.zig+5-1
...@@ -701,7 +701,11 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {...@@ -701,7 +701,11 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
701 }701 }
702 } else {702 } else {
703 const vaddr = try self.allocateTextBlock(&decl.link.coff, code.len, required_alignment);703 const vaddr = try self.allocateTextBlock(&decl.link.coff, code.len, required_alignment);
704 log.debug("allocated text block for {s} at 0x{x} (size: {Bi})\n", .{ mem.spanZ(decl.name), vaddr, code.len });704 log.debug("allocated text block for {s} at 0x{x} (size: {Bi})\n", .{
705 mem.spanZ(decl.name),
706 vaddr,
707 std.fmt.fmtIntSizeDec(code.len),
708 });
705 errdefer self.freeTextBlock(&decl.link.coff);709 errdefer self.freeTextBlock(&decl.link.coff);
706 self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;710 self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;
707 try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);711 try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);
src/link/Elf.zig+26-18
...@@ -1107,7 +1107,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1107,7 +1107,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1107 for (buf) |*phdr, i| {1107 for (buf) |*phdr, i| {
1108 phdr.* = progHeaderTo32(self.program_headers.items[i]);1108 phdr.* = progHeaderTo32(self.program_headers.items[i]);
1109 if (foreign_endian) {1109 if (foreign_endian) {
1110 bswapAllFields(elf.Elf32_Phdr, phdr);1110 std.elf.bswapAllFields(elf.Elf32_Phdr, phdr);
1111 }1111 }
1112 }1112 }
1113 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);1113 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
...@@ -1119,7 +1119,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1119,7 +1119,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1119 for (buf) |*phdr, i| {1119 for (buf) |*phdr, i| {
1120 phdr.* = self.program_headers.items[i];1120 phdr.* = self.program_headers.items[i];
1121 if (foreign_endian) {1121 if (foreign_endian) {
1122 bswapAllFields(elf.Elf64_Phdr, phdr);1122 std.elf.bswapAllFields(elf.Elf64_Phdr, phdr);
1123 }1123 }
1124 }1124 }
1125 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);1125 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
...@@ -1196,7 +1196,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1196,7 +1196,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1196 shdr.* = sectHeaderTo32(self.sections.items[i]);1196 shdr.* = sectHeaderTo32(self.sections.items[i]);
1197 log.debug("writing section {}\n", .{shdr.*});1197 log.debug("writing section {}\n", .{shdr.*});
1198 if (foreign_endian) {1198 if (foreign_endian) {
1199 bswapAllFields(elf.Elf32_Shdr, shdr);1199 std.elf.bswapAllFields(elf.Elf32_Shdr, shdr);
1200 }1200 }
1201 }1201 }
1202 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);1202 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
...@@ -1209,7 +1209,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1209,7 +1209,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1209 shdr.* = self.sections.items[i];1209 shdr.* = self.sections.items[i];
1210 log.debug("writing section {}\n", .{shdr.*});1210 log.debug("writing section {}\n", .{shdr.*});
1211 if (foreign_endian) {1211 if (foreign_endian) {
1212 bswapAllFields(elf.Elf64_Shdr, shdr);1212 std.elf.bswapAllFields(elf.Elf64_Shdr, shdr);
1213 }1213 }
1214 }1214 }
1215 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);1215 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
...@@ -2787,14 +2787,14 @@ fn writeProgHeader(self: *Elf, index: usize) !void {...@@ -2787,14 +2787,14 @@ fn writeProgHeader(self: *Elf, index: usize) !void {
2787 .p32 => {2787 .p32 => {
2788 var phdr = [1]elf.Elf32_Phdr{progHeaderTo32(self.program_headers.items[index])};2788 var phdr = [1]elf.Elf32_Phdr{progHeaderTo32(self.program_headers.items[index])};
2789 if (foreign_endian) {2789 if (foreign_endian) {
2790 bswapAllFields(elf.Elf32_Phdr, &phdr[0]);2790 std.elf.bswapAllFields(elf.Elf32_Phdr, &phdr[0]);
2791 }2791 }
2792 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);2792 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);
2793 },2793 },
2794 .p64 => {2794 .p64 => {
2795 var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]};2795 var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]};
2796 if (foreign_endian) {2796 if (foreign_endian) {
2797 bswapAllFields(elf.Elf64_Phdr, &phdr[0]);2797 std.elf.bswapAllFields(elf.Elf64_Phdr, &phdr[0]);
2798 }2798 }
2799 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);2799 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);
2800 },2800 },
...@@ -2808,7 +2808,7 @@ fn writeSectHeader(self: *Elf, index: usize) !void {...@@ -2808,7 +2808,7 @@ fn writeSectHeader(self: *Elf, index: usize) !void {
2808 var shdr: [1]elf.Elf32_Shdr = undefined;2808 var shdr: [1]elf.Elf32_Shdr = undefined;
2809 shdr[0] = sectHeaderTo32(self.sections.items[index]);2809 shdr[0] = sectHeaderTo32(self.sections.items[index]);
2810 if (foreign_endian) {2810 if (foreign_endian) {
2811 bswapAllFields(elf.Elf32_Shdr, &shdr[0]);2811 std.elf.bswapAllFields(elf.Elf32_Shdr, &shdr[0]);
2812 }2812 }
2813 const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr);2813 const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr);
2814 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);2814 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
...@@ -2816,7 +2816,7 @@ fn writeSectHeader(self: *Elf, index: usize) !void {...@@ -2816,7 +2816,7 @@ fn writeSectHeader(self: *Elf, index: usize) !void {
2816 .p64 => {2816 .p64 => {
2817 var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]};2817 var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]};
2818 if (foreign_endian) {2818 if (foreign_endian) {
2819 bswapAllFields(elf.Elf64_Shdr, &shdr[0]);2819 std.elf.bswapAllFields(elf.Elf64_Shdr, &shdr[0]);
2820 }2820 }
2821 const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr);2821 const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr);
2822 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);2822 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
...@@ -2914,7 +2914,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {...@@ -2914,7 +2914,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {
2914 },2914 },
2915 };2915 };
2916 if (foreign_endian) {2916 if (foreign_endian) {
2917 bswapAllFields(elf.Elf32_Sym, &sym[0]);2917 std.elf.bswapAllFields(elf.Elf32_Sym, &sym[0]);
2918 }2918 }
2919 const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index;2919 const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index;
2920 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);2920 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
...@@ -2922,7 +2922,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {...@@ -2922,7 +2922,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {
2922 .p64 => {2922 .p64 => {
2923 var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]};2923 var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]};
2924 if (foreign_endian) {2924 if (foreign_endian) {
2925 bswapAllFields(elf.Elf64_Sym, &sym[0]);2925 std.elf.bswapAllFields(elf.Elf64_Sym, &sym[0]);
2926 }2926 }
2927 const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index;2927 const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index;
2928 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);2928 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
...@@ -2953,7 +2953,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -2953,7 +2953,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
2953 .st_shndx = self.global_symbols.items[i].st_shndx,2953 .st_shndx = self.global_symbols.items[i].st_shndx,
2954 };2954 };
2955 if (foreign_endian) {2955 if (foreign_endian) {
2956 bswapAllFields(elf.Elf32_Sym, sym);2956 std.elf.bswapAllFields(elf.Elf32_Sym, sym);
2957 }2957 }
2958 }2958 }
2959 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);2959 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);
...@@ -2972,7 +2972,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -2972,7 +2972,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
2972 .st_shndx = self.global_symbols.items[i].st_shndx,2972 .st_shndx = self.global_symbols.items[i].st_shndx,
2973 };2973 };
2974 if (foreign_endian) {2974 if (foreign_endian) {
2975 bswapAllFields(elf.Elf64_Sym, sym);2975 std.elf.bswapAllFields(elf.Elf64_Sym, sym);
2976 }2976 }
2977 }2977 }
2978 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);2978 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);
...@@ -3188,10 +3188,6 @@ fn pwriteDbgInfoNops(...@@ -3188,10 +3188,6 @@ fn pwriteDbgInfoNops(
3188 try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);3188 try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
3189}3189}
31903190
3191fn bswapAllFields(comptime S: type, ptr: *S) void {
3192 @panic("TODO implement bswapAllFields");
3193}
3194
3195fn progHeaderTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {3191fn progHeaderTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {
3196 return .{3192 return .{
3197 .p_type = phdr.p_type,3193 .p_type = phdr.p_type,
...@@ -3234,8 +3230,20 @@ fn getLDMOption(target: std.Target) ?[]const u8 {...@@ -3234,8 +3230,20 @@ fn getLDMOption(target: std.Target) ?[]const u8 {
3234 .sparcv9 => return "elf64_sparc",3230 .sparcv9 => return "elf64_sparc",
3235 .mips => return "elf32btsmip",3231 .mips => return "elf32btsmip",
3236 .mipsel => return "elf32ltsmip",3232 .mipsel => return "elf32ltsmip",
3237 .mips64 => return "elf64btsmip",3233 .mips64 => {
3238 .mips64el => return "elf64ltsmip",3234 if (target.abi == .gnuabin32) {
3235 return "elf32btsmipn32";
3236 } else {
3237 return "elf64btsmip";
3238 }
3239 },
3240 .mips64el => {
3241 if (target.abi == .gnuabin32) {
3242 return "elf32ltsmipn32";
3243 } else {
3244 return "elf64ltsmip";
3245 }
3246 },
3239 .s390x => return "elf64_s390",3247 .s390x => return "elf64_s390",
3240 .x86_64 => {3248 .x86_64 => {
3241 if (target.abi == .gnux32) {3249 if (target.abi == .gnux32) {
src/test.zig+2-2
...@@ -868,10 +868,10 @@ pub const TestContext = struct {...@@ -868,10 +868,10 @@ pub const TestContext = struct {
868 std.testing.zig_exe_path,868 std.testing.zig_exe_path,
869 "run",869 "run",
870 "-cflags",870 "-cflags",
871 "-std=c89",871 "-std=c99",
872 "-pedantic",872 "-pedantic",
873 "-Werror",873 "-Werror",
874 "-Wno-declaration-after-statement",874 "-Wno-incompatible-library-redeclaration", // https://github.com/ziglang/zig/issues/875
875 "--",875 "--",
876 "-lc",876 "-lc",
877 exe_path,877 exe_path,
src/translate_c.zig+120-44
...@@ -671,15 +671,6 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -671,15 +671,6 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
671 break :blk null;671 break :blk null;
672 };672 };
673673
674 const alignment = blk: {
675 const alignment = var_decl.getAlignedAttribute(c.clang_context);
676 if (alignment != 0) {
677 // Clang reports the alignment in bits
678 break :blk alignment / 8;
679 }
680 break :blk null;
681 };
682
683 const node = try Tag.var_decl.create(c.arena, .{674 const node = try Tag.var_decl.create(c.arena, .{
684 .is_pub = is_pub,675 .is_pub = is_pub,
685 .is_const = is_const,676 .is_const = is_const,
...@@ -687,7 +678,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -687,7 +678,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
687 .is_export = is_export,678 .is_export = is_export,
688 .is_threadlocal = is_threadlocal,679 .is_threadlocal = is_threadlocal,
689 .linksection_string = linksection_string,680 .linksection_string = linksection_string,
690 .alignment = alignment,681 .alignment = zigAlignment(var_decl.getAlignedAttribute(c.clang_context)),
691 .name = checked_name,682 .name = checked_name,
692 .type = type_node,683 .type = type_node,
693 .init = init_node,684 .init = init_node,
...@@ -833,14 +824,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD...@@ -833,14 +824,7 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD
833 else => |e| return e,824 else => |e| return e,
834 };825 };
835826
836 const alignment = blk_2: {827 const alignment = zigAlignment(field_decl.getAlignedAttribute(c.clang_context));
837 const alignment = field_decl.getAlignedAttribute(c.clang_context);
838 if (alignment != 0) {
839 // Clang reports the alignment in bits
840 break :blk_2 alignment / 8;
841 }
842 break :blk_2 null;
843 };
844828
845 if (is_anon) {829 if (is_anon) {
846 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);830 try c.decl_table.putNoClobber(c.gpa, @ptrToInt(field_decl.getCanonicalDecl()), field_name);
...@@ -1070,6 +1054,10 @@ fn transStmt(...@@ -1070,6 +1054,10 @@ fn transStmt(
1070 return maybeSuppressResult(c, scope, result_used, expr);1054 return maybeSuppressResult(c, scope, result_used, expr);
1071 },1055 },
1072 .OffsetOfExprClass => return transOffsetOfExpr(c, scope, @ptrCast(*const clang.OffsetOfExpr, stmt), result_used),1056 .OffsetOfExprClass => return transOffsetOfExpr(c, scope, @ptrCast(*const clang.OffsetOfExpr, stmt), result_used),
1057 .CompoundLiteralExprClass => {
1058 const compound_literal = @ptrCast(*const clang.CompoundLiteralExpr, stmt);
1059 return transExpr(c, scope, compound_literal.getInitializer(), result_used);
1060 },
1073 else => {1061 else => {
1074 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});1062 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});
1075 },1063 },
...@@ -1127,6 +1115,52 @@ fn transOffsetOfExpr(...@@ -1127,6 +1115,52 @@ fn transOffsetOfExpr(
1127 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO: implement complex OffsetOfExpr translation", .{});1115 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "TODO: implement complex OffsetOfExpr translation", .{});
1128}1116}
11291117
1118/// Cast a signed integer node to a usize, for use in pointer arithmetic. Negative numbers
1119/// will become very large positive numbers but that is ok since we only use this in
1120/// pointer arithmetic expressions, where wraparound will ensure we get the correct value.
1121/// node -> @bitCast(usize, @intCast(isize, node))
1122fn usizeCastForWrappingPtrArithmetic(gpa: *mem.Allocator, node: Node) TransError!Node {
1123 const intcast_node = try Tag.int_cast.create(gpa, .{
1124 .lhs = try Tag.identifier.create(gpa, "isize"),
1125 .rhs = node,
1126 });
1127
1128 return Tag.bit_cast.create(gpa, .{
1129 .lhs = try Tag.identifier.create(gpa, "usize"),
1130 .rhs = intcast_node,
1131 });
1132}
1133
1134/// Translate an arithmetic expression with a pointer operand and a signed-integer operand.
1135/// Zig requires a usize argument for pointer arithmetic, so we intCast to isize and then
1136/// bitcast to usize; pointer wraparound make the math work.
1137/// Zig pointer addition is not commutative (unlike C); the pointer operand needs to be on the left.
1138/// The + operator in C is not a sequence point so it should be safe to switch the order if necessary.
1139fn transCreatePointerArithmeticSignedOp(
1140 c: *Context,
1141 scope: *Scope,
1142 stmt: *const clang.BinaryOperator,
1143 result_used: ResultUsed,
1144) TransError!Node {
1145 const is_add = stmt.getOpcode() == .Add;
1146 const lhs = stmt.getLHS();
1147 const rhs = stmt.getRHS();
1148 const swap_operands = is_add and cIsSignedInteger(getExprQualType(c, lhs));
1149
1150 const swizzled_lhs = if (swap_operands) rhs else lhs;
1151 const swizzled_rhs = if (swap_operands) lhs else rhs;
1152
1153 const lhs_node = try transExpr(c, scope, swizzled_lhs, .used);
1154 const rhs_node = try transExpr(c, scope, swizzled_rhs, .used);
1155
1156 const bitcast_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
1157
1158 const arith_args = .{ .lhs = lhs_node, .rhs = bitcast_node };
1159 const arith_node = try if (is_add) Tag.add.create(c.arena, arith_args) else Tag.sub.create(c.arena, arith_args);
1160
1161 return maybeSuppressResult(c, scope, result_used, arith_node);
1162}
1163
1130fn transBinaryOperator(1164fn transBinaryOperator(
1131 c: *Context,1165 c: *Context,
1132 scope: *Scope,1166 scope: *Scope,
...@@ -1184,6 +1218,12 @@ fn transBinaryOperator(...@@ -1184,6 +1218,12 @@ fn transBinaryOperator(
1184 .LOr => {1218 .LOr => {
1185 return transCreateNodeBoolInfixOp(c, scope, stmt, .@"or", result_used);1219 return transCreateNodeBoolInfixOp(c, scope, stmt, .@"or", result_used);
1186 },1220 },
1221 .Add, .Sub => {
1222 // `ptr + idx` and `idx + ptr` -> ptr + @bitCast(usize, @intCast(isize, idx))
1223 // `ptr - idx` -> ptr - @bitCast(usize, @intCast(isize, idx))
1224 if (qualTypeIsPtr(qt) and (cIsSignedInteger(getExprQualType(c, stmt.getLHS())) or
1225 cIsSignedInteger(getExprQualType(c, stmt.getRHS())))) return transCreatePointerArithmeticSignedOp(c, scope, stmt, result_used);
1226 },
1187 else => {},1227 else => {},
1188 }1228 }
1189 var op_id: Tag = undefined;1229 var op_id: Tag = undefined;
...@@ -1329,6 +1369,13 @@ fn transCStyleCastExprClass(...@@ -1329,6 +1369,13 @@ fn transCStyleCastExprClass(
1329 return maybeSuppressResult(c, scope, result_used, cast_node);1369 return maybeSuppressResult(c, scope, result_used, cast_node);
1330}1370}
13311371
1372/// Clang reports the alignment in bits, we use bytes
1373/// Clang uses 0 for "no alignment specified", we use null
1374fn zigAlignment(bit_alignment: c_uint) ?c_uint {
1375 if (bit_alignment == 0) return null;
1376 return bit_alignment / 8;
1377}
1378
1332fn transDeclStmtOne(1379fn transDeclStmtOne(
1333 c: *Context,1380 c: *Context,
1334 scope: *Scope,1381 scope: *Scope,
...@@ -1368,6 +1415,7 @@ fn transDeclStmtOne(...@@ -1368,6 +1415,7 @@ fn transDeclStmtOne(
1368 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {1415 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
1369 init_node = try Tag.bool_to_int.create(c.arena, init_node);1416 init_node = try Tag.bool_to_int.create(c.arena, init_node);
1370 }1417 }
1418
1371 const node = try Tag.var_decl.create(c.arena, .{1419 const node = try Tag.var_decl.create(c.arena, .{
1372 .is_pub = false,1420 .is_pub = false,
1373 .is_const = is_const,1421 .is_const = is_const,
...@@ -1375,7 +1423,7 @@ fn transDeclStmtOne(...@@ -1375,7 +1423,7 @@ fn transDeclStmtOne(
1375 .is_export = false,1423 .is_export = false,
1376 .is_threadlocal = false,1424 .is_threadlocal = false,
1377 .linksection_string = null,1425 .linksection_string = null,
1378 .alignment = null,1426 .alignment = zigAlignment(var_decl.getAlignedAttribute(c.clang_context)),
1379 .name = mangled_name,1427 .name = mangled_name,
1380 .type = type_node,1428 .type = type_node,
1381 .init = init_node,1429 .init = init_node,
...@@ -1449,7 +1497,8 @@ fn transImplicitCastExpr(...@@ -1449,7 +1497,8 @@ fn transImplicitCastExpr(
1449 }1497 }
14501498
1451 const addr = try Tag.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used));1499 const addr = try Tag.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used));
1452 return maybeSuppressResult(c, scope, result_used, addr);1500 const casted = try transCPtrCast(c, scope, expr.getBeginLoc(), dest_type, src_type, addr);
1501 return maybeSuppressResult(c, scope, result_used, casted);
1453 },1502 },
1454 .NullToPointer => {1503 .NullToPointer => {
1455 return Tag.null_literal.init();1504 return Tag.null_literal.init();
...@@ -2515,8 +2564,8 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:...@@ -2515,8 +2564,8 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
2515 });2564 });
2516 return maybeSuppressResult(c, scope, used, as_node);2565 return maybeSuppressResult(c, scope, used, as_node);
2517 },2566 },
2518 else => {2567 else => |kind| {
2519 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "unsupported constant expression kind", .{});2568 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "unsupported constant expression kind '{s}'", .{kind});
2520 },2569 },
2521 }2570 }
2522}2571}
...@@ -2999,6 +3048,7 @@ fn transCreateCompoundAssign(...@@ -2999,6 +3048,7 @@ fn transCreateCompoundAssign(
2999 const lhs_qt = getExprQualType(c, lhs);3048 const lhs_qt = getExprQualType(c, lhs);
3000 const rhs_qt = getExprQualType(c, rhs);3049 const rhs_qt = getExprQualType(c, rhs);
3001 const is_signed = cIsSignedInteger(lhs_qt);3050 const is_signed = cIsSignedInteger(lhs_qt);
3051 const is_ptr_op_signed = qualTypeIsPtr(lhs_qt) and cIsSignedInteger(rhs_qt);
3002 const requires_int_cast = blk: {3052 const requires_int_cast = blk: {
3003 const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt);3053 const are_integers = cIsInteger(lhs_qt) and cIsInteger(rhs_qt);
3004 const are_same_sign = cIsSignedInteger(lhs_qt) == cIsSignedInteger(rhs_qt);3054 const are_same_sign = cIsSignedInteger(lhs_qt) == cIsSignedInteger(rhs_qt);
...@@ -3025,6 +3075,10 @@ fn transCreateCompoundAssign(...@@ -3025,6 +3075,10 @@ fn transCreateCompoundAssign(
3025 else3075 else
3026 try transExpr(c, scope, rhs, .used);3076 try transExpr(c, scope, rhs, .used);
30273077
3078 if (is_ptr_op_signed) {
3079 rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
3080 }
3081
3028 if (is_shift or requires_int_cast) {3082 if (is_shift or requires_int_cast) {
3029 // @intCast(rhs)3083 // @intCast(rhs)
3030 const cast_to_type = if (is_shift)3084 const cast_to_type = if (is_shift)
...@@ -3077,6 +3131,9 @@ fn transCreateCompoundAssign(...@@ -3077,6 +3131,9 @@ fn transCreateCompoundAssign(
30773131
3078 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });3132 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
3079 }3133 }
3134 if (is_ptr_op_signed) {
3135 rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
3136 }
30803137
3081 const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used);3138 const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used);
3082 try block_scope.statements.append(assign);3139 try block_scope.statements.append(assign);
...@@ -3104,10 +3161,10 @@ fn transCPtrCast(...@@ -3104,10 +3161,10 @@ fn transCPtrCast(
3104 const src_child_type = src_ty.getPointeeType();3161 const src_child_type = src_ty.getPointeeType();
3105 const dst_type_node = try transType(c, scope, ty, loc);3162 const dst_type_node = try transType(c, scope, ty, loc);
31063163
3107 if ((src_child_type.isConstQualified() and3164 if (!src_ty.isArrayType() and ((src_child_type.isConstQualified() and
3108 !child_type.isConstQualified()) or3165 !child_type.isConstQualified()) or
3109 (src_child_type.isVolatileQualified() and3166 (src_child_type.isVolatileQualified() and
3110 !child_type.isVolatileQualified()))3167 !child_type.isVolatileQualified())))
3111 {3168 {
3112 // Casting away const or volatile requires us to use @intToPtr3169 // Casting away const or volatile requires us to use @intToPtr
3113 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);3170 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
...@@ -4067,16 +4124,7 @@ fn finishTransFnProto(...@@ -4067,16 +4124,7 @@ fn finishTransFnProto(
4067 break :blk null;4124 break :blk null;
4068 };4125 };
40694126
4070 const alignment = blk: {4127 const alignment = if (fn_decl) |decl| zigAlignment(decl.getAlignedAttribute(c.clang_context)) else null;
4071 if (fn_decl) |decl| {
4072 const alignment = decl.getAlignedAttribute(c.clang_context);
4073 if (alignment != 0) {
4074 // Clang reports the alignment in bits
4075 break :blk alignment / 8;
4076 }
4077 }
4078 break :blk null;
4079 };
40804128
4081 const explicit_callconv = if ((is_export or is_extern) and cc == .C) null else cc;4129 const explicit_callconv = if ((is_export or is_extern) and cc == .C) null else cc;
40824130
...@@ -4387,40 +4435,68 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4387,40 +4435,68 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
43874435
4388 switch (m.list[m.i].id) {4436 switch (m.list[m.i].id) {
4389 .IntegerLiteral => |suffix| {4437 .IntegerLiteral => |suffix| {
4438 var radix: []const u8 = "decimal";
4390 if (lit_bytes.len > 2 and lit_bytes[0] == '0') {4439 if (lit_bytes.len > 2 and lit_bytes[0] == '0') {
4391 switch (lit_bytes[1]) {4440 switch (lit_bytes[1]) {
4392 '0'...'7' => {4441 '0'...'7' => {
4393 // Octal4442 // Octal
4394 lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes});4443 lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes[1..]});
4444 radix = "octal";
4395 },4445 },
4396 'X' => {4446 'X' => {
4397 // Hexadecimal with capital X, valid in C but not in Zig4447 // Hexadecimal with capital X, valid in C but not in Zig
4398 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]});4448 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]});
4449 radix = "hexadecimal";
4450 },
4451 'x' => {
4452 radix = "hexadecimal";
4399 },4453 },
4400 else => {},4454 else => {},
4401 }4455 }
4402 }4456 }
44034457
4404 if (suffix == .none) {
4405 return transCreateNodeNumber(c, lit_bytes, .int);
4406 }
4407
4408 const type_node = try Tag.type.create(c.arena, switch (suffix) {4458 const type_node = try Tag.type.create(c.arena, switch (suffix) {
4459 .none => "c_int",
4409 .u => "c_uint",4460 .u => "c_uint",
4410 .l => "c_long",4461 .l => "c_long",
4411 .lu => "c_ulong",4462 .lu => "c_ulong",
4412 .ll => "c_longlong",4463 .ll => "c_longlong",
4413 .llu => "c_ulonglong",4464 .llu => "c_ulonglong",
4414 else => unreachable,4465 .f => unreachable,
4415 });4466 });
4416 lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (suffix) {4467 lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (suffix) {
4417 .u, .l => @as(u8, 1),4468 .none => @as(u8, 0),
4469 .u, .l => 1,
4418 .lu, .ll => 2,4470 .lu, .ll => 2,
4419 .llu => 3,4471 .llu => 3,
4420 else => unreachable,4472 .f => unreachable,
4421 }];4473 }];
4422 const rhs = try transCreateNodeNumber(c, lit_bytes, .int);4474
4423 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });4475 const value = std.fmt.parseInt(i128, lit_bytes, 0) catch math.maxInt(i128);
4476
4477 // make the output less noisy by skipping promoteIntLiteral where
4478 // it's guaranteed to not be required because of C standard type constraints
4479 const guaranteed_to_fit = switch (suffix) {
4480 .none => if (math.cast(i16, value)) |_| true else |_| false,
4481 .u => if (math.cast(u16, value)) |_| true else |_| false,
4482 .l => if (math.cast(i32, value)) |_| true else |_| false,
4483 .lu => if (math.cast(u32, value)) |_| true else |_| false,
4484 .ll => if (math.cast(i64, value)) |_| true else |_| false,
4485 .llu => if (math.cast(u64, value)) |_| true else |_| false,
4486 .f => unreachable,
4487 };
4488
4489 const literal_node = try transCreateNodeNumber(c, lit_bytes, .int);
4490
4491 if (guaranteed_to_fit) {
4492 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = literal_node });
4493 } else {
4494 return Tag.std_meta_promoteIntLiteral.create(c.arena, .{
4495 .type = type_node,
4496 .value = literal_node,
4497 .radix = try Tag.enum_literal.create(c.arena, radix),
4498 });
4499 }
4424 },4500 },
4425 .FloatLiteral => |suffix| {4501 .FloatLiteral => |suffix| {
4426 if (lit_bytes[0] == '.')4502 if (lit_bytes[0] == '.')
src/translate_c/ast.zig+29
...@@ -39,6 +39,7 @@ pub const Node = extern union {...@@ -39,6 +39,7 @@ pub const Node = extern union {
39 float_literal,39 float_literal,
40 string_literal,40 string_literal,
41 char_literal,41 char_literal,
42 enum_literal,
42 identifier,43 identifier,
43 @"if",44 @"if",
44 /// if (!operand) break;45 /// if (!operand) break;
...@@ -117,6 +118,7 @@ pub const Node = extern union {...@@ -117,6 +118,7 @@ pub const Node = extern union {
117 /// @intCast(lhs, rhs)118 /// @intCast(lhs, rhs)
118 int_cast,119 int_cast,
119 /// @rem(lhs, rhs)120 /// @rem(lhs, rhs)
121 std_meta_promoteIntLiteral,
120 rem,122 rem,
121 /// @divTrunc(lhs, rhs)123 /// @divTrunc(lhs, rhs)
122 div_trunc,124 div_trunc,
...@@ -312,6 +314,7 @@ pub const Node = extern union {...@@ -312,6 +314,7 @@ pub const Node = extern union {
312 .float_literal,314 .float_literal,
313 .string_literal,315 .string_literal,
314 .char_literal,316 .char_literal,
317 .enum_literal,
315 .identifier,318 .identifier,
316 .warning,319 .warning,
317 .type,320 .type,
...@@ -328,6 +331,7 @@ pub const Node = extern union {...@@ -328,6 +331,7 @@ pub const Node = extern union {
328 .tuple => Payload.TupleInit,331 .tuple => Payload.TupleInit,
329 .container_init => Payload.ContainerInit,332 .container_init => Payload.ContainerInit,
330 .std_meta_cast => Payload.Infix,333 .std_meta_cast => Payload.Infix,
334 .std_meta_promoteIntLiteral => Payload.PromoteIntLiteral,
331 .block => Payload.Block,335 .block => Payload.Block,
332 .c_pointer, .single_pointer => Payload.Pointer,336 .c_pointer, .single_pointer => Payload.Pointer,
333 .array_type => Payload.Array,337 .array_type => Payload.Array,
...@@ -651,6 +655,15 @@ pub const Payload = struct {...@@ -651,6 +655,15 @@ pub const Payload = struct {
651 field_name: []const u8,655 field_name: []const u8,
652 },656 },
653 };657 };
658
659 pub const PromoteIntLiteral = struct {
660 base: Payload,
661 data: struct {
662 value: Node,
663 type: Node,
664 radix: Node,
665 },
666 };
654};667};
655668
656/// Converts the nodes into a Zig ast.669/// Converts the nodes into a Zig ast.
...@@ -821,6 +834,11 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -821,6 +834,11 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
821 const import_node = try renderStdImport(c, "meta", "cast");834 const import_node = try renderStdImport(c, "meta", "cast");
822 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });835 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });
823 },836 },
837 .std_meta_promoteIntLiteral => {
838 const payload = node.castTag(.std_meta_promoteIntLiteral).?.data;
839 const import_node = try renderStdImport(c, "meta", "promoteIntLiteral");
840 return renderCall(c, import_node, &.{ payload.type, payload.value, payload.radix });
841 },
824 .std_meta_sizeof => {842 .std_meta_sizeof => {
825 const payload = node.castTag(.std_meta_sizeof).?.data;843 const payload = node.castTag(.std_meta_sizeof).?.data;
826 const import_node = try renderStdImport(c, "meta", "sizeof");844 const import_node = try renderStdImport(c, "meta", "sizeof");
...@@ -988,6 +1006,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -988,6 +1006,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
988 .data = undefined,1006 .data = undefined,
989 });1007 });
990 },1008 },
1009 .enum_literal => {
1010 const payload = node.castTag(.enum_literal).?.data;
1011 _ = try c.addToken(.period, ".");
1012 return c.addNode(.{
1013 .tag = .enum_literal,
1014 .main_token = try c.addToken(.identifier, payload),
1015 .data = undefined,
1016 });
1017 },
991 .fail_decl => {1018 .fail_decl => {
992 const payload = node.castTag(.fail_decl).?.data;1019 const payload = node.castTag(.fail_decl).?.data;
993 // pub const name = @compileError(msg);1020 // pub const name = @compileError(msg);
...@@ -1982,11 +2009,13 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -1982,11 +2009,13 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
1982 .typeof,2009 .typeof,
1983 .std_meta_sizeof,2010 .std_meta_sizeof,
1984 .std_meta_cast,2011 .std_meta_cast,
2012 .std_meta_promoteIntLiteral,
1985 .std_mem_zeroinit,2013 .std_mem_zeroinit,
1986 .integer_literal,2014 .integer_literal,
1987 .float_literal,2015 .float_literal,
1988 .string_literal,2016 .string_literal,
1989 .char_literal,2017 .char_literal,
2018 .enum_literal,
1990 .identifier,2019 .identifier,
1991 .field_access,2020 .field_access,
1992 .ptr_cast,2021 .ptr_cast,
src/type.zig+70-2
...@@ -97,6 +97,8 @@ pub const Type = extern union {...@@ -97,6 +97,8 @@ pub const Type = extern union {
97 .@"struct", .empty_struct => return .Struct,97 .@"struct", .empty_struct => return .Struct,
98 .@"enum" => return .Enum,98 .@"enum" => return .Enum,
99 .@"union" => return .Union,99 .@"union" => return .Union,
100
101 .var_args_param => unreachable, // can be any type
100 }102 }
101 }103 }
102104
...@@ -258,6 +260,8 @@ pub const Type = extern union {...@@ -258,6 +260,8 @@ pub const Type = extern union {
258 if (!a.fnParamType(i).eql(b.fnParamType(i)))260 if (!a.fnParamType(i).eql(b.fnParamType(i)))
259 return false;261 return false;
260 }262 }
263 if (a.fnIsVarArgs() != b.fnIsVarArgs())
264 return false;
261 return true;265 return true;
262 },266 },
263 .Optional => {267 .Optional => {
...@@ -323,6 +327,7 @@ pub const Type = extern union {...@@ -323,6 +327,7 @@ pub const Type = extern union {
323 while (i < params_len) : (i += 1) {327 while (i < params_len) : (i += 1) {
324 std.hash.autoHash(&hasher, self.fnParamType(i).hash());328 std.hash.autoHash(&hasher, self.fnParamType(i).hash());
325 }329 }
330 std.hash.autoHash(&hasher, self.fnIsVarArgs());
326 },331 },
327 .Optional => {332 .Optional => {
328 var buf: Payload.ElemType = undefined;333 var buf: Payload.ElemType = undefined;
...@@ -397,6 +402,7 @@ pub const Type = extern union {...@@ -397,6 +402,7 @@ pub const Type = extern union {
397 .@"anyframe",402 .@"anyframe",
398 .inferred_alloc_const,403 .inferred_alloc_const,
399 .inferred_alloc_mut,404 .inferred_alloc_mut,
405 .var_args_param,
400 => unreachable,406 => unreachable,
401407
402 .array_u8,408 .array_u8,
...@@ -446,6 +452,7 @@ pub const Type = extern union {...@@ -446,6 +452,7 @@ pub const Type = extern union {
446 .return_type = try payload.return_type.copy(allocator),452 .return_type = try payload.return_type.copy(allocator),
447 .param_types = param_types,453 .param_types = param_types,
448 .cc = payload.cc,454 .cc = payload.cc,
455 .is_var_args = payload.is_var_args,
449 });456 });
450 },457 },
451 .pointer => {458 .pointer => {
...@@ -535,6 +542,7 @@ pub const Type = extern union {...@@ -535,6 +542,7 @@ pub const Type = extern union {
535 .comptime_int,542 .comptime_int,
536 .comptime_float,543 .comptime_float,
537 .noreturn,544 .noreturn,
545 .var_args_param,
538 => return out_stream.writeAll(@tagName(t)),546 => return out_stream.writeAll(@tagName(t)),
539547
540 .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"),548 .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"),
...@@ -558,6 +566,12 @@ pub const Type = extern union {...@@ -558,6 +566,12 @@ pub const Type = extern union {
558 if (i != 0) try out_stream.writeAll(", ");566 if (i != 0) try out_stream.writeAll(", ");
559 try param_type.format("", .{}, out_stream);567 try param_type.format("", .{}, out_stream);
560 }568 }
569 if (payload.is_var_args) {
570 if (payload.param_types.len != 0) {
571 try out_stream.writeAll(", ");
572 }
573 try out_stream.writeAll("...");
574 }
561 try out_stream.writeAll(") callconv(.");575 try out_stream.writeAll(") callconv(.");
562 try out_stream.writeAll(@tagName(payload.cc));576 try out_stream.writeAll(@tagName(payload.cc));
563 try out_stream.writeAll(")");577 try out_stream.writeAll(")");
...@@ -844,6 +858,7 @@ pub const Type = extern union {...@@ -844,6 +858,7 @@ pub const Type = extern union {
844858
845 .inferred_alloc_const => unreachable,859 .inferred_alloc_const => unreachable,
846 .inferred_alloc_mut => unreachable,860 .inferred_alloc_mut => unreachable,
861 .var_args_param => unreachable,
847 };862 };
848 }863 }
849864
...@@ -969,6 +984,7 @@ pub const Type = extern union {...@@ -969,6 +984,7 @@ pub const Type = extern union {
969 .inferred_alloc_const,984 .inferred_alloc_const,
970 .inferred_alloc_mut,985 .inferred_alloc_mut,
971 .@"opaque",986 .@"opaque",
987 .var_args_param,
972 => unreachable,988 => unreachable,
973 };989 };
974 }990 }
...@@ -995,6 +1011,7 @@ pub const Type = extern union {...@@ -995,6 +1011,7 @@ pub const Type = extern union {
995 .inferred_alloc_const => unreachable,1011 .inferred_alloc_const => unreachable,
996 .inferred_alloc_mut => unreachable,1012 .inferred_alloc_mut => unreachable,
997 .@"opaque" => unreachable,1013 .@"opaque" => unreachable,
1014 .var_args_param => unreachable,
9981015
999 .u8,1016 .u8,
1000 .i8,1017 .i8,
...@@ -1179,6 +1196,7 @@ pub const Type = extern union {...@@ -1179,6 +1196,7 @@ pub const Type = extern union {
1179 .@"struct",1196 .@"struct",
1180 .@"union",1197 .@"union",
1181 .@"opaque",1198 .@"opaque",
1199 .var_args_param,
1182 => false,1200 => false,
11831201
1184 .single_const_pointer,1202 .single_const_pointer,
...@@ -1256,6 +1274,7 @@ pub const Type = extern union {...@@ -1256,6 +1274,7 @@ pub const Type = extern union {
1256 .@"struct",1274 .@"struct",
1257 .@"union",1275 .@"union",
1258 .@"opaque",1276 .@"opaque",
1277 .var_args_param,
1259 => unreachable,1278 => unreachable,
12601279
1261 .const_slice,1280 .const_slice,
...@@ -1354,6 +1373,7 @@ pub const Type = extern union {...@@ -1354,6 +1373,7 @@ pub const Type = extern union {
1354 .@"struct",1373 .@"struct",
1355 .@"union",1374 .@"union",
1356 .@"opaque",1375 .@"opaque",
1376 .var_args_param,
1357 => false,1377 => false,
13581378
1359 .const_slice,1379 .const_slice,
...@@ -1434,6 +1454,7 @@ pub const Type = extern union {...@@ -1434,6 +1454,7 @@ pub const Type = extern union {
1434 .@"struct",1454 .@"struct",
1435 .@"union",1455 .@"union",
1436 .@"opaque",1456 .@"opaque",
1457 .var_args_param,
1437 => false,1458 => false,
14381459
1439 .single_const_pointer,1460 .single_const_pointer,
...@@ -1523,6 +1544,7 @@ pub const Type = extern union {...@@ -1523,6 +1544,7 @@ pub const Type = extern union {
1523 .@"struct",1544 .@"struct",
1524 .@"union",1545 .@"union",
1525 .@"opaque",1546 .@"opaque",
1547 .var_args_param,
1526 => false,1548 => false,
15271549
1528 .pointer => {1550 .pointer => {
...@@ -1607,6 +1629,7 @@ pub const Type = extern union {...@@ -1607,6 +1629,7 @@ pub const Type = extern union {
1607 .@"struct",1629 .@"struct",
1608 .@"union",1630 .@"union",
1609 .@"opaque",1631 .@"opaque",
1632 .var_args_param,
1610 => false,1633 => false,
16111634
1612 .pointer => {1635 .pointer => {
...@@ -1663,8 +1686,8 @@ pub const Type = extern union {...@@ -1663,8 +1686,8 @@ pub const Type = extern union {
1663 return ty.optionalChild(&buf).isValidVarType(is_extern);1686 return ty.optionalChild(&buf).isValidVarType(is_extern);
1664 },1687 },
1665 .Pointer, .Array => ty = ty.elemType(),1688 .Pointer, .Array => ty = ty.elemType(),
1689 .ErrorUnion => ty = ty.errorUnionChild(),
16661690
1667 .ErrorUnion => @panic("TODO fn isValidVarType"),
1668 .Fn => @panic("TODO fn isValidVarType"),1691 .Fn => @panic("TODO fn isValidVarType"),
1669 .Struct => @panic("TODO struct isValidVarType"),1692 .Struct => @panic("TODO struct isValidVarType"),
1670 .Union => @panic("TODO union isValidVarType"),1693 .Union => @panic("TODO union isValidVarType"),
...@@ -1733,6 +1756,7 @@ pub const Type = extern union {...@@ -1733,6 +1756,7 @@ pub const Type = extern union {
1733 .@"struct" => unreachable,1756 .@"struct" => unreachable,
1734 .@"union" => unreachable,1757 .@"union" => unreachable,
1735 .@"opaque" => unreachable,1758 .@"opaque" => unreachable,
1759 .var_args_param => unreachable,
17361760
1737 .array => self.castTag(.array).?.data.elem_type,1761 .array => self.castTag(.array).?.data.elem_type,
1738 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,1762 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
...@@ -1789,6 +1813,29 @@ pub const Type = extern union {...@@ -1789,6 +1813,29 @@ pub const Type = extern union {
1789 }1813 }
1790 }1814 }
17911815
1816 /// Asserts that the type is an error union.
1817 pub fn errorUnionChild(self: Type) Type {
1818 return switch (self.tag()) {
1819 .anyerror_void_error_union => Type.initTag(.anyerror),
1820 .error_union => {
1821 const payload = self.castTag(.error_union).?;
1822 return payload.data.payload;
1823 },
1824 else => unreachable,
1825 };
1826 }
1827
1828 pub fn errorUnionSet(self: Type) Type {
1829 return switch (self.tag()) {
1830 .anyerror_void_error_union => Type.initTag(.anyerror),
1831 .error_union => {
1832 const payload = self.castTag(.error_union).?;
1833 return payload.data.error_set;
1834 },
1835 else => unreachable,
1836 };
1837 }
1838
1792 /// Asserts the type is an array or vector.1839 /// Asserts the type is an array or vector.
1793 pub fn arrayLen(self: Type) u64 {1840 pub fn arrayLen(self: Type) u64 {
1794 return switch (self.tag()) {1841 return switch (self.tag()) {
...@@ -1862,6 +1909,7 @@ pub const Type = extern union {...@@ -1862,6 +1909,7 @@ pub const Type = extern union {
1862 .@"struct",1909 .@"struct",
1863 .@"union",1910 .@"union",
1864 .@"opaque",1911 .@"opaque",
1912 .var_args_param,
1865 => unreachable,1913 => unreachable,
18661914
1867 .array => self.castTag(.array).?.data.len,1915 .array => self.castTag(.array).?.data.len,
...@@ -1936,6 +1984,7 @@ pub const Type = extern union {...@@ -1936,6 +1984,7 @@ pub const Type = extern union {
1936 .@"struct",1984 .@"struct",
1937 .@"union",1985 .@"union",
1938 .@"opaque",1986 .@"opaque",
1987 .var_args_param,
1939 => unreachable,1988 => unreachable,
19401989
1941 .single_const_pointer,1990 .single_const_pointer,
...@@ -2025,6 +2074,7 @@ pub const Type = extern union {...@@ -2025,6 +2074,7 @@ pub const Type = extern union {
2025 .@"struct",2074 .@"struct",
2026 .@"union",2075 .@"union",
2027 .@"opaque",2076 .@"opaque",
2077 .var_args_param,
2028 => false,2078 => false,
20292079
2030 .int_signed,2080 .int_signed,
...@@ -2110,6 +2160,7 @@ pub const Type = extern union {...@@ -2110,6 +2160,7 @@ pub const Type = extern union {
2110 .@"struct",2160 .@"struct",
2111 .@"union",2161 .@"union",
2112 .@"opaque",2162 .@"opaque",
2163 .var_args_param,
2113 => false,2164 => false,
21142165
2115 .int_unsigned,2166 .int_unsigned,
...@@ -2181,6 +2232,7 @@ pub const Type = extern union {...@@ -2181,6 +2232,7 @@ pub const Type = extern union {
2181 .@"struct",2232 .@"struct",
2182 .@"union",2233 .@"union",
2183 .@"opaque",2234 .@"opaque",
2235 .var_args_param,
2184 => unreachable,2236 => unreachable,
21852237
2186 .int_unsigned => .{2238 .int_unsigned => .{
...@@ -2280,6 +2332,7 @@ pub const Type = extern union {...@@ -2280,6 +2332,7 @@ pub const Type = extern union {
2280 .@"struct",2332 .@"struct",
2281 .@"union",2333 .@"union",
2282 .@"opaque",2334 .@"opaque",
2335 .var_args_param,
2283 => false,2336 => false,
22842337
2285 .usize,2338 .usize,
...@@ -2400,6 +2453,7 @@ pub const Type = extern union {...@@ -2400,6 +2453,7 @@ pub const Type = extern union {
2400 .@"struct",2453 .@"struct",
2401 .@"union",2454 .@"union",
2402 .@"opaque",2455 .@"opaque",
2456 .var_args_param,
2403 => unreachable,2457 => unreachable,
2404 };2458 };
2405 }2459 }
...@@ -2486,6 +2540,7 @@ pub const Type = extern union {...@@ -2486,6 +2540,7 @@ pub const Type = extern union {
2486 .@"struct",2540 .@"struct",
2487 .@"union",2541 .@"union",
2488 .@"opaque",2542 .@"opaque",
2543 .var_args_param,
2489 => unreachable,2544 => unreachable,
2490 }2545 }
2491 }2546 }
...@@ -2571,6 +2626,7 @@ pub const Type = extern union {...@@ -2571,6 +2626,7 @@ pub const Type = extern union {
2571 .@"struct",2626 .@"struct",
2572 .@"union",2627 .@"union",
2573 .@"opaque",2628 .@"opaque",
2629 .var_args_param,
2574 => unreachable,2630 => unreachable,
2575 }2631 }
2576 }2632 }
...@@ -2656,6 +2712,7 @@ pub const Type = extern union {...@@ -2656,6 +2712,7 @@ pub const Type = extern union {
2656 .@"struct",2712 .@"struct",
2657 .@"union",2713 .@"union",
2658 .@"opaque",2714 .@"opaque",
2715 .var_args_param,
2659 => unreachable,2716 => unreachable,
2660 };2717 };
2661 }2718 }
...@@ -2738,6 +2795,7 @@ pub const Type = extern union {...@@ -2738,6 +2795,7 @@ pub const Type = extern union {
2738 .@"struct",2795 .@"struct",
2739 .@"union",2796 .@"union",
2740 .@"opaque",2797 .@"opaque",
2798 .var_args_param,
2741 => unreachable,2799 => unreachable,
2742 };2800 };
2743 }2801 }
...@@ -2749,7 +2807,7 @@ pub const Type = extern union {...@@ -2749,7 +2807,7 @@ pub const Type = extern union {
2749 .fn_void_no_args => false,2807 .fn_void_no_args => false,
2750 .fn_naked_noreturn_no_args => false,2808 .fn_naked_noreturn_no_args => false,
2751 .fn_ccc_void_no_args => false,2809 .fn_ccc_void_no_args => false,
2752 .function => false,2810 .function => self.castTag(.function).?.data.is_var_args,
27532811
2754 .f16,2812 .f16,
2755 .f32,2813 .f32,
...@@ -2820,6 +2878,7 @@ pub const Type = extern union {...@@ -2820,6 +2878,7 @@ pub const Type = extern union {
2820 .@"struct",2878 .@"struct",
2821 .@"union",2879 .@"union",
2822 .@"opaque",2880 .@"opaque",
2881 .var_args_param,
2823 => unreachable,2882 => unreachable,
2824 };2883 };
2825 }2884 }
...@@ -2902,6 +2961,7 @@ pub const Type = extern union {...@@ -2902,6 +2961,7 @@ pub const Type = extern union {
2902 .@"struct",2961 .@"struct",
2903 .@"union",2962 .@"union",
2904 .@"opaque",2963 .@"opaque",
2964 .var_args_param,
2905 => false,2965 => false,
2906 };2966 };
2907 }2967 }
...@@ -2962,6 +3022,7 @@ pub const Type = extern union {...@@ -2962,6 +3022,7 @@ pub const Type = extern union {
2962 .error_set,3022 .error_set,
2963 .error_set_single,3023 .error_set_single,
2964 .@"opaque",3024 .@"opaque",
3025 .var_args_param,
2965 => return null,3026 => return null,
29663027
2967 .@"enum" => @panic("TODO onePossibleValue enum"),3028 .@"enum" => @panic("TODO onePossibleValue enum"),
...@@ -3079,6 +3140,7 @@ pub const Type = extern union {...@@ -3079,6 +3140,7 @@ pub const Type = extern union {
3079 .@"struct",3140 .@"struct",
3080 .@"union",3141 .@"union",
3081 .@"opaque",3142 .@"opaque",
3143 .var_args_param,
3082 => return false,3144 => return false,
30833145
3084 .c_const_pointer,3146 .c_const_pointer,
...@@ -3168,6 +3230,7 @@ pub const Type = extern union {...@@ -3168,6 +3230,7 @@ pub const Type = extern union {
3168 .pointer,3230 .pointer,
3169 .inferred_alloc_const,3231 .inferred_alloc_const,
3170 .inferred_alloc_mut,3232 .inferred_alloc_mut,
3233 .var_args_param,
3171 => unreachable,3234 => unreachable,
31723235
3173 .empty_struct => self.castTag(.empty_struct).?.data,3236 .empty_struct => self.castTag(.empty_struct).?.data,
...@@ -3285,6 +3348,9 @@ pub const Type = extern union {...@@ -3285,6 +3348,9 @@ pub const Type = extern union {
3285 anyerror_void_error_union,3348 anyerror_void_error_union,
3286 @"anyframe",3349 @"anyframe",
3287 const_slice_u8,3350 const_slice_u8,
3351 /// This is a special type for variadic parameters of a function call.
3352 /// Casts to it will validate that the type can be passed to a c calling convetion function.
3353 var_args_param,
3288 /// This is a special value that tracks a set of types that have been stored3354 /// This is a special value that tracks a set of types that have been stored
3289 /// to an inferred allocation. It does not support most of the normal type queries.3355 /// to an inferred allocation. It does not support most of the normal type queries.
3290 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.3356 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
...@@ -3373,6 +3439,7 @@ pub const Type = extern union {...@@ -3373,6 +3439,7 @@ pub const Type = extern union {
3373 .const_slice_u8,3439 .const_slice_u8,
3374 .inferred_alloc_const,3440 .inferred_alloc_const,
3375 .inferred_alloc_mut,3441 .inferred_alloc_mut,
3442 .var_args_param,
3376 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),3443 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
33773444
3378 .array_u8,3445 .array_u8,
...@@ -3479,6 +3546,7 @@ pub const Type = extern union {...@@ -3479,6 +3546,7 @@ pub const Type = extern union {
3479 param_types: []Type,3546 param_types: []Type,
3480 return_type: Type,3547 return_type: Type,
3481 cc: std.builtin.CallingConvention,3548 cc: std.builtin.CallingConvention,
3549 is_var_args: bool,
3482 },3550 },
3483 };3551 };
34843552
src/zig_clang.cpp+5
...@@ -2822,6 +2822,11 @@ const struct ZigClangExpr *ZigClangCompoundAssignOperator_getRHS(const struct Zi...@@ -2822,6 +2822,11 @@ const struct ZigClangExpr *ZigClangCompoundAssignOperator_getRHS(const struct Zi
2822 return reinterpret_cast<const struct ZigClangExpr *>(casted->getRHS());2822 return reinterpret_cast<const struct ZigClangExpr *>(casted->getRHS());
2823}2823}
28242824
2825const struct ZigClangExpr *ZigClangCompoundLiteralExpr_getInitializer(const ZigClangCompoundLiteralExpr *self) {
2826 auto casted = reinterpret_cast<const clang::CompoundLiteralExpr *>(self);
2827 return reinterpret_cast<const ZigClangExpr *>(casted->getInitializer());
2828}
2829
2825enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *self) {2830enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *self) {
2826 auto casted = reinterpret_cast<const clang::UnaryOperator *>(self);2831 auto casted = reinterpret_cast<const clang::UnaryOperator *>(self);
2827 return (ZigClangUO)casted->getOpcode();2832 return (ZigClangUO)casted->getOpcode();
src/zig_clang.h+2
...@@ -1224,6 +1224,8 @@ ZIG_EXTERN_C enum ZigClangBO ZigClangCompoundAssignOperator_getOpcode(const stru...@@ -1224,6 +1224,8 @@ ZIG_EXTERN_C enum ZigClangBO ZigClangCompoundAssignOperator_getOpcode(const stru
1224ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getLHS(const struct ZigClangCompoundAssignOperator *);1224ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getLHS(const struct ZigClangCompoundAssignOperator *);
1225ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getRHS(const struct ZigClangCompoundAssignOperator *);1225ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getRHS(const struct ZigClangCompoundAssignOperator *);
12261226
1227ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundLiteralExpr_getInitializer(const struct ZigClangCompoundLiteralExpr *);
1228
1227ZIG_EXTERN_C enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *);1229ZIG_EXTERN_C enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *);
1228ZIG_EXTERN_C struct ZigClangQualType ZigClangUnaryOperator_getType(const struct ZigClangUnaryOperator *);1230ZIG_EXTERN_C struct ZigClangQualType ZigClangUnaryOperator_getType(const struct ZigClangUnaryOperator *);
1229ZIG_EXTERN_C const struct ZigClangExpr *ZigClangUnaryOperator_getSubExpr(const struct ZigClangUnaryOperator *);1231ZIG_EXTERN_C const struct ZigClangExpr *ZigClangUnaryOperator_getSubExpr(const struct ZigClangUnaryOperator *);
src/zir.zig+35-2
...@@ -61,6 +61,8 @@ pub const Inst = struct {...@@ -61,6 +61,8 @@ pub const Inst = struct {
61 as,61 as,
62 /// Inline assembly.62 /// Inline assembly.
63 @"asm",63 @"asm",
64 /// Await an async function.
65 @"await",
64 /// Bitwise AND. `&`66 /// Bitwise AND. `&`
65 bit_and,67 bit_and,
66 /// TODO delete this instruction, it has no purpose.68 /// TODO delete this instruction, it has no purpose.
...@@ -176,8 +178,12 @@ pub const Inst = struct {...@@ -176,8 +178,12 @@ pub const Inst = struct {
176 @"fn",178 @"fn",
177 /// Returns a function type, assuming unspecified calling convention.179 /// Returns a function type, assuming unspecified calling convention.
178 fn_type,180 fn_type,
181 /// Same as `fn_type` but the function is variadic.
182 fn_type_var_args,
179 /// Returns a function type, with a calling convention instruction operand.183 /// Returns a function type, with a calling convention instruction operand.
180 fn_type_cc,184 fn_type_cc,
185 /// Same as `fn_type_cc` but the function is variadic.
186 fn_type_cc_var_args,
181 /// @import(operand)187 /// @import(operand)
182 import,188 import,
183 /// Integer literal.189 /// Integer literal.
...@@ -212,6 +218,8 @@ pub const Inst = struct {...@@ -212,6 +218,8 @@ pub const Inst = struct {
212 mul,218 mul,
213 /// Twos complement wrapping integer multiplication.219 /// Twos complement wrapping integer multiplication.
214 mulwrap,220 mulwrap,
221 /// An await inside a nosuspend scope.
222 nosuspend_await,
215 /// Given a reference to a function and a parameter index, returns the223 /// Given a reference to a function and a parameter index, returns the
216 /// type of the parameter. TODO what happens when the parameter is `anytype`?224 /// type of the parameter. TODO what happens when the parameter is `anytype`?
217 param_type,225 param_type,
...@@ -226,6 +234,8 @@ pub const Inst = struct {...@@ -226,6 +234,8 @@ pub const Inst = struct {
226 /// the memory location is in the stack frame, local to the scope containing the234 /// the memory location is in the stack frame, local to the scope containing the
227 /// instruction.235 /// instruction.
228 ref,236 ref,
237 /// Resume an async function.
238 @"resume",
229 /// Obtains a pointer to the return value.239 /// Obtains a pointer to the return value.
230 ret_ptr,240 ret_ptr,
231 /// Obtains the return type of the in-scope function.241 /// Obtains the return type of the in-scope function.
...@@ -348,6 +358,11 @@ pub const Inst = struct {...@@ -348,6 +358,11 @@ pub const Inst = struct {
348 enum_type,358 enum_type,
349 /// Does nothing; returns a void value.359 /// Does nothing; returns a void value.
350 void_value,360 void_value,
361 /// Suspend an async function.
362 @"suspend",
363 /// Suspend an async function.
364 /// Same as .suspend but with a block.
365 suspend_block,
351 /// A switch expression.366 /// A switch expression.
352 switchbr,367 switchbr,
353 /// Same as `switchbr` but the target is a pointer to the value being switched on.368 /// Same as `switchbr` but the target is a pointer to the value being switched on.
...@@ -369,6 +384,7 @@ pub const Inst = struct {...@@ -369,6 +384,7 @@ pub const Inst = struct {
369 .unreachable_unsafe,384 .unreachable_unsafe,
370 .unreachable_safe,385 .unreachable_safe,
371 .void_value,386 .void_value,
387 .@"suspend",
372 => NoOp,388 => NoOp,
373389
374 .alloc,390 .alloc,
...@@ -417,6 +433,9 @@ pub const Inst = struct {...@@ -417,6 +433,9 @@ pub const Inst = struct {
417 .import,433 .import,
418 .set_eval_branch_quota,434 .set_eval_branch_quota,
419 .indexable_ptr_len,435 .indexable_ptr_len,
436 .@"resume",
437 .@"await",
438 .nosuspend_await,
420 => UnOp,439 => UnOp,
421440
422 .add,441 .add,
...@@ -461,6 +480,7 @@ pub const Inst = struct {...@@ -461,6 +480,7 @@ pub const Inst = struct {
461 .block_flat,480 .block_flat,
462 .block_comptime,481 .block_comptime,
463 .block_comptime_flat,482 .block_comptime_flat,
483 .suspend_block,
464 => Block,484 => Block,
465485
466 .switchbr, .switchbr_ref => SwitchBr,486 .switchbr, .switchbr_ref => SwitchBr,
...@@ -486,8 +506,8 @@ pub const Inst = struct {...@@ -486,8 +506,8 @@ pub const Inst = struct {
486 .@"export" => Export,506 .@"export" => Export,
487 .param_type => ParamType,507 .param_type => ParamType,
488 .primitive => Primitive,508 .primitive => Primitive,
489 .fn_type => FnType,509 .fn_type, .fn_type_var_args => FnType,
490 .fn_type_cc => FnTypeCc,510 .fn_type_cc, .fn_type_cc_var_args => FnTypeCc,
491 .elem_ptr, .elem_val => Elem,511 .elem_ptr, .elem_val => Elem,
492 .condbr => CondBr,512 .condbr => CondBr,
493 .ptr_type => PtrType,513 .ptr_type => PtrType,
...@@ -563,7 +583,9 @@ pub const Inst = struct {...@@ -563,7 +583,9 @@ pub const Inst = struct {
563 .field_val_named,583 .field_val_named,
564 .@"fn",584 .@"fn",
565 .fn_type,585 .fn_type,
586 .fn_type_var_args,
566 .fn_type_cc,587 .fn_type_cc,
588 .fn_type_cc_var_args,
567 .int,589 .int,
568 .intcast,590 .intcast,
569 .int_type,591 .int_type,
...@@ -633,6 +655,9 @@ pub const Inst = struct {...@@ -633,6 +655,9 @@ pub const Inst = struct {
633 .struct_type,655 .struct_type,
634 .void_value,656 .void_value,
635 .switch_range,657 .switch_range,
658 .@"resume",
659 .@"await",
660 .nosuspend_await,
636 => false,661 => false,
637662
638 .@"break",663 .@"break",
...@@ -649,6 +674,8 @@ pub const Inst = struct {...@@ -649,6 +674,8 @@ pub const Inst = struct {
649 .container_field,674 .container_field,
650 .switchbr,675 .switchbr,
651 .switchbr_ref,676 .switchbr_ref,
677 .@"suspend",
678 .suspend_block,
652 => true,679 => true,
653 };680 };
654 }681 }
...@@ -1653,8 +1680,11 @@ const DumpTzir = struct {...@@ -1653,8 +1680,11 @@ const DumpTzir = struct {
1653 },1680 },
16541681
1655 .add,1682 .add,
1683 .addwrap,
1656 .sub,1684 .sub,
1685 .subwrap,
1657 .mul,1686 .mul,
1687 .mulwrap,
1658 .cmp_lt,1688 .cmp_lt,
1659 .cmp_lte,1689 .cmp_lte,
1660 .cmp_eq,1690 .cmp_eq,
...@@ -1776,8 +1806,11 @@ const DumpTzir = struct {...@@ -1776,8 +1806,11 @@ const DumpTzir = struct {
1776 },1806 },
17771807
1778 .add,1808 .add,
1809 .addwrap,
1779 .sub,1810 .sub,
1811 .subwrap,
1780 .mul,1812 .mul,
1813 .mulwrap,
1781 .cmp_lt,1814 .cmp_lt,
1782 .cmp_lte,1815 .cmp_lte,
1783 .cmp_eq,1816 .cmp_eq,
src/zir_sema.zig+50-22
...@@ -91,8 +91,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -91,8 +91,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
91 .@"fn" => return zirFn(mod, scope, old_inst.castTag(.@"fn").?),91 .@"fn" => return zirFn(mod, scope, old_inst.castTag(.@"fn").?),
92 .@"export" => return zirExport(mod, scope, old_inst.castTag(.@"export").?),92 .@"export" => return zirExport(mod, scope, old_inst.castTag(.@"export").?),
93 .primitive => return zirPrimitive(mod, scope, old_inst.castTag(.primitive).?),93 .primitive => return zirPrimitive(mod, scope, old_inst.castTag(.primitive).?),
94 .fn_type => return zirFnType(mod, scope, old_inst.castTag(.fn_type).?),94 .fn_type => return zirFnType(mod, scope, old_inst.castTag(.fn_type).?, false),
95 .fn_type_cc => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc).?),95 .fn_type_cc => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc).?, false),
96 .fn_type_var_args => return zirFnType(mod, scope, old_inst.castTag(.fn_type_var_args).?, true),
97 .fn_type_cc_var_args => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc_var_args).?, true),
96 .intcast => return zirIntcast(mod, scope, old_inst.castTag(.intcast).?),98 .intcast => return zirIntcast(mod, scope, old_inst.castTag(.intcast).?),
97 .bitcast => return zirBitcast(mod, scope, old_inst.castTag(.bitcast).?),99 .bitcast => return zirBitcast(mod, scope, old_inst.castTag(.bitcast).?),
98 .floatcast => return zirFloatcast(mod, scope, old_inst.castTag(.floatcast).?),100 .floatcast => return zirFloatcast(mod, scope, old_inst.castTag(.floatcast).?),
...@@ -160,6 +162,11 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -160,6 +162,11 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
160 .switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false),162 .switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false),
161 .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true),163 .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true),
162 .switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),164 .switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),
165 .@"await" => return zirAwait(mod, scope, old_inst.castTag(.@"await").?),
166 .nosuspend_await => return zirAwait(mod, scope, old_inst.castTag(.nosuspend_await).?),
167 .@"resume" => return zirResume(mod, scope, old_inst.castTag(.@"resume").?),
168 .@"suspend" => return zirSuspend(mod, scope, old_inst.castTag(.@"suspend").?),
169 .suspend_block => return zirSuspendBlock(mod, scope, old_inst.castTag(.suspend_block).?),
163170
164 .container_field_named,171 .container_field_named,
165 .container_field_typed,172 .container_field_typed,
...@@ -517,9 +524,11 @@ fn zirParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType) InnerErr...@@ -517,9 +524,11 @@ fn zirParamType(mod: *Module, scope: *Scope, inst: *zir.Inst.ParamType) InnerErr
517 },524 },
518 };525 };
519526
520 // TODO support C-style var args
521 const param_count = fn_ty.fnParamLen();527 const param_count = fn_ty.fnParamLen();
522 if (arg_index >= param_count) {528 if (arg_index >= param_count) {
529 if (fn_ty.fnIsVarArgs()) {
530 return mod.constType(scope, inst.base.src, Type.initTag(.var_args_param));
531 }
523 return mod.fail(scope, inst.base.src, "arg index {d} out of bounds; '{}' has {d} argument(s)", .{532 return mod.fail(scope, inst.base.src, "arg index {d} out of bounds; '{}' has {d} argument(s)", .{
524 arg_index,533 arg_index,
525 fn_ty,534 fn_ty,
...@@ -941,6 +950,7 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {...@@ -941,6 +950,7 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
941 const call_params_len = inst.positionals.args.len;950 const call_params_len = inst.positionals.args.len;
942 const fn_params_len = func.ty.fnParamLen();951 const fn_params_len = func.ty.fnParamLen();
943 if (func.ty.fnIsVarArgs()) {952 if (func.ty.fnIsVarArgs()) {
953 assert(cc == .C);
944 if (call_params_len < fn_params_len) {954 if (call_params_len < fn_params_len) {
945 // TODO add error note: declared here955 // TODO add error note: declared here
946 return mod.fail(956 return mod.fail(
...@@ -950,7 +960,6 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {...@@ -950,7 +960,6 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
950 .{ fn_params_len, call_params_len },960 .{ fn_params_len, call_params_len },
951 );961 );
952 }962 }
953 return mod.fail(scope, inst.base.src, "TODO implement support for calling var args functions", .{});
954 } else if (fn_params_len != call_params_len) {963 } else if (fn_params_len != call_params_len) {
955 // TODO add error note: declared here964 // TODO add error note: declared here
956 return mod.fail(965 return mod.fail(
...@@ -969,15 +978,10 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {...@@ -969,15 +978,10 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
969 }978 }
970979
971 // TODO handle function calls of generic functions980 // TODO handle function calls of generic functions
972981 const casted_args = try scope.arena().alloc(*Inst, call_params_len);
973 const fn_param_types = try mod.gpa.alloc(Type, fn_params_len);
974 defer mod.gpa.free(fn_param_types);
975 func.ty.fnParamTypes(fn_param_types);
976
977 const casted_args = try scope.arena().alloc(*Inst, fn_params_len);
978 for (inst.positionals.args) |src_arg, i| {982 for (inst.positionals.args) |src_arg, i| {
979 const uncasted_arg = try resolveInst(mod, scope, src_arg);983 // the args are already casted to the result of a param type instruction.
980 casted_args[i] = try mod.coerce(scope, fn_param_types[i], uncasted_arg);984 casted_args[i] = try resolveInst(mod, scope, src_arg);
981 }985 }
982986
983 const ret_type = func.ty.fnReturnType();987 const ret_type = func.ty.fnReturnType();
...@@ -1080,6 +1084,22 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {...@@ -1080,6 +1084,22 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {
1080 });1084 });
1081}1085}
10821086
1087fn zirAwait(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1088 return mod.fail(scope, inst.base.src, "TODO implement await", .{});
1089}
1090
1091fn zirResume(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1092 return mod.fail(scope, inst.base.src, "TODO implement resume", .{});
1093}
1094
1095fn zirSuspend(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
1096 return mod.fail(scope, inst.base.src, "TODO implement suspend", .{});
1097}
1098
1099fn zirSuspendBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
1100 return mod.fail(scope, inst.base.src, "TODO implement suspend", .{});
1101}
1102
1083fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {1103fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {
1084 const tracy = trace(@src());1104 const tracy = trace(@src());
1085 defer tracy.end();1105 defer tracy.end();
...@@ -1482,7 +1502,7 @@ fn zirEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp)...@@ -1482,7 +1502,7 @@ fn zirEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp)
1482 return mod.constVoid(scope, unwrap.base.src);1502 return mod.constVoid(scope, unwrap.base.src);
1483}1503}
14841504
1485fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {1505fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType, var_args: bool) InnerError!*Inst {
1486 const tracy = trace(@src());1506 const tracy = trace(@src());
1487 defer tracy.end();1507 defer tracy.end();
14881508
...@@ -1493,10 +1513,11 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*...@@ -1493,10 +1513,11 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*
1493 fntype.positionals.param_types,1513 fntype.positionals.param_types,
1494 fntype.positionals.return_type,1514 fntype.positionals.return_type,
1495 .Unspecified,1515 .Unspecified,
1516 var_args,
1496 );1517 );
1497}1518}
14981519
1499fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerError!*Inst {1520fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc, var_args: bool) InnerError!*Inst {
1500 const tracy = trace(@src());1521 const tracy = trace(@src());
1501 defer tracy.end();1522 defer tracy.end();
15021523
...@@ -1513,6 +1534,7 @@ fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerErr...@@ -1513,6 +1534,7 @@ fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerErr
1513 fntype.positionals.param_types,1534 fntype.positionals.param_types,
1514 fntype.positionals.return_type,1535 fntype.positionals.return_type,
1515 cc,1536 cc,
1537 var_args,
1516 );1538 );
1517}1539}
15181540
...@@ -1523,11 +1545,12 @@ fn fnTypeCommon(...@@ -1523,11 +1545,12 @@ fn fnTypeCommon(
1523 zir_param_types: []*zir.Inst,1545 zir_param_types: []*zir.Inst,
1524 zir_return_type: *zir.Inst,1546 zir_return_type: *zir.Inst,
1525 cc: std.builtin.CallingConvention,1547 cc: std.builtin.CallingConvention,
1548 var_args: bool,
1526) InnerError!*Inst {1549) InnerError!*Inst {
1527 const return_type = try resolveType(mod, scope, zir_return_type);1550 const return_type = try resolveType(mod, scope, zir_return_type);
15281551
1529 // Hot path for some common function types.1552 // Hot path for some common function types.
1530 if (zir_param_types.len == 0) {1553 if (zir_param_types.len == 0 and !var_args) {
1531 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {1554 if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
1532 return mod.constType(scope, zir_inst.src, Type.initTag(.fn_noreturn_no_args));1555 return mod.constType(scope, zir_inst.src, Type.initTag(.fn_noreturn_no_args));
1533 }1556 }
...@@ -1560,6 +1583,7 @@ fn fnTypeCommon(...@@ -1560,6 +1583,7 @@ fn fnTypeCommon(
1560 .param_types = param_types,1583 .param_types = param_types,
1561 .return_type = return_type,1584 .return_type = return_type,
1562 .cc = cc,1585 .cc = cc,
1586 .is_var_args = var_args,
1563 });1587 });
1564 return mod.constType(scope, zir_inst.src, fn_ty);1588 return mod.constType(scope, zir_inst.src, fn_ty);
1565}1589}
...@@ -2046,7 +2070,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In...@@ -2046,7 +2070,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In
2046 rhs.ty.arrayLen(),2070 rhs.ty.arrayLen(),
2047 });2071 });
2048 }2072 }
2049 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBitwise", .{});2073 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in zirBitwise", .{});
2050 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {2074 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
2051 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{2075 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
2052 lhs.ty,2076 lhs.ty,
...@@ -2127,7 +2151,7 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!...@@ -2127,7 +2151,7 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!
2127 rhs.ty.arrayLen(),2151 rhs.ty.arrayLen(),
2128 });2152 });
2129 }2153 }
2130 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBinOp", .{});2154 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in zirBinOp", .{});
2131 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {2155 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
2132 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{2156 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
2133 lhs.ty,2157 lhs.ty,
...@@ -2155,10 +2179,13 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!...@@ -2155,10 +2179,13 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!
2155 }2179 }
21562180
2157 const b = try mod.requireRuntimeBlock(scope, inst.base.src);2181 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
2158 const ir_tag = switch (inst.base.tag) {2182 const ir_tag: Inst.Tag = switch (inst.base.tag) {
2159 .add => Inst.Tag.add,2183 .add => .add,
2160 .sub => Inst.Tag.sub,2184 .addwrap => .addwrap,
2161 .mul => Inst.Tag.mul,2185 .sub => .sub,
2186 .subwrap => .subwrap,
2187 .mul => .mul,
2188 .mulwrap => .mulwrap,
2162 else => return mod.fail(scope, inst.base.src, "TODO implement arithmetic for operand '{s}''", .{@tagName(inst.base.tag)}),2189 else => return mod.fail(scope, inst.base.src, "TODO implement arithmetic for operand '{s}''", .{@tagName(inst.base.tag)}),
2163 };2190 };
21642191
...@@ -2302,7 +2329,8 @@ fn zirCmp(...@@ -2302,7 +2329,8 @@ fn zirCmp(
2302 return mod.constBool(scope, inst.base.src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq));2329 return mod.constBool(scope, inst.base.src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq));
2303 }2330 }
2304 }2331 }
2305 return mod.fail(scope, inst.base.src, "TODO implement equality comparison between runtime errors", .{});2332 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
2333 return mod.addBinOp(b, inst.base.src, Type.initTag(.bool), if (op == .eq) .cmp_eq else .cmp_neq, lhs, rhs);
2306 } else if (lhs.ty.isNumeric() and rhs.ty.isNumeric()) {2334 } else if (lhs.ty.isNumeric() and rhs.ty.isNumeric()) {
2307 // This operation allows any combination of integer and float types, regardless of the2335 // This operation allows any combination of integer and float types, regardless of the
2308 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for2336 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
test/run_translated_c.zig+56
...@@ -1131,4 +1131,60 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1131,4 +1131,60 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1131 \\ return 0;1131 \\ return 0;
1132 \\}1132 \\}
1133 , "");1133 , "");
1134
1135 cases.add("pointer arithmetic with signed operand",
1136 \\#include <stdlib.h>
1137 \\int main() {
1138 \\ int array[10];
1139 \\ int *x = &array[5];
1140 \\ int *y;
1141 \\ int idx = 0;
1142 \\ y = x + ++idx;
1143 \\ if (y != x + 1 || y != &array[6]) abort();
1144 \\ y = idx + x;
1145 \\ if (y != x + 1 || y != &array[6]) abort();
1146 \\ y = x - idx;
1147 \\ if (y != x - 1 || y != &array[4]) abort();
1148 \\
1149 \\ idx = 0;
1150 \\ y = --idx + x;
1151 \\ if (y != x - 1 || y != &array[4]) abort();
1152 \\ y = idx + x;
1153 \\ if (y != x - 1 || y != &array[4]) abort();
1154 \\ y = x - idx;
1155 \\ if (y != x + 1 || y != &array[6]) abort();
1156 \\
1157 \\ idx = 1;
1158 \\ x += idx;
1159 \\ if (x != &array[6]) abort();
1160 \\ x -= idx;
1161 \\ if (x != &array[5]) abort();
1162 \\ y = (x += idx);
1163 \\ if (y != x || y != &array[6]) abort();
1164 \\ y = (x -= idx);
1165 \\ if (y != x || y != &array[5]) abort();
1166 \\
1167 \\ if (array + idx != &array[1] || array + 1 != &array[1]) abort();
1168 \\ idx = -1;
1169 \\ if (array - idx != &array[1]) abort();
1170 \\
1171 \\ return 0;
1172 \\}
1173 , "");
1174
1175 cases.add("Compound literals",
1176 \\#include <stdlib.h>
1177 \\struct Foo {
1178 \\ int a;
1179 \\ char b[2];
1180 \\ float c;
1181 \\};
1182 \\int main() {
1183 \\ struct Foo foo;
1184 \\ int x = 1, y = 2;
1185 \\ foo = (struct Foo) {x + y, {'a', 'b'}, 42.0f};
1186 \\ if (foo.a != x + y || foo.b[0] != 'a' || foo.b[1] != 'b' || foo.c != 42.0f) abort();
1187 \\ return 0;
1188 \\}
1189 , "");
1134}1190}
test/stage2/cbe.zig+70
...@@ -41,6 +41,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -41,6 +41,19 @@ pub fn addCases(ctx: *TestContext) !void {
41 , "yo!" ++ std.cstr.line_sep);41 , "yo!" ++ std.cstr.line_sep);
42 }42 }
4343
44 {
45 var case = ctx.exeFromCompiledC("var args", .{});
46
47 case.addCompareOutput(
48 \\extern fn printf(format: [*:0]const u8, ...) c_int;
49 \\
50 \\export fn main() c_int {
51 \\ _ = printf("Hello, %s!\n", "world");
52 \\ return 0;
53 \\}
54 , "Hello, world!\n");
55 }
56
44 {57 {
45 var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64);58 var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64);
4659
...@@ -231,6 +244,63 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -231,6 +244,63 @@ pub fn addCases(ctx: *TestContext) !void {
231 \\}244 \\}
232 , "");245 , "");
233 }246 }
247 //{
248 // var case = ctx.exeFromCompiledC("optionals", .{});
249
250 // // Simple while loop
251 // case.addCompareOutput(
252 // \\export fn main() c_int {
253 // \\ var count: c_int = 0;
254 // \\ var opt_ptr: ?*c_int = &count;
255 // \\ while (opt_ptr) |_| : (count += 1) {
256 // \\ if (count == 4) opt_ptr = null;
257 // \\ }
258 // \\ return count - 5;
259 // \\}
260 // , "");
261
262 // // Same with non pointer optionals
263 // case.addCompareOutput(
264 // \\export fn main() c_int {
265 // \\ var count: c_int = 0;
266 // \\ var opt_ptr: ?c_int = count;
267 // \\ while (opt_ptr) |_| : (count += 1) {
268 // \\ if (count == 4) opt_ptr = null;
269 // \\ }
270 // \\ return count - 5;
271 // \\}
272 // , "");
273 //}
274 {
275 var case = ctx.exeFromCompiledC("errors", .{});
276 case.addCompareOutput(
277 \\export fn main() c_int {
278 \\ var e1 = error.Foo;
279 \\ var e2 = error.Bar;
280 \\ assert(e1 != e2);
281 \\ assert(e1 == error.Foo);
282 \\ assert(e2 == error.Bar);
283 \\ return 0;
284 \\}
285 \\fn assert(b: bool) void {
286 \\ if (!b) unreachable;
287 \\}
288 , "");
289 case.addCompareOutput(
290 \\export fn main() c_int {
291 \\ var e: anyerror!c_int = 0;
292 \\ const i = e catch 69;
293 \\ return i;
294 \\}
295 , "");
296 case.addCompareOutput(
297 \\export fn main() c_int {
298 \\ var e: anyerror!c_int = error.Foo;
299 \\ const i = e catch 69;
300 \\ return 69 - i;
301 \\}
302 , "");
303 }
234 ctx.c("empty start function", linux_x64,304 ctx.c("empty start function", linux_x64,
235 \\export fn _start() noreturn {305 \\export fn _start() noreturn {
236 \\ unreachable;306 \\ unreachable;
test/translate_c.zig+65-39
...@@ -232,12 +232,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -232,12 +232,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
232 \\ | (*((unsigned char *)(p) + 1) << 8) \232 \\ | (*((unsigned char *)(p) + 1) << 8) \
233 \\ | (*((unsigned char *)(p) + 2) << 16))233 \\ | (*((unsigned char *)(p) + 2) << 16))
234 , &[_][]const u8{234 , &[_][]const u8{
235 \\pub const FOO = (foo + 2).*;235 \\pub const FOO = (foo + @as(c_int, 2)).*;
236 ,236 ,
237 \\pub const VALUE = ((((1 + (2 * 3)) + (4 * 5)) + 6) << 7) | @boolToInt(8 == 9);237 \\pub const VALUE = ((((@as(c_int, 1) + (@as(c_int, 2) * @as(c_int, 3))) + (@as(c_int, 4) * @as(c_int, 5))) + @as(c_int, 6)) << @as(c_int, 7)) | @boolToInt(@as(c_int, 8) == @as(c_int, 9));
238 ,238 ,
239 \\pub fn _AL_READ3BYTES(p: anytype) callconv(.Inline) @TypeOf((@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + 1).* << 8)) | ((@import("std").meta.cast([*c]u8, p) + 2).* << 16)) {239 \\pub fn _AL_READ3BYTES(p: anytype) callconv(.Inline) @TypeOf((@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16))) {
240 \\ return (@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + 1).* << 8)) | ((@import("std").meta.cast([*c]u8, p) + 2).* << 16);240 \\ return (@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16));
241 \\}241 \\}
242 });242 });
243243
...@@ -312,14 +312,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -312,14 +312,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
312 \\ return type_1;312 \\ return type_1;
313 \\}313 \\}
314 ,314 ,
315 \\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ 200, 200, 200, 255 });315 \\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ @as(c_int, 200), @as(c_int, 200), @as(c_int, 200), @as(c_int, 255) });
316 ,316 ,
317 \\pub const struct_boom_t = extern struct {317 \\pub const struct_boom_t = extern struct {
318 \\ i1: c_int,318 \\ i1: c_int,
319 \\};319 \\};
320 \\pub const boom_t = struct_boom_t;320 \\pub const boom_t = struct_boom_t;
321 ,321 ,
322 \\pub const FOO = @import("std").mem.zeroInit(boom_t, .{1});322 \\pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)});
323 });323 });
324324
325 cases.add("complex switch",325 cases.add("complex switch",
...@@ -343,8 +343,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -343,8 +343,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
343 cases.add("correct semicolon after infixop",343 cases.add("correct semicolon after infixop",
344 \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)344 \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)
345 , &[_][]const u8{345 , &[_][]const u8{
346 \\pub fn __ferror_unlocked_body(_fp: anytype) callconv(.Inline) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != 0) {346 \\pub fn __ferror_unlocked_body(_fp: anytype) callconv(.Inline) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0)) {
347 \\ return (_fp.*._flags & _IO_ERR_SEEN) != 0;347 \\ return (_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0);
348 \\}348 \\}
349 });349 });
350350
...@@ -352,11 +352,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -352,11 +352,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
352 \\#define FOO(x) ((x >= 0) + (x >= 0))352 \\#define FOO(x) ((x >= 0) + (x >= 0))
353 \\#define BAR 1 && 2 > 4353 \\#define BAR 1 && 2 > 4
354 , &[_][]const u8{354 , &[_][]const u8{
355 \\pub fn FOO(x: anytype) callconv(.Inline) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) {355 \\pub fn FOO(x: anytype) callconv(.Inline) @TypeOf(@boolToInt(x >= @as(c_int, 0)) + @boolToInt(x >= @as(c_int, 0))) {
356 \\ return @boolToInt(x >= 0) + @boolToInt(x >= 0);356 \\ return @boolToInt(x >= @as(c_int, 0)) + @boolToInt(x >= @as(c_int, 0));
357 \\}357 \\}
358 ,358 ,
359 \\pub const BAR = (1 != 0) and (2 > 4);359 \\pub const BAR = (@as(c_int, 1) != 0) and (@as(c_int, 2) > @as(c_int, 4));
360 });360 });
361361
362 cases.add("struct with aligned fields",362 cases.add("struct with aligned fields",
...@@ -401,15 +401,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -401,15 +401,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
401 \\ break :blk bar;401 \\ break :blk bar;
402 \\};402 \\};
403 ,403 ,
404 \\pub fn bar(x: anytype) callconv(.Inline) @TypeOf(baz(1, 2)) {404 \\pub fn bar(x: anytype) callconv(.Inline) @TypeOf(baz(@as(c_int, 1), @as(c_int, 2))) {
405 \\ return blk: {405 \\ return blk: {
406 \\ _ = &x;406 \\ _ = &x;
407 \\ _ = 3;407 \\ _ = @as(c_int, 3);
408 \\ _ = 4 == 4;408 \\ _ = @as(c_int, 4) == @as(c_int, 4);
409 \\ _ = 5 * 6;409 \\ _ = @as(c_int, 5) * @as(c_int, 6);
410 \\ _ = baz(1, 2);410 \\ _ = baz(@as(c_int, 1), @as(c_int, 2));
411 \\ _ = 2 % 2;411 \\ _ = @as(c_int, 2) % @as(c_int, 2);
412 \\ break :blk baz(1, 2);412 \\ break :blk baz(@as(c_int, 1), @as(c_int, 2));
413 \\ };413 \\ };
414 \\}414 \\}
415 });415 });
...@@ -418,9 +418,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -418,9 +418,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
418 \\#define foo 1418 \\#define foo 1
419 \\#define inline 2419 \\#define inline 2
420 , &[_][]const u8{420 , &[_][]const u8{
421 \\pub const foo = 1;421 \\pub const foo = @as(c_int, 1);
422 ,422 ,
423 \\pub const @"inline" = 2;423 \\pub const @"inline" = @as(c_int, 2);
424 });424 });
425425
426 cases.add("macro line continuation",426 cases.add("macro line continuation",
...@@ -507,7 +507,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -507,7 +507,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
507 cases.add("#define hex literal with capital X",507 cases.add("#define hex literal with capital X",
508 \\#define VAL 0XF00D508 \\#define VAL 0XF00D
509 , &[_][]const u8{509 , &[_][]const u8{
510 \\pub const VAL = 0xF00D;510 \\pub const VAL = @import("std").meta.promoteIntLiteral(c_int, 0xF00D, .hexadecimal);
511 });511 });
512512
513 cases.add("anonymous struct & unions",513 cases.add("anonymous struct & unions",
...@@ -643,9 +643,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -643,9 +643,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
643 \\extern char my_array[16];643 \\extern char my_array[16];
644 \\__attribute__ ((aligned(128)))644 \\__attribute__ ((aligned(128)))
645 \\void my_fn(void) { }645 \\void my_fn(void) { }
646 \\void other_fn(void) {
647 \\ char ARR[16] __attribute__ ((aligned (16)));
648 \\}
646 , &[_][]const u8{649 , &[_][]const u8{
647 \\pub extern var my_array: [16]u8 align(128);650 \\pub extern var my_array: [16]u8 align(128);
648 \\pub export fn my_fn() align(128) void {}651 \\pub export fn my_fn() align(128) void {}
652 \\pub export fn other_fn() void {
653 \\ var ARR: [16]u8 align(16) = undefined;
654 \\}
649 });655 });
650656
651 cases.add("linksection() attribute",657 cases.add("linksection() attribute",
...@@ -872,7 +878,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -872,7 +878,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
872 cases.add("macro with left shift",878 cases.add("macro with left shift",
873 \\#define REDISMODULE_READ (1<<0)879 \\#define REDISMODULE_READ (1<<0)
874 , &[_][]const u8{880 , &[_][]const u8{
875 \\pub const REDISMODULE_READ = 1 << 0;881 \\pub const REDISMODULE_READ = @as(c_int, 1) << @as(c_int, 0);
876 });882 });
877883
878 cases.add("macro with right shift",884 cases.add("macro with right shift",
...@@ -881,7 +887,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -881,7 +887,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
881 , &[_][]const u8{887 , &[_][]const u8{
882 \\pub const FLASH_SIZE = @as(c_ulong, 0x200000);888 \\pub const FLASH_SIZE = @as(c_ulong, 0x200000);
883 ,889 ,
884 \\pub const FLASH_BANK_SIZE = FLASH_SIZE >> 1;890 \\pub const FLASH_BANK_SIZE = FLASH_SIZE >> @as(c_int, 1);
885 });891 });
886892
887 cases.add("double define struct",893 cases.add("double define struct",
...@@ -949,14 +955,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -949,14 +955,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
949 cases.add("#define an unsigned integer literal",955 cases.add("#define an unsigned integer literal",
950 \\#define CHANNEL_COUNT 24956 \\#define CHANNEL_COUNT 24
951 , &[_][]const u8{957 , &[_][]const u8{
952 \\pub const CHANNEL_COUNT = 24;958 \\pub const CHANNEL_COUNT = @as(c_int, 24);
953 });959 });
954960
955 cases.add("#define referencing another #define",961 cases.add("#define referencing another #define",
956 \\#define THING2 THING1962 \\#define THING2 THING1
957 \\#define THING1 1234963 \\#define THING1 1234
958 , &[_][]const u8{964 , &[_][]const u8{
959 \\pub const THING1 = 1234;965 \\pub const THING1 = @as(c_int, 1234);
960 ,966 ,
961 \\pub const THING2 = THING1;967 \\pub const THING2 = THING1;
962 });968 });
...@@ -1002,7 +1008,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1002,7 +1008,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1002 cases.add("macro with parens around negative number",1008 cases.add("macro with parens around negative number",
1003 \\#define LUA_GLOBALSINDEX (-10002)1009 \\#define LUA_GLOBALSINDEX (-10002)
1004 , &[_][]const u8{1010 , &[_][]const u8{
1005 \\pub const LUA_GLOBALSINDEX = -10002;1011 \\pub const LUA_GLOBALSINDEX = -@as(c_int, 10002);
1006 });1012 });
10071013
1008 cases.add(1014 cases.add(
...@@ -1085,8 +1091,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1085,8 +1091,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1085 \\#define foo 1 //foo1091 \\#define foo 1 //foo
1086 \\#define bar /* bar */ 21092 \\#define bar /* bar */ 2
1087 , &[_][]const u8{1093 , &[_][]const u8{
1088 "pub const foo = 1;",1094 "pub const foo = @as(c_int, 1);",
1089 "pub const bar = 2;",1095 "pub const bar = @as(c_int, 2);",
1090 });1096 });
10911097
1092 cases.add("string prefix",1098 cases.add("string prefix",
...@@ -1716,7 +1722,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1716,7 +1722,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1716 cases.add("comment after integer literal",1722 cases.add("comment after integer literal",
1717 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */1723 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
1718 , &[_][]const u8{1724 , &[_][]const u8{
1719 \\pub const SDL_INIT_VIDEO = 0x00000020;1725 \\pub const SDL_INIT_VIDEO = @as(c_int, 0x00000020);
1720 });1726 });
17211727
1722 cases.add("u integer suffix after hex literal",1728 cases.add("u integer suffix after hex literal",
...@@ -1830,8 +1836,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1830,8 +1836,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1830 , &[_][]const u8{1836 , &[_][]const u8{
1831 \\pub extern var c: c_int;1837 \\pub extern var c: c_int;
1832 ,1838 ,
1833 \\pub fn BASIC(c_1: anytype) callconv(.Inline) @TypeOf(c_1 * 2) {1839 \\pub fn BASIC(c_1: anytype) callconv(.Inline) @TypeOf(c_1 * @as(c_int, 2)) {
1834 \\ return c_1 * 2;1840 \\ return c_1 * @as(c_int, 2);
1835 \\}1841 \\}
1836 ,1842 ,
1837 \\pub fn FOO(L: anytype, b: anytype) callconv(.Inline) @TypeOf(L + b) {1843 \\pub fn FOO(L: anytype, b: anytype) callconv(.Inline) @TypeOf(L + b) {
...@@ -2475,7 +2481,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2475,7 +2481,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2475 \\ return array[@intCast(c_uint, index)];2481 \\ return array[@intCast(c_uint, index)];
2476 \\}2482 \\}
2477 ,2483 ,
2478 \\pub const ACCESS = array[2];2484 \\pub const ACCESS = array[@as(c_int, 2)];
2479 });2485 });
24802486
2481 cases.add("cast signed array index to unsigned",2487 cases.add("cast signed array index to unsigned",
...@@ -3091,7 +3097,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3091,7 +3097,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3091 ,3097 ,
3092 \\pub const BAR = @import("std").meta.cast(?*c_void, a);3098 \\pub const BAR = @import("std").meta.cast(?*c_void, a);
3093 ,3099 ,
3094 \\pub const BAZ = @import("std").meta.cast(u32, 2);3100 \\pub const BAZ = @import("std").meta.cast(u32, @as(c_int, 2));
3095 });3101 });
30963102
3097 cases.add("macro with cast to unsigned short, long, and long long",3103 cases.add("macro with cast to unsigned short, long, and long long",
...@@ -3099,9 +3105,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3099,9 +3105,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3099 \\#define CURLAUTH_BASIC ((unsigned long) 1)3105 \\#define CURLAUTH_BASIC ((unsigned long) 1)
3100 \\#define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1)3106 \\#define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1)
3101 , &[_][]const u8{3107 , &[_][]const u8{
3102 \\pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").meta.cast(c_ushort, 1);3108 \\pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").meta.cast(c_ushort, @as(c_int, 1));
3103 \\pub const CURLAUTH_BASIC = @import("std").meta.cast(c_ulong, 1);3109 \\pub const CURLAUTH_BASIC = @import("std").meta.cast(c_ulong, @as(c_int, 1));
3104 \\pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").meta.cast(c_ulonglong, 1);3110 \\pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").meta.cast(c_ulonglong, @as(c_int, 1));
3105 });3111 });
31063112
3107 cases.add("macro conditional operator",3113 cases.add("macro conditional operator",
...@@ -3196,7 +3202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3196,7 +3202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3196 \\ bar_1 = 2;3202 \\ bar_1 = 2;
3197 \\}3203 \\}
3198 ,3204 ,
3199 \\pub const bar = 4;3205 \\pub const bar = @as(c_int, 4);
3200 });3206 });
32013207
3202 cases.add("don't export inline functions",3208 cases.add("don't export inline functions",
...@@ -3325,9 +3331,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3325,9 +3331,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3325 \\#define NULL ((void*)0)3331 \\#define NULL ((void*)0)
3326 \\#define FOO ((int)0x8000)3332 \\#define FOO ((int)0x8000)
3327 , &[_][]const u8{3333 , &[_][]const u8{
3328 \\pub const NULL = @import("std").meta.cast(?*c_void, 0);3334 \\pub const NULL = @import("std").meta.cast(?*c_void, @as(c_int, 0));
3329 ,3335 ,
3330 \\pub const FOO = @import("std").meta.cast(c_int, 0x8000);3336 \\pub const FOO = @import("std").meta.cast(c_int, @import("std").meta.promoteIntLiteral(c_int, 0x8000, .hexadecimal));
3331 });3337 });
33323338
3333 if (std.Target.current.abi == .msvc) {3339 if (std.Target.current.abi == .msvc) {
...@@ -3392,4 +3398,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3392,4 +3398,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3392 \\ unnamed_0: struct_unnamed_2,3398 \\ unnamed_0: struct_unnamed_2,
3393 \\};3399 \\};
3394 });3400 });
3401
3402 cases.add("integer literal promotion",
3403 \\#define GUARANTEED_TO_FIT_1 1024
3404 \\#define GUARANTEED_TO_FIT_2 10241024L
3405 \\#define GUARANTEED_TO_FIT_3 20482048LU
3406 \\#define MAY_NEED_PROMOTION_1 10241024
3407 \\#define MAY_NEED_PROMOTION_2 307230723072L
3408 \\#define MAY_NEED_PROMOTION_3 819281928192LU
3409 \\#define MAY_NEED_PROMOTION_HEX 0x80000000
3410 \\#define MAY_NEED_PROMOTION_OCT 020000000000
3411 , &[_][]const u8{
3412 \\pub const GUARANTEED_TO_FIT_1 = @as(c_int, 1024);
3413 \\pub const GUARANTEED_TO_FIT_2 = @as(c_long, 10241024);
3414 \\pub const GUARANTEED_TO_FIT_3 = @as(c_ulong, 20482048);
3415 \\pub const MAY_NEED_PROMOTION_1 = @import("std").meta.promoteIntLiteral(c_int, 10241024, .decimal);
3416 \\pub const MAY_NEED_PROMOTION_2 = @import("std").meta.promoteIntLiteral(c_long, 307230723072, .decimal);
3417 \\pub const MAY_NEED_PROMOTION_3 = @import("std").meta.promoteIntLiteral(c_ulong, 819281928192, .decimal);
3418 \\pub const MAY_NEED_PROMOTION_HEX = @import("std").meta.promoteIntLiteral(c_int, 0x80000000, .hexadecimal);
3419 \\pub const MAY_NEED_PROMOTION_OCT = @import("std").meta.promoteIntLiteral(c_int, 0o20000000000, .octal);
3420 });
3395}3421}
tools/process_headers.zig+18-12
...@@ -270,7 +270,7 @@ pub fn main() !void {...@@ -270,7 +270,7 @@ pub fn main() !void {
270 if (std.mem.eql(u8, args[arg_i], "--help"))270 if (std.mem.eql(u8, args[arg_i], "--help"))
271 usageAndExit(args[0]);271 usageAndExit(args[0]);
272 if (arg_i + 1 >= args.len) {272 if (arg_i + 1 >= args.len) {
273 std.debug.warn("expected argument after '{}'\n", .{args[arg_i]});273 std.debug.warn("expected argument after '{s}'\n", .{args[arg_i]});
274 usageAndExit(args[0]);274 usageAndExit(args[0]);
275 }275 }
276276
...@@ -283,7 +283,7 @@ pub fn main() !void {...@@ -283,7 +283,7 @@ pub fn main() !void {
283 assert(opt_abi == null);283 assert(opt_abi == null);
284 opt_abi = args[arg_i + 1];284 opt_abi = args[arg_i + 1];
285 } else {285 } else {
286 std.debug.warn("unrecognized argument: {}\n", .{args[arg_i]});286 std.debug.warn("unrecognized argument: {s}\n", .{args[arg_i]});
287 usageAndExit(args[0]);287 usageAndExit(args[0]);
288 }288 }
289289
...@@ -297,10 +297,10 @@ pub fn main() !void {...@@ -297,10 +297,10 @@ pub fn main() !void {
297 else if (std.mem.eql(u8, abi_name, "glibc"))297 else if (std.mem.eql(u8, abi_name, "glibc"))
298 LibCVendor.glibc298 LibCVendor.glibc
299 else {299 else {
300 std.debug.warn("unrecognized C ABI: {}\n", .{abi_name});300 std.debug.warn("unrecognized C ABI: {s}\n", .{abi_name});
301 usageAndExit(args[0]);301 usageAndExit(args[0]);
302 };302 };
303 const generic_name = try std.fmt.allocPrint(allocator, "generic-{}", .{abi_name});303 const generic_name = try std.fmt.allocPrint(allocator, "generic-{s}", .{abi_name});
304304
305 // TODO compiler crashed when I wrote this the canonical way305 // TODO compiler crashed when I wrote this the canonical way
306 var libc_targets: []const LibCTarget = undefined;306 var libc_targets: []const LibCTarget = undefined;
...@@ -368,10 +368,10 @@ pub fn main() !void {...@@ -368,10 +368,10 @@ pub fn main() !void {
368 if (gop.found_existing) {368 if (gop.found_existing) {
369 max_bytes_saved += raw_bytes.len;369 max_bytes_saved += raw_bytes.len;
370 gop.entry.value.hit_count += 1;370 gop.entry.value.hit_count += 1;
371 std.debug.warn("duplicate: {} {} ({Bi:2})\n", .{371 std.debug.warn("duplicate: {s} {s} ({:2})\n", .{
372 libc_target.name,372 libc_target.name,
373 rel_path,373 rel_path,
374 raw_bytes.len,374 std.fmt.fmtIntSizeDec(raw_bytes.len),
375 });375 });
376 } else {376 } else {
377 gop.entry.value = Contents{377 gop.entry.value = Contents{
...@@ -390,16 +390,19 @@ pub fn main() !void {...@@ -390,16 +390,19 @@ pub fn main() !void {
390 };390 };
391 try target_to_hash.putNoClobber(dest_target, hash);391 try target_to_hash.putNoClobber(dest_target, hash);
392 },392 },
393 else => std.debug.warn("warning: weird file: {}\n", .{full_path}),393 else => std.debug.warn("warning: weird file: {s}\n", .{full_path}),
394 }394 }
395 }395 }
396 }396 }
397 break;397 break;
398 } else {398 } else {
399 std.debug.warn("warning: libc target not found: {}\n", .{libc_target.name});399 std.debug.warn("warning: libc target not found: {s}\n", .{libc_target.name});
400 }400 }
401 }401 }
402 std.debug.warn("summary: {Bi:2} could be reduced to {Bi:2}\n", .{ total_bytes, total_bytes - max_bytes_saved });402 std.debug.warn("summary: {:2} could be reduced to {:2}\n", .{
403 std.fmt.fmtIntSizeDec(total_bytes),
404 std.fmt.fmtIntSizeDec(total_bytes - max_bytes_saved),
405 });
403 try std.fs.cwd().makePath(out_dir);406 try std.fs.cwd().makePath(out_dir);
404407
405 var missed_opportunity_bytes: usize = 0;408 var missed_opportunity_bytes: usize = 0;
...@@ -428,7 +431,10 @@ pub fn main() !void {...@@ -428,7 +431,10 @@ pub fn main() !void {
428 if (contender.hit_count > 1) {431 if (contender.hit_count > 1) {
429 const this_missed_bytes = contender.hit_count * contender.bytes.len;432 const this_missed_bytes = contender.hit_count * contender.bytes.len;
430 missed_opportunity_bytes += this_missed_bytes;433 missed_opportunity_bytes += this_missed_bytes;
431 std.debug.warn("Missed opportunity ({Bi:2}): {}\n", .{ this_missed_bytes, path_kv.key });434 std.debug.warn("Missed opportunity ({:2}): {s}\n", .{
435 std.fmt.fmtIntSizeDec(this_missed_bytes),
436 path_kv.key,
437 });
432 } else break;438 } else break;
433 }439 }
434 }440 }
...@@ -442,7 +448,7 @@ pub fn main() !void {...@@ -442,7 +448,7 @@ pub fn main() !void {
442 .specific => |a| @tagName(a),448 .specific => |a| @tagName(a),
443 else => @tagName(dest_target.arch),449 else => @tagName(dest_target.arch),
444 };450 };
445 const out_subpath = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{451 const out_subpath = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{
446 arch_name,452 arch_name,
447 @tagName(dest_target.os),453 @tagName(dest_target.os),
448 @tagName(dest_target.abi),454 @tagName(dest_target.abi),
...@@ -455,7 +461,7 @@ pub fn main() !void {...@@ -455,7 +461,7 @@ pub fn main() !void {
455}461}
456462
457fn usageAndExit(arg0: []const u8) noreturn {463fn usageAndExit(arg0: []const u8) noreturn {
458 std.debug.warn("Usage: {} [--search-path <dir>] --out <dir> --abi <name>\n", .{arg0});464 std.debug.warn("Usage: {s} [--search-path <dir>] --out <dir> --abi <name>\n", .{arg0});
459 std.debug.warn("--search-path can be used any number of times.\n", .{});465 std.debug.warn("--search-path can be used any number of times.\n", .{});
460 std.debug.warn(" subdirectories of search paths look like, e.g. x86_64-linux-gnu\n", .{});466 std.debug.warn(" subdirectories of search paths look like, e.g. x86_64-linux-gnu\n", .{});
461 std.debug.warn("--out is a dir that will be created, and populated with the results\n", .{});467 std.debug.warn("--out is a dir that will be created, and populated with the results\n", .{});