| author | |
| committer | |
| log | 1f34c03ac14ac352ec03267ca8592dadfbd5e4bc |
| tree | ebcb851922636b7dd2b17acb72187836c86180ec |
| parent | 868253a9c94d9907fae81e5e3108c7d10a85f5c3 |
| parent | 8ebb18d9da0bfbe6a974636fd36e3391d1de253b |
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); |
| 36 | 36 | ||
| 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(); |
| 39 | 48 | ||
| ... | @@ -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 {}; |
| 52 | 61 | ||
| 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 | } |
| 56 | 65 | ||
| ... | @@ -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 | } else | 576 | } 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 comment | 793 | // 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; |
| 789 | 797 | ||
| 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 | } |
| 1004 | 1012 | ||
| 1005 | fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: anytype, zig_exe: []const u8) !void { | 1013 | fn 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; |
| 1007 | 1015 | ||
| 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_2 | 58 | #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 90000 | 60 | #define __IPHONE_OS_VERSION_MIN_REQUIRED 90000 |
| 61 | #endif | 61 | #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_1 | 68 | #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 90000 | 70 | #define __IPHONE_OS_VERSION_MIN_REQUIRED 90000 |
| 71 | #endif | 71 | #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 50000 | 78 | #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 110000 | 80 | #define __IPHONE_OS_VERSION_MIN_REQUIRED 110000 |
| 81 | #endif | 81 | #endif |
| ... | @@ -90,14 +90,14 @@ | ... | @@ -90,14 +90,14 @@ |
| 90 | #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED | 90 | #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_ALLOWED | 92 | #ifndef __MAC_OS_X_VERSION_MAX_ALLOWED |
| 93 | #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_11_0 | 93 | #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_11_1 |
| 94 | #endif | 94 | #endif |
| 95 | #endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */ | 95 | #endif /* __MAC_OS_X_VERSION_MIN_REQUIRED */ |
| 96 | 96 | ||
| 97 | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED | 97 | #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_ALLOWED | 99 | #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED |
| 100 | #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_14_2 | 100 | #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_14_3 |
| 101 | #endif | 101 | #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_0 | 103 | #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 101404 | 118 | #define MAC_OS_X_VERSION_10_14_4 101404 |
| 119 | #define MAC_OS_X_VERSION_10_15 101500 | 119 | #define MAC_OS_X_VERSION_10_15 101500 |
| 120 | #define MAC_OS_VERSION_11_0 110000 | 120 | #define MAC_OS_VERSION_11_0 110000 |
| 121 | #define MAC_OS_VERSION_11_1 110100 | ||
| 121 | 122 | ||
| 122 | /* | 123 | /* |
| 123 | * If min OS not specified, assume 10.4 for intel | 124 | * 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_ALLOWED | 147 | #ifndef MAC_OS_X_VERSION_MAX_ALLOWED |
| 147 | #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_VERSION_11_0 | 148 | #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_REQUIRED | 149 | #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_MIN_REQUIRED |
| 149 | #else | 150 | #else |
| 150 | #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_VERSION_11_0 | 151 | #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_VERSION_11_1 |
| 151 | #endif | 152 | #endif |
| 152 | #endif | 153 | #endif |
| 153 | 154 |
lib/libc/include/aarch64-macos-gnu/AvailabilityVersions.h+4| ... | @@ -58,6 +58,7 @@ | ... | @@ -58,6 +58,7 @@ |
| 58 | #define __MAC_10_15_4 101504 | 58 | #define __MAC_10_15_4 101504 |
| 59 | #define __MAC_10_16 101600 | 59 | #define __MAC_10_16 101600 |
| 60 | #define __MAC_11_0 110000 | 60 | #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 */ |
| 62 | 63 | ||
| 63 | #define __IPHONE_2_0 20000 | 64 | #define __IPHONE_2_0 20000 |
| ... | @@ -110,6 +111,7 @@ | ... | @@ -110,6 +111,7 @@ |
| 110 | #define __IPHONE_14_0 140000 | 111 | #define __IPHONE_14_0 140000 |
| 111 | #define __IPHONE_14_1 140100 | 112 | #define __IPHONE_14_1 140100 |
| 112 | #define __IPHONE_14_2 140200 | 113 | #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 */ |
| 114 | 116 | ||
| 115 | #define __TVOS_9_0 90000 | 117 | #define __TVOS_9_0 90000 |
| ... | @@ -136,6 +138,7 @@ | ... | @@ -136,6 +138,7 @@ |
| 136 | #define __TVOS_14_0 140000 | 138 | #define __TVOS_14_0 140000 |
| 137 | #define __TVOS_14_1 140100 | 139 | #define __TVOS_14_1 140100 |
| 138 | #define __TVOS_14_2 140200 | 140 | #define __TVOS_14_2 140200 |
| 141 | #define __TVOS_14_3 140300 | ||
| 139 | 142 | ||
| 140 | #define __WATCHOS_1_0 10000 | 143 | #define __WATCHOS_1_0 10000 |
| 141 | #define __WATCHOS_2_0 20000 | 144 | #define __WATCHOS_2_0 20000 |
| ... | @@ -158,6 +161,7 @@ | ... | @@ -158,6 +161,7 @@ |
| 158 | #define __WATCHOS_6_2 60200 | 161 | #define __WATCHOS_6_2 60200 |
| 159 | #define __WATCHOS_7_0 70000 | 162 | #define __WATCHOS_7_0 70000 |
| 160 | #define __WATCHOS_7_1 70100 | 163 | #define __WATCHOS_7_1 70100 |
| 164 | #define __WATCHOS_7_2 70200 | ||
| 161 | 165 | ||
| 162 | /* | 166 | /* |
| 163 | * Set up standard Mac OS X versions | 167 | * 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 | */ | ||
| 85 | int 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 | |||
| 92 | int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 93 | int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); | ||
| 94 | int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); | ||
| 95 | int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); | ||
| 96 | int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 97 | int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 98 | int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); | ||
| 99 | int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 100 | int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 101 | int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 102 | int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 103 | int 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)); | ||
| 104 | int 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 | */ | ||
| 111 | int 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 | |||
| 122 | int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); | ||
| 123 | int proc_setpcontrol(const int control); | ||
| 124 | |||
| 125 | int proc_track_dirty(pid_t pid, uint32_t flags); | ||
| 126 | int proc_set_dirty(pid_t pid, bool dirty); | ||
| 127 | int proc_get_dirty(pid_t pid, uint32_t *flags); | ||
| 128 | int proc_clear_dirty(pid_t pid, uint32_t flags); | ||
| 129 | |||
| 130 | int 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 | */ | ||
| 139 | int proc_set_no_smt(void) __API_AVAILABLE(macos(11.0)); | ||
| 140 | |||
| 141 | /* Set NO_SMT on the current thread */ | ||
| 142 | int 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 | */ | ||
| 150 | int proc_set_csm(uint32_t flags) __API_AVAILABLE(macos(11.0)); | ||
| 151 | |||
| 152 | /* Set CPU security mitigation on the current thread */ | ||
| 153 | int 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 | */ | ||
| 176 | int proc_list_uptrs(pid_t pid, uint64_t *buffer, uint32_t buffersize); | ||
| 177 | |||
| 178 | int proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz); | ||
| 179 | int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, | ||
| 180 | int buffersize); | ||
| 181 | #endif /* PRIVATE */ | ||
| 182 | |||
| 183 | int 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) |
| 89 | 89 | ||
| 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) | ||
| 90 | 94 | ||
| 91 | #else /* defined(__arm64__) */ | 95 | #else /* defined(__arm64__) */ |
| 92 | #error architecture not supported | 96 | #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 | */ | ||
| 75 | struct 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 | */ | ||
| 145 | struct 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 | */ | ||
| 157 | struct 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 | |||
| 172 | struct 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 | |||
| 251 | struct 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 | #endif | 330 | #endif |
| 331 | 331 | ||
| 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__ >= 1000 | 338 | #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) x | 339 | #define __DARWIN_ALIAS_STARTING_MAC___MAC_10_0(x) x |
| 334 | #else | 340 | #else |
| ... | @@ -531,4 +537,10 @@ | ... | @@ -531,4 +537,10 @@ |
| 531 | #define __DARWIN_ALIAS_STARTING_MAC___MAC_11_0(x) x | 537 | #define __DARWIN_ALIAS_STARTING_MAC___MAC_11_0(x) x |
| 532 | #else | 538 | #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 | #endif | 546 | #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 | */ | ||
| 75 | struct 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 | */ | ||
| 117 | struct 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 | */ | ||
| 140 | struct 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 | |||
| 60 | struct 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 | |||
| 86 | struct 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 | |||
| 127 | struct 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 | |||
| 148 | struct proc_taskallinfo { | ||
| 149 | 	struct proc_bsdinfo pbsd; | ||
| 150 | 	struct proc_taskinfo ptinfo; | ||
| 151 | }; | ||
| 152 | |||
| 153 | #define MAXTHREADNAMESIZE 64 | ||
| 154 | |||
| 155 | struct 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 | |||
| 169 | struct 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 | |||
| 225 | struct 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 | |||
| 239 | struct 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 | |||
| 258 | struct 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 | |||
| 265 | struct 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 | */ | ||
| 276 | struct 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 | |||
| 300 | struct vnode_info { | ||
| 301 | 	struct vinfo_stat vi_stat; | ||
| 302 | 	int vi_type; | ||
| 303 | 	int vi_pad; | ||
| 304 | 	fsid_t vi_fsid; | ||
| 305 | }; | ||
| 306 | |||
| 307 | struct vnode_info_path { | ||
| 308 | 	struct vnode_info vip_vi; | ||
| 309 | 	char vip_path[MAXPATHLEN]; /* tail end of it */ | ||
| 310 | }; | ||
| 311 | |||
| 312 | struct vnode_fdinfo { | ||
| 313 | 	struct proc_fileinfo pfi; | ||
| 314 | 	struct vnode_info pvi; | ||
| 315 | }; | ||
| 316 | |||
| 317 | struct vnode_fdinfowithpath { | ||
| 318 | 	struct proc_fileinfo pfi; | ||
| 319 | 	struct vnode_info_path pvip; | ||
| 320 | }; | ||
| 321 | |||
| 322 | struct proc_regionwithpathinfo { | ||
| 323 | 	struct proc_regioninfo prp_prinfo; | ||
| 324 | 	struct vnode_info_path prp_vip; | ||
| 325 | }; | ||
| 326 | |||
| 327 | struct proc_regionpath { | ||
| 328 | 	uint64_t prpo_addr; | ||
| 329 | 	uint64_t prpo_regionlength; | ||
| 330 | 	char prpo_path[MAXPATHLEN]; | ||
| 331 | }; | ||
| 332 | |||
| 333 | struct proc_vnodepathinfo { | ||
| 334 | 	struct vnode_info_path pvi_cdir; | ||
| 335 | 	struct vnode_info_path pvi_rdir; | ||
| 336 | }; | ||
| 337 | |||
| 338 | struct 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 | |||
| 355 | struct in4in6_addr { | ||
| 356 | 	u_int32_t i46a_pad32[3]; | ||
| 357 | 	struct in_addr i46a_addr4; | ||
| 358 | }; | ||
| 359 | |||
| 360 | struct 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 | |||
| 413 | struct 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 | |||
| 428 | struct 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 | |||
| 445 | struct 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 | |||
| 455 | struct 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 | |||
| 465 | struct 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 | |||
| 479 | struct 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 | |||
| 503 | struct 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 | |||
| 513 | enum { | ||
| 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 | |||
| 524 | struct 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 | |||
| 555 | struct socket_fdinfo { | ||
| 556 | 	struct proc_fileinfo pfi; | ||
| 557 | 	struct socket_info psi; | ||
| 558 | }; | ||
| 559 | |||
| 560 | |||
| 561 | |||
| 562 | struct psem_info { | ||
| 563 | 	struct vinfo_stat psem_stat; | ||
| 564 | 	char psem_name[MAXPATHLEN]; | ||
| 565 | }; | ||
| 566 | |||
| 567 | struct psem_fdinfo { | ||
| 568 | 	struct proc_fileinfo pfi; | ||
| 569 | 	struct psem_info pseminfo; | ||
| 570 | }; | ||
| 571 | |||
| 572 | |||
| 573 | |||
| 574 | struct pshm_info { | ||
| 575 | 	struct vinfo_stat pshm_stat; | ||
| 576 | 	uint64_t pshm_mappaddr; | ||
| 577 | 	char pshm_name[MAXPATHLEN]; | ||
| 578 | }; | ||
| 579 | |||
| 580 | struct pshm_fdinfo { | ||
| 581 | 	struct proc_fileinfo pfi; | ||
| 582 | 	struct pshm_info pshminfo; | ||
| 583 | }; | ||
| 584 | |||
| 585 | |||
| 586 | struct 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 | |||
| 594 | struct pipe_fdinfo { | ||
| 595 | 	struct proc_fileinfo pfi; | ||
| 596 | 	struct pipe_info pipeinfo; | ||
| 597 | }; | ||
| 598 | |||
| 599 | |||
| 600 | struct kqueue_info { | ||
| 601 | 	struct vinfo_stat kq_stat; | ||
| 602 | 	uint32_t kq_state; | ||
| 603 | 	uint32_t rfu_1; /* reserved */ | ||
| 604 | }; | ||
| 605 | |||
| 606 | struct 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 | |||
| 630 | struct kqueue_fdinfo { | ||
| 631 | 	struct proc_fileinfo pfi; | ||
| 632 | 	struct kqueue_info kqueueinfo; | ||
| 633 | }; | ||
| 634 | |||
| 635 | struct appletalk_info { | ||
| 636 | 	struct vinfo_stat atalk_stat; | ||
| 637 | }; | ||
| 638 | |||
| 639 | struct appletalk_fdinfo { | ||
| 640 | 	struct proc_fileinfo pfi; | ||
| 641 | 	struct appletalk_info appletalkinfo; | ||
| 642 | }; | ||
| 643 | |||
| 644 | typedef 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 | |||
| 657 | struct proc_fdinfo { | ||
| 658 | 	int32_t proc_fd; | ||
| 659 | 	uint32_t proc_fdtype; | ||
| 660 | }; | ||
| 661 | |||
| 662 | struct 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)) | ||
| 38 | int getcontext(ucontext_t *); | ||
| 39 | |||
| 40 | __API_DEPRECATED("No longer supported", macos(10.5, 10.6)) | ||
| 41 | void makecontext(ucontext_t *, void (*)(), int, ...); | ||
| 42 | |||
| 43 | __API_DEPRECATED("No longer supported", macos(10.5, 10.6)) | ||
| 44 | int setcontext(const ucontext_t *); | ||
| 45 | |||
| 46 | __API_DEPRECATED("No longer supported", macos(10.5, 10.6)) | ||
| 47 | int 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 | */ | ||
| 85 | int 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 | |||
| 92 | int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 93 | int proc_listallpids(void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); | ||
| 94 | int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); | ||
| 95 | int proc_listchildpids(pid_t ppid, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_1); | ||
| 96 | int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 97 | int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 98 | int proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3); | ||
| 99 | int proc_name(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 100 | int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 101 | int proc_kmsgbuf(void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 102 | int proc_pidpath(int pid, void * buffer, uint32_t buffersize) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); | ||
| 103 | int 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)); | ||
| 104 | int 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 | */ | ||
| 111 | int 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 | |||
| 122 | int proc_setpcontrol(const int control) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2); | ||
| 123 | int proc_setpcontrol(const int control); | ||
| 124 | |||
| 125 | int proc_track_dirty(pid_t pid, uint32_t flags); | ||
| 126 | int proc_set_dirty(pid_t pid, bool dirty); | ||
| 127 | int proc_get_dirty(pid_t pid, uint32_t *flags); | ||
| 128 | int proc_clear_dirty(pid_t pid, uint32_t flags); | ||
| 129 | |||
| 130 | int 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 | */ | ||
| 139 | int proc_set_no_smt(void) __API_AVAILABLE(macos(11.0)); | ||
| 140 | |||
| 141 | /* Set NO_SMT on the current thread */ | ||
| 142 | int 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 | */ | ||
| 150 | int proc_set_csm(uint32_t flags) __API_AVAILABLE(macos(11.0)); | ||
| 151 | |||
| 152 | /* Set CPU security mitigation on the current thread */ | ||
| 153 | int 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 | */ | ||
| 176 | int proc_list_uptrs(pid_t pid, uint64_t *buffer, uint32_t buffersize); | ||
| 177 | |||
| 178 | int proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz); | ||
| 179 | int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, | ||
| 180 | int buffersize); | ||
| 181 | #endif /* PRIVATE */ | ||
| 182 | |||
| 183 | int 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 | */ | ||
| 75 | struct 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 | */ | ||
| 145 | struct 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 | */ | ||
| 157 | struct 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 | |||
| 172 | struct 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 | |||
| 251 | struct 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 | */ | ||
| 14 | OS_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 | |||
| 62 | struct 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 | ||
| 68 | struct OS_REFINED_FOR_SWIFT os_workgroup_interval_data_opaque_s { | ||
| 69 | 	uint32_t sig; | ||
| 70 | 	char opaque[__OS_WORKGROUP_INTERVAL_DATA_SIZE__]; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct 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 | |||
| 31 | OS_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 | */ | ||
| 40 | OS_WORKGROUP_SUBCLASS_DECL_PROTO(os_workgroup_interval, Repeatable); | ||
| 41 | OS_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 | */ | ||
| 55 | typedef struct os_workgroup_interval_data_opaque_s os_workgroup_interval_data_s; | ||
| 56 | typedef 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 | */ | ||
| 91 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 92 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT | ||
| 93 | int | ||
| 94 | os_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 | */ | ||
| 120 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 121 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT | ||
| 122 | int | ||
| 123 | os_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 | */ | ||
| 145 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 146 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT | ||
| 147 | int | ||
| 148 | os_workgroup_interval_finish(os_workgroup_interval_t wg, | ||
| 149 | 		os_workgroup_interval_data_t _Nullable data); | ||
| 150 | |||
| 151 | OS_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 | |||
| 31 | OS_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 | */ | ||
| 48 | OS_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 | */ | ||
| 60 | typedef struct os_workgroup_attr_opaque_s os_workgroup_attr_s; | ||
| 61 | typedef 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 | */ | ||
| 89 | API_AVAILABLE(macos(11.0)) | ||
| 90 | API_UNAVAILABLE(ios, tvos, watchos) | ||
| 91 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT | ||
| 92 | int | ||
| 93 | os_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 | */ | ||
| 113 | API_AVAILABLE(macos(11.0)) | ||
| 114 | API_UNAVAILABLE(ios, tvos, watchos) | ||
| 115 | OS_SWIFT_NAME(WorkGroup.init(__name:port:)) OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED | ||
| 116 | os_workgroup_t _Nullable | ||
| 117 | os_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 | */ | ||
| 135 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 136 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED | ||
| 137 | os_workgroup_t _Nullable | ||
| 138 | os_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 | */ | ||
| 147 | OS_REFINED_FOR_SWIFT | ||
| 148 | typedef struct os_workgroup_join_token_opaque_s os_workgroup_join_token_s; | ||
| 149 | OS_REFINED_FOR_SWIFT | ||
| 150 | typedef 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 | */ | ||
| 174 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 175 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT | ||
| 176 | int | ||
| 177 | os_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 | */ | ||
| 199 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 200 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT | ||
| 201 | void | ||
| 202 | os_workgroup_leave(os_workgroup_t wg, os_workgroup_join_token_t token); | ||
| 203 | |||
| 204 | /* Working Arena index of a thread in a workgroup */ | ||
| 205 | typedef uint32_t os_workgroup_index; | ||
| 206 | /* Destructor for Working Arena */ | ||
| 207 | typedef 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 | */ | ||
| 238 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 239 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT | ||
| 240 | int | ||
| 241 | os_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 | */ | ||
| 268 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 269 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT | ||
| 270 | void * _Nullable | ||
| 271 | os_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 | */ | ||
| 296 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 297 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT | ||
| 298 | void | ||
| 299 | os_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 | */ | ||
| 308 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 309 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT | ||
| 310 | bool | ||
| 311 | os_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 | */ | ||
| 322 | OS_REFINED_FOR_SWIFT | ||
| 323 | typedef struct os_workgroup_max_parallel_threads_attr_s os_workgroup_mpt_attr_s; | ||
| 324 | OS_REFINED_FOR_SWIFT | ||
| 325 | typedef 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 | */ | ||
| 347 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 348 | OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT | ||
| 349 | int | ||
| 350 | os_workgroup_max_parallel_threads(os_workgroup_t wg, os_workgroup_mpt_attr_t | ||
| 351 | 		_Nullable attr); | ||
| 352 | |||
| 353 | OS_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 | |||
| 33 | OS_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 | */ | ||
| 41 | OS_WORKGROUP_SUBCLASS_DECL_PROTO(os_workgroup_parallel, Parallelizable); | ||
| 42 | OS_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 | */ | ||
| 63 | API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0)) | ||
| 64 | OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED | ||
| 65 | OS_SWIFT_NAME(WorkGroupParallel.init(__name:attr:)) | ||
| 66 | os_workgroup_parallel_t _Nullable | ||
| 67 | os_workgroup_parallel_create(const char * _Nullable name, | ||
| 68 | 	os_workgroup_attr_t _Nullable attr); | ||
| 69 | |||
| 70 | OS_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 | */ | ||
| 75 | struct 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 | */ | ||
| 117 | struct 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 | */ | ||
| 140 | struct 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 | |||
| 60 | struct 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 | |||
| 86 | struct 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 | |||
| 127 | struct 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 | |||
| 148 | struct proc_taskallinfo { | ||
| 149 | 	struct proc_bsdinfo pbsd; | ||
| 150 | 	struct proc_taskinfo ptinfo; | ||
| 151 | }; | ||
| 152 | |||
| 153 | #define MAXTHREADNAMESIZE 64 | ||
| 154 | |||
| 155 | struct 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 | |||
| 169 | struct 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 | |||
| 225 | struct 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 | |||
| 239 | struct 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 | |||
| 258 | struct 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 | |||
| 265 | struct 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 | */ | ||
| 276 | struct 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 | |||
| 300 | struct vnode_info { | ||
| 301 | 	struct vinfo_stat vi_stat; | ||
| 302 | 	int vi_type; | ||
| 303 | 	int vi_pad; | ||
| 304 | 	fsid_t vi_fsid; | ||
| 305 | }; | ||
| 306 | |||
| 307 | struct vnode_info_path { | ||
| 308 | 	struct vnode_info vip_vi; | ||
| 309 | 	char vip_path[MAXPATHLEN]; /* tail end of it */ | ||
| 310 | }; | ||
| 311 | |||
| 312 | struct vnode_fdinfo { | ||
| 313 | 	struct proc_fileinfo pfi; | ||
| 314 | 	struct vnode_info pvi; | ||
| 315 | }; | ||
| 316 | |||
| 317 | struct vnode_fdinfowithpath { | ||
| 318 | 	struct proc_fileinfo pfi; | ||
| 319 | 	struct vnode_info_path pvip; | ||
| 320 | }; | ||
| 321 | |||
| 322 | struct proc_regionwithpathinfo { | ||
| 323 | 	struct proc_regioninfo prp_prinfo; | ||
| 324 | 	struct vnode_info_path prp_vip; | ||
| 325 | }; | ||
| 326 | |||
| 327 | struct proc_regionpath { | ||
| 328 | 	uint64_t prpo_addr; | ||
| 329 | 	uint64_t prpo_regionlength; | ||
| 330 | 	char prpo_path[MAXPATHLEN]; | ||
| 331 | }; | ||
| 332 | |||
| 333 | struct proc_vnodepathinfo { | ||
| 334 | 	struct vnode_info_path pvi_cdir; | ||
| 335 | 	struct vnode_info_path pvi_rdir; | ||
| 336 | }; | ||
| 337 | |||
| 338 | struct 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 | |||
| 355 | struct in4in6_addr { | ||
| 356 | 	u_int32_t i46a_pad32[3]; | ||
| 357 | 	struct in_addr i46a_addr4; | ||
| 358 | }; | ||
| 359 | |||
| 360 | struct 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 | |||
| 413 | struct 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 | |||
| 428 | struct 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 | |||
| 445 | struct 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 | |||
| 455 | struct 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 | |||
| 465 | struct 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 | |||
| 479 | struct 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 | |||
| 503 | struct 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 | |||
| 513 | enum { | ||
| 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 | |||
| 524 | struct 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 | |||
| 555 | struct socket_fdinfo { | ||
| 556 | 	struct proc_fileinfo pfi; | ||
| 557 | 	struct socket_info psi; | ||
| 558 | }; | ||
| 559 | |||
| 560 | |||
| 561 | |||
| 562 | struct psem_info { | ||
| 563 | 	struct vinfo_stat psem_stat; | ||
| 564 | 	char psem_name[MAXPATHLEN]; | ||
| 565 | }; | ||
| 566 | |||
| 567 | struct psem_fdinfo { | ||
| 568 | 	struct proc_fileinfo pfi; | ||
| 569 | 	struct psem_info pseminfo; | ||
| 570 | }; | ||
| 571 | |||
| 572 | |||
| 573 | |||
| 574 | struct pshm_info { | ||
| 575 | 	struct vinfo_stat pshm_stat; | ||
| 576 | 	uint64_t pshm_mappaddr; | ||
| 577 | 	char pshm_name[MAXPATHLEN]; | ||
| 578 | }; | ||
| 579 | |||
| 580 | struct pshm_fdinfo { | ||
| 581 | 	struct proc_fileinfo pfi; | ||
| 582 | 	struct pshm_info pshminfo; | ||
| 583 | }; | ||
| 584 | |||
| 585 | |||
| 586 | struct 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 | |||
| 594 | struct pipe_fdinfo { | ||
| 595 | 	struct proc_fileinfo pfi; | ||
| 596 | 	struct pipe_info pipeinfo; | ||
| 597 | }; | ||
| 598 | |||
| 599 | |||
| 600 | struct kqueue_info { | ||
| 601 | 	struct vinfo_stat kq_stat; | ||
| 602 | 	uint32_t kq_state; | ||
| 603 | 	uint32_t rfu_1; /* reserved */ | ||
| 604 | }; | ||
| 605 | |||
| 606 | struct 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 | |||
| 630 | struct kqueue_fdinfo { | ||
| 631 | 	struct proc_fileinfo pfi; | ||
| 632 | 	struct kqueue_info kqueueinfo; | ||
| 633 | }; | ||
| 634 | |||
| 635 | struct appletalk_info { | ||
| 636 | 	struct vinfo_stat atalk_stat; | ||
| 637 | }; | ||
| 638 | |||
| 639 | struct appletalk_fdinfo { | ||
| 640 | 	struct proc_fileinfo pfi; | ||
| 641 | 	struct appletalk_info appletalkinfo; | ||
| 642 | }; | ||
| 643 | |||
| 644 | typedef 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 | |||
| 657 | struct proc_fdinfo { | ||
| 658 | 	int32_t proc_fd; | ||
| 659 | 	uint32_t proc_fdtype; | ||
| 660 | }; | ||
| 661 | |||
| 662 | struct 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)) | ||
| 38 | int getcontext(ucontext_t *); | ||
| 39 | |||
| 40 | __API_DEPRECATED("No longer supported", macos(10.5, 10.6)) | ||
| 41 | void makecontext(ucontext_t *, void (*)(), int, ...); | ||
| 42 | |||
| 43 | __API_DEPRECATED("No longer supported", macos(10.5, 10.6)) | ||
| 44 | int setcontext(const ucontext_t *); | ||
| 45 | |||
| 46 | __API_DEPRECATED("No longer supported", macos(10.5, 10.6)) | ||
| 47 | int 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. |
| 60 | update_lock: std.Thread.Mutex = .{}, | 60 | update_lock: std.Thread.Mutex = .{}, |
| 61 | 61 | ||
| 62 | /// Keeps track of how many columns in the terminal have been output, so that | ||
| 63 | /// we can move the cursor back later. | ||
| 64 | columns_written: usize = undefined, | ||
| 65 | |||
| 66 | /// Represents one unit of progress. Each node can have children nodes, or | 62 | /// 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`. |
| 68 | pub const Node = struct { | 64 | pub 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 | } |
| 189 | 184 | ||
| 185 | // ED -- Clear screen | ||
| 186 | const ED = "\x1b[J"; | ||
| 187 | // DECSC -- Save cursor position | ||
| 188 | const DECSC = "\x1b7"; | ||
| 189 | // DECRC -- Restore cursor position | ||
| 190 | const 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 | |||
| 190 | fn refreshWithHeldLock(self: *Progress) void { | 194 | fn 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; |
| 194 | 198 | ||
| 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 cursor | 201 | // 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 the | 202 | // when it becomes too long. |
| 200 | // line | 203 | 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) |
| 208 | 211 | 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); |
| 213 | 216 | 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. |
| 216 | 219 | 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 - |
| 218 | 221 | @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 | } | ||
| 246 | 224 | ||
| 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 | } |
| 249 | 247 | ||
| 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 | } |
| 281 | 279 | ||
| 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 | } |
| 288 | 302 | ||
| ... | @@ -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 | } |
| 298 | 311 | ||
| 299 | fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: anytype) void { | 312 | fn 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 | } |
| 367 | 367 | ||
| 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 | }; |
| 39 | 39 | ||
| 40 | pub fn getErrno(rc: anytype) u16 { | 40 | pub 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. |
| 338 | pub const Header = struct { | 338 | pub 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 | }; |
| 389 | 390 | ||
| 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; |
| 423 | 430 | ||
| 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 | } |
| 436 | 435 | ||
| 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 | } |
| 456 | 446 | ||
| 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 | } |
| 564 | 554 | ||
| 555 | pub 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 | } | ||
| 561 | test "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 | |||
| 565 | pub const EI_NIDENT = 16; | 575 | pub const EI_NIDENT = 16; |
| 566 | 576 | ||
| 567 | pub const EI_CLASS = 4; | 577 | pub const EI_CLASS = 4; |
| ... | @@ -1515,6 +1525,8 @@ pub const EM = extern enum(u16) { | ... | @@ -1515,6 +1525,8 @@ pub const EM = extern enum(u16) { |
| 1515 | 1525 | ||
| 1516 | /// Linux kernel bpf virtual machine | 1526 | /// Linux kernel bpf virtual machine |
| 1517 | _BPF = 247, | 1527 | _BPF = 247, |
| 1528 | |||
| 1529 | _, | ||
| 1518 | }; | 1530 | }; |
| 1519 | 1531 | ||
| 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 following | 36 | /// 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 inserted | 42 | /// - *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 text | 44 | /// - *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* aligned | 45 | /// - *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-termination | 57 | /// - 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-termination | 58 | /// - 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 notation | 59 | /// - `e`: output floating point value in scientific notation |
| 66 | /// - `d`: output numeric value in decimal notation | 60 | /// - `d`: output numeric value in decimal notation |
| 67 | /// - `b`: output integer value in binary notation | 61 | /// - `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 | } |
| 627 | 621 | ||
| 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 | } |
| 792 | 786 | ||
| 787 | fn 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 | |||
| 831 | const formatSizeDec = formatSizeImpl(1000).f; | ||
| 832 | const 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, ...). | ||
| 837 | pub 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, ...). | ||
| 844 | pub fn fmtIntSizeBin(value: u64) std.fmt.Formatter(formatSizeBin) { | ||
| 845 | return .{ .data = value }; | ||
| 846 | } | ||
| 847 | |||
| 793 | pub fn formatText( | 848 | pub 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 | } |
| 1113 | 1168 | ||
| 1114 | pub 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 | |||
| 1155 | pub fn formatInt( | 1169 | pub 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 | } |
| 1212 | 1226 | ||
| 1213 | /// Formats a number of nanoseconds according to its magnitude: | 1227 | fn 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 | ||
| 1217 | pub 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 | } |
| 1258 | 1268 | ||
| 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 | } |
| 1263 | 1273 | ||
| 1264 | test "formatDuration" { | 1274 | /// Return a Formatter for number of nanoseconds according to its magnitude: |
| 1275 | /// [#y][#w][#d][#h][#m]#[.###][n|u|m]s | ||
| 1276 | pub fn fmtDuration(ns: u64) Formatter(formatDuration) { | ||
| 1277 | return .{ .data = ns }; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | test "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 | } |
| 1295 | 1312 | ||
| 1296 | /// Wraps a `u64` to format with `formatDuration`. | ||
| 1297 | const 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`. | ||
| 1306 | pub fn duration(ns: u64) Duration { | ||
| 1307 | return Duration{ .ns = ns }; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | pub const ParseIntError = error{ | 1313 | pub const ParseIntError = error{ |
| 1311 | /// The result cannot fit in the type specified | 1314 | /// 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 | } |
| 1807 | 1810 | ||
| 1808 | test "filesize" { | 1811 | test "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 | } |
| 1812 | 1819 | ||
| 1813 | test "struct" { | 1820 | test "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 | } |
| 2219 | 2224 | ||
| 2220 | test "enum-literal" { | 2225 | test "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 | } |
| 340 | 340 | ||
| 341 | pub fn parseFloat(comptime T: type, s: []const u8) !T { | 341 | pub 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 | } |
| 345 | 345 | ||
| ... | @@ -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, "-")); | ||
| 382 | 384 | ||
| 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 | } |
| 51 | 51 | ||
| 52 | pub fn AutoHashMap(comptime K: type, comptime V: type) type { | 52 | pub 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 | } |
| 55 | 55 | ||
| 56 | pub fn AutoHashMapUnmanaged(comptime K: type, comptime V: type) type { | 56 | pub 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 | } |
| 59 | 59 | ||
| 60 | /// Builtin hashmap for strings as keys. | 60 | /// Builtin hashmap for strings as keys. |
| 61 | pub fn StringHashMap(comptime V: type) type { | 61 | pub 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 | } |
| 64 | 64 | ||
| 65 | pub fn StringHashMapUnmanaged(comptime V: type) type { | 65 | pub 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 | } |
| 68 | 68 | ||
| 69 | pub fn eqlString(a: []const u8, b: []const u8) bool { | 69 | pub 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 | } |
| 76 | 76 | ||
| 77 | pub const DefaultMaxLoadPercentage = 80; | 77 | /// Deprecated use `default_max_load_percentage` |
| 78 | pub const DefaultMaxLoadPercentage = default_max_load_percentage; | ||
| 79 | |||
| 80 | pub const default_max_load_percentage = 80; | ||
| 78 | 81 | ||
| 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, |
| 97 | 100 | ||
| 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); |
| 257 | 260 | ||
| 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 to | 277 | // 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 the | 279 | /// 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, |
| 279 | 282 | ||
| 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; |
| 283 | 286 | ||
| 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 | }; |
| 384 | 387 | ||
| 385 | pub const Managed = HashMap(K, V, hashFn, eqlFn, MaxLoadPercentage); | 388 | pub const Managed = HashMap(K, V, hashFn, eqlFn, max_load_percentage); |
| 386 | 389 | ||
| 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 | } |
| 393 | 396 | ||
| 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 | } |
| 397 | 400 | ||
| 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 | } |
| 426 | 429 | ||
| 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 | } |
| 445 | 448 | ||
| ... | @@ -712,9 +715,9 @@ pub fn HashMapUnmanaged( | ... | @@ -712,9 +715,9 @@ pub fn HashMapUnmanaged( |
| 712 | } | 715 | } |
| 713 | 716 | ||
| 714 | // This counts the number of occupied slots, used + tombstones, which is | 717 | // 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); |
| 737 | 740 | ||
| 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 | } |
| 752 | 755 | ||
| 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)); |
| 757 | 760 | ||
| ... | @@ -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); |
| 763 | 766 | ||
| 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" { |
| 943 | 946 | ||
| 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); |
| 947 | 950 | ||
| 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 | } |
| 36 | 36 |
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 | else | 648 | 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 | else | 712 | 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 | else | 720 | 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 | } |
| 1096 | 1096 | ||
| 1097 | pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal }; | ||
| 1098 | |||
| 1099 | fn 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. | ||
| 1123 | pub 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 | |||
| 1131 | test "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 will | 1149 | /// 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; |
| 8 | const meta = std.meta; | 8 | const meta = std.meta; |
| 9 | const mem = std.mem; | 9 | const mem = std.mem; |
| 10 | const Allocator = mem.Allocator; | 10 | const Allocator = mem.Allocator; |
| 11 | const testing = std.testing; | ||
| 11 | 12 | ||
| 12 | pub fn MultiArrayList(comptime S: type) type { | 13 | pub 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, |
| 28 | 29 | ||
| 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 | } |
| 288 | 293 | ||
| 289 | test "basic usage" { | 294 | test "basic usage" { |
| 290 | const testing = std.testing; | ||
| 291 | const ally = testing.allocator; | 295 | const ally = testing.allocator; |
| 292 | 296 | ||
| 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); |
| 301 | 305 | ||
| 306 | testing.expectEqual(@as(usize, 0), list.items(.a).len); | ||
| 307 | |||
| 302 | try list.ensureCapacity(ally, 2); | 308 | try list.ensureCapacity(ally, 2); |
| 303 | 309 | ||
| 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 capacityInBytes | 375 | // 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. |
| 371 | test "regression test for @reduce bug" { | 377 | test "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 }); |
| 413 | 419 | ||
| 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 | |||
| 454 | test "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; |
| 145 | 145 | ||
| 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 | }; |
| 158 | 160 | ||
| 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 | } |
| 1506 | 1508 | ||
| ... | @@ -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{ |
| 4622 | 4624 | ||
| 4623 | /// Call this when you made a syscall or something that sets errno | 4625 | /// 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. |
| 4625 | pub fn unexpectedErrno(err: usize) UnexpectedError { | 4627 | pub 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 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const std = @import("std"); |
| 2 | 2 | ||
| 3 | pub fn build(b: *Builder) void { | 3 | pub fn build(b: *std.build.Builder) void { |
| 4 | // Standard target options allows the person running `zig build` to choose | 4 | // Standard target options allows the person running `zig build` to choose |
| 5 | // what target to build for. Here we do not override the defaults, which | 5 | // 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 options | 6 | // 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 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const std = @import("std"); |
| 2 | 2 | ||
| 3 | pub fn build(b: *Builder) void { | 3 | pub 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 rparen | 773 | 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 rbrace | 776 | 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 SliceOpen | 996 | assert(extra.end != 0); // should have used slice_open |
| 993 | end_offset += 1; // rbracket | 997 | 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 Slice | 1002 | assert(extra.sentinel != 0); // should have used slice |
| 999 | end_offset += 1; // rbracket | 1003 | 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 { |
| 2925 | 2929 | ||
| 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 statement | 937 | /// 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 following | 938 | /// 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 | /// PrefixTypeOp | 1612 | /// PrefixTypeOp |
| 1610 | /// <- QUESTIONMARK | 1613 | /// <- QUESTIONMARK |
| 1611 | /// / KEYWORD_anyframe MINUSRARROW | 1614 | /// / 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 | /// PtrTypeStart | 1619 | /// PtrTypeStart |
| 1615 | /// <- ASTERISK | 1620 | /// <- ASTERISK |
| 1616 | /// / ASTERISK2 | 1621 | /// / ASTERISK2 |
| 1617 | /// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET | 1622 | /// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET |
| 1618 | /// ArrayTypeStart <- LBRACKET Expr? (COLON Expr)? RBRACKET | 1623 | /// 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 | else | 1787 | 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 | } |
| 3439 | 3447 | ||
| 3440 | /// SuffixOp | 3448 | /// SuffixOp |
| 3441 | /// <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET | 3449 | /// <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET |
| 3442 | /// / DOT IDENTIFIER | 3450 | /// / DOT IDENTIFIER |
| 3443 | /// / DOTASTERISK | 3451 | /// / DOTASTERISK |
| 3444 | /// / DOTQUESTIONMARK | 3452 | /// / DOTQUESTIONMARK |
| ... | @@ -3450,17 +3458,6 @@ const Parser = struct { | ... | @@ -3450,17 +3458,6 @@ const Parser = struct { |
| 3450 | 3458 | ||
| 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 | } |
| 965 | 967 | ||
| 968 | test "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 | |||
| 978 | test "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 | |||
| 966 | test "zig fmt: enum literal" { | 989 | test "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 | } |
| 4278 | 4301 | ||
| 4302 | test "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 | |||
| 4279 | test "zig fmt: insert trailing comma if there are comments between switch values" { | 4314 | test "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 | } |
| 4317 | 4352 | ||
| 4318 | test "zig fmt: error for invalid align" { | 4353 | test "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 | } |
| 4325 | 4366 | ||
| ... | @@ -4580,6 +4621,16 @@ test "recovery: missing comma in params" { | ... | @@ -4580,6 +4621,16 @@ test "recovery: missing comma in params" { |
| 4580 | }); | 4621 | }); |
| 4581 | } | 4622 | } |
| 4582 | 4623 | ||
| 4624 | test "recovery: missing while rbrace" { | ||
| 4625 | try testError( | ||
| 4626 | \\fn a() b { | ||
| 4627 | \\ while (d) { | ||
| 4628 | \\} | ||
| 4629 | , &[_]Error{ | ||
| 4630 | .expected_statement, | ||
| 4631 | }); | ||
| 4632 | } | ||
| 4633 | |||
| 4583 | const std = @import("std"); | 4634 | const std = @import("std"); |
| 4584 | const mem = std.mem; | 4635 | const mem = std.mem; |
| 4585 | const warn = std.debug.warn; | 4636 | const 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 | }, |
| 472 | 472 | ||
| 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), |
| 476 | 476 | ||
| 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]) or | 823 | 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; | ||
| 826 | 829 | ||
| 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); // lbracket | 831 | 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); // rbracket | 837 | 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 | } |
| 836 | 841 | ||
| 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 | } |
| 843 | 846 | ||
| 844 | try renderToken(ais, tree, end_last + 1, .none); // colon | 847 | 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 | } |
| 848 | 849 | ||
| 849 | fn renderAsmOutput( | 850 | fn 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(); |
| 1658 | 1660 |
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 | } |
| 415 | 423 | ||
| ... | @@ -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 | } |
| 441 | 453 | ||
| ... | @@ -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 | } |
| 466 | 481 | ||
| ... | @@ -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 | } |
| 477 | 494 | ||
| ... | @@ -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 | }; |
| 511 | 560 | ||
| 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 needing | 789 | /// 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, | ||
| 743 | 794 | ||
| 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 | }; |
| 777 | 838 | ||
| 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 }; |
| 1137 | 1199 | ||
| 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 the | 1305 | // TODO instead of enum literal type, this needs to be the |
| 1239 | // std.builtin.CallingConvention enum. We need to implement importing other files | 1306 | // 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 | }; | ||
| 1258 | 1338 | ||
| 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 | } |
| 1319 | 1404 | ||
| 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); |
| 1322 | 1411 | ||
| ... | @@ -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 | } |
| 3296 | 3385 | ||
| 3297 | pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) InnerError!*Inst { | 3386 | pub 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 | } |
| 3449 | 3541 | ||
| 3542 | pub 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 | |||
| 3450 | pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst { | 3551 | pub 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), |
| 628 | 628 | ||
| 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", .{}), |
| 634 | 637 | ||
| 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", .{}), |
| 654 | 657 | ||
| 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 | } |
| 666 | 666 | ||
| ... | @@ -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); |
| 845 | 849 | ||
| 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 | } |
| 850 | 856 | ||
| ... | @@ -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 | } |
| 3634 | 3646 | ||
| 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 location | 3656 | // TODO function call with result location |
| 3641 | return rvalue(mod, scope, rl, result); | 3657 | return rvalue(mod, scope, rl, result); |
| 3642 | } | 3658 | } |
| 3643 | 3659 | ||
| 3660 | fn 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 | |||
| 3710 | fn 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 | |||
| 3721 | fn 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 | |||
| 3743 | fn 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 | |||
| 3644 | pub const simple_types = std.ComptimeStringMap(Value.Tag, .{ | 3751 | pub 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 | }; |
| 273 | 273 | ||
| 274 | pub const CompoundLiteralExpr = opaque { | ||
| 275 | pub const getInitializer = ZigClangCompoundLiteralExpr_getInitializer; | ||
| 276 | extern fn ZigClangCompoundLiteralExpr_getInitializer(*const CompoundLiteralExpr) *const Expr; | ||
| 277 | }; | ||
| 278 | |||
| 274 | pub const CompoundStmt = opaque { | 279 | pub 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 | } |
| 1131 | 1134 | ||
| 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 | } |
| 1141 | 1153 | ||
| 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 | } |
| 1394 | 1415 | ||
| 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 | }; |
| 33 | 33 | ||
| 34 | pub const CValueMap = std.AutoHashMap(*Inst, CValue); | 34 | pub const CValueMap = std.AutoHashMap(*Inst, CValue); |
| 35 | pub const TypedefMap = std.HashMap(Type, struct { name: []const u8, rendered: []u8 }, Type.hash, Type.eql, std.hash_map.default_max_load_percentage); | ||
| 36 | |||
| 37 | fn 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 | |||
| 60 | pub fn typeToCIdentifier(t: Type) std.fmt.Formatter(formatTypeAsCIdentifier) { | ||
| 61 | return .{ .data = t }; | ||
| 62 | } | ||
| 35 | 63 | ||
| 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, | ||
| 118 | 147 | ||
| 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 | } |
| 233 | 313 | ||
| ... | @@ -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 comptime | 433 | .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 | } |
| 799 | 950 | ||
| 951 | fn 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 | |||
| 971 | fn 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 | ||
| 998 | fn 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 | } | ||
| 1011 | fn 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 | |||
| 1026 | fn 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 | } | ||
| 1042 | fn 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 | } | ||
| 1052 | fn 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 | |||
| 1063 | fn 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 | |||
| 800 | fn IndentWriter(comptime UnderlyingWriter: type) type { | 1075 | fn 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 { |
| 53 | 53 | ||
| 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, |
| 166 | 169 | ||
| 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"); |
| 9 | const link = @import("../link.zig"); | 9 | const link = @import("../link.zig"); |
| 10 | const trace = @import("../tracy.zig").trace; | 10 | const trace = @import("../tracy.zig").trace; |
| 11 | const C = @This(); | 11 | const C = @This(); |
| 12 | const Type = @import("../type.zig").Type; | ||
| 12 | 13 | ||
| 13 | pub const base_tag: link.File.Tag = .c; | 14 | pub const base_tag: link.File.Tag = .c; |
| 14 | pub const zig_h = @embedFile("C/zig.h"); | 15 | pub 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. |
| 29 | pub const FnBlock = struct { | 30 | pub const FnBlock = struct { |
| 30 | fwd_decl: std.ArrayListUnmanaged(u8), | 31 | fwd_decl: std.ArrayListUnmanaged(u8), |
| 32 | typedefs: codegen.TypedefMap.Unmanaged, | ||
| 31 | 33 | ||
| 32 | pub const empty: FnBlock = .{ | 34 | pub const empty: FnBlock = .{ |
| 33 | .fwd_decl = .{}, | 35 | .fwd_decl = .{}, |
| 36 | .typedefs = .{}, | ||
| 34 | }; | 37 | }; |
| 35 | }; | 38 | }; |
| 36 | 39 | ||
| ... | @@ -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 {} |
| 74 | pub fn freeDecl(self: *C, decl: *Module.Decl) void { | 77 | pub 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 | } |
| 78 | 86 | ||
| 79 | pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | 87 | 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,8 +89,16 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 81 | defer tracy.end(); | 89 | defer tracy.end(); |
| 82 | 90 | ||
| 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); |
| 87 | 103 | ||
| 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.code | 115 | .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 | } | ||
| 104 | 128 | ||
| 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 | }; |
| 112 | 136 | ||
| 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(); |
| 115 | 141 | ||
| 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(); |
| 143 | 169 | ||
| 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); |
| 146 | 172 | ||
| 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 | }); |
| 152 | 178 | ||
| 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(); | ||
| 154 | 197 | ||
| 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 should | 199 | // 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 | } |
| 179 | 232 | ||
| 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 | } |
| 3190 | 3190 | ||
| 3191 | fn bswapAllFields(comptime S: type, ptr: *S) void { | ||
| 3192 | @panic("TODO implement bswapAllFields"); | ||
| 3193 | } | ||
| 3194 | |||
| 3195 | fn progHeaderTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { | 3191 | fn 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 | }; |
| 673 | 673 | ||
| 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 | }; |
| 835 | 826 | ||
| 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 | }; | ||
| 844 | 828 | ||
| 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 | } |
| 1129 | 1117 | ||
| 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)) | ||
| 1122 | fn 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. | ||
| 1139 | fn 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 | |||
| 1130 | fn transBinaryOperator( | 1164 | fn 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 | } |
| 1331 | 1371 | ||
| 1372 | /// Clang reports the alignment in bits, we use bytes | ||
| 1373 | /// Clang uses 0 for "no alignment specified", we use null | ||
| 1374 | fn zigAlignment(bit_alignment: c_uint) ?c_uint { | ||
| 1375 | if (bit_alignment == 0) return null; | ||
| 1376 | return bit_alignment / 8; | ||
| 1377 | } | ||
| 1378 | |||
| 1332 | fn transDeclStmtOne( | 1379 | fn 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 | } |
| 1450 | 1498 | ||
| 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 | else | 3075 | else |
| 3026 | try transExpr(c, scope, rhs, .used); | 3076 | try transExpr(c, scope, rhs, .used); |
| 3027 | 3077 | ||
| 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( |
| 3077 | 3131 | ||
| 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 | } | ||
| 3080 | 3137 | ||
| 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); |
| 3106 | 3163 | ||
| 3107 | if ((src_child_type.isConstQualified() and | 3164 | if (!src_ty.isArrayType() and ((src_child_type.isConstQualified() and |
| 3108 | !child_type.isConstQualified()) or | 3165 | !child_type.isConstQualified()) or |
| 3109 | (src_child_type.isVolatileQualified() and | 3166 | (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 @intToPtr | 3169 | // 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 | }; |
| 4069 | 4126 | ||
| 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 | }; | ||
| 4080 | 4128 | ||
| 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; |
| 4082 | 4130 | ||
| ... | @@ -4387,40 +4435,68 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { | ... | @@ -4387,40 +4435,68 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 4387 | 4435 | ||
| 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 | // Octal | 4442 | // 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 Zig | 4447 | // 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 | } |
| 4403 | 4457 | ||
| 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 | }; |
| 655 | 668 | ||
| 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 | } |
| 102 | 104 | ||
| ... | @@ -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, |
| 401 | 407 | ||
| 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)), |
| 539 | 547 | ||
| 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 { |
| 844 | 858 | ||
| 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 | } |
| 849 | 864 | ||
| ... | @@ -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, | ||
| 998 | 1015 | ||
| 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, |
| 1183 | 1201 | ||
| 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, |
| 1260 | 1279 | ||
| 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, |
| 1358 | 1378 | ||
| 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, |
| 1438 | 1459 | ||
| 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, |
| 1527 | 1549 | ||
| 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, |
| 1611 | 1634 | ||
| 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(), | ||
| 1666 | 1690 | ||
| 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, | ||
| 1736 | 1760 | ||
| 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 | } |
| 1791 | 1815 | ||
| 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, |
| 1866 | 1914 | ||
| 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, |
| 1940 | 1989 | ||
| 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, |
| 2029 | 2079 | ||
| 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, |
| 2114 | 2165 | ||
| 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, |
| 2185 | 2237 | ||
| 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, |
| 2284 | 2337 | ||
| 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, |
| 2753 | 2811 | ||
| 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, |
| 2966 | 3027 | ||
| 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, |
| 3083 | 3145 | ||
| 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, |
| 3172 | 3235 | ||
| 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 stored | 3354 | /// 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"), |
| 3377 | 3444 | ||
| 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 | }; |
| 3484 | 3552 |
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 | } |
| 2824 | 2824 | ||
| 2825 | const 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 | |||
| 2825 | enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *self) { | 2830 | enum 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 |
| 1224 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getLHS(const struct ZigClangCompoundAssignOperator *); | 1224 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getLHS(const struct ZigClangCompoundAssignOperator *); |
| 1225 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getRHS(const struct ZigClangCompoundAssignOperator *); | 1225 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundAssignOperator_getRHS(const struct ZigClangCompoundAssignOperator *); |
| 1226 | 1226 | ||
| 1227 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCompoundLiteralExpr_getInitializer(const struct ZigClangCompoundLiteralExpr *); | ||
| 1228 | |||
| 1227 | ZIG_EXTERN_C enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *); | 1229 | ZIG_EXTERN_C enum ZigClangUO ZigClangUnaryOperator_getOpcode(const struct ZigClangUnaryOperator *); |
| 1228 | ZIG_EXTERN_C struct ZigClangQualType ZigClangUnaryOperator_getType(const struct ZigClangUnaryOperator *); | 1230 | ZIG_EXTERN_C struct ZigClangQualType ZigClangUnaryOperator_getType(const struct ZigClangUnaryOperator *); |
| 1229 | ZIG_EXTERN_C const struct ZigClangExpr *ZigClangUnaryOperator_getSubExpr(const struct ZigClangUnaryOperator *); | 1231 | ZIG_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 the | 223 | /// 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 the | 234 | /// 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, |
| 373 | 389 | ||
| 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, |
| 421 | 440 | ||
| 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, |
| 465 | 485 | ||
| 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, |
| 637 | 662 | ||
| 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 | }, |
| 1654 | 1681 | ||
| 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 | }, |
| 1777 | 1807 | ||
| 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).?), | ||
| 163 | 170 | ||
| 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 | }; |
| 519 | 526 | ||
| 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 here | 955 | // 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 here | 964 | // 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 | } |
| 970 | 979 | ||
| 971 | // TODO handle function calls of generic functions | 980 | // TODO handle function calls of generic functions |
| 972 | 981 | 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 | } |
| 982 | 986 | ||
| 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 | } |
| 1082 | 1086 | ||
| 1087 | fn zirAwait(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1088 | return mod.fail(scope, inst.base.src, "TODO implement await", .{}); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | fn zirResume(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1092 | return mod.fail(scope, inst.base.src, "TODO implement resume", .{}); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | fn zirSuspend(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | ||
| 1096 | return mod.fail(scope, inst.base.src, "TODO implement suspend", .{}); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | fn zirSuspendBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst { | ||
| 1100 | return mod.fail(scope, inst.base.src, "TODO implement suspend", .{}); | ||
| 1101 | } | ||
| 1102 | |||
| 1083 | fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst { | 1103 | fn 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 | } |
| 1484 | 1504 | ||
| 1485 | fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { | 1505 | fn 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(); |
| 1488 | 1508 | ||
| ... | @@ -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 | } |
| 1498 | 1519 | ||
| 1499 | fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerError!*Inst { | 1520 | fn 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(); |
| 1502 | 1523 | ||
| ... | @@ -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 | } |
| 1518 | 1540 | ||
| ... | @@ -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); |
| 1528 | 1551 | ||
| 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 | } |
| 2156 | 2180 | ||
| 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 | }; |
| 2164 | 2191 | ||
| ... | @@ -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 the | 2335 | // 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 for | 2336 | // 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 | } |
| 43 | 43 | ||
| 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); |
| 46 | 59 | ||
| ... | @@ -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 | }); |
| 243 | 243 | ||
| ... | @@ -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 | }); |
| 324 | 324 | ||
| 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 | }); |
| 350 | 350 | ||
| ... | @@ -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 > 4 | 353 | \\#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 | }); |
| 361 | 361 | ||
| 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 1 | 418 | \\#define foo 1 |
| 419 | \\#define inline 2 | 419 | \\#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 | }); |
| 425 | 425 | ||
| 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 0XF00D | 508 | \\#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 | }); |
| 512 | 512 | ||
| 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 | }); |
| 650 | 656 | ||
| 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 | }); |
| 877 | 883 | ||
| 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 | }); |
| 886 | 892 | ||
| 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 24 | 956 | \\#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 | }); |
| 954 | 960 | ||
| 955 | cases.add("#define referencing another #define", | 961 | cases.add("#define referencing another #define", |
| 956 | \\#define THING2 THING1 | 962 | \\#define THING2 THING1 |
| 957 | \\#define THING1 1234 | 963 | \\#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 | }); |
| 1007 | 1013 | ||
| 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 //foo | 1091 | \\#define foo 1 //foo |
| 1086 | \\#define bar /* bar */ 2 | 1092 | \\#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 | }); |
| 1091 | 1097 | ||
| 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 | }); |
| 1721 | 1727 | ||
| 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 | }); |
| 2480 | 2486 | ||
| 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 | }); |
| 3096 | 3102 | ||
| 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 | }); |
| 3106 | 3112 | ||
| 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 | }); |
| 3201 | 3207 | ||
| 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 | }); |
| 3332 | 3338 | ||
| 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 | } |
| 276 | 276 | ||
| ... | @@ -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 | } |
| 289 | 289 | ||
| ... | @@ -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.glibc | 298 | 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}); |
| 304 | 304 | ||
| 305 | // TODO compiler crashed when I wrote this the canonical way | 305 | // 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); |
| 404 | 407 | ||
| 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 | } |
| 456 | 462 | ||
| 457 | fn usageAndExit(arg0: []const u8) noreturn { | 463 | fn 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", .{}); |