authorgravatar for leroycepearson@geemili.xyzLeRoyce Pearson <leroycepearson@geemili.xyz> 2020-03-23 21:39:10-06:00
committergravatar for leroycepearson@geemili.xyzLeRoyce Pearson <leroycepearson@geemili.xyz> 2020-03-23 21:39:16-06:00
log113b217593ab5b0369b76251b99a195f361cc220
tree9aa8e8d78304afcc51bef0ace49bb5b3017804f6
parent0b93932a2103b178d3ab5235c837df14173ed38c
parentdc44fe053c609f389e375f6857f96b6bb3794897

Merge branch 'master' into feature-file-locks


107 files changed, 10674 insertions(+), 1748 deletions(-)

CMakeLists.txt-1
...@@ -622,7 +622,6 @@ set(BUILD_LIBSTAGE2_ARGS "build-lib"...@@ -622,7 +622,6 @@ set(BUILD_LIBSTAGE2_ARGS "build-lib"
622 --cache on622 --cache on
623 --output-dir "${CMAKE_BINARY_DIR}"623 --output-dir "${CMAKE_BINARY_DIR}"
624 ${LIBSTAGE2_RELEASE_ARG}624 ${LIBSTAGE2_RELEASE_ARG}
625 --disable-gen-h
626 --bundle-compiler-rt625 --bundle-compiler-rt
627 -fPIC626 -fPIC
628 -lc627 -lc
build.zig+11-6
...@@ -134,7 +134,8 @@ pub fn build(b: *Builder) !void {...@@ -134,7 +134,8 @@ pub fn build(b: *Builder) !void {
134 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));134 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
135 test_step.dependOn(tests.addTranslateCTests(b, test_filter));135 test_step.dependOn(tests.addTranslateCTests(b, test_filter));
136 test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter));136 test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter));
137 test_step.dependOn(tests.addGenHTests(b, test_filter));137 // tests for this feature are disabled until we have the self-hosted compiler available
138 //test_step.dependOn(tests.addGenHTests(b, test_filter));
138 test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));139 test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
139 test_step.dependOn(docs_step);140 test_step.dependOn(docs_step);
140}141}
...@@ -298,10 +299,14 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -298,10 +299,14 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
298 dependOnLib(b, exe, ctx.llvm);299 dependOnLib(b, exe, ctx.llvm);
299300
300 if (exe.target.getOsTag() == .linux) {301 if (exe.target.getOsTag() == .linux) {
301 try addCxxKnownPath(b, ctx, exe, "libstdc++.a",302 // First we try to static link against gcc libstdc++. If that doesn't work,
302 \\Unable to determine path to libstdc++.a303 // we fall back to -lc++ and cross our fingers.
303 \\On Fedora, install libstdc++-static and try again.304 addCxxKnownPath(b, ctx, exe, "libstdc++.a", "") catch |err| switch (err) {
304 );305 error.RequiredLibraryNotFound => {
306 exe.linkSystemLibrary("c++");
307 },
308 else => |e| return e,
309 };
305310
306 exe.linkSystemLibrary("pthread");311 exe.linkSystemLibrary("pthread");
307 } else if (exe.target.isFreeBSD()) {312 } else if (exe.target.isFreeBSD()) {
...@@ -320,7 +325,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -320,7 +325,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
320 // System compiler, not gcc.325 // System compiler, not gcc.
321 exe.linkSystemLibrary("c++");326 exe.linkSystemLibrary("c++");
322 },327 },
323 else => return err,328 else => |e| return e,
324 }329 }
325 }330 }
326331
ci/drone/linux_script+2-1
...@@ -26,7 +26,8 @@ make -j$(nproc) install...@@ -26,7 +26,8 @@ make -j$(nproc) install
26# TODO test-cli is hitting https://github.com/ziglang/zig/issues/352626# TODO test-cli is hitting https://github.com/ziglang/zig/issues/3526
27./zig build test-asm-link test-runtime-safety27./zig build test-asm-link test-runtime-safety
28# TODO test-translate-c is hitting https://github.com/ziglang/zig/issues/352628# TODO test-translate-c is hitting https://github.com/ziglang/zig/issues/3526
29./zig build test-gen-h29# TODO disabled until we are shipping self-hosted
30#./zig build test-gen-h
30# TODO test-compile-errors is hitting https://github.com/ziglang/zig/issues/352631# TODO test-compile-errors is hitting https://github.com/ziglang/zig/issues/3526
31# TODO building docs is hitting https://github.com/ziglang/zig/issues/352632# TODO building docs is hitting https://github.com/ziglang/zig/issues/3526
3233
ci/srht/freebsd_script+2-1
...@@ -42,7 +42,8 @@ release/bin/zig build test-asm-link...@@ -42,7 +42,8 @@ release/bin/zig build test-asm-link
42release/bin/zig build test-runtime-safety42release/bin/zig build test-runtime-safety
43release/bin/zig build test-translate-c43release/bin/zig build test-translate-c
44release/bin/zig build test-run-translated-c44release/bin/zig build test-run-translated-c
45release/bin/zig build test-gen-h45# TODO disabled until we are shipping self-hosted
46#release/bin/zig build test-gen-h
46release/bin/zig build test-compile-errors47release/bin/zig build test-compile-errors
47release/bin/zig build docs48release/bin/zig build docs
4849
doc/docgen.zig+19-3
...@@ -48,7 +48,7 @@ pub fn main() !void {...@@ -48,7 +48,7 @@ pub fn main() !void {
48 var toc = try genToc(allocator, &tokenizer);48 var toc = try genToc(allocator, &tokenizer);
4949
50 try fs.cwd().makePath(tmp_dir_name);50 try fs.cwd().makePath(tmp_dir_name);
51 defer fs.deleteTree(tmp_dir_name) catch {};51 defer fs.cwd().deleteTree(tmp_dir_name) catch {};
5252
53 try genHtml(allocator, &tokenizer, &toc, buffered_out_stream.outStream(), zig_exe);53 try genHtml(allocator, &tokenizer, &toc, buffered_out_stream.outStream(), zig_exe);
54 try buffered_out_stream.flush();54 try buffered_out_stream.flush();
...@@ -1096,6 +1096,9 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1096,6 +1096,9 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1096 try build_args.append("-lc");1096 try build_args.append("-lc");
1097 try out.print(" -lc", .{});1097 try out.print(" -lc", .{});
1098 }1098 }
1099 const target = try std.zig.CrossTarget.parse(.{
1100 .arch_os_abi = code.target_str orelse "native",
1101 });
1099 if (code.target_str) |triple| {1102 if (code.target_str) |triple| {
1100 try build_args.appendSlice(&[_][]const u8{ "-target", triple });1103 try build_args.appendSlice(&[_][]const u8{ "-target", triple });
1101 if (!code.is_inline) {1104 if (!code.is_inline) {
...@@ -1150,7 +1153,15 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1150,7 +1153,15 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1150 }1153 }
1151 }1154 }
11521155
1153 const path_to_exe = mem.trim(u8, exec_result.stdout, " \r\n");1156 const path_to_exe_dir = mem.trim(u8, exec_result.stdout, " \r\n");
1157 const path_to_exe_basename = try std.fmt.allocPrint(allocator, "{}{}", .{
1158 code.name,
1159 target.exeFileExt(),
1160 });
1161 const path_to_exe = try fs.path.join(allocator, &[_][]const u8{
1162 path_to_exe_dir,
1163 path_to_exe_basename,
1164 });
1154 const run_args = &[_][]const u8{path_to_exe};1165 const run_args = &[_][]const u8{path_to_exe};
11551166
1156 var exited_with_signal = false;1167 var exited_with_signal = false;
...@@ -1486,7 +1497,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1486,7 +1497,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1486}1497}
14871498
1488fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u8) !ChildProcess.ExecResult {1499fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u8) !ChildProcess.ExecResult {
1489 const result = try ChildProcess.exec(allocator, args, null, env_map, max_doc_file_size);1500 const result = try ChildProcess.exec2(.{
1501 .allocator = allocator,
1502 .argv = args,
1503 .env_map = env_map,
1504 .max_output_bytes = max_doc_file_size,
1505 });
1490 switch (result.term) {1506 switch (result.term) {
1491 .Exited => |exit_code| {1507 .Exited => |exit_code| {
1492 if (exit_code != 0) {1508 if (exit_code != 0) {
doc/langref.html.in+27-20
...@@ -885,6 +885,12 @@ const hex_int = 0xff;...@@ -885,6 +885,12 @@ const hex_int = 0xff;
885const another_hex_int = 0xFF;885const another_hex_int = 0xFF;
886const octal_int = 0o755;886const octal_int = 0o755;
887const binary_int = 0b11110000;887const binary_int = 0b11110000;
888
889// underscores may be placed between two digits as a visual separator
890const one_billion = 1_000_000_000;
891const binary_mask = 0b1_1111_1111;
892const permissions = 0o7_5_5;
893const big_address = 0xFF80_0000_0000_0000;
888 {#code_end#}894 {#code_end#}
889 {#header_close#}895 {#header_close#}
890 {#header_open|Runtime Integer Values#}896 {#header_open|Runtime Integer Values#}
...@@ -947,6 +953,11 @@ const yet_another = 123.0e+77;...@@ -947,6 +953,11 @@ const yet_another = 123.0e+77;
947const hex_floating_point = 0x103.70p-5;953const hex_floating_point = 0x103.70p-5;
948const another_hex_float = 0x103.70;954const another_hex_float = 0x103.70;
949const yet_another_hex_float = 0x103.70P-5;955const yet_another_hex_float = 0x103.70P-5;
956
957// underscores may be placed between two digits as a visual separator
958const lightspeed = 299_792_458.000_000;
959const nanosecond = 0.000_000_001;
960const more_hex = 0x1234_5678.9ABC_CDEFp-10;
950 {#code_end#}961 {#code_end#}
951 <p>962 <p>
952 There is no syntax for NaN, infinity, or negative infinity. For these special values,963 There is no syntax for NaN, infinity, or negative infinity. For these special values,
...@@ -2093,8 +2104,9 @@ var foo: u8 align(4) = 100;...@@ -2093,8 +2104,9 @@ var foo: u8 align(4) = 100;
2093test "global variable alignment" {2104test "global variable alignment" {
2094 assert(@TypeOf(&foo).alignment == 4);2105 assert(@TypeOf(&foo).alignment == 4);
2095 assert(@TypeOf(&foo) == *align(4) u8);2106 assert(@TypeOf(&foo) == *align(4) u8);
2096 const slice = @as(*[1]u8, &foo)[0..];2107 const as_pointer_to_array: *[1]u8 = &foo;
2097 assert(@TypeOf(slice) == []align(4) u8);2108 const as_slice: []u8 = as_pointer_to_array;
2109 assert(@TypeOf(as_slice) == []align(4) u8);
2098}2110}
20992111
2100fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }2112fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }
...@@ -2187,7 +2199,8 @@ test "basic slices" {...@@ -2187,7 +2199,8 @@ test "basic slices" {
2187 // a slice is that the array's length is part of the type and known at2199 // a slice is that the array's length is part of the type and known at
2188 // compile-time, whereas the slice's length is known at runtime.2200 // compile-time, whereas the slice's length is known at runtime.
2189 // Both can be accessed with the `len` field.2201 // Both can be accessed with the `len` field.
2190 const slice = array[0..array.len];2202 var known_at_runtime_zero: usize = 0;
2203 const slice = array[known_at_runtime_zero..array.len];
2191 assert(&slice[0] == &array[0]);2204 assert(&slice[0] == &array[0]);
2192 assert(slice.len == array.len);2205 assert(slice.len == array.len);
21932206
...@@ -2207,13 +2220,15 @@ test "basic slices" {...@@ -2207,13 +2220,15 @@ test "basic slices" {
2207 {#code_end#}2220 {#code_end#}
2208 <p>This is one reason we prefer slices to pointers.</p>2221 <p>This is one reason we prefer slices to pointers.</p>
2209 {#code_begin|test|slices#}2222 {#code_begin|test|slices#}
2210const assert = @import("std").debug.assert;2223const std = @import("std");
2211const mem = @import("std").mem;2224const assert = std.debug.assert;
2212const fmt = @import("std").fmt;2225const mem = std.mem;
2226const fmt = std.fmt;
22132227
2214test "using slices for strings" {2228test "using slices for strings" {
2215 // Zig has no concept of strings. String literals are arrays of u8, and2229 // Zig has no concept of strings. String literals are const pointers to
2216 // in general the string type is []u8 (slice of u8).2230 // arrays of u8, and by convention parameters that are "strings" are
2231 // expected to be UTF-8 encoded slices of u8.
2217 // Here we coerce [5]u8 to []const u82232 // Here we coerce [5]u8 to []const u8
2218 const hello: []const u8 = "hello";2233 const hello: []const u8 = "hello";
2219 const world: []const u8 = "世界";2234 const world: []const u8 = "世界";
...@@ -2222,7 +2237,7 @@ test "using slices for strings" {...@@ -2222,7 +2237,7 @@ test "using slices for strings" {
2222 // You can use slice syntax on an array to convert an array into a slice.2237 // You can use slice syntax on an array to convert an array into a slice.
2223 const all_together_slice = all_together[0..];2238 const all_together_slice = all_together[0..];
2224 // String concatenation example.2239 // String concatenation example.
2225 const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", .{hello, world});2240 const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", .{ hello, world });
22262241
2227 // Generally, you can use UTF-8 and not worry about whether something is a2242 // Generally, you can use UTF-8 and not worry about whether something is a
2228 // string. If you don't need to deal with individual characters, no need2243 // string. If you don't need to deal with individual characters, no need
...@@ -2239,23 +2254,15 @@ test "slice pointer" {...@@ -2239,23 +2254,15 @@ test "slice pointer" {
2239 slice[2] = 3;2254 slice[2] = 3;
2240 assert(slice[2] == 3);2255 assert(slice[2] == 3);
2241 // The slice is mutable because we sliced a mutable pointer.2256 // The slice is mutable because we sliced a mutable pointer.
2242 assert(@TypeOf(slice) == []u8);2257 // Furthermore, it is actually a pointer to an array, since the start
2258 // and end indexes were both comptime-known.
2259 assert(@TypeOf(slice) == *[5]u8);
22432260
2244 // You can also slice a slice:2261 // You can also slice a slice:
2245 const slice2 = slice[2..3];2262 const slice2 = slice[2..3];
2246 assert(slice2.len == 1);2263 assert(slice2.len == 1);
2247 assert(slice2[0] == 3);2264 assert(slice2[0] == 3);
2248}2265}
2249
2250test "slice widening" {
2251 // Zig supports slice widening and slice narrowing. Cast a slice of u8
2252 // to a slice of anything else, and Zig will perform the length conversion.
2253 const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
2254 const slice = mem.bytesAsSlice(u32, array[0..]);
2255 assert(slice.len == 2);
2256 assert(slice[0] == 0x12121212);
2257 assert(slice[1] == 0x13131313);
2258}
2259 {#code_end#}2266 {#code_end#}
2260 {#see_also|Pointers|for|Arrays#}2267 {#see_also|Pointers|for|Arrays#}
22612268
lib/libc/glibc/abi.txt+135
...@@ -193,6 +193,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -193,6 +193,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
193193
194194
1952919529
196
1962919729
197198
1982919929
...@@ -514,6 +515,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -514,6 +515,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
5142951529
5152951629
5162951729
51829
517519
5182952029
519521
...@@ -697,6 +699,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -697,6 +699,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
6972969929
6982970029
6992970129
702
7002970329
7012970429
7022970529
...@@ -819,6 +822,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -819,6 +822,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
8192982229
8202982329
8212982429
82529
822826
8232982729
8242982829
...@@ -904,6 +908,9 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -904,6 +908,9 @@ aarch64-linux-gnu aarch64_be-linux-gnu
9042990829
9052990929
9062991029
91129
912
913
9072991429
9082991529
9092991629
...@@ -1004,6 +1011,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -1004,6 +1011,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
100429101129
100529101229
100629101329
101429
10071015
100829101629
100929101729
...@@ -1033,6 +1041,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu...@@ -1033,6 +1041,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
103329104129
103429104229
103529104329
104429
10361045
103729104629
103829104729
...@@ -3920,6 +3929,7 @@ s390x-linux-gnu...@@ -3920,6 +3929,7 @@ s390x-linux-gnu
39203929
39213930
3922539315
3932
392327393327
39243934
392527393527
...@@ -4241,6 +4251,7 @@ s390x-linux-gnu...@@ -4241,6 +4251,7 @@ s390x-linux-gnu
4241542515
4242542525
4243542535
42545
424411425511
424527425627
42464257
...@@ -4424,6 +4435,7 @@ s390x-linux-gnu...@@ -4424,6 +4435,7 @@ s390x-linux-gnu
442419443519
442519443619
4426544375
4438
4427544395
4428544405
442928444128
...@@ -4543,6 +4555,7 @@ s390x-linux-gnu...@@ -4543,6 +4555,7 @@ s390x-linux-gnu
454327455527
45444556
454516455716
4558
4546545595
4547545605
454815456115
...@@ -4631,6 +4644,9 @@ s390x-linux-gnu...@@ -4631,6 +4644,9 @@ s390x-linux-gnu
463116464416
4632546455
4633546465
4647
4648
464912
4634546505
4635546515
4636546525
...@@ -4731,6 +4747,7 @@ s390x-linux-gnu...@@ -4731,6 +4747,7 @@ s390x-linux-gnu
4731547475
4732547485
4733547495
47505
47344751
4735547525
4736547535
...@@ -4756,6 +4773,7 @@ s390x-linux-gnu...@@ -4756,6 +4773,7 @@ s390x-linux-gnu
4756547735
4757547745
4758547755
47765
475931 5477731 5
476024 5 12 16477824 5 12 16
476124 5 12 16477924 5 12 16
...@@ -7645,6 +7663,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -7645,6 +7663,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
76457663
76467664
76477665
7666
76487667
76497668
765027766927
...@@ -7968,6 +7987,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -7968,6 +7987,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
796816798716
796916798816
797016798916
799016
79717991
797227799227
79737993
...@@ -8151,6 +8171,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -8151,6 +8171,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
815119817119
815219817219
815316817316
8174
815416817516
815516817616
815628817728
...@@ -8273,6 +8294,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -8273,6 +8294,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
827316829416
827416829516
827516829616
829716
82768298
827716829916
827816830016
...@@ -8358,6 +8380,9 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -8358,6 +8380,9 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
835816838016
835916838116
836016838216
838316
8384
8385
836116838616
836216838716
836316838816
...@@ -8458,6 +8483,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -8458,6 +8483,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
845816848316
845916848416
846016848516
848616
84618487
846216848816
846316848916
...@@ -8484,6 +8510,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf...@@ -8484,6 +8510,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
848416851016
848516851116
848616851216
851316
848724 16851424 16
848824 16851524 16
848916851616
...@@ -11374,6 +11401,7 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -11374,6 +11401,7 @@ sparc-linux-gnu sparcel-linux-gnu
1137411401
1137511402
113760114030
11404
11377271140527
1137811406
11379271140727
...@@ -11693,6 +11721,7 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -11693,6 +11721,7 @@ sparc-linux-gnu sparcel-linux-gnu
116930117210
116940117220
116951117231
117241
116960117250
116970117260
116983 11117273 11
...@@ -11878,6 +11907,7 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -11878,6 +11907,7 @@ sparc-linux-gnu sparcel-linux-gnu
11878191190719
11879191190819
118800119090
11910
118810119110
118821119121
11883281191328
...@@ -11997,6 +12027,7 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -11997,6 +12027,7 @@ sparc-linux-gnu sparcel-linux-gnu
11997331202733
1199812028
11999161202916
12030
120005120315
120010120320
12002151203315
...@@ -12085,6 +12116,9 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -12085,6 +12116,9 @@ sparc-linux-gnu sparcel-linux-gnu
12085161211616
120860121170
120870121180
1211912
12120
12121
120881121221
120891121231
120901121241
...@@ -12183,6 +12217,7 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -12183,6 +12217,7 @@ sparc-linux-gnu sparcel-linux-gnu
121831122171
121841122181
121851122191
122201
121860122210
121870122220
1218812223
...@@ -12207,6 +12242,7 @@ sparc-linux-gnu sparcel-linux-gnu...@@ -12207,6 +12242,7 @@ sparc-linux-gnu sparcel-linux-gnu
122070122420
122080122430
122090122440
122450
122105122465
122110122470
122120122480
...@@ -15101,6 +15137,7 @@ sparcv9-linux-gnu...@@ -15101,6 +15137,7 @@ sparcv9-linux-gnu
151015151375
151025151385
1510315139
15140
15104271514127
1510515142
15106271514327
...@@ -15422,6 +15459,7 @@ sparcv9-linux-gnu...@@ -15422,6 +15459,7 @@ sparcv9-linux-gnu
154225154595
154235154605
154245154615
154625
15425111546311
15426271546427
1542715465
...@@ -15605,6 +15643,7 @@ sparcv9-linux-gnu...@@ -15605,6 +15643,7 @@ sparcv9-linux-gnu
15605191564319
15606191564419
156075156455
15646
156085156475
156095156485
15610281564928
...@@ -15724,6 +15763,7 @@ sparcv9-linux-gnu...@@ -15724,6 +15763,7 @@ sparcv9-linux-gnu
15724271576327
1572515764
15726161576516
15766
157275157675
157285157685
15729151576915
...@@ -15812,6 +15852,9 @@ sparcv9-linux-gnu...@@ -15812,6 +15852,9 @@ sparcv9-linux-gnu
15812161585216
158135158535
158145158545
1585512
15856
15857
158155158585
158165158595
158175158605
...@@ -15912,6 +15955,7 @@ sparcv9-linux-gnu...@@ -15912,6 +15955,7 @@ sparcv9-linux-gnu
159125159555
159135159565
159145159575
159585
1591515959
159165159605
159175159615
...@@ -15938,6 +15982,7 @@ sparcv9-linux-gnu...@@ -15938,6 +15982,7 @@ sparcv9-linux-gnu
159385159825
159395159835
159405159845
159855
1594124 28 5 12 161598624 28 5 12 16
1594224 28 5 12 161598724 28 5 12 16
159435 14159885 14
...@@ -18828,6 +18873,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -18828,6 +18873,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
1882818873
1882918874
188300188750
18876
18831271887727
1883218878
18833271887927
...@@ -19147,6 +19193,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -19147,6 +19193,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
191470191930
191480191940
191495191955
191965
191500191970
191510191980
19152111919911
...@@ -19332,6 +19379,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -19332,6 +19379,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19332191937919
19333191938019
193340193810
19382
193350193830
193365193845
19337281938528
...@@ -19450,6 +19498,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -19450,6 +19498,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19450271949827
19451271949927
1945219500
1950116
19453161950216
194545195035
194550195040
...@@ -19539,6 +19588,9 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -19539,6 +19588,9 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19539161958816
195400195890
195410195900
1959112
19592
19593
195425195945
195435195955
195445195965
...@@ -19637,6 +19689,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -19637,6 +19689,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
196375196895
196385196905
196395196915
196925
196400196930
196410196940
196420196950
...@@ -19661,6 +19714,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64...@@ -19661,6 +19714,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
196610197140
196620197150
196630197160
197170
196645197185
196650197190
196660197200
...@@ -22555,6 +22609,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -22555,6 +22609,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
2255522609
2255622610
225570226110
22612
22558272261327
2255922614
22560272261527
...@@ -22874,6 +22929,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -22874,6 +22929,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
228740229290
228750229300
228765229315
229325
228770229330
228780229340
22879112293511
...@@ -23059,6 +23115,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -23059,6 +23115,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
23059192311519
23060192311619
230610231170
23118
230620231190
230635231205
23064282312128
...@@ -23177,6 +23234,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -23177,6 +23234,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
23177272323427
23178272323527
2317923236
2323716
23180162323816
231815232395
231820232400
...@@ -23266,6 +23324,9 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -23266,6 +23324,9 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
23266162332416
232670233250
232680233260
2332712
23328
23329
232695233305
232705233315
232715233325
...@@ -23364,6 +23425,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -23364,6 +23425,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
233645234255
233655234265
233665234275
234285
233670234290
233680234300
233690234310
...@@ -23388,6 +23450,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32...@@ -23388,6 +23450,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
233880234500
233890234510
233900234520
234530
233915234545
233920234550
233930234560
...@@ -26282,6 +26345,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -26282,6 +26345,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
2628226345
2628326346
262840263470
26348
26285272634927
2628626350
26287272635127
...@@ -26601,6 +26665,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -26601,6 +26665,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
266010266650
266020266660
266035266675
266685
266040266690
266050266700
26606112667111
...@@ -26786,6 +26851,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -26786,6 +26851,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
26786192685119
26787192685219
267880268530
26854
267890268550
267905268565
26791282685728
...@@ -26904,6 +26970,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -26904,6 +26970,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
26904272697027
2690526971
2690626972
2697316
26907162697416
269085269755
269090269760
...@@ -26993,6 +27060,9 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -26993,6 +27060,9 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
26993162706016
269940270610
269950270620
2706312
27064
27065
269965270665
269975270675
269985270685
...@@ -27091,6 +27161,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -27091,6 +27161,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
270915271615
270925271625
270935271635
271645
270940271650
270950271660
270960271670
...@@ -27115,6 +27186,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf...@@ -27115,6 +27186,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
271150271860
271160271870
271170271880
271890
271185271905
271190271910
271200271920
...@@ -30009,6 +30081,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30009,6 +30081,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
3000930081
3001030082
300110300830
30084
30012273008527
3001330086
30014273008727
...@@ -30328,6 +30401,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30328,6 +30401,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
303280304010
303290304020
303305304035
304045
303310304050
303320304060
30333113040711
...@@ -30513,6 +30587,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30513,6 +30587,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
30513193058719
30514193058819
305150305890
30590
305160305910
305175305925
30518283059328
...@@ -30631,6 +30706,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30631,6 +30706,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
30631273070627
3063230707
3063330708
3070916
30634163071016
306355307115
306360307120
...@@ -30720,6 +30796,9 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30720,6 +30796,9 @@ mipsel-linux-gnueabi mips-linux-gnueabi
30720163079616
307210307970
307220307980
3079912
30800
30801
307235308025
307245308035
307255308045
...@@ -30818,6 +30897,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30818,6 +30897,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
308185308975
308195308985
308205308995
309005
308210309010
308220309020
308230309030
...@@ -30842,6 +30922,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi...@@ -30842,6 +30922,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
308420309220
308430309230
308440309240
309250
308455309265
308460309270
308470309280
...@@ -33734,6 +33815,7 @@ x86_64-linux-gnu...@@ -33734,6 +33815,7 @@ x86_64-linux-gnu
3373433815
3373533816
3373633817
33818
3373733819
3373833820
33739273382127
...@@ -34057,6 +34139,7 @@ x86_64-linux-gnu...@@ -34057,6 +34139,7 @@ x86_64-linux-gnu
34057103413910
34058103414010
34059103414110
3414210
34060113414311
34061273414427
34062363414536
...@@ -34240,6 +34323,7 @@ x86_64-linux-gnu...@@ -34240,6 +34323,7 @@ x86_64-linux-gnu
34240193432319
34241193432419
34242103432510
34326
34243103432710
34244103432810
34245283432928
...@@ -34359,6 +34443,7 @@ x86_64-linux-gnu...@@ -34359,6 +34443,7 @@ x86_64-linux-gnu
34359273444327
3436034444
34361163444516
34446
34362103444710
34363103444810
34364153444915
...@@ -34447,6 +34532,9 @@ x86_64-linux-gnu...@@ -34447,6 +34532,9 @@ x86_64-linux-gnu
34447163453216
34448103453310
34449103453410
3453512
34536
34537
34450103453810
34451103453910
34452103454010
...@@ -34547,6 +34635,7 @@ x86_64-linux-gnu...@@ -34547,6 +34635,7 @@ x86_64-linux-gnu
34547103463510
34548103463610
34549103463710
3463810
3455034639
34551103464010
34552103464110
...@@ -34573,6 +34662,7 @@ x86_64-linux-gnu...@@ -34573,6 +34662,7 @@ x86_64-linux-gnu
34573103466210
34574103466310
34575103466410
3466510
3457624 10 12 163466624 10 12 16
3457724 10 12 163466724 10 12 16
3457810 143466810 14
...@@ -37461,6 +37551,7 @@ x86_64-linux-gnux32...@@ -37461,6 +37551,7 @@ x86_64-linux-gnux32
3746137551
3746237552
3746337553
37554
3746437555
3746537556
37466283755728
...@@ -37784,6 +37875,7 @@ x86_64-linux-gnux32...@@ -37784,6 +37875,7 @@ x86_64-linux-gnux32
37784283787528
37785283787628
37786283787728
3787828
3778737879
37788283788028
37789363788136
...@@ -37967,6 +38059,7 @@ x86_64-linux-gnux32...@@ -37967,6 +38059,7 @@ x86_64-linux-gnux32
37967283805928
37968283806028
37969283806128
38062
37970283806328
37971283806428
37972283806528
...@@ -38086,6 +38179,7 @@ x86_64-linux-gnux32...@@ -38086,6 +38179,7 @@ x86_64-linux-gnux32
38086283817928
3808738180
38088283818128
38182
38089283818328
38090283818428
38091283818528
...@@ -38174,6 +38268,9 @@ x86_64-linux-gnux32...@@ -38174,6 +38268,9 @@ x86_64-linux-gnux32
38174283826828
38175283826928
38176283827028
3827128
38272
38273
38177283827428
38178283827528
38179283827628
...@@ -38274,6 +38371,7 @@ x86_64-linux-gnux32...@@ -38274,6 +38371,7 @@ x86_64-linux-gnux32
38274283837128
38275283837228
38276283837328
3837428
3827738375
38278283837628
38279283837728
...@@ -38303,6 +38401,7 @@ x86_64-linux-gnux32...@@ -38303,6 +38401,7 @@ x86_64-linux-gnux32
38303283840128
38304283840228
38305283840328
3840428
3830638405
38307283840628
38308283840728
...@@ -41190,6 +41289,7 @@ i386-linux-gnu...@@ -41190,6 +41289,7 @@ i386-linux-gnu
4119041289
4119141290
411920412910
4129212
41193274129327
41194364129436
41195274129527
...@@ -41509,6 +41609,7 @@ i386-linux-gnu...@@ -41509,6 +41609,7 @@ i386-linux-gnu
415090416090
415100416100
415111416111
416121
415120416130
415130416140
415143 11416153 11
...@@ -41694,6 +41795,7 @@ i386-linux-gnu...@@ -41694,6 +41795,7 @@ i386-linux-gnu
41694194179519
41695194179619
416960417970
41798
416970417990
416981418001
41699284180128
...@@ -41813,6 +41915,7 @@ i386-linux-gnu...@@ -41813,6 +41915,7 @@ i386-linux-gnu
41813274191527
4181441916
41815164191716
41918
418165419195
418170419200
41818154192115
...@@ -41901,6 +42004,9 @@ i386-linux-gnu...@@ -41901,6 +42004,9 @@ i386-linux-gnu
41901164200416
419020420050
419030420060
4200712
42008
42009
419041420101
419051420111
419061420121
...@@ -41999,6 +42105,7 @@ i386-linux-gnu...@@ -41999,6 +42105,7 @@ i386-linux-gnu
419991421051
420001421061
420011421071
421081
420020421090
420030421100
4200442111
...@@ -42023,6 +42130,7 @@ i386-linux-gnu...@@ -42023,6 +42130,7 @@ i386-linux-gnu
420230421300
420240421310
420250421320
421330
420265421345
420270421350
420280421360
...@@ -44915,6 +45023,7 @@ powerpc64le-linux-gnu...@@ -44915,6 +45023,7 @@ powerpc64le-linux-gnu
4491545023
4491645024
4491745025
45026
4491845027
4491945028
44920294502929
...@@ -45238,6 +45347,7 @@ powerpc64le-linux-gnu...@@ -45238,6 +45347,7 @@ powerpc64le-linux-gnu
45238294534729
45239294534829
45240294534929
4535029
4524145351
45242294535229
45243364535336
...@@ -45421,6 +45531,7 @@ powerpc64le-linux-gnu...@@ -45421,6 +45531,7 @@ powerpc64le-linux-gnu
45421294553129
45422294553229
45423294553329
4553433
45424294553529
45425294553629
45426294553729
...@@ -45540,6 +45651,7 @@ powerpc64le-linux-gnu...@@ -45540,6 +45651,7 @@ powerpc64le-linux-gnu
45540294565129
4554145652
45542294565329
45654
45543294565529
45544294565629
45545294565729
...@@ -45628,6 +45740,9 @@ powerpc64le-linux-gnu...@@ -45628,6 +45740,9 @@ powerpc64le-linux-gnu
45628294574029
45629294574129
45630294574229
4574329
4574432
45745
45631294574629
45632294574729
45633294574829
...@@ -45728,6 +45843,7 @@ powerpc64le-linux-gnu...@@ -45728,6 +45843,7 @@ powerpc64le-linux-gnu
45728294584329
45729294584429
45730294584529
4584629
4573145847
45732294584829
45733294584929
...@@ -45757,6 +45873,7 @@ powerpc64le-linux-gnu...@@ -45757,6 +45873,7 @@ powerpc64le-linux-gnu
45757294587329
45758294587429
45759294587529
4587629
4576045877
45761294587829
45762294587929
...@@ -48642,6 +48759,7 @@ powerpc64-linux-gnu...@@ -48642,6 +48759,7 @@ powerpc64-linux-gnu
4864248759
4864348760
4864448761
48762
4864548763
4864648764
48647274876527
...@@ -48965,6 +49083,7 @@ powerpc64-linux-gnu...@@ -48965,6 +49083,7 @@ powerpc64-linux-gnu
48965124908312
48966124908412
48967124908512
4908612
4896849087
48969274908827
4897049089
...@@ -49148,6 +49267,7 @@ powerpc64-linux-gnu...@@ -49148,6 +49267,7 @@ powerpc64-linux-gnu
49148194926719
49149194926819
49150124926912
4927033
49151124927112
49152124927212
49153284927328
...@@ -49267,6 +49387,7 @@ powerpc64-linux-gnu...@@ -49267,6 +49387,7 @@ powerpc64-linux-gnu
49267274938727
4926849388
49269164938916
49390
49270124939112
49271124939212
49272154939315
...@@ -49355,6 +49476,9 @@ powerpc64-linux-gnu...@@ -49355,6 +49476,9 @@ powerpc64-linux-gnu
49355164947616
49356124947712
49357124947812
4947912
4948032
49481
49358124948212
49359124948312
49360124948412
...@@ -49455,6 +49579,7 @@ powerpc64-linux-gnu...@@ -49455,6 +49579,7 @@ powerpc64-linux-gnu
49455124957912
49456124958012
49457124958112
4958212
4945849583
49459124958412
49460124958512
...@@ -49480,6 +49605,7 @@ powerpc64-linux-gnu...@@ -49480,6 +49605,7 @@ powerpc64-linux-gnu
49480124960512
49481124960612
49482124960712
4960812
4948312 154960912 15
4948424 12 164961024 12 16
4948524 12 164961124 12 16
...@@ -52369,6 +52495,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -52369,6 +52495,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
5236952495
5237052496
5237152497
52498
5237252499
5237352500
52374275250127
...@@ -52690,6 +52817,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -52690,6 +52817,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
526900528170
526910528180
526921528191
528201
526930528210
526940528220
526953 11528233 11
...@@ -52875,6 +53003,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -52875,6 +53003,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
52875195300319
52876195300419
528770530050
5300633
528780530070
528791530081
52880285300928
...@@ -52994,6 +53123,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -52994,6 +53123,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
52994275312327
52995135312413
52996165312516
53126
529975531275
529980531280
52999155312915
...@@ -53082,6 +53212,9 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -53082,6 +53212,9 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
53082165321216
530830532130
530840532140
5321512
5321632
53217
530851532181
530861532191
530871532201
...@@ -53180,6 +53313,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -53180,6 +53313,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
531801533131
531811533141
531821533151
533161
531830533170
531840533180
5318553319
...@@ -53204,6 +53338,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf...@@ -53204,6 +53338,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
532040533380
532050533390
532060533400
533410
532075533425
532080533430
532090533440
lib/libc/glibc/fns.txt+9
...@@ -192,6 +192,7 @@ _Qp_uitoq c...@@ -192,6 +192,7 @@ _Qp_uitoq c
192_Qp_uxtoq c192_Qp_uxtoq c
193_Qp_xtoq c193_Qp_xtoq c
194___brk_addr c194___brk_addr c
195___tls_get_addr ld
195__acos_finite m196__acos_finite m
196__acosf128_finite m197__acosf128_finite m
197__acosf_finite m198__acosf_finite m
...@@ -511,6 +512,7 @@ __libc_memalign c...@@ -511,6 +512,7 @@ __libc_memalign c
511__libc_pvalloc c512__libc_pvalloc c
512__libc_realloc c513__libc_realloc c
513__libc_sa_len c514__libc_sa_len c
515__libc_stack_end ld
514__libc_start_main c516__libc_start_main c
515__libc_valloc c517__libc_valloc c
516__libpthread_version_placeholder pthread518__libpthread_version_placeholder pthread
...@@ -696,6 +698,7 @@ __open_2 c...@@ -696,6 +698,7 @@ __open_2 c
696__openat64_2 c698__openat64_2 c
697__openat_2 c699__openat_2 c
698__overflow c700__overflow c
701__parse_hwcap_and_convert_at_platform ld
699__pipe c702__pipe c
700__poll c703__poll c
701__poll_chk c704__poll_chk c
...@@ -815,6 +818,7 @@ __sqrtf_finite m...@@ -815,6 +818,7 @@ __sqrtf_finite m
815__sqrtl_finite m818__sqrtl_finite m
816__sqrtsf2 c819__sqrtsf2 c
817__stack_chk_fail c820__stack_chk_fail c
821__stack_chk_guard ld
818__statfs c822__statfs c
819__stpcpy c823__stpcpy c
820__stpcpy_chk c824__stpcpy_chk c
...@@ -903,6 +907,9 @@ __sysctl c...@@ -903,6 +907,9 @@ __sysctl c
903__syslog_chk c907__syslog_chk c
904__sysv_signal c908__sysv_signal c
905__timezone c909__timezone c
910__tls_get_addr ld
911__tls_get_addr_opt ld
912__tls_get_offset ld
906__toascii_l c913__toascii_l c
907__tolower_l c914__tolower_l c
908__toupper_l c915__toupper_l c
...@@ -999,6 +1006,7 @@ __ynf128_finite m...@@ -999,6 +1006,7 @@ __ynf128_finite m
999__ynf_finite m1006__ynf_finite m
1000__ynl_finite m1007__ynl_finite m
1001_authenticate c1008_authenticate c
1009_dl_mcount ld
1002_dl_mcount_wrapper c1010_dl_mcount_wrapper c
1003_dl_mcount_wrapper_check c1011_dl_mcount_wrapper_check c
1004_environ c1012_environ c
...@@ -1024,6 +1032,7 @@ _pthread_cleanup_pop pthread...@@ -1024,6 +1032,7 @@ _pthread_cleanup_pop pthread
1024_pthread_cleanup_pop_restore pthread1032_pthread_cleanup_pop_restore pthread
1025_pthread_cleanup_push pthread1033_pthread_cleanup_push pthread
1026_pthread_cleanup_push_defer pthread1034_pthread_cleanup_push_defer pthread
1035_r_debug ld
1027_res c1036_res c
1028_res_hconf c1037_res_hconf c
1029_rpc_dtablesize c1038_rpc_dtablesize c
lib/std/build.zig+35-23
...@@ -377,7 +377,7 @@ pub const Builder = struct {...@@ -377,7 +377,7 @@ pub const Builder = struct {
377 if (self.verbose) {377 if (self.verbose) {
378 warn("rm {}\n", .{full_path});378 warn("rm {}\n", .{full_path});
379 }379 }
380 fs.deleteTree(full_path) catch {};380 fs.cwd().deleteTree(full_path) catch {};
381 }381 }
382382
383 // TODO remove empty directories383 // TODO remove empty directories
...@@ -847,7 +847,8 @@ pub const Builder = struct {...@@ -847,7 +847,8 @@ pub const Builder = struct {
847 if (self.verbose) {847 if (self.verbose) {
848 warn("cp {} {} ", .{ source_path, dest_path });848 warn("cp {} {} ", .{ source_path, dest_path });
849 }849 }
850 const prev_status = try fs.updateFile(source_path, dest_path);850 const cwd = fs.cwd();
851 const prev_status = try fs.Dir.updateFile(cwd, source_path, cwd, dest_path, .{});
851 if (self.verbose) switch (prev_status) {852 if (self.verbose) switch (prev_status) {
852 .stale => warn("# installed\n", .{}),853 .stale => warn("# installed\n", .{}),
853 .fresh => warn("# up-to-date\n", .{}),854 .fresh => warn("# up-to-date\n", .{}),
...@@ -1120,7 +1121,7 @@ pub const LibExeObjStep = struct {...@@ -1120,7 +1121,7 @@ pub const LibExeObjStep = struct {
1120 emit_llvm_ir: bool = false,1121 emit_llvm_ir: bool = false,
1121 emit_asm: bool = false,1122 emit_asm: bool = false,
1122 emit_bin: bool = true,1123 emit_bin: bool = true,
1123 disable_gen_h: bool,1124 emit_h: bool = false,
1124 bundle_compiler_rt: bool,1125 bundle_compiler_rt: bool,
1125 disable_stack_probing: bool,1126 disable_stack_probing: bool,
1126 disable_sanitize_c: bool,1127 disable_sanitize_c: bool,
...@@ -1157,8 +1158,14 @@ pub const LibExeObjStep = struct {...@@ -1157,8 +1158,14 @@ pub const LibExeObjStep = struct {
11571158
1158 valgrind_support: ?bool = null,1159 valgrind_support: ?bool = null,
11591160
1161 /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
1162 /// file.
1160 link_eh_frame_hdr: bool = false,1163 link_eh_frame_hdr: bool = false,
11611164
1165 /// Place every function in its own section so that unused ones may be
1166 /// safely garbage-collected during the linking phase.
1167 link_function_sections: bool = false,
1168
1162 /// Uses system Wine installation to run cross compiled Windows build artifacts.1169 /// Uses system Wine installation to run cross compiled Windows build artifacts.
1163 enable_wine: bool = false,1170 enable_wine: bool = false,
11641171
...@@ -1274,7 +1281,6 @@ pub const LibExeObjStep = struct {...@@ -1274,7 +1281,6 @@ pub const LibExeObjStep = struct {
1274 .exec_cmd_args = null,1281 .exec_cmd_args = null,
1275 .name_prefix = "",1282 .name_prefix = "",
1276 .filter = null,1283 .filter = null,
1277 .disable_gen_h = false,
1278 .bundle_compiler_rt = false,1284 .bundle_compiler_rt = false,
1279 .disable_stack_probing = false,1285 .disable_stack_probing = false,
1280 .disable_sanitize_c = false,1286 .disable_sanitize_c = false,
...@@ -1593,8 +1599,9 @@ pub const LibExeObjStep = struct {...@@ -1593,8 +1599,9 @@ pub const LibExeObjStep = struct {
1593 self.main_pkg_path = dir_path;1599 self.main_pkg_path = dir_path;
1594 }1600 }
15951601
1596 pub fn setDisableGenH(self: *LibExeObjStep, value: bool) void {1602 /// Deprecated; just set the field directly.
1597 self.disable_gen_h = value;1603 pub fn setDisableGenH(self: *LibExeObjStep, is_disabled: bool) void {
1604 self.emit_h = !is_disabled;
1598 }1605 }
15991606
1600 pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void {1607 pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void {
...@@ -1625,7 +1632,7 @@ pub const LibExeObjStep = struct {...@@ -1625,7 +1632,7 @@ pub const LibExeObjStep = struct {
1625 /// the make step, from a step that has declared a dependency on this one.1632 /// the make step, from a step that has declared a dependency on this one.
1626 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {1633 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
1627 assert(self.kind != Kind.Exe);1634 assert(self.kind != Kind.Exe);
1628 assert(!self.disable_gen_h);1635 assert(self.emit_h);
1629 return fs.path.join(1636 return fs.path.join(
1630 self.builder.allocator,1637 self.builder.allocator,
1631 &[_][]const u8{ self.output_dir.?, self.out_h_filename },1638 &[_][]const u8{ self.output_dir.?, self.out_h_filename },
...@@ -1672,7 +1679,7 @@ pub const LibExeObjStep = struct {...@@ -1672,7 +1679,7 @@ pub const LibExeObjStep = struct {
1672 }1679 }
16731680
1674 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {1681 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
1675 const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream;1682 const out = self.build_options_contents.outStream();
1676 out.print("pub const {} = {};\n", .{ name, value }) catch unreachable;1683 out.print("pub const {} = {};\n", .{ name, value }) catch unreachable;
1677 }1684 }
16781685
...@@ -1877,6 +1884,7 @@ pub const LibExeObjStep = struct {...@@ -1877,6 +1884,7 @@ pub const LibExeObjStep = struct {
1877 if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");1884 if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");
1878 if (self.emit_asm) try zig_args.append("-femit-asm");1885 if (self.emit_asm) try zig_args.append("-femit-asm");
1879 if (!self.emit_bin) try zig_args.append("-fno-emit-bin");1886 if (!self.emit_bin) try zig_args.append("-fno-emit-bin");
1887 if (self.emit_h) try zig_args.append("-femit-h");
18801888
1881 if (self.strip) {1889 if (self.strip) {
1882 try zig_args.append("--strip");1890 try zig_args.append("--strip");
...@@ -1884,7 +1892,9 @@ pub const LibExeObjStep = struct {...@@ -1884,7 +1892,9 @@ pub const LibExeObjStep = struct {
1884 if (self.link_eh_frame_hdr) {1892 if (self.link_eh_frame_hdr) {
1885 try zig_args.append("--eh-frame-hdr");1893 try zig_args.append("--eh-frame-hdr");
1886 }1894 }
18871895 if (self.link_function_sections) {
1896 try zig_args.append("-ffunction-sections");
1897 }
1888 if (self.single_threaded) {1898 if (self.single_threaded) {
1889 try zig_args.append("--single-threaded");1899 try zig_args.append("--single-threaded");
1890 }1900 }
...@@ -1920,9 +1930,6 @@ pub const LibExeObjStep = struct {...@@ -1920,9 +1930,6 @@ pub const LibExeObjStep = struct {
1920 if (self.is_dynamic) {1930 if (self.is_dynamic) {
1921 try zig_args.append("-dynamic");1931 try zig_args.append("-dynamic");
1922 }1932 }
1923 if (self.disable_gen_h) {
1924 try zig_args.append("--disable-gen-h");
1925 }
1926 if (self.bundle_compiler_rt) {1933 if (self.bundle_compiler_rt) {
1927 try zig_args.append("--bundle-compiler-rt");1934 try zig_args.append("--bundle-compiler-rt");
1928 }1935 }
...@@ -2060,7 +2067,7 @@ pub const LibExeObjStep = struct {...@@ -2060,7 +2067,7 @@ pub const LibExeObjStep = struct {
2060 try zig_args.append("-isystem");2067 try zig_args.append("-isystem");
2061 try zig_args.append(self.builder.pathFromRoot(include_path));2068 try zig_args.append(self.builder.pathFromRoot(include_path));
2062 },2069 },
2063 .OtherStep => |other| if (!other.disable_gen_h) {2070 .OtherStep => |other| if (other.emit_h) {
2064 const h_path = other.getOutputHPath();2071 const h_path = other.getOutputHPath();
2065 try zig_args.append("-isystem");2072 try zig_args.append("-isystem");
2066 try zig_args.append(fs.path.dirname(h_path).?);2073 try zig_args.append(fs.path.dirname(h_path).?);
...@@ -2144,17 +2151,22 @@ pub const LibExeObjStep = struct {...@@ -2144,17 +2151,22 @@ pub const LibExeObjStep = struct {
2144 try zig_args.append("--cache");2151 try zig_args.append("--cache");
2145 try zig_args.append("on");2152 try zig_args.append("on");
21462153
2147 const output_path_nl = try builder.execFromStep(zig_args.toSliceConst(), &self.step);2154 const output_dir_nl = try builder.execFromStep(zig_args.toSliceConst(), &self.step);
2148 const output_path = mem.trimRight(u8, output_path_nl, "\r\n");2155 const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n");
21492156
2150 if (self.output_dir) |output_dir| {2157 if (self.output_dir) |output_dir| {
2151 const full_dest = try fs.path.join(builder.allocator, &[_][]const u8{2158 var src_dir = try std.fs.cwd().openDir(build_output_dir, .{ .iterate = true });
2152 output_dir,2159 defer src_dir.close();
2153 fs.path.basename(output_path),2160
2154 });2161 var dest_dir = try std.fs.cwd().openDir(output_dir, .{});
2155 try builder.updateFile(output_path, full_dest);2162 defer dest_dir.close();
2163
2164 var it = src_dir.iterate();
2165 while (try it.next()) |entry| {
2166 _ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{});
2167 }
2156 } else {2168 } else {
2157 self.output_dir = fs.path.dirname(output_path).?;2169 self.output_dir = build_output_dir;
2158 }2170 }
2159 }2171 }
21602172
...@@ -2195,7 +2207,7 @@ const InstallArtifactStep = struct {...@@ -2195,7 +2207,7 @@ const InstallArtifactStep = struct {
2195 break :blk InstallDir.Lib;2207 break :blk InstallDir.Lib;
2196 }2208 }
2197 } else null,2209 } else null,
2198 .h_dir = if (artifact.kind == .Lib and !artifact.disable_gen_h) .Header else null,2210 .h_dir = if (artifact.kind == .Lib and artifact.emit_h) .Header else null,
2199 };2211 };
2200 self.step.dependOn(&artifact.step);2212 self.step.dependOn(&artifact.step);
2201 artifact.install_step = self;2213 artifact.install_step = self;
...@@ -2352,7 +2364,7 @@ pub const RemoveDirStep = struct {...@@ -2352,7 +2364,7 @@ pub const RemoveDirStep = struct {
2352 const self = @fieldParentPtr(RemoveDirStep, "step", step);2364 const self = @fieldParentPtr(RemoveDirStep, "step", step);
23532365
2354 const full_path = self.builder.pathFromRoot(self.dir_path);2366 const full_path = self.builder.pathFromRoot(self.dir_path);
2355 fs.deleteTree(full_path) catch |err| {2367 fs.cwd().deleteTree(full_path) catch |err| {
2356 warn("Unable to remove {}: {}\n", .{ full_path, @errorName(err) });2368 warn("Unable to remove {}: {}\n", .{ full_path, @errorName(err) });
2357 return err;2369 return err;
2358 };2370 };
lib/std/build/run.zig+3-1
...@@ -29,6 +29,8 @@ pub const RunStep = struct {...@@ -29,6 +29,8 @@ pub const RunStep = struct {
29 stdout_action: StdIoAction = .inherit,29 stdout_action: StdIoAction = .inherit,
30 stderr_action: StdIoAction = .inherit,30 stderr_action: StdIoAction = .inherit,
3131
32 stdin_behavior: std.ChildProcess.StdIo = .Inherit,
33
32 expected_exit_code: u8 = 0,34 expected_exit_code: u8 = 0,
3335
34 pub const StdIoAction = union(enum) {36 pub const StdIoAction = union(enum) {
...@@ -159,7 +161,7 @@ pub const RunStep = struct {...@@ -159,7 +161,7 @@ pub const RunStep = struct {
159 child.cwd = cwd;161 child.cwd = cwd;
160 child.env_map = self.env_map orelse self.builder.env_map;162 child.env_map = self.env_map orelse self.builder.env_map;
161163
162 child.stdin_behavior = .Ignore;164 child.stdin_behavior = self.stdin_behavior;
163 child.stdout_behavior = stdIoActionToBehavior(self.stdout_action);165 child.stdout_behavior = stdIoActionToBehavior(self.stdout_action);
164 child.stderr_behavior = stdIoActionToBehavior(self.stderr_action);166 child.stderr_behavior = stdIoActionToBehavior(self.stderr_action);
165167
lib/std/build/write_file.zig+1-1
...@@ -78,7 +78,7 @@ pub const WriteFileStep = struct {...@@ -78,7 +78,7 @@ pub const WriteFileStep = struct {
78 warn("unable to make path {}: {}\n", .{ self.output_dir, @errorName(err) });78 warn("unable to make path {}: {}\n", .{ self.output_dir, @errorName(err) });
79 return err;79 return err;
80 };80 };
81 var dir = try fs.cwd().openDirTraverse(self.output_dir);81 var dir = try fs.cwd().openDir(self.output_dir, .{});
82 defer dir.close();82 defer dir.close();
83 for (self.files.toSliceConst()) |file| {83 for (self.files.toSliceConst()) |file| {
84 dir.writeFile(file.basename, file.bytes) catch |err| {84 dir.writeFile(file.basename, file.bytes) catch |err| {
lib/std/c.zig+1
...@@ -106,6 +106,7 @@ pub extern "c" fn mkdir(path: [*:0]const u8, mode: c_uint) c_int;...@@ -106,6 +106,7 @@ pub extern "c" fn mkdir(path: [*:0]const u8, mode: c_uint) c_int;
106pub extern "c" fn mkdirat(dirfd: fd_t, path: [*:0]const u8, mode: u32) c_int;106pub extern "c" fn mkdirat(dirfd: fd_t, path: [*:0]const u8, mode: u32) c_int;
107pub extern "c" fn symlink(existing: [*:0]const u8, new: [*:0]const u8) c_int;107pub extern "c" fn symlink(existing: [*:0]const u8, new: [*:0]const u8) c_int;
108pub extern "c" fn rename(old: [*:0]const u8, new: [*:0]const u8) c_int;108pub extern "c" fn rename(old: [*:0]const u8, new: [*:0]const u8) c_int;
109pub extern "c" fn renameat(olddirfd: fd_t, old: [*:0]const u8, newdirfd: fd_t, new: [*:0]const u8) c_int;
109pub extern "c" fn chdir(path: [*:0]const u8) c_int;110pub extern "c" fn chdir(path: [*:0]const u8) c_int;
110pub extern "c" fn fchdir(fd: fd_t) c_int;111pub extern "c" fn fchdir(fd: fd_t) c_int;
111pub extern "c" fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) c_int;112pub extern "c" fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) c_int;
lib/std/crypto/aes.zig+19-19
...@@ -15,10 +15,10 @@ fn rotw(w: u32) u32 {...@@ -15,10 +15,10 @@ fn rotw(w: u32) u32 {
1515
16// Encrypt one block from src into dst, using the expanded key xk.16// Encrypt one block from src into dst, using the expanded key xk.
17fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {17fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
18 var s0 = mem.readIntSliceBig(u32, src[0..4]);18 var s0 = mem.readIntBig(u32, src[0..4]);
19 var s1 = mem.readIntSliceBig(u32, src[4..8]);19 var s1 = mem.readIntBig(u32, src[4..8]);
20 var s2 = mem.readIntSliceBig(u32, src[8..12]);20 var s2 = mem.readIntBig(u32, src[8..12]);
21 var s3 = mem.readIntSliceBig(u32, src[12..16]);21 var s3 = mem.readIntBig(u32, src[12..16]);
2222
23 // First round just XORs input with key.23 // First round just XORs input with key.
24 s0 ^= xk[0];24 s0 ^= xk[0];
...@@ -58,18 +58,18 @@ fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {...@@ -58,18 +58,18 @@ fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
58 s2 ^= xk[k + 2];58 s2 ^= xk[k + 2];
59 s3 ^= xk[k + 3];59 s3 ^= xk[k + 3];
6060
61 mem.writeIntSliceBig(u32, dst[0..4], s0);61 mem.writeIntBig(u32, dst[0..4], s0);
62 mem.writeIntSliceBig(u32, dst[4..8], s1);62 mem.writeIntBig(u32, dst[4..8], s1);
63 mem.writeIntSliceBig(u32, dst[8..12], s2);63 mem.writeIntBig(u32, dst[8..12], s2);
64 mem.writeIntSliceBig(u32, dst[12..16], s3);64 mem.writeIntBig(u32, dst[12..16], s3);
65}65}
6666
67// Decrypt one block from src into dst, using the expanded key xk.67// Decrypt one block from src into dst, using the expanded key xk.
68pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {68pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
69 var s0 = mem.readIntSliceBig(u32, src[0..4]);69 var s0 = mem.readIntBig(u32, src[0..4]);
70 var s1 = mem.readIntSliceBig(u32, src[4..8]);70 var s1 = mem.readIntBig(u32, src[4..8]);
71 var s2 = mem.readIntSliceBig(u32, src[8..12]);71 var s2 = mem.readIntBig(u32, src[8..12]);
72 var s3 = mem.readIntSliceBig(u32, src[12..16]);72 var s3 = mem.readIntBig(u32, src[12..16]);
7373
74 // First round just XORs input with key.74 // First round just XORs input with key.
75 s0 ^= xk[0];75 s0 ^= xk[0];
...@@ -109,10 +109,10 @@ pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {...@@ -109,10 +109,10 @@ pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
109 s2 ^= xk[k + 2];109 s2 ^= xk[k + 2];
110 s3 ^= xk[k + 3];110 s3 ^= xk[k + 3];
111111
112 mem.writeIntSliceBig(u32, dst[0..4], s0);112 mem.writeIntBig(u32, dst[0..4], s0);
113 mem.writeIntSliceBig(u32, dst[4..8], s1);113 mem.writeIntBig(u32, dst[4..8], s1);
114 mem.writeIntSliceBig(u32, dst[8..12], s2);114 mem.writeIntBig(u32, dst[8..12], s2);
115 mem.writeIntSliceBig(u32, dst[12..16], s3);115 mem.writeIntBig(u32, dst[12..16], s3);
116}116}
117117
118fn xorBytes(dst: []u8, a: []const u8, b: []const u8) usize {118fn xorBytes(dst: []u8, a: []const u8, b: []const u8) usize {
...@@ -154,8 +154,8 @@ fn AES(comptime keysize: usize) type {...@@ -154,8 +154,8 @@ fn AES(comptime keysize: usize) type {
154 var n: usize = 0;154 var n: usize = 0;
155 while (n < src.len) {155 while (n < src.len) {
156 ctx.encrypt(keystream[0..], ctrbuf[0..]);156 ctx.encrypt(keystream[0..], ctrbuf[0..]);
157 var ctr_i = std.mem.readIntSliceBig(u128, ctrbuf[0..]);157 var ctr_i = std.mem.readIntBig(u128, ctrbuf[0..]);
158 std.mem.writeIntSliceBig(u128, ctrbuf[0..], ctr_i +% 1);158 std.mem.writeIntBig(u128, ctrbuf[0..], ctr_i +% 1);
159159
160 n += xorBytes(dst[n..], src[n..], &keystream);160 n += xorBytes(dst[n..], src[n..], &keystream);
161 }161 }
...@@ -251,7 +251,7 @@ fn expandKey(key: []const u8, enc: []u32, dec: []u32) void {...@@ -251,7 +251,7 @@ fn expandKey(key: []const u8, enc: []u32, dec: []u32) void {
251 var i: usize = 0;251 var i: usize = 0;
252 var nk = key.len / 4;252 var nk = key.len / 4;
253 while (i < nk) : (i += 1) {253 while (i < nk) : (i += 1) {
254 enc[i] = mem.readIntSliceBig(u32, key[4 * i .. 4 * i + 4]);254 enc[i] = mem.readIntBig(u32, key[4 * i ..][0..4]);
255 }255 }
256 while (i < enc.len) : (i += 1) {256 while (i < enc.len) : (i += 1) {
257 var t = enc[i - 1];257 var t = enc[i - 1];
lib/std/crypto/blake2.zig+4-7
...@@ -123,8 +123,7 @@ fn Blake2s(comptime out_len: usize) type {...@@ -123,8 +123,7 @@ fn Blake2s(comptime out_len: usize) type {
123 const rr = d.h[0 .. out_len / 32];123 const rr = d.h[0 .. out_len / 32];
124124
125 for (rr) |s, j| {125 for (rr) |s, j| {
126 // TODO https://github.com/ziglang/zig/issues/863126 mem.writeIntLittle(u32, out[4 * j ..][0..4], s);
127 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
128 }127 }
129 }128 }
130129
...@@ -135,8 +134,7 @@ fn Blake2s(comptime out_len: usize) type {...@@ -135,8 +134,7 @@ fn Blake2s(comptime out_len: usize) type {
135 var v: [16]u32 = undefined;134 var v: [16]u32 = undefined;
136135
137 for (m) |*r, i| {136 for (m) |*r, i| {
138 // TODO https://github.com/ziglang/zig/issues/863137 r.* = mem.readIntLittle(u32, b[4 * i ..][0..4]);
139 r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
140 }138 }
141139
142 var k: usize = 0;140 var k: usize = 0;
...@@ -358,8 +356,7 @@ fn Blake2b(comptime out_len: usize) type {...@@ -358,8 +356,7 @@ fn Blake2b(comptime out_len: usize) type {
358 const rr = d.h[0 .. out_len / 64];356 const rr = d.h[0 .. out_len / 64];
359357
360 for (rr) |s, j| {358 for (rr) |s, j| {
361 // TODO https://github.com/ziglang/zig/issues/863359 mem.writeIntLittle(u64, out[8 * j ..][0..8], s);
362 mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
363 }360 }
364 }361 }
365362
...@@ -370,7 +367,7 @@ fn Blake2b(comptime out_len: usize) type {...@@ -370,7 +367,7 @@ fn Blake2b(comptime out_len: usize) type {
370 var v: [16]u64 = undefined;367 var v: [16]u64 = undefined;
371368
372 for (m) |*r, i| {369 for (m) |*r, i| {
373 r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);370 r.* = mem.readIntLittle(u64, b[8 * i ..][0..8]);
374 }371 }
375372
376 var k: usize = 0;373 var k: usize = 0;
lib/std/crypto/chacha20.zig+30-31
...@@ -61,8 +61,7 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {...@@ -61,8 +61,7 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
61 }61 }
6262
63 for (x) |_, i| {63 for (x) |_, i| {
64 // TODO https://github.com/ziglang/zig/issues/86364 mem.writeIntLittle(u32, out[4 * i ..][0..4], x[i] +% input[i]);
65 mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
66 }65 }
67}66}
6867
...@@ -73,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo...@@ -73,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
7372
74 const c = "expand 32-byte k";73 const c = "expand 32-byte k";
75 const constant_le = [_]u32{74 const constant_le = [_]u32{
76 mem.readIntSliceLittle(u32, c[0..4]),75 mem.readIntLittle(u32, c[0..4]),
77 mem.readIntSliceLittle(u32, c[4..8]),76 mem.readIntLittle(u32, c[4..8]),
78 mem.readIntSliceLittle(u32, c[8..12]),77 mem.readIntLittle(u32, c[8..12]),
79 mem.readIntSliceLittle(u32, c[12..16]),78 mem.readIntLittle(u32, c[12..16]),
80 };79 };
8180
82 mem.copy(u32, ctx[0..], constant_le[0..4]);81 mem.copy(u32, ctx[0..], constant_le[0..4]);
...@@ -120,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:...@@ -120,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
120 var k: [8]u32 = undefined;119 var k: [8]u32 = undefined;
121 var c: [4]u32 = undefined;120 var c: [4]u32 = undefined;
122121
123 k[0] = mem.readIntSliceLittle(u32, key[0..4]);122 k[0] = mem.readIntLittle(u32, key[0..4]);
124 k[1] = mem.readIntSliceLittle(u32, key[4..8]);123 k[1] = mem.readIntLittle(u32, key[4..8]);
125 k[2] = mem.readIntSliceLittle(u32, key[8..12]);124 k[2] = mem.readIntLittle(u32, key[8..12]);
126 k[3] = mem.readIntSliceLittle(u32, key[12..16]);125 k[3] = mem.readIntLittle(u32, key[12..16]);
127 k[4] = mem.readIntSliceLittle(u32, key[16..20]);126 k[4] = mem.readIntLittle(u32, key[16..20]);
128 k[5] = mem.readIntSliceLittle(u32, key[20..24]);127 k[5] = mem.readIntLittle(u32, key[20..24]);
129 k[6] = mem.readIntSliceLittle(u32, key[24..28]);128 k[6] = mem.readIntLittle(u32, key[24..28]);
130 k[7] = mem.readIntSliceLittle(u32, key[28..32]);129 k[7] = mem.readIntLittle(u32, key[28..32]);
131130
132 c[0] = counter;131 c[0] = counter;
133 c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);132 c[1] = mem.readIntLittle(u32, nonce[0..4]);
134 c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);133 c[2] = mem.readIntLittle(u32, nonce[4..8]);
135 c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);134 c[3] = mem.readIntLittle(u32, nonce[8..12]);
136 chaCha20_internal(out, in, k, c);135 chaCha20_internal(out, in, k, c);
137}136}
138137
...@@ -147,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]...@@ -147,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
147 var k: [8]u32 = undefined;146 var k: [8]u32 = undefined;
148 var c: [4]u32 = undefined;147 var c: [4]u32 = undefined;
149148
150 k[0] = mem.readIntSliceLittle(u32, key[0..4]);149 k[0] = mem.readIntLittle(u32, key[0..4]);
151 k[1] = mem.readIntSliceLittle(u32, key[4..8]);150 k[1] = mem.readIntLittle(u32, key[4..8]);
152 k[2] = mem.readIntSliceLittle(u32, key[8..12]);151 k[2] = mem.readIntLittle(u32, key[8..12]);
153 k[3] = mem.readIntSliceLittle(u32, key[12..16]);152 k[3] = mem.readIntLittle(u32, key[12..16]);
154 k[4] = mem.readIntSliceLittle(u32, key[16..20]);153 k[4] = mem.readIntLittle(u32, key[16..20]);
155 k[5] = mem.readIntSliceLittle(u32, key[20..24]);154 k[5] = mem.readIntLittle(u32, key[20..24]);
156 k[6] = mem.readIntSliceLittle(u32, key[24..28]);155 k[6] = mem.readIntLittle(u32, key[24..28]);
157 k[7] = mem.readIntSliceLittle(u32, key[28..32]);156 k[7] = mem.readIntLittle(u32, key[28..32]);
158157
159 c[0] = @truncate(u32, counter);158 c[0] = @truncate(u32, counter);
160 c[1] = @truncate(u32, counter >> 32);159 c[1] = @truncate(u32, counter >> 32);
161 c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);160 c[2] = mem.readIntLittle(u32, nonce[0..4]);
162 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);161 c[3] = mem.readIntLittle(u32, nonce[4..8]);
163162
164 const block_size = (1 << 6);163 const block_size = (1 << 6);
165 // The full block size is greater than the address space on a 32bit machine164 // The full block size is greater than the address space on a 32bit machine
...@@ -463,8 +462,8 @@ pub fn chacha20poly1305Seal(dst: []u8, plaintext: []const u8, data: []const u8,...@@ -463,8 +462,8 @@ pub fn chacha20poly1305Seal(dst: []u8, plaintext: []const u8, data: []const u8,
463 mac.update(zeros[0..padding]);462 mac.update(zeros[0..padding]);
464 }463 }
465 var lens: [16]u8 = undefined;464 var lens: [16]u8 = undefined;
466 mem.writeIntSliceLittle(u64, lens[0..8], data.len);465 mem.writeIntLittle(u64, lens[0..8], data.len);
467 mem.writeIntSliceLittle(u64, lens[8..16], plaintext.len);466 mem.writeIntLittle(u64, lens[8..16], plaintext.len);
468 mac.update(lens[0..]);467 mac.update(lens[0..]);
469 mac.final(dst[plaintext.len..]);468 mac.final(dst[plaintext.len..]);
470}469}
...@@ -500,8 +499,8 @@ pub fn chacha20poly1305Open(dst: []u8, msgAndTag: []const u8, data: []const u8,...@@ -500,8 +499,8 @@ pub fn chacha20poly1305Open(dst: []u8, msgAndTag: []const u8, data: []const u8,
500 mac.update(zeros[0..padding]);499 mac.update(zeros[0..padding]);
501 }500 }
502 var lens: [16]u8 = undefined;501 var lens: [16]u8 = undefined;
503 mem.writeIntSliceLittle(u64, lens[0..8], data.len);502 mem.writeIntLittle(u64, lens[0..8], data.len);
504 mem.writeIntSliceLittle(u64, lens[8..16], ciphertext.len);503 mem.writeIntLittle(u64, lens[8..16], ciphertext.len);
505 mac.update(lens[0..]);504 mac.update(lens[0..]);
506 var computedTag: [16]u8 = undefined;505 var computedTag: [16]u8 = undefined;
507 mac.final(computedTag[0..]);506 mac.final(computedTag[0..]);
lib/std/crypto/md5.zig+1-2
...@@ -112,8 +112,7 @@ pub const Md5 = struct {...@@ -112,8 +112,7 @@ pub const Md5 = struct {
112 d.round(d.buf[0..]);112 d.round(d.buf[0..]);
113113
114 for (d.s) |s, j| {114 for (d.s) |s, j| {
115 // TODO https://github.com/ziglang/zig/issues/863115 mem.writeIntLittle(u32, out[4 * j ..][0..4], s);
116 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
117 }116 }
118 }117 }
119118
lib/std/crypto/poly1305.zig+14-15
...@@ -3,11 +3,11 @@...@@ -3,11 +3,11 @@
3// https://monocypher.org/3// https://monocypher.org/
44
5const std = @import("../std.zig");5const std = @import("../std.zig");
6const builtin = @import("builtin");6const builtin = std.builtin;
77
8const Endian = builtin.Endian;8const Endian = builtin.Endian;
9const readIntSliceLittle = std.mem.readIntSliceLittle;9const readIntLittle = std.mem.readIntLittle;
10const writeIntSliceLittle = std.mem.writeIntSliceLittle;10const writeIntLittle = std.mem.writeIntLittle;
1111
12pub const Poly1305 = struct {12pub const Poly1305 = struct {
13 const Self = @This();13 const Self = @This();
...@@ -59,19 +59,19 @@ pub const Poly1305 = struct {...@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
59 {59 {
60 var i: usize = 0;60 var i: usize = 0;
61 while (i < 1) : (i += 1) {61 while (i < 1) : (i += 1) {
62 ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;62 ctx.r[0] = readIntLittle(u32, key[0..4]) & 0x0fffffff;
63 }63 }
64 }64 }
65 {65 {
66 var i: usize = 1;66 var i: usize = 1;
67 while (i < 4) : (i += 1) {67 while (i < 4) : (i += 1) {
68 ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;68 ctx.r[i] = readIntLittle(u32, key[i * 4 ..][0..4]) & 0x0ffffffc;
69 }69 }
70 }70 }
71 {71 {
72 var i: usize = 0;72 var i: usize = 0;
73 while (i < 4) : (i += 1) {73 while (i < 4) : (i += 1) {
74 ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);74 ctx.pad[i] = readIntLittle(u32, key[i * 4 + 16 ..][0..4]);
75 }75 }
76 }76 }
7777
...@@ -168,10 +168,10 @@ pub const Poly1305 = struct {...@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
168 const nb_blocks = nmsg.len >> 4;168 const nb_blocks = nmsg.len >> 4;
169 var i: usize = 0;169 var i: usize = 0;
170 while (i < nb_blocks) : (i += 1) {170 while (i < nb_blocks) : (i += 1) {
171 ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);171 ctx.c[0] = readIntLittle(u32, nmsg[0..4]);
172 ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);172 ctx.c[1] = readIntLittle(u32, nmsg[4..8]);
173 ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);173 ctx.c[2] = readIntLittle(u32, nmsg[8..12]);
174 ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);174 ctx.c[3] = readIntLittle(u32, nmsg[12..16]);
175 polyBlock(ctx);175 polyBlock(ctx);
176 nmsg = nmsg[16..];176 nmsg = nmsg[16..];
177 }177 }
...@@ -210,11 +210,10 @@ pub const Poly1305 = struct {...@@ -210,11 +210,10 @@ pub const Poly1305 = struct {
210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
212212
213 // TODO https://github.com/ziglang/zig/issues/863213 writeIntLittle(u32, out[0..4], @truncate(u32, uu0));
214 writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));214 writeIntLittle(u32, out[4..8], @truncate(u32, uu1));
215 writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));215 writeIntLittle(u32, out[8..12], @truncate(u32, uu2));
216 writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));216 writeIntLittle(u32, out[12..16], @truncate(u32, uu3));
217 writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
218217
219 ctx.secureZero();218 ctx.secureZero();
220 }219 }
lib/std/crypto/sha1.zig+1-2
...@@ -109,8 +109,7 @@ pub const Sha1 = struct {...@@ -109,8 +109,7 @@ pub const Sha1 = struct {
109 d.round(d.buf[0..]);109 d.round(d.buf[0..]);
110110
111 for (d.s) |s, j| {111 for (d.s) |s, j| {
112 // TODO https://github.com/ziglang/zig/issues/863112 mem.writeIntBig(u32, out[4 * j ..][0..4], s);
113 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
114 }113 }
115 }114 }
116115
lib/std/crypto/sha2.zig+2-4
...@@ -167,8 +167,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {...@@ -167,8 +167,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
167 const rr = d.s[0 .. params.out_len / 32];167 const rr = d.s[0 .. params.out_len / 32];
168168
169 for (rr) |s, j| {169 for (rr) |s, j| {
170 // TODO https://github.com/ziglang/zig/issues/863170 mem.writeIntBig(u32, out[4 * j ..][0..4], s);
171 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
172 }171 }
173 }172 }
174173
...@@ -509,8 +508,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {...@@ -509,8 +508,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
509 const rr = d.s[0 .. params.out_len / 64];508 const rr = d.s[0 .. params.out_len / 64];
510509
511 for (rr) |s, j| {510 for (rr) |s, j| {
512 // TODO https://github.com/ziglang/zig/issues/863511 mem.writeIntBig(u64, out[8 * j ..][0..8], s);
513 mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
514 }512 }
515 }513 }
516514
lib/std/crypto/sha3.zig+2-3
...@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
120 var c = [_]u64{0} ** 5;120 var c = [_]u64{0} ** 5;
121121
122 for (s) |*r, i| {122 for (s) |*r, i| {
123 r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);123 r.* = mem.readIntLittle(u64, d[8 * i ..][0..8]);
124 }124 }
125125
126 comptime var x: usize = 0;126 comptime var x: usize = 0;
...@@ -167,8 +167,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -167,8 +167,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
167 }167 }
168168
169 for (s) |r, i| {169 for (s) |r, i| {
170 // TODO https://github.com/ziglang/zig/issues/863170 mem.writeIntLittle(u64, d[8 * i ..][0..8], r);
171 mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
172 }171 }
173}172}
174173
lib/std/crypto/x25519.zig+20-21
...@@ -7,8 +7,8 @@ const builtin = @import("builtin");...@@ -7,8 +7,8 @@ const builtin = @import("builtin");
7const fmt = std.fmt;7const fmt = std.fmt;
88
9const Endian = builtin.Endian;9const Endian = builtin.Endian;
10const readIntSliceLittle = std.mem.readIntSliceLittle;10const readIntLittle = std.mem.readIntLittle;
11const writeIntSliceLittle = std.mem.writeIntSliceLittle;11const writeIntLittle = std.mem.writeIntLittle;
1212
13// Based on Supercop's ref10 implementation.13// Based on Supercop's ref10 implementation.
14pub const X25519 = struct {14pub const X25519 = struct {
...@@ -255,16 +255,16 @@ const Fe = struct {...@@ -255,16 +255,16 @@ const Fe = struct {
255255
256 var t: [10]i64 = undefined;256 var t: [10]i64 = undefined;
257257
258 t[0] = readIntSliceLittle(u32, s[0..4]);258 t[0] = readIntLittle(u32, s[0..4]);
259 t[1] = @as(u32, readIntSliceLittle(u24, s[4..7])) << 6;259 t[1] = @as(u32, readIntLittle(u24, s[4..7])) << 6;
260 t[2] = @as(u32, readIntSliceLittle(u24, s[7..10])) << 5;260 t[2] = @as(u32, readIntLittle(u24, s[7..10])) << 5;
261 t[3] = @as(u32, readIntSliceLittle(u24, s[10..13])) << 3;261 t[3] = @as(u32, readIntLittle(u24, s[10..13])) << 3;
262 t[4] = @as(u32, readIntSliceLittle(u24, s[13..16])) << 2;262 t[4] = @as(u32, readIntLittle(u24, s[13..16])) << 2;
263 t[5] = readIntSliceLittle(u32, s[16..20]);263 t[5] = readIntLittle(u32, s[16..20]);
264 t[6] = @as(u32, readIntSliceLittle(u24, s[20..23])) << 7;264 t[6] = @as(u32, readIntLittle(u24, s[20..23])) << 7;
265 t[7] = @as(u32, readIntSliceLittle(u24, s[23..26])) << 5;265 t[7] = @as(u32, readIntLittle(u24, s[23..26])) << 5;
266 t[8] = @as(u32, readIntSliceLittle(u24, s[26..29])) << 4;266 t[8] = @as(u32, readIntLittle(u24, s[26..29])) << 4;
267 t[9] = (@as(u32, readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;267 t[9] = (@as(u32, readIntLittle(u24, s[29..32])) & 0x7fffff) << 2;
268268
269 carry1(h, t[0..]);269 carry1(h, t[0..]);
270 }270 }
...@@ -544,15 +544,14 @@ const Fe = struct {...@@ -544,15 +544,14 @@ const Fe = struct {
544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));
545 }545 }
546546
547 // TODO https://github.com/ziglang/zig/issues/863547 writeIntLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
548 writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));548 writeIntLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
549 writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));549 writeIntLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
550 writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));550 writeIntLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
551 writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));551 writeIntLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
552 writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));552 writeIntLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
553 writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));553 writeIntLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
554 writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));554 writeIntLittle(u32, s[28..32], (ut[8] >> 20) | (ut[9] << 6));
555 writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
556555
557 std.mem.secureZero(i64, t[0..]);556 std.mem.secureZero(i64, t[0..]);
558 }557 }
lib/std/debug.zig+44-11
...@@ -235,9 +235,17 @@ pub fn panic(comptime format: []const u8, args: var) noreturn {...@@ -235,9 +235,17 @@ pub fn panic(comptime format: []const u8, args: var) noreturn {
235 panicExtra(null, first_trace_addr, format, args);235 panicExtra(null, first_trace_addr, format, args);
236}236}
237237
238/// TODO multithreaded awareness238/// Non-zero whenever the program triggered a panic.
239/// The counter is incremented/decremented atomically.
239var panicking: u8 = 0;240var panicking: u8 = 0;
240241
242// Locked to avoid interleaving panic messages from multiple threads.
243var panic_mutex = std.Mutex.init();
244
245/// Counts how many times the panic handler is invoked by this thread.
246/// This is used to catch and handle panics triggered by the panic handler.
247threadlocal var panic_stage: usize = 0;
248
241pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: var) noreturn {249pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: var) noreturn {
242 @setCold(true);250 @setCold(true);
243251
...@@ -247,25 +255,50 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c...@@ -247,25 +255,50 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
247 resetSegfaultHandler();255 resetSegfaultHandler();
248 }256 }
249257
250 switch (@atomicRmw(u8, &panicking, .Add, 1, .SeqCst)) {258 switch (panic_stage) {
251 0 => {259 0 => {
252 const stderr = getStderrStream();260 panic_stage = 1;
253 noasync stderr.print(format ++ "\n", args) catch os.abort();261
254 if (trace) |t| {262 _ = @atomicRmw(u8, &panicking, .Add, 1, .SeqCst);
255 dumpStackTrace(t.*);263
264 // Make sure to release the mutex when done
265 {
266 const held = panic_mutex.acquire();
267 defer held.release();
268
269 const stderr = getStderrStream();
270 noasync stderr.print(format ++ "\n", args) catch os.abort();
271 if (trace) |t| {
272 dumpStackTrace(t.*);
273 }
274 dumpCurrentStackTrace(first_trace_addr);
275 }
276
277 if (@atomicRmw(u8, &panicking, .Sub, 1, .SeqCst) != 1) {
278 // Another thread is panicking, wait for the last one to finish
279 // and call abort()
280
281 // Sleep forever without hammering the CPU
282 var event = std.ResetEvent.init();
283 event.wait();
284
285 unreachable;
256 }286 }
257 dumpCurrentStackTrace(first_trace_addr);
258 },287 },
259 1 => {288 1 => {
260 // TODO detect if a different thread caused the panic, because in that case289 panic_stage = 2;
261 // we would want to return here instead of calling abort, so that the thread290
262 // which first called panic can finish printing a stack trace.291 // A panic happened while trying to print a previous panic message,
263 warn("Panicked during a panic. Aborting.\n", .{});292 // we're still holding the mutex but that's fine as we're going to
293 // call abort()
294 const stderr = getStderrStream();
295 noasync stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort();
264 },296 },
265 else => {297 else => {
266 // Panicked while printing "Panicked during a panic."298 // Panicked while printing "Panicked during a panic."
267 },299 },
268 }300 }
301
269 os.abort();302 os.abort();
270}303}
271304
lib/std/dwarf.zig+1-2
...@@ -717,8 +717,7 @@ pub const DwarfInfo = struct {...@@ -717,8 +717,7 @@ pub const DwarfInfo = struct {
717 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));717 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
718718
719 const version = try in.readInt(u16, di.endian);719 const version = try in.readInt(u16, di.endian);
720 // TODO support 3 and 5720 if (version < 2 or version > 4) return error.InvalidDebugInfo;
721 if (version != 2 and version != 4) return error.InvalidDebugInfo;
722721
723 const prologue_length = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);722 const prologue_length = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);
724 const prog_start_offset = (try seekable.getPos()) + prologue_length;723 const prog_start_offset = (try seekable.getPos()) + prologue_length;
lib/std/fmt.zig+2-1
...@@ -1223,7 +1223,8 @@ test "slice" {...@@ -1223,7 +1223,8 @@ test "slice" {
1223 try testFmt("slice: abc\n", "slice: {}\n", .{value});1223 try testFmt("slice: abc\n", "slice: {}\n", .{value});
1224 }1224 }
1225 {1225 {
1226 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];1226 var runtime_zero: usize = 0;
1227 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero];
1227 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});1228 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
1228 }1229 }
12291230
lib/std/fs.zig+233-311
...@@ -81,134 +81,74 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:...@@ -81,134 +81,74 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
81 }81 }
82}82}
8383
84// TODO fix enum literal not casting to error union84pub const PrevStatus = enum {
85const PrevStatus = enum {
86 stale,85 stale,
87 fresh,86 fresh,
88};87};
8988
90pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus {89pub const CopyFileOptions = struct {
91 return updateFileMode(source_path, dest_path, null);90 /// When this is `null` the mode is copied from the source file.
92}91 override_mode: ?File.Mode = null,
92};
9393
94/// Check the file size, mtime, and mode of `source_path` and `dest_path`. If they are equal, does nothing.94/// Same as `Dir.updateFile`, except asserts that both `source_path` and `dest_path`
95/// Otherwise, atomically copies `source_path` to `dest_path`. The destination file gains the mtime,95/// are absolute. See `Dir.updateFile` for a function that operates on both
96/// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.96/// absolute and relative paths.
97/// Returns the previous status of the file before updating.97pub fn updateFileAbsolute(
98/// If any of the directories do not exist for dest_path, they are created.98 source_path: []const u8,
99/// TODO rework this to integrate with Dir99 dest_path: []const u8,
100pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus {100 args: CopyFileOptions,
101) !PrevStatus {
102 assert(path.isAbsolute(source_path));
103 assert(path.isAbsolute(dest_path));
101 const my_cwd = cwd();104 const my_cwd = cwd();
102105 return Dir.updateFile(my_cwd, source_path, my_cwd, dest_path, args);
103 var src_file = try my_cwd.openFile(source_path, .{});
104 defer src_file.close();
105
106 const src_stat = try src_file.stat();
107 check_dest_stat: {
108 const dest_stat = blk: {
109 var dest_file = my_cwd.openFile(dest_path, .{}) catch |err| switch (err) {
110 error.FileNotFound => break :check_dest_stat,
111 else => |e| return e,
112 };
113 defer dest_file.close();
114
115 break :blk try dest_file.stat();
116 };
117
118 if (src_stat.size == dest_stat.size and
119 src_stat.mtime == dest_stat.mtime and
120 src_stat.mode == dest_stat.mode)
121 {
122 return PrevStatus.fresh;
123 }
124 }
125 const actual_mode = mode orelse src_stat.mode;
126
127 if (path.dirname(dest_path)) |dirname| {
128 try cwd().makePath(dirname);
129 }
130
131 var atomic_file = try AtomicFile.init(dest_path, actual_mode);
132 defer atomic_file.deinit();
133
134 try atomic_file.file.writeFileAll(src_file, .{ .in_len = src_stat.size });
135 try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime);
136 try atomic_file.finish();
137 return PrevStatus.stale;
138}106}
139107
140/// Guaranteed to be atomic.108/// Same as `Dir.copyFile`, except asserts that both `source_path` and `dest_path`
141/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,109/// are absolute. See `Dir.copyFile` for a function that operates on both
142/// there is a possibility of power loss or application termination leaving temporary files present110/// absolute and relative paths.
143/// in the same directory as dest_path.111pub fn copyFileAbsolute(source_path: []const u8, dest_path: []const u8, args: CopyFileOptions) !void {
144/// Destination file will have the same mode as the source file.112 assert(path.isAbsolute(source_path));
145/// TODO rework this to integrate with Dir113 assert(path.isAbsolute(dest_path));
146pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {114 const my_cwd = cwd();
147 var in_file = try cwd().openFile(source_path, .{});115 return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
148 defer in_file.close();
149
150 const stat = try in_file.stat();
151
152 var atomic_file = try AtomicFile.init(dest_path, stat.mode);
153 defer atomic_file.deinit();
154
155 try atomic_file.file.writeFileAll(in_file, .{ .in_len = stat.size });
156 return atomic_file.finish();
157}
158
159/// Guaranteed to be atomic.
160/// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,
161/// there is a possibility of power loss or application termination leaving temporary files present
162/// in the same directory as dest_path.
163/// TODO rework this to integrate with Dir
164pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
165 var in_file = try cwd().openFile(source_path, .{});
166 defer in_file.close();
167
168 var atomic_file = try AtomicFile.init(dest_path, mode);
169 defer atomic_file.deinit();
170
171 try atomic_file.file.writeFileAll(in_file, .{});
172 return atomic_file.finish();
173}116}
174117
175/// TODO update this API to avoid a getrandom syscall for every operation. It118/// TODO update this API to avoid a getrandom syscall for every operation.
176/// should accept a random interface.
177/// TODO rework this to integrate with Dir
178pub const AtomicFile = struct {119pub const AtomicFile = struct {
179 file: File,120 file: File,
180 tmp_path_buf: [MAX_PATH_BYTES]u8,121 tmp_path_buf: [MAX_PATH_BYTES - 1:0]u8,
181 dest_path: []const u8,122 dest_path: []const u8,
182 finished: bool,123 file_open: bool,
124 file_exists: bool,
125 dir: Dir,
183126
184 const InitError = File.OpenError;127 const InitError = File.OpenError;
185128
186 /// dest_path must remain valid for the lifetime of AtomicFile129 /// TODO rename this. Callers should go through Dir API
187 /// call finish to atomically replace dest_path with contents130 pub fn init2(dest_path: []const u8, mode: File.Mode, dir: Dir) InitError!AtomicFile {
188 pub fn init(dest_path: []const u8, mode: File.Mode) InitError!AtomicFile {
189 const dirname = path.dirname(dest_path);131 const dirname = path.dirname(dest_path);
190 var rand_buf: [12]u8 = undefined;132 var rand_buf: [12]u8 = undefined;
191 const dirname_component_len = if (dirname) |d| d.len + 1 else 0;133 const dirname_component_len = if (dirname) |d| d.len + 1 else 0;
192 const encoded_rand_len = comptime base64.Base64Encoder.calcSize(rand_buf.len);134 const encoded_rand_len = comptime base64.Base64Encoder.calcSize(rand_buf.len);
193 const tmp_path_len = dirname_component_len + encoded_rand_len;135 const tmp_path_len = dirname_component_len + encoded_rand_len;
194 var tmp_path_buf: [MAX_PATH_BYTES]u8 = undefined;136 var tmp_path_buf: [MAX_PATH_BYTES - 1:0]u8 = undefined;
195 if (tmp_path_len >= tmp_path_buf.len) return error.NameTooLong;137 if (tmp_path_len > tmp_path_buf.len) return error.NameTooLong;
196138
197 if (dirname) |dir| {139 if (dirname) |dn| {
198 mem.copy(u8, tmp_path_buf[0..], dir);140 mem.copy(u8, tmp_path_buf[0..], dn);
199 tmp_path_buf[dir.len] = path.sep;141 tmp_path_buf[dn.len] = path.sep;
200 }142 }
201143
202 tmp_path_buf[tmp_path_len] = 0;144 tmp_path_buf[tmp_path_len] = 0;
203 const tmp_path_slice = tmp_path_buf[0..tmp_path_len :0];145 const tmp_path_slice = tmp_path_buf[0..tmp_path_len :0];
204146
205 const my_cwd = cwd();
206
207 while (true) {147 while (true) {
208 try crypto.randomBytes(rand_buf[0..]);148 try crypto.randomBytes(rand_buf[0..]);
209 base64_encoder.encode(tmp_path_slice[dirname_component_len..tmp_path_len], &rand_buf);149 base64_encoder.encode(tmp_path_slice[dirname_component_len..tmp_path_len], &rand_buf);
210150
211 const file = my_cwd.createFileC(151 const file = dir.createFileC(
212 tmp_path_slice,152 tmp_path_slice,
213 .{ .mode = mode, .exclusive = true },153 .{ .mode = mode, .exclusive = true },
214 ) catch |err| switch (err) {154 ) catch |err| switch (err) {
...@@ -220,33 +160,46 @@ pub const AtomicFile = struct {...@@ -220,33 +160,46 @@ pub const AtomicFile = struct {
220 .file = file,160 .file = file,
221 .tmp_path_buf = tmp_path_buf,161 .tmp_path_buf = tmp_path_buf,
222 .dest_path = dest_path,162 .dest_path = dest_path,
223 .finished = false,163 .file_open = true,
164 .file_exists = true,
165 .dir = dir,
224 };166 };
225 }167 }
226 }168 }
227169
170 /// Deprecated. Use `Dir.atomicFile`.
171 pub fn init(dest_path: []const u8, mode: File.Mode) InitError!AtomicFile {
172 return init2(dest_path, mode, cwd());
173 }
174
228 /// always call deinit, even after successful finish()175 /// always call deinit, even after successful finish()
229 pub fn deinit(self: *AtomicFile) void {176 pub fn deinit(self: *AtomicFile) void {
230 if (!self.finished) {177 if (self.file_open) {
231 self.file.close();178 self.file.close();
232 cwd().deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};179 self.file_open = false;
233 self.finished = true;180 }
181 if (self.file_exists) {
182 self.dir.deleteFileC(&self.tmp_path_buf) catch {};
183 self.file_exists = false;
234 }184 }
185 self.* = undefined;
235 }186 }
236187
237 pub fn finish(self: *AtomicFile) !void {188 pub fn finish(self: *AtomicFile) !void {
238 assert(!self.finished);189 assert(self.file_exists);
190 if (self.file_open) {
191 self.file.close();
192 self.file_open = false;
193 }
239 if (std.Target.current.os.tag == .windows) {194 if (std.Target.current.os.tag == .windows) {
240 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);195 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
241 const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));196 const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
242 self.file.close();197 try os.renameatW(self.dir.fd, &tmp_path_w, self.dir.fd, &dest_path_w, os.windows.TRUE);
243 self.finished = true;198 self.file_exists = false;
244 return os.renameW(&tmp_path_w, &dest_path_w);
245 } else {199 } else {
246 const dest_path_c = try os.toPosixPath(self.dest_path);200 const dest_path_c = try os.toPosixPath(self.dest_path);
247 self.file.close();201 try os.renameatZ(self.dir.fd, &self.tmp_path_buf, self.dir.fd, &dest_path_c);
248 self.finished = true;202 self.file_exists = false;
249 return os.renameC(@ptrCast([*:0]u8, &self.tmp_path_buf), &dest_path_c);
250 }203 }
251 }204 }
252};205};
...@@ -274,44 +227,21 @@ pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {...@@ -274,44 +227,21 @@ pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {
274 os.windows.CloseHandle(handle);227 os.windows.CloseHandle(handle);
275}228}
276229
277/// Returns `error.DirNotEmpty` if the directory is not empty.230/// Deprecated; use `Dir.deleteDir`.
278/// To delete a directory recursively, see `deleteTree`.
279pub fn deleteDir(dir_path: []const u8) !void {231pub fn deleteDir(dir_path: []const u8) !void {
280 return os.rmdir(dir_path);232 return os.rmdir(dir_path);
281}233}
282234
283/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.235/// Deprecated; use `Dir.deleteDirC`.
284pub fn deleteDirC(dir_path: [*:0]const u8) !void {236pub fn deleteDirC(dir_path: [*:0]const u8) !void {
285 return os.rmdirC(dir_path);237 return os.rmdirC(dir_path);
286}238}
287239
288/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.240/// Deprecated; use `Dir.deleteDirW`.
289pub fn deleteDirW(dir_path: [*:0]const u16) !void {241pub fn deleteDirW(dir_path: [*:0]const u16) !void {
290 return os.rmdirW(dir_path);242 return os.rmdirW(dir_path);
291}243}
292244
293/// Removes a symlink, file, or directory.
294/// If `full_path` is relative, this is equivalent to `Dir.deleteTree` with the
295/// current working directory as the open directory handle.
296/// If `full_path` is absolute, this is equivalent to `Dir.deleteTree` with the
297/// base directory.
298pub fn deleteTree(full_path: []const u8) !void {
299 if (path.isAbsolute(full_path)) {
300 const dirname = path.dirname(full_path) orelse return error{
301 /// Attempt to remove the root file system path.
302 /// This error is unreachable if `full_path` is relative.
303 CannotDeleteRootDirectory,
304 }.CannotDeleteRootDirectory;
305
306 var dir = try cwd().openDirList(dirname);
307 defer dir.close();
308
309 return dir.deleteTree(path.basename(full_path));
310 } else {
311 return cwd().deleteTree(full_path);
312 }
313}
314
315pub const Dir = struct {245pub const Dir = struct {
316 fd: os.fd_t,246 fd: os.fd_t,
317247
...@@ -368,7 +298,7 @@ pub const Dir = struct {...@@ -368,7 +298,7 @@ pub const Dir = struct {
368 if (rc == 0) return null;298 if (rc == 0) return null;
369 if (rc < 0) {299 if (rc < 0) {
370 switch (os.errno(rc)) {300 switch (os.errno(rc)) {
371 os.EBADF => unreachable,301 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
372 os.EFAULT => unreachable,302 os.EFAULT => unreachable,
373 os.ENOTDIR => unreachable,303 os.ENOTDIR => unreachable,
374 os.EINVAL => unreachable,304 os.EINVAL => unreachable,
...@@ -411,13 +341,13 @@ pub const Dir = struct {...@@ -411,13 +341,13 @@ pub const Dir = struct {
411 if (self.index >= self.end_index) {341 if (self.index >= self.end_index) {
412 const rc = os.system.getdirentries(342 const rc = os.system.getdirentries(
413 self.dir.fd,343 self.dir.fd,
414 self.buf[0..].ptr,344 &self.buf,
415 self.buf.len,345 self.buf.len,
416 &self.seek,346 &self.seek,
417 );347 );
418 switch (os.errno(rc)) {348 switch (os.errno(rc)) {
419 0 => {},349 0 => {},
420 os.EBADF => unreachable,350 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
421 os.EFAULT => unreachable,351 os.EFAULT => unreachable,
422 os.ENOTDIR => unreachable,352 os.ENOTDIR => unreachable,
423 os.EINVAL => unreachable,353 os.EINVAL => unreachable,
...@@ -473,7 +403,7 @@ pub const Dir = struct {...@@ -473,7 +403,7 @@ pub const Dir = struct {
473 const rc = os.linux.getdents64(self.dir.fd, &self.buf, self.buf.len);403 const rc = os.linux.getdents64(self.dir.fd, &self.buf, self.buf.len);
474 switch (os.linux.getErrno(rc)) {404 switch (os.linux.getErrno(rc)) {
475 0 => {},405 0 => {},
476 os.EBADF => unreachable,406 os.EBADF => unreachable, // Dir is invalid or was opened without iteration ability
477 os.EFAULT => unreachable,407 os.EFAULT => unreachable,
478 os.ENOTDIR => unreachable,408 os.ENOTDIR => unreachable,
479 os.EINVAL => unreachable,409 os.EINVAL => unreachable,
...@@ -547,7 +477,8 @@ pub const Dir = struct {...@@ -547,7 +477,8 @@ pub const Dir = struct {
547 self.end_index = io.Information;477 self.end_index = io.Information;
548 switch (rc) {478 switch (rc) {
549 .SUCCESS => {},479 .SUCCESS => {},
550 .ACCESS_DENIED => return error.AccessDenied,480 .ACCESS_DENIED => return error.AccessDenied, // Double-check that the Dir was opened with iteration ability
481
551 else => return w.unexpectedStatus(rc),482 else => return w.unexpectedStatus(rc),
552 }483 }
553 }484 }
...@@ -625,16 +556,6 @@ pub const Dir = struct {...@@ -625,16 +556,6 @@ pub const Dir = struct {
625 DeviceBusy,556 DeviceBusy,
626 } || os.UnexpectedError;557 } || os.UnexpectedError;
627558
628 /// Deprecated; call `cwd().openDirList` directly.
629 pub fn open(dir_path: []const u8) OpenError!Dir {
630 return cwd().openDirList(dir_path);
631 }
632
633 /// Deprecated; call `cwd().openDirListC` directly.
634 pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir {
635 return cwd().openDirListC(dir_path_c);
636 }
637
638 pub fn close(self: *Dir) void {559 pub fn close(self: *Dir) void {
639 if (need_async_thread) {560 if (need_async_thread) {
640 std.event.Loop.instance.?.close(self.fd);561 std.event.Loop.instance.?.close(self.fd);
...@@ -696,7 +617,7 @@ pub const Dir = struct {...@@ -696,7 +617,7 @@ pub const Dir = struct {
696 var flock = mem.zeroes(os.Flock);617 var flock = mem.zeroes(os.Flock);
697 flock.l_type = if (flags.write) os.F_WRLCK else os.F_RDLCK;618 flock.l_type = if (flags.write) os.F_WRLCK else os.F_RDLCK;
698 flock.l_whence = os.SEEK_SET;619 flock.l_whence = os.SEEK_SET;
699 try os.fcntl(fd, os.F_SETLKW, &flock);620 _ = try os.fcntl(fd, os.F_SETLKW, @ptrToInt(&flock));
700 }621 }
701622
702 return File{623 return File{
...@@ -721,7 +642,10 @@ pub const Dir = struct {...@@ -721,7 +642,10 @@ pub const Dir = struct {
721 (if (flags.write) @as(os.windows.ULONG, 0) else w.FILE_SHARE_READ)642 (if (flags.write) @as(os.windows.ULONG, 0) else w.FILE_SHARE_READ)
722 else643 else
723 null;644 null;
724 return self.openFileWindows(sub_path_w, access_mask, share_access, w.FILE_OPEN);645 return @as(File, .{
646 .handle = try os.windows.OpenFileW(self.fd, sub_path_w, null, access_mask, share_access, w.FILE_OPEN),
647 .io_mode = .blocking,
648 });
725 }649 }
726650
727 /// Creates, opens, or overwrites a file with write access.651 /// Creates, opens, or overwrites a file with write access.
...@@ -765,7 +689,7 @@ pub const Dir = struct {...@@ -765,7 +689,7 @@ pub const Dir = struct {
765 var flock = mem.zeroes(os.Flock);689 var flock = mem.zeroes(os.Flock);
766 flock.l_type = os.F_WRLCK;690 flock.l_type = os.F_WRLCK;
767 flock.l_whence = os.SEEK_SET;691 flock.l_whence = os.SEEK_SET;
768 try os.fcntl(fd, os.F_SETLKW, &flock);692 _ = try os.fcntl(fd, os.F_SETLKW, @ptrToInt(&flock));
769 }693 }
770694
771 return File{ .handle = fd, .io_mode = .blocking };695 return File{ .handle = fd, .io_mode = .blocking };
...@@ -788,7 +712,10 @@ pub const Dir = struct {...@@ -788,7 +712,10 @@ pub const Dir = struct {
788 @as(os.windows.ULONG, w.FILE_SHARE_DELETE)712 @as(os.windows.ULONG, w.FILE_SHARE_DELETE)
789 else713 else
790 null;714 null;
791 return self.openFileWindows(sub_path_w, access_mask, share_access, creation);715 return @as(File, .{
716 .handle = try os.windows.OpenFileW(self.fd, sub_path_w, null, access_mask, share_access, creation),
717 .io_mode = .blocking,
718 });
792 }719 }
793720
794 /// Deprecated; call `openFile` directly.721 /// Deprecated; call `openFile` directly.
...@@ -806,87 +733,6 @@ pub const Dir = struct {...@@ -806,87 +733,6 @@ pub const Dir = struct {
806 return self.openFileW(sub_path, .{});733 return self.openFileW(sub_path, .{});
807 }734 }
808735
809 pub fn openFileWindows(
810 self: Dir,
811 sub_path_w: [*:0]const u16,
812 access_mask: os.windows.ACCESS_MASK,
813 share_access_opt: ?os.windows.ULONG,
814 creation: os.windows.ULONG,
815 ) File.OpenError!File {
816 var delay: usize = 1;
817 while (true) {
818 const w = os.windows;
819
820 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
821 return error.IsDir;
822 }
823 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
824 return error.IsDir;
825 }
826
827 var result = File{
828 .handle = undefined,
829 .io_mode = .blocking,
830 };
831
832 const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
833 error.Overflow => return error.NameTooLong,
834 };
835 var nt_name = w.UNICODE_STRING{
836 .Length = path_len_bytes,
837 .MaximumLength = path_len_bytes,
838 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
839 };
840 var attr = w.OBJECT_ATTRIBUTES{
841 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
842 .RootDirectory = if (path.isAbsoluteWindowsW(sub_path_w)) null else self.fd,
843 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
844 .ObjectName = &nt_name,
845 .SecurityDescriptor = null,
846 .SecurityQualityOfService = null,
847 };
848 var io: w.IO_STATUS_BLOCK = undefined;
849 const share_access = share_access_opt orelse w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE;
850 const rc = w.ntdll.NtCreateFile(
851 &result.handle,
852 access_mask,
853 &attr,
854 &io,
855 null,
856 w.FILE_ATTRIBUTE_NORMAL,
857 share_access,
858 creation,
859 w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT,
860 null,
861 0,
862 );
863 switch (rc) {
864 .SUCCESS => return result,
865 .OBJECT_NAME_INVALID => unreachable,
866 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
867 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
868 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
869 .INVALID_PARAMETER => unreachable,
870 .SHARING_VIOLATION => {
871 // TODO: check if async or blocking
872 //return error.SharingViolation
873 // Sleep so we don't consume a ton of CPU waiting to get lock on file
874 std.time.sleep(delay);
875 // Increase sleep time as long as it is less than 5 seconds
876 if (delay < 5 * std.time.ns_per_s) {
877 delay *= 2;
878 }
879 continue;
880 },
881 .ACCESS_DENIED => return error.AccessDenied,
882 .PIPE_BUSY => return error.PipeBusy,
883 .OBJECT_PATH_SYNTAX_BAD => unreachable,
884 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
885 else => return w.unexpectedStatus(rc),
886 }
887 }
888 }
889
890 pub fn makeDir(self: Dir, sub_path: []const u8) !void {736 pub fn makeDir(self: Dir, sub_path: []const u8) !void {
891 try os.mkdirat(self.fd, sub_path, default_new_dir_mode);737 try os.mkdirat(self.fd, sub_path, default_new_dir_mode);
892 }738 }
...@@ -945,77 +791,61 @@ pub const Dir = struct {...@@ -945,77 +791,61 @@ pub const Dir = struct {
945 try os.fchdir(self.fd);791 try os.fchdir(self.fd);
946 }792 }
947793
948 /// Deprecated; call `openDirList` directly.794 pub const OpenDirOptions = struct {
949 pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir {795 /// `true` means the opened directory can be used as the `Dir` parameter
950 return self.openDirList(sub_path);796 /// for functions which operate based on an open directory handle. When `false`,
951 }797 /// such operations are Illegal Behavior.
952798 access_sub_paths: bool = true,
953 /// Deprecated; call `openDirListC` directly.
954 pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
955 return self.openDirListC(sub_path_c);
956 }
957
958 /// Opens a directory at the given path with the ability to access subpaths
959 /// of the result. Calling `iterate` on the result is illegal behavior; to
960 /// list the contents of a directory, open it with `openDirList`.
961 ///
962 /// Call `close` on the result when done.
963 ///
964 /// Asserts that the path parameter has no null bytes.
965 pub fn openDirTraverse(self: Dir, sub_path: []const u8) OpenError!Dir {
966 if (builtin.os.tag == .windows) {
967 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
968 return self.openDirTraverseW(&sub_path_w);
969 }
970799
971 const sub_path_c = try os.toPosixPath(sub_path);800 /// `true` means the opened directory can be scanned for the files and sub-directories
972 return self.openDirTraverseC(&sub_path_c);801 /// of the result. It means the `iterate` function can be called.
973 }802 iterate: bool = false,
803 };
974804
975 /// Opens a directory at the given path with the ability to access subpaths and list contents805 /// Opens a directory at the given path. The directory is a system resource that remains
976 /// of the result. If the ability to list contents is unneeded, `openDirTraverse` acts the806 /// open until `close` is called on the result.
977 /// same and may be more efficient.
978 ///
979 /// Call `close` on the result when done.
980 ///807 ///
981 /// Asserts that the path parameter has no null bytes.808 /// Asserts that the path parameter has no null bytes.
982 pub fn openDirList(self: Dir, sub_path: []const u8) OpenError!Dir {809 pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir {
983 if (builtin.os.tag == .windows) {810 if (builtin.os.tag == .windows) {
984 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);811 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
985 return self.openDirListW(&sub_path_w);812 return self.openDirW(&sub_path_w, args);
813 } else {
814 const sub_path_c = try os.toPosixPath(sub_path);
815 return self.openDirC(&sub_path_c, args);
986 }816 }
987
988 const sub_path_c = try os.toPosixPath(sub_path);
989 return self.openDirListC(&sub_path_c);
990 }817 }
991818
992 /// Same as `openDirTraverse` except the parameter is null-terminated.819 /// Same as `openDir` except the parameter is null-terminated.
993 pub fn openDirTraverseC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {820 pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir {
994 if (builtin.os.tag == .windows) {821 if (builtin.os.tag == .windows) {
995 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);822 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
996 return self.openDirTraverseW(&sub_path_w);823 return self.openDirW(&sub_path_w, args);
997 } else {824 } else if (!args.iterate) {
998 const O_PATH = if (@hasDecl(os, "O_PATH")) os.O_PATH else 0;825 const O_PATH = if (@hasDecl(os, "O_PATH")) os.O_PATH else 0;
999 return self.openDirFlagsC(sub_path_c, os.O_RDONLY | os.O_CLOEXEC | O_PATH);826 return self.openDirFlagsC(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC | O_PATH);
827 } else {
828 return self.openDirFlagsC(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC);
1000 }829 }
1001 }830 }
1002831
1003 /// Same as `openDirList` except the parameter is null-terminated.832 /// Same as `openDir` except the path parameter is WTF-16 encoded, NT-prefixed.
1004 pub fn openDirListC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {833 /// This function asserts the target OS is Windows.
1005 if (builtin.os.tag == .windows) {834 pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) OpenError!Dir {
1006 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);835 const w = os.windows;
1007 return self.openDirListW(&sub_path_w);836 // TODO remove some of these flags if args.access_sub_paths is false
1008 } else {837 const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |
1009 return self.openDirFlagsC(sub_path_c, os.O_RDONLY | os.O_CLOEXEC);838 w.SYNCHRONIZE | w.FILE_TRAVERSE;
1010 }839 const flags: u32 = if (args.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags;
840 return self.openDirAccessMaskW(sub_path_w, flags);
1011 }841 }
1012842
843 /// `flags` must contain `os.O_DIRECTORY`.
1013 fn openDirFlagsC(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir {844 fn openDirFlagsC(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir {
1014 const os_flags = flags | os.O_DIRECTORY;
1015 const result = if (need_async_thread)845 const result = if (need_async_thread)
1016 std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, os_flags, 0)846 std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, flags, 0)
1017 else847 else
1018 os.openatC(self.fd, sub_path_c, os_flags, 0);848 os.openatC(self.fd, sub_path_c, flags, 0);
1019 const fd = result catch |err| switch (err) {849 const fd = result catch |err| switch (err) {
1020 error.FileTooBig => unreachable, // can't happen for directories850 error.FileTooBig => unreachable, // can't happen for directories
1021 error.IsDir => unreachable, // we're providing O_DIRECTORY851 error.IsDir => unreachable, // we're providing O_DIRECTORY
...@@ -1026,22 +856,6 @@ pub const Dir = struct {...@@ -1026,22 +856,6 @@ pub const Dir = struct {
1026 return Dir{ .fd = fd };856 return Dir{ .fd = fd };
1027 }857 }
1028858
1029 /// Same as `openDirTraverse` except the path parameter is UTF16LE, NT-prefixed.
1030 /// This function is Windows-only.
1031 pub fn openDirTraverseW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
1032 const w = os.windows;
1033
1034 return self.openDirAccessMaskW(sub_path_w, w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | w.SYNCHRONIZE | w.FILE_TRAVERSE);
1035 }
1036
1037 /// Same as `openDirList` except the path parameter is UTF16LE, NT-prefixed.
1038 /// This function is Windows-only.
1039 pub fn openDirListW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
1040 const w = os.windows;
1041
1042 return self.openDirAccessMaskW(sub_path_w, w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | w.SYNCHRONIZE | w.FILE_TRAVERSE | w.FILE_LIST_DIRECTORY);
1043 }
1044
1045 fn openDirAccessMaskW(self: Dir, sub_path_w: [*:0]const u16, access_mask: u32) OpenError!Dir {859 fn openDirAccessMaskW(self: Dir, sub_path_w: [*:0]const u16, access_mask: u32) OpenError!Dir {
1046 const w = os.windows;860 const w = os.windows;
1047861
...@@ -1262,7 +1076,7 @@ pub const Dir = struct {...@@ -1262,7 +1076,7 @@ pub const Dir = struct {
1262 error.Unexpected,1076 error.Unexpected,
1263 => |e| return e,1077 => |e| return e,
1264 }1078 }
1265 var dir = self.openDirList(sub_path) catch |err| switch (err) {1079 var dir = self.openDir(sub_path, .{ .iterate = true }) catch |err| switch (err) {
1266 error.NotDir => {1080 error.NotDir => {
1267 if (got_access_denied) {1081 if (got_access_denied) {
1268 return error.AccessDenied;1082 return error.AccessDenied;
...@@ -1295,7 +1109,6 @@ pub const Dir = struct {...@@ -1295,7 +1109,6 @@ pub const Dir = struct {
12951109
1296 var dir_name_buf: [MAX_PATH_BYTES]u8 = undefined;1110 var dir_name_buf: [MAX_PATH_BYTES]u8 = undefined;
1297 var dir_name: []const u8 = sub_path;1111 var dir_name: []const u8 = sub_path;
1298 var parent_dir = self;
12991112
1300 // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function.1113 // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function.
1301 // Go through each entry and if it is not a directory, delete it. If it is a directory,1114 // Go through each entry and if it is not a directory, delete it. If it is a directory,
...@@ -1327,7 +1140,7 @@ pub const Dir = struct {...@@ -1327,7 +1140,7 @@ pub const Dir = struct {
1327 => |e| return e,1140 => |e| return e,
1328 }1141 }
13291142
1330 const new_dir = dir.openDirList(entry.name) catch |err| switch (err) {1143 const new_dir = dir.openDir(entry.name, .{ .iterate = true }) catch |err| switch (err) {
1331 error.NotDir => {1144 error.NotDir => {
1332 if (got_access_denied) {1145 if (got_access_denied) {
1333 return error.AccessDenied;1146 return error.AccessDenied;
...@@ -1434,9 +1247,96 @@ pub const Dir = struct {...@@ -1434,9 +1247,96 @@ pub const Dir = struct {
1434 pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void {1247 pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
1435 return os.faccessatW(self.fd, sub_path_w, 0, 0);1248 return os.faccessatW(self.fd, sub_path_w, 0, 0);
1436 }1249 }
1250
1251 /// Check the file size, mtime, and mode of `source_path` and `dest_path`. If they are equal, does nothing.
1252 /// Otherwise, atomically copies `source_path` to `dest_path`. The destination file gains the mtime,
1253 /// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
1254 /// Returns the previous status of the file before updating.
1255 /// If any of the directories do not exist for dest_path, they are created.
1256 pub fn updateFile(
1257 source_dir: Dir,
1258 source_path: []const u8,
1259 dest_dir: Dir,
1260 dest_path: []const u8,
1261 options: CopyFileOptions,
1262 ) !PrevStatus {
1263 var src_file = try source_dir.openFile(source_path, .{});
1264 defer src_file.close();
1265
1266 const src_stat = try src_file.stat();
1267 const actual_mode = options.override_mode orelse src_stat.mode;
1268 check_dest_stat: {
1269 const dest_stat = blk: {
1270 var dest_file = dest_dir.openFile(dest_path, .{}) catch |err| switch (err) {
1271 error.FileNotFound => break :check_dest_stat,
1272 else => |e| return e,
1273 };
1274 defer dest_file.close();
1275
1276 break :blk try dest_file.stat();
1277 };
1278
1279 if (src_stat.size == dest_stat.size and
1280 src_stat.mtime == dest_stat.mtime and
1281 actual_mode == dest_stat.mode)
1282 {
1283 return PrevStatus.fresh;
1284 }
1285 }
1286
1287 if (path.dirname(dest_path)) |dirname| {
1288 try dest_dir.makePath(dirname);
1289 }
1290
1291 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = actual_mode });
1292 defer atomic_file.deinit();
1293
1294 try atomic_file.file.writeFileAll(src_file, .{ .in_len = src_stat.size });
1295 try atomic_file.file.updateTimes(src_stat.atime, src_stat.mtime);
1296 try atomic_file.finish();
1297 return PrevStatus.stale;
1298 }
1299
1300 /// Guaranteed to be atomic.
1301 /// On Linux, until https://patchwork.kernel.org/patch/9636735/ is merged and readily available,
1302 /// there is a possibility of power loss or application termination leaving temporary files present
1303 /// in the same directory as dest_path.
1304 pub fn copyFile(
1305 source_dir: Dir,
1306 source_path: []const u8,
1307 dest_dir: Dir,
1308 dest_path: []const u8,
1309 options: CopyFileOptions,
1310 ) !void {
1311 var in_file = try source_dir.openFile(source_path, .{});
1312 defer in_file.close();
1313
1314 var size: ?u64 = null;
1315 const mode = options.override_mode orelse blk: {
1316 const stat = try in_file.stat();
1317 size = stat.size;
1318 break :blk stat.mode;
1319 };
1320
1321 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = mode });
1322 defer atomic_file.deinit();
1323
1324 try atomic_file.file.writeFileAll(in_file, .{ .in_len = size });
1325 return atomic_file.finish();
1326 }
1327
1328 pub const AtomicFileOptions = struct {
1329 mode: File.Mode = File.default_mode,
1330 };
1331
1332 /// `dest_path` must remain valid for the lifetime of `AtomicFile`.
1333 /// Call `AtomicFile.finish` to atomically replace `dest_path` with contents.
1334 pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions) !AtomicFile {
1335 return AtomicFile.init2(dest_path, options.mode, self);
1336 }
1437};1337};
14381338
1439/// Returns an handle to the current working directory that is open for traversal.1339/// Returns an handle to the current working directory. It is not opened with iteration capability.
1440/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.1340/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
1441/// On POSIX targets, this function is comptime-callable.1341/// On POSIX targets, this function is comptime-callable.
1442pub fn cwd() Dir {1342pub fn cwd() Dir {
...@@ -1514,6 +1414,25 @@ pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void...@@ -1514,6 +1414,25 @@ pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) DeleteFileError!void
1514 return cwd().deleteFileW(absolute_path_w);1414 return cwd().deleteFileW(absolute_path_w);
1515}1415}
15161416
1417/// Removes a symlink, file, or directory.
1418/// This is equivalent to `Dir.deleteTree` with the base directory.
1419/// Asserts that the path is absolute. See `Dir.deleteTree` for a function that
1420/// operates on both absolute and relative paths.
1421/// Asserts that the path parameter has no null bytes.
1422pub fn deleteTreeAbsolute(absolute_path: []const u8) !void {
1423 assert(path.isAbsolute(absolute_path));
1424 const dirname = path.dirname(absolute_path) orelse return error{
1425 /// Attempt to remove the root file system path.
1426 /// This error is unreachable if `absolute_path` is relative.
1427 CannotDeleteRootDirectory,
1428 }.CannotDeleteRootDirectory;
1429
1430 var dir = try cwd().openDir(dirname, .{});
1431 defer dir.close();
1432
1433 return dir.deleteTree(path.basename(absolute_path));
1434}
1435
1517pub const Walker = struct {1436pub const Walker = struct {
1518 stack: std.ArrayList(StackItem),1437 stack: std.ArrayList(StackItem),
1519 name_buffer: std.Buffer,1438 name_buffer: std.Buffer,
...@@ -1548,7 +1467,7 @@ pub const Walker = struct {...@@ -1548,7 +1467,7 @@ pub const Walker = struct {
1548 try self.name_buffer.appendByte(path.sep);1467 try self.name_buffer.appendByte(path.sep);
1549 try self.name_buffer.append(base.name);1468 try self.name_buffer.append(base.name);
1550 if (base.kind == .Directory) {1469 if (base.kind == .Directory) {
1551 var new_dir = top.dir_it.dir.openDirList(base.name) catch |err| switch (err) {1470 var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
1552 error.NameTooLong => unreachable, // no path sep in base.name1471 error.NameTooLong => unreachable, // no path sep in base.name
1553 else => |e| return e,1472 else => |e| return e,
1554 };1473 };
...@@ -1586,7 +1505,7 @@ pub const Walker = struct {...@@ -1586,7 +1505,7 @@ pub const Walker = struct {
1586pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {1505pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
1587 assert(!mem.endsWith(u8, dir_path, path.sep_str));1506 assert(!mem.endsWith(u8, dir_path, path.sep_str));
15881507
1589 var dir = try cwd().openDirList(dir_path);1508 var dir = try cwd().openDir(dir_path, .{ .iterate = true });
1590 errdefer dir.close();1509 errdefer dir.close();
15911510
1592 var name_buffer = try std.Buffer.init(allocator, dir_path);1511 var name_buffer = try std.Buffer.init(allocator, dir_path);
...@@ -1605,13 +1524,12 @@ pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {...@@ -1605,13 +1524,12 @@ pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker {
1605 return walker;1524 return walker;
1606}1525}
16071526
1608/// Read value of a symbolic link.1527/// Deprecated; use `Dir.readLink`.
1609/// The return value is a slice of buffer, from index `0`.
1610pub fn readLink(pathname: []const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {1528pub fn readLink(pathname: []const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
1611 return os.readlink(pathname, buffer);1529 return os.readlink(pathname, buffer);
1612}1530}
16131531
1614/// Same as `readLink`, except the parameter is null-terminated.1532/// Deprecated; use `Dir.readLinkC`.
1615pub fn readLinkC(pathname_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {1533pub fn readLinkC(pathname_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
1616 return os.readlinkC(pathname_c, buffer);1534 return os.readlinkC(pathname_c, buffer);
1617}1535}
...@@ -1718,6 +1636,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const...@@ -1718,6 +1636,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const
1718}1636}
17191637
1720/// `realpath`, except caller must free the returned memory.1638/// `realpath`, except caller must free the returned memory.
1639/// TODO integrate with `Dir`
1721pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {1640pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
1722 var buf: [MAX_PATH_BYTES]u8 = undefined;1641 var buf: [MAX_PATH_BYTES]u8 = undefined;
1723 return mem.dupe(allocator, u8, try os.realpath(pathname, &buf));1642 return mem.dupe(allocator, u8, try os.realpath(pathname, &buf));
...@@ -1726,6 +1645,9 @@ pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {...@@ -1726,6 +1645,9 @@ pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
1726test "" {1645test "" {
1727 _ = makeDirAbsolute;1646 _ = makeDirAbsolute;
1728 _ = makeDirAbsoluteZ;1647 _ = makeDirAbsoluteZ;
1648 _ = copyFileAbsolute;
1649 _ = updateFileAbsolute;
1650 _ = Dir.copyFile;
1729 _ = @import("fs/path.zig");1651 _ = @import("fs/path.zig");
1730 _ = @import("fs/file.zig");1652 _ = @import("fs/file.zig");
1731 _ = @import("fs/get_app_data_dir.zig");1653 _ = @import("fs/get_app_data_dir.zig");
lib/std/fs/watch.zig+1-1
...@@ -619,7 +619,7 @@ test "write a file, watch it, write it again" {...@@ -619,7 +619,7 @@ test "write a file, watch it, write it again" {
619 if (true) return error.SkipZigTest;619 if (true) return error.SkipZigTest;
620620
621 try fs.cwd().makePath(test_tmp_dir);621 try fs.cwd().makePath(test_tmp_dir);
622 defer os.deleteTree(test_tmp_dir) catch {};622 defer fs.cwd().deleteTree(test_tmp_dir) catch {};
623623
624 const allocator = std.heap.page_allocator;624 const allocator = std.heap.page_allocator;
625 return testFsWatch(&allocator);625 return testFsWatch(&allocator);
lib/std/hash/auto_hash.zig+8-4
...@@ -40,7 +40,9 @@ pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void {...@@ -40,7 +40,9 @@ pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void {
40 .DeepRecursive => hashArray(hasher, key, .DeepRecursive),40 .DeepRecursive => hashArray(hasher, key, .DeepRecursive),
41 },41 },
4242
43 .Many, .C, => switch (strat) {43 .Many,
44 .C,
45 => switch (strat) {
44 .Shallow => hash(hasher, @ptrToInt(key), .Shallow),46 .Shallow => hash(hasher, @ptrToInt(key), .Shallow),
45 else => @compileError(47 else => @compileError(
46 \\ unknown-length pointers and C pointers cannot be hashed deeply.48 \\ unknown-length pointers and C pointers cannot be hashed deeply.
...@@ -236,9 +238,11 @@ test "hash slice shallow" {...@@ -236,9 +238,11 @@ test "hash slice shallow" {
236 defer std.testing.allocator.destroy(array1);238 defer std.testing.allocator.destroy(array1);
237 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };239 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };
238 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };240 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };
239 const a = array1[0..];241 // TODO audit deep/shallow - maybe it has the wrong behavior with respect to array pointers and slices
240 const b = array2[0..];242 var runtime_zero: usize = 0;
241 const c = array1[0..3];243 const a = array1[runtime_zero..];
244 const b = array2[runtime_zero..];
245 const c = array1[runtime_zero..3];
242 testing.expect(testHashShallow(a) == testHashShallow(a));246 testing.expect(testHashShallow(a) == testHashShallow(a));
243 testing.expect(testHashShallow(a) != testHashShallow(array1));247 testing.expect(testHashShallow(a) != testHashShallow(array1));
244 testing.expect(testHashShallow(a) != testHashShallow(b));248 testing.expect(testHashShallow(a) != testHashShallow(b));
lib/std/hash/siphash.zig+3-3
...@@ -39,8 +39,8 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -39,8 +39,8 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
39 pub fn init(key: []const u8) Self {39 pub fn init(key: []const u8) Self {
40 assert(key.len >= 16);40 assert(key.len >= 16);
4141
42 const k0 = mem.readIntSliceLittle(u64, key[0..8]);42 const k0 = mem.readIntLittle(u64, key[0..8]);
43 const k1 = mem.readIntSliceLittle(u64, key[8..16]);43 const k1 = mem.readIntLittle(u64, key[8..16]);
4444
45 var d = Self{45 var d = Self{
46 .v0 = k0 ^ 0x736f6d6570736575,46 .v0 = k0 ^ 0x736f6d6570736575,
...@@ -111,7 +111,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -111,7 +111,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
111 fn round(self: *Self, b: []const u8) void {111 fn round(self: *Self, b: []const u8) void {
112 assert(b.len == 8);112 assert(b.len == 8);
113113
114 const m = mem.readIntSliceLittle(u64, b[0..]);114 const m = mem.readIntLittle(u64, b[0..8]);
115 self.v3 ^= m;115 self.v3 ^= m;
116116
117 // TODO this is a workaround, should be able to supply the value without a separate variable117 // TODO this is a workaround, should be able to supply the value without a separate variable
lib/std/hash/wyhash.zig+1-1
...@@ -11,7 +11,7 @@ const primes = [_]u64{...@@ -11,7 +11,7 @@ const primes = [_]u64{
1111
12fn read_bytes(comptime bytes: u8, data: []const u8) u64 {12fn read_bytes(comptime bytes: u8, data: []const u8) u64 {
13 const T = std.meta.IntType(false, 8 * bytes);13 const T = std.meta.IntType(false, 8 * bytes);
14 return mem.readIntSliceLittle(T, data[0..bytes]);14 return mem.readIntLittle(T, data[0..bytes]);
15}15}
1616
17fn read_8bytes_swapped(data: []const u8) u64 {17fn read_8bytes_swapped(data: []const u8) u64 {
lib/std/io/serialization.zig+5-1
...@@ -1,6 +1,10 @@...@@ -1,6 +1,10 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const builtin = std.builtin;2const builtin = std.builtin;
3const io = std.io;3const io = std.io;
4const assert = std.debug.assert;
5const math = std.math;
6const meta = std.meta;
7const trait = meta.trait;
48
5pub const Packing = enum {9pub const Packing = enum {
6 /// Pack data to byte alignment10 /// Pack data to byte alignment
...@@ -252,7 +256,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -252,7 +256,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
252 byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);256 byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
253 }257 }
254258
255 try self.out_stream.write(&buffer);259 try self.out_stream.writeAll(&buffer);
256 }260 }
257261
258 /// Serializes the passed value into the stream262 /// Serializes the passed value into the stream
lib/std/json.zig+16-7
...@@ -2249,11 +2249,16 @@ pub const StringifyOptions = struct {...@@ -2249,11 +2249,16 @@ pub const StringifyOptions = struct {
2249 // TODO: allow picking if []u8 is string or array?2249 // TODO: allow picking if []u8 is string or array?
2250};2250};
22512251
2252pub const StringifyError = error{
2253 TooMuchData,
2254 DifferentData,
2255};
2256
2252pub fn stringify(2257pub fn stringify(
2253 value: var,2258 value: var,
2254 options: StringifyOptions,2259 options: StringifyOptions,
2255 out_stream: var,2260 out_stream: var,
2256) !void {2261) StringifyError!void {
2257 const T = @TypeOf(value);2262 const T = @TypeOf(value);
2258 switch (@typeInfo(T)) {2263 switch (@typeInfo(T)) {
2259 .Float, .ComptimeFloat => {2264 .Float, .ComptimeFloat => {
...@@ -2320,9 +2325,15 @@ pub fn stringify(...@@ -2320,9 +2325,15 @@ pub fn stringify(
2320 return;2325 return;
2321 },2326 },
2322 .Pointer => |ptr_info| switch (ptr_info.size) {2327 .Pointer => |ptr_info| switch (ptr_info.size) {
2323 .One => {2328 .One => switch (@typeInfo(ptr_info.child)) {
2324 // TODO: avoid loops?2329 .Array => {
2325 return try stringify(value.*, options, out_stream);2330 const Slice = []const std.meta.Elem(ptr_info.child);
2331 return stringify(@as(Slice, value), options, out_stream);
2332 },
2333 else => {
2334 // TODO: avoid loops?
2335 return stringify(value.*, options, out_stream);
2336 },
2326 },2337 },
2327 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)2338 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
2328 .Slice => {2339 .Slice => {
...@@ -2381,9 +2392,7 @@ pub fn stringify(...@@ -2381,9 +2392,7 @@ pub fn stringify(
2381 },2392 },
2382 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),2393 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
2383 },2394 },
2384 .Array => |info| {2395 .Array => return stringify(&value, options, out_stream),
2385 return try stringify(value[0..], options, out_stream);
2386 },
2387 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),2396 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
2388 }2397 }
2389 unreachable;2398 unreachable;
lib/std/math/big/int.zig+25-4
...@@ -373,6 +373,7 @@ pub const Int = struct {...@@ -373,6 +373,7 @@ pub const Int = struct {
373 const d = switch (ch) {373 const d = switch (ch) {
374 '0'...'9' => ch - '0',374 '0'...'9' => ch - '0',
375 'a'...'f' => (ch - 'a') + 0xa,375 'a'...'f' => (ch - 'a') + 0xa,
376 'A'...'F' => (ch - 'A') + 0xa,
376 else => return error.InvalidCharForDigit,377 else => return error.InvalidCharForDigit,
377 };378 };
378379
...@@ -393,8 +394,9 @@ pub const Int = struct {...@@ -393,8 +394,9 @@ pub const Int = struct {
393394
394 /// Set self from the string representation `value`.395 /// Set self from the string representation `value`.
395 ///396 ///
396 /// value must contain only digits <= `base`. Base prefixes are not allowed (e.g. 0x43 should397 /// `value` must contain only digits <= `base` and is case insensitive. Base prefixes are
397 /// simply be 43).398 /// not allowed (e.g. 0x43 should simply be 43). Underscores in the input string are
399 /// ignored and can be used as digit separators.
398 ///400 ///
399 /// Returns an error if memory could not be allocated or `value` has invalid digits for the401 /// Returns an error if memory could not be allocated or `value` has invalid digits for the
400 /// requested base.402 /// requested base.
...@@ -415,6 +417,9 @@ pub const Int = struct {...@@ -415,6 +417,9 @@ pub const Int = struct {
415 try self.set(0);417 try self.set(0);
416418
417 for (value[i..]) |ch| {419 for (value[i..]) |ch| {
420 if (ch == '_') {
421 continue;
422 }
418 const d = try charToDigit(ch, base);423 const d = try charToDigit(ch, base);
419424
420 const ap_d = Int.initFixed(([_]Limb{d})[0..]);425 const ap_d = Int.initFixed(([_]Limb{d})[0..]);
...@@ -520,13 +525,13 @@ pub const Int = struct {...@@ -520,13 +525,13 @@ pub const Int = struct {
520 comptime fmt: []const u8,525 comptime fmt: []const u8,
521 options: std.fmt.FormatOptions,526 options: std.fmt.FormatOptions,
522 out_stream: var,527 out_stream: var,
523 ) FmtError!void {528 ) !void {
524 self.assertWritable();529 self.assertWritable();
525 // TODO look at fmt and support other bases530 // TODO look at fmt and support other bases
526 // TODO support read-only fixed integers531 // TODO support read-only fixed integers
527 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");532 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
528 defer self.allocator.?.free(str);533 defer self.allocator.?.free(str);
529 return out_stream.print(str);534 return out_stream.writeAll(str);
530 }535 }
531536
532 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.537 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
...@@ -1582,6 +1587,22 @@ test "big.int string negative" {...@@ -1582,6 +1587,22 @@ test "big.int string negative" {
1582 testing.expect((try a.to(i32)) == -1023);1587 testing.expect((try a.to(i32)) == -1023);
1583}1588}
15841589
1590test "big.int string set number with underscores" {
1591 var a = try Int.init(testing.allocator);
1592 defer a.deinit();
1593
1594 try a.setString(10, "__1_2_0_3_1_7_2_4_1_2_0_____9_1__2__4_7_8_1_2_4_1_2_9_0_8_4_7_1_2_4___");
1595 testing.expect((try a.to(u128)) == 120317241209124781241290847124);
1596}
1597
1598test "big.int string set case insensitive number" {
1599 var a = try Int.init(testing.allocator);
1600 defer a.deinit();
1601
1602 try a.setString(16, "aB_cD_eF");
1603 testing.expect((try a.to(u32)) == 0xabcdef);
1604}
1605
1585test "big.int string set bad char error" {1606test "big.int string set bad char error" {
1586 var a = try Int.init(testing.allocator);1607 var a = try Int.init(testing.allocator);
1587 defer a.deinit();1608 defer a.deinit();
lib/std/mem.zig+137-75
...@@ -116,7 +116,7 @@ pub const Allocator = struct {...@@ -116,7 +116,7 @@ pub const Allocator = struct {
116 pub fn allocSentinel(self: *Allocator, comptime Elem: type, n: usize, comptime sentinel: Elem) Error![:sentinel]Elem {116 pub fn allocSentinel(self: *Allocator, comptime Elem: type, n: usize, comptime sentinel: Elem) Error![:sentinel]Elem {
117 var ptr = try self.alloc(Elem, n + 1);117 var ptr = try self.alloc(Elem, n + 1);
118 ptr[n] = sentinel;118 ptr[n] = sentinel;
119 return ptr[0 .. n :sentinel];119 return ptr[0..n :sentinel];
120 }120 }
121121
122 pub fn alignedAlloc(122 pub fn alignedAlloc(
...@@ -496,14 +496,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {...@@ -496,14 +496,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
496 return true;496 return true;
497}497}
498498
499/// Deprecated. Use `span`.499/// Deprecated. Use `spanZ`.
500pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {500pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {
501 return ptr[0..len(ptr) :0];501 return ptr[0..lenZ(ptr) :0];
502}502}
503503
504/// Deprecated. Use `span`.504/// Deprecated. Use `spanZ`.
505pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {505pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
506 return ptr[0..len(ptr) :0];506 return ptr[0..lenZ(ptr) :0];
507}507}
508508
509/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and509/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
...@@ -548,6 +548,9 @@ test "Span" {...@@ -548,6 +548,9 @@ test "Span" {
548/// returns a slice. If there is a sentinel on the input type, there will be a548/// returns a slice. If there is a sentinel on the input type, there will be a
549/// sentinel on the output type. The constness of the output type matches549/// sentinel on the output type. The constness of the output type matches
550/// the constness of the input type.550/// the constness of the input type.
551///
552/// When there is both a sentinel and an array length or slice length, the
553/// length value is used instead of the sentinel.
551pub fn span(ptr: var) Span(@TypeOf(ptr)) {554pub fn span(ptr: var) Span(@TypeOf(ptr)) {
552 const Result = Span(@TypeOf(ptr));555 const Result = Span(@TypeOf(ptr));
553 const l = len(ptr);556 const l = len(ptr);
...@@ -560,20 +563,42 @@ pub fn span(ptr: var) Span(@TypeOf(ptr)) {...@@ -560,20 +563,42 @@ pub fn span(ptr: var) Span(@TypeOf(ptr)) {
560563
561test "span" {564test "span" {
562 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };565 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
563 const ptr = array[0..2 :3].ptr;566 const ptr = @as([*:3]u16, array[0..2 :3]);
564 testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 }));567 testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 }));
565 testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 }));568 testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 }));
566}569}
567570
571/// Same as `span`, except when there is both a sentinel and an array
572/// length or slice length, scans the memory for the sentinel value
573/// rather than using the length.
574pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) {
575 const Result = Span(@TypeOf(ptr));
576 const l = lenZ(ptr);
577 if (@typeInfo(Result).Pointer.sentinel) |s| {
578 return ptr[0..l :s];
579 } else {
580 return ptr[0..l];
581 }
582}
583
584test "spanZ" {
585 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
586 const ptr = @as([*:3]u16, array[0..2 :3]);
587 testing.expect(eql(u16, spanZ(ptr), &[_]u16{ 1, 2 }));
588 testing.expect(eql(u16, spanZ(&array), &[_]u16{ 1, 2, 3, 4, 5 }));
589}
590
568/// Takes a pointer to an array, an array, a sentinel-terminated pointer,591/// Takes a pointer to an array, an array, a sentinel-terminated pointer,
569/// or a slice, and returns the length.592/// or a slice, and returns the length.
593/// In the case of a sentinel-terminated array, it uses the array length.
594/// For C pointers it assumes it is a pointer-to-many with a 0 sentinel.
570pub fn len(ptr: var) usize {595pub fn len(ptr: var) usize {
571 return switch (@typeInfo(@TypeOf(ptr))) {596 return switch (@typeInfo(@TypeOf(ptr))) {
572 .Array => |info| info.len,597 .Array => |info| info.len,
573 .Pointer => |info| switch (info.size) {598 .Pointer => |info| switch (info.size) {
574 .One => switch (@typeInfo(info.child)) {599 .One => switch (@typeInfo(info.child)) {
575 .Array => |x| x.len,600 .Array => ptr.len,
576 else => @compileError("invalid type given to std.mem.length"),601 else => @compileError("invalid type given to std.mem.len"),
577 },602 },
578 .Many => if (info.sentinel) |sentinel|603 .Many => if (info.sentinel) |sentinel|
579 indexOfSentinel(info.child, sentinel, ptr)604 indexOfSentinel(info.child, sentinel, ptr)
...@@ -582,7 +607,7 @@ pub fn len(ptr: var) usize {...@@ -582,7 +607,7 @@ pub fn len(ptr: var) usize {
582 .C => indexOfSentinel(info.child, 0, ptr),607 .C => indexOfSentinel(info.child, 0, ptr),
583 .Slice => ptr.len,608 .Slice => ptr.len,
584 },609 },
585 else => @compileError("invalid type given to std.mem.length"),610 else => @compileError("invalid type given to std.mem.len"),
586 };611 };
587}612}
588613
...@@ -594,9 +619,67 @@ test "len" {...@@ -594,9 +619,67 @@ test "len" {
594 testing.expect(len(&array) == 5);619 testing.expect(len(&array) == 5);
595 testing.expect(len(array[0..3]) == 3);620 testing.expect(len(array[0..3]) == 3);
596 array[2] = 0;621 array[2] = 0;
597 const ptr = array[0..2 :0].ptr;622 const ptr = @as([*:0]u16, array[0..2 :0]);
598 testing.expect(len(ptr) == 2);623 testing.expect(len(ptr) == 2);
599 }624 }
625 {
626 var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 };
627 testing.expect(len(&array) == 5);
628 array[2] = 0;
629 testing.expect(len(&array) == 5);
630 }
631}
632
633/// Takes a pointer to an array, an array, a sentinel-terminated pointer,
634/// or a slice, and returns the length.
635/// In the case of a sentinel-terminated array, it scans the array
636/// for a sentinel and uses that for the length, rather than using the array length.
637/// For C pointers it assumes it is a pointer-to-many with a 0 sentinel.
638pub fn lenZ(ptr: var) usize {
639 return switch (@typeInfo(@TypeOf(ptr))) {
640 .Array => |info| if (info.sentinel) |sentinel|
641 indexOfSentinel(info.child, sentinel, &ptr)
642 else
643 info.len,
644 .Pointer => |info| switch (info.size) {
645 .One => switch (@typeInfo(info.child)) {
646 .Array => |x| if (x.sentinel) |sentinel|
647 indexOfSentinel(x.child, sentinel, ptr)
648 else
649 ptr.len,
650 else => @compileError("invalid type given to std.mem.lenZ"),
651 },
652 .Many => if (info.sentinel) |sentinel|
653 indexOfSentinel(info.child, sentinel, ptr)
654 else
655 @compileError("length of pointer with no sentinel"),
656 .C => indexOfSentinel(info.child, 0, ptr),
657 .Slice => if (info.sentinel) |sentinel|
658 indexOfSentinel(info.child, sentinel, ptr.ptr)
659 else
660 ptr.len,
661 },
662 else => @compileError("invalid type given to std.mem.lenZ"),
663 };
664}
665
666test "lenZ" {
667 testing.expect(lenZ("aoeu") == 4);
668
669 {
670 var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
671 testing.expect(lenZ(&array) == 5);
672 testing.expect(lenZ(array[0..3]) == 3);
673 array[2] = 0;
674 const ptr = @as([*:0]u16, array[0..2 :0]);
675 testing.expect(lenZ(ptr) == 2);
676 }
677 {
678 var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 };
679 testing.expect(lenZ(&array) == 5);
680 array[2] = 0;
681 testing.expect(lenZ(&array) == 2);
682 }
600}683}
601684
602pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {685pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {
...@@ -810,8 +893,7 @@ pub const readIntBig = switch (builtin.endian) {...@@ -810,8 +893,7 @@ pub const readIntBig = switch (builtin.endian) {
810pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {893pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
811 const n = @divExact(T.bit_count, 8);894 const n = @divExact(T.bit_count, 8);
812 assert(bytes.len >= n);895 assert(bytes.len >= n);
813 // TODO https://github.com/ziglang/zig/issues/863896 return readIntNative(T, bytes[0..n]);
814 return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr));
815}897}
816898
817/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0899/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
...@@ -849,8 +931,7 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, en...@@ -849,8 +931,7 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, en
849pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {931pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
850 const n = @divExact(T.bit_count, 8);932 const n = @divExact(T.bit_count, 8);
851 assert(bytes.len >= n);933 assert(bytes.len >= n);
852 // TODO https://github.com/ziglang/zig/issues/863934 return readInt(T, bytes[0..n], endian);
853 return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian);
854}935}
855936
856test "comptime read/write int" {937test "comptime read/write int" {
...@@ -1572,24 +1653,24 @@ pub fn nativeToBig(comptime T: type, x: T) T {...@@ -1572,24 +1653,24 @@ pub fn nativeToBig(comptime T: type, x: T) T {
1572}1653}
15731654
1574fn AsBytesReturnType(comptime P: type) type {1655fn AsBytesReturnType(comptime P: type) type {
1575 if (comptime !trait.isSingleItemPtr(P))1656 if (!trait.isSingleItemPtr(P))
1576 @compileError("expected single item pointer, passed " ++ @typeName(P));1657 @compileError("expected single item pointer, passed " ++ @typeName(P));
15771658
1578 const size = @as(usize, @sizeOf(meta.Child(P)));1659 const size = @sizeOf(meta.Child(P));
1579 const alignment = comptime meta.alignment(P);1660 const alignment = meta.alignment(P);
15801661
1581 if (alignment == 0) {1662 if (alignment == 0) {
1582 if (comptime trait.isConstPtr(P))1663 if (trait.isConstPtr(P))
1583 return *const [size]u8;1664 return *const [size]u8;
1584 return *[size]u8;1665 return *[size]u8;
1585 }1666 }
15861667
1587 if (comptime trait.isConstPtr(P))1668 if (trait.isConstPtr(P))
1588 return *align(alignment) const [size]u8;1669 return *align(alignment) const [size]u8;
1589 return *align(alignment) [size]u8;1670 return *align(alignment) [size]u8;
1590}1671}
15911672
1592///Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness.1673/// Given a pointer to a single item, returns a slice of the underlying bytes, preserving constness.
1593pub fn asBytes(ptr: var) AsBytesReturnType(@TypeOf(ptr)) {1674pub fn asBytes(ptr: var) AsBytesReturnType(@TypeOf(ptr)) {
1594 const P = @TypeOf(ptr);1675 const P = @TypeOf(ptr);
1595 return @ptrCast(AsBytesReturnType(P), ptr);1676 return @ptrCast(AsBytesReturnType(P), ptr);
...@@ -1736,34 +1817,50 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {...@@ -1736,34 +1817,50 @@ fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {
1736}1817}
17371818
1738pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) {1819pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) {
1739 const bytesSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(bytes))) bytes[0..] else bytes;
1740
1741 // let's not give an undefined pointer to @ptrCast1820 // let's not give an undefined pointer to @ptrCast
1742 // it may be equal to zero and fail a null check1821 // it may be equal to zero and fail a null check
1743 if (bytesSlice.len == 0) {1822 if (bytes.len == 0) {
1744 return &[0]T{};1823 return &[0]T{};
1745 }1824 }
17461825
1747 const bytesType = @TypeOf(bytesSlice);1826 const Bytes = @TypeOf(bytes);
1748 const alignment = comptime meta.alignment(bytesType);1827 const alignment = comptime meta.alignment(Bytes);
17491828
1750 const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T;1829 const cast_target = if (comptime trait.isConstPtr(Bytes)) [*]align(alignment) const T else [*]align(alignment) T;
17511830
1752 return @ptrCast(castTarget, bytesSlice.ptr)[0..@divExact(bytes.len, @sizeOf(T))];1831 return @ptrCast(cast_target, bytes)[0..@divExact(bytes.len, @sizeOf(T))];
1753}1832}
17541833
1755test "bytesAsSlice" {1834test "bytesAsSlice" {
1756 const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };1835 {
1757 const slice = bytesAsSlice(u16, bytes[0..]);1836 const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
1758 testing.expect(slice.len == 2);1837 const slice = bytesAsSlice(u16, bytes[0..]);
1759 testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);1838 testing.expect(slice.len == 2);
1760 testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);1839 testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
1840 testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
1841 }
1842 {
1843 const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
1844 var runtime_zero: usize = 0;
1845 const slice = bytesAsSlice(u16, bytes[runtime_zero..]);
1846 testing.expect(slice.len == 2);
1847 testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
1848 testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
1849 }
1761}1850}
17621851
1763test "bytesAsSlice keeps pointer alignment" {1852test "bytesAsSlice keeps pointer alignment" {
1764 var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };1853 {
1765 const numbers = bytesAsSlice(u32, bytes[0..]);1854 var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
1766 comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);1855 const numbers = bytesAsSlice(u32, bytes[0..]);
1856 comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
1857 }
1858 {
1859 var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
1860 var runtime_zero: usize = 0;
1861 const numbers = bytesAsSlice(u32, bytes[runtime_zero..]);
1862 comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
1863 }
1767}1864}
17681865
1769test "bytesAsSlice on a packed struct" {1866test "bytesAsSlice on a packed struct" {
...@@ -1799,21 +1896,19 @@ fn SliceAsBytesReturnType(comptime sliceType: type) type {...@@ -1799,21 +1896,19 @@ fn SliceAsBytesReturnType(comptime sliceType: type) type {
1799}1896}
18001897
1801pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {1898pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {
1802 const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice;1899 const Slice = @TypeOf(slice);
1803 const actualSliceTypeInfo = @typeInfo(@TypeOf(actualSlice)).Pointer;
18041900
1805 // let's not give an undefined pointer to @ptrCast1901 // let's not give an undefined pointer to @ptrCast
1806 // it may be equal to zero and fail a null check1902 // it may be equal to zero and fail a null check
1807 if (actualSlice.len == 0 and actualSliceTypeInfo.sentinel == null) {1903 if (slice.len == 0 and comptime meta.sentinel(Slice) == null) {
1808 return &[0]u8{};1904 return &[0]u8{};
1809 }1905 }
18101906
1811 const sliceType = @TypeOf(actualSlice);1907 const alignment = comptime meta.alignment(Slice);
1812 const alignment = comptime meta.alignment(sliceType);
18131908
1814 const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8;1909 const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8;
18151910
1816 return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))];1911 return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Elem(Slice))];
1817}1912}
18181913
1819test "sliceAsBytes" {1914test "sliceAsBytes" {
...@@ -1883,39 +1978,6 @@ test "sliceAsBytes and bytesAsSlice back" {...@@ -1883,39 +1978,6 @@ test "sliceAsBytes and bytesAsSlice back" {
1883 testing.expect(bytes[11] == math.maxInt(u8));1978 testing.expect(bytes[11] == math.maxInt(u8));
1884}1979}
18851980
1886fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
1887 if (trait.isConstPtr(T))
1888 return *const [length]meta.Child(meta.Child(T));
1889 return *[length]meta.Child(meta.Child(T));
1890}
1891
1892/// Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.
1893/// TODO this will be obsoleted by https://github.com/ziglang/zig/issues/863
1894pub fn subArrayPtr(
1895 ptr: var,
1896 comptime start: usize,
1897 comptime length: usize,
1898) SubArrayPtrReturnType(@TypeOf(ptr), length) {
1899 assert(start + length <= ptr.*.len);
1900
1901 const ReturnType = SubArrayPtrReturnType(@TypeOf(ptr), length);
1902 const T = meta.Child(meta.Child(@TypeOf(ptr)));
1903 return @ptrCast(ReturnType, &ptr[start]);
1904}
1905
1906test "subArrayPtr" {
1907 const a1: [6]u8 = "abcdef".*;
1908 const sub1 = subArrayPtr(&a1, 2, 3);
1909 testing.expect(eql(u8, sub1, "cde"));
1910
1911 var a2: [6]u8 = "abcdef".*;
1912 var sub2 = subArrayPtr(&a2, 2, 3);
1913
1914 testing.expect(eql(u8, sub2, "cde"));
1915 sub2[1] = 'X';
1916 testing.expect(eql(u8, &a2, "abcXef"));
1917}
1918
1919/// Round an address up to the nearest aligned address1981/// Round an address up to the nearest aligned address
1920/// The alignment must be a power of 2 and greater than 0.1982/// The alignment must be a power of 2 and greater than 0.
1921pub fn alignForward(addr: usize, alignment: usize) usize {1983pub fn alignForward(addr: usize, alignment: usize) usize {
lib/std/meta.zig+50-15
...@@ -104,7 +104,7 @@ pub fn Child(comptime T: type) type {...@@ -104,7 +104,7 @@ pub fn Child(comptime T: type) type {
104 .Array => |info| info.child,104 .Array => |info| info.child,
105 .Pointer => |info| info.child,105 .Pointer => |info| info.child,
106 .Optional => |info| info.child,106 .Optional => |info| info.child,
107 else => @compileError("Expected pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"),107 else => @compileError("Expected pointer, optional, or array type, found '" ++ @typeName(T) ++ "'"),
108 };108 };
109}109}
110110
...@@ -115,30 +115,65 @@ test "std.meta.Child" {...@@ -115,30 +115,65 @@ test "std.meta.Child" {
115 testing.expect(Child(?u8) == u8);115 testing.expect(Child(?u8) == u8);
116}116}
117117
118/// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel118/// Given a "memory span" type, returns the "element type".
119pub fn Sentinel(comptime T: type) Child(T) {119pub fn Elem(comptime T: type) type {
120 // comptime asserts that ptr has a sentinel
121 switch (@typeInfo(T)) {120 switch (@typeInfo(T)) {
122 .Array => |arrayInfo| {121 .Array => |info| return info.child,
123 return comptime arrayInfo.sentinel.?;122 .Pointer => |info| switch (info.size) {
123 .One => switch (@typeInfo(info.child)) {
124 .Array => |array_info| return array_info.child,
125 else => {},
126 },
127 .Many, .C, .Slice => return info.child,
124 },128 },
125 .Pointer => |ptrInfo| {129 else => {},
126 switch (ptrInfo.size) {130 }
127 .Many, .Slice => {131 @compileError("Expected pointer, slice, or array, found '" ++ @typeName(T) ++ "'");
128 return comptime ptrInfo.sentinel.?;132}
133
134test "std.meta.Elem" {
135 testing.expect(Elem([1]u8) == u8);
136 testing.expect(Elem([*]u8) == u8);
137 testing.expect(Elem([]u8) == u8);
138 testing.expect(Elem(*[10]u8) == u8);
139}
140
141/// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value,
142/// or `null` if there is not one.
143/// Types which cannot possibly have a sentinel will be a compile error.
144pub fn sentinel(comptime T: type) ?Elem(T) {
145 switch (@typeInfo(T)) {
146 .Array => |info| return info.sentinel,
147 .Pointer => |info| {
148 switch (info.size) {
149 .Many, .Slice => return info.sentinel,
150 .One => switch (@typeInfo(info.child)) {
151 .Array => |array_info| return array_info.sentinel,
152 else => {},
129 },153 },
130 else => {},154 else => {},
131 }155 }
132 },156 },
133 else => {},157 else => {},
134 }158 }
135 @compileError("not a sentinel type, found '" ++ @typeName(T) ++ "'");159 @compileError("type '" ++ @typeName(T) ++ "' cannot possibly have a sentinel");
136}160}
137161
138test "std.meta.Sentinel" {162test "std.meta.sentinel" {
139 testing.expectEqual(@as(u8, 0), Sentinel([:0]u8));163 testSentinel();
140 testing.expectEqual(@as(u8, 0), Sentinel([*:0]u8));164 comptime testSentinel();
141 testing.expectEqual(@as(u8, 0), Sentinel([5:0]u8));165}
166
167fn testSentinel() void {
168 testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?);
169 testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?);
170 testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?);
171 testing.expectEqual(@as(u8, 0), sentinel(*const [5:0]u8).?);
172
173 testing.expect(sentinel([]u8) == null);
174 testing.expect(sentinel([*]u8) == null);
175 testing.expect(sentinel([5]u8) == null);
176 testing.expect(sentinel(*const [5]u8) == null);
142}177}
143178
144pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {179pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
lib/std/meta/trait.zig+7-5
...@@ -230,9 +230,10 @@ pub fn isSingleItemPtr(comptime T: type) bool {...@@ -230,9 +230,10 @@ pub fn isSingleItemPtr(comptime T: type) bool {
230230
231test "std.meta.trait.isSingleItemPtr" {231test "std.meta.trait.isSingleItemPtr" {
232 const array = [_]u8{0} ** 10;232 const array = [_]u8{0} ** 10;
233 testing.expect(isSingleItemPtr(@TypeOf(&array[0])));233 comptime testing.expect(isSingleItemPtr(@TypeOf(&array[0])));
234 testing.expect(!isSingleItemPtr(@TypeOf(array)));234 comptime testing.expect(!isSingleItemPtr(@TypeOf(array)));
235 testing.expect(!isSingleItemPtr(@TypeOf(array[0..1])));235 var runtime_zero: usize = 0;
236 testing.expect(!isSingleItemPtr(@TypeOf(array[runtime_zero..1])));
236}237}
237238
238pub fn isManyItemPtr(comptime T: type) bool {239pub fn isManyItemPtr(comptime T: type) bool {
...@@ -259,7 +260,8 @@ pub fn isSlice(comptime T: type) bool {...@@ -259,7 +260,8 @@ pub fn isSlice(comptime T: type) bool {
259260
260test "std.meta.trait.isSlice" {261test "std.meta.trait.isSlice" {
261 const array = [_]u8{0} ** 10;262 const array = [_]u8{0} ** 10;
262 testing.expect(isSlice(@TypeOf(array[0..])));263 var runtime_zero: usize = 0;
264 testing.expect(isSlice(@TypeOf(array[runtime_zero..])));
263 testing.expect(!isSlice(@TypeOf(array)));265 testing.expect(!isSlice(@TypeOf(array)));
264 testing.expect(!isSlice(@TypeOf(&array[0])));266 testing.expect(!isSlice(@TypeOf(&array[0])));
265}267}
...@@ -276,7 +278,7 @@ pub fn isIndexable(comptime T: type) bool {...@@ -276,7 +278,7 @@ pub fn isIndexable(comptime T: type) bool {
276278
277test "std.meta.trait.isIndexable" {279test "std.meta.trait.isIndexable" {
278 const array = [_]u8{0} ** 10;280 const array = [_]u8{0} ** 10;
279 const slice = array[0..];281 const slice = @as([]const u8, &array);
280282
281 testing.expect(isIndexable(@TypeOf(array)));283 testing.expect(isIndexable(@TypeOf(array)));
282 testing.expect(isIndexable(@TypeOf(&array)));284 testing.expect(isIndexable(@TypeOf(&array)));
lib/std/net.zig+6-4
...@@ -612,8 +612,7 @@ fn linuxLookupName(...@@ -612,8 +612,7 @@ fn linuxLookupName(
612 } else {612 } else {
613 mem.copy(u8, &sa6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");613 mem.copy(u8, &sa6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");
614 mem.copy(u8, &da6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");614 mem.copy(u8, &da6.addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff");
615 // TODO https://github.com/ziglang/zig/issues/863615 mem.writeIntNative(u32, da6.addr[12..], addr.addr.in.addr);
616 mem.writeIntNative(u32, @ptrCast(*[4]u8, da6.addr[12..].ptr), addr.addr.in.addr);
617 da4.addr = addr.addr.in.addr;616 da4.addr = addr.addr.in.addr;
618 da = @ptrCast(*os.sockaddr, &da4);617 da = @ptrCast(*os.sockaddr, &da4);
619 dalen = @sizeOf(os.sockaddr_in);618 dalen = @sizeOf(os.sockaddr_in);
...@@ -821,7 +820,7 @@ fn linuxLookupNameFromHosts(...@@ -821,7 +820,7 @@ fn linuxLookupNameFromHosts(
821 // Skip to the delimiter in the stream, to fix parsing820 // Skip to the delimiter in the stream, to fix parsing
822 try stream.skipUntilDelimiterOrEof('\n');821 try stream.skipUntilDelimiterOrEof('\n');
823 // Use the truncated line. A truncated comment or hostname will be handled correctly.822 // Use the truncated line. A truncated comment or hostname will be handled correctly.
824 break :blk line_buf[0..];823 break :blk &line_buf;
825 },824 },
826 else => |e| return e,825 else => |e| return e,
827 }) |line| {826 }) |line| {
...@@ -958,7 +957,10 @@ fn linuxLookupNameFromDns(...@@ -958,7 +957,10 @@ fn linuxLookupNameFromDns(
958 }957 }
959 }958 }
960959
961 var ap = [2][]u8{ apbuf[0][0..0], apbuf[1][0..0] };960 var ap = [2][]u8{ apbuf[0], apbuf[1] };
961 ap[0].len = 0;
962 ap[1].len = 0;
963
962 try resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq], rc);964 try resMSendRc(qp[0..nq], ap[0..nq], apbuf[0..nq], rc);
963965
964 var i: usize = 0;966 var i: usize = 0;
lib/std/os.zig+143-23
...@@ -461,13 +461,11 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {...@@ -461,13 +461,11 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
461 );461 );
462462
463 switch (rc) {463 switch (rc) {
464 .SUCCESS => {},464 .SUCCESS => return,
465 .INVALID_HANDLE => unreachable, // Handle not open for writing465 .INVALID_HANDLE => unreachable, // Handle not open for writing
466 .ACCESS_DENIED => return error.CannotTruncate,466 .ACCESS_DENIED => return error.CannotTruncate,
467 else => return windows.unexpectedStatus(rc),467 else => return windows.unexpectedStatus(rc),
468 }468 }
469
470 return;
471 }469 }
472470
473 while (true) {471 while (true) {
...@@ -852,6 +850,7 @@ pub const OpenError = error{...@@ -852,6 +850,7 @@ pub const OpenError = error{
852850
853/// Open and possibly create a file. Keeps trying if it gets interrupted.851/// Open and possibly create a file. Keeps trying if it gets interrupted.
854/// See also `openC`.852/// See also `openC`.
853/// TODO support windows
855pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {854pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
856 const file_path_c = try toPosixPath(file_path);855 const file_path_c = try toPosixPath(file_path);
857 return openC(&file_path_c, flags, perm);856 return openC(&file_path_c, flags, perm);
...@@ -859,6 +858,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {...@@ -859,6 +858,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
859858
860/// Open and possibly create a file. Keeps trying if it gets interrupted.859/// Open and possibly create a file. Keeps trying if it gets interrupted.
861/// See also `open`.860/// See also `open`.
861/// TODO support windows
862pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {862pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
863 while (true) {863 while (true) {
864 const rc = system.open(file_path, flags, perm);864 const rc = system.open(file_path, flags, perm);
...@@ -892,6 +892,7 @@ pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {...@@ -892,6 +892,7 @@ pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
892/// Open and possibly create a file. Keeps trying if it gets interrupted.892/// Open and possibly create a file. Keeps trying if it gets interrupted.
893/// `file_path` is relative to the open directory handle `dir_fd`.893/// `file_path` is relative to the open directory handle `dir_fd`.
894/// See also `openatC`.894/// See also `openatC`.
895/// TODO support windows
895pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t {896pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t {
896 const file_path_c = try toPosixPath(file_path);897 const file_path_c = try toPosixPath(file_path);
897 return openatC(dir_fd, &file_path_c, flags, mode);898 return openatC(dir_fd, &file_path_c, flags, mode);
...@@ -900,6 +901,7 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope...@@ -900,6 +901,7 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope
900/// Open and possibly create a file. Keeps trying if it gets interrupted.901/// Open and possibly create a file. Keeps trying if it gets interrupted.
901/// `file_path` is relative to the open directory handle `dir_fd`.902/// `file_path` is relative to the open directory handle `dir_fd`.
902/// See also `openat`.903/// See also `openat`.
904/// TODO support windows
903pub fn openatC(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) OpenError!fd_t {905pub fn openatC(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) OpenError!fd_t {
904 while (true) {906 while (true) {
905 const rc = system.openat(dir_fd, file_path, flags, mode);907 const rc = system.openat(dir_fd, file_path, flags, mode);
...@@ -1140,24 +1142,6 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8)...@@ -1140,24 +1142,6 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8)
1140 allocator.free(envp_buf);1142 allocator.free(envp_buf);
1141}1143}
11421144
1143pub const FcntlError = error{
1144 /// The file is locked by another process
1145 FileLocked,
1146} || UnexpectedError;
1147
1148/// Attempts to get lock the file, blocking if the file is locked.
1149pub fn fcntl(fd: fd_t, cmd: i32, flock_p: *Flock) FcntlError!void {
1150 while (true) {
1151 switch (errno(system.fcntl(fd, cmd, flock_p))) {
1152 0 => return,
1153 EACCES => return error.FileLocked,
1154 EAGAIN => return error.FileLocked,
1155 EINTR => continue,
1156 else => |err| return unexpectedErrno(err),
1157 }
1158 }
1159}
1160
1161/// Get an environment variable.1145/// Get an environment variable.
1162/// See also `getenvZ`.1146/// See also `getenvZ`.
1163pub fn getenv(key: []const u8) ?[]const u8 {1147pub fn getenv(key: []const u8) ?[]const u8 {
...@@ -1545,6 +1529,9 @@ const RenameError = error{...@@ -1545,6 +1529,9 @@ const RenameError = error{
1545 RenameAcrossMountPoints,1529 RenameAcrossMountPoints,
1546 InvalidUtf8,1530 InvalidUtf8,
1547 BadPathName,1531 BadPathName,
1532 NoDevice,
1533 SharingViolation,
1534 PipeBusy,
1548} || UnexpectedError;1535} || UnexpectedError;
15491536
1550/// Change the name or location of a file.1537/// Change the name or location of a file.
...@@ -1598,6 +1585,113 @@ pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!v...@@ -1598,6 +1585,113 @@ pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!v
1598 return windows.MoveFileExW(old_path, new_path, flags);1585 return windows.MoveFileExW(old_path, new_path, flags);
1599}1586}
16001587
1588/// Change the name or location of a file based on an open directory handle.
1589pub fn renameat(
1590 old_dir_fd: fd_t,
1591 old_path: []const u8,
1592 new_dir_fd: fd_t,
1593 new_path: []const u8,
1594) RenameError!void {
1595 if (builtin.os.tag == .windows) {
1596 const old_path_w = try windows.sliceToPrefixedFileW(old_path);
1597 const new_path_w = try windows.sliceToPrefixedFileW(new_path);
1598 return renameatW(old_dir_fd, &old_path_w, new_dir_fd, &new_path_w, windows.TRUE);
1599 } else {
1600 const old_path_c = try toPosixPath(old_path);
1601 const new_path_c = try toPosixPath(new_path);
1602 return renameatZ(old_dir_fd, &old_path_c, new_dir_fd, &new_path_c);
1603 }
1604}
1605
1606/// Same as `renameat` except the parameters are null-terminated byte arrays.
1607pub fn renameatZ(
1608 old_dir_fd: fd_t,
1609 old_path: [*:0]const u8,
1610 new_dir_fd: fd_t,
1611 new_path: [*:0]const u8,
1612) RenameError!void {
1613 if (builtin.os.tag == .windows) {
1614 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
1615 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
1616 return renameatW(old_dir_fd, &old_path_w, new_dir_fd, &new_path_w, windows.TRUE);
1617 }
1618
1619 switch (errno(system.renameat(old_dir_fd, old_path, new_dir_fd, new_path))) {
1620 0 => return,
1621 EACCES => return error.AccessDenied,
1622 EPERM => return error.AccessDenied,
1623 EBUSY => return error.FileBusy,
1624 EDQUOT => return error.DiskQuota,
1625 EFAULT => unreachable,
1626 EINVAL => unreachable,
1627 EISDIR => return error.IsDir,
1628 ELOOP => return error.SymLinkLoop,
1629 EMLINK => return error.LinkQuotaExceeded,
1630 ENAMETOOLONG => return error.NameTooLong,
1631 ENOENT => return error.FileNotFound,
1632 ENOTDIR => return error.NotDir,
1633 ENOMEM => return error.SystemResources,
1634 ENOSPC => return error.NoSpaceLeft,
1635 EEXIST => return error.PathAlreadyExists,
1636 ENOTEMPTY => return error.PathAlreadyExists,
1637 EROFS => return error.ReadOnlyFileSystem,
1638 EXDEV => return error.RenameAcrossMountPoints,
1639 else => |err| return unexpectedErrno(err),
1640 }
1641}
1642
1643/// Same as `renameat` except the parameters are null-terminated UTF16LE encoded byte arrays.
1644/// Assumes target is Windows.
1645/// TODO these args can actually be slices when using ntdll. audit the rest of the W functions too.
1646pub fn renameatW(
1647 old_dir_fd: fd_t,
1648 old_path: [*:0]const u16,
1649 new_dir_fd: fd_t,
1650 new_path_w: [*:0]const u16,
1651 ReplaceIfExists: windows.BOOLEAN,
1652) RenameError!void {
1653 const access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE;
1654 const src_fd = try windows.OpenFileW(old_dir_fd, old_path, null, access_mask, windows.FILE_OPEN);
1655 defer windows.CloseHandle(src_fd);
1656
1657 const struct_buf_len = @sizeOf(windows.FILE_RENAME_INFORMATION) + (MAX_PATH_BYTES - 1);
1658 var rename_info_buf: [struct_buf_len]u8 align(@alignOf(windows.FILE_RENAME_INFORMATION)) = undefined;
1659 const new_path = mem.span(new_path_w);
1660 const struct_len = @sizeOf(windows.FILE_RENAME_INFORMATION) - 1 + new_path.len * 2;
1661 if (struct_len > struct_buf_len) return error.NameTooLong;
1662
1663 const rename_info = @ptrCast(*windows.FILE_RENAME_INFORMATION, &rename_info_buf);
1664
1665 rename_info.* = .{
1666 .ReplaceIfExists = ReplaceIfExists,
1667 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(new_path_w)) null else new_dir_fd,
1668 .FileNameLength = @intCast(u32, new_path.len * 2), // already checked error.NameTooLong
1669 .FileName = undefined,
1670 };
1671 std.mem.copy(u16, @as([*]u16, &rename_info.FileName)[0..new_path.len], new_path);
1672
1673 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
1674
1675 const rc = windows.ntdll.NtSetInformationFile(
1676 src_fd,
1677 &io_status_block,
1678 rename_info,
1679 @intCast(u32, struct_len), // already checked for error.NameTooLong
1680 .FileRenameInformation,
1681 );
1682
1683 switch (rc) {
1684 .SUCCESS => return,
1685 .INVALID_HANDLE => unreachable,
1686 .INVALID_PARAMETER => unreachable,
1687 .OBJECT_PATH_SYNTAX_BAD => unreachable,
1688 .ACCESS_DENIED => return error.AccessDenied,
1689 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
1690 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
1691 else => return windows.unexpectedStatus(rc),
1692 }
1693}
1694
1601pub const MakeDirError = error{1695pub const MakeDirError = error{
1602 AccessDenied,1696 AccessDenied,
1603 DiskQuota,1697 DiskQuota,
...@@ -2090,7 +2184,7 @@ const ListenError = error{...@@ -2090,7 +2184,7 @@ const ListenError = error{
2090 OperationNotSupported,2184 OperationNotSupported,
2091} || UnexpectedError;2185} || UnexpectedError;
20922186
2093pub fn listen(sockfd: i32, backlog: u32) ListenError!void {2187pub fn listen(sockfd: fd_t, backlog: u32) ListenError!void {
2094 const rc = system.listen(sockfd, backlog);2188 const rc = system.listen(sockfd, backlog);
2095 switch (errno(rc)) {2189 switch (errno(rc)) {
2096 0 => return,2190 0 => return,
...@@ -2381,7 +2475,7 @@ pub fn connect(sockfd: fd_t, sock_addr: *const sockaddr, len: socklen_t) Connect...@@ -2381,7 +2475,7 @@ pub fn connect(sockfd: fd_t, sock_addr: *const sockaddr, len: socklen_t) Connect
2381 }2475 }
2382}2476}
23832477
2384pub fn getsockoptError(sockfd: i32) ConnectError!void {2478pub fn getsockoptError(sockfd: fd_t) ConnectError!void {
2385 var err_code: u32 = undefined;2479 var err_code: u32 = undefined;
2386 var size: u32 = @sizeOf(u32);2480 var size: u32 = @sizeOf(u32);
2387 const rc = system.getsockopt(sockfd, SOL_SOCKET, SO_ERROR, @ptrCast([*]u8, &err_code), &size);2481 const rc = system.getsockopt(sockfd, SOL_SOCKET, SO_ERROR, @ptrCast([*]u8, &err_code), &size);
...@@ -3069,6 +3163,31 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {...@@ -3069,6 +3163,31 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
3069 }3163 }
3070}3164}
30713165
3166pub const FcntlError = error{
3167 PermissionDenied,
3168 FileBusy,
3169 ProcessFdQuotaExceeded,
3170 Locked,
3171} || UnexpectedError;
3172
3173pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize {
3174 while (true) {
3175 const rc = system.fcntl(fd, cmd, arg);
3176 switch (errno(rc)) {
3177 0 => return @intCast(usize, rc),
3178 EINTR => continue,
3179 EACCES => return error.Locked,
3180 EBADF => unreachable,
3181 EBUSY => return error.FileBusy,
3182 EINVAL => unreachable, // invalid parameters
3183 EPERM => return error.PermissionDenied,
3184 EMFILE => return error.ProcessFdQuotaExceeded,
3185 ENOTDIR => unreachable, // invalid parameter
3186 else => |err| return unexpectedErrno(err),
3187 }
3188 }
3189}
3190
3072pub const RealPathError = error{3191pub const RealPathError = error{
3073 FileNotFound,3192 FileNotFound,
3074 AccessDenied,3193 AccessDenied,
...@@ -3143,6 +3262,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP...@@ -3143,6 +3262,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
3143}3262}
31443263
3145/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.3264/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.
3265/// TODO use ntdll for better semantics
3146pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {3266pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
3147 const h_file = try windows.CreateFileW(3267 const h_file = try windows.CreateFileW(
3148 pathname,3268 pathname,
lib/std/os/bits/dragonfly.zig+2
...@@ -283,6 +283,8 @@ pub const F_LOCK = 1;...@@ -283,6 +283,8 @@ pub const F_LOCK = 1;
283pub const F_TLOCK = 2;283pub const F_TLOCK = 2;
284pub const F_TEST = 3;284pub const F_TEST = 3;
285285
286pub const FD_CLOEXEC = 1;
287
286pub const AT_FDCWD = -328243;288pub const AT_FDCWD = -328243;
287pub const AT_SYMLINK_NOFOLLOW = 1;289pub const AT_SYMLINK_NOFOLLOW = 1;
288pub const AT_REMOVEDIR = 2;290pub const AT_REMOVEDIR = 2;
lib/std/os/bits/freebsd.zig+2
...@@ -372,6 +372,8 @@ pub const F_GETOWN_EX = 16;...@@ -372,6 +372,8 @@ pub const F_GETOWN_EX = 16;
372372
373pub const F_GETOWNER_UIDS = 17;373pub const F_GETOWNER_UIDS = 17;
374374
375pub const FD_CLOEXEC = 1;
376
375pub const SEEK_SET = 0;377pub const SEEK_SET = 0;
376pub const SEEK_CUR = 1;378pub const SEEK_CUR = 1;
377pub const SEEK_END = 2;379pub const SEEK_END = 2;
lib/std/os/bits/linux.zig+2
...@@ -136,6 +136,8 @@ pub const MAP_FIXED_NOREPLACE = 0x100000;...@@ -136,6 +136,8 @@ pub const MAP_FIXED_NOREPLACE = 0x100000;
136/// For anonymous mmap, memory could be uninitialized136/// For anonymous mmap, memory could be uninitialized
137pub const MAP_UNINITIALIZED = 0x4000000;137pub const MAP_UNINITIALIZED = 0x4000000;
138138
139pub const FD_CLOEXEC = 1;
140
139pub const F_OK = 0;141pub const F_OK = 0;
140pub const X_OK = 1;142pub const X_OK = 1;
141pub const W_OK = 2;143pub const W_OK = 2;
lib/std/os/bits/netbsd.zig+2
...@@ -327,6 +327,8 @@ pub const F_RDLCK = 1;...@@ -327,6 +327,8 @@ pub const F_RDLCK = 1;
327pub const F_WRLCK = 3;327pub const F_WRLCK = 3;
328pub const F_UNLCK = 2;328pub const F_UNLCK = 2;
329329
330pub const FD_CLOEXEC = 1;
331
330pub const SEEK_SET = 0;332pub const SEEK_SET = 0;
331pub const SEEK_CUR = 1;333pub const SEEK_CUR = 1;
332pub const SEEK_END = 2;334pub const SEEK_END = 2;
lib/std/os/linux.zig+8-8
...@@ -219,10 +219,6 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of...@@ -219,10 +219,6 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of
219 }219 }
220}220}
221221
222pub fn fcntl(fd: fd_t, cmd: i32, arg: ?*c_void) usize {
223 return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), @ptrToInt(arg));
224}
225
226pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {222pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {
227 return syscall3(SYS_mprotect, @ptrToInt(address), length, protection);223 return syscall3(SYS_mprotect, @ptrToInt(address), length, protection);
228}224}
...@@ -469,17 +465,17 @@ pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const...@@ -469,17 +465,17 @@ pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const
469 return syscall4(465 return syscall4(
470 SYS_renameat,466 SYS_renameat,
471 @bitCast(usize, @as(isize, oldfd)),467 @bitCast(usize, @as(isize, oldfd)),
472 @ptrToInt(old),468 @ptrToInt(oldpath),
473 @bitCast(usize, @as(isize, newfd)),469 @bitCast(usize, @as(isize, newfd)),
474 @ptrToInt(new),470 @ptrToInt(newpath),
475 );471 );
476 } else {472 } else {
477 return syscall5(473 return syscall5(
478 SYS_renameat2,474 SYS_renameat2,
479 @bitCast(usize, @as(isize, oldfd)),475 @bitCast(usize, @as(isize, oldfd)),
480 @ptrToInt(old),476 @ptrToInt(oldpath),
481 @bitCast(usize, @as(isize, newfd)),477 @bitCast(usize, @as(isize, newfd)),
482 @ptrToInt(new),478 @ptrToInt(newpath),
483 0,479 0,
484 );480 );
485 }481 }
...@@ -592,6 +588,10 @@ pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize {...@@ -592,6 +588,10 @@ pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize {
592 return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0);588 return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0);
593}589}
594590
591pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {
592 return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), arg);
593}
594
595var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);595var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
596596
597// We must follow the C calling convention when we call into the VDSO597// We must follow the C calling convention when we call into the VDSO
lib/std/os/test.zig+44-12
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const os = std.os;2const os = std.os;
3const testing = std.testing;3const testing = std.testing;
4const expect = std.testing.expect;4const expect = testing.expect;
5const expectEqual = testing.expectEqual;
5const io = std.io;6const io = std.io;
6const fs = std.fs;7const fs = std.fs;
7const mem = std.mem;8const mem = std.mem;
...@@ -19,8 +20,8 @@ test "makePath, put some files in it, deleteTree" {...@@ -19,8 +20,8 @@ test "makePath, put some files in it, deleteTree" {
19 try fs.cwd().makePath("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");20 try fs.cwd().makePath("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
20 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");21 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
21 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");22 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
22 try fs.deleteTree("os_test_tmp");23 try fs.cwd().deleteTree("os_test_tmp");
23 if (fs.cwd().openDirTraverse("os_test_tmp")) |dir| {24 if (fs.cwd().openDir("os_test_tmp", .{})) |dir| {
24 @panic("expected error");25 @panic("expected error");
25 } else |err| {26 } else |err| {
26 expect(err == error.FileNotFound);27 expect(err == error.FileNotFound);
...@@ -37,7 +38,7 @@ test "access file" {...@@ -37,7 +38,7 @@ test "access file" {
3738
38 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");39 try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");
39 try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);40 try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);
40 try fs.deleteTree("os_test_tmp");41 try fs.cwd().deleteTree("os_test_tmp");
41}42}
4243
43fn testThreadIdFn(thread_id: *Thread.Id) void {44fn testThreadIdFn(thread_id: *Thread.Id) void {
...@@ -46,9 +47,9 @@ fn testThreadIdFn(thread_id: *Thread.Id) void {...@@ -46,9 +47,9 @@ fn testThreadIdFn(thread_id: *Thread.Id) void {
4647
47test "sendfile" {48test "sendfile" {
48 try fs.cwd().makePath("os_test_tmp");49 try fs.cwd().makePath("os_test_tmp");
49 defer fs.deleteTree("os_test_tmp") catch {};50 defer fs.cwd().deleteTree("os_test_tmp") catch {};
5051
51 var dir = try fs.cwd().openDirList("os_test_tmp");52 var dir = try fs.cwd().openDir("os_test_tmp", .{});
52 defer dir.close();53 defer dir.close();
5354
54 const line1 = "line1\n";55 const line1 = "line1\n";
...@@ -112,14 +113,16 @@ test "fs.copyFile" {...@@ -112,14 +113,16 @@ test "fs.copyFile" {
112 const dest_file = "tmp_test_copy_file2.txt";113 const dest_file = "tmp_test_copy_file2.txt";
113 const dest_file2 = "tmp_test_copy_file3.txt";114 const dest_file2 = "tmp_test_copy_file3.txt";
114115
115 try fs.cwd().writeFile(src_file, data);116 const cwd = fs.cwd();
116 defer fs.cwd().deleteFile(src_file) catch {};
117117
118 try fs.copyFile(src_file, dest_file);118 try cwd.writeFile(src_file, data);
119 defer fs.cwd().deleteFile(dest_file) catch {};119 defer cwd.deleteFile(src_file) catch {};
120120
121 try fs.copyFileMode(src_file, dest_file2, File.default_mode);121 try cwd.copyFile(src_file, cwd, dest_file, .{});
122 defer fs.cwd().deleteFile(dest_file2) catch {};122 defer cwd.deleteFile(dest_file) catch {};
123
124 try cwd.copyFile(src_file, cwd, dest_file2, .{ .override_mode = File.default_mode });
125 defer cwd.deleteFile(dest_file2) catch {};
123126
124 try expectFileContents(dest_file, data);127 try expectFileContents(dest_file, data);
125 try expectFileContents(dest_file2, data);128 try expectFileContents(dest_file2, data);
...@@ -446,3 +449,32 @@ test "getenv" {...@@ -446,3 +449,32 @@ test "getenv" {
446 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);449 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
447 }450 }
448}451}
452
453test "fcntl" {
454 if (builtin.os.tag == .windows)
455 return error.SkipZigTest;
456
457 const test_out_file = "os_tmp_test";
458
459 const file = try fs.cwd().createFile(test_out_file, .{});
460 defer {
461 file.close();
462 fs.cwd().deleteFile(test_out_file) catch {};
463 }
464
465 // Note: The test assumes createFile opens the file with O_CLOEXEC
466 {
467 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
468 expect((flags & os.FD_CLOEXEC) != 0);
469 }
470 {
471 _ = try os.fcntl(file.handle, os.F_SETFD, 0);
472 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
473 expect((flags & os.FD_CLOEXEC) == 0);
474 }
475 {
476 _ = try os.fcntl(file.handle, os.F_SETFD, os.FD_CLOEXEC);
477 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
478 expect((flags & os.FD_CLOEXEC) != 0);
479 }
480}
lib/std/os/windows.zig+85-1
...@@ -88,6 +88,82 @@ pub fn CreateFileW(...@@ -88,6 +88,82 @@ pub fn CreateFileW(
88 return result;88 return result;
89}89}
9090
91pub const OpenError = error{
92 IsDir,
93 FileNotFound,
94 NoDevice,
95 SharingViolation,
96 AccessDenied,
97 PipeBusy,
98 PathAlreadyExists,
99 Unexpected,
100 NameTooLong,
101};
102
103/// TODO rename to CreateFileW
104/// TODO actually we don't need the path parameter to be null terminated
105pub fn OpenFileW(
106 dir: ?HANDLE,
107 sub_path_w: [*:0]const u16,
108 sa: ?*SECURITY_ATTRIBUTES,
109 access_mask: ACCESS_MASK,
110 creation: ULONG,
111) OpenError!HANDLE {
112 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
113 return error.IsDir;
114 }
115 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
116 return error.IsDir;
117 }
118
119 var result: HANDLE = undefined;
120
121 const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
122 error.Overflow => return error.NameTooLong,
123 };
124 var nt_name = UNICODE_STRING{
125 .Length = path_len_bytes,
126 .MaximumLength = path_len_bytes,
127 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
128 };
129 var attr = OBJECT_ATTRIBUTES{
130 .Length = @sizeOf(OBJECT_ATTRIBUTES),
131 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dir,
132 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
133 .ObjectName = &nt_name,
134 .SecurityDescriptor = if (sa) |ptr| ptr.lpSecurityDescriptor else null,
135 .SecurityQualityOfService = null,
136 };
137 var io: IO_STATUS_BLOCK = undefined;
138 const rc = ntdll.NtCreateFile(
139 &result,
140 access_mask,
141 &attr,
142 &io,
143 null,
144 FILE_ATTRIBUTE_NORMAL,
145 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
146 creation,
147 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
148 null,
149 0,
150 );
151 switch (rc) {
152 .SUCCESS => return result,
153 .OBJECT_NAME_INVALID => unreachable,
154 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
155 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
156 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
157 .INVALID_PARAMETER => unreachable,
158 .SHARING_VIOLATION => return error.SharingViolation,
159 .ACCESS_DENIED => return error.AccessDenied,
160 .PIPE_BUSY => return error.PipeBusy,
161 .OBJECT_PATH_SYNTAX_BAD => unreachable,
162 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
163 else => return unexpectedStatus(rc),
164 }
165}
166
91pub const CreatePipeError = error{Unexpected};167pub const CreatePipeError = error{Unexpected};
92168
93pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) CreatePipeError!void {169pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) CreatePipeError!void {
...@@ -1200,7 +1276,15 @@ pub fn unexpectedError(err: Win32Error) std.os.UnexpectedError {...@@ -1200,7 +1276,15 @@ pub fn unexpectedError(err: Win32Error) std.os.UnexpectedError {
1200 // 614 is the length of the longest windows error desciption1276 // 614 is the length of the longest windows error desciption
1201 var buf_u16: [614]u16 = undefined;1277 var buf_u16: [614]u16 = undefined;
1202 var buf_u8: [614]u8 = undefined;1278 var buf_u8: [614]u8 = undefined;
1203 var len = kernel32.FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, null, err, MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT), buf_u16[0..].ptr, buf_u16.len / @sizeOf(TCHAR), null);1279 const len = kernel32.FormatMessageW(
1280 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1281 null,
1282 err,
1283 MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT),
1284 &buf_u16,
1285 buf_u16.len / @sizeOf(TCHAR),
1286 null,
1287 );
1204 _ = std.unicode.utf16leToUtf8(&buf_u8, buf_u16[0..len]) catch unreachable;1288 _ = std.unicode.utf16leToUtf8(&buf_u8, buf_u16[0..len]) catch unreachable;
1205 std.debug.warn("error.Unexpected: GetLastError({}): {}\n", .{ @enumToInt(err), buf_u8[0..len] });1289 std.debug.warn("error.Unexpected: GetLastError({}): {}\n", .{ @enumToInt(err), buf_u8[0..len] });
1206 std.debug.dumpCurrentStackTrace(null);1290 std.debug.dumpCurrentStackTrace(null);
lib/std/os/windows/bits.zig+7
...@@ -242,6 +242,13 @@ pub const FILE_NAME_INFORMATION = extern struct {...@@ -242,6 +242,13 @@ pub const FILE_NAME_INFORMATION = extern struct {
242 FileName: [1]WCHAR,242 FileName: [1]WCHAR,
243};243};
244244
245pub const FILE_RENAME_INFORMATION = extern struct {
246 ReplaceIfExists: BOOLEAN,
247 RootDirectory: ?HANDLE,
248 FileNameLength: ULONG,
249 FileName: [1]WCHAR,
250};
251
245pub const IO_STATUS_BLOCK = extern struct {252pub const IO_STATUS_BLOCK = extern struct {
246 // "DUMMYUNIONNAME" expands to "u"253 // "DUMMYUNIONNAME" expands to "u"
247 u: extern union {254 u: extern union {
lib/std/rand.zig+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// ```5// ```
6// var buf: [8]u8 = undefined;6// var buf: [8]u8 = undefined;
7// try std.crypto.randomBytes(buf[0..]);7// try std.crypto.randomBytes(buf[0..]);
8// const seed = mem.readIntSliceLittle(u64, buf[0..8]);8// const seed = mem.readIntLittle(u64, buf[0..8]);
9//9//
10// var r = DefaultPrng.init(seed);10// var r = DefaultPrng.init(seed);
11//11//
lib/std/special/compiler_rt/floatundisf.zig+19-19
...@@ -69,23 +69,23 @@ test "floatundisf" {...@@ -69,23 +69,23 @@ test "floatundisf" {
69 test__floatundisf(0, 0.0);69 test__floatundisf(0, 0.0);
70 test__floatundisf(1, 1.0);70 test__floatundisf(1, 1.0);
71 test__floatundisf(2, 2.0);71 test__floatundisf(2, 2.0);
72 test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62F);72 test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62);
73 test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62F);73 test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62);
74 test__floatundisf(0x8000008000000000, 0x1p+63F);74 test__floatundisf(0x8000008000000000, 0x1p+63);
75 test__floatundisf(0x8000010000000000, 0x1.000002p+63F);75 test__floatundisf(0x8000010000000000, 0x1.000002p+63);
76 test__floatundisf(0x8000000000000000, 0x1p+63F);76 test__floatundisf(0x8000000000000000, 0x1p+63);
77 test__floatundisf(0x8000000000000001, 0x1p+63F);77 test__floatundisf(0x8000000000000001, 0x1p+63);
78 test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64F);78 test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64);
79 test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64F);79 test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64);
80 test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50F);80 test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50);
81 test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50F);81 test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50);
82 test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50F);82 test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50);
83 test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50F);83 test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50);
84 test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50F);84 test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50);
85 test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50F);85 test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50);
86 test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50F);86 test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50);
87 test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50F);87 test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50);
88 test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50F);88 test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50);
89 test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50F);89 test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50);
90 test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50F);90 test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50);
91}91}
lib/std/start.zig+4
...@@ -41,6 +41,10 @@ fn _DllMainCRTStartup(...@@ -41,6 +41,10 @@ fn _DllMainCRTStartup(
41 fdwReason: std.os.windows.DWORD,41 fdwReason: std.os.windows.DWORD,
42 lpReserved: std.os.windows.LPVOID,42 lpReserved: std.os.windows.LPVOID,
43) callconv(.Stdcall) std.os.windows.BOOL {43) callconv(.Stdcall) std.os.windows.BOOL {
44 if (!builtin.single_threaded) {
45 _ = @import("start_windows_tls.zig");
46 }
47
44 if (@hasDecl(root, "DllMain")) {48 if (@hasDecl(root, "DllMain")) {
45 return root.DllMain(hinstDLL, fdwReason, lpReserved);49 return root.DllMain(hinstDLL, fdwReason, lpReserved);
46 }50 }
lib/std/thread.zig+45-6
...@@ -6,6 +6,8 @@ const windows = std.os.windows;...@@ -6,6 +6,8 @@ const windows = std.os.windows;
6const c = std.c;6const c = std.c;
7const assert = std.debug.assert;7const assert = std.debug.assert;
88
9const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'";
10
9pub const Thread = struct {11pub const Thread = struct {
10 data: Data,12 data: Data,
1113
...@@ -158,15 +160,34 @@ pub const Thread = struct {...@@ -158,15 +160,34 @@ pub const Thread = struct {
158 };160 };
159 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {161 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
160 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;162 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
163
161 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {164 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
162 .Int => {165 .NoReturn => {
163 return startFn(arg);166 startFn(arg);
164 },167 },
165 .Void => {168 .Void => {
166 startFn(arg);169 startFn(arg);
167 return 0;170 return 0;
168 },171 },
169 else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"),172 .Int => |info| {
173 if (info.bits != 8) {
174 @compileError(bad_startfn_ret);
175 }
176 return startFn(arg);
177 },
178 .ErrorUnion => |info| {
179 if (info.payload != void) {
180 @compileError(bad_startfn_ret);
181 }
182 startFn(arg) catch |err| {
183 std.debug.warn("error: {}\n", .{@errorName(err)});
184 if (@errorReturnTrace()) |trace| {
185 std.debug.dumpStackTrace(trace.*);
186 }
187 };
188 return 0;
189 },
190 else => @compileError(bad_startfn_ret),
170 }191 }
171 }192 }
172 };193 };
...@@ -202,14 +223,32 @@ pub const Thread = struct {...@@ -202,14 +223,32 @@ pub const Thread = struct {
202 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;223 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
203224
204 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {225 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
205 .Int => {226 .NoReturn => {
206 return startFn(arg);227 startFn(arg);
207 },228 },
208 .Void => {229 .Void => {
209 startFn(arg);230 startFn(arg);
210 return 0;231 return 0;
211 },232 },
212 else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"),233 .Int => |info| {
234 if (info.bits != 8) {
235 @compileError(bad_startfn_ret);
236 }
237 return startFn(arg);
238 },
239 .ErrorUnion => |info| {
240 if (info.payload != void) {
241 @compileError(bad_startfn_ret);
242 }
243 startFn(arg) catch |err| {
244 std.debug.warn("error: {}\n", .{@errorName(err)});
245 if (@errorReturnTrace()) |trace| {
246 std.debug.dumpStackTrace(trace.*);
247 }
248 };
249 return 0;
250 },
251 else => @compileError(bad_startfn_ret),
213 }252 }
214 }253 }
215 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {254 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {
lib/std/unicode.zig+10-10
...@@ -251,12 +251,12 @@ pub const Utf16LeIterator = struct {...@@ -251,12 +251,12 @@ pub const Utf16LeIterator = struct {
251 pub fn nextCodepoint(it: *Utf16LeIterator) !?u21 {251 pub fn nextCodepoint(it: *Utf16LeIterator) !?u21 {
252 assert(it.i <= it.bytes.len);252 assert(it.i <= it.bytes.len);
253 if (it.i == it.bytes.len) return null;253 if (it.i == it.bytes.len) return null;
254 const c0: u21 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);254 const c0: u21 = mem.readIntLittle(u16, it.bytes[it.i..][0..2]);
255 if (c0 & ~@as(u21, 0x03ff) == 0xd800) {255 if (c0 & ~@as(u21, 0x03ff) == 0xd800) {
256 // surrogate pair256 // surrogate pair
257 it.i += 2;257 it.i += 2;
258 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;258 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
259 const c1: u21 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);259 const c1: u21 = mem.readIntLittle(u16, it.bytes[it.i..][0..2]);
260 if (c1 & ~@as(u21, 0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;260 if (c1 & ~@as(u21, 0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
261 it.i += 2;261 it.i += 2;
262 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));262 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
...@@ -630,11 +630,11 @@ test "utf8ToUtf16LeWithNull" {...@@ -630,11 +630,11 @@ test "utf8ToUtf16LeWithNull" {
630 }630 }
631}631}
632632
633/// Converts a UTF-8 string literal into a UTF-16LE string literal. 633/// Converts a UTF-8 string literal into a UTF-16LE string literal.
634pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8) :0] u16 {634pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8):0]u16 {
635 comptime {635 comptime {
636 const len: usize = calcUtf16LeLen(utf8);636 const len: usize = calcUtf16LeLen(utf8);
637 var utf16le: [len :0]u16 = [_ :0]u16{0} ** len;637 var utf16le: [len:0]u16 = [_:0]u16{0} ** len;
638 const utf16le_len = utf8ToUtf16Le(&utf16le, utf8[0..]) catch |err| @compileError(err);638 const utf16le_len = utf8ToUtf16Le(&utf16le, utf8[0..]) catch |err| @compileError(err);
639 assert(len == utf16le_len);639 assert(len == utf16le_len);
640 return &utf16le;640 return &utf16le;
...@@ -660,8 +660,8 @@ fn calcUtf16LeLen(utf8: []const u8) usize {...@@ -660,8 +660,8 @@ fn calcUtf16LeLen(utf8: []const u8) usize {
660}660}
661661
662test "utf8ToUtf16LeStringLiteral" {662test "utf8ToUtf16LeStringLiteral" {
663{663 {
664 const bytes = [_:0]u16{ 0x41 };664 const bytes = [_:0]u16{0x41};
665 const utf16 = utf8ToUtf16LeStringLiteral("A");665 const utf16 = utf8ToUtf16LeStringLiteral("A");
666 testing.expectEqualSlices(u16, &bytes, utf16);666 testing.expectEqualSlices(u16, &bytes, utf16);
667 testing.expect(utf16[1] == 0);667 testing.expect(utf16[1] == 0);
...@@ -673,19 +673,19 @@ test "utf8ToUtf16LeStringLiteral" {...@@ -673,19 +673,19 @@ test "utf8ToUtf16LeStringLiteral" {
673 testing.expect(utf16[2] == 0);673 testing.expect(utf16[2] == 0);
674 }674 }
675 {675 {
676 const bytes = [_:0]u16{ 0x02FF };676 const bytes = [_:0]u16{0x02FF};
677 const utf16 = utf8ToUtf16LeStringLiteral("\u{02FF}");677 const utf16 = utf8ToUtf16LeStringLiteral("\u{02FF}");
678 testing.expectEqualSlices(u16, &bytes, utf16);678 testing.expectEqualSlices(u16, &bytes, utf16);
679 testing.expect(utf16[1] == 0);679 testing.expect(utf16[1] == 0);
680 }680 }
681 {681 {
682 const bytes = [_:0]u16{ 0x7FF };682 const bytes = [_:0]u16{0x7FF};
683 const utf16 = utf8ToUtf16LeStringLiteral("\u{7FF}");683 const utf16 = utf8ToUtf16LeStringLiteral("\u{7FF}");
684 testing.expectEqualSlices(u16, &bytes, utf16);684 testing.expectEqualSlices(u16, &bytes, utf16);
685 testing.expect(utf16[1] == 0);685 testing.expect(utf16[1] == 0);
686 }686 }
687 {687 {
688 const bytes = [_:0]u16{ 0x801 };688 const bytes = [_:0]u16{0x801};
689 const utf16 = utf8ToUtf16LeStringLiteral("\u{801}");689 const utf16 = utf8ToUtf16LeStringLiteral("\u{801}");
690 testing.expectEqualSlices(u16, &bytes, utf16);690 testing.expectEqualSlices(u16, &bytes, utf16);
691 testing.expect(utf16[1] == 0);691 testing.expect(utf16[1] == 0);
lib/std/zig/ast.zig+65-92
...@@ -740,11 +740,11 @@ pub const Node = struct {...@@ -740,11 +740,11 @@ pub const Node = struct {
740 var i = index;740 var i = index;
741741
742 switch (self.init_arg_expr) {742 switch (self.init_arg_expr) {
743 InitArg.Type => |t| {743 .Type => |t| {
744 if (i < 1) return t;744 if (i < 1) return t;
745 i -= 1;745 i -= 1;
746 },746 },
747 InitArg.None, InitArg.Enum => {},747 .None, .Enum => {},
748 }748 }
749749
750 if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i).*;750 if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i).*;
...@@ -904,12 +904,7 @@ pub const Node = struct {...@@ -904,12 +904,7 @@ pub const Node = struct {
904 }904 }
905905
906 switch (self.return_type) {906 switch (self.return_type) {
907 // TODO allow this and next prong to share bodies since the types are the same907 .Explicit, .InferErrorSet => |node| {
908 ReturnType.Explicit => |node| {
909 if (i < 1) return node;
910 i -= 1;
911 },
912 ReturnType.InferErrorSet => |node| {
913 if (i < 1) return node;908 if (i < 1) return node;
914 i -= 1;909 i -= 1;
915 },910 },
...@@ -934,9 +929,7 @@ pub const Node = struct {...@@ -934,9 +929,7 @@ pub const Node = struct {
934 pub fn lastToken(self: *const FnProto) TokenIndex {929 pub fn lastToken(self: *const FnProto) TokenIndex {
935 if (self.body_node) |body_node| return body_node.lastToken();930 if (self.body_node) |body_node| return body_node.lastToken();
936 switch (self.return_type) {931 switch (self.return_type) {
937 // TODO allow this and next prong to share bodies since the types are the same932 .Explicit, .InferErrorSet => |node| return node.lastToken(),
938 ReturnType.Explicit => |node| return node.lastToken(),
939 ReturnType.InferErrorSet => |node| return node.lastToken(),
940 }933 }
941 }934 }
942 };935 };
...@@ -1039,6 +1032,7 @@ pub const Node = struct {...@@ -1039,6 +1032,7 @@ pub const Node = struct {
1039 pub const Defer = struct {1032 pub const Defer = struct {
1040 base: Node = Node{ .id = .Defer },1033 base: Node = Node{ .id = .Defer },
1041 defer_token: TokenIndex,1034 defer_token: TokenIndex,
1035 payload: ?*Node,
1042 expr: *Node,1036 expr: *Node,
10431037
1044 pub fn iterate(self: *Defer, index: usize) ?*Node {1038 pub fn iterate(self: *Defer, index: usize) ?*Node {
...@@ -1512,55 +1506,55 @@ pub const Node = struct {...@@ -1512,55 +1506,55 @@ pub const Node = struct {
1512 i -= 1;1506 i -= 1;
15131507
1514 switch (self.op) {1508 switch (self.op) {
1515 Op.Catch => |maybe_payload| {1509 .Catch => |maybe_payload| {
1516 if (maybe_payload) |payload| {1510 if (maybe_payload) |payload| {
1517 if (i < 1) return payload;1511 if (i < 1) return payload;
1518 i -= 1;1512 i -= 1;
1519 }1513 }
1520 },1514 },
15211515
1522 Op.Add,1516 .Add,
1523 Op.AddWrap,1517 .AddWrap,
1524 Op.ArrayCat,1518 .ArrayCat,
1525 Op.ArrayMult,1519 .ArrayMult,
1526 Op.Assign,1520 .Assign,
1527 Op.AssignBitAnd,1521 .AssignBitAnd,
1528 Op.AssignBitOr,1522 .AssignBitOr,
1529 Op.AssignBitShiftLeft,1523 .AssignBitShiftLeft,
1530 Op.AssignBitShiftRight,1524 .AssignBitShiftRight,
1531 Op.AssignBitXor,1525 .AssignBitXor,
1532 Op.AssignDiv,1526 .AssignDiv,
1533 Op.AssignSub,1527 .AssignSub,
1534 Op.AssignSubWrap,1528 .AssignSubWrap,
1535 Op.AssignMod,1529 .AssignMod,
1536 Op.AssignAdd,1530 .AssignAdd,
1537 Op.AssignAddWrap,1531 .AssignAddWrap,
1538 Op.AssignMul,1532 .AssignMul,
1539 Op.AssignMulWrap,1533 .AssignMulWrap,
1540 Op.BangEqual,1534 .BangEqual,
1541 Op.BitAnd,1535 .BitAnd,
1542 Op.BitOr,1536 .BitOr,
1543 Op.BitShiftLeft,1537 .BitShiftLeft,
1544 Op.BitShiftRight,1538 .BitShiftRight,
1545 Op.BitXor,1539 .BitXor,
1546 Op.BoolAnd,1540 .BoolAnd,
1547 Op.BoolOr,1541 .BoolOr,
1548 Op.Div,1542 .Div,
1549 Op.EqualEqual,1543 .EqualEqual,
1550 Op.ErrorUnion,1544 .ErrorUnion,
1551 Op.GreaterOrEqual,1545 .GreaterOrEqual,
1552 Op.GreaterThan,1546 .GreaterThan,
1553 Op.LessOrEqual,1547 .LessOrEqual,
1554 Op.LessThan,1548 .LessThan,
1555 Op.MergeErrorSets,1549 .MergeErrorSets,
1556 Op.Mod,1550 .Mod,
1557 Op.Mul,1551 .Mul,
1558 Op.MulWrap,1552 .MulWrap,
1559 Op.Period,1553 .Period,
1560 Op.Range,1554 .Range,
1561 Op.Sub,1555 .Sub,
1562 Op.SubWrap,1556 .SubWrap,
1563 Op.UnwrapOptional,1557 .UnwrapOptional,
1564 => {},1558 => {},
1565 }1559 }
15661560
...@@ -1591,7 +1585,6 @@ pub const Node = struct {...@@ -1591,7 +1585,6 @@ pub const Node = struct {
1591 Await,1585 Await,
1592 BitNot,1586 BitNot,
1593 BoolNot,1587 BoolNot,
1594 Cancel,
1595 OptionalType,1588 OptionalType,
1596 Negation,1589 Negation,
1597 NegationWrap,1590 NegationWrap,
...@@ -1628,8 +1621,7 @@ pub const Node = struct {...@@ -1628,8 +1621,7 @@ pub const Node = struct {
1628 var i = index;1621 var i = index;
16291622
1630 switch (self.op) {1623 switch (self.op) {
1631 // TODO https://github.com/ziglang/zig/issues/11071624 .PtrType, .SliceType => |addr_of_info| {
1632 Op.SliceType => |addr_of_info| {
1633 if (addr_of_info.sentinel) |sentinel| {1625 if (addr_of_info.sentinel) |sentinel| {
1634 if (i < 1) return sentinel;1626 if (i < 1) return sentinel;
1635 i -= 1;1627 i -= 1;
...@@ -1641,14 +1633,7 @@ pub const Node = struct {...@@ -1641,14 +1633,7 @@ pub const Node = struct {
1641 }1633 }
1642 },1634 },
16431635
1644 Op.PtrType => |addr_of_info| {1636 .ArrayType => |array_info| {
1645 if (addr_of_info.align_info) |align_info| {
1646 if (i < 1) return align_info.node;
1647 i -= 1;
1648 }
1649 },
1650
1651 Op.ArrayType => |array_info| {
1652 if (i < 1) return array_info.len_expr;1637 if (i < 1) return array_info.len_expr;
1653 i -= 1;1638 i -= 1;
1654 if (array_info.sentinel) |sentinel| {1639 if (array_info.sentinel) |sentinel| {
...@@ -1657,16 +1642,15 @@ pub const Node = struct {...@@ -1657,16 +1642,15 @@ pub const Node = struct {
1657 }1642 }
1658 },1643 },
16591644
1660 Op.AddressOf,1645 .AddressOf,
1661 Op.Await,1646 .Await,
1662 Op.BitNot,1647 .BitNot,
1663 Op.BoolNot,1648 .BoolNot,
1664 Op.Cancel,1649 .OptionalType,
1665 Op.OptionalType,1650 .Negation,
1666 Op.Negation,1651 .NegationWrap,
1667 Op.NegationWrap,1652 .Try,
1668 Op.Try,1653 .Resume,
1669 Op.Resume,
1670 => {},1654 => {},
1671 }1655 }
16721656
...@@ -1850,19 +1834,13 @@ pub const Node = struct {...@@ -1850,19 +1834,13 @@ pub const Node = struct {
1850 var i = index;1834 var i = index;
18511835
1852 switch (self.kind) {1836 switch (self.kind) {
1853 Kind.Break => |maybe_label| {1837 .Break, .Continue => |maybe_label| {
1854 if (maybe_label) |label| {
1855 if (i < 1) return label;
1856 i -= 1;
1857 }
1858 },
1859 Kind.Continue => |maybe_label| {
1860 if (maybe_label) |label| {1838 if (maybe_label) |label| {
1861 if (i < 1) return label;1839 if (i < 1) return label;
1862 i -= 1;1840 i -= 1;
1863 }1841 }
1864 },1842 },
1865 Kind.Return => {},1843 .Return => {},
1866 }1844 }
18671845
1868 if (self.rhs) |rhs| {1846 if (self.rhs) |rhs| {
...@@ -1883,17 +1861,12 @@ pub const Node = struct {...@@ -1883,17 +1861,12 @@ pub const Node = struct {
1883 }1861 }
18841862
1885 switch (self.kind) {1863 switch (self.kind) {
1886 Kind.Break => |maybe_label| {1864 .Break, .Continue => |maybe_label| {
1887 if (maybe_label) |label| {
1888 return label.lastToken();
1889 }
1890 },
1891 Kind.Continue => |maybe_label| {
1892 if (maybe_label) |label| {1865 if (maybe_label) |label| {
1893 return label.lastToken();1866 return label.lastToken();
1894 }1867 }
1895 },1868 },
1896 Kind.Return => return self.ltoken,1869 .Return => return self.ltoken,
1897 }1870 }
18981871
1899 return self.ltoken;1872 return self.ltoken;
...@@ -2134,11 +2107,11 @@ pub const Node = struct {...@@ -2134,11 +2107,11 @@ pub const Node = struct {
2134 i -= 1;2107 i -= 1;
21352108
2136 switch (self.kind) {2109 switch (self.kind) {
2137 Kind.Variable => |variable_name| {2110 .Variable => |variable_name| {
2138 if (i < 1) return &variable_name.base;2111 if (i < 1) return &variable_name.base;
2139 i -= 1;2112 i -= 1;
2140 },2113 },
2141 Kind.Return => |return_type| {2114 .Return => |return_type| {
2142 if (i < 1) return return_type;2115 if (i < 1) return return_type;
2143 i -= 1;2116 i -= 1;
2144 },2117 },
lib/std/zig/parse.zig+342-352
...@@ -23,7 +23,7 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {...@@ -23,7 +23,7 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {
23 var arena = std.heap.ArenaAllocator.init(allocator);23 var arena = std.heap.ArenaAllocator.init(allocator);
24 errdefer arena.deinit();24 errdefer arena.deinit();
25 const tree = try arena.allocator.create(ast.Tree);25 const tree = try arena.allocator.create(ast.Tree);
26 tree.* = ast.Tree{26 tree.* = .{
27 .source = source,27 .source = source,
28 .root_node = undefined,28 .root_node = undefined,
29 .arena_allocator = arena,29 .arena_allocator = arena,
...@@ -66,10 +66,10 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {...@@ -66,10 +66,10 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {
66/// Root <- skip ContainerMembers eof66/// Root <- skip ContainerMembers eof
67fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!*Node.Root {67fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!*Node.Root {
68 const node = try arena.create(Node.Root);68 const node = try arena.create(Node.Root);
69 node.* = Node.Root{69 node.* = .{
70 .decls = try parseContainerMembers(arena, it, tree),70 .decls = try parseContainerMembers(arena, it, tree),
71 .eof_token = eatToken(it, .Eof) orelse {71 .eof_token = eatToken(it, .Eof) orelse {
72 try tree.errors.push(AstError{72 try tree.errors.push(.{
73 .ExpectedContainerMembers = .{ .token = it.index },73 .ExpectedContainerMembers = .{ .token = it.index },
74 });74 });
75 return error.ParseError;75 return error.ParseError;
...@@ -139,8 +139,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No...@@ -139,8 +139,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No
139 }139 }
140140
141 if (visib_token != null) {141 if (visib_token != null) {
142 try tree.errors.push(AstError{142 try tree.errors.push(.{
143 .ExpectedPubItem = AstError.ExpectedPubItem{ .token = it.index },143 .ExpectedPubItem = .{ .token = it.index },
144 });144 });
145 return error.ParseError;145 return error.ParseError;
146 }146 }
...@@ -157,8 +157,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No...@@ -157,8 +157,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No
157157
158 // Dangling doc comment158 // Dangling doc comment
159 if (doc_comments != null) {159 if (doc_comments != null) {
160 try tree.errors.push(AstError{160 try tree.errors.push(.{
161 .UnattachedDocComment = AstError.UnattachedDocComment{ .token = doc_comments.?.firstToken() },161 .UnattachedDocComment = .{ .token = doc_comments.?.firstToken() },
162 });162 });
163 }163 }
164 break;164 break;
...@@ -177,7 +177,7 @@ fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree)...@@ -177,7 +177,7 @@ fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree)
177 if (lines.len == 0) return null;177 if (lines.len == 0) return null;
178178
179 const node = try arena.create(Node.DocComment);179 const node = try arena.create(Node.DocComment);
180 node.* = Node.DocComment{180 node.* = .{
181 .lines = lines,181 .lines = lines,
182 };182 };
183 return &node.base;183 return &node.base;
...@@ -186,15 +186,15 @@ fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree)...@@ -186,15 +186,15 @@ fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree)
186/// TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block186/// TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block
187fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {187fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
188 const test_token = eatToken(it, .Keyword_test) orelse return null;188 const test_token = eatToken(it, .Keyword_test) orelse return null;
189 const name_node = try expectNode(arena, it, tree, parseStringLiteralSingle, AstError{189 const name_node = try expectNode(arena, it, tree, parseStringLiteralSingle, .{
190 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },190 .ExpectedStringLiteral = .{ .token = it.index },
191 });191 });
192 const block_node = try expectNode(arena, it, tree, parseBlock, AstError{192 const block_node = try expectNode(arena, it, tree, parseBlock, .{
193 .ExpectedLBrace = AstError.ExpectedLBrace{ .token = it.index },193 .ExpectedLBrace = .{ .token = it.index },
194 });194 });
195195
196 const test_node = try arena.create(Node.TestDecl);196 const test_node = try arena.create(Node.TestDecl);
197 test_node.* = Node.TestDecl{197 test_node.* = .{
198 .doc_comments = null,198 .doc_comments = null,
199 .test_token = test_token,199 .test_token = test_token,
200 .name = name_node,200 .name = name_node,
...@@ -211,12 +211,12 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*...@@ -211,12 +211,12 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*
211 return null;211 return null;
212 };212 };
213 putBackToken(it, lbrace);213 putBackToken(it, lbrace);
214 const block_node = try expectNode(arena, it, tree, parseBlockExpr, AstError{214 const block_node = try expectNode(arena, it, tree, parseBlockExpr, .{
215 .ExpectedLabelOrLBrace = AstError.ExpectedLabelOrLBrace{ .token = it.index },215 .ExpectedLabelOrLBrace = .{ .token = it.index },
216 });216 });
217217
218 const comptime_node = try arena.create(Node.Comptime);218 const comptime_node = try arena.create(Node.Comptime);
219 comptime_node.* = Node.Comptime{219 comptime_node.* = .{
220 .doc_comments = null,220 .doc_comments = null,
221 .comptime_token = tok,221 .comptime_token = tok,
222 .expr = block_node,222 .expr = block_node,
...@@ -250,8 +250,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -250,8 +250,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
250 fn_node.body_node = body_node;250 fn_node.body_node = body_node;
251 return node;251 return node;
252 }252 }
253 try tree.errors.push(AstError{253 try tree.errors.push(.{
254 .ExpectedSemiOrLBrace = AstError.ExpectedSemiOrLBrace{ .token = it.index },254 .ExpectedSemiOrLBrace = .{ .token = it.index },
255 });255 });
256 return null;256 return null;
257 }257 }
...@@ -277,8 +277,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -277,8 +277,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
277 }277 }
278278
279 if (thread_local_token != null) {279 if (thread_local_token != null) {
280 try tree.errors.push(AstError{280 try tree.errors.push(.{
281 .ExpectedVarDecl = AstError.ExpectedVarDecl{ .token = it.index },281 .ExpectedVarDecl = .{ .token = it.index },
282 });282 });
283 return error.ParseError;283 return error.ParseError;
284 }284 }
...@@ -291,8 +291,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -291,8 +291,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
291 }291 }
292292
293 const use_node = (try parseUse(arena, it, tree)) orelse return null;293 const use_node = (try parseUse(arena, it, tree)) orelse return null;
294 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{294 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
295 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },295 .ExpectedExpr = .{ .token = it.index },
296 });296 });
297 const semicolon_token = try expectToken(it, tree, .Semicolon);297 const semicolon_token = try expectToken(it, tree, .Semicolon);
298 const use_node_raw = use_node.cast(Node.Use).?;298 const use_node_raw = use_node.cast(Node.Use).?;
...@@ -310,7 +310,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -310,7 +310,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
310 if (fnCC == .Extern) {310 if (fnCC == .Extern) {
311 putBackToken(it, fnCC.Extern); // 'extern' is also used in ContainerDecl311 putBackToken(it, fnCC.Extern); // 'extern' is also used in ContainerDecl
312 } else {312 } else {
313 try tree.errors.push(AstError{313 try tree.errors.push(.{
314 .ExpectedToken = .{ .token = it.index, .expected_id = .Keyword_fn },314 .ExpectedToken = .{ .token = it.index, .expected_id = .Keyword_fn },
315 });315 });
316 return error.ParseError;316 return error.ParseError;
...@@ -328,16 +328,16 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -328,16 +328,16 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
328 const exclamation_token = eatToken(it, .Bang);328 const exclamation_token = eatToken(it, .Bang);
329329
330 const return_type_expr = (try parseVarType(arena, it, tree)) orelse330 const return_type_expr = (try parseVarType(arena, it, tree)) orelse
331 try expectNode(arena, it, tree, parseTypeExpr, AstError{331 try expectNode(arena, it, tree, parseTypeExpr, .{
332 .ExpectedReturnType = AstError.ExpectedReturnType{ .token = it.index },332 .ExpectedReturnType = .{ .token = it.index },
333 });333 });
334334
335 const return_type = if (exclamation_token != null)335 const return_type: Node.FnProto.ReturnType = if (exclamation_token != null)
336 Node.FnProto.ReturnType{336 .{
337 .InferErrorSet = return_type_expr,337 .InferErrorSet = return_type_expr,
338 }338 }
339 else339 else
340 Node.FnProto.ReturnType{340 .{
341 .Explicit = return_type_expr,341 .Explicit = return_type_expr,
342 };342 };
343343
...@@ -347,7 +347,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -347,7 +347,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
347 null;347 null;
348348
349 const fn_proto_node = try arena.create(Node.FnProto);349 const fn_proto_node = try arena.create(Node.FnProto);
350 fn_proto_node.* = Node.FnProto{350 fn_proto_node.* = .{
351 .doc_comments = null,351 .doc_comments = null,
352 .visib_token = null,352 .visib_token = null,
353 .fn_token = fn_token,353 .fn_token = fn_token,
...@@ -382,8 +382,8 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -382,8 +382,8 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
382382
383 const name_token = try expectToken(it, tree, .Identifier);383 const name_token = try expectToken(it, tree, .Identifier);
384 const type_node = if (eatToken(it, .Colon) != null)384 const type_node = if (eatToken(it, .Colon) != null)
385 try expectNode(arena, it, tree, parseTypeExpr, AstError{385 try expectNode(arena, it, tree, parseTypeExpr, .{
386 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },386 .ExpectedTypeExpr = .{ .token = it.index },
387 })387 })
388 else388 else
389 null;389 null;
...@@ -391,14 +391,14 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -391,14 +391,14 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
391 const section_node = try parseLinkSection(arena, it, tree);391 const section_node = try parseLinkSection(arena, it, tree);
392 const eq_token = eatToken(it, .Equal);392 const eq_token = eatToken(it, .Equal);
393 const init_node = if (eq_token != null) blk: {393 const init_node = if (eq_token != null) blk: {
394 break :blk try expectNode(arena, it, tree, parseExpr, AstError{394 break :blk try expectNode(arena, it, tree, parseExpr, .{
395 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },395 .ExpectedExpr = .{ .token = it.index },
396 });396 });
397 } else null;397 } else null;
398 const semicolon_token = try expectToken(it, tree, .Semicolon);398 const semicolon_token = try expectToken(it, tree, .Semicolon);
399399
400 const node = try arena.create(Node.VarDecl);400 const node = try arena.create(Node.VarDecl);
401 node.* = Node.VarDecl{401 node.* = .{
402 .doc_comments = null,402 .doc_comments = null,
403 .visib_token = null,403 .visib_token = null,
404 .thread_local_token = null,404 .thread_local_token = null,
...@@ -433,22 +433,22 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -433,22 +433,22 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
433 node.* = .{ .token = var_tok };433 node.* = .{ .token = var_tok };
434 type_expr = &node.base;434 type_expr = &node.base;
435 } else {435 } else {
436 type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{436 type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
437 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },437 .ExpectedTypeExpr = .{ .token = it.index },
438 });438 });
439 align_expr = try parseByteAlign(arena, it, tree);439 align_expr = try parseByteAlign(arena, it, tree);
440 }440 }
441 }441 }
442442
443 const value_expr = if (eatToken(it, .Equal)) |_|443 const value_expr = if (eatToken(it, .Equal)) |_|
444 try expectNode(arena, it, tree, parseExpr, AstError{444 try expectNode(arena, it, tree, parseExpr, .{
445 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },445 .ExpectedExpr = .{ .token = it.index },
446 })446 })
447 else447 else
448 null;448 null;
449449
450 const node = try arena.create(Node.ContainerField);450 const node = try arena.create(Node.ContainerField);
451 node.* = Node.ContainerField{451 node.* = .{
452 .doc_comments = null,452 .doc_comments = null,
453 .comptime_token = comptime_token,453 .comptime_token = comptime_token,
454 .name_token = name_token,454 .name_token = name_token,
...@@ -465,7 +465,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -465,7 +465,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
465/// / KEYWORD_noasync BlockExprStatement465/// / KEYWORD_noasync BlockExprStatement
466/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)466/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
467/// / KEYWORD_defer BlockExprStatement467/// / KEYWORD_defer BlockExprStatement
468/// / KEYWORD_errdefer BlockExprStatement468/// / KEYWORD_errdefer Payload? BlockExprStatement
469/// / IfStatement469/// / IfStatement
470/// / LabeledStatement470/// / LabeledStatement
471/// / SwitchExpr471/// / SwitchExpr
...@@ -481,12 +481,12 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No...@@ -481,12 +481,12 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
481 }481 }
482482
483 if (comptime_token) |token| {483 if (comptime_token) |token| {
484 const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, AstError{484 const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, .{
485 .ExpectedBlockOrAssignment = AstError.ExpectedBlockOrAssignment{ .token = it.index },485 .ExpectedBlockOrAssignment = .{ .token = it.index },
486 });486 });
487487
488 const node = try arena.create(Node.Comptime);488 const node = try arena.create(Node.Comptime);
489 node.* = Node.Comptime{489 node.* = .{
490 .doc_comments = null,490 .doc_comments = null,
491 .comptime_token = token,491 .comptime_token = token,
492 .expr = block_expr,492 .expr = block_expr,
...@@ -511,13 +511,13 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No...@@ -511,13 +511,13 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
511 const semicolon = eatToken(it, .Semicolon);511 const semicolon = eatToken(it, .Semicolon);
512512
513 const body_node = if (semicolon == null) blk: {513 const body_node = if (semicolon == null) blk: {
514 break :blk try expectNode(arena, it, tree, parseBlockExprStatement, AstError{514 break :blk try expectNode(arena, it, tree, parseBlockExprStatement, .{
515 .ExpectedBlockOrExpression = AstError.ExpectedBlockOrExpression{ .token = it.index },515 .ExpectedBlockOrExpression = .{ .token = it.index },
516 });516 });
517 } else null;517 } else null;
518518
519 const node = try arena.create(Node.Suspend);519 const node = try arena.create(Node.Suspend);
520 node.* = Node.Suspend{520 node.* = .{
521 .suspend_token = suspend_token,521 .suspend_token = suspend_token,
522 .body = body_node,522 .body = body_node,
523 };523 };
...@@ -526,13 +526,18 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No...@@ -526,13 +526,18 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
526526
527 const defer_token = eatToken(it, .Keyword_defer) orelse eatToken(it, .Keyword_errdefer);527 const defer_token = eatToken(it, .Keyword_defer) orelse eatToken(it, .Keyword_errdefer);
528 if (defer_token) |token| {528 if (defer_token) |token| {
529 const expr_node = try expectNode(arena, it, tree, parseBlockExprStatement, AstError{529 const payload = if (tree.tokens.at(token).id == .Keyword_errdefer)
530 .ExpectedBlockOrExpression = AstError.ExpectedBlockOrExpression{ .token = it.index },530 try parsePayload(arena, it, tree)
531 else
532 null;
533 const expr_node = try expectNode(arena, it, tree, parseBlockExprStatement, .{
534 .ExpectedBlockOrExpression = .{ .token = it.index },
531 });535 });
532 const node = try arena.create(Node.Defer);536 const node = try arena.create(Node.Defer);
533 node.* = Node.Defer{537 node.* = .{
534 .defer_token = token,538 .defer_token = token,
535 .expr = expr_node,539 .expr = expr_node,
540 .payload = payload,
536 };541 };
537 return &node.base;542 return &node.base;
538 }543 }
...@@ -561,8 +566,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -561,8 +566,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
561 } else null;566 } else null;
562567
563 if (block_expr == null and assign_expr == null) {568 if (block_expr == null and assign_expr == null) {
564 try tree.errors.push(AstError{569 try tree.errors.push(.{
565 .ExpectedBlockOrAssignment = AstError.ExpectedBlockOrAssignment{ .token = it.index },570 .ExpectedBlockOrAssignment = .{ .token = it.index },
566 });571 });
567 return error.ParseError;572 return error.ParseError;
568 }573 }
...@@ -572,12 +577,12 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -572,12 +577,12 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
572 const else_node = if (semicolon == null) blk: {577 const else_node = if (semicolon == null) blk: {
573 const else_token = eatToken(it, .Keyword_else) orelse break :blk null;578 const else_token = eatToken(it, .Keyword_else) orelse break :blk null;
574 const payload = try parsePayload(arena, it, tree);579 const payload = try parsePayload(arena, it, tree);
575 const else_body = try expectNode(arena, it, tree, parseStatement, AstError{580 const else_body = try expectNode(arena, it, tree, parseStatement, .{
576 .InvalidToken = AstError.InvalidToken{ .token = it.index },581 .InvalidToken = .{ .token = it.index },
577 });582 });
578583
579 const node = try arena.create(Node.Else);584 const node = try arena.create(Node.Else);
580 node.* = Node.Else{585 node.* = .{
581 .else_token = else_token,586 .else_token = else_token,
582 .payload = payload,587 .payload = payload,
583 .body = else_body,588 .body = else_body,
...@@ -599,8 +604,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -599,8 +604,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
599 if_prefix.@"else" = else_node;604 if_prefix.@"else" = else_node;
600 return if_node;605 return if_node;
601 }606 }
602 try tree.errors.push(AstError{607 try tree.errors.push(.{
603 .ExpectedSemiOrElse = AstError.ExpectedSemiOrElse{ .token = it.index },608 .ExpectedSemiOrElse = .{ .token = it.index },
604 });609 });
605 return error.ParseError;610 return error.ParseError;
606 }611 }
...@@ -628,8 +633,8 @@ fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*...@@ -628,8 +633,8 @@ fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*
628 }633 }
629634
630 if (label_token != null) {635 if (label_token != null) {
631 try tree.errors.push(AstError{636 try tree.errors.push(.{
632 .ExpectedLabelable = AstError.ExpectedLabelable{ .token = it.index },637 .ExpectedLabelable = .{ .token = it.index },
633 });638 });
634 return error.ParseError;639 return error.ParseError;
635 }640 }
...@@ -665,12 +670,12 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -665,12 +670,12 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
665 for_prefix.body = block_expr_node;670 for_prefix.body = block_expr_node;
666671
667 if (eatToken(it, .Keyword_else)) |else_token| {672 if (eatToken(it, .Keyword_else)) |else_token| {
668 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{673 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
669 .InvalidToken = AstError.InvalidToken{ .token = it.index },674 .InvalidToken = .{ .token = it.index },
670 });675 });
671676
672 const else_node = try arena.create(Node.Else);677 const else_node = try arena.create(Node.Else);
673 else_node.* = Node.Else{678 else_node.* = .{
674 .else_token = else_token,679 .else_token = else_token,
675 .payload = null,680 .payload = null,
676 .body = statement_node,681 .body = statement_node,
...@@ -689,12 +694,12 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -689,12 +694,12 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
689 if (eatToken(it, .Semicolon) != null) return node;694 if (eatToken(it, .Semicolon) != null) return node;
690695
691 if (eatToken(it, .Keyword_else)) |else_token| {696 if (eatToken(it, .Keyword_else)) |else_token| {
692 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{697 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
693 .ExpectedStatement = AstError.ExpectedStatement{ .token = it.index },698 .ExpectedStatement = .{ .token = it.index },
694 });699 });
695700
696 const else_node = try arena.create(Node.Else);701 const else_node = try arena.create(Node.Else);
697 else_node.* = Node.Else{702 else_node.* = .{
698 .else_token = else_token,703 .else_token = else_token,
699 .payload = null,704 .payload = null,
700 .body = statement_node,705 .body = statement_node,
...@@ -703,8 +708,8 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -703,8 +708,8 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
703 return node;708 return node;
704 }709 }
705710
706 try tree.errors.push(AstError{711 try tree.errors.push(.{
707 .ExpectedSemiOrElse = AstError.ExpectedSemiOrElse{ .token = it.index },712 .ExpectedSemiOrElse = .{ .token = it.index },
708 });713 });
709 return null;714 return null;
710 }715 }
...@@ -725,12 +730,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -725,12 +730,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
725 if (eatToken(it, .Keyword_else)) |else_token| {730 if (eatToken(it, .Keyword_else)) |else_token| {
726 const payload = try parsePayload(arena, it, tree);731 const payload = try parsePayload(arena, it, tree);
727732
728 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{733 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
729 .InvalidToken = AstError.InvalidToken{ .token = it.index },734 .InvalidToken = .{ .token = it.index },
730 });735 });
731736
732 const else_node = try arena.create(Node.Else);737 const else_node = try arena.create(Node.Else);
733 else_node.* = Node.Else{738 else_node.* = .{
734 .else_token = else_token,739 .else_token = else_token,
735 .payload = payload,740 .payload = payload,
736 .body = statement_node,741 .body = statement_node,
...@@ -751,12 +756,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -751,12 +756,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
751 if (eatToken(it, .Keyword_else)) |else_token| {756 if (eatToken(it, .Keyword_else)) |else_token| {
752 const payload = try parsePayload(arena, it, tree);757 const payload = try parsePayload(arena, it, tree);
753758
754 const statement_node = try expectNode(arena, it, tree, parseStatement, AstError{759 const statement_node = try expectNode(arena, it, tree, parseStatement, .{
755 .ExpectedStatement = AstError.ExpectedStatement{ .token = it.index },760 .ExpectedStatement = .{ .token = it.index },
756 });761 });
757762
758 const else_node = try arena.create(Node.Else);763 const else_node = try arena.create(Node.Else);
759 else_node.* = Node.Else{764 else_node.* = .{
760 .else_token = else_token,765 .else_token = else_token,
761 .payload = payload,766 .payload = payload,
762 .body = statement_node,767 .body = statement_node,
...@@ -765,8 +770,8 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -765,8 +770,8 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
765 return node;770 return node;
766 }771 }
767772
768 try tree.errors.push(AstError{773 try tree.errors.push(.{
769 .ExpectedSemiOrElse = AstError.ExpectedSemiOrElse{ .token = it.index },774 .ExpectedSemiOrElse = .{ .token = it.index },
770 });775 });
771 return null;776 return null;
772 }777 }
...@@ -894,8 +899,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -894,8 +899,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
894 }899 }
895900
896 if (eatToken(it, .Keyword_comptime)) |token| {901 if (eatToken(it, .Keyword_comptime)) |token| {
897 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{902 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
898 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },903 .ExpectedExpr = .{ .token = it.index },
899 });904 });
900 const node = try arena.create(Node.Comptime);905 const node = try arena.create(Node.Comptime);
901 node.* = .{906 node.* = .{
...@@ -907,8 +912,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -907,8 +912,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
907 }912 }
908913
909 if (eatToken(it, .Keyword_noasync)) |token| {914 if (eatToken(it, .Keyword_noasync)) |token| {
910 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{915 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
911 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },916 .ExpectedExpr = .{ .token = it.index },
912 });917 });
913 const node = try arena.create(Node.Noasync);918 const node = try arena.create(Node.Noasync);
914 node.* = .{919 node.* = .{
...@@ -930,13 +935,13 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -930,13 +935,13 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
930 }935 }
931936
932 if (eatToken(it, .Keyword_resume)) |token| {937 if (eatToken(it, .Keyword_resume)) |token| {
933 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{938 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
934 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },939 .ExpectedExpr = .{ .token = it.index },
935 });940 });
936 const node = try arena.create(Node.PrefixOp);941 const node = try arena.create(Node.PrefixOp);
937 node.* = .{942 node.* = .{
938 .op_token = token,943 .op_token = token,
939 .op = Node.PrefixOp.Op.Resume,944 .op = .Resume,
940 .rhs = expr_node,945 .rhs = expr_node,
941 };946 };
942 return &node.base;947 return &node.base;
...@@ -992,7 +997,7 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -992,7 +997,7 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
992 const rbrace = try expectToken(it, tree, .RBrace);997 const rbrace = try expectToken(it, tree, .RBrace);
993998
994 const block_node = try arena.create(Node.Block);999 const block_node = try arena.create(Node.Block);
995 block_node.* = Node.Block{1000 block_node.* = .{
996 .label = null,1001 .label = null,
997 .lbrace = lbrace,1002 .lbrace = lbrace,
998 .statements = statements,1003 .statements = statements,
...@@ -1019,8 +1024,8 @@ fn parseLoopExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1019,8 +1024,8 @@ fn parseLoopExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1019 if (inline_token == null) return null;1024 if (inline_token == null) return null;
10201025
1021 // If we've seen "inline", there should have been a "for" or "while"1026 // If we've seen "inline", there should have been a "for" or "while"
1022 try tree.errors.push(AstError{1027 try tree.errors.push(.{
1023 .ExpectedInlinable = AstError.ExpectedInlinable{ .token = it.index },1028 .ExpectedInlinable = .{ .token = it.index },
1024 });1029 });
1025 return error.ParseError;1030 return error.ParseError;
1026}1031}
...@@ -1030,18 +1035,18 @@ fn parseForExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1030,18 +1035,18 @@ fn parseForExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1030 const node = (try parseForPrefix(arena, it, tree)) orelse return null;1035 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
1031 const for_prefix = node.cast(Node.For).?;1036 const for_prefix = node.cast(Node.For).?;
10321037
1033 const body_node = try expectNode(arena, it, tree, parseExpr, AstError{1038 const body_node = try expectNode(arena, it, tree, parseExpr, .{
1034 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1039 .ExpectedExpr = .{ .token = it.index },
1035 });1040 });
1036 for_prefix.body = body_node;1041 for_prefix.body = body_node;
10371042
1038 if (eatToken(it, .Keyword_else)) |else_token| {1043 if (eatToken(it, .Keyword_else)) |else_token| {
1039 const body = try expectNode(arena, it, tree, parseExpr, AstError{1044 const body = try expectNode(arena, it, tree, parseExpr, .{
1040 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1045 .ExpectedExpr = .{ .token = it.index },
1041 });1046 });
10421047
1043 const else_node = try arena.create(Node.Else);1048 const else_node = try arena.create(Node.Else);
1044 else_node.* = Node.Else{1049 else_node.* = .{
1045 .else_token = else_token,1050 .else_token = else_token,
1046 .payload = null,1051 .payload = null,
1047 .body = body,1052 .body = body,
...@@ -1058,19 +1063,19 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1058,19 +1063,19 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1058 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;1063 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
1059 const while_prefix = node.cast(Node.While).?;1064 const while_prefix = node.cast(Node.While).?;
10601065
1061 const body_node = try expectNode(arena, it, tree, parseExpr, AstError{1066 const body_node = try expectNode(arena, it, tree, parseExpr, .{
1062 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1067 .ExpectedExpr = .{ .token = it.index },
1063 });1068 });
1064 while_prefix.body = body_node;1069 while_prefix.body = body_node;
10651070
1066 if (eatToken(it, .Keyword_else)) |else_token| {1071 if (eatToken(it, .Keyword_else)) |else_token| {
1067 const payload = try parsePayload(arena, it, tree);1072 const payload = try parsePayload(arena, it, tree);
1068 const body = try expectNode(arena, it, tree, parseExpr, AstError{1073 const body = try expectNode(arena, it, tree, parseExpr, .{
1069 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1074 .ExpectedExpr = .{ .token = it.index },
1070 });1075 });
10711076
1072 const else_node = try arena.create(Node.Else);1077 const else_node = try arena.create(Node.Else);
1073 else_node.* = Node.Else{1078 else_node.* = .{
1074 .else_token = else_token,1079 .else_token = else_token,
1075 .payload = payload,1080 .payload = payload,
1076 .body = body,1081 .body = body,
...@@ -1098,14 +1103,14 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf...@@ -1098,14 +1103,14 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
1098 const lbrace = eatToken(it, .LBrace) orelse return null;1103 const lbrace = eatToken(it, .LBrace) orelse return null;
1099 var init_list = Node.SuffixOp.Op.InitList.init(arena);1104 var init_list = Node.SuffixOp.Op.InitList.init(arena);
11001105
1101 const op = blk: {1106 const op: Node.SuffixOp.Op = blk: {
1102 if (try parseFieldInit(arena, it, tree)) |field_init| {1107 if (try parseFieldInit(arena, it, tree)) |field_init| {
1103 try init_list.push(field_init);1108 try init_list.push(field_init);
1104 while (eatToken(it, .Comma)) |_| {1109 while (eatToken(it, .Comma)) |_| {
1105 const next = (try parseFieldInit(arena, it, tree)) orelse break;1110 const next = (try parseFieldInit(arena, it, tree)) orelse break;
1106 try init_list.push(next);1111 try init_list.push(next);
1107 }1112 }
1108 break :blk Node.SuffixOp.Op{ .StructInitializer = init_list };1113 break :blk .{ .StructInitializer = init_list };
1109 }1114 }
11101115
1111 if (try parseExpr(arena, it, tree)) |expr| {1116 if (try parseExpr(arena, it, tree)) |expr| {
...@@ -1114,14 +1119,14 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf...@@ -1114,14 +1119,14 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
1114 const next = (try parseExpr(arena, it, tree)) orelse break;1119 const next = (try parseExpr(arena, it, tree)) orelse break;
1115 try init_list.push(next);1120 try init_list.push(next);
1116 }1121 }
1117 break :blk Node.SuffixOp.Op{ .ArrayInitializer = init_list };1122 break :blk .{ .ArrayInitializer = init_list };
1118 }1123 }
11191124
1120 break :blk Node.SuffixOp.Op{ .StructInitializer = init_list };1125 break :blk .{ .StructInitializer = init_list };
1121 };1126 };
11221127
1123 const node = try arena.create(Node.SuffixOp);1128 const node = try arena.create(Node.SuffixOp);
1124 node.* = Node.SuffixOp{1129 node.* = .{
1125 .lhs = .{ .node = undefined }, // set by caller1130 .lhs = .{ .node = undefined }, // set by caller
1126 .op = op,1131 .op = op,
1127 .rtoken = try expectToken(it, tree, .RBrace),1132 .rtoken = try expectToken(it, tree, .RBrace),
...@@ -1140,8 +1145,8 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -1140,8 +1145,8 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
11401145
1141 if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(arena, it, tree)) |node| {1146 if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(arena, it, tree)) |node| {
1142 const error_union = node.cast(Node.InfixOp).?;1147 const error_union = node.cast(Node.InfixOp).?;
1143 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{1148 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1144 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },1149 .ExpectedTypeExpr = .{ .token = it.index },
1145 });1150 });
1146 error_union.lhs = suffix_expr;1151 error_union.lhs = suffix_expr;
1147 error_union.rhs = type_expr;1152 error_union.rhs = type_expr;
...@@ -1168,8 +1173,8 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1168,8 +1173,8 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1168 return parsePrimaryTypeExpr(arena, it, tree);1173 return parsePrimaryTypeExpr(arena, it, tree);
1169 }1174 }
1170 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr1175 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr
1171 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, AstError{1176 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, .{
1172 .ExpectedPrimaryTypeExpr = AstError.ExpectedPrimaryTypeExpr{ .token = it.index },1177 .ExpectedPrimaryTypeExpr = .{ .token = it.index },
1173 });1178 });
11741179
1175 while (try parseSuffixOp(arena, it, tree)) |node| {1180 while (try parseSuffixOp(arena, it, tree)) |node| {
...@@ -1182,16 +1187,16 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1182,16 +1187,16 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1182 }1187 }
11831188
1184 const params = (try parseFnCallArguments(arena, it, tree)) orelse {1189 const params = (try parseFnCallArguments(arena, it, tree)) orelse {
1185 try tree.errors.push(AstError{1190 try tree.errors.push(.{
1186 .ExpectedParamList = AstError.ExpectedParamList{ .token = it.index },1191 .ExpectedParamList = .{ .token = it.index },
1187 });1192 });
1188 return null;1193 return null;
1189 };1194 };
1190 const node = try arena.create(Node.SuffixOp);1195 const node = try arena.create(Node.SuffixOp);
1191 node.* = Node.SuffixOp{1196 node.* = .{
1192 .lhs = .{ .node = res },1197 .lhs = .{ .node = res },
1193 .op = Node.SuffixOp.Op{1198 .op = .{
1194 .Call = Node.SuffixOp.Op.Call{1199 .Call = .{
1195 .params = params.list,1200 .params = params.list,
1196 .async_token = async_token,1201 .async_token = async_token,
1197 },1202 },
...@@ -1215,10 +1220,10 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1215,10 +1220,10 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1215 }1220 }
1216 if (try parseFnCallArguments(arena, it, tree)) |params| {1221 if (try parseFnCallArguments(arena, it, tree)) |params| {
1217 const call = try arena.create(Node.SuffixOp);1222 const call = try arena.create(Node.SuffixOp);
1218 call.* = Node.SuffixOp{1223 call.* = .{
1219 .lhs = .{ .node = res },1224 .lhs = .{ .node = res },
1220 .op = Node.SuffixOp.Op{1225 .op = .{
1221 .Call = Node.SuffixOp.Op.Call{1226 .Call = .{
1222 .params = params.list,1227 .params = params.list,
1223 .async_token = null,1228 .async_token = null,
1224 },1229 },
...@@ -1264,7 +1269,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1264,7 +1269,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1264 if (try parseBuiltinCall(arena, it, tree)) |node| return node;1269 if (try parseBuiltinCall(arena, it, tree)) |node| return node;
1265 if (eatToken(it, .CharLiteral)) |token| {1270 if (eatToken(it, .CharLiteral)) |token| {
1266 const node = try arena.create(Node.CharLiteral);1271 const node = try arena.create(Node.CharLiteral);
1267 node.* = Node.CharLiteral{1272 node.* = .{
1268 .token = token,1273 .token = token,
1269 };1274 };
1270 return &node.base;1275 return &node.base;
...@@ -1300,15 +1305,15 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1300,15 +1305,15 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1300 }1305 }
1301 if (eatToken(it, .Keyword_error)) |token| {1306 if (eatToken(it, .Keyword_error)) |token| {
1302 const period = try expectToken(it, tree, .Period);1307 const period = try expectToken(it, tree, .Period);
1303 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{1308 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1304 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1309 .ExpectedIdentifier = .{ .token = it.index },
1305 });1310 });
1306 const global_error_set = try createLiteral(arena, Node.ErrorType, token);1311 const global_error_set = try createLiteral(arena, Node.ErrorType, token);
1307 const node = try arena.create(Node.InfixOp);1312 const node = try arena.create(Node.InfixOp);
1308 node.* = .{1313 node.* = .{
1309 .op_token = period,1314 .op_token = period,
1310 .lhs = global_error_set,1315 .lhs = global_error_set,
1311 .op = Node.InfixOp.Op.Period,1316 .op = .Period,
1312 .rhs = identifier,1317 .rhs = identifier,
1313 };1318 };
1314 return &node.base;1319 return &node.base;
...@@ -1358,7 +1363,7 @@ fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1358,7 +1363,7 @@ fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1358 const rbrace = try expectToken(it, tree, .RBrace);1363 const rbrace = try expectToken(it, tree, .RBrace);
13591364
1360 const node = try arena.create(Node.ErrorSetDecl);1365 const node = try arena.create(Node.ErrorSetDecl);
1361 node.* = Node.ErrorSetDecl{1366 node.* = .{
1362 .error_token = error_token,1367 .error_token = error_token,
1363 .decls = decls,1368 .decls = decls,
1364 .rbrace_token = rbrace,1369 .rbrace_token = rbrace,
...@@ -1369,13 +1374,13 @@ fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1369,13 +1374,13 @@ fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1369/// GroupedExpr <- LPAREN Expr RPAREN1374/// GroupedExpr <- LPAREN Expr RPAREN
1370fn parseGroupedExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1375fn parseGroupedExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1371 const lparen = eatToken(it, .LParen) orelse return null;1376 const lparen = eatToken(it, .LParen) orelse return null;
1372 const expr = try expectNode(arena, it, tree, parseExpr, AstError{1377 const expr = try expectNode(arena, it, tree, parseExpr, .{
1373 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1378 .ExpectedExpr = .{ .token = it.index },
1374 });1379 });
1375 const rparen = try expectToken(it, tree, .RParen);1380 const rparen = try expectToken(it, tree, .RParen);
13761381
1377 const node = try arena.create(Node.GroupedExpression);1382 const node = try arena.create(Node.GroupedExpression);
1378 node.* = Node.GroupedExpression{1383 node.* = .{
1379 .lparen = lparen,1384 .lparen = lparen,
1380 .expr = expr,1385 .expr = expr,
1381 .rparen = rparen,1386 .rparen = rparen,
...@@ -1435,8 +1440,8 @@ fn parseLoopTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1435,8 +1440,8 @@ fn parseLoopTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1435 if (inline_token == null) return null;1440 if (inline_token == null) return null;
14361441
1437 // If we've seen "inline", there should have been a "for" or "while"1442 // If we've seen "inline", there should have been a "for" or "while"
1438 try tree.errors.push(AstError{1443 try tree.errors.push(.{
1439 .ExpectedInlinable = AstError.ExpectedInlinable{ .token = it.index },1444 .ExpectedInlinable = .{ .token = it.index },
1440 });1445 });
1441 return error.ParseError;1446 return error.ParseError;
1442}1447}
...@@ -1446,18 +1451,18 @@ fn parseForTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1446,18 +1451,18 @@ fn parseForTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1446 const node = (try parseForPrefix(arena, it, tree)) orelse return null;1451 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
1447 const for_prefix = node.cast(Node.For).?;1452 const for_prefix = node.cast(Node.For).?;
14481453
1449 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{1454 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1450 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },1455 .ExpectedTypeExpr = .{ .token = it.index },
1451 });1456 });
1452 for_prefix.body = type_expr;1457 for_prefix.body = type_expr;
14531458
1454 if (eatToken(it, .Keyword_else)) |else_token| {1459 if (eatToken(it, .Keyword_else)) |else_token| {
1455 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{1460 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1456 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },1461 .ExpectedTypeExpr = .{ .token = it.index },
1457 });1462 });
14581463
1459 const else_node = try arena.create(Node.Else);1464 const else_node = try arena.create(Node.Else);
1460 else_node.* = Node.Else{1465 else_node.* = .{
1461 .else_token = else_token,1466 .else_token = else_token,
1462 .payload = null,1467 .payload = null,
1463 .body = else_expr,1468 .body = else_expr,
...@@ -1474,20 +1479,20 @@ fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod...@@ -1474,20 +1479,20 @@ fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
1474 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;1479 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
1475 const while_prefix = node.cast(Node.While).?;1480 const while_prefix = node.cast(Node.While).?;
14761481
1477 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{1482 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1478 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },1483 .ExpectedTypeExpr = .{ .token = it.index },
1479 });1484 });
1480 while_prefix.body = type_expr;1485 while_prefix.body = type_expr;
14811486
1482 if (eatToken(it, .Keyword_else)) |else_token| {1487 if (eatToken(it, .Keyword_else)) |else_token| {
1483 const payload = try parsePayload(arena, it, tree);1488 const payload = try parsePayload(arena, it, tree);
14841489
1485 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{1490 const else_expr = try expectNode(arena, it, tree, parseTypeExpr, .{
1486 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },1491 .ExpectedTypeExpr = .{ .token = it.index },
1487 });1492 });
14881493
1489 const else_node = try arena.create(Node.Else);1494 const else_node = try arena.create(Node.Else);
1490 else_node.* = Node.Else{1495 else_node.* = .{
1491 .else_token = else_token,1496 .else_token = else_token,
1492 .payload = null,1497 .payload = null,
1493 .body = else_expr,1498 .body = else_expr,
...@@ -1503,8 +1508,8 @@ fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod...@@ -1503,8 +1508,8 @@ fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
1503fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1508fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1504 const switch_token = eatToken(it, .Keyword_switch) orelse return null;1509 const switch_token = eatToken(it, .Keyword_switch) orelse return null;
1505 _ = try expectToken(it, tree, .LParen);1510 _ = try expectToken(it, tree, .LParen);
1506 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{1511 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1507 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1512 .ExpectedExpr = .{ .token = it.index },
1508 });1513 });
1509 _ = try expectToken(it, tree, .RParen);1514 _ = try expectToken(it, tree, .RParen);
1510 _ = try expectToken(it, tree, .LBrace);1515 _ = try expectToken(it, tree, .LBrace);
...@@ -1512,7 +1517,7 @@ fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1512,7 +1517,7 @@ fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1512 const rbrace = try expectToken(it, tree, .RBrace);1517 const rbrace = try expectToken(it, tree, .RBrace);
15131518
1514 const node = try arena.create(Node.Switch);1519 const node = try arena.create(Node.Switch);
1515 node.* = Node.Switch{1520 node.* = .{
1516 .switch_token = switch_token,1521 .switch_token = switch_token,
1517 .expr = expr_node,1522 .expr = expr_node,
1518 .cases = cases,1523 .cases = cases,
...@@ -1526,12 +1531,12 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1526,12 +1531,12 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1526 const asm_token = eatToken(it, .Keyword_asm) orelse return null;1531 const asm_token = eatToken(it, .Keyword_asm) orelse return null;
1527 const volatile_token = eatToken(it, .Keyword_volatile);1532 const volatile_token = eatToken(it, .Keyword_volatile);
1528 _ = try expectToken(it, tree, .LParen);1533 _ = try expectToken(it, tree, .LParen);
1529 const template = try expectNode(arena, it, tree, parseExpr, AstError{1534 const template = try expectNode(arena, it, tree, parseExpr, .{
1530 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1535 .ExpectedExpr = .{ .token = it.index },
1531 });1536 });
15321537
1533 const node = try arena.create(Node.Asm);1538 const node = try arena.create(Node.Asm);
1534 node.* = Node.Asm{1539 node.* = .{
1535 .asm_token = asm_token,1540 .asm_token = asm_token,
1536 .volatile_token = volatile_token,1541 .volatile_token = volatile_token,
1537 .template = template,1542 .template = template,
...@@ -1553,7 +1558,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1553,7 +1558,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1553 // anon enum literal1558 // anon enum literal
1554 if (eatToken(it, .Identifier)) |name| {1559 if (eatToken(it, .Identifier)) |name| {
1555 const node = try arena.create(Node.EnumLiteral);1560 const node = try arena.create(Node.EnumLiteral);
1556 node.* = Node.EnumLiteral{1561 node.* = .{
1557 .dot = dot,1562 .dot = dot,
1558 .name = name,1563 .name = name,
1559 };1564 };
...@@ -1580,32 +1585,32 @@ fn parseAsmOutput(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node:...@@ -1580,32 +1585,32 @@ fn parseAsmOutput(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node:
1580/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN1585/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
1581fn parseAsmOutputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.AsmOutput {1586fn parseAsmOutputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.AsmOutput {
1582 const lbracket = eatToken(it, .LBracket) orelse return null;1587 const lbracket = eatToken(it, .LBracket) orelse return null;
1583 const name = try expectNode(arena, it, tree, parseIdentifier, AstError{1588 const name = try expectNode(arena, it, tree, parseIdentifier, .{
1584 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1589 .ExpectedIdentifier = .{ .token = it.index },
1585 });1590 });
1586 _ = try expectToken(it, tree, .RBracket);1591 _ = try expectToken(it, tree, .RBracket);
15871592
1588 const constraint = try expectNode(arena, it, tree, parseStringLiteral, AstError{1593 const constraint = try expectNode(arena, it, tree, parseStringLiteral, .{
1589 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },1594 .ExpectedStringLiteral = .{ .token = it.index },
1590 });1595 });
15911596
1592 _ = try expectToken(it, tree, .LParen);1597 _ = try expectToken(it, tree, .LParen);
1593 const kind = blk: {1598 const kind: Node.AsmOutput.Kind = blk: {
1594 if (eatToken(it, .Arrow) != null) {1599 if (eatToken(it, .Arrow) != null) {
1595 const return_ident = try expectNode(arena, it, tree, parseTypeExpr, AstError{1600 const return_ident = try expectNode(arena, it, tree, parseTypeExpr, .{
1596 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },1601 .ExpectedTypeExpr = .{ .token = it.index },
1597 });1602 });
1598 break :blk Node.AsmOutput.Kind{ .Return = return_ident };1603 break :blk .{ .Return = return_ident };
1599 }1604 }
1600 const variable = try expectNode(arena, it, tree, parseIdentifier, AstError{1605 const variable = try expectNode(arena, it, tree, parseIdentifier, .{
1601 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1606 .ExpectedIdentifier = .{ .token = it.index },
1602 });1607 });
1603 break :blk Node.AsmOutput.Kind{ .Variable = variable.cast(Node.Identifier).? };1608 break :blk .{ .Variable = variable.cast(Node.Identifier).? };
1604 };1609 };
1605 const rparen = try expectToken(it, tree, .RParen);1610 const rparen = try expectToken(it, tree, .RParen);
16061611
1607 const node = try arena.create(Node.AsmOutput);1612 const node = try arena.create(Node.AsmOutput);
1608 node.* = Node.AsmOutput{1613 node.* = .{
1609 .lbracket = lbracket,1614 .lbracket = lbracket,
1610 .symbolic_name = name,1615 .symbolic_name = name,
1611 .constraint = constraint,1616 .constraint = constraint,
...@@ -1625,23 +1630,23 @@ fn parseAsmInput(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node: *...@@ -1625,23 +1630,23 @@ fn parseAsmInput(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node: *
1625/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN1630/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
1626fn parseAsmInputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.AsmInput {1631fn parseAsmInputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.AsmInput {
1627 const lbracket = eatToken(it, .LBracket) orelse return null;1632 const lbracket = eatToken(it, .LBracket) orelse return null;
1628 const name = try expectNode(arena, it, tree, parseIdentifier, AstError{1633 const name = try expectNode(arena, it, tree, parseIdentifier, .{
1629 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1634 .ExpectedIdentifier = .{ .token = it.index },
1630 });1635 });
1631 _ = try expectToken(it, tree, .RBracket);1636 _ = try expectToken(it, tree, .RBracket);
16321637
1633 const constraint = try expectNode(arena, it, tree, parseStringLiteral, AstError{1638 const constraint = try expectNode(arena, it, tree, parseStringLiteral, .{
1634 .ExpectedStringLiteral = AstError.ExpectedStringLiteral{ .token = it.index },1639 .ExpectedStringLiteral = .{ .token = it.index },
1635 });1640 });
16361641
1637 _ = try expectToken(it, tree, .LParen);1642 _ = try expectToken(it, tree, .LParen);
1638 const expr = try expectNode(arena, it, tree, parseExpr, AstError{1643 const expr = try expectNode(arena, it, tree, parseExpr, .{
1639 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1644 .ExpectedExpr = .{ .token = it.index },
1640 });1645 });
1641 const rparen = try expectToken(it, tree, .RParen);1646 const rparen = try expectToken(it, tree, .RParen);
16421647
1643 const node = try arena.create(Node.AsmInput);1648 const node = try arena.create(Node.AsmInput);
1644 node.* = Node.AsmInput{1649 node.* = .{
1645 .lbracket = lbracket,1650 .lbracket = lbracket,
1646 .symbolic_name = name,1651 .symbolic_name = name,
1647 .constraint = constraint,1652 .constraint = constraint,
...@@ -1664,8 +1669,8 @@ fn parseAsmClobbers(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node...@@ -1664,8 +1669,8 @@ fn parseAsmClobbers(arena: *Allocator, it: *TokenIterator, tree: *Tree, asm_node
1664/// BreakLabel <- COLON IDENTIFIER1669/// BreakLabel <- COLON IDENTIFIER
1665fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1670fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1666 _ = eatToken(it, .Colon) orelse return null;1671 _ = eatToken(it, .Colon) orelse return null;
1667 return try expectNode(arena, it, tree, parseIdentifier, AstError{1672 return try expectNode(arena, it, tree, parseIdentifier, .{
1668 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1673 .ExpectedIdentifier = .{ .token = it.index },
1669 });1674 });
1670}1675}
16711676
...@@ -1694,12 +1699,12 @@ fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1694,12 +1699,12 @@ fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1694 putBackToken(it, period_token);1699 putBackToken(it, period_token);
1695 return null;1700 return null;
1696 };1701 };
1697 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{1702 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1698 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1703 .ExpectedExpr = .{ .token = it.index },
1699 });1704 });
17001705
1701 const node = try arena.create(Node.FieldInitializer);1706 const node = try arena.create(Node.FieldInitializer);
1702 node.* = Node.FieldInitializer{1707 node.* = .{
1703 .period_token = period_token,1708 .period_token = period_token,
1704 .name_token = name_token,1709 .name_token = name_token,
1705 .expr = expr_node,1710 .expr = expr_node,
...@@ -1711,8 +1716,8 @@ fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1711,8 +1716,8 @@ fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1711fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1716fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1712 _ = eatToken(it, .Colon) orelse return null;1717 _ = eatToken(it, .Colon) orelse return null;
1713 _ = try expectToken(it, tree, .LParen);1718 _ = try expectToken(it, tree, .LParen);
1714 const node = try expectNode(arena, it, tree, parseAssignExpr, AstError{1719 const node = try expectNode(arena, it, tree, parseAssignExpr, .{
1715 .ExpectedExprOrAssignment = AstError.ExpectedExprOrAssignment{ .token = it.index },1720 .ExpectedExprOrAssignment = .{ .token = it.index },
1716 });1721 });
1717 _ = try expectToken(it, tree, .RParen);1722 _ = try expectToken(it, tree, .RParen);
1718 return node;1723 return node;
...@@ -1722,8 +1727,8 @@ fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?...@@ -1722,8 +1727,8 @@ fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
1722fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1727fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1723 _ = eatToken(it, .Keyword_linksection) orelse return null;1728 _ = eatToken(it, .Keyword_linksection) orelse return null;
1724 _ = try expectToken(it, tree, .LParen);1729 _ = try expectToken(it, tree, .LParen);
1725 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{1730 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1726 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1731 .ExpectedExpr = .{ .token = it.index },
1727 });1732 });
1728 _ = try expectToken(it, tree, .RParen);1733 _ = try expectToken(it, tree, .RParen);
1729 return expr_node;1734 return expr_node;
...@@ -1733,8 +1738,8 @@ fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1733,8 +1738,8 @@ fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1733fn parseCallconv(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1738fn parseCallconv(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1734 _ = eatToken(it, .Keyword_callconv) orelse return null;1739 _ = eatToken(it, .Keyword_callconv) orelse return null;
1735 _ = try expectToken(it, tree, .LParen);1740 _ = try expectToken(it, tree, .LParen);
1736 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{1741 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
1737 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1742 .ExpectedExpr = .{ .token = it.index },
1738 });1743 });
1739 _ = try expectToken(it, tree, .RParen);1744 _ = try expectToken(it, tree, .RParen);
1740 return expr_node;1745 return expr_node;
...@@ -1775,14 +1780,14 @@ fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1775,14 +1780,14 @@ fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1775 comptime_token == null and1780 comptime_token == null and
1776 name_token == null and1781 name_token == null and
1777 doc_comments == null) return null;1782 doc_comments == null) return null;
1778 try tree.errors.push(AstError{1783 try tree.errors.push(.{
1779 .ExpectedParamType = AstError.ExpectedParamType{ .token = it.index },1784 .ExpectedParamType = .{ .token = it.index },
1780 });1785 });
1781 return error.ParseError;1786 return error.ParseError;
1782 };1787 };
17831788
1784 const param_decl = try arena.create(Node.ParamDecl);1789 const param_decl = try arena.create(Node.ParamDecl);
1785 param_decl.* = Node.ParamDecl{1790 param_decl.* = .{
1786 .doc_comments = doc_comments,1791 .doc_comments = doc_comments,
1787 .comptime_token = comptime_token,1792 .comptime_token = comptime_token,
1788 .noalias_token = noalias_token,1793 .noalias_token = noalias_token,
...@@ -1821,14 +1826,14 @@ const ParamType = union(enum) {...@@ -1821,14 +1826,14 @@ const ParamType = union(enum) {
1821fn parseIfPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1826fn parseIfPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1822 const if_token = eatToken(it, .Keyword_if) orelse return null;1827 const if_token = eatToken(it, .Keyword_if) orelse return null;
1823 _ = try expectToken(it, tree, .LParen);1828 _ = try expectToken(it, tree, .LParen);
1824 const condition = try expectNode(arena, it, tree, parseExpr, AstError{1829 const condition = try expectNode(arena, it, tree, parseExpr, .{
1825 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1830 .ExpectedExpr = .{ .token = it.index },
1826 });1831 });
1827 _ = try expectToken(it, tree, .RParen);1832 _ = try expectToken(it, tree, .RParen);
1828 const payload = try parsePtrPayload(arena, it, tree);1833 const payload = try parsePtrPayload(arena, it, tree);
18291834
1830 const node = try arena.create(Node.If);1835 const node = try arena.create(Node.If);
1831 node.* = Node.If{1836 node.* = .{
1832 .if_token = if_token,1837 .if_token = if_token,
1833 .condition = condition,1838 .condition = condition,
1834 .payload = payload,1839 .payload = payload,
...@@ -1843,8 +1848,8 @@ fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1843,8 +1848,8 @@ fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1843 const while_token = eatToken(it, .Keyword_while) orelse return null;1848 const while_token = eatToken(it, .Keyword_while) orelse return null;
18441849
1845 _ = try expectToken(it, tree, .LParen);1850 _ = try expectToken(it, tree, .LParen);
1846 const condition = try expectNode(arena, it, tree, parseExpr, AstError{1851 const condition = try expectNode(arena, it, tree, parseExpr, .{
1847 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1852 .ExpectedExpr = .{ .token = it.index },
1848 });1853 });
1849 _ = try expectToken(it, tree, .RParen);1854 _ = try expectToken(it, tree, .RParen);
18501855
...@@ -1852,7 +1857,7 @@ fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1852,7 +1857,7 @@ fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1852 const continue_expr = try parseWhileContinueExpr(arena, it, tree);1857 const continue_expr = try parseWhileContinueExpr(arena, it, tree);
18531858
1854 const node = try arena.create(Node.While);1859 const node = try arena.create(Node.While);
1855 node.* = Node.While{1860 node.* = .{
1856 .label = null,1861 .label = null,
1857 .inline_token = null,1862 .inline_token = null,
1858 .while_token = while_token,1863 .while_token = while_token,
...@@ -1870,17 +1875,17 @@ fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1870,17 +1875,17 @@ fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1870 const for_token = eatToken(it, .Keyword_for) orelse return null;1875 const for_token = eatToken(it, .Keyword_for) orelse return null;
18711876
1872 _ = try expectToken(it, tree, .LParen);1877 _ = try expectToken(it, tree, .LParen);
1873 const array_expr = try expectNode(arena, it, tree, parseExpr, AstError{1878 const array_expr = try expectNode(arena, it, tree, parseExpr, .{
1874 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },1879 .ExpectedExpr = .{ .token = it.index },
1875 });1880 });
1876 _ = try expectToken(it, tree, .RParen);1881 _ = try expectToken(it, tree, .RParen);
18771882
1878 const payload = try expectNode(arena, it, tree, parsePtrIndexPayload, AstError{1883 const payload = try expectNode(arena, it, tree, parsePtrIndexPayload, .{
1879 .ExpectedPayload = AstError.ExpectedPayload{ .token = it.index },1884 .ExpectedPayload = .{ .token = it.index },
1880 });1885 });
18811886
1882 const node = try arena.create(Node.For);1887 const node = try arena.create(Node.For);
1883 node.* = Node.For{1888 node.* = .{
1884 .label = null,1889 .label = null,
1885 .inline_token = null,1890 .inline_token = null,
1886 .for_token = for_token,1891 .for_token = for_token,
...@@ -1895,13 +1900,13 @@ fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1895,13 +1900,13 @@ fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1895/// Payload <- PIPE IDENTIFIER PIPE1900/// Payload <- PIPE IDENTIFIER PIPE
1896fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1901fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1897 const lpipe = eatToken(it, .Pipe) orelse return null;1902 const lpipe = eatToken(it, .Pipe) orelse return null;
1898 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{1903 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1899 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1904 .ExpectedIdentifier = .{ .token = it.index },
1900 });1905 });
1901 const rpipe = try expectToken(it, tree, .Pipe);1906 const rpipe = try expectToken(it, tree, .Pipe);
19021907
1903 const node = try arena.create(Node.Payload);1908 const node = try arena.create(Node.Payload);
1904 node.* = Node.Payload{1909 node.* = .{
1905 .lpipe = lpipe,1910 .lpipe = lpipe,
1906 .error_symbol = identifier,1911 .error_symbol = identifier,
1907 .rpipe = rpipe,1912 .rpipe = rpipe,
...@@ -1913,13 +1918,13 @@ fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1913,13 +1918,13 @@ fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1913fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1918fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1914 const lpipe = eatToken(it, .Pipe) orelse return null;1919 const lpipe = eatToken(it, .Pipe) orelse return null;
1915 const asterisk = eatToken(it, .Asterisk);1920 const asterisk = eatToken(it, .Asterisk);
1916 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{1921 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1917 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1922 .ExpectedIdentifier = .{ .token = it.index },
1918 });1923 });
1919 const rpipe = try expectToken(it, tree, .Pipe);1924 const rpipe = try expectToken(it, tree, .Pipe);
19201925
1921 const node = try arena.create(Node.PointerPayload);1926 const node = try arena.create(Node.PointerPayload);
1922 node.* = Node.PointerPayload{1927 node.* = .{
1923 .lpipe = lpipe,1928 .lpipe = lpipe,
1924 .ptr_token = asterisk,1929 .ptr_token = asterisk,
1925 .value_symbol = identifier,1930 .value_symbol = identifier,
...@@ -1932,21 +1937,21 @@ fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1932,21 +1937,21 @@ fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1932fn parsePtrIndexPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1937fn parsePtrIndexPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1933 const lpipe = eatToken(it, .Pipe) orelse return null;1938 const lpipe = eatToken(it, .Pipe) orelse return null;
1934 const asterisk = eatToken(it, .Asterisk);1939 const asterisk = eatToken(it, .Asterisk);
1935 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{1940 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1936 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1941 .ExpectedIdentifier = .{ .token = it.index },
1937 });1942 });
19381943
1939 const index = if (eatToken(it, .Comma) == null)1944 const index = if (eatToken(it, .Comma) == null)
1940 null1945 null
1941 else1946 else
1942 try expectNode(arena, it, tree, parseIdentifier, AstError{1947 try expectNode(arena, it, tree, parseIdentifier, .{
1943 .ExpectedIdentifier = AstError.ExpectedIdentifier{ .token = it.index },1948 .ExpectedIdentifier = .{ .token = it.index },
1944 });1949 });
19451950
1946 const rpipe = try expectToken(it, tree, .Pipe);1951 const rpipe = try expectToken(it, tree, .Pipe);
19471952
1948 const node = try arena.create(Node.PointerIndexPayload);1953 const node = try arena.create(Node.PointerIndexPayload);
1949 node.* = Node.PointerIndexPayload{1954 node.* = .{
1950 .lpipe = lpipe,1955 .lpipe = lpipe,
1951 .ptr_token = asterisk,1956 .ptr_token = asterisk,
1952 .value_symbol = identifier,1957 .value_symbol = identifier,
...@@ -1961,8 +1966,8 @@ fn parseSwitchProng(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1961,8 +1966,8 @@ fn parseSwitchProng(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1961 const node = (try parseSwitchCase(arena, it, tree)) orelse return null;1966 const node = (try parseSwitchCase(arena, it, tree)) orelse return null;
1962 const arrow = try expectToken(it, tree, .EqualAngleBracketRight);1967 const arrow = try expectToken(it, tree, .EqualAngleBracketRight);
1963 const payload = try parsePtrPayload(arena, it, tree);1968 const payload = try parsePtrPayload(arena, it, tree);
1964 const expr = try expectNode(arena, it, tree, parseAssignExpr, AstError{1969 const expr = try expectNode(arena, it, tree, parseAssignExpr, .{
1965 .ExpectedExprOrAssignment = AstError.ExpectedExprOrAssignment{ .token = it.index },1970 .ExpectedExprOrAssignment = .{ .token = it.index },
1966 });1971 });
19671972
1968 const switch_case = node.cast(Node.SwitchCase).?;1973 const switch_case = node.cast(Node.SwitchCase).?;
...@@ -1987,14 +1992,14 @@ fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1987,14 +1992,14 @@ fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1987 }1992 }
1988 } else if (eatToken(it, .Keyword_else)) |else_token| {1993 } else if (eatToken(it, .Keyword_else)) |else_token| {
1989 const else_node = try arena.create(Node.SwitchElse);1994 const else_node = try arena.create(Node.SwitchElse);
1990 else_node.* = Node.SwitchElse{1995 else_node.* = .{
1991 .token = else_token,1996 .token = else_token,
1992 };1997 };
1993 try list.push(&else_node.base);1998 try list.push(&else_node.base);
1994 } else return null;1999 } else return null;
19952000
1996 const node = try arena.create(Node.SwitchCase);2001 const node = try arena.create(Node.SwitchCase);
1997 node.* = Node.SwitchCase{2002 node.* = .{
1998 .items = list,2003 .items = list,
1999 .arrow_token = undefined, // set by caller2004 .arrow_token = undefined, // set by caller
2000 .payload = null,2005 .payload = null,
...@@ -2007,15 +2012,15 @@ fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2007,15 +2012,15 @@ fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2007fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2012fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2008 const expr = (try parseExpr(arena, it, tree)) orelse return null;2013 const expr = (try parseExpr(arena, it, tree)) orelse return null;
2009 if (eatToken(it, .Ellipsis3)) |token| {2014 if (eatToken(it, .Ellipsis3)) |token| {
2010 const range_end = try expectNode(arena, it, tree, parseExpr, AstError{2015 const range_end = try expectNode(arena, it, tree, parseExpr, .{
2011 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2016 .ExpectedExpr = .{ .token = it.index },
2012 });2017 });
20132018
2014 const node = try arena.create(Node.InfixOp);2019 const node = try arena.create(Node.InfixOp);
2015 node.* = Node.InfixOp{2020 node.* = .{
2016 .op_token = token,2021 .op_token = token,
2017 .lhs = expr,2022 .lhs = expr,
2018 .op = Node.InfixOp.Op{ .Range = {} },2023 .op = .Range,
2019 .rhs = range_end,2024 .rhs = range_end,
2020 };2025 };
2021 return &node.base;2026 return &node.base;
...@@ -2039,24 +2044,22 @@ fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2039,24 +2044,22 @@ fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2039/// / MINUSPERCENTEQUAL2044/// / MINUSPERCENTEQUAL
2040/// / EQUAL2045/// / EQUAL
2041fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2046fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2042 const Op = Node.InfixOp.Op;
2043
2044 const token = nextToken(it);2047 const token = nextToken(it);
2045 const op = switch (token.ptr.id) {2048 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2046 .AsteriskEqual => Op{ .AssignMul = {} },2049 .AsteriskEqual => .AssignMul,
2047 .SlashEqual => Op{ .AssignDiv = {} },2050 .SlashEqual => .AssignDiv,
2048 .PercentEqual => Op{ .AssignMod = {} },2051 .PercentEqual => .AssignMod,
2049 .PlusEqual => Op{ .AssignAdd = {} },2052 .PlusEqual => .AssignAdd,
2050 .MinusEqual => Op{ .AssignSub = {} },2053 .MinusEqual => .AssignSub,
2051 .AngleBracketAngleBracketLeftEqual => Op{ .AssignBitShiftLeft = {} },2054 .AngleBracketAngleBracketLeftEqual => .AssignBitShiftLeft,
2052 .AngleBracketAngleBracketRightEqual => Op{ .AssignBitShiftRight = {} },2055 .AngleBracketAngleBracketRightEqual => .AssignBitShiftRight,
2053 .AmpersandEqual => Op{ .AssignBitAnd = {} },2056 .AmpersandEqual => .AssignBitAnd,
2054 .CaretEqual => Op{ .AssignBitXor = {} },2057 .CaretEqual => .AssignBitXor,
2055 .PipeEqual => Op{ .AssignBitOr = {} },2058 .PipeEqual => .AssignBitOr,
2056 .AsteriskPercentEqual => Op{ .AssignMulWrap = {} },2059 .AsteriskPercentEqual => .AssignMulWrap,
2057 .PlusPercentEqual => Op{ .AssignAddWrap = {} },2060 .PlusPercentEqual => .AssignAddWrap,
2058 .MinusPercentEqual => Op{ .AssignSubWrap = {} },2061 .MinusPercentEqual => .AssignSubWrap,
2059 .Equal => Op{ .Assign = {} },2062 .Equal => .Assign,
2060 else => {2063 else => {
2061 putBackToken(it, token.index);2064 putBackToken(it, token.index);
2062 return null;2065 return null;
...@@ -2064,7 +2067,7 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2064,7 +2067,7 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2064 };2067 };
20652068
2066 const node = try arena.create(Node.InfixOp);2069 const node = try arena.create(Node.InfixOp);
2067 node.* = Node.InfixOp{2070 node.* = .{
2068 .op_token = token.index,2071 .op_token = token.index,
2069 .lhs = undefined, // set by caller2072 .lhs = undefined, // set by caller
2070 .op = op,2073 .op = op,
...@@ -2081,16 +2084,14 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2081,16 +2084,14 @@ fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2081/// / LARROWEQUAL2084/// / LARROWEQUAL
2082/// / RARROWEQUAL2085/// / RARROWEQUAL
2083fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2086fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2084 const ops = Node.InfixOp.Op;
2085
2086 const token = nextToken(it);2087 const token = nextToken(it);
2087 const op = switch (token.ptr.id) {2088 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2088 .EqualEqual => ops{ .EqualEqual = {} },2089 .EqualEqual => .EqualEqual,
2089 .BangEqual => ops{ .BangEqual = {} },2090 .BangEqual => .BangEqual,
2090 .AngleBracketLeft => ops{ .LessThan = {} },2091 .AngleBracketLeft => .LessThan,
2091 .AngleBracketRight => ops{ .GreaterThan = {} },2092 .AngleBracketRight => .GreaterThan,
2092 .AngleBracketLeftEqual => ops{ .LessOrEqual = {} },2093 .AngleBracketLeftEqual => .LessOrEqual,
2093 .AngleBracketRightEqual => ops{ .GreaterOrEqual = {} },2094 .AngleBracketRightEqual => .GreaterOrEqual,
2094 else => {2095 else => {
2095 putBackToken(it, token.index);2096 putBackToken(it, token.index);
2096 return null;2097 return null;
...@@ -2107,15 +2108,13 @@ fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2107,15 +2108,13 @@ fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2107/// / KEYWORD_orelse2108/// / KEYWORD_orelse
2108/// / KEYWORD_catch Payload?2109/// / KEYWORD_catch Payload?
2109fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2110fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2110 const ops = Node.InfixOp.Op;
2111
2112 const token = nextToken(it);2111 const token = nextToken(it);
2113 const op = switch (token.ptr.id) {2112 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2114 .Ampersand => ops{ .BitAnd = {} },2113 .Ampersand => .BitAnd,
2115 .Caret => ops{ .BitXor = {} },2114 .Caret => .BitXor,
2116 .Pipe => ops{ .BitOr = {} },2115 .Pipe => .BitOr,
2117 .Keyword_orelse => ops{ .UnwrapOptional = {} },2116 .Keyword_orelse => .UnwrapOptional,
2118 .Keyword_catch => ops{ .Catch = try parsePayload(arena, it, tree) },2117 .Keyword_catch => .{ .Catch = try parsePayload(arena, it, tree) },
2119 else => {2118 else => {
2120 putBackToken(it, token.index);2119 putBackToken(it, token.index);
2121 return null;2120 return null;
...@@ -2129,12 +2128,10 @@ fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2129,12 +2128,10 @@ fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2129/// <- LARROW22128/// <- LARROW2
2130/// / RARROW22129/// / RARROW2
2131fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2130fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2132 const ops = Node.InfixOp.Op;
2133
2134 const token = nextToken(it);2131 const token = nextToken(it);
2135 const op = switch (token.ptr.id) {2132 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2136 .AngleBracketAngleBracketLeft => ops{ .BitShiftLeft = {} },2133 .AngleBracketAngleBracketLeft => .BitShiftLeft,
2137 .AngleBracketAngleBracketRight => ops{ .BitShiftRight = {} },2134 .AngleBracketAngleBracketRight => .BitShiftRight,
2138 else => {2135 else => {
2139 putBackToken(it, token.index);2136 putBackToken(it, token.index);
2140 return null;2137 return null;
...@@ -2151,15 +2148,13 @@ fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2151,15 +2148,13 @@ fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2151/// / PLUSPERCENT2148/// / PLUSPERCENT
2152/// / MINUSPERCENT2149/// / MINUSPERCENT
2153fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2150fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2154 const ops = Node.InfixOp.Op;
2155
2156 const token = nextToken(it);2151 const token = nextToken(it);
2157 const op = switch (token.ptr.id) {2152 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2158 .Plus => ops{ .Add = {} },2153 .Plus => .Add,
2159 .Minus => ops{ .Sub = {} },2154 .Minus => .Sub,
2160 .PlusPlus => ops{ .ArrayCat = {} },2155 .PlusPlus => .ArrayCat,
2161 .PlusPercent => ops{ .AddWrap = {} },2156 .PlusPercent => .AddWrap,
2162 .MinusPercent => ops{ .SubWrap = {} },2157 .MinusPercent => .SubWrap,
2163 else => {2158 else => {
2164 putBackToken(it, token.index);2159 putBackToken(it, token.index);
2165 return null;2160 return null;
...@@ -2177,16 +2172,14 @@ fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2177,16 +2172,14 @@ fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2177/// / ASTERISK22172/// / ASTERISK2
2178/// / ASTERISKPERCENT2173/// / ASTERISKPERCENT
2179fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2174fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2180 const ops = Node.InfixOp.Op;
2181
2182 const token = nextToken(it);2175 const token = nextToken(it);
2183 const op = switch (token.ptr.id) {2176 const op: Node.InfixOp.Op = switch (token.ptr.id) {
2184 .PipePipe => ops{ .BoolOr = {} },2177 .PipePipe => .MergeErrorSets,
2185 .Asterisk => ops{ .Mul = {} },2178 .Asterisk => .Mul,
2186 .Slash => ops{ .Div = {} },2179 .Slash => .Div,
2187 .Percent => ops{ .Mod = {} },2180 .Percent => .Mod,
2188 .AsteriskAsterisk => ops{ .ArrayMult = {} },2181 .AsteriskAsterisk => .ArrayMult,
2189 .AsteriskPercent => ops{ .MulWrap = {} },2182 .AsteriskPercent => .MulWrap,
2190 else => {2183 else => {
2191 putBackToken(it, token.index);2184 putBackToken(it, token.index);
2192 return null;2185 return null;
...@@ -2205,17 +2198,15 @@ fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2205,17 +2198,15 @@ fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2205/// / KEYWORD_try2198/// / KEYWORD_try
2206/// / KEYWORD_await2199/// / KEYWORD_await
2207fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2200fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2208 const ops = Node.PrefixOp.Op;
2209
2210 const token = nextToken(it);2201 const token = nextToken(it);
2211 const op = switch (token.ptr.id) {2202 const op: Node.PrefixOp.Op = switch (token.ptr.id) {
2212 .Bang => ops{ .BoolNot = {} },2203 .Bang => .BoolNot,
2213 .Minus => ops{ .Negation = {} },2204 .Minus => .Negation,
2214 .Tilde => ops{ .BitNot = {} },2205 .Tilde => .BitNot,
2215 .MinusPercent => ops{ .NegationWrap = {} },2206 .MinusPercent => .NegationWrap,
2216 .Ampersand => ops{ .AddressOf = {} },2207 .Ampersand => .AddressOf,
2217 .Keyword_try => ops{ .Try = {} },2208 .Keyword_try => .Try,
2218 .Keyword_await => ops{ .Await = .{} },2209 .Keyword_await => .Await,
2219 else => {2210 else => {
2220 putBackToken(it, token.index);2211 putBackToken(it, token.index);
2221 return null;2212 return null;
...@@ -2223,7 +2214,7 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2223,7 +2214,7 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2223 };2214 };
22242215
2225 const node = try arena.create(Node.PrefixOp);2216 const node = try arena.create(Node.PrefixOp);
2226 node.* = Node.PrefixOp{2217 node.* = .{
2227 .op_token = token.index,2218 .op_token = token.index,
2228 .op = op,2219 .op = op,
2229 .rhs = undefined, // set by caller2220 .rhs = undefined, // set by caller
...@@ -2246,9 +2237,9 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2246,9 +2237,9 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2246fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2237fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2247 if (eatToken(it, .QuestionMark)) |token| {2238 if (eatToken(it, .QuestionMark)) |token| {
2248 const node = try arena.create(Node.PrefixOp);2239 const node = try arena.create(Node.PrefixOp);
2249 node.* = Node.PrefixOp{2240 node.* = .{
2250 .op_token = token,2241 .op_token = token,
2251 .op = Node.PrefixOp.Op.OptionalType,2242 .op = .OptionalType,
2252 .rhs = undefined, // set by caller2243 .rhs = undefined, // set by caller
2253 };2244 };
2254 return &node.base;2245 return &node.base;
...@@ -2264,7 +2255,7 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2264,7 +2255,7 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2264 return null;2255 return null;
2265 };2256 };
2266 const node = try arena.create(Node.AnyFrameType);2257 const node = try arena.create(Node.AnyFrameType);
2267 node.* = Node.AnyFrameType{2258 node.* = .{
2268 .anyframe_token = token,2259 .anyframe_token = token,
2269 .result = Node.AnyFrameType.Result{2260 .result = Node.AnyFrameType.Result{
2270 .arrow_token = arrow,2261 .arrow_token = arrow,
...@@ -2286,18 +2277,18 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2286,18 +2277,18 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2286 while (true) {2277 while (true) {
2287 if (eatToken(it, .Keyword_align)) |align_token| {2278 if (eatToken(it, .Keyword_align)) |align_token| {
2288 const lparen = try expectToken(it, tree, .LParen);2279 const lparen = try expectToken(it, tree, .LParen);
2289 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{2280 const expr_node = try expectNode(arena, it, tree, parseExpr, .{
2290 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2281 .ExpectedExpr = .{ .token = it.index },
2291 });2282 });
22922283
2293 // Optional bit range2284 // Optional bit range
2294 const bit_range = if (eatToken(it, .Colon)) |_| bit_range_value: {2285 const bit_range = if (eatToken(it, .Colon)) |_| bit_range_value: {
2295 const range_start = try expectNode(arena, it, tree, parseIntegerLiteral, AstError{2286 const range_start = try expectNode(arena, it, tree, parseIntegerLiteral, .{
2296 .ExpectedIntegerLiteral = AstError.ExpectedIntegerLiteral{ .token = it.index },2287 .ExpectedIntegerLiteral = .{ .token = it.index },
2297 });2288 });
2298 _ = try expectToken(it, tree, .Colon);2289 _ = try expectToken(it, tree, .Colon);
2299 const range_end = try expectNode(arena, it, tree, parseIntegerLiteral, AstError{2290 const range_end = try expectNode(arena, it, tree, parseIntegerLiteral, .{
2300 .ExpectedIntegerLiteral = AstError.ExpectedIntegerLiteral{ .token = it.index },2291 .ExpectedIntegerLiteral = .{ .token = it.index },
2301 });2292 });
23022293
2303 break :bit_range_value Node.PrefixOp.PtrInfo.Align.BitRange{2294 break :bit_range_value Node.PrefixOp.PtrInfo.Align.BitRange{
...@@ -2340,8 +2331,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2340,8 +2331,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2340 while (true) {2331 while (true) {
2341 if (try parseByteAlign(arena, it, tree)) |align_expr| {2332 if (try parseByteAlign(arena, it, tree)) |align_expr| {
2342 if (slice_type.align_info != null) {2333 if (slice_type.align_info != null) {
2343 try tree.errors.push(AstError{2334 try tree.errors.push(.{
2344 .ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index },2335 .ExtraAlignQualifier = .{ .token = it.index },
2345 });2336 });
2346 return error.ParseError;2337 return error.ParseError;
2347 }2338 }
...@@ -2353,8 +2344,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2353,8 +2344,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2353 }2344 }
2354 if (eatToken(it, .Keyword_const)) |const_token| {2345 if (eatToken(it, .Keyword_const)) |const_token| {
2355 if (slice_type.const_token != null) {2346 if (slice_type.const_token != null) {
2356 try tree.errors.push(AstError{2347 try tree.errors.push(.{
2357 .ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index },2348 .ExtraConstQualifier = .{ .token = it.index },
2358 });2349 });
2359 return error.ParseError;2350 return error.ParseError;
2360 }2351 }
...@@ -2363,8 +2354,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2363,8 +2354,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2363 }2354 }
2364 if (eatToken(it, .Keyword_volatile)) |volatile_token| {2355 if (eatToken(it, .Keyword_volatile)) |volatile_token| {
2365 if (slice_type.volatile_token != null) {2356 if (slice_type.volatile_token != null) {
2366 try tree.errors.push(AstError{2357 try tree.errors.push(.{
2367 .ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index },2358 .ExtraVolatileQualifier = .{ .token = it.index },
2368 });2359 });
2369 return error.ParseError;2360 return error.ParseError;
2370 }2361 }
...@@ -2373,8 +2364,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2373,8 +2364,8 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2373 }2364 }
2374 if (eatToken(it, .Keyword_allowzero)) |allowzero_token| {2365 if (eatToken(it, .Keyword_allowzero)) |allowzero_token| {
2375 if (slice_type.allowzero_token != null) {2366 if (slice_type.allowzero_token != null) {
2376 try tree.errors.push(AstError{2367 try tree.errors.push(.{
2377 .ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index },2368 .ExtraAllowZeroQualifier = .{ .token = it.index },
2378 });2369 });
2379 return error.ParseError;2370 return error.ParseError;
2380 }2371 }
...@@ -2398,15 +2389,14 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2398,15 +2389,14 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2398/// / DOTASTERISK2389/// / DOTASTERISK
2399/// / DOTQUESTIONMARK2390/// / DOTQUESTIONMARK
2400fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2391fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2401 const Op = Node.SuffixOp.Op;
2402 const OpAndToken = struct {2392 const OpAndToken = struct {
2403 op: Node.SuffixOp.Op,2393 op: Node.SuffixOp.Op,
2404 token: TokenIndex,2394 token: TokenIndex,
2405 };2395 };
2406 const op_and_token = blk: {2396 const op_and_token: OpAndToken = blk: {
2407 if (eatToken(it, .LBracket)) |_| {2397 if (eatToken(it, .LBracket)) |_| {
2408 const index_expr = try expectNode(arena, it, tree, parseExpr, AstError{2398 const index_expr = try expectNode(arena, it, tree, parseExpr, .{
2409 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2399 .ExpectedExpr = .{ .token = it.index },
2410 });2400 });
24112401
2412 if (eatToken(it, .Ellipsis2) != null) {2402 if (eatToken(it, .Ellipsis2) != null) {
...@@ -2415,9 +2405,9 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2415,9 +2405,9 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2415 try parseExpr(arena, it, tree)2405 try parseExpr(arena, it, tree)
2416 else2406 else
2417 null;2407 null;
2418 break :blk OpAndToken{2408 break :blk .{
2419 .op = Op{2409 .op = .{
2420 .Slice = Op.Slice{2410 .Slice = .{
2421 .start = index_expr,2411 .start = index_expr,
2422 .end = end_expr,2412 .end = end_expr,
2423 .sentinel = sentinel,2413 .sentinel = sentinel,
...@@ -2427,14 +2417,14 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2427,14 +2417,14 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2427 };2417 };
2428 }2418 }
24292419
2430 break :blk OpAndToken{2420 break :blk .{
2431 .op = Op{ .ArrayAccess = index_expr },2421 .op = .{ .ArrayAccess = index_expr },
2432 .token = try expectToken(it, tree, .RBracket),2422 .token = try expectToken(it, tree, .RBracket),
2433 };2423 };
2434 }2424 }
24352425
2436 if (eatToken(it, .PeriodAsterisk)) |period_asterisk| {2426 if (eatToken(it, .PeriodAsterisk)) |period_asterisk| {
2437 break :blk OpAndToken{ .op = Op{ .Deref = {} }, .token = period_asterisk };2427 break :blk .{ .op = .Deref, .token = period_asterisk };
2438 }2428 }
24392429
2440 if (eatToken(it, .Period)) |period| {2430 if (eatToken(it, .Period)) |period| {
...@@ -2443,19 +2433,19 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2443,19 +2433,19 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2443 // Should there be an ast.Node.SuffixOp.FieldAccess variant? Or should2433 // Should there be an ast.Node.SuffixOp.FieldAccess variant? Or should
2444 // this grammar rule be altered?2434 // this grammar rule be altered?
2445 const node = try arena.create(Node.InfixOp);2435 const node = try arena.create(Node.InfixOp);
2446 node.* = Node.InfixOp{2436 node.* = .{
2447 .op_token = period,2437 .op_token = period,
2448 .lhs = undefined, // set by caller2438 .lhs = undefined, // set by caller
2449 .op = Node.InfixOp.Op.Period,2439 .op = .Period,
2450 .rhs = identifier,2440 .rhs = identifier,
2451 };2441 };
2452 return &node.base;2442 return &node.base;
2453 }2443 }
2454 if (eatToken(it, .QuestionMark)) |question_mark| {2444 if (eatToken(it, .QuestionMark)) |question_mark| {
2455 break :blk OpAndToken{ .op = Op{ .UnwrapOptional = {} }, .token = question_mark };2445 break :blk .{ .op = .UnwrapOptional, .token = question_mark };
2456 }2446 }
2457 try tree.errors.push(AstError{2447 try tree.errors.push(.{
2458 .ExpectedSuffixOp = AstError.ExpectedSuffixOp{ .token = it.index },2448 .ExpectedSuffixOp = .{ .token = it.index },
2459 });2449 });
2460 return null;2450 return null;
2461 }2451 }
...@@ -2464,7 +2454,7 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2464,7 +2454,7 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2464 };2454 };
24652455
2466 const node = try arena.create(Node.SuffixOp);2456 const node = try arena.create(Node.SuffixOp);
2467 node.* = Node.SuffixOp{2457 node.* = .{
2468 .lhs = undefined, // set by caller2458 .lhs = undefined, // set by caller
2469 .op = op_and_token.op,2459 .op = op_and_token.op,
2470 .rtoken = op_and_token.token,2460 .rtoken = op_and_token.token,
...@@ -2491,22 +2481,22 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2491,22 +2481,22 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2491 const lbracket = eatToken(it, .LBracket) orelse return null;2481 const lbracket = eatToken(it, .LBracket) orelse return null;
2492 const expr = try parseExpr(arena, it, tree);2482 const expr = try parseExpr(arena, it, tree);
2493 const sentinel = if (eatToken(it, .Colon)) |_|2483 const sentinel = if (eatToken(it, .Colon)) |_|
2494 try expectNode(arena, it, tree, parseExpr, AstError{2484 try expectNode(arena, it, tree, parseExpr, .{
2495 .ExpectedExpr = .{ .token = it.index },2485 .ExpectedExpr = .{ .token = it.index },
2496 })2486 })
2497 else2487 else
2498 null;2488 null;
2499 const rbracket = try expectToken(it, tree, .RBracket);2489 const rbracket = try expectToken(it, tree, .RBracket);
25002490
2501 const op = if (expr) |len_expr|2491 const op: Node.PrefixOp.Op = if (expr) |len_expr|
2502 Node.PrefixOp.Op{2492 .{
2503 .ArrayType = .{2493 .ArrayType = .{
2504 .len_expr = len_expr,2494 .len_expr = len_expr,
2505 .sentinel = sentinel,2495 .sentinel = sentinel,
2506 },2496 },
2507 }2497 }
2508 else2498 else
2509 Node.PrefixOp.Op{2499 .{
2510 .SliceType = Node.PrefixOp.PtrInfo{2500 .SliceType = Node.PrefixOp.PtrInfo{
2511 .allowzero_token = null,2501 .allowzero_token = null,
2512 .align_info = null,2502 .align_info = null,
...@@ -2517,7 +2507,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2517,7 +2507,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2517 };2507 };
25182508
2519 const node = try arena.create(Node.PrefixOp);2509 const node = try arena.create(Node.PrefixOp);
2520 node.* = Node.PrefixOp{2510 node.* = .{
2521 .op_token = lbracket,2511 .op_token = lbracket,
2522 .op = op,2512 .op = op,
2523 .rhs = undefined, // set by caller2513 .rhs = undefined, // set by caller
...@@ -2533,7 +2523,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2533,7 +2523,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2533fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2523fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2534 if (eatToken(it, .Asterisk)) |asterisk| {2524 if (eatToken(it, .Asterisk)) |asterisk| {
2535 const sentinel = if (eatToken(it, .Colon)) |_|2525 const sentinel = if (eatToken(it, .Colon)) |_|
2536 try expectNode(arena, it, tree, parseExpr, AstError{2526 try expectNode(arena, it, tree, parseExpr, .{
2537 .ExpectedExpr = .{ .token = it.index },2527 .ExpectedExpr = .{ .token = it.index },
2538 })2528 })
2539 else2529 else
...@@ -2549,17 +2539,17 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2549,17 +2539,17 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
25492539
2550 if (eatToken(it, .AsteriskAsterisk)) |double_asterisk| {2540 if (eatToken(it, .AsteriskAsterisk)) |double_asterisk| {
2551 const node = try arena.create(Node.PrefixOp);2541 const node = try arena.create(Node.PrefixOp);
2552 node.* = Node.PrefixOp{2542 node.* = .{
2553 .op_token = double_asterisk,2543 .op_token = double_asterisk,
2554 .op = Node.PrefixOp.Op{ .PtrType = .{} },2544 .op = .{ .PtrType = .{} },
2555 .rhs = undefined, // set by caller2545 .rhs = undefined, // set by caller
2556 };2546 };
25572547
2558 // Special case for **, which is its own token2548 // Special case for **, which is its own token
2559 const child = try arena.create(Node.PrefixOp);2549 const child = try arena.create(Node.PrefixOp);
2560 child.* = Node.PrefixOp{2550 child.* = .{
2561 .op_token = double_asterisk,2551 .op_token = double_asterisk,
2562 .op = Node.PrefixOp.Op{ .PtrType = .{} },2552 .op = .{ .PtrType = .{} },
2563 .rhs = undefined, // set by caller2553 .rhs = undefined, // set by caller
2564 };2554 };
2565 node.rhs = &child.base;2555 node.rhs = &child.base;
...@@ -2586,7 +2576,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2586,7 +2576,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2586 }2576 }
2587 }2577 }
2588 const sentinel = if (eatToken(it, .Colon)) |_|2578 const sentinel = if (eatToken(it, .Colon)) |_|
2589 try expectNode(arena, it, tree, parseExpr, AstError{2579 try expectNode(arena, it, tree, parseExpr, .{
2590 .ExpectedExpr = .{ .token = it.index },2580 .ExpectedExpr = .{ .token = it.index },
2591 })2581 })
2592 else2582 else
...@@ -2629,8 +2619,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?...@@ -2629,8 +2619,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
2629 .Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} },2619 .Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} },
2630 .Keyword_enum => blk: {2620 .Keyword_enum => blk: {
2631 if (eatToken(it, .LParen) != null) {2621 if (eatToken(it, .LParen) != null) {
2632 const expr = try expectNode(arena, it, tree, parseExpr, AstError{2622 const expr = try expectNode(arena, it, tree, parseExpr, .{
2633 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2623 .ExpectedExpr = .{ .token = it.index },
2634 });2624 });
2635 _ = try expectToken(it, tree, .RParen);2625 _ = try expectToken(it, tree, .RParen);
2636 break :blk Node.ContainerDecl.InitArg{ .Type = expr };2626 break :blk Node.ContainerDecl.InitArg{ .Type = expr };
...@@ -2641,8 +2631,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?...@@ -2641,8 +2631,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
2641 if (eatToken(it, .LParen) != null) {2631 if (eatToken(it, .LParen) != null) {
2642 if (eatToken(it, .Keyword_enum) != null) {2632 if (eatToken(it, .Keyword_enum) != null) {
2643 if (eatToken(it, .LParen) != null) {2633 if (eatToken(it, .LParen) != null) {
2644 const expr = try expectNode(arena, it, tree, parseExpr, AstError{2634 const expr = try expectNode(arena, it, tree, parseExpr, .{
2645 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2635 .ExpectedExpr = .{ .token = it.index },
2646 });2636 });
2647 _ = try expectToken(it, tree, .RParen);2637 _ = try expectToken(it, tree, .RParen);
2648 _ = try expectToken(it, tree, .RParen);2638 _ = try expectToken(it, tree, .RParen);
...@@ -2651,8 +2641,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?...@@ -2651,8 +2641,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
2651 _ = try expectToken(it, tree, .RParen);2641 _ = try expectToken(it, tree, .RParen);
2652 break :blk Node.ContainerDecl.InitArg{ .Enum = null };2642 break :blk Node.ContainerDecl.InitArg{ .Enum = null };
2653 }2643 }
2654 const expr = try expectNode(arena, it, tree, parseExpr, AstError{2644 const expr = try expectNode(arena, it, tree, parseExpr, .{
2655 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2645 .ExpectedExpr = .{ .token = it.index },
2656 });2646 });
2657 _ = try expectToken(it, tree, .RParen);2647 _ = try expectToken(it, tree, .RParen);
2658 break :blk Node.ContainerDecl.InitArg{ .Type = expr };2648 break :blk Node.ContainerDecl.InitArg{ .Type = expr };
...@@ -2666,7 +2656,7 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?...@@ -2666,7 +2656,7 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
2666 };2656 };
26672657
2668 const node = try arena.create(Node.ContainerDecl);2658 const node = try arena.create(Node.ContainerDecl);
2669 node.* = Node.ContainerDecl{2659 node.* = .{
2670 .layout_token = null,2660 .layout_token = null,
2671 .kind_token = kind_token.index,2661 .kind_token = kind_token.index,
2672 .init_arg_expr = init_arg_expr,2662 .init_arg_expr = init_arg_expr,
...@@ -2681,8 +2671,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?...@@ -2681,8 +2671,8 @@ fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?
2681fn parseByteAlign(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2671fn parseByteAlign(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2682 _ = eatToken(it, .Keyword_align) orelse return null;2672 _ = eatToken(it, .Keyword_align) orelse return null;
2683 _ = try expectToken(it, tree, .LParen);2673 _ = try expectToken(it, tree, .LParen);
2684 const expr = try expectNode(arena, it, tree, parseExpr, AstError{2674 const expr = try expectNode(arena, it, tree, parseExpr, .{
2685 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2675 .ExpectedExpr = .{ .token = it.index },
2686 });2676 });
2687 _ = try expectToken(it, tree, .RParen);2677 _ = try expectToken(it, tree, .RParen);
2688 return expr;2678 return expr;
...@@ -2738,7 +2728,7 @@ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) No...@@ -2738,7 +2728,7 @@ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) No
2738 pub fn parse(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node {2728 pub fn parse(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node {
2739 const op_token = eatToken(it, token) orelse return null;2729 const op_token = eatToken(it, token) orelse return null;
2740 const node = try arena.create(Node.InfixOp);2730 const node = try arena.create(Node.InfixOp);
2741 node.* = Node.InfixOp{2731 node.* = .{
2742 .op_token = op_token,2732 .op_token = op_token,
2743 .lhs = undefined, // set by caller2733 .lhs = undefined, // set by caller
2744 .op = op,2734 .op = op,
...@@ -2754,13 +2744,13 @@ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) No...@@ -2754,13 +2744,13 @@ fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) No
2754fn parseBuiltinCall(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2744fn parseBuiltinCall(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2755 const token = eatToken(it, .Builtin) orelse return null;2745 const token = eatToken(it, .Builtin) orelse return null;
2756 const params = (try parseFnCallArguments(arena, it, tree)) orelse {2746 const params = (try parseFnCallArguments(arena, it, tree)) orelse {
2757 try tree.errors.push(AstError{2747 try tree.errors.push(.{
2758 .ExpectedParamList = AstError.ExpectedParamList{ .token = it.index },2748 .ExpectedParamList = .{ .token = it.index },
2759 });2749 });
2760 return error.ParseError;2750 return error.ParseError;
2761 };2751 };
2762 const node = try arena.create(Node.BuiltinCall);2752 const node = try arena.create(Node.BuiltinCall);
2763 node.* = Node.BuiltinCall{2753 node.* = .{
2764 .builtin_token = token,2754 .builtin_token = token,
2765 .params = params.list,2755 .params = params.list,
2766 .rparen_token = params.rparen,2756 .rparen_token = params.rparen,
...@@ -2773,7 +2763,7 @@ fn parseErrorTag(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2773,7 +2763,7 @@ fn parseErrorTag(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2773 const token = eatToken(it, .Identifier) orelse return null;2763 const token = eatToken(it, .Identifier) orelse return null;
27742764
2775 const node = try arena.create(Node.ErrorTag);2765 const node = try arena.create(Node.ErrorTag);
2776 node.* = Node.ErrorTag{2766 node.* = .{
2777 .doc_comments = doc_comments,2767 .doc_comments = doc_comments,
2778 .name_token = token,2768 .name_token = token,
2779 };2769 };
...@@ -2783,7 +2773,7 @@ fn parseErrorTag(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2783,7 +2773,7 @@ fn parseErrorTag(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2783fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2773fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2784 const token = eatToken(it, .Identifier) orelse return null;2774 const token = eatToken(it, .Identifier) orelse return null;
2785 const node = try arena.create(Node.Identifier);2775 const node = try arena.create(Node.Identifier);
2786 node.* = Node.Identifier{2776 node.* = .{
2787 .token = token,2777 .token = token,
2788 };2778 };
2789 return &node.base;2779 return &node.base;
...@@ -2792,7 +2782,7 @@ fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2792,7 +2782,7 @@ fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2792fn parseVarType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2782fn parseVarType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2793 const token = eatToken(it, .Keyword_var) orelse return null;2783 const token = eatToken(it, .Keyword_var) orelse return null;
2794 const node = try arena.create(Node.VarType);2784 const node = try arena.create(Node.VarType);
2795 node.* = Node.VarType{2785 node.* = .{
2796 .token = token,2786 .token = token,
2797 };2787 };
2798 return &node.base;2788 return &node.base;
...@@ -2810,7 +2800,7 @@ fn createLiteral(arena: *Allocator, comptime T: type, token: TokenIndex) !*Node...@@ -2810,7 +2800,7 @@ fn createLiteral(arena: *Allocator, comptime T: type, token: TokenIndex) !*Node
2810fn parseStringLiteralSingle(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2800fn parseStringLiteralSingle(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2811 if (eatToken(it, .StringLiteral)) |token| {2801 if (eatToken(it, .StringLiteral)) |token| {
2812 const node = try arena.create(Node.StringLiteral);2802 const node = try arena.create(Node.StringLiteral);
2813 node.* = Node.StringLiteral{2803 node.* = .{
2814 .token = token,2804 .token = token,
2815 };2805 };
2816 return &node.base;2806 return &node.base;
...@@ -2824,7 +2814,7 @@ fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod...@@ -2824,7 +2814,7 @@ fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
28242814
2825 if (eatToken(it, .MultilineStringLiteralLine)) |first_line| {2815 if (eatToken(it, .MultilineStringLiteralLine)) |first_line| {
2826 const node = try arena.create(Node.MultilineStringLiteral);2816 const node = try arena.create(Node.MultilineStringLiteral);
2827 node.* = Node.MultilineStringLiteral{2817 node.* = .{
2828 .lines = Node.MultilineStringLiteral.LineList.init(arena),2818 .lines = Node.MultilineStringLiteral.LineList.init(arena),
2829 };2819 };
2830 try node.lines.push(first_line);2820 try node.lines.push(first_line);
...@@ -2840,7 +2830,7 @@ fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod...@@ -2840,7 +2830,7 @@ fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
2840fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2830fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2841 const token = eatToken(it, .IntegerLiteral) orelse return null;2831 const token = eatToken(it, .IntegerLiteral) orelse return null;
2842 const node = try arena.create(Node.IntegerLiteral);2832 const node = try arena.create(Node.IntegerLiteral);
2843 node.* = Node.IntegerLiteral{2833 node.* = .{
2844 .token = token,2834 .token = token,
2845 };2835 };
2846 return &node.base;2836 return &node.base;
...@@ -2849,7 +2839,7 @@ fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2849,7 +2839,7 @@ fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2849fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2839fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2850 const token = eatToken(it, .FloatLiteral) orelse return null;2840 const token = eatToken(it, .FloatLiteral) orelse return null;
2851 const node = try arena.create(Node.FloatLiteral);2841 const node = try arena.create(Node.FloatLiteral);
2852 node.* = Node.FloatLiteral{2842 node.* = .{
2853 .token = token,2843 .token = token,
2854 };2844 };
2855 return &node.base;2845 return &node.base;
...@@ -2858,9 +2848,9 @@ fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2858,9 +2848,9 @@ fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2858fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2848fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2859 const token = eatToken(it, .Keyword_try) orelse return null;2849 const token = eatToken(it, .Keyword_try) orelse return null;
2860 const node = try arena.create(Node.PrefixOp);2850 const node = try arena.create(Node.PrefixOp);
2861 node.* = Node.PrefixOp{2851 node.* = .{
2862 .op_token = token,2852 .op_token = token,
2863 .op = Node.PrefixOp.Op.Try,2853 .op = .Try,
2864 .rhs = undefined, // set by caller2854 .rhs = undefined, // set by caller
2865 };2855 };
2866 return &node.base;2856 return &node.base;
...@@ -2869,7 +2859,7 @@ fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2869,7 +2859,7 @@ fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2869fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2859fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2870 const token = eatToken(it, .Keyword_usingnamespace) orelse return null;2860 const token = eatToken(it, .Keyword_usingnamespace) orelse return null;
2871 const node = try arena.create(Node.Use);2861 const node = try arena.create(Node.Use);
2872 node.* = Node.Use{2862 node.* = .{
2873 .doc_comments = null,2863 .doc_comments = null,
2874 .visib_token = null,2864 .visib_token = null,
2875 .use_token = token,2865 .use_token = token,
...@@ -2884,17 +2874,17 @@ fn parseIf(arena: *Allocator, it: *TokenIterator, tree: *Tree, bodyParseFn: Node...@@ -2884,17 +2874,17 @@ fn parseIf(arena: *Allocator, it: *TokenIterator, tree: *Tree, bodyParseFn: Node
2884 const node = (try parseIfPrefix(arena, it, tree)) orelse return null;2874 const node = (try parseIfPrefix(arena, it, tree)) orelse return null;
2885 const if_prefix = node.cast(Node.If).?;2875 const if_prefix = node.cast(Node.If).?;
28862876
2887 if_prefix.body = try expectNode(arena, it, tree, bodyParseFn, AstError{2877 if_prefix.body = try expectNode(arena, it, tree, bodyParseFn, .{
2888 .InvalidToken = AstError.InvalidToken{ .token = it.index },2878 .InvalidToken = .{ .token = it.index },
2889 });2879 });
28902880
2891 const else_token = eatToken(it, .Keyword_else) orelse return node;2881 const else_token = eatToken(it, .Keyword_else) orelse return node;
2892 const payload = try parsePayload(arena, it, tree);2882 const payload = try parsePayload(arena, it, tree);
2893 const else_expr = try expectNode(arena, it, tree, bodyParseFn, AstError{2883 const else_expr = try expectNode(arena, it, tree, bodyParseFn, .{
2894 .InvalidToken = AstError.InvalidToken{ .token = it.index },2884 .InvalidToken = .{ .token = it.index },
2895 });2885 });
2896 const else_node = try arena.create(Node.Else);2886 const else_node = try arena.create(Node.Else);
2897 else_node.* = Node.Else{2887 else_node.* = .{
2898 .else_token = else_token,2888 .else_token = else_token,
2899 .payload = payload,2889 .payload = payload,
2900 .body = else_expr,2890 .body = else_expr,
...@@ -2914,7 +2904,7 @@ fn parseDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.D...@@ -2914,7 +2904,7 @@ fn parseDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.D
2914 if (lines.len == 0) return null;2904 if (lines.len == 0) return null;
29152905
2916 const node = try arena.create(Node.DocComment);2906 const node = try arena.create(Node.DocComment);
2917 node.* = Node.DocComment{2907 node.* = .{
2918 .lines = lines,2908 .lines = lines,
2919 };2909 };
2920 return node;2910 return node;
...@@ -2925,7 +2915,7 @@ fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, a...@@ -2925,7 +2915,7 @@ fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, a
2925 const comment_token = eatToken(it, .DocComment) orelse return null;2915 const comment_token = eatToken(it, .DocComment) orelse return null;
2926 if (tree.tokensOnSameLine(after_token, comment_token)) {2916 if (tree.tokensOnSameLine(after_token, comment_token)) {
2927 const node = try arena.create(Node.DocComment);2917 const node = try arena.create(Node.DocComment);
2928 node.* = Node.DocComment{2918 node.* = .{
2929 .lines = Node.DocComment.LineList.init(arena),2919 .lines = Node.DocComment.LineList.init(arena),
2930 };2920 };
2931 try node.lines.push(comment_token);2921 try node.lines.push(comment_token);
...@@ -2974,14 +2964,14 @@ fn parsePrefixOpExpr(...@@ -2974,14 +2964,14 @@ fn parsePrefixOpExpr(
2974 switch (rightmost_op.id) {2964 switch (rightmost_op.id) {
2975 .PrefixOp => {2965 .PrefixOp => {
2976 const prefix_op = rightmost_op.cast(Node.PrefixOp).?;2966 const prefix_op = rightmost_op.cast(Node.PrefixOp).?;
2977 prefix_op.rhs = try expectNode(arena, it, tree, childParseFn, AstError{2967 prefix_op.rhs = try expectNode(arena, it, tree, childParseFn, .{
2978 .InvalidToken = AstError.InvalidToken{ .token = it.index },2968 .InvalidToken = .{ .token = it.index },
2979 });2969 });
2980 },2970 },
2981 .AnyFrameType => {2971 .AnyFrameType => {
2982 const prom = rightmost_op.cast(Node.AnyFrameType).?;2972 const prom = rightmost_op.cast(Node.AnyFrameType).?;
2983 prom.result.?.return_type = try expectNode(arena, it, tree, childParseFn, AstError{2973 prom.result.?.return_type = try expectNode(arena, it, tree, childParseFn, .{
2984 .InvalidToken = AstError.InvalidToken{ .token = it.index },2974 .InvalidToken = .{ .token = it.index },
2985 });2975 });
2986 },2976 },
2987 else => unreachable,2977 else => unreachable,
...@@ -3010,8 +3000,8 @@ fn parseBinOpExpr(...@@ -3010,8 +3000,8 @@ fn parseBinOpExpr(
3010 var res = (try childParseFn(arena, it, tree)) orelse return null;3000 var res = (try childParseFn(arena, it, tree)) orelse return null;
30113001
3012 while (try opParseFn(arena, it, tree)) |node| {3002 while (try opParseFn(arena, it, tree)) |node| {
3013 const right = try expectNode(arena, it, tree, childParseFn, AstError{3003 const right = try expectNode(arena, it, tree, childParseFn, .{
3014 .InvalidToken = AstError.InvalidToken{ .token = it.index },3004 .InvalidToken = .{ .token = it.index },
3015 });3005 });
3016 const left = res;3006 const left = res;
3017 res = node;3007 res = node;
...@@ -3031,7 +3021,7 @@ fn parseBinOpExpr(...@@ -3031,7 +3021,7 @@ fn parseBinOpExpr(
30313021
3032fn createInfixOp(arena: *Allocator, index: TokenIndex, op: Node.InfixOp.Op) !*Node {3022fn createInfixOp(arena: *Allocator, index: TokenIndex, op: Node.InfixOp.Op) !*Node {
3033 const node = try arena.create(Node.InfixOp);3023 const node = try arena.create(Node.InfixOp);
3034 node.* = Node.InfixOp{3024 node.* = .{
3035 .op_token = index,3025 .op_token = index,
3036 .lhs = undefined, // set by caller3026 .lhs = undefined, // set by caller
3037 .op = op,3027 .op = op,
...@@ -3051,8 +3041,8 @@ fn eatAnnotatedToken(it: *TokenIterator, id: Token.Id) ?AnnotatedToken {...@@ -3051,8 +3041,8 @@ fn eatAnnotatedToken(it: *TokenIterator, id: Token.Id) ?AnnotatedToken {
3051fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex {3041fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex {
3052 const token = nextToken(it);3042 const token = nextToken(it);
3053 if (token.ptr.id != id) {3043 if (token.ptr.id != id) {
3054 try tree.errors.push(AstError{3044 try tree.errors.push(.{
3055 .ExpectedToken = AstError.ExpectedToken{ .token = token.index, .expected_id = id },3045 .ExpectedToken = .{ .token = token.index, .expected_id = id },
3056 });3046 });
3057 return error.ParseError;3047 return error.ParseError;
3058 }3048 }
lib/std/zig/parser_test.zig+84
...@@ -1,3 +1,16 @@...@@ -1,3 +1,16 @@
1test "zig fmt: errdefer with payload" {
2 try testCanonical(
3 \\pub fn main() anyerror!void {
4 \\ errdefer |a| x += 1;
5 \\ errdefer |a| {}
6 \\ errdefer |a| {
7 \\ x += 1;
8 \\ }
9 \\}
10 \\
11 );
12}
13
1test "zig fmt: noasync block" {14test "zig fmt: noasync block" {
2 try testCanonical(15 try testCanonical(
3 \\pub fn main() anyerror!void {16 \\pub fn main() anyerror!void {
...@@ -1509,6 +1522,8 @@ test "zig fmt: error set declaration" {...@@ -1509,6 +1522,8 @@ test "zig fmt: error set declaration" {
1509 \\const Error = error{OutOfMemory};1522 \\const Error = error{OutOfMemory};
1510 \\const Error = error{};1523 \\const Error = error{};
1511 \\1524 \\
1525 \\const Error = error{ OutOfMemory, OutOfTime };
1526 \\
1512 );1527 );
1513}1528}
15141529
...@@ -2800,6 +2815,75 @@ test "zig fmt: extern without container keyword returns error" {...@@ -2800,6 +2815,75 @@ test "zig fmt: extern without container keyword returns error" {
2800 );2815 );
2801}2816}
28022817
2818test "zig fmt: integer literals with underscore separators" {
2819 try testTransform(
2820 \\const
2821 \\ x =
2822 \\ 1_234_567
2823 \\ +(0b0_1-0o7_0+0xff_FF ) + 0_0;
2824 ,
2825 \\const x = 1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;
2826 \\
2827 );
2828}
2829
2830test "zig fmt: hex literals with underscore separators" {
2831 try testTransform(
2832 \\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
2833 \\ var c: [1_000]u64 = [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
2834 \\ for (c [ 0_0 .. ]) |_, i| {
2835 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
2836 \\ }
2837 \\ return c;
2838 \\}
2839 \\
2840 \\
2841 ,
2842 \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
2843 \\ var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
2844 \\ for (c[0_0..]) |_, i| {
2845 \\ c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
2846 \\ }
2847 \\ return c;
2848 \\}
2849 \\
2850 );
2851}
2852
2853test "zig fmt: decimal float literals with underscore separators" {
2854 try testTransform(
2855 \\pub fn main() void {
2856 \\ const a:f64=(10.0e-0+(10.e+0))+10_00.00_00e-2+00_00.00_10e+4;
2857 \\ const b:f64=010.0--0_10.+0_1_0.0_0+1e2;
2858 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2859 \\}
2860 ,
2861 \\pub fn main() void {
2862 \\ const a: f64 = (10.0e-0 + (10.e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
2863 \\ const b: f64 = 010.0 - -0_10. + 0_1_0.0_0 + 1e2;
2864 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2865 \\}
2866 \\
2867 );
2868}
2869
2870test "zig fmt: hexadeciaml float literals with underscore separators" {
2871 try testTransform(
2872 \\pub fn main() void {
2873 \\ const a: f64 = (0x10.0p-0+(0x10.p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
2874 \\ const b: f64 = 0x0010.0--0x00_10.+0x10.00+0x1p4;
2875 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2876 \\}
2877 ,
2878 \\pub fn main() void {
2879 \\ const a: f64 = (0x10.0p-0 + (0x10.p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
2880 \\ const b: f64 = 0x0010.0 - -0x00_10. + 0x10.00 + 0x1p4;
2881 \\ std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
2882 \\}
2883 \\
2884 );
2885}
2886
2803const std = @import("std");2887const std = @import("std");
2804const mem = std.mem;2888const mem = std.mem;
2805const warn = std.debug.warn;2889const warn = std.debug.warn;
lib/std/zig/render.zig+44-18
...@@ -376,6 +376,9 @@ fn renderExpression(...@@ -376,6 +376,9 @@ fn renderExpression(
376 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);376 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
377377
378 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);378 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
379 if (defer_node.payload) |payload| {
380 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
381 }
379 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);382 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
380 },383 },
381 .Comptime => {384 .Comptime => {
...@@ -583,7 +586,6 @@ fn renderExpression(...@@ -583,7 +586,6 @@ fn renderExpression(
583 },586 },
584587
585 .Try,588 .Try,
586 .Cancel,
587 .Resume,589 .Resume,
588 => {590 => {
589 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);591 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
...@@ -1269,25 +1271,51 @@ fn renderExpression(...@@ -1269,25 +1271,51 @@ fn renderExpression(
1269 }1271 }
12701272
1271 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error1273 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
1272 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
1273 const new_indent = indent + indent_delta;
12741274
1275 var it = err_set_decl.decls.iterator(0);1275 const src_has_trailing_comma = blk: {
1276 while (it.next()) |node| {1276 const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
1277 try stream.writeByteNTimes(' ', new_indent);1277 break :blk tree.tokens.at(maybe_comma).id == .Comma;
1278 };
12781279
1279 if (it.peek()) |next_node| {1280 if (src_has_trailing_comma) {
1280 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);1281 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
1281 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // ,1282 const new_indent = indent + indent_delta;
12821283
1283 try renderExtraNewline(tree, stream, start_col, next_node.*);1284 var it = err_set_decl.decls.iterator(0);
1284 } else {1285 while (it.next()) |node| {
1285 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);1286 try stream.writeByteNTimes(' ', new_indent);
1287
1288 if (it.peek()) |next_node| {
1289 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
1290 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // ,
1291
1292 try renderExtraNewline(tree, stream, start_col, next_node.*);
1293 } else {
1294 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
1295 }
1286 }1296 }
1287 }
12881297
1289 try stream.writeByteNTimes(' ', indent);1298 try stream.writeByteNTimes(' ', indent);
1290 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }1299 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
1300 } else {
1301 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); // {
1302
1303 var it = err_set_decl.decls.iterator(0);
1304 while (it.next()) |node| {
1305 if (it.peek()) |next_node| {
1306 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
1307
1308 const comma_token = tree.nextToken(node.*.lastToken());
1309 assert(tree.tokens.at(comma_token).id == .Comma);
1310 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
1311 try renderExtraNewline(tree, stream, start_col, next_node.*);
1312 } else {
1313 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space);
1314 }
1315 }
1316
1317 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
1318 }
1291 },1319 },
12921320
1293 .ErrorTag => {1321 .ErrorTag => {
...@@ -1590,8 +1618,7 @@ fn renderExpression(...@@ -1590,8 +1618,7 @@ fn renderExpression(
1590 }1618 }
1591 } else {1619 } else {
1592 var it = switch_case.items.iterator(0);1620 var it = switch_case.items.iterator(0);
1593 while (true) {1621 while (it.next()) |node| {
1594 const node = it.next().?;
1595 if (it.peek()) |next_node| {1622 if (it.peek()) |next_node| {
1596 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);1623 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
15971624
...@@ -1602,7 +1629,6 @@ fn renderExpression(...@@ -1602,7 +1629,6 @@ fn renderExpression(
1602 } else {1629 } else {
1603 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma);1630 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma);
1604 try stream.writeByteNTimes(' ', indent);1631 try stream.writeByteNTimes(' ', indent);
1605 break;
1606 }1632 }
1607 }1633 }
1608 }1634 }
lib/std/zig/system.zig+4-1
...@@ -468,6 +468,9 @@ pub const NativeTargetInfo = struct {...@@ -468,6 +468,9 @@ pub const NativeTargetInfo = struct {
468 error.InvalidUtf8 => unreachable,468 error.InvalidUtf8 => unreachable,
469 error.BadPathName => unreachable,469 error.BadPathName => unreachable,
470 error.PipeBusy => unreachable,470 error.PipeBusy => unreachable,
471 error.PermissionDenied => unreachable,
472 error.FileBusy => unreachable,
473 error.Locked => unreachable,
471474
472 error.IsDir,475 error.IsDir,
473 error.NotDir,476 error.NotDir,
...@@ -754,7 +757,7 @@ pub const NativeTargetInfo = struct {...@@ -754,7 +757,7 @@ pub const NativeTargetInfo = struct {
754 const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));757 const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));
755 var it = mem.tokenize(rpath_list, ":");758 var it = mem.tokenize(rpath_list, ":");
756 while (it.next()) |rpath| {759 while (it.next()) |rpath| {
757 var dir = fs.cwd().openDirList(rpath) catch |err| switch (err) {760 var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) {
758 error.NameTooLong => unreachable,761 error.NameTooLong => unreachable,
759 error.InvalidUtf8 => unreachable,762 error.InvalidUtf8 => unreachable,
760 error.BadPathName => unreachable,763 error.BadPathName => unreachable,
lib/std/zig/tokenizer.zig+438-57
...@@ -387,17 +387,23 @@ pub const Tokenizer = struct {...@@ -387,17 +387,23 @@ pub const Tokenizer = struct {
387 DocComment,387 DocComment,
388 ContainerDocComment,388 ContainerDocComment,
389 Zero,389 Zero,
390 IntegerLiteral,390 IntegerLiteralDec,
391 IntegerLiteralWithRadix,391 IntegerLiteralDecNoUnderscore,
392 IntegerLiteralWithRadixHex,392 IntegerLiteralBin,
393 NumberDot,393 IntegerLiteralBinNoUnderscore,
394 IntegerLiteralOct,
395 IntegerLiteralOctNoUnderscore,
396 IntegerLiteralHex,
397 IntegerLiteralHexNoUnderscore,
398 NumberDotDec,
394 NumberDotHex,399 NumberDotHex,
395 FloatFraction,400 FloatFractionDec,
401 FloatFractionDecNoUnderscore,
396 FloatFractionHex,402 FloatFractionHex,
403 FloatFractionHexNoUnderscore,
397 FloatExponentUnsigned,404 FloatExponentUnsigned,
398 FloatExponentUnsignedHex,
399 FloatExponentNumber,405 FloatExponentNumber,
400 FloatExponentNumberHex,406 FloatExponentNumberNoUnderscore,
401 Ampersand,407 Ampersand,
402 Caret,408 Caret,
403 Percent,409 Percent,
...@@ -412,6 +418,10 @@ pub const Tokenizer = struct {...@@ -412,6 +418,10 @@ pub const Tokenizer = struct {
412 SawAtSign,418 SawAtSign,
413 };419 };
414420
421 fn isIdentifierChar(char: u8) bool {
422 return std.ascii.isAlNum(char) or char == '_';
423 }
424
415 pub fn next(self: *Tokenizer) Token {425 pub fn next(self: *Tokenizer) Token {
416 if (self.pending_invalid_token) |token| {426 if (self.pending_invalid_token) |token| {
417 self.pending_invalid_token = null;427 self.pending_invalid_token = null;
...@@ -550,7 +560,7 @@ pub const Tokenizer = struct {...@@ -550,7 +560,7 @@ pub const Tokenizer = struct {
550 result.id = Token.Id.IntegerLiteral;560 result.id = Token.Id.IntegerLiteral;
551 },561 },
552 '1'...'9' => {562 '1'...'9' => {
553 state = State.IntegerLiteral;563 state = State.IntegerLiteralDec;
554 result.id = Token.Id.IntegerLiteral;564 result.id = Token.Id.IntegerLiteral;
555 },565 },
556 else => {566 else => {
...@@ -1048,55 +1058,145 @@ pub const Tokenizer = struct {...@@ -1048,55 +1058,145 @@ pub const Tokenizer = struct {
1048 else => self.checkLiteralCharacter(),1058 else => self.checkLiteralCharacter(),
1049 },1059 },
1050 State.Zero => switch (c) {1060 State.Zero => switch (c) {
1051 'b', 'o' => {1061 'b' => {
1052 state = State.IntegerLiteralWithRadix;1062 state = State.IntegerLiteralBinNoUnderscore;
1063 },
1064 'o' => {
1065 state = State.IntegerLiteralOctNoUnderscore;
1053 },1066 },
1054 'x' => {1067 'x' => {
1055 state = State.IntegerLiteralWithRadixHex;1068 state = State.IntegerLiteralHexNoUnderscore;
1056 },1069 },
1057 else => {1070 '0'...'9', '_', '.', 'e', 'E' => {
1058 // reinterpret as a normal number1071 // reinterpret as a decimal number
1059 self.index -= 1;1072 self.index -= 1;
1060 state = State.IntegerLiteral;1073 state = State.IntegerLiteralDec;
1074 },
1075 else => {
1076 if (isIdentifierChar(c)) {
1077 result.id = Token.Id.Invalid;
1078 }
1079 break;
1080 },
1081 },
1082 State.IntegerLiteralBinNoUnderscore => switch (c) {
1083 '0'...'1' => {
1084 state = State.IntegerLiteralBin;
1085 },
1086 else => {
1087 result.id = Token.Id.Invalid;
1088 break;
1089 },
1090 },
1091 State.IntegerLiteralBin => switch (c) {
1092 '_' => {
1093 state = State.IntegerLiteralBinNoUnderscore;
1094 },
1095 '0'...'1' => {},
1096 else => {
1097 if (isIdentifierChar(c)) {
1098 result.id = Token.Id.Invalid;
1099 }
1100 break;
1101 },
1102 },
1103 State.IntegerLiteralOctNoUnderscore => switch (c) {
1104 '0'...'7' => {
1105 state = State.IntegerLiteralOct;
1106 },
1107 else => {
1108 result.id = Token.Id.Invalid;
1109 break;
1110 },
1111 },
1112 State.IntegerLiteralOct => switch (c) {
1113 '_' => {
1114 state = State.IntegerLiteralOctNoUnderscore;
1115 },
1116 '0'...'7' => {},
1117 else => {
1118 if (isIdentifierChar(c)) {
1119 result.id = Token.Id.Invalid;
1120 }
1121 break;
1122 },
1123 },
1124 State.IntegerLiteralDecNoUnderscore => switch (c) {
1125 '0'...'9' => {
1126 state = State.IntegerLiteralDec;
1127 },
1128 else => {
1129 result.id = Token.Id.Invalid;
1130 break;
1061 },1131 },
1062 },1132 },
1063 State.IntegerLiteral => switch (c) {1133 State.IntegerLiteralDec => switch (c) {
1134 '_' => {
1135 state = State.IntegerLiteralDecNoUnderscore;
1136 },
1064 '.' => {1137 '.' => {
1065 state = State.NumberDot;1138 state = State.NumberDotDec;
1139 result.id = Token.Id.FloatLiteral;
1066 },1140 },
1067 'p', 'P', 'e', 'E' => {1141 'e', 'E' => {
1068 state = State.FloatExponentUnsigned;1142 state = State.FloatExponentUnsigned;
1143 result.id = Token.Id.FloatLiteral;
1069 },1144 },
1070 '0'...'9' => {},1145 '0'...'9' => {},
1071 else => break,1146 else => {
1147 if (isIdentifierChar(c)) {
1148 result.id = Token.Id.Invalid;
1149 }
1150 break;
1151 },
1072 },1152 },
1073 State.IntegerLiteralWithRadix => switch (c) {1153 State.IntegerLiteralHexNoUnderscore => switch (c) {
1074 '.' => {1154 '0'...'9', 'a'...'f', 'A'...'F' => {
1075 state = State.NumberDot;1155 state = State.IntegerLiteralHex;
1156 },
1157 else => {
1158 result.id = Token.Id.Invalid;
1159 break;
1076 },1160 },
1077 '0'...'9' => {},
1078 else => break,
1079 },1161 },
1080 State.IntegerLiteralWithRadixHex => switch (c) {1162 State.IntegerLiteralHex => switch (c) {
1163 '_' => {
1164 state = State.IntegerLiteralHexNoUnderscore;
1165 },
1081 '.' => {1166 '.' => {
1082 state = State.NumberDotHex;1167 state = State.NumberDotHex;
1168 result.id = Token.Id.FloatLiteral;
1083 },1169 },
1084 'p', 'P' => {1170 'p', 'P' => {
1085 state = State.FloatExponentUnsignedHex;1171 state = State.FloatExponentUnsigned;
1172 result.id = Token.Id.FloatLiteral;
1086 },1173 },
1087 '0'...'9', 'a'...'f', 'A'...'F' => {},1174 '0'...'9', 'a'...'f', 'A'...'F' => {},
1088 else => break,1175 else => {
1176 if (isIdentifierChar(c)) {
1177 result.id = Token.Id.Invalid;
1178 }
1179 break;
1180 },
1089 },1181 },
1090 State.NumberDot => switch (c) {1182 State.NumberDotDec => switch (c) {
1091 '.' => {1183 '.' => {
1092 self.index -= 1;1184 self.index -= 1;
1093 state = State.Start;1185 state = State.Start;
1094 break;1186 break;
1095 },1187 },
1096 else => {1188 'e', 'E' => {
1097 self.index -= 1;1189 state = State.FloatExponentUnsigned;
1190 },
1191 '0'...'9' => {
1098 result.id = Token.Id.FloatLiteral;1192 result.id = Token.Id.FloatLiteral;
1099 state = State.FloatFraction;1193 state = State.FloatFractionDec;
1194 },
1195 else => {
1196 if (isIdentifierChar(c)) {
1197 result.id = Token.Id.Invalid;
1198 }
1199 break;
1100 },1200 },
1101 },1201 },
1102 State.NumberDotHex => switch (c) {1202 State.NumberDotHex => switch (c) {
...@@ -1105,65 +1205,112 @@ pub const Tokenizer = struct {...@@ -1105,65 +1205,112 @@ pub const Tokenizer = struct {
1105 state = State.Start;1205 state = State.Start;
1106 break;1206 break;
1107 },1207 },
1108 else => {1208 'p', 'P' => {
1109 self.index -= 1;1209 state = State.FloatExponentUnsigned;
1210 },
1211 '0'...'9', 'a'...'f', 'A'...'F' => {
1110 result.id = Token.Id.FloatLiteral;1212 result.id = Token.Id.FloatLiteral;
1111 state = State.FloatFractionHex;1213 state = State.FloatFractionHex;
1112 },1214 },
1215 else => {
1216 if (isIdentifierChar(c)) {
1217 result.id = Token.Id.Invalid;
1218 }
1219 break;
1220 },
1113 },1221 },
1114 State.FloatFraction => switch (c) {1222 State.FloatFractionDecNoUnderscore => switch (c) {
1223 '0'...'9' => {
1224 state = State.FloatFractionDec;
1225 },
1226 else => {
1227 result.id = Token.Id.Invalid;
1228 break;
1229 },
1230 },
1231 State.FloatFractionDec => switch (c) {
1232 '_' => {
1233 state = State.FloatFractionDecNoUnderscore;
1234 },
1115 'e', 'E' => {1235 'e', 'E' => {
1116 state = State.FloatExponentUnsigned;1236 state = State.FloatExponentUnsigned;
1117 },1237 },
1118 '0'...'9' => {},1238 '0'...'9' => {},
1119 else => break,1239 else => {
1240 if (isIdentifierChar(c)) {
1241 result.id = Token.Id.Invalid;
1242 }
1243 break;
1244 },
1245 },
1246 State.FloatFractionHexNoUnderscore => switch (c) {
1247 '0'...'9', 'a'...'f', 'A'...'F' => {
1248 state = State.FloatFractionHex;
1249 },
1250 else => {
1251 result.id = Token.Id.Invalid;
1252 break;
1253 },
1120 },1254 },
1121 State.FloatFractionHex => switch (c) {1255 State.FloatFractionHex => switch (c) {
1256 '_' => {
1257 state = State.FloatFractionHexNoUnderscore;
1258 },
1122 'p', 'P' => {1259 'p', 'P' => {
1123 state = State.FloatExponentUnsignedHex;1260 state = State.FloatExponentUnsigned;
1124 },1261 },
1125 '0'...'9', 'a'...'f', 'A'...'F' => {},1262 '0'...'9', 'a'...'f', 'A'...'F' => {},
1126 else => break,1263 else => {
1264 if (isIdentifierChar(c)) {
1265 result.id = Token.Id.Invalid;
1266 }
1267 break;
1268 },
1127 },1269 },
1128 State.FloatExponentUnsigned => switch (c) {1270 State.FloatExponentUnsigned => switch (c) {
1129 '+', '-' => {1271 '+', '-' => {
1130 state = State.FloatExponentNumber;1272 state = State.FloatExponentNumberNoUnderscore;
1131 },1273 },
1132 else => {1274 else => {
1133 // reinterpret as a normal exponent number1275 // reinterpret as a normal exponent number
1134 self.index -= 1;1276 self.index -= 1;
1135 state = State.FloatExponentNumber;1277 state = State.FloatExponentNumberNoUnderscore;
1136 },1278 },
1137 },1279 },
1138 State.FloatExponentUnsignedHex => switch (c) {1280 State.FloatExponentNumberNoUnderscore => switch (c) {
1139 '+', '-' => {1281 '0'...'9' => {
1140 state = State.FloatExponentNumberHex;1282 state = State.FloatExponentNumber;
1141 },1283 },
1142 else => {1284 else => {
1143 // reinterpret as a normal exponent number1285 result.id = Token.Id.Invalid;
1144 self.index -= 1;1286 break;
1145 state = State.FloatExponentNumberHex;
1146 },1287 },
1147 },1288 },
1148 State.FloatExponentNumber => switch (c) {1289 State.FloatExponentNumber => switch (c) {
1290 '_' => {
1291 state = State.FloatExponentNumberNoUnderscore;
1292 },
1149 '0'...'9' => {},1293 '0'...'9' => {},
1150 else => break,1294 else => {
1151 },1295 if (isIdentifierChar(c)) {
1152 State.FloatExponentNumberHex => switch (c) {1296 result.id = Token.Id.Invalid;
1153 '0'...'9', 'a'...'f', 'A'...'F' => {},1297 }
1154 else => break,1298 break;
1299 },
1155 },1300 },
1156 }1301 }
1157 } else if (self.index == self.buffer.len) {1302 } else if (self.index == self.buffer.len) {
1158 switch (state) {1303 switch (state) {
1159 State.Start,1304 State.Start,
1160 State.IntegerLiteral,1305 State.IntegerLiteralDec,
1161 State.IntegerLiteralWithRadix,1306 State.IntegerLiteralBin,
1162 State.IntegerLiteralWithRadixHex,1307 State.IntegerLiteralOct,
1163 State.FloatFraction,1308 State.IntegerLiteralHex,
1309 State.NumberDotDec,
1310 State.NumberDotHex,
1311 State.FloatFractionDec,
1164 State.FloatFractionHex,1312 State.FloatFractionHex,
1165 State.FloatExponentNumber,1313 State.FloatExponentNumber,
1166 State.FloatExponentNumberHex,
1167 State.StringLiteral, // find this error later1314 State.StringLiteral, // find this error later
1168 State.MultilineStringLiteralLine,1315 State.MultilineStringLiteralLine,
1169 State.Builtin,1316 State.Builtin,
...@@ -1184,10 +1331,14 @@ pub const Tokenizer = struct {...@@ -1184,10 +1331,14 @@ pub const Tokenizer = struct {
1184 result.id = Token.Id.ContainerDocComment;1331 result.id = Token.Id.ContainerDocComment;
1185 },1332 },
11861333
1187 State.NumberDot,1334 State.IntegerLiteralDecNoUnderscore,
1188 State.NumberDotHex,1335 State.IntegerLiteralBinNoUnderscore,
1336 State.IntegerLiteralOctNoUnderscore,
1337 State.IntegerLiteralHexNoUnderscore,
1338 State.FloatFractionDecNoUnderscore,
1339 State.FloatFractionHexNoUnderscore,
1340 State.FloatExponentNumberNoUnderscore,
1189 State.FloatExponentUnsigned,1341 State.FloatExponentUnsigned,
1190 State.FloatExponentUnsignedHex,
1191 State.SawAtSign,1342 State.SawAtSign,
1192 State.Backslash,1343 State.Backslash,
1193 State.CharLiteral,1344 State.CharLiteral,
...@@ -1585,6 +1736,236 @@ test "correctly parse pointer assignment" {...@@ -1585,6 +1736,236 @@ test "correctly parse pointer assignment" {
1585 });1736 });
1586}1737}
15871738
1739test "tokenizer - number literals decimal" {
1740 testTokenize("0", &[_]Token.Id{.IntegerLiteral});
1741 testTokenize("1", &[_]Token.Id{.IntegerLiteral});
1742 testTokenize("2", &[_]Token.Id{.IntegerLiteral});
1743 testTokenize("3", &[_]Token.Id{.IntegerLiteral});
1744 testTokenize("4", &[_]Token.Id{.IntegerLiteral});
1745 testTokenize("5", &[_]Token.Id{.IntegerLiteral});
1746 testTokenize("6", &[_]Token.Id{.IntegerLiteral});
1747 testTokenize("7", &[_]Token.Id{.IntegerLiteral});
1748 testTokenize("8", &[_]Token.Id{.IntegerLiteral});
1749 testTokenize("9", &[_]Token.Id{.IntegerLiteral});
1750 testTokenize("0a", &[_]Token.Id{ .Invalid, .Identifier });
1751 testTokenize("9b", &[_]Token.Id{ .Invalid, .Identifier });
1752 testTokenize("1z", &[_]Token.Id{ .Invalid, .Identifier });
1753 testTokenize("1z_1", &[_]Token.Id{ .Invalid, .Identifier });
1754 testTokenize("9z3", &[_]Token.Id{ .Invalid, .Identifier });
1755
1756 testTokenize("0_0", &[_]Token.Id{.IntegerLiteral});
1757 testTokenize("0001", &[_]Token.Id{.IntegerLiteral});
1758 testTokenize("01234567890", &[_]Token.Id{.IntegerLiteral});
1759 testTokenize("012_345_6789_0", &[_]Token.Id{.IntegerLiteral});
1760 testTokenize("0_1_2_3_4_5_6_7_8_9_0", &[_]Token.Id{.IntegerLiteral});
1761
1762 testTokenize("00_", &[_]Token.Id{.Invalid});
1763 testTokenize("0_0_", &[_]Token.Id{.Invalid});
1764 testTokenize("0__0", &[_]Token.Id{ .Invalid, .Identifier });
1765 testTokenize("0_0f", &[_]Token.Id{ .Invalid, .Identifier });
1766 testTokenize("0_0_f", &[_]Token.Id{ .Invalid, .Identifier });
1767 testTokenize("0_0_f_00", &[_]Token.Id{ .Invalid, .Identifier });
1768 testTokenize("1_,", &[_]Token.Id{ .Invalid, .Comma });
1769
1770 testTokenize("1.", &[_]Token.Id{.FloatLiteral});
1771 testTokenize("0.0", &[_]Token.Id{.FloatLiteral});
1772 testTokenize("1.0", &[_]Token.Id{.FloatLiteral});
1773 testTokenize("10.0", &[_]Token.Id{.FloatLiteral});
1774 testTokenize("0e0", &[_]Token.Id{.FloatLiteral});
1775 testTokenize("1e0", &[_]Token.Id{.FloatLiteral});
1776 testTokenize("1e100", &[_]Token.Id{.FloatLiteral});
1777 testTokenize("1.e100", &[_]Token.Id{.FloatLiteral});
1778 testTokenize("1.0e100", &[_]Token.Id{.FloatLiteral});
1779 testTokenize("1.0e+100", &[_]Token.Id{.FloatLiteral});
1780 testTokenize("1.0e-100", &[_]Token.Id{.FloatLiteral});
1781 testTokenize("1_0_0_0.0_0_0_0_0_1e1_0_0_0", &[_]Token.Id{.FloatLiteral});
1782 testTokenize("1.+", &[_]Token.Id{ .FloatLiteral, .Plus });
1783
1784 testTokenize("1e", &[_]Token.Id{.Invalid});
1785 testTokenize("1.0e1f0", &[_]Token.Id{ .Invalid, .Identifier });
1786 testTokenize("1.0p100", &[_]Token.Id{ .Invalid, .Identifier });
1787 testTokenize("1.0p-100", &[_]Token.Id{ .Invalid, .Identifier, .Minus, .IntegerLiteral });
1788 testTokenize("1.0p1f0", &[_]Token.Id{ .Invalid, .Identifier });
1789 testTokenize("1.0_,", &[_]Token.Id{ .Invalid, .Comma });
1790 testTokenize("1_.0", &[_]Token.Id{ .Invalid, .Period, .IntegerLiteral });
1791 testTokenize("1._", &[_]Token.Id{ .Invalid, .Identifier });
1792 testTokenize("1.a", &[_]Token.Id{ .Invalid, .Identifier });
1793 testTokenize("1.z", &[_]Token.Id{ .Invalid, .Identifier });
1794 testTokenize("1._0", &[_]Token.Id{ .Invalid, .Identifier });
1795 testTokenize("1._+", &[_]Token.Id{ .Invalid, .Identifier, .Plus });
1796 testTokenize("1._e", &[_]Token.Id{ .Invalid, .Identifier });
1797 testTokenize("1.0e", &[_]Token.Id{.Invalid});
1798 testTokenize("1.0e,", &[_]Token.Id{ .Invalid, .Comma });
1799 testTokenize("1.0e_", &[_]Token.Id{ .Invalid, .Identifier });
1800 testTokenize("1.0e+_", &[_]Token.Id{ .Invalid, .Identifier });
1801 testTokenize("1.0e-_", &[_]Token.Id{ .Invalid, .Identifier });
1802 testTokenize("1.0e0_+", &[_]Token.Id{ .Invalid, .Plus });
1803}
1804
1805test "tokenizer - number literals binary" {
1806 testTokenize("0b0", &[_]Token.Id{.IntegerLiteral});
1807 testTokenize("0b1", &[_]Token.Id{.IntegerLiteral});
1808 testTokenize("0b2", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1809 testTokenize("0b3", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1810 testTokenize("0b4", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1811 testTokenize("0b5", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1812 testTokenize("0b6", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1813 testTokenize("0b7", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1814 testTokenize("0b8", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1815 testTokenize("0b9", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1816 testTokenize("0ba", &[_]Token.Id{ .Invalid, .Identifier });
1817 testTokenize("0bb", &[_]Token.Id{ .Invalid, .Identifier });
1818 testTokenize("0bc", &[_]Token.Id{ .Invalid, .Identifier });
1819 testTokenize("0bd", &[_]Token.Id{ .Invalid, .Identifier });
1820 testTokenize("0be", &[_]Token.Id{ .Invalid, .Identifier });
1821 testTokenize("0bf", &[_]Token.Id{ .Invalid, .Identifier });
1822 testTokenize("0bz", &[_]Token.Id{ .Invalid, .Identifier });
1823
1824 testTokenize("0b0000_0000", &[_]Token.Id{.IntegerLiteral});
1825 testTokenize("0b1111_1111", &[_]Token.Id{.IntegerLiteral});
1826 testTokenize("0b10_10_10_10", &[_]Token.Id{.IntegerLiteral});
1827 testTokenize("0b0_1_0_1_0_1_0_1", &[_]Token.Id{.IntegerLiteral});
1828 testTokenize("0b1.", &[_]Token.Id{ .IntegerLiteral, .Period });
1829 testTokenize("0b1.0", &[_]Token.Id{ .IntegerLiteral, .Period, .IntegerLiteral });
1830
1831 testTokenize("0B0", &[_]Token.Id{ .Invalid, .Identifier });
1832 testTokenize("0b_", &[_]Token.Id{ .Invalid, .Identifier });
1833 testTokenize("0b_0", &[_]Token.Id{ .Invalid, .Identifier });
1834 testTokenize("0b1_", &[_]Token.Id{.Invalid});
1835 testTokenize("0b0__1", &[_]Token.Id{ .Invalid, .Identifier });
1836 testTokenize("0b0_1_", &[_]Token.Id{.Invalid});
1837 testTokenize("0b1e", &[_]Token.Id{ .Invalid, .Identifier });
1838 testTokenize("0b1p", &[_]Token.Id{ .Invalid, .Identifier });
1839 testTokenize("0b1e0", &[_]Token.Id{ .Invalid, .Identifier });
1840 testTokenize("0b1p0", &[_]Token.Id{ .Invalid, .Identifier });
1841 testTokenize("0b1_,", &[_]Token.Id{ .Invalid, .Comma });
1842}
1843
1844test "tokenizer - number literals octal" {
1845 testTokenize("0o0", &[_]Token.Id{.IntegerLiteral});
1846 testTokenize("0o1", &[_]Token.Id{.IntegerLiteral});
1847 testTokenize("0o2", &[_]Token.Id{.IntegerLiteral});
1848 testTokenize("0o3", &[_]Token.Id{.IntegerLiteral});
1849 testTokenize("0o4", &[_]Token.Id{.IntegerLiteral});
1850 testTokenize("0o5", &[_]Token.Id{.IntegerLiteral});
1851 testTokenize("0o6", &[_]Token.Id{.IntegerLiteral});
1852 testTokenize("0o7", &[_]Token.Id{.IntegerLiteral});
1853 testTokenize("0o8", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1854 testTokenize("0o9", &[_]Token.Id{ .Invalid, .IntegerLiteral });
1855 testTokenize("0oa", &[_]Token.Id{ .Invalid, .Identifier });
1856 testTokenize("0ob", &[_]Token.Id{ .Invalid, .Identifier });
1857 testTokenize("0oc", &[_]Token.Id{ .Invalid, .Identifier });
1858 testTokenize("0od", &[_]Token.Id{ .Invalid, .Identifier });
1859 testTokenize("0oe", &[_]Token.Id{ .Invalid, .Identifier });
1860 testTokenize("0of", &[_]Token.Id{ .Invalid, .Identifier });
1861 testTokenize("0oz", &[_]Token.Id{ .Invalid, .Identifier });
1862
1863 testTokenize("0o01234567", &[_]Token.Id{.IntegerLiteral});
1864 testTokenize("0o0123_4567", &[_]Token.Id{.IntegerLiteral});
1865 testTokenize("0o01_23_45_67", &[_]Token.Id{.IntegerLiteral});
1866 testTokenize("0o0_1_2_3_4_5_6_7", &[_]Token.Id{.IntegerLiteral});
1867 testTokenize("0o7.", &[_]Token.Id{ .IntegerLiteral, .Period });
1868 testTokenize("0o7.0", &[_]Token.Id{ .IntegerLiteral, .Period, .IntegerLiteral });
1869
1870 testTokenize("0O0", &[_]Token.Id{ .Invalid, .Identifier });
1871 testTokenize("0o_", &[_]Token.Id{ .Invalid, .Identifier });
1872 testTokenize("0o_0", &[_]Token.Id{ .Invalid, .Identifier });
1873 testTokenize("0o1_", &[_]Token.Id{.Invalid});
1874 testTokenize("0o0__1", &[_]Token.Id{ .Invalid, .Identifier });
1875 testTokenize("0o0_1_", &[_]Token.Id{.Invalid});
1876 testTokenize("0o1e", &[_]Token.Id{ .Invalid, .Identifier });
1877 testTokenize("0o1p", &[_]Token.Id{ .Invalid, .Identifier });
1878 testTokenize("0o1e0", &[_]Token.Id{ .Invalid, .Identifier });
1879 testTokenize("0o1p0", &[_]Token.Id{ .Invalid, .Identifier });
1880 testTokenize("0o_,", &[_]Token.Id{ .Invalid, .Identifier, .Comma });
1881}
1882
1883test "tokenizer - number literals hexadeciaml" {
1884 testTokenize("0x0", &[_]Token.Id{.IntegerLiteral});
1885 testTokenize("0x1", &[_]Token.Id{.IntegerLiteral});
1886 testTokenize("0x2", &[_]Token.Id{.IntegerLiteral});
1887 testTokenize("0x3", &[_]Token.Id{.IntegerLiteral});
1888 testTokenize("0x4", &[_]Token.Id{.IntegerLiteral});
1889 testTokenize("0x5", &[_]Token.Id{.IntegerLiteral});
1890 testTokenize("0x6", &[_]Token.Id{.IntegerLiteral});
1891 testTokenize("0x7", &[_]Token.Id{.IntegerLiteral});
1892 testTokenize("0x8", &[_]Token.Id{.IntegerLiteral});
1893 testTokenize("0x9", &[_]Token.Id{.IntegerLiteral});
1894 testTokenize("0xa", &[_]Token.Id{.IntegerLiteral});
1895 testTokenize("0xb", &[_]Token.Id{.IntegerLiteral});
1896 testTokenize("0xc", &[_]Token.Id{.IntegerLiteral});
1897 testTokenize("0xd", &[_]Token.Id{.IntegerLiteral});
1898 testTokenize("0xe", &[_]Token.Id{.IntegerLiteral});
1899 testTokenize("0xf", &[_]Token.Id{.IntegerLiteral});
1900 testTokenize("0xA", &[_]Token.Id{.IntegerLiteral});
1901 testTokenize("0xB", &[_]Token.Id{.IntegerLiteral});
1902 testTokenize("0xC", &[_]Token.Id{.IntegerLiteral});
1903 testTokenize("0xD", &[_]Token.Id{.IntegerLiteral});
1904 testTokenize("0xE", &[_]Token.Id{.IntegerLiteral});
1905 testTokenize("0xF", &[_]Token.Id{.IntegerLiteral});
1906 testTokenize("0x0z", &[_]Token.Id{ .Invalid, .Identifier });
1907 testTokenize("0xz", &[_]Token.Id{ .Invalid, .Identifier });
1908
1909 testTokenize("0x0123456789ABCDEF", &[_]Token.Id{.IntegerLiteral});
1910 testTokenize("0x0123_4567_89AB_CDEF", &[_]Token.Id{.IntegerLiteral});
1911 testTokenize("0x01_23_45_67_89AB_CDE_F", &[_]Token.Id{.IntegerLiteral});
1912 testTokenize("0x0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F", &[_]Token.Id{.IntegerLiteral});
1913
1914 testTokenize("0X0", &[_]Token.Id{ .Invalid, .Identifier });
1915 testTokenize("0x_", &[_]Token.Id{ .Invalid, .Identifier });
1916 testTokenize("0x_1", &[_]Token.Id{ .Invalid, .Identifier });
1917 testTokenize("0x1_", &[_]Token.Id{.Invalid});
1918 testTokenize("0x0__1", &[_]Token.Id{ .Invalid, .Identifier });
1919 testTokenize("0x0_1_", &[_]Token.Id{.Invalid});
1920 testTokenize("0x_,", &[_]Token.Id{ .Invalid, .Identifier, .Comma });
1921
1922 testTokenize("0x1.", &[_]Token.Id{.FloatLiteral});
1923 testTokenize("0x1.0", &[_]Token.Id{.FloatLiteral});
1924 testTokenize("0xF.", &[_]Token.Id{.FloatLiteral});
1925 testTokenize("0xF.0", &[_]Token.Id{.FloatLiteral});
1926 testTokenize("0xF.F", &[_]Token.Id{.FloatLiteral});
1927 testTokenize("0xF.Fp0", &[_]Token.Id{.FloatLiteral});
1928 testTokenize("0xF.FP0", &[_]Token.Id{.FloatLiteral});
1929 testTokenize("0x1p0", &[_]Token.Id{.FloatLiteral});
1930 testTokenize("0xfp0", &[_]Token.Id{.FloatLiteral});
1931 testTokenize("0x1.+0xF.", &[_]Token.Id{ .FloatLiteral, .Plus, .FloatLiteral });
1932
1933 testTokenize("0x0123456.789ABCDEF", &[_]Token.Id{.FloatLiteral});
1934 testTokenize("0x0_123_456.789_ABC_DEF", &[_]Token.Id{.FloatLiteral});
1935 testTokenize("0x0_1_2_3_4_5_6.7_8_9_A_B_C_D_E_F", &[_]Token.Id{.FloatLiteral});
1936 testTokenize("0x0p0", &[_]Token.Id{.FloatLiteral});
1937 testTokenize("0x0.0p0", &[_]Token.Id{.FloatLiteral});
1938 testTokenize("0xff.ffp10", &[_]Token.Id{.FloatLiteral});
1939 testTokenize("0xff.ffP10", &[_]Token.Id{.FloatLiteral});
1940 testTokenize("0xff.p10", &[_]Token.Id{.FloatLiteral});
1941 testTokenize("0xffp10", &[_]Token.Id{.FloatLiteral});
1942 testTokenize("0xff_ff.ff_ffp1_0_0_0", &[_]Token.Id{.FloatLiteral});
1943 testTokenize("0xf_f_f_f.f_f_f_fp+1_000", &[_]Token.Id{.FloatLiteral});
1944 testTokenize("0xf_f_f_f.f_f_f_fp-1_00_0", &[_]Token.Id{.FloatLiteral});
1945
1946 testTokenize("0x1e", &[_]Token.Id{.IntegerLiteral});
1947 testTokenize("0x1e0", &[_]Token.Id{.IntegerLiteral});
1948 testTokenize("0x1p", &[_]Token.Id{.Invalid});
1949 testTokenize("0xfp0z1", &[_]Token.Id{ .Invalid, .Identifier });
1950 testTokenize("0xff.ffpff", &[_]Token.Id{ .Invalid, .Identifier });
1951 testTokenize("0x0.p", &[_]Token.Id{.Invalid});
1952 testTokenize("0x0.z", &[_]Token.Id{ .Invalid, .Identifier });
1953 testTokenize("0x0._", &[_]Token.Id{ .Invalid, .Identifier });
1954 testTokenize("0x0_.0", &[_]Token.Id{ .Invalid, .Period, .IntegerLiteral });
1955 testTokenize("0x0_.0.0", &[_]Token.Id{ .Invalid, .Period, .FloatLiteral });
1956 testTokenize("0x0._0", &[_]Token.Id{ .Invalid, .Identifier });
1957 testTokenize("0x0.0_", &[_]Token.Id{.Invalid});
1958 testTokenize("0x0_p0", &[_]Token.Id{ .Invalid, .Identifier });
1959 testTokenize("0x0_.p0", &[_]Token.Id{ .Invalid, .Period, .Identifier });
1960 testTokenize("0x0._p0", &[_]Token.Id{ .Invalid, .Identifier });
1961 testTokenize("0x0.0_p0", &[_]Token.Id{ .Invalid, .Identifier });
1962 testTokenize("0x0._0p0", &[_]Token.Id{ .Invalid, .Identifier });
1963 testTokenize("0x0.0p_0", &[_]Token.Id{ .Invalid, .Identifier });
1964 testTokenize("0x0.0p+_0", &[_]Token.Id{ .Invalid, .Identifier });
1965 testTokenize("0x0.0p-_0", &[_]Token.Id{ .Invalid, .Identifier });
1966 testTokenize("0x0.0p0_", &[_]Token.Id{ .Invalid, .Eof });
1967}
1968
1588fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {1969fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
1589 var tokenizer = Tokenizer.init(source);1970 var tokenizer = Tokenizer.init(source);
1590 for (expected_tokens) |expected_token_id| {1971 for (expected_tokens) |expected_token_id| {
src-self-hosted/c_int.zig+4-4
...@@ -69,9 +69,9 @@ pub const CInt = struct {...@@ -69,9 +69,9 @@ pub const CInt = struct {
69 };69 };
7070
71 pub fn sizeInBits(cint: CInt, self: Target) u32 {71 pub fn sizeInBits(cint: CInt, self: Target) u32 {
72 const arch = self.getArch();72 const arch = self.cpu.arch;
73 switch (self.os.tag) {73 switch (self.os.tag) {
74 .freestanding, .other => switch (self.getArch()) {74 .freestanding, .other => switch (self.cpu.arch) {
75 .msp430 => switch (cint.id) {75 .msp430 => switch (cint.id) {
76 .Short,76 .Short,
77 .UShort,77 .UShort,
...@@ -94,7 +94,7 @@ pub const CInt = struct {...@@ -94,7 +94,7 @@ pub const CInt = struct {
94 => return 32,94 => return 32,
95 .Long,95 .Long,
96 .ULong,96 .ULong,
97 => return self.getArchPtrBitWidth(),97 => return self.cpu.arch.ptrBitWidth(),
98 .LongLong,98 .LongLong,
99 .ULongLong,99 .ULongLong,
100 => return 64,100 => return 64,
...@@ -114,7 +114,7 @@ pub const CInt = struct {...@@ -114,7 +114,7 @@ pub const CInt = struct {
114 => return 32,114 => return 32,
115 .Long,115 .Long,
116 .ULong,116 .ULong,
117 => return self.getArchPtrBitWidth(),117 => return self.cpu.arch.ptrBitWidth(),
118 .LongLong,118 .LongLong,
119 .ULongLong,119 .ULongLong,
120 => return 64,120 => return 64,
src-self-hosted/clang_options.zig created+126
...@@ -0,0 +1,126 @@
1const std = @import("std");
2const mem = std.mem;
3
4pub const list = @import("clang_options_data.zig").data;
5
6pub const CliArg = struct {
7 name: []const u8,
8 syntax: Syntax,
9
10 /// TODO we're going to want to change this when we start shipping self-hosted because this causes
11 /// all the functions in stage2.zig to get exported.
12 zig_equivalent: @import("stage2.zig").ClangArgIterator.ZigEquivalent,
13
14 /// Prefixed by "-"
15 pd1: bool = false,
16
17 /// Prefixed by "--"
18 pd2: bool = false,
19
20 /// Prefixed by "/"
21 psl: bool = false,
22
23 pub const Syntax = union(enum) {
24 /// A flag with no values.
25 flag,
26
27 /// An option which prefixes its (single) value.
28 joined,
29
30 /// An option which is followed by its value.
31 separate,
32
33 /// An option which is either joined to its (non-empty) value, or followed by its value.
34 joined_or_separate,
35
36 /// An option which is both joined to its (first) value, and followed by its (second) value.
37 joined_and_separate,
38
39 /// An option followed by its values, which are separated by commas.
40 comma_joined,
41
42 /// An option which consumes an optional joined argument and any other remaining arguments.
43 remaining_args_joined,
44
45 /// An option which is which takes multiple (separate) arguments.
46 multi_arg: u8,
47 };
48
49 pub fn matchEql(self: CliArg, arg: []const u8) u2 {
50 if (self.pd1 and arg.len >= self.name.len + 1 and
51 mem.startsWith(u8, arg, "-") and mem.eql(u8, arg[1..], self.name))
52 {
53 return 1;
54 }
55 if (self.pd2 and arg.len >= self.name.len + 2 and
56 mem.startsWith(u8, arg, "--") and mem.eql(u8, arg[2..], self.name))
57 {
58 return 2;
59 }
60 if (self.psl and arg.len >= self.name.len + 1 and
61 mem.startsWith(u8, arg, "/") and mem.eql(u8, arg[1..], self.name))
62 {
63 return 1;
64 }
65 return 0;
66 }
67
68 pub fn matchStartsWith(self: CliArg, arg: []const u8) usize {
69 if (self.pd1 and arg.len >= self.name.len + 1 and
70 mem.startsWith(u8, arg, "-") and mem.startsWith(u8, arg[1..], self.name))
71 {
72 return self.name.len + 1;
73 }
74 if (self.pd2 and arg.len >= self.name.len + 2 and
75 mem.startsWith(u8, arg, "--") and mem.startsWith(u8, arg[2..], self.name))
76 {
77 return self.name.len + 2;
78 }
79 if (self.psl and arg.len >= self.name.len + 1 and
80 mem.startsWith(u8, arg, "/") and mem.startsWith(u8, arg[1..], self.name))
81 {
82 return self.name.len + 1;
83 }
84 return 0;
85 }
86};
87
88/// Shortcut function for initializing a `CliArg`
89pub fn flagpd1(name: []const u8) CliArg {
90 return .{
91 .name = name,
92 .syntax = .flag,
93 .zig_equivalent = .other,
94 .pd1 = true,
95 };
96}
97
98/// Shortcut function for initializing a `CliArg`
99pub fn joinpd1(name: []const u8) CliArg {
100 return .{
101 .name = name,
102 .syntax = .joined,
103 .zig_equivalent = .other,
104 .pd1 = true,
105 };
106}
107
108/// Shortcut function for initializing a `CliArg`
109pub fn jspd1(name: []const u8) CliArg {
110 return .{
111 .name = name,
112 .syntax = .joined_or_separate,
113 .zig_equivalent = .other,
114 .pd1 = true,
115 };
116}
117
118/// Shortcut function for initializing a `CliArg`
119pub fn sepd1(name: []const u8) CliArg {
120 return .{
121 .name = name,
122 .syntax = .separate,
123 .zig_equivalent = .other,
124 .pd1 = true,
125 };
126}
src-self-hosted/clang_options_data.zig created+5702
...@@ -0,0 +1,5702 @@
1// This file is generated by tools/update_clang_options.zig.
2// zig fmt: off
3usingnamespace @import("clang_options.zig");
4pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
5flagpd1("C"),
6flagpd1("CC"),
7.{
8 .name = "E",
9 .syntax = .flag,
10 .zig_equivalent = .preprocess,
11 .pd1 = true,
12 .pd2 = false,
13 .psl = false,
14},
15flagpd1("EB"),
16flagpd1("EL"),
17flagpd1("Eonly"),
18flagpd1("H"),
19.{
20 .name = "<input>",
21 .syntax = .flag,
22 .zig_equivalent = .other,
23 .pd1 = false,
24 .pd2 = false,
25 .psl = false,
26},
27flagpd1("I-"),
28flagpd1("M"),
29flagpd1("MD"),
30flagpd1("MG"),
31flagpd1("MM"),
32flagpd1("MMD"),
33flagpd1("MP"),
34flagpd1("MV"),
35flagpd1("Mach"),
36flagpd1("O0"),
37flagpd1("O4"),
38.{
39 .name = "O",
40 .syntax = .flag,
41 .zig_equivalent = .optimize,
42 .pd1 = true,
43 .pd2 = false,
44 .psl = false,
45},
46flagpd1("ObjC"),
47flagpd1("ObjC++"),
48flagpd1("P"),
49flagpd1("Q"),
50flagpd1("Qn"),
51flagpd1("Qunused-arguments"),
52flagpd1("Qy"),
53.{
54 .name = "S",
55 .syntax = .flag,
56 .zig_equivalent = .driver_punt,
57 .pd1 = true,
58 .pd2 = false,
59 .psl = false,
60},
61.{
62 .name = "<unknown>",
63 .syntax = .flag,
64 .zig_equivalent = .other,
65 .pd1 = false,
66 .pd2 = false,
67 .psl = false,
68},
69flagpd1("WCL4"),
70flagpd1("Wall"),
71flagpd1("Wdeprecated"),
72flagpd1("Wlarge-by-value-copy"),
73flagpd1("Wno-deprecated"),
74flagpd1("Wno-rewrite-macros"),
75flagpd1("Wno-write-strings"),
76flagpd1("Wwrite-strings"),
77flagpd1("X"),
78sepd1("Xanalyzer"),
79sepd1("Xassembler"),
80sepd1("Xclang"),
81sepd1("Xcuda-fatbinary"),
82sepd1("Xcuda-ptxas"),
83sepd1("Xlinker"),
84sepd1("Xopenmp-target"),
85sepd1("Xpreprocessor"),
86flagpd1("Z"),
87flagpd1("Z-Xlinker-no-demangle"),
88flagpd1("Z-reserved-lib-cckext"),
89flagpd1("Z-reserved-lib-stdc++"),
90sepd1("Zlinker-input"),
91.{
92 .name = "CLASSPATH",
93 .syntax = .separate,
94 .zig_equivalent = .other,
95 .pd1 = false,
96 .pd2 = true,
97 .psl = false,
98},
99flagpd1("###"),
100.{
101 .name = "Brepro",
102 .syntax = .flag,
103 .zig_equivalent = .other,
104 .pd1 = true,
105 .pd2 = false,
106 .psl = true,
107},
108.{
109 .name = "Brepro-",
110 .syntax = .flag,
111 .zig_equivalent = .other,
112 .pd1 = true,
113 .pd2 = false,
114 .psl = true,
115},
116.{
117 .name = "Bt",
118 .syntax = .flag,
119 .zig_equivalent = .other,
120 .pd1 = true,
121 .pd2 = false,
122 .psl = true,
123},
124.{
125 .name = "Bt+",
126 .syntax = .flag,
127 .zig_equivalent = .other,
128 .pd1 = true,
129 .pd2 = false,
130 .psl = true,
131},
132.{
133 .name = "C",
134 .syntax = .flag,
135 .zig_equivalent = .other,
136 .pd1 = true,
137 .pd2 = false,
138 .psl = true,
139},
140.{
141 .name = "E",
142 .syntax = .flag,
143 .zig_equivalent = .preprocess,
144 .pd1 = true,
145 .pd2 = false,
146 .psl = true,
147},
148.{
149 .name = "EP",
150 .syntax = .flag,
151 .zig_equivalent = .other,
152 .pd1 = true,
153 .pd2 = false,
154 .psl = true,
155},
156.{
157 .name = "FA",
158 .syntax = .flag,
159 .zig_equivalent = .other,
160 .pd1 = true,
161 .pd2 = false,
162 .psl = true,
163},
164.{
165 .name = "FC",
166 .syntax = .flag,
167 .zig_equivalent = .other,
168 .pd1 = true,
169 .pd2 = false,
170 .psl = true,
171},
172.{
173 .name = "FS",
174 .syntax = .flag,
175 .zig_equivalent = .other,
176 .pd1 = true,
177 .pd2 = false,
178 .psl = true,
179},
180.{
181 .name = "Fx",
182 .syntax = .flag,
183 .zig_equivalent = .other,
184 .pd1 = true,
185 .pd2 = false,
186 .psl = true,
187},
188.{
189 .name = "G1",
190 .syntax = .flag,
191 .zig_equivalent = .other,
192 .pd1 = true,
193 .pd2 = false,
194 .psl = true,
195},
196.{
197 .name = "G2",
198 .syntax = .flag,
199 .zig_equivalent = .other,
200 .pd1 = true,
201 .pd2 = false,
202 .psl = true,
203},
204.{
205 .name = "GA",
206 .syntax = .flag,
207 .zig_equivalent = .other,
208 .pd1 = true,
209 .pd2 = false,
210 .psl = true,
211},
212.{
213 .name = "GF",
214 .syntax = .flag,
215 .zig_equivalent = .other,
216 .pd1 = true,
217 .pd2 = false,
218 .psl = true,
219},
220.{
221 .name = "GF-",
222 .syntax = .flag,
223 .zig_equivalent = .other,
224 .pd1 = true,
225 .pd2 = false,
226 .psl = true,
227},
228.{
229 .name = "GH",
230 .syntax = .flag,
231 .zig_equivalent = .other,
232 .pd1 = true,
233 .pd2 = false,
234 .psl = true,
235},
236.{
237 .name = "GL",
238 .syntax = .flag,
239 .zig_equivalent = .other,
240 .pd1 = true,
241 .pd2 = false,
242 .psl = true,
243},
244.{
245 .name = "GL-",
246 .syntax = .flag,
247 .zig_equivalent = .other,
248 .pd1 = true,
249 .pd2 = false,
250 .psl = true,
251},
252.{
253 .name = "GR",
254 .syntax = .flag,
255 .zig_equivalent = .other,
256 .pd1 = true,
257 .pd2 = false,
258 .psl = true,
259},
260.{
261 .name = "GR-",
262 .syntax = .flag,
263 .zig_equivalent = .other,
264 .pd1 = true,
265 .pd2 = false,
266 .psl = true,
267},
268.{
269 .name = "GS",
270 .syntax = .flag,
271 .zig_equivalent = .other,
272 .pd1 = true,
273 .pd2 = false,
274 .psl = true,
275},
276.{
277 .name = "GS-",
278 .syntax = .flag,
279 .zig_equivalent = .other,
280 .pd1 = true,
281 .pd2 = false,
282 .psl = true,
283},
284.{
285 .name = "GT",
286 .syntax = .flag,
287 .zig_equivalent = .other,
288 .pd1 = true,
289 .pd2 = false,
290 .psl = true,
291},
292.{
293 .name = "GX",
294 .syntax = .flag,
295 .zig_equivalent = .other,
296 .pd1 = true,
297 .pd2 = false,
298 .psl = true,
299},
300.{
301 .name = "GX-",
302 .syntax = .flag,
303 .zig_equivalent = .other,
304 .pd1 = true,
305 .pd2 = false,
306 .psl = true,
307},
308.{
309 .name = "GZ",
310 .syntax = .flag,
311 .zig_equivalent = .other,
312 .pd1 = true,
313 .pd2 = false,
314 .psl = true,
315},
316.{
317 .name = "Gd",
318 .syntax = .flag,
319 .zig_equivalent = .other,
320 .pd1 = true,
321 .pd2 = false,
322 .psl = true,
323},
324.{
325 .name = "Ge",
326 .syntax = .flag,
327 .zig_equivalent = .other,
328 .pd1 = true,
329 .pd2 = false,
330 .psl = true,
331},
332.{
333 .name = "Gh",
334 .syntax = .flag,
335 .zig_equivalent = .other,
336 .pd1 = true,
337 .pd2 = false,
338 .psl = true,
339},
340.{
341 .name = "Gm",
342 .syntax = .flag,
343 .zig_equivalent = .other,
344 .pd1 = true,
345 .pd2 = false,
346 .psl = true,
347},
348.{
349 .name = "Gm-",
350 .syntax = .flag,
351 .zig_equivalent = .other,
352 .pd1 = true,
353 .pd2 = false,
354 .psl = true,
355},
356.{
357 .name = "Gr",
358 .syntax = .flag,
359 .zig_equivalent = .other,
360 .pd1 = true,
361 .pd2 = false,
362 .psl = true,
363},
364.{
365 .name = "Gregcall",
366 .syntax = .flag,
367 .zig_equivalent = .other,
368 .pd1 = true,
369 .pd2 = false,
370 .psl = true,
371},
372.{
373 .name = "Gv",
374 .syntax = .flag,
375 .zig_equivalent = .other,
376 .pd1 = true,
377 .pd2 = false,
378 .psl = true,
379},
380.{
381 .name = "Gw",
382 .syntax = .flag,
383 .zig_equivalent = .other,
384 .pd1 = true,
385 .pd2 = false,
386 .psl = true,
387},
388.{
389 .name = "Gw-",
390 .syntax = .flag,
391 .zig_equivalent = .other,
392 .pd1 = true,
393 .pd2 = false,
394 .psl = true,
395},
396.{
397 .name = "Gy",
398 .syntax = .flag,
399 .zig_equivalent = .other,
400 .pd1 = true,
401 .pd2 = false,
402 .psl = true,
403},
404.{
405 .name = "Gy-",
406 .syntax = .flag,
407 .zig_equivalent = .other,
408 .pd1 = true,
409 .pd2 = false,
410 .psl = true,
411},
412.{
413 .name = "Gz",
414 .syntax = .flag,
415 .zig_equivalent = .other,
416 .pd1 = true,
417 .pd2 = false,
418 .psl = true,
419},
420.{
421 .name = "H",
422 .syntax = .flag,
423 .zig_equivalent = .other,
424 .pd1 = true,
425 .pd2 = false,
426 .psl = true,
427},
428.{
429 .name = "HELP",
430 .syntax = .flag,
431 .zig_equivalent = .other,
432 .pd1 = true,
433 .pd2 = false,
434 .psl = true,
435},
436.{
437 .name = "J",
438 .syntax = .flag,
439 .zig_equivalent = .other,
440 .pd1 = true,
441 .pd2 = false,
442 .psl = true,
443},
444.{
445 .name = "JMC",
446 .syntax = .flag,
447 .zig_equivalent = .other,
448 .pd1 = true,
449 .pd2 = false,
450 .psl = true,
451},
452.{
453 .name = "LD",
454 .syntax = .flag,
455 .zig_equivalent = .other,
456 .pd1 = true,
457 .pd2 = false,
458 .psl = true,
459},
460.{
461 .name = "LDd",
462 .syntax = .flag,
463 .zig_equivalent = .other,
464 .pd1 = true,
465 .pd2 = false,
466 .psl = true,
467},
468.{
469 .name = "LN",
470 .syntax = .flag,
471 .zig_equivalent = .other,
472 .pd1 = true,
473 .pd2 = false,
474 .psl = true,
475},
476.{
477 .name = "MD",
478 .syntax = .flag,
479 .zig_equivalent = .other,
480 .pd1 = true,
481 .pd2 = false,
482 .psl = true,
483},
484.{
485 .name = "MDd",
486 .syntax = .flag,
487 .zig_equivalent = .other,
488 .pd1 = true,
489 .pd2 = false,
490 .psl = true,
491},
492.{
493 .name = "MT",
494 .syntax = .flag,
495 .zig_equivalent = .other,
496 .pd1 = true,
497 .pd2 = false,
498 .psl = true,
499},
500.{
501 .name = "MTd",
502 .syntax = .flag,
503 .zig_equivalent = .other,
504 .pd1 = true,
505 .pd2 = false,
506 .psl = true,
507},
508.{
509 .name = "P",
510 .syntax = .flag,
511 .zig_equivalent = .other,
512 .pd1 = true,
513 .pd2 = false,
514 .psl = true,
515},
516.{
517 .name = "QIfist",
518 .syntax = .flag,
519 .zig_equivalent = .other,
520 .pd1 = true,
521 .pd2 = false,
522 .psl = true,
523},
524.{
525 .name = "?",
526 .syntax = .flag,
527 .zig_equivalent = .other,
528 .pd1 = true,
529 .pd2 = false,
530 .psl = true,
531},
532.{
533 .name = "Qfast_transcendentals",
534 .syntax = .flag,
535 .zig_equivalent = .other,
536 .pd1 = true,
537 .pd2 = false,
538 .psl = true,
539},
540.{
541 .name = "Qimprecise_fwaits",
542 .syntax = .flag,
543 .zig_equivalent = .other,
544 .pd1 = true,
545 .pd2 = false,
546 .psl = true,
547},
548.{
549 .name = "Qpar",
550 .syntax = .flag,
551 .zig_equivalent = .other,
552 .pd1 = true,
553 .pd2 = false,
554 .psl = true,
555},
556.{
557 .name = "Qsafe_fp_loads",
558 .syntax = .flag,
559 .zig_equivalent = .other,
560 .pd1 = true,
561 .pd2 = false,
562 .psl = true,
563},
564.{
565 .name = "Qspectre",
566 .syntax = .flag,
567 .zig_equivalent = .other,
568 .pd1 = true,
569 .pd2 = false,
570 .psl = true,
571},
572.{
573 .name = "Qvec",
574 .syntax = .flag,
575 .zig_equivalent = .other,
576 .pd1 = true,
577 .pd2 = false,
578 .psl = true,
579},
580.{
581 .name = "Qvec-",
582 .syntax = .flag,
583 .zig_equivalent = .other,
584 .pd1 = true,
585 .pd2 = false,
586 .psl = true,
587},
588.{
589 .name = "TC",
590 .syntax = .flag,
591 .zig_equivalent = .other,
592 .pd1 = true,
593 .pd2 = false,
594 .psl = true,
595},
596.{
597 .name = "TP",
598 .syntax = .flag,
599 .zig_equivalent = .other,
600 .pd1 = true,
601 .pd2 = false,
602 .psl = true,
603},
604.{
605 .name = "V",
606 .syntax = .flag,
607 .zig_equivalent = .other,
608 .pd1 = true,
609 .pd2 = false,
610 .psl = true,
611},
612.{
613 .name = "W0",
614 .syntax = .flag,
615 .zig_equivalent = .other,
616 .pd1 = true,
617 .pd2 = false,
618 .psl = true,
619},
620.{
621 .name = "W1",
622 .syntax = .flag,
623 .zig_equivalent = .other,
624 .pd1 = true,
625 .pd2 = false,
626 .psl = true,
627},
628.{
629 .name = "W2",
630 .syntax = .flag,
631 .zig_equivalent = .other,
632 .pd1 = true,
633 .pd2 = false,
634 .psl = true,
635},
636.{
637 .name = "W3",
638 .syntax = .flag,
639 .zig_equivalent = .other,
640 .pd1 = true,
641 .pd2 = false,
642 .psl = true,
643},
644.{
645 .name = "W4",
646 .syntax = .flag,
647 .zig_equivalent = .other,
648 .pd1 = true,
649 .pd2 = false,
650 .psl = true,
651},
652.{
653 .name = "WL",
654 .syntax = .flag,
655 .zig_equivalent = .other,
656 .pd1 = true,
657 .pd2 = false,
658 .psl = true,
659},
660.{
661 .name = "WX",
662 .syntax = .flag,
663 .zig_equivalent = .other,
664 .pd1 = true,
665 .pd2 = false,
666 .psl = true,
667},
668.{
669 .name = "WX-",
670 .syntax = .flag,
671 .zig_equivalent = .other,
672 .pd1 = true,
673 .pd2 = false,
674 .psl = true,
675},
676.{
677 .name = "Wall",
678 .syntax = .flag,
679 .zig_equivalent = .other,
680 .pd1 = true,
681 .pd2 = false,
682 .psl = true,
683},
684.{
685 .name = "Wp64",
686 .syntax = .flag,
687 .zig_equivalent = .other,
688 .pd1 = true,
689 .pd2 = false,
690 .psl = true,
691},
692.{
693 .name = "X",
694 .syntax = .flag,
695 .zig_equivalent = .other,
696 .pd1 = true,
697 .pd2 = false,
698 .psl = true,
699},
700.{
701 .name = "Y-",
702 .syntax = .flag,
703 .zig_equivalent = .other,
704 .pd1 = true,
705 .pd2 = false,
706 .psl = true,
707},
708.{
709 .name = "Yd",
710 .syntax = .flag,
711 .zig_equivalent = .other,
712 .pd1 = true,
713 .pd2 = false,
714 .psl = true,
715},
716.{
717 .name = "Z7",
718 .syntax = .flag,
719 .zig_equivalent = .other,
720 .pd1 = true,
721 .pd2 = false,
722 .psl = true,
723},
724.{
725 .name = "ZH:MD5",
726 .syntax = .flag,
727 .zig_equivalent = .other,
728 .pd1 = true,
729 .pd2 = false,
730 .psl = true,
731},
732.{
733 .name = "ZH:SHA1",
734 .syntax = .flag,
735 .zig_equivalent = .other,
736 .pd1 = true,
737 .pd2 = false,
738 .psl = true,
739},
740.{
741 .name = "ZH:SHA_256",
742 .syntax = .flag,
743 .zig_equivalent = .other,
744 .pd1 = true,
745 .pd2 = false,
746 .psl = true,
747},
748.{
749 .name = "ZI",
750 .syntax = .flag,
751 .zig_equivalent = .other,
752 .pd1 = true,
753 .pd2 = false,
754 .psl = true,
755},
756.{
757 .name = "Za",
758 .syntax = .flag,
759 .zig_equivalent = .other,
760 .pd1 = true,
761 .pd2 = false,
762 .psl = true,
763},
764.{
765 .name = "Zc:__cplusplus",
766 .syntax = .flag,
767 .zig_equivalent = .other,
768 .pd1 = true,
769 .pd2 = false,
770 .psl = true,
771},
772.{
773 .name = "Zc:alignedNew",
774 .syntax = .flag,
775 .zig_equivalent = .other,
776 .pd1 = true,
777 .pd2 = false,
778 .psl = true,
779},
780.{
781 .name = "Zc:alignedNew-",
782 .syntax = .flag,
783 .zig_equivalent = .other,
784 .pd1 = true,
785 .pd2 = false,
786 .psl = true,
787},
788.{
789 .name = "Zc:auto",
790 .syntax = .flag,
791 .zig_equivalent = .other,
792 .pd1 = true,
793 .pd2 = false,
794 .psl = true,
795},
796.{
797 .name = "Zc:char8_t",
798 .syntax = .flag,
799 .zig_equivalent = .other,
800 .pd1 = true,
801 .pd2 = false,
802 .psl = true,
803},
804.{
805 .name = "Zc:char8_t-",
806 .syntax = .flag,
807 .zig_equivalent = .other,
808 .pd1 = true,
809 .pd2 = false,
810 .psl = true,
811},
812.{
813 .name = "Zc:dllexportInlines",
814 .syntax = .flag,
815 .zig_equivalent = .other,
816 .pd1 = true,
817 .pd2 = false,
818 .psl = true,
819},
820.{
821 .name = "Zc:dllexportInlines-",
822 .syntax = .flag,
823 .zig_equivalent = .other,
824 .pd1 = true,
825 .pd2 = false,
826 .psl = true,
827},
828.{
829 .name = "Zc:forScope",
830 .syntax = .flag,
831 .zig_equivalent = .other,
832 .pd1 = true,
833 .pd2 = false,
834 .psl = true,
835},
836.{
837 .name = "Zc:inline",
838 .syntax = .flag,
839 .zig_equivalent = .other,
840 .pd1 = true,
841 .pd2 = false,
842 .psl = true,
843},
844.{
845 .name = "Zc:rvalueCast",
846 .syntax = .flag,
847 .zig_equivalent = .other,
848 .pd1 = true,
849 .pd2 = false,
850 .psl = true,
851},
852.{
853 .name = "Zc:sizedDealloc",
854 .syntax = .flag,
855 .zig_equivalent = .other,
856 .pd1 = true,
857 .pd2 = false,
858 .psl = true,
859},
860.{
861 .name = "Zc:sizedDealloc-",
862 .syntax = .flag,
863 .zig_equivalent = .other,
864 .pd1 = true,
865 .pd2 = false,
866 .psl = true,
867},
868.{
869 .name = "Zc:strictStrings",
870 .syntax = .flag,
871 .zig_equivalent = .other,
872 .pd1 = true,
873 .pd2 = false,
874 .psl = true,
875},
876.{
877 .name = "Zc:ternary",
878 .syntax = .flag,
879 .zig_equivalent = .other,
880 .pd1 = true,
881 .pd2 = false,
882 .psl = true,
883},
884.{
885 .name = "Zc:threadSafeInit",
886 .syntax = .flag,
887 .zig_equivalent = .other,
888 .pd1 = true,
889 .pd2 = false,
890 .psl = true,
891},
892.{
893 .name = "Zc:threadSafeInit-",
894 .syntax = .flag,
895 .zig_equivalent = .other,
896 .pd1 = true,
897 .pd2 = false,
898 .psl = true,
899},
900.{
901 .name = "Zc:trigraphs",
902 .syntax = .flag,
903 .zig_equivalent = .other,
904 .pd1 = true,
905 .pd2 = false,
906 .psl = true,
907},
908.{
909 .name = "Zc:trigraphs-",
910 .syntax = .flag,
911 .zig_equivalent = .other,
912 .pd1 = true,
913 .pd2 = false,
914 .psl = true,
915},
916.{
917 .name = "Zc:twoPhase",
918 .syntax = .flag,
919 .zig_equivalent = .other,
920 .pd1 = true,
921 .pd2 = false,
922 .psl = true,
923},
924.{
925 .name = "Zc:twoPhase-",
926 .syntax = .flag,
927 .zig_equivalent = .other,
928 .pd1 = true,
929 .pd2 = false,
930 .psl = true,
931},
932.{
933 .name = "Zc:wchar_t",
934 .syntax = .flag,
935 .zig_equivalent = .other,
936 .pd1 = true,
937 .pd2 = false,
938 .psl = true,
939},
940.{
941 .name = "Zd",
942 .syntax = .flag,
943 .zig_equivalent = .other,
944 .pd1 = true,
945 .pd2 = false,
946 .psl = true,
947},
948.{
949 .name = "Ze",
950 .syntax = .flag,
951 .zig_equivalent = .other,
952 .pd1 = true,
953 .pd2 = false,
954 .psl = true,
955},
956.{
957 .name = "Zg",
958 .syntax = .flag,
959 .zig_equivalent = .other,
960 .pd1 = true,
961 .pd2 = false,
962 .psl = true,
963},
964.{
965 .name = "Zi",
966 .syntax = .flag,
967 .zig_equivalent = .other,
968 .pd1 = true,
969 .pd2 = false,
970 .psl = true,
971},
972.{
973 .name = "Zl",
974 .syntax = .flag,
975 .zig_equivalent = .other,
976 .pd1 = true,
977 .pd2 = false,
978 .psl = true,
979},
980.{
981 .name = "Zo",
982 .syntax = .flag,
983 .zig_equivalent = .other,
984 .pd1 = true,
985 .pd2 = false,
986 .psl = true,
987},
988.{
989 .name = "Zo-",
990 .syntax = .flag,
991 .zig_equivalent = .other,
992 .pd1 = true,
993 .pd2 = false,
994 .psl = true,
995},
996.{
997 .name = "Zp",
998 .syntax = .flag,
999 .zig_equivalent = .other,
1000 .pd1 = true,
1001 .pd2 = false,
1002 .psl = true,
1003},
1004.{
1005 .name = "Zs",
1006 .syntax = .flag,
1007 .zig_equivalent = .other,
1008 .pd1 = true,
1009 .pd2 = false,
1010 .psl = true,
1011},
1012.{
1013 .name = "analyze-",
1014 .syntax = .flag,
1015 .zig_equivalent = .other,
1016 .pd1 = true,
1017 .pd2 = false,
1018 .psl = true,
1019},
1020.{
1021 .name = "await",
1022 .syntax = .flag,
1023 .zig_equivalent = .other,
1024 .pd1 = true,
1025 .pd2 = false,
1026 .psl = true,
1027},
1028.{
1029 .name = "bigobj",
1030 .syntax = .flag,
1031 .zig_equivalent = .other,
1032 .pd1 = true,
1033 .pd2 = false,
1034 .psl = true,
1035},
1036.{
1037 .name = "c",
1038 .syntax = .flag,
1039 .zig_equivalent = .c,
1040 .pd1 = true,
1041 .pd2 = false,
1042 .psl = true,
1043},
1044.{
1045 .name = "d1PP",
1046 .syntax = .flag,
1047 .zig_equivalent = .other,
1048 .pd1 = true,
1049 .pd2 = false,
1050 .psl = true,
1051},
1052.{
1053 .name = "d1reportAllClassLayout",
1054 .syntax = .flag,
1055 .zig_equivalent = .other,
1056 .pd1 = true,
1057 .pd2 = false,
1058 .psl = true,
1059},
1060.{
1061 .name = "d2FastFail",
1062 .syntax = .flag,
1063 .zig_equivalent = .other,
1064 .pd1 = true,
1065 .pd2 = false,
1066 .psl = true,
1067},
1068.{
1069 .name = "d2Zi+",
1070 .syntax = .flag,
1071 .zig_equivalent = .other,
1072 .pd1 = true,
1073 .pd2 = false,
1074 .psl = true,
1075},
1076.{
1077 .name = "diagnostics:caret",
1078 .syntax = .flag,
1079 .zig_equivalent = .other,
1080 .pd1 = true,
1081 .pd2 = false,
1082 .psl = true,
1083},
1084.{
1085 .name = "diagnostics:classic",
1086 .syntax = .flag,
1087 .zig_equivalent = .other,
1088 .pd1 = true,
1089 .pd2 = false,
1090 .psl = true,
1091},
1092.{
1093 .name = "diagnostics:column",
1094 .syntax = .flag,
1095 .zig_equivalent = .other,
1096 .pd1 = true,
1097 .pd2 = false,
1098 .psl = true,
1099},
1100.{
1101 .name = "fallback",
1102 .syntax = .flag,
1103 .zig_equivalent = .other,
1104 .pd1 = true,
1105 .pd2 = false,
1106 .psl = true,
1107},
1108.{
1109 .name = "fp:except",
1110 .syntax = .flag,
1111 .zig_equivalent = .other,
1112 .pd1 = true,
1113 .pd2 = false,
1114 .psl = true,
1115},
1116.{
1117 .name = "fp:except-",
1118 .syntax = .flag,
1119 .zig_equivalent = .other,
1120 .pd1 = true,
1121 .pd2 = false,
1122 .psl = true,
1123},
1124.{
1125 .name = "fp:fast",
1126 .syntax = .flag,
1127 .zig_equivalent = .other,
1128 .pd1 = true,
1129 .pd2 = false,
1130 .psl = true,
1131},
1132.{
1133 .name = "fp:precise",
1134 .syntax = .flag,
1135 .zig_equivalent = .other,
1136 .pd1 = true,
1137 .pd2 = false,
1138 .psl = true,
1139},
1140.{
1141 .name = "fp:strict",
1142 .syntax = .flag,
1143 .zig_equivalent = .other,
1144 .pd1 = true,
1145 .pd2 = false,
1146 .psl = true,
1147},
1148.{
1149 .name = "help",
1150 .syntax = .flag,
1151 .zig_equivalent = .driver_punt,
1152 .pd1 = true,
1153 .pd2 = false,
1154 .psl = true,
1155},
1156.{
1157 .name = "homeparams",
1158 .syntax = .flag,
1159 .zig_equivalent = .other,
1160 .pd1 = true,
1161 .pd2 = false,
1162 .psl = true,
1163},
1164.{
1165 .name = "hotpatch",
1166 .syntax = .flag,
1167 .zig_equivalent = .other,
1168 .pd1 = true,
1169 .pd2 = false,
1170 .psl = true,
1171},
1172.{
1173 .name = "kernel",
1174 .syntax = .flag,
1175 .zig_equivalent = .other,
1176 .pd1 = true,
1177 .pd2 = false,
1178 .psl = true,
1179},
1180.{
1181 .name = "kernel-",
1182 .syntax = .flag,
1183 .zig_equivalent = .other,
1184 .pd1 = true,
1185 .pd2 = false,
1186 .psl = true,
1187},
1188.{
1189 .name = "nologo",
1190 .syntax = .flag,
1191 .zig_equivalent = .other,
1192 .pd1 = true,
1193 .pd2 = false,
1194 .psl = true,
1195},
1196.{
1197 .name = "openmp",
1198 .syntax = .flag,
1199 .zig_equivalent = .other,
1200 .pd1 = true,
1201 .pd2 = false,
1202 .psl = true,
1203},
1204.{
1205 .name = "openmp-",
1206 .syntax = .flag,
1207 .zig_equivalent = .other,
1208 .pd1 = true,
1209 .pd2 = false,
1210 .psl = true,
1211},
1212.{
1213 .name = "openmp:experimental",
1214 .syntax = .flag,
1215 .zig_equivalent = .other,
1216 .pd1 = true,
1217 .pd2 = false,
1218 .psl = true,
1219},
1220.{
1221 .name = "permissive-",
1222 .syntax = .flag,
1223 .zig_equivalent = .other,
1224 .pd1 = true,
1225 .pd2 = false,
1226 .psl = true,
1227},
1228.{
1229 .name = "sdl",
1230 .syntax = .flag,
1231 .zig_equivalent = .other,
1232 .pd1 = true,
1233 .pd2 = false,
1234 .psl = true,
1235},
1236.{
1237 .name = "sdl-",
1238 .syntax = .flag,
1239 .zig_equivalent = .other,
1240 .pd1 = true,
1241 .pd2 = false,
1242 .psl = true,
1243},
1244.{
1245 .name = "showFilenames",
1246 .syntax = .flag,
1247 .zig_equivalent = .other,
1248 .pd1 = true,
1249 .pd2 = false,
1250 .psl = true,
1251},
1252.{
1253 .name = "showFilenames-",
1254 .syntax = .flag,
1255 .zig_equivalent = .other,
1256 .pd1 = true,
1257 .pd2 = false,
1258 .psl = true,
1259},
1260.{
1261 .name = "showIncludes",
1262 .syntax = .flag,
1263 .zig_equivalent = .other,
1264 .pd1 = true,
1265 .pd2 = false,
1266 .psl = true,
1267},
1268.{
1269 .name = "u",
1270 .syntax = .flag,
1271 .zig_equivalent = .other,
1272 .pd1 = true,
1273 .pd2 = false,
1274 .psl = true,
1275},
1276.{
1277 .name = "utf-8",
1278 .syntax = .flag,
1279 .zig_equivalent = .other,
1280 .pd1 = true,
1281 .pd2 = false,
1282 .psl = true,
1283},
1284.{
1285 .name = "validate-charset",
1286 .syntax = .flag,
1287 .zig_equivalent = .other,
1288 .pd1 = true,
1289 .pd2 = false,
1290 .psl = true,
1291},
1292.{
1293 .name = "validate-charset-",
1294 .syntax = .flag,
1295 .zig_equivalent = .other,
1296 .pd1 = true,
1297 .pd2 = false,
1298 .psl = true,
1299},
1300.{
1301 .name = "vmb",
1302 .syntax = .flag,
1303 .zig_equivalent = .other,
1304 .pd1 = true,
1305 .pd2 = false,
1306 .psl = true,
1307},
1308.{
1309 .name = "vmg",
1310 .syntax = .flag,
1311 .zig_equivalent = .other,
1312 .pd1 = true,
1313 .pd2 = false,
1314 .psl = true,
1315},
1316.{
1317 .name = "vmm",
1318 .syntax = .flag,
1319 .zig_equivalent = .other,
1320 .pd1 = true,
1321 .pd2 = false,
1322 .psl = true,
1323},
1324.{
1325 .name = "vms",
1326 .syntax = .flag,
1327 .zig_equivalent = .other,
1328 .pd1 = true,
1329 .pd2 = false,
1330 .psl = true,
1331},
1332.{
1333 .name = "vmv",
1334 .syntax = .flag,
1335 .zig_equivalent = .other,
1336 .pd1 = true,
1337 .pd2 = false,
1338 .psl = true,
1339},
1340.{
1341 .name = "volatile:iso",
1342 .syntax = .flag,
1343 .zig_equivalent = .other,
1344 .pd1 = true,
1345 .pd2 = false,
1346 .psl = true,
1347},
1348.{
1349 .name = "volatile:ms",
1350 .syntax = .flag,
1351 .zig_equivalent = .other,
1352 .pd1 = true,
1353 .pd2 = false,
1354 .psl = true,
1355},
1356.{
1357 .name = "w",
1358 .syntax = .flag,
1359 .zig_equivalent = .other,
1360 .pd1 = true,
1361 .pd2 = false,
1362 .psl = true,
1363},
1364.{
1365 .name = "wd4005",
1366 .syntax = .flag,
1367 .zig_equivalent = .other,
1368 .pd1 = true,
1369 .pd2 = false,
1370 .psl = true,
1371},
1372.{
1373 .name = "wd4018",
1374 .syntax = .flag,
1375 .zig_equivalent = .other,
1376 .pd1 = true,
1377 .pd2 = false,
1378 .psl = true,
1379},
1380.{
1381 .name = "wd4100",
1382 .syntax = .flag,
1383 .zig_equivalent = .other,
1384 .pd1 = true,
1385 .pd2 = false,
1386 .psl = true,
1387},
1388.{
1389 .name = "wd4910",
1390 .syntax = .flag,
1391 .zig_equivalent = .other,
1392 .pd1 = true,
1393 .pd2 = false,
1394 .psl = true,
1395},
1396.{
1397 .name = "wd4996",
1398 .syntax = .flag,
1399 .zig_equivalent = .other,
1400 .pd1 = true,
1401 .pd2 = false,
1402 .psl = true,
1403},
1404.{
1405 .name = "all-warnings",
1406 .syntax = .flag,
1407 .zig_equivalent = .other,
1408 .pd1 = false,
1409 .pd2 = true,
1410 .psl = false,
1411},
1412.{
1413 .name = "analyze",
1414 .syntax = .flag,
1415 .zig_equivalent = .other,
1416 .pd1 = false,
1417 .pd2 = true,
1418 .psl = false,
1419},
1420.{
1421 .name = "analyzer-no-default-checks",
1422 .syntax = .flag,
1423 .zig_equivalent = .other,
1424 .pd1 = false,
1425 .pd2 = true,
1426 .psl = false,
1427},
1428.{
1429 .name = "assemble",
1430 .syntax = .flag,
1431 .zig_equivalent = .driver_punt,
1432 .pd1 = false,
1433 .pd2 = true,
1434 .psl = false,
1435},
1436.{
1437 .name = "assert",
1438 .syntax = .separate,
1439 .zig_equivalent = .other,
1440 .pd1 = false,
1441 .pd2 = true,
1442 .psl = false,
1443},
1444.{
1445 .name = "bootclasspath",
1446 .syntax = .separate,
1447 .zig_equivalent = .other,
1448 .pd1 = false,
1449 .pd2 = true,
1450 .psl = false,
1451},
1452.{
1453 .name = "classpath",
1454 .syntax = .separate,
1455 .zig_equivalent = .other,
1456 .pd1 = false,
1457 .pd2 = true,
1458 .psl = false,
1459},
1460.{
1461 .name = "comments",
1462 .syntax = .flag,
1463 .zig_equivalent = .other,
1464 .pd1 = false,
1465 .pd2 = true,
1466 .psl = false,
1467},
1468.{
1469 .name = "comments-in-macros",
1470 .syntax = .flag,
1471 .zig_equivalent = .other,
1472 .pd1 = false,
1473 .pd2 = true,
1474 .psl = false,
1475},
1476.{
1477 .name = "compile",
1478 .syntax = .flag,
1479 .zig_equivalent = .other,
1480 .pd1 = false,
1481 .pd2 = true,
1482 .psl = false,
1483},
1484.{
1485 .name = "constant-cfstrings",
1486 .syntax = .flag,
1487 .zig_equivalent = .other,
1488 .pd1 = false,
1489 .pd2 = true,
1490 .psl = false,
1491},
1492.{
1493 .name = "debug",
1494 .syntax = .flag,
1495 .zig_equivalent = .debug,
1496 .pd1 = false,
1497 .pd2 = true,
1498 .psl = false,
1499},
1500.{
1501 .name = "define-macro",
1502 .syntax = .separate,
1503 .zig_equivalent = .other,
1504 .pd1 = false,
1505 .pd2 = true,
1506 .psl = false,
1507},
1508.{
1509 .name = "dependencies",
1510 .syntax = .flag,
1511 .zig_equivalent = .other,
1512 .pd1 = false,
1513 .pd2 = true,
1514 .psl = false,
1515},
1516.{
1517 .name = "dyld-prefix",
1518 .syntax = .separate,
1519 .zig_equivalent = .other,
1520 .pd1 = false,
1521 .pd2 = true,
1522 .psl = false,
1523},
1524.{
1525 .name = "encoding",
1526 .syntax = .separate,
1527 .zig_equivalent = .other,
1528 .pd1 = false,
1529 .pd2 = true,
1530 .psl = false,
1531},
1532.{
1533 .name = "entry",
1534 .syntax = .flag,
1535 .zig_equivalent = .other,
1536 .pd1 = false,
1537 .pd2 = true,
1538 .psl = false,
1539},
1540.{
1541 .name = "extdirs",
1542 .syntax = .separate,
1543 .zig_equivalent = .other,
1544 .pd1 = false,
1545 .pd2 = true,
1546 .psl = false,
1547},
1548.{
1549 .name = "extra-warnings",
1550 .syntax = .flag,
1551 .zig_equivalent = .other,
1552 .pd1 = false,
1553 .pd2 = true,
1554 .psl = false,
1555},
1556.{
1557 .name = "for-linker",
1558 .syntax = .separate,
1559 .zig_equivalent = .other,
1560 .pd1 = false,
1561 .pd2 = true,
1562 .psl = false,
1563},
1564.{
1565 .name = "force-link",
1566 .syntax = .separate,
1567 .zig_equivalent = .other,
1568 .pd1 = false,
1569 .pd2 = true,
1570 .psl = false,
1571},
1572.{
1573 .name = "help-hidden",
1574 .syntax = .flag,
1575 .zig_equivalent = .other,
1576 .pd1 = false,
1577 .pd2 = true,
1578 .psl = false,
1579},
1580.{
1581 .name = "include-barrier",
1582 .syntax = .flag,
1583 .zig_equivalent = .other,
1584 .pd1 = false,
1585 .pd2 = true,
1586 .psl = false,
1587},
1588.{
1589 .name = "include-directory",
1590 .syntax = .separate,
1591 .zig_equivalent = .other,
1592 .pd1 = false,
1593 .pd2 = true,
1594 .psl = false,
1595},
1596.{
1597 .name = "include-directory-after",
1598 .syntax = .separate,
1599 .zig_equivalent = .other,
1600 .pd1 = false,
1601 .pd2 = true,
1602 .psl = false,
1603},
1604.{
1605 .name = "include-prefix",
1606 .syntax = .separate,
1607 .zig_equivalent = .other,
1608 .pd1 = false,
1609 .pd2 = true,
1610 .psl = false,
1611},
1612.{
1613 .name = "include-with-prefix",
1614 .syntax = .separate,
1615 .zig_equivalent = .other,
1616 .pd1 = false,
1617 .pd2 = true,
1618 .psl = false,
1619},
1620.{
1621 .name = "include-with-prefix-after",
1622 .syntax = .separate,
1623 .zig_equivalent = .other,
1624 .pd1 = false,
1625 .pd2 = true,
1626 .psl = false,
1627},
1628.{
1629 .name = "include-with-prefix-before",
1630 .syntax = .separate,
1631 .zig_equivalent = .other,
1632 .pd1 = false,
1633 .pd2 = true,
1634 .psl = false,
1635},
1636.{
1637 .name = "language",
1638 .syntax = .separate,
1639 .zig_equivalent = .other,
1640 .pd1 = false,
1641 .pd2 = true,
1642 .psl = false,
1643},
1644.{
1645 .name = "library-directory",
1646 .syntax = .separate,
1647 .zig_equivalent = .other,
1648 .pd1 = false,
1649 .pd2 = true,
1650 .psl = false,
1651},
1652.{
1653 .name = "mhwdiv",
1654 .syntax = .separate,
1655 .zig_equivalent = .other,
1656 .pd1 = false,
1657 .pd2 = true,
1658 .psl = false,
1659},
1660.{
1661 .name = "migrate",
1662 .syntax = .flag,
1663 .zig_equivalent = .other,
1664 .pd1 = false,
1665 .pd2 = true,
1666 .psl = false,
1667},
1668.{
1669 .name = "no-line-commands",
1670 .syntax = .flag,
1671 .zig_equivalent = .other,
1672 .pd1 = false,
1673 .pd2 = true,
1674 .psl = false,
1675},
1676.{
1677 .name = "no-standard-includes",
1678 .syntax = .flag,
1679 .zig_equivalent = .other,
1680 .pd1 = false,
1681 .pd2 = true,
1682 .psl = false,
1683},
1684.{
1685 .name = "no-standard-libraries",
1686 .syntax = .flag,
1687 .zig_equivalent = .nostdlib,
1688 .pd1 = false,
1689 .pd2 = true,
1690 .psl = false,
1691},
1692.{
1693 .name = "no-undefined",
1694 .syntax = .flag,
1695 .zig_equivalent = .other,
1696 .pd1 = false,
1697 .pd2 = true,
1698 .psl = false,
1699},
1700.{
1701 .name = "no-warnings",
1702 .syntax = .flag,
1703 .zig_equivalent = .other,
1704 .pd1 = false,
1705 .pd2 = true,
1706 .psl = false,
1707},
1708.{
1709 .name = "optimize",
1710 .syntax = .flag,
1711 .zig_equivalent = .optimize,
1712 .pd1 = false,
1713 .pd2 = true,
1714 .psl = false,
1715},
1716.{
1717 .name = "output",
1718 .syntax = .separate,
1719 .zig_equivalent = .other,
1720 .pd1 = false,
1721 .pd2 = true,
1722 .psl = false,
1723},
1724.{
1725 .name = "output-class-directory",
1726 .syntax = .separate,
1727 .zig_equivalent = .other,
1728 .pd1 = false,
1729 .pd2 = true,
1730 .psl = false,
1731},
1732.{
1733 .name = "param",
1734 .syntax = .separate,
1735 .zig_equivalent = .other,
1736 .pd1 = false,
1737 .pd2 = true,
1738 .psl = false,
1739},
1740.{
1741 .name = "precompile",
1742 .syntax = .flag,
1743 .zig_equivalent = .other,
1744 .pd1 = false,
1745 .pd2 = true,
1746 .psl = false,
1747},
1748.{
1749 .name = "prefix",
1750 .syntax = .separate,
1751 .zig_equivalent = .other,
1752 .pd1 = false,
1753 .pd2 = true,
1754 .psl = false,
1755},
1756.{
1757 .name = "preprocess",
1758 .syntax = .flag,
1759 .zig_equivalent = .preprocess,
1760 .pd1 = false,
1761 .pd2 = true,
1762 .psl = false,
1763},
1764.{
1765 .name = "print-diagnostic-categories",
1766 .syntax = .flag,
1767 .zig_equivalent = .other,
1768 .pd1 = false,
1769 .pd2 = true,
1770 .psl = false,
1771},
1772.{
1773 .name = "print-file-name",
1774 .syntax = .separate,
1775 .zig_equivalent = .other,
1776 .pd1 = false,
1777 .pd2 = true,
1778 .psl = false,
1779},
1780.{
1781 .name = "print-missing-file-dependencies",
1782 .syntax = .flag,
1783 .zig_equivalent = .other,
1784 .pd1 = false,
1785 .pd2 = true,
1786 .psl = false,
1787},
1788.{
1789 .name = "print-prog-name",
1790 .syntax = .separate,
1791 .zig_equivalent = .other,
1792 .pd1 = false,
1793 .pd2 = true,
1794 .psl = false,
1795},
1796.{
1797 .name = "profile",
1798 .syntax = .flag,
1799 .zig_equivalent = .other,
1800 .pd1 = false,
1801 .pd2 = true,
1802 .psl = false,
1803},
1804.{
1805 .name = "profile-blocks",
1806 .syntax = .flag,
1807 .zig_equivalent = .other,
1808 .pd1 = false,
1809 .pd2 = true,
1810 .psl = false,
1811},
1812.{
1813 .name = "resource",
1814 .syntax = .separate,
1815 .zig_equivalent = .other,
1816 .pd1 = false,
1817 .pd2 = true,
1818 .psl = false,
1819},
1820.{
1821 .name = "rtlib",
1822 .syntax = .separate,
1823 .zig_equivalent = .other,
1824 .pd1 = false,
1825 .pd2 = true,
1826 .psl = false,
1827},
1828.{
1829 .name = "serialize-diagnostics",
1830 .syntax = .separate,
1831 .zig_equivalent = .other,
1832 .pd1 = true,
1833 .pd2 = true,
1834 .psl = false,
1835},
1836.{
1837 .name = "signed-char",
1838 .syntax = .flag,
1839 .zig_equivalent = .other,
1840 .pd1 = false,
1841 .pd2 = true,
1842 .psl = false,
1843},
1844.{
1845 .name = "std",
1846 .syntax = .separate,
1847 .zig_equivalent = .other,
1848 .pd1 = false,
1849 .pd2 = true,
1850 .psl = false,
1851},
1852.{
1853 .name = "stdlib",
1854 .syntax = .separate,
1855 .zig_equivalent = .other,
1856 .pd1 = false,
1857 .pd2 = true,
1858 .psl = false,
1859},
1860.{
1861 .name = "sysroot",
1862 .syntax = .separate,
1863 .zig_equivalent = .other,
1864 .pd1 = false,
1865 .pd2 = true,
1866 .psl = false,
1867},
1868.{
1869 .name = "target-help",
1870 .syntax = .flag,
1871 .zig_equivalent = .other,
1872 .pd1 = false,
1873 .pd2 = true,
1874 .psl = false,
1875},
1876.{
1877 .name = "trace-includes",
1878 .syntax = .flag,
1879 .zig_equivalent = .other,
1880 .pd1 = false,
1881 .pd2 = true,
1882 .psl = false,
1883},
1884.{
1885 .name = "undefine-macro",
1886 .syntax = .separate,
1887 .zig_equivalent = .other,
1888 .pd1 = false,
1889 .pd2 = true,
1890 .psl = false,
1891},
1892.{
1893 .name = "unsigned-char",
1894 .syntax = .flag,
1895 .zig_equivalent = .other,
1896 .pd1 = false,
1897 .pd2 = true,
1898 .psl = false,
1899},
1900.{
1901 .name = "user-dependencies",
1902 .syntax = .flag,
1903 .zig_equivalent = .other,
1904 .pd1 = false,
1905 .pd2 = true,
1906 .psl = false,
1907},
1908.{
1909 .name = "verbose",
1910 .syntax = .flag,
1911 .zig_equivalent = .other,
1912 .pd1 = false,
1913 .pd2 = true,
1914 .psl = false,
1915},
1916.{
1917 .name = "version",
1918 .syntax = .flag,
1919 .zig_equivalent = .other,
1920 .pd1 = false,
1921 .pd2 = true,
1922 .psl = false,
1923},
1924.{
1925 .name = "write-dependencies",
1926 .syntax = .flag,
1927 .zig_equivalent = .other,
1928 .pd1 = false,
1929 .pd2 = true,
1930 .psl = false,
1931},
1932.{
1933 .name = "write-user-dependencies",
1934 .syntax = .flag,
1935 .zig_equivalent = .other,
1936 .pd1 = false,
1937 .pd2 = true,
1938 .psl = false,
1939},
1940sepd1("add-plugin"),
1941flagpd1("faggressive-function-elimination"),
1942flagpd1("fno-aggressive-function-elimination"),
1943flagpd1("falign-commons"),
1944flagpd1("fno-align-commons"),
1945flagpd1("falign-jumps"),
1946flagpd1("fno-align-jumps"),
1947flagpd1("falign-labels"),
1948flagpd1("fno-align-labels"),
1949flagpd1("falign-loops"),
1950flagpd1("fno-align-loops"),
1951flagpd1("faligned-alloc-unavailable"),
1952flagpd1("all_load"),
1953flagpd1("fall-intrinsics"),
1954flagpd1("fno-all-intrinsics"),
1955sepd1("allowable_client"),
1956flagpd1("cfg-add-implicit-dtors"),
1957flagpd1("unoptimized-cfg"),
1958flagpd1("analyze"),
1959sepd1("analyze-function"),
1960sepd1("analyzer-checker"),
1961flagpd1("analyzer-checker-help"),
1962flagpd1("analyzer-checker-help-alpha"),
1963flagpd1("analyzer-checker-help-developer"),
1964flagpd1("analyzer-checker-option-help"),
1965flagpd1("analyzer-checker-option-help-alpha"),
1966flagpd1("analyzer-checker-option-help-developer"),
1967sepd1("analyzer-config"),
1968sepd1("analyzer-config-compatibility-mode"),
1969flagpd1("analyzer-config-help"),
1970sepd1("analyzer-constraints"),
1971flagpd1("analyzer-disable-all-checks"),
1972sepd1("analyzer-disable-checker"),
1973flagpd1("analyzer-disable-retry-exhausted"),
1974flagpd1("analyzer-display-progress"),
1975sepd1("analyzer-dump-egraph"),
1976sepd1("analyzer-inline-max-stack-depth"),
1977sepd1("analyzer-inlining-mode"),
1978flagpd1("analyzer-list-enabled-checkers"),
1979sepd1("analyzer-max-loop"),
1980flagpd1("analyzer-opt-analyze-headers"),
1981flagpd1("analyzer-opt-analyze-nested-blocks"),
1982sepd1("analyzer-output"),
1983sepd1("analyzer-purge"),
1984flagpd1("analyzer-stats"),
1985sepd1("analyzer-store"),
1986flagpd1("analyzer-viz-egraph-graphviz"),
1987flagpd1("analyzer-werror"),
1988flagpd1("fslp-vectorize-aggressive"),
1989flagpd1("fno-slp-vectorize-aggressive"),
1990flagpd1("fexpensive-optimizations"),
1991flagpd1("fno-expensive-optimizations"),
1992flagpd1("fdefer-pop"),
1993flagpd1("fno-defer-pop"),
1994flagpd1("fextended-identifiers"),
1995flagpd1("fno-extended-identifiers"),
1996flagpd1("fhonor-infinites"),
1997flagpd1("fno-honor-infinites"),
1998flagpd1("findirect-virtual-calls"),
1999sepd1("fnew-alignment"),
2000flagpd1("faligned-new"),
2001flagpd1("fno-aligned-new"),
2002flagpd1("fsched-interblock"),
2003flagpd1("ftree-vectorize"),
2004flagpd1("fno-tree-vectorize"),
2005flagpd1("ftree-slp-vectorize"),
2006flagpd1("fno-tree-slp-vectorize"),
2007flagpd1("fterminated-vtables"),
2008flagpd1("grecord-gcc-switches"),
2009flagpd1("gno-record-gcc-switches"),
2010flagpd1("fident"),
2011flagpd1("nocudalib"),
2012.{
2013 .name = "system-header-prefix",
2014 .syntax = .separate,
2015 .zig_equivalent = .other,
2016 .pd1 = false,
2017 .pd2 = true,
2018 .psl = false,
2019},
2020.{
2021 .name = "no-system-header-prefix",
2022 .syntax = .separate,
2023 .zig_equivalent = .other,
2024 .pd1 = false,
2025 .pd2 = true,
2026 .psl = false,
2027},
2028flagpd1("integrated-as"),
2029flagpd1("no-integrated-as"),
2030flagpd1("fkeep-inline-functions"),
2031flagpd1("fno-keep-inline-functions"),
2032flagpd1("fno-semantic-interposition"),
2033.{
2034 .name = "Gs",
2035 .syntax = .flag,
2036 .zig_equivalent = .other,
2037 .pd1 = true,
2038 .pd2 = false,
2039 .psl = true,
2040},
2041.{
2042 .name = "O1",
2043 .syntax = .flag,
2044 .zig_equivalent = .optimize,
2045 .pd1 = true,
2046 .pd2 = false,
2047 .psl = true,
2048},
2049.{
2050 .name = "O2",
2051 .syntax = .flag,
2052 .zig_equivalent = .optimize,
2053 .pd1 = true,
2054 .pd2 = false,
2055 .psl = true,
2056},
2057flagpd1("fno-ident"),
2058.{
2059 .name = "Ob0",
2060 .syntax = .flag,
2061 .zig_equivalent = .other,
2062 .pd1 = true,
2063 .pd2 = false,
2064 .psl = true,
2065},
2066.{
2067 .name = "Ob1",
2068 .syntax = .flag,
2069 .zig_equivalent = .other,
2070 .pd1 = true,
2071 .pd2 = false,
2072 .psl = true,
2073},
2074.{
2075 .name = "Ob2",
2076 .syntax = .flag,
2077 .zig_equivalent = .other,
2078 .pd1 = true,
2079 .pd2 = false,
2080 .psl = true,
2081},
2082.{
2083 .name = "Od",
2084 .syntax = .flag,
2085 .zig_equivalent = .other,
2086 .pd1 = true,
2087 .pd2 = false,
2088 .psl = true,
2089},
2090.{
2091 .name = "Og",
2092 .syntax = .flag,
2093 .zig_equivalent = .optimize,
2094 .pd1 = true,
2095 .pd2 = false,
2096 .psl = true,
2097},
2098.{
2099 .name = "Oi",
2100 .syntax = .flag,
2101 .zig_equivalent = .other,
2102 .pd1 = true,
2103 .pd2 = false,
2104 .psl = true,
2105},
2106.{
2107 .name = "Oi-",
2108 .syntax = .flag,
2109 .zig_equivalent = .other,
2110 .pd1 = true,
2111 .pd2 = false,
2112 .psl = true,
2113},
2114.{
2115 .name = "Os",
2116 .syntax = .flag,
2117 .zig_equivalent = .other,
2118 .pd1 = true,
2119 .pd2 = false,
2120 .psl = true,
2121},
2122.{
2123 .name = "Ot",
2124 .syntax = .flag,
2125 .zig_equivalent = .other,
2126 .pd1 = true,
2127 .pd2 = false,
2128 .psl = true,
2129},
2130.{
2131 .name = "Ox",
2132 .syntax = .flag,
2133 .zig_equivalent = .other,
2134 .pd1 = true,
2135 .pd2 = false,
2136 .psl = true,
2137},
2138flagpd1("fcuda-rdc"),
2139.{
2140 .name = "Oy",
2141 .syntax = .flag,
2142 .zig_equivalent = .other,
2143 .pd1 = true,
2144 .pd2 = false,
2145 .psl = true,
2146},
2147.{
2148 .name = "Oy-",
2149 .syntax = .flag,
2150 .zig_equivalent = .other,
2151 .pd1 = true,
2152 .pd2 = false,
2153 .psl = true,
2154},
2155flagpd1("fno-cuda-rdc"),
2156flagpd1("shared-libasan"),
2157flagpd1("frecord-gcc-switches"),
2158flagpd1("fno-record-gcc-switches"),
2159.{
2160 .name = "ansi",
2161 .syntax = .flag,
2162 .zig_equivalent = .other,
2163 .pd1 = true,
2164 .pd2 = true,
2165 .psl = false,
2166},
2167sepd1("arch"),
2168flagpd1("arch_errors_fatal"),
2169sepd1("arch_only"),
2170flagpd1("arcmt-check"),
2171flagpd1("arcmt-migrate"),
2172flagpd1("arcmt-migrate-emit-errors"),
2173sepd1("arcmt-migrate-report-output"),
2174flagpd1("arcmt-modify"),
2175flagpd1("ast-dump"),
2176flagpd1("ast-dump-all"),
2177sepd1("ast-dump-filter"),
2178flagpd1("ast-dump-lookups"),
2179flagpd1("ast-list"),
2180sepd1("ast-merge"),
2181flagpd1("ast-print"),
2182flagpd1("ast-view"),
2183flagpd1("fautomatic"),
2184flagpd1("fno-automatic"),
2185sepd1("aux-triple"),
2186flagpd1("fbackslash"),
2187flagpd1("fno-backslash"),
2188flagpd1("fbacktrace"),
2189flagpd1("fno-backtrace"),
2190flagpd1("bind_at_load"),
2191flagpd1("fbounds-check"),
2192flagpd1("fno-bounds-check"),
2193flagpd1("fbranch-count-reg"),
2194flagpd1("fno-branch-count-reg"),
2195flagpd1("building-pch-with-obj"),
2196flagpd1("bundle"),
2197sepd1("bundle_loader"),
2198.{
2199 .name = "c",
2200 .syntax = .flag,
2201 .zig_equivalent = .c,
2202 .pd1 = true,
2203 .pd2 = false,
2204 .psl = false,
2205},
2206flagpd1("fcaller-saves"),
2207flagpd1("fno-caller-saves"),
2208flagpd1("cc1"),
2209flagpd1("cc1as"),
2210flagpd1("ccc-arcmt-check"),
2211sepd1("ccc-arcmt-migrate"),
2212flagpd1("ccc-arcmt-modify"),
2213sepd1("ccc-gcc-name"),
2214sepd1("ccc-install-dir"),
2215sepd1("ccc-objcmt-migrate"),
2216flagpd1("ccc-print-bindings"),
2217flagpd1("ccc-print-phases"),
2218flagpd1("cfguard"),
2219flagpd1("cfguard-no-checks"),
2220sepd1("chain-include"),
2221flagpd1("fcheck-array-temporaries"),
2222flagpd1("fno-check-array-temporaries"),
2223flagpd1("cl-denorms-are-zero"),
2224flagpd1("cl-fast-relaxed-math"),
2225flagpd1("cl-finite-math-only"),
2226flagpd1("cl-fp32-correctly-rounded-divide-sqrt"),
2227flagpd1("cl-kernel-arg-info"),
2228flagpd1("cl-mad-enable"),
2229flagpd1("cl-no-signed-zeros"),
2230flagpd1("cl-opt-disable"),
2231flagpd1("cl-single-precision-constant"),
2232flagpd1("cl-strict-aliasing"),
2233flagpd1("cl-uniform-work-group-size"),
2234flagpd1("cl-unsafe-math-optimizations"),
2235sepd1("code-completion-at"),
2236flagpd1("code-completion-brief-comments"),
2237flagpd1("code-completion-macros"),
2238flagpd1("code-completion-patterns"),
2239flagpd1("code-completion-with-fixits"),
2240.{
2241 .name = "combine",
2242 .syntax = .flag,
2243 .zig_equivalent = .other,
2244 .pd1 = true,
2245 .pd2 = true,
2246 .psl = false,
2247},
2248flagpd1("compiler-options-dump"),
2249.{
2250 .name = "compress-debug-sections",
2251 .syntax = .flag,
2252 .zig_equivalent = .other,
2253 .pd1 = true,
2254 .pd2 = true,
2255 .psl = false,
2256},
2257.{
2258 .name = "config",
2259 .syntax = .separate,
2260 .zig_equivalent = .other,
2261 .pd1 = false,
2262 .pd2 = true,
2263 .psl = false,
2264},
2265.{
2266 .name = "coverage",
2267 .syntax = .flag,
2268 .zig_equivalent = .other,
2269 .pd1 = true,
2270 .pd2 = true,
2271 .psl = false,
2272},
2273flagpd1("coverage-cfg-checksum"),
2274sepd1("coverage-data-file"),
2275flagpd1("coverage-exit-block-before-body"),
2276flagpd1("coverage-no-function-names-in-data"),
2277sepd1("coverage-notes-file"),
2278flagpd1("cpp"),
2279flagpd1("cpp-precomp"),
2280flagpd1("fcray-pointer"),
2281flagpd1("fno-cray-pointer"),
2282.{
2283 .name = "cuda-compile-host-device",
2284 .syntax = .flag,
2285 .zig_equivalent = .other,
2286 .pd1 = false,
2287 .pd2 = true,
2288 .psl = false,
2289},
2290.{
2291 .name = "cuda-device-only",
2292 .syntax = .flag,
2293 .zig_equivalent = .other,
2294 .pd1 = false,
2295 .pd2 = true,
2296 .psl = false,
2297},
2298.{
2299 .name = "cuda-host-only",
2300 .syntax = .flag,
2301 .zig_equivalent = .other,
2302 .pd1 = false,
2303 .pd2 = true,
2304 .psl = false,
2305},
2306.{
2307 .name = "cuda-noopt-device-debug",
2308 .syntax = .flag,
2309 .zig_equivalent = .other,
2310 .pd1 = false,
2311 .pd2 = true,
2312 .psl = false,
2313},
2314.{
2315 .name = "cuda-path-ignore-env",
2316 .syntax = .flag,
2317 .zig_equivalent = .other,
2318 .pd1 = false,
2319 .pd2 = true,
2320 .psl = false,
2321},
2322flagpd1("dA"),
2323flagpd1("dD"),
2324flagpd1("dI"),
2325flagpd1("dM"),
2326flagpd1("d"),
2327flagpd1("fd-lines-as-code"),
2328flagpd1("fno-d-lines-as-code"),
2329flagpd1("fd-lines-as-comments"),
2330flagpd1("fno-d-lines-as-comments"),
2331flagpd1("dead_strip"),
2332flagpd1("debug-forward-template-params"),
2333flagpd1("debug-info-macro"),
2334flagpd1("fdefault-double-8"),
2335flagpd1("fno-default-double-8"),
2336sepd1("default-function-attr"),
2337flagpd1("fdefault-inline"),
2338flagpd1("fno-default-inline"),
2339flagpd1("fdefault-integer-8"),
2340flagpd1("fno-default-integer-8"),
2341flagpd1("fdefault-real-8"),
2342flagpd1("fno-default-real-8"),
2343sepd1("defsym"),
2344sepd1("dependency-dot"),
2345sepd1("dependency-file"),
2346flagpd1("detailed-preprocessing-record"),
2347flagpd1("fdevirtualize"),
2348flagpd1("fno-devirtualize"),
2349flagpd1("fdevirtualize-speculatively"),
2350flagpd1("fno-devirtualize-speculatively"),
2351sepd1("diagnostic-log-file"),
2352sepd1("serialize-diagnostic-file"),
2353flagpd1("disable-O0-optnone"),
2354flagpd1("disable-free"),
2355flagpd1("disable-lifetime-markers"),
2356flagpd1("disable-llvm-optzns"),
2357flagpd1("disable-llvm-passes"),
2358flagpd1("disable-llvm-verifier"),
2359flagpd1("disable-objc-default-synthesize-properties"),
2360flagpd1("disable-pragma-debug-crash"),
2361flagpd1("disable-red-zone"),
2362flagpd1("discard-value-names"),
2363flagpd1("fdollar-ok"),
2364flagpd1("fno-dollar-ok"),
2365flagpd1("dump-coverage-mapping"),
2366flagpd1("dump-deserialized-decls"),
2367flagpd1("fdump-fortran-optimized"),
2368flagpd1("fno-dump-fortran-optimized"),
2369flagpd1("fdump-fortran-original"),
2370flagpd1("fno-dump-fortran-original"),
2371flagpd1("fdump-parse-tree"),
2372flagpd1("fno-dump-parse-tree"),
2373flagpd1("dump-raw-tokens"),
2374flagpd1("dump-tokens"),
2375flagpd1("dumpmachine"),
2376flagpd1("dumpspecs"),
2377flagpd1("dumpversion"),
2378flagpd1("dwarf-column-info"),
2379sepd1("dwarf-debug-flags"),
2380sepd1("dwarf-debug-producer"),
2381flagpd1("dwarf-explicit-import"),
2382flagpd1("dwarf-ext-refs"),
2383sepd1("dylib_file"),
2384flagpd1("dylinker"),
2385flagpd1("dynamic"),
2386flagpd1("dynamiclib"),
2387flagpd1("feliminate-unused-debug-types"),
2388flagpd1("fno-eliminate-unused-debug-types"),
2389flagpd1("emit-ast"),
2390flagpd1("emit-codegen-only"),
2391flagpd1("emit-header-module"),
2392flagpd1("emit-html"),
2393flagpd1("emit-interface-stubs"),
2394flagpd1("emit-llvm"),
2395flagpd1("emit-llvm-bc"),
2396flagpd1("emit-llvm-only"),
2397flagpd1("emit-llvm-uselists"),
2398flagpd1("emit-merged-ifs"),
2399flagpd1("emit-module"),
2400flagpd1("emit-module-interface"),
2401flagpd1("emit-obj"),
2402flagpd1("emit-pch"),
2403flagpd1("enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang"),
2404sepd1("error-on-deserialized-decl"),
2405sepd1("exported_symbols_list"),
2406flagpd1("fexternal-blas"),
2407flagpd1("fno-external-blas"),
2408flagpd1("ff2c"),
2409flagpd1("fno-f2c"),
2410.{
2411 .name = "fPIC",
2412 .syntax = .flag,
2413 .zig_equivalent = .pic,
2414 .pd1 = true,
2415 .pd2 = false,
2416 .psl = false,
2417},
2418flagpd1("fPIE"),
2419flagpd1("faccess-control"),
2420flagpd1("faddrsig"),
2421flagpd1("falign-functions"),
2422flagpd1("faligned-allocation"),
2423flagpd1("fallow-editor-placeholders"),
2424flagpd1("fallow-half-arguments-and-returns"),
2425flagpd1("fallow-pch-with-compiler-errors"),
2426flagpd1("fallow-unsupported"),
2427flagpd1("faltivec"),
2428flagpd1("fansi-escape-codes"),
2429flagpd1("fapple-kext"),
2430flagpd1("fapple-link-rtlib"),
2431flagpd1("fapple-pragma-pack"),
2432flagpd1("fapplication-extension"),
2433flagpd1("fapply-global-visibility-to-externs"),
2434flagpd1("fasm"),
2435flagpd1("fasm-blocks"),
2436flagpd1("fassociative-math"),
2437flagpd1("fassume-sane-operator-new"),
2438flagpd1("fast"),
2439flagpd1("fastcp"),
2440flagpd1("fastf"),
2441flagpd1("fasynchronous-unwind-tables"),
2442flagpd1("ffat-lto-objects"),
2443flagpd1("fno-fat-lto-objects"),
2444flagpd1("fauto-profile"),
2445flagpd1("fauto-profile-accurate"),
2446flagpd1("fautolink"),
2447flagpd1("fblocks"),
2448flagpd1("fblocks-runtime-optional"),
2449flagpd1("fborland-extensions"),
2450sepd1("fbracket-depth"),
2451flagpd1("fbuiltin"),
2452flagpd1("fbuiltin-module-map"),
2453flagpd1("fcall-saved-x10"),
2454flagpd1("fcall-saved-x11"),
2455flagpd1("fcall-saved-x12"),
2456flagpd1("fcall-saved-x13"),
2457flagpd1("fcall-saved-x14"),
2458flagpd1("fcall-saved-x15"),
2459flagpd1("fcall-saved-x18"),
2460flagpd1("fcall-saved-x8"),
2461flagpd1("fcall-saved-x9"),
2462flagpd1("fcaret-diagnostics"),
2463sepd1("fcaret-diagnostics-max-lines"),
2464flagpd1("fcf-protection"),
2465flagpd1("fchar8_t"),
2466flagpd1("fcheck-new"),
2467flagpd1("fno-check-new"),
2468flagpd1("fcolor-diagnostics"),
2469flagpd1("fcommon"),
2470flagpd1("fcomplete-member-pointers"),
2471flagpd1("fconcepts-ts"),
2472flagpd1("fconst-strings"),
2473flagpd1("fconstant-cfstrings"),
2474sepd1("fconstant-string-class"),
2475sepd1("fconstexpr-backtrace-limit"),
2476sepd1("fconstexpr-depth"),
2477sepd1("fconstexpr-steps"),
2478flagpd1("fconvergent-functions"),
2479flagpd1("fcoroutines-ts"),
2480flagpd1("fcoverage-mapping"),
2481flagpd1("fcreate-profile"),
2482flagpd1("fcs-profile-generate"),
2483flagpd1("fcuda-allow-variadic-functions"),
2484flagpd1("fcuda-approx-transcendentals"),
2485flagpd1("fcuda-flush-denormals-to-zero"),
2486sepd1("fcuda-include-gpubinary"),
2487flagpd1("fcuda-is-device"),
2488flagpd1("fcuda-short-ptr"),
2489flagpd1("fcxx-exceptions"),
2490flagpd1("fcxx-modules"),
2491flagpd1("fc++-static-destructors"),
2492flagpd1("fdata-sections"),
2493sepd1("fdebug-compilation-dir"),
2494flagpd1("fdebug-info-for-profiling"),
2495flagpd1("fdebug-macro"),
2496flagpd1("fdebug-pass-arguments"),
2497flagpd1("fdebug-pass-manager"),
2498flagpd1("fdebug-pass-structure"),
2499flagpd1("fdebug-ranges-base-address"),
2500flagpd1("fdebug-types-section"),
2501flagpd1("fdebugger-cast-result-to-id"),
2502flagpd1("fdebugger-objc-literal"),
2503flagpd1("fdebugger-support"),
2504flagpd1("fdeclare-opencl-builtins"),
2505flagpd1("fdeclspec"),
2506flagpd1("fdelayed-template-parsing"),
2507flagpd1("fdelete-null-pointer-checks"),
2508flagpd1("fdeprecated-macro"),
2509flagpd1("fdiagnostics-absolute-paths"),
2510flagpd1("fdiagnostics-color"),
2511flagpd1("fdiagnostics-fixit-info"),
2512sepd1("fdiagnostics-format"),
2513flagpd1("fdiagnostics-parseable-fixits"),
2514flagpd1("fdiagnostics-print-source-range-info"),
2515sepd1("fdiagnostics-show-category"),
2516flagpd1("fdiagnostics-show-hotness"),
2517flagpd1("fdiagnostics-show-note-include-stack"),
2518flagpd1("fdiagnostics-show-option"),
2519flagpd1("fdiagnostics-show-template-tree"),
2520flagpd1("fdigraphs"),
2521flagpd1("fdisable-module-hash"),
2522flagpd1("fdiscard-value-names"),
2523flagpd1("fdollars-in-identifiers"),
2524flagpd1("fdouble-square-bracket-attributes"),
2525flagpd1("fdump-record-layouts"),
2526flagpd1("fdump-record-layouts-simple"),
2527flagpd1("fdump-vtable-layouts"),
2528flagpd1("fdwarf2-cfi-asm"),
2529flagpd1("fdwarf-directory-asm"),
2530flagpd1("fdwarf-exceptions"),
2531flagpd1("felide-constructors"),
2532flagpd1("feliminate-unused-debug-symbols"),
2533flagpd1("fembed-bitcode"),
2534flagpd1("fembed-bitcode-marker"),
2535flagpd1("femit-all-decls"),
2536flagpd1("femit-coverage-data"),
2537flagpd1("femit-coverage-notes"),
2538flagpd1("femit-debug-entry-values"),
2539flagpd1("femulated-tls"),
2540flagpd1("fencode-extended-block-signature"),
2541sepd1("ferror-limit"),
2542flagpd1("fescaping-block-tail-calls"),
2543flagpd1("fexceptions"),
2544flagpd1("fexperimental-isel"),
2545flagpd1("fexperimental-new-constant-interpreter"),
2546flagpd1("fexperimental-new-pass-manager"),
2547flagpd1("fexternc-nounwind"),
2548flagpd1("ffake-address-space-map"),
2549flagpd1("ffast-math"),
2550flagpd1("ffine-grained-bitfield-accesses"),
2551flagpd1("ffinite-math-only"),
2552flagpd1("ffixed-point"),
2553flagpd1("ffixed-r19"),
2554flagpd1("ffixed-r9"),
2555flagpd1("ffixed-x1"),
2556flagpd1("ffixed-x10"),
2557flagpd1("ffixed-x11"),
2558flagpd1("ffixed-x12"),
2559flagpd1("ffixed-x13"),
2560flagpd1("ffixed-x14"),
2561flagpd1("ffixed-x15"),
2562flagpd1("ffixed-x16"),
2563flagpd1("ffixed-x17"),
2564flagpd1("ffixed-x18"),
2565flagpd1("ffixed-x19"),
2566flagpd1("ffixed-x2"),
2567flagpd1("ffixed-x20"),
2568flagpd1("ffixed-x21"),
2569flagpd1("ffixed-x22"),
2570flagpd1("ffixed-x23"),
2571flagpd1("ffixed-x24"),
2572flagpd1("ffixed-x25"),
2573flagpd1("ffixed-x26"),
2574flagpd1("ffixed-x27"),
2575flagpd1("ffixed-x28"),
2576flagpd1("ffixed-x29"),
2577flagpd1("ffixed-x3"),
2578flagpd1("ffixed-x30"),
2579flagpd1("ffixed-x31"),
2580flagpd1("ffixed-x4"),
2581flagpd1("ffixed-x5"),
2582flagpd1("ffixed-x6"),
2583flagpd1("ffixed-x7"),
2584flagpd1("ffixed-x8"),
2585flagpd1("ffixed-x9"),
2586flagpd1("ffor-scope"),
2587flagpd1("fforbid-guard-variables"),
2588flagpd1("fforce-dwarf-frame"),
2589flagpd1("fforce-emit-vtables"),
2590flagpd1("fforce-enable-int128"),
2591flagpd1("ffreestanding"),
2592flagpd1("ffunction-sections"),
2593flagpd1("fgnu89-inline"),
2594flagpd1("fgnu-inline-asm"),
2595flagpd1("fgnu-keywords"),
2596flagpd1("fgnu-runtime"),
2597flagpd1("fgpu-allow-device-init"),
2598flagpd1("fgpu-rdc"),
2599flagpd1("fheinous-gnu-extensions"),
2600flagpd1("fhip-dump-offload-linker-script"),
2601flagpd1("fhip-new-launch-api"),
2602flagpd1("fhonor-infinities"),
2603flagpd1("fhonor-nans"),
2604flagpd1("fhosted"),
2605sepd1("filelist"),
2606sepd1("filetype"),
2607flagpd1("fimplicit-module-maps"),
2608flagpd1("fimplicit-modules"),
2609flagpd1("finclude-default-header"),
2610flagpd1("finline"),
2611flagpd1("finline-functions"),
2612flagpd1("finline-hint-functions"),
2613flagpd1("finline-limit"),
2614flagpd1("fno-inline-limit"),
2615flagpd1("finstrument-function-entry-bare"),
2616flagpd1("finstrument-functions"),
2617flagpd1("finstrument-functions-after-inlining"),
2618flagpd1("fintegrated-as"),
2619flagpd1("fintegrated-cc1"),
2620flagpd1("fix-only-warnings"),
2621flagpd1("fix-what-you-can"),
2622flagpd1("ffixed-form"),
2623flagpd1("fno-fixed-form"),
2624flagpd1("fixit"),
2625flagpd1("fixit-recompile"),
2626flagpd1("fixit-to-temporary"),
2627flagpd1("fjump-tables"),
2628flagpd1("fkeep-static-consts"),
2629flagpd1("flat_namespace"),
2630flagpd1("flax-vector-conversions"),
2631flagpd1("flimit-debug-info"),
2632flagpd1("ffloat-store"),
2633flagpd1("fno-float-store"),
2634flagpd1("flto"),
2635flagpd1("flto-unit"),
2636flagpd1("flto-visibility-public-std"),
2637sepd1("fmacro-backtrace-limit"),
2638flagpd1("fmath-errno"),
2639flagpd1("fmerge-all-constants"),
2640flagpd1("fmerge-functions"),
2641sepd1("fmessage-length"),
2642sepd1("fmodule-feature"),
2643flagpd1("fmodule-file-deps"),
2644sepd1("fmodule-implementation-of"),
2645flagpd1("fmodule-map-file-home-is-cwd"),
2646flagpd1("fmodule-maps"),
2647sepd1("fmodule-name"),
2648flagpd1("fmodules"),
2649flagpd1("fmodules-codegen"),
2650flagpd1("fmodules-debuginfo"),
2651flagpd1("fmodules-decluse"),
2652flagpd1("fmodules-disable-diagnostic-validation"),
2653flagpd1("fmodules-hash-content"),
2654flagpd1("fmodules-local-submodule-visibility"),
2655flagpd1("fmodules-search-all"),
2656flagpd1("fmodules-strict-context-hash"),
2657flagpd1("fmodules-strict-decluse"),
2658flagpd1("fmodules-ts"),
2659sepd1("fmodules-user-build-path"),
2660flagpd1("fmodules-validate-input-files-content"),
2661flagpd1("fmodules-validate-once-per-build-session"),
2662flagpd1("fmodules-validate-system-headers"),
2663flagpd1("fms-compatibility"),
2664flagpd1("fms-extensions"),
2665flagpd1("fms-volatile"),
2666flagpd1("fmudflap"),
2667flagpd1("fmudflapth"),
2668flagpd1("fnative-half-arguments-and-returns"),
2669flagpd1("fnative-half-type"),
2670flagpd1("fnested-functions"),
2671flagpd1("fnext-runtime"),
2672.{
2673 .name = "fno-PIC",
2674 .syntax = .flag,
2675 .zig_equivalent = .no_pic,
2676 .pd1 = true,
2677 .pd2 = false,
2678 .psl = false,
2679},
2680flagpd1("fno-PIE"),
2681flagpd1("fno-access-control"),
2682flagpd1("fno-addrsig"),
2683flagpd1("fno-align-functions"),
2684flagpd1("fno-aligned-allocation"),
2685flagpd1("fno-allow-editor-placeholders"),
2686flagpd1("fno-altivec"),
2687flagpd1("fno-apple-pragma-pack"),
2688flagpd1("fno-application-extension"),
2689flagpd1("fno-asm"),
2690flagpd1("fno-asm-blocks"),
2691flagpd1("fno-associative-math"),
2692flagpd1("fno-assume-sane-operator-new"),
2693flagpd1("fno-asynchronous-unwind-tables"),
2694flagpd1("fno-auto-profile"),
2695flagpd1("fno-auto-profile-accurate"),
2696flagpd1("fno-autolink"),
2697flagpd1("fno-bitfield-type-align"),
2698flagpd1("fno-blocks"),
2699flagpd1("fno-borland-extensions"),
2700flagpd1("fno-builtin"),
2701flagpd1("fno-caret-diagnostics"),
2702flagpd1("fno-char8_t"),
2703flagpd1("fno-color-diagnostics"),
2704flagpd1("fno-common"),
2705flagpd1("fno-complete-member-pointers"),
2706flagpd1("fno-concept-satisfaction-caching"),
2707flagpd1("fno-const-strings"),
2708flagpd1("fno-constant-cfstrings"),
2709flagpd1("fno-coroutines-ts"),
2710flagpd1("fno-coverage-mapping"),
2711flagpd1("fno-crash-diagnostics"),
2712flagpd1("fno-cuda-approx-transcendentals"),
2713flagpd1("fno-cuda-flush-denormals-to-zero"),
2714flagpd1("fno-cuda-host-device-constexpr"),
2715flagpd1("fno-cuda-short-ptr"),
2716flagpd1("fno-cxx-exceptions"),
2717flagpd1("fno-cxx-modules"),
2718flagpd1("fno-c++-static-destructors"),
2719flagpd1("fno-data-sections"),
2720flagpd1("fno-debug-info-for-profiling"),
2721flagpd1("fno-debug-macro"),
2722flagpd1("fno-debug-pass-manager"),
2723flagpd1("fno-debug-ranges-base-address"),
2724flagpd1("fno-debug-types-section"),
2725flagpd1("fno-declspec"),
2726flagpd1("fno-delayed-template-parsing"),
2727flagpd1("fno-delete-null-pointer-checks"),
2728flagpd1("fno-deprecated-macro"),
2729flagpd1("fno-diagnostics-color"),
2730flagpd1("fno-diagnostics-fixit-info"),
2731flagpd1("fno-diagnostics-show-hotness"),
2732flagpd1("fno-diagnostics-show-note-include-stack"),
2733flagpd1("fno-diagnostics-show-option"),
2734flagpd1("fno-diagnostics-use-presumed-location"),
2735flagpd1("fno-digraphs"),
2736flagpd1("fno-discard-value-names"),
2737flagpd1("fno-dllexport-inlines"),
2738flagpd1("fno-dollars-in-identifiers"),
2739flagpd1("fno-double-square-bracket-attributes"),
2740flagpd1("fno-dwarf2-cfi-asm"),
2741flagpd1("fno-dwarf-directory-asm"),
2742flagpd1("fno-elide-constructors"),
2743flagpd1("fno-elide-type"),
2744flagpd1("fno-eliminate-unused-debug-symbols"),
2745flagpd1("fno-emulated-tls"),
2746flagpd1("fno-escaping-block-tail-calls"),
2747flagpd1("fno-exceptions"),
2748flagpd1("fno-experimental-isel"),
2749flagpd1("fno-experimental-new-pass-manager"),
2750flagpd1("fno-fast-math"),
2751flagpd1("fno-fine-grained-bitfield-accesses"),
2752flagpd1("fno-finite-math-only"),
2753flagpd1("fno-fixed-point"),
2754flagpd1("fno-for-scope"),
2755flagpd1("fno-force-dwarf-frame"),
2756flagpd1("fno-force-emit-vtables"),
2757flagpd1("fno-force-enable-int128"),
2758flagpd1("fno-function-sections"),
2759flagpd1("fno-gnu89-inline"),
2760flagpd1("fno-gnu-inline-asm"),
2761flagpd1("fno-gnu-keywords"),
2762flagpd1("fno-gpu-allow-device-init"),
2763flagpd1("fno-gpu-rdc"),
2764flagpd1("fno-hip-new-launch-api"),
2765flagpd1("fno-honor-infinities"),
2766flagpd1("fno-honor-nans"),
2767flagpd1("fno-implicit-module-maps"),
2768flagpd1("fno-implicit-modules"),
2769flagpd1("fno-inline"),
2770flagpd1("fno-inline-functions"),
2771flagpd1("fno-integrated-as"),
2772flagpd1("fno-integrated-cc1"),
2773flagpd1("fno-jump-tables"),
2774flagpd1("fno-lax-vector-conversions"),
2775flagpd1("fno-limit-debug-info"),
2776flagpd1("fno-lto"),
2777flagpd1("fno-lto-unit"),
2778flagpd1("fno-math-builtin"),
2779flagpd1("fno-math-errno"),
2780flagpd1("fno-max-type-align"),
2781flagpd1("fno-merge-all-constants"),
2782flagpd1("fno-module-file-deps"),
2783flagpd1("fno-module-maps"),
2784flagpd1("fno-modules"),
2785flagpd1("fno-modules-decluse"),
2786flagpd1("fno-modules-error-recovery"),
2787flagpd1("fno-modules-global-index"),
2788flagpd1("fno-modules-search-all"),
2789flagpd1("fno-strict-modules-decluse"),
2790flagpd1("fno_modules-validate-input-files-content"),
2791flagpd1("fno-modules-validate-system-headers"),
2792flagpd1("fno-ms-compatibility"),
2793flagpd1("fno-ms-extensions"),
2794flagpd1("fno-objc-arc"),
2795flagpd1("fno-objc-arc-exceptions"),
2796flagpd1("fno-objc-convert-messages-to-runtime-calls"),
2797flagpd1("fno-objc-exceptions"),
2798flagpd1("fno-objc-infer-related-result-type"),
2799flagpd1("fno-objc-legacy-dispatch"),
2800flagpd1("fno-objc-nonfragile-abi"),
2801flagpd1("fno-objc-weak"),
2802flagpd1("fno-omit-frame-pointer"),
2803flagpd1("fno-openmp"),
2804flagpd1("fno-openmp-cuda-force-full-runtime"),
2805flagpd1("fno-openmp-cuda-mode"),
2806flagpd1("fno-openmp-optimistic-collapse"),
2807flagpd1("fno-openmp-simd"),
2808flagpd1("fno-operator-names"),
2809flagpd1("fno-optimize-sibling-calls"),
2810flagpd1("fno-pack-struct"),
2811flagpd1("fno-padding-on-unsigned-fixed-point"),
2812flagpd1("fno-pascal-strings"),
2813flagpd1("fno-pch-timestamp"),
2814flagpd1("fno_pch-validate-input-files-content"),
2815flagpd1("fno-pic"),
2816flagpd1("fno-pie"),
2817flagpd1("fno-plt"),
2818flagpd1("fno-preserve-as-comments"),
2819flagpd1("fno-profile-arcs"),
2820flagpd1("fno-profile-generate"),
2821flagpd1("fno-profile-instr-generate"),
2822flagpd1("fno-profile-instr-use"),
2823flagpd1("fno-profile-sample-accurate"),
2824flagpd1("fno-profile-sample-use"),
2825flagpd1("fno-profile-use"),
2826flagpd1("fno-reciprocal-math"),
2827flagpd1("fno-record-command-line"),
2828flagpd1("fno-register-global-dtors-with-atexit"),
2829flagpd1("fno-relaxed-template-template-args"),
2830flagpd1("fno-reroll-loops"),
2831flagpd1("fno-rewrite-imports"),
2832flagpd1("fno-rewrite-includes"),
2833flagpd1("fno-ropi"),
2834flagpd1("fno-rounding-math"),
2835flagpd1("fno-rtlib-add-rpath"),
2836flagpd1("fno-rtti"),
2837flagpd1("fno-rtti-data"),
2838flagpd1("fno-rwpi"),
2839flagpd1("fno-sanitize-address-poison-custom-array-cookie"),
2840flagpd1("fno-sanitize-address-use-after-scope"),
2841flagpd1("fno-sanitize-address-use-odr-indicator"),
2842flagpd1("fno-sanitize-blacklist"),
2843flagpd1("fno-sanitize-cfi-canonical-jump-tables"),
2844flagpd1("fno-sanitize-cfi-cross-dso"),
2845flagpd1("fno-sanitize-link-c++-runtime"),
2846flagpd1("fno-sanitize-link-runtime"),
2847flagpd1("fno-sanitize-memory-track-origins"),
2848flagpd1("fno-sanitize-memory-use-after-dtor"),
2849flagpd1("fno-sanitize-minimal-runtime"),
2850flagpd1("fno-sanitize-recover"),
2851flagpd1("fno-sanitize-stats"),
2852flagpd1("fno-sanitize-thread-atomics"),
2853flagpd1("fno-sanitize-thread-func-entry-exit"),
2854flagpd1("fno-sanitize-thread-memory-access"),
2855flagpd1("fno-sanitize-undefined-trap-on-error"),
2856flagpd1("fno-save-optimization-record"),
2857flagpd1("fno-short-enums"),
2858flagpd1("fno-short-wchar"),
2859flagpd1("fno-show-column"),
2860flagpd1("fno-show-source-location"),
2861flagpd1("fno-signaling-math"),
2862flagpd1("fno-signed-char"),
2863flagpd1("fno-signed-wchar"),
2864flagpd1("fno-signed-zeros"),
2865flagpd1("fno-sized-deallocation"),
2866flagpd1("fno-slp-vectorize"),
2867flagpd1("fno-spell-checking"),
2868flagpd1("fno-split-dwarf-inlining"),
2869flagpd1("fno-split-lto-unit"),
2870flagpd1("fno-stack-protector"),
2871flagpd1("fno-stack-size-section"),
2872flagpd1("fno-standalone-debug"),
2873flagpd1("fno-strict-aliasing"),
2874flagpd1("fno-strict-enums"),
2875flagpd1("fno-strict-float-cast-overflow"),
2876flagpd1("fno-strict-overflow"),
2877flagpd1("fno-strict-return"),
2878flagpd1("fno-strict-vtable-pointers"),
2879flagpd1("fno-struct-path-tbaa"),
2880flagpd1("fno-temp-file"),
2881flagpd1("fno-threadsafe-statics"),
2882flagpd1("fno-trapping-math"),
2883flagpd1("fno-trigraphs"),
2884flagpd1("fno-unique-section-names"),
2885flagpd1("fno-unit-at-a-time"),
2886flagpd1("fno-unroll-loops"),
2887flagpd1("fno-unsafe-math-optimizations"),
2888flagpd1("fno-unsigned-char"),
2889flagpd1("fno-unwind-tables"),
2890flagpd1("fno-use-cxa-atexit"),
2891flagpd1("fno-use-init-array"),
2892flagpd1("fno-use-line-directives"),
2893flagpd1("fno-validate-pch"),
2894flagpd1("fno-var-tracking"),
2895flagpd1("fno-vectorize"),
2896flagpd1("fno-verbose-asm"),
2897flagpd1("fno-virtual-function_elimination"),
2898flagpd1("fno-wchar"),
2899flagpd1("fno-whole-program-vtables"),
2900flagpd1("fno-working-directory"),
2901flagpd1("fno-wrapv"),
2902flagpd1("fno-zero-initialized-in-bss"),
2903flagpd1("fno-zvector"),
2904flagpd1("fnoopenmp-relocatable-target"),
2905flagpd1("fnoopenmp-use-tls"),
2906flagpd1("fno-xray-always-emit-customevents"),
2907flagpd1("fno-xray-always-emit-typedevents"),
2908flagpd1("fno-xray-instrument"),
2909flagpd1("fnoxray-link-deps"),
2910flagpd1("fobjc-arc"),
2911flagpd1("fobjc-arc-exceptions"),
2912flagpd1("fobjc-atdefs"),
2913flagpd1("fobjc-call-cxx-cdtors"),
2914flagpd1("fobjc-convert-messages-to-runtime-calls"),
2915flagpd1("fobjc-exceptions"),
2916flagpd1("fobjc-gc"),
2917flagpd1("fobjc-gc-only"),
2918flagpd1("fobjc-infer-related-result-type"),
2919flagpd1("fobjc-legacy-dispatch"),
2920flagpd1("fobjc-link-runtime"),
2921flagpd1("fobjc-new-property"),
2922flagpd1("fobjc-nonfragile-abi"),
2923flagpd1("fobjc-runtime-has-weak"),
2924flagpd1("fobjc-sender-dependent-dispatch"),
2925flagpd1("fobjc-subscripting-legacy-runtime"),
2926flagpd1("fobjc-weak"),
2927flagpd1("fomit-frame-pointer"),
2928flagpd1("fopenmp"),
2929flagpd1("fopenmp-cuda-force-full-runtime"),
2930flagpd1("fopenmp-cuda-mode"),
2931flagpd1("fopenmp-enable-irbuilder"),
2932sepd1("fopenmp-host-ir-file-path"),
2933flagpd1("fopenmp-is-device"),
2934flagpd1("fopenmp-optimistic-collapse"),
2935flagpd1("fopenmp-relocatable-target"),
2936flagpd1("fopenmp-simd"),
2937flagpd1("fopenmp-use-tls"),
2938sepd1("foperator-arrow-depth"),
2939flagpd1("foptimize-sibling-calls"),
2940flagpd1("force_cpusubtype_ALL"),
2941flagpd1("force_flat_namespace"),
2942sepd1("force_load"),
2943flagpd1("forder-file-instrumentation"),
2944flagpd1("fpack-struct"),
2945flagpd1("fpadding-on-unsigned-fixed-point"),
2946flagpd1("fparse-all-comments"),
2947flagpd1("fpascal-strings"),
2948flagpd1("fpcc-struct-return"),
2949flagpd1("fpch-preprocess"),
2950flagpd1("fpch-validate-input-files-content"),
2951flagpd1("fpic"),
2952flagpd1("fpie"),
2953flagpd1("fplt"),
2954flagpd1("fpreserve-as-comments"),
2955flagpd1("fpreserve-vec3-type"),
2956flagpd1("fprofile-arcs"),
2957flagpd1("fprofile-generate"),
2958flagpd1("fprofile-instr-generate"),
2959flagpd1("fprofile-instr-use"),
2960sepd1("fprofile-remapping-file"),
2961flagpd1("fprofile-sample-accurate"),
2962flagpd1("fprofile-sample-use"),
2963flagpd1("fprofile-use"),
2964sepd1("framework"),
2965flagpd1("freciprocal-math"),
2966flagpd1("frecord-command-line"),
2967flagpd1("ffree-form"),
2968flagpd1("fno-free-form"),
2969flagpd1("freg-struct-return"),
2970flagpd1("fregister-global-dtors-with-atexit"),
2971flagpd1("frelaxed-template-template-args"),
2972flagpd1("freroll-loops"),
2973flagpd1("fretain-comments-from-system-headers"),
2974flagpd1("frewrite-imports"),
2975flagpd1("frewrite-includes"),
2976sepd1("frewrite-map-file"),
2977flagpd1("ffriend-injection"),
2978flagpd1("fno-friend-injection"),
2979flagpd1("ffrontend-optimize"),
2980flagpd1("fno-frontend-optimize"),
2981flagpd1("fropi"),
2982flagpd1("frounding-math"),
2983flagpd1("frtlib-add-rpath"),
2984flagpd1("frtti"),
2985flagpd1("frwpi"),
2986flagpd1("fsanitize-address-globals-dead-stripping"),
2987flagpd1("fsanitize-address-poison-custom-array-cookie"),
2988flagpd1("fsanitize-address-use-after-scope"),
2989flagpd1("fsanitize-address-use-odr-indicator"),
2990flagpd1("fsanitize-cfi-canonical-jump-tables"),
2991flagpd1("fsanitize-cfi-cross-dso"),
2992flagpd1("fsanitize-cfi-icall-generalize-pointers"),
2993flagpd1("fsanitize-coverage-8bit-counters"),
2994flagpd1("fsanitize-coverage-indirect-calls"),
2995flagpd1("fsanitize-coverage-inline-8bit-counters"),
2996flagpd1("fsanitize-coverage-no-prune"),
2997flagpd1("fsanitize-coverage-pc-table"),
2998flagpd1("fsanitize-coverage-stack-depth"),
2999flagpd1("fsanitize-coverage-trace-bb"),
3000flagpd1("fsanitize-coverage-trace-cmp"),
3001flagpd1("fsanitize-coverage-trace-div"),
3002flagpd1("fsanitize-coverage-trace-gep"),
3003flagpd1("fsanitize-coverage-trace-pc"),
3004flagpd1("fsanitize-coverage-trace-pc-guard"),
3005flagpd1("fsanitize-link-c++-runtime"),
3006flagpd1("fsanitize-link-runtime"),
3007flagpd1("fsanitize-memory-track-origins"),
3008flagpd1("fsanitize-memory-use-after-dtor"),
3009flagpd1("fsanitize-minimal-runtime"),
3010flagpd1("fsanitize-recover"),
3011flagpd1("fsanitize-stats"),
3012flagpd1("fsanitize-thread-atomics"),
3013flagpd1("fsanitize-thread-func-entry-exit"),
3014flagpd1("fsanitize-thread-memory-access"),
3015flagpd1("fsanitize-undefined-trap-on-error"),
3016flagpd1("fsave-optimization-record"),
3017flagpd1("fseh-exceptions"),
3018flagpd1("fshort-enums"),
3019flagpd1("fshort-wchar"),
3020flagpd1("fshow-column"),
3021flagpd1("fshow-source-location"),
3022flagpd1("fsignaling-math"),
3023flagpd1("fsigned-bitfields"),
3024flagpd1("fsigned-char"),
3025flagpd1("fsigned-wchar"),
3026flagpd1("fsigned-zeros"),
3027flagpd1("fsized-deallocation"),
3028flagpd1("fsjlj-exceptions"),
3029flagpd1("fslp-vectorize"),
3030flagpd1("fspell-checking"),
3031sepd1("fspell-checking-limit"),
3032flagpd1("fsplit-dwarf-inlining"),
3033flagpd1("fsplit-lto-unit"),
3034flagpd1("fsplit-stack"),
3035flagpd1("fstack-protector"),
3036flagpd1("fstack-protector-all"),
3037flagpd1("fstack-protector-strong"),
3038flagpd1("fstack-size-section"),
3039flagpd1("fstandalone-debug"),
3040flagpd1("fstrict-aliasing"),
3041flagpd1("fstrict-enums"),
3042flagpd1("fstrict-float-cast-overflow"),
3043flagpd1("fstrict-overflow"),
3044flagpd1("fstrict-return"),
3045flagpd1("fstrict-vtable-pointers"),
3046flagpd1("fstruct-path-tbaa"),
3047flagpd1("fsycl-is-device"),
3048flagpd1("fsyntax-only"),
3049sepd1("ftabstop"),
3050sepd1("ftemplate-backtrace-limit"),
3051sepd1("ftemplate-depth"),
3052flagpd1("ftest-coverage"),
3053flagpd1("fthreadsafe-statics"),
3054flagpd1("ftime-report"),
3055flagpd1("ftime-trace"),
3056flagpd1("ftrapping-math"),
3057flagpd1("ftrapv"),
3058sepd1("ftrapv-handler"),
3059flagpd1("ftrigraphs"),
3060sepd1("ftype-visibility"),
3061sepd1("function-alignment"),
3062flagpd1("ffunction-attribute-list"),
3063flagpd1("fno-function-attribute-list"),
3064flagpd1("funique-section-names"),
3065flagpd1("funit-at-a-time"),
3066flagpd1("funknown-anytype"),
3067flagpd1("funroll-loops"),
3068flagpd1("funsafe-math-optimizations"),
3069flagpd1("funsigned-bitfields"),
3070flagpd1("funsigned-char"),
3071flagpd1("funwind-tables"),
3072flagpd1("fuse-cxa-atexit"),
3073flagpd1("fuse-init-array"),
3074flagpd1("fuse-line-directives"),
3075flagpd1("fuse-register-sized-bitfield-access"),
3076flagpd1("fvalidate-ast-input-files-content"),
3077flagpd1("fvectorize"),
3078flagpd1("fverbose-asm"),
3079flagpd1("fvirtual-function-elimination"),
3080sepd1("fvisibility"),
3081flagpd1("fvisibility-global-new-delete-hidden"),
3082flagpd1("fvisibility-inlines-hidden"),
3083flagpd1("fvisibility-ms-compat"),
3084flagpd1("fwasm-exceptions"),
3085flagpd1("fwhole-program-vtables"),
3086flagpd1("fwrapv"),
3087flagpd1("fwritable-strings"),
3088flagpd1("fxray-always-emit-customevents"),
3089flagpd1("fxray-always-emit-typedevents"),
3090flagpd1("fxray-instrument"),
3091flagpd1("fxray-link-deps"),
3092flagpd1("fzero-initialized-in-bss"),
3093flagpd1("fzvector"),
3094flagpd1("g0"),
3095flagpd1("g1"),
3096flagpd1("g2"),
3097flagpd1("g3"),
3098.{
3099 .name = "g",
3100 .syntax = .flag,
3101 .zig_equivalent = .debug,
3102 .pd1 = true,
3103 .pd2 = false,
3104 .psl = false,
3105},
3106sepd1("gcc-toolchain"),
3107flagpd1("gcodeview"),
3108flagpd1("gcodeview-ghash"),
3109flagpd1("gcolumn-info"),
3110flagpd1("fgcse-after-reload"),
3111flagpd1("fno-gcse-after-reload"),
3112flagpd1("fgcse"),
3113flagpd1("fno-gcse"),
3114flagpd1("fgcse-las"),
3115flagpd1("fno-gcse-las"),
3116flagpd1("fgcse-sm"),
3117flagpd1("fno-gcse-sm"),
3118flagpd1("gdwarf"),
3119flagpd1("gdwarf-2"),
3120flagpd1("gdwarf-3"),
3121flagpd1("gdwarf-4"),
3122flagpd1("gdwarf-5"),
3123flagpd1("gdwarf-aranges"),
3124flagpd1("gembed-source"),
3125sepd1("gen-cdb-fragment-path"),
3126flagpd1("gen-reproducer"),
3127flagpd1("gfull"),
3128flagpd1("ggdb"),
3129flagpd1("ggdb0"),
3130flagpd1("ggdb1"),
3131flagpd1("ggdb2"),
3132flagpd1("ggdb3"),
3133flagpd1("ggnu-pubnames"),
3134flagpd1("ginline-line-tables"),
3135flagpd1("gline-directives-only"),
3136flagpd1("gline-tables-only"),
3137flagpd1("glldb"),
3138flagpd1("gmlt"),
3139flagpd1("gmodules"),
3140flagpd1("gno-codeview-ghash"),
3141flagpd1("gno-column-info"),
3142flagpd1("gno-embed-source"),
3143flagpd1("gno-gnu-pubnames"),
3144flagpd1("gno-inline-line-tables"),
3145flagpd1("gno-pubnames"),
3146flagpd1("gno-record-command-line"),
3147flagpd1("gno-strict-dwarf"),
3148flagpd1("fgnu"),
3149flagpd1("fno-gnu"),
3150flagpd1("gpubnames"),
3151flagpd1("grecord-command-line"),
3152flagpd1("gsce"),
3153flagpd1("gsplit-dwarf"),
3154flagpd1("gstrict-dwarf"),
3155flagpd1("gtoggle"),
3156flagpd1("gused"),
3157flagpd1("gz"),
3158sepd1("header-include-file"),
3159.{
3160 .name = "help",
3161 .syntax = .flag,
3162 .zig_equivalent = .driver_punt,
3163 .pd1 = true,
3164 .pd2 = true,
3165 .psl = false,
3166},
3167.{
3168 .name = "hip-link",
3169 .syntax = .flag,
3170 .zig_equivalent = .other,
3171 .pd1 = false,
3172 .pd2 = true,
3173 .psl = false,
3174},
3175sepd1("image_base"),
3176flagpd1("fimplement-inlines"),
3177flagpd1("fno-implement-inlines"),
3178flagpd1("fimplicit-none"),
3179flagpd1("fno-implicit-none"),
3180flagpd1("fimplicit-templates"),
3181flagpd1("fno-implicit-templates"),
3182sepd1("imultilib"),
3183sepd1("include-pch"),
3184flagpd1("index-header-map"),
3185sepd1("init"),
3186flagpd1("finit-local-zero"),
3187flagpd1("fno-init-local-zero"),
3188flagpd1("init-only"),
3189flagpd1("finline-functions-called-once"),
3190flagpd1("fno-inline-functions-called-once"),
3191flagpd1("finline-small-functions"),
3192flagpd1("fno-inline-small-functions"),
3193sepd1("install_name"),
3194flagpd1("finteger-4-integer-8"),
3195flagpd1("fno-integer-4-integer-8"),
3196flagpd1("fintrinsic-modules-path"),
3197flagpd1("fno-intrinsic-modules-path"),
3198flagpd1("fipa-cp"),
3199flagpd1("fno-ipa-cp"),
3200flagpd1("fivopts"),
3201flagpd1("fno-ivopts"),
3202flagpd1("keep_private_externs"),
3203sepd1("lazy_framework"),
3204sepd1("lazy_library"),
3205sepd1("load"),
3206flagpd1("m16"),
3207flagpd1("m32"),
3208flagpd1("m3dnow"),
3209flagpd1("m3dnowa"),
3210flagpd1("m64"),
3211flagpd1("m80387"),
3212flagpd1("mabi=ieeelongdouble"),
3213flagpd1("mabicalls"),
3214flagpd1("madx"),
3215flagpd1("maes"),
3216sepd1("main-file-name"),
3217flagpd1("malign-double"),
3218flagpd1("maltivec"),
3219flagpd1("marm"),
3220flagpd1("masm-verbose"),
3221flagpd1("massembler-fatal-warnings"),
3222flagpd1("massembler-no-warn"),
3223flagpd1("matomics"),
3224flagpd1("mavx"),
3225flagpd1("mavx2"),
3226flagpd1("mavx512bf16"),
3227flagpd1("mavx512bitalg"),
3228flagpd1("mavx512bw"),
3229flagpd1("mavx512cd"),
3230flagpd1("mavx512dq"),
3231flagpd1("mavx512er"),
3232flagpd1("mavx512f"),
3233flagpd1("mavx512ifma"),
3234flagpd1("mavx512pf"),
3235flagpd1("mavx512vbmi"),
3236flagpd1("mavx512vbmi2"),
3237flagpd1("mavx512vl"),
3238flagpd1("mavx512vnni"),
3239flagpd1("mavx512vp2intersect"),
3240flagpd1("mavx512vpopcntdq"),
3241flagpd1("fmax-identifier-length"),
3242flagpd1("fno-max-identifier-length"),
3243flagpd1("mbackchain"),
3244flagpd1("mbig-endian"),
3245flagpd1("mbmi"),
3246flagpd1("mbmi2"),
3247flagpd1("mbranch-likely"),
3248flagpd1("mbranch-target-enforce"),
3249flagpd1("mbranches-within-32B-boundaries"),
3250flagpd1("mbulk-memory"),
3251flagpd1("mcheck-zero-division"),
3252flagpd1("mcldemote"),
3253flagpd1("mclflushopt"),
3254flagpd1("mclwb"),
3255flagpd1("mclzero"),
3256flagpd1("mcmodel=medany"),
3257flagpd1("mcmodel=medlow"),
3258flagpd1("mcmpb"),
3259flagpd1("mcmse"),
3260sepd1("mcode-model"),
3261flagpd1("mcode-object-v3"),
3262flagpd1("mconstant-cfstrings"),
3263flagpd1("mconstructor-aliases"),
3264flagpd1("mcpu=?"),
3265flagpd1("mcrbits"),
3266flagpd1("mcrc"),
3267flagpd1("mcumode"),
3268flagpd1("mcx16"),
3269sepd1("mdebug-pass"),
3270flagpd1("mdirect-move"),
3271flagpd1("mdisable-tail-calls"),
3272flagpd1("mdouble-float"),
3273flagpd1("mdsp"),
3274flagpd1("mdspr2"),
3275sepd1("meabi"),
3276flagpd1("membedded-data"),
3277flagpd1("menable-no-infs"),
3278flagpd1("menable-no-nans"),
3279flagpd1("menable-unsafe-fp-math"),
3280flagpd1("menqcmd"),
3281flagpd1("fmerge-constants"),
3282flagpd1("fno-merge-constants"),
3283flagpd1("mexception-handling"),
3284flagpd1("mexecute-only"),
3285flagpd1("mextern-sdata"),
3286flagpd1("mf16c"),
3287flagpd1("mfancy-math-387"),
3288flagpd1("mfentry"),
3289flagpd1("mfix-and-continue"),
3290flagpd1("mfix-cortex-a53-835769"),
3291flagpd1("mfloat128"),
3292sepd1("mfloat-abi"),
3293flagpd1("mfma"),
3294flagpd1("mfma4"),
3295flagpd1("mfp32"),
3296flagpd1("mfp64"),
3297sepd1("mfpmath"),
3298flagpd1("mfprnd"),
3299flagpd1("mfpxx"),
3300flagpd1("mfsgsbase"),
3301flagpd1("mfxsr"),
3302flagpd1("mgeneral-regs-only"),
3303flagpd1("mgfni"),
3304flagpd1("mginv"),
3305flagpd1("mglibc"),
3306flagpd1("mglobal-merge"),
3307flagpd1("mgpopt"),
3308flagpd1("mhard-float"),
3309flagpd1("mhvx"),
3310flagpd1("mhtm"),
3311flagpd1("miamcu"),
3312flagpd1("mieee-fp"),
3313flagpd1("mieee-rnd-near"),
3314flagpd1("migrate"),
3315flagpd1("no-finalize-removal"),
3316flagpd1("no-ns-alloc-error"),
3317flagpd1("mimplicit-float"),
3318flagpd1("mincremental-linker-compatible"),
3319flagpd1("minline-all-stringops"),
3320flagpd1("minvariant-function-descriptors"),
3321flagpd1("minvpcid"),
3322flagpd1("mips1"),
3323flagpd1("mips16"),
3324flagpd1("mips2"),
3325flagpd1("mips3"),
3326flagpd1("mips32"),
3327flagpd1("mips32r2"),
3328flagpd1("mips32r3"),
3329flagpd1("mips32r5"),
3330flagpd1("mips32r6"),
3331flagpd1("mips4"),
3332flagpd1("mips5"),
3333flagpd1("mips64"),
3334flagpd1("mips64r2"),
3335flagpd1("mips64r3"),
3336flagpd1("mips64r5"),
3337flagpd1("mips64r6"),
3338flagpd1("misel"),
3339flagpd1("mkernel"),
3340flagpd1("mldc1-sdc1"),
3341sepd1("mlimit-float-precision"),
3342sepd1("mlink-bitcode-file"),
3343sepd1("mlink-builtin-bitcode"),
3344sepd1("mlink-cuda-bitcode"),
3345flagpd1("mlittle-endian"),
3346sepd1("mllvm"),
3347flagpd1("mlocal-sdata"),
3348flagpd1("mlong-calls"),
3349flagpd1("mlong-double-128"),
3350flagpd1("mlong-double-64"),
3351flagpd1("mlong-double-80"),
3352flagpd1("mlongcall"),
3353flagpd1("mlwp"),
3354flagpd1("mlzcnt"),
3355flagpd1("mmadd4"),
3356flagpd1("mmemops"),
3357flagpd1("mmfcrf"),
3358flagpd1("mmfocrf"),
3359flagpd1("mmicromips"),
3360flagpd1("mmmx"),
3361flagpd1("mmovbe"),
3362flagpd1("mmovdir64b"),
3363flagpd1("mmovdiri"),
3364flagpd1("mmpx"),
3365flagpd1("mms-bitfields"),
3366flagpd1("mmsa"),
3367flagpd1("mmt"),
3368flagpd1("mmultivalue"),
3369flagpd1("mmutable-globals"),
3370flagpd1("mmwaitx"),
3371flagpd1("mno-3dnow"),
3372flagpd1("mno-3dnowa"),
3373flagpd1("mno-80387"),
3374flagpd1("mno-abicalls"),
3375flagpd1("mno-adx"),
3376flagpd1("mno-aes"),
3377flagpd1("mno-altivec"),
3378flagpd1("mno-atomics"),
3379flagpd1("mno-avx"),
3380flagpd1("mno-avx2"),
3381flagpd1("mno-avx512bf16"),
3382flagpd1("mno-avx512bitalg"),
3383flagpd1("mno-avx512bw"),
3384flagpd1("mno-avx512cd"),
3385flagpd1("mno-avx512dq"),
3386flagpd1("mno-avx512er"),
3387flagpd1("mno-avx512f"),
3388flagpd1("mno-avx512ifma"),
3389flagpd1("mno-avx512pf"),
3390flagpd1("mno-avx512vbmi"),
3391flagpd1("mno-avx512vbmi2"),
3392flagpd1("mno-avx512vl"),
3393flagpd1("mno-avx512vnni"),
3394flagpd1("mno-avx512vp2intersect"),
3395flagpd1("mno-avx512vpopcntdq"),
3396flagpd1("mno-backchain"),
3397flagpd1("mno-bmi"),
3398flagpd1("mno-bmi2"),
3399flagpd1("mno-branch-likely"),
3400flagpd1("mno-bulk-memory"),
3401flagpd1("mno-check-zero-division"),
3402flagpd1("mno-cldemote"),
3403flagpd1("mno-clflushopt"),
3404flagpd1("mno-clwb"),
3405flagpd1("mno-clzero"),
3406flagpd1("mno-cmpb"),
3407flagpd1("mno-code-object-v3"),
3408flagpd1("mno-constant-cfstrings"),
3409flagpd1("mno-crbits"),
3410flagpd1("mno-crc"),
3411flagpd1("mno-cumode"),
3412flagpd1("mno-cx16"),
3413flagpd1("mno-dsp"),
3414flagpd1("mno-dspr2"),
3415flagpd1("mno-embedded-data"),
3416flagpd1("mno-enqcmd"),
3417flagpd1("mno-exception-handling"),
3418flagpd1("mnoexecstack"),
3419flagpd1("mno-execute-only"),
3420flagpd1("mno-extern-sdata"),
3421flagpd1("mno-f16c"),
3422flagpd1("mno-fix-cortex-a53-835769"),
3423flagpd1("mno-float128"),
3424flagpd1("mno-fma"),
3425flagpd1("mno-fma4"),
3426flagpd1("mno-fprnd"),
3427flagpd1("mno-fsgsbase"),
3428flagpd1("mno-fxsr"),
3429flagpd1("mno-gfni"),
3430flagpd1("mno-ginv"),
3431flagpd1("mno-global-merge"),
3432flagpd1("mno-gpopt"),
3433flagpd1("mno-hvx"),
3434flagpd1("mno-htm"),
3435flagpd1("mno-iamcu"),
3436flagpd1("mno-implicit-float"),
3437flagpd1("mno-incremental-linker-compatible"),
3438flagpd1("mno-inline-all-stringops"),
3439flagpd1("mno-invariant-function-descriptors"),
3440flagpd1("mno-invpcid"),
3441flagpd1("mno-isel"),
3442flagpd1("mno-ldc1-sdc1"),
3443flagpd1("mno-local-sdata"),
3444flagpd1("mno-long-calls"),
3445flagpd1("mno-longcall"),
3446flagpd1("mno-lwp"),
3447flagpd1("mno-lzcnt"),
3448flagpd1("mno-madd4"),
3449flagpd1("mno-memops"),
3450flagpd1("mno-mfcrf"),
3451flagpd1("mno-mfocrf"),
3452flagpd1("mno-micromips"),
3453flagpd1("mno-mips16"),
3454flagpd1("mno-mmx"),
3455flagpd1("mno-movbe"),
3456flagpd1("mno-movdir64b"),
3457flagpd1("mno-movdiri"),
3458flagpd1("mno-movt"),
3459flagpd1("mno-mpx"),
3460flagpd1("mno-ms-bitfields"),
3461flagpd1("mno-msa"),
3462flagpd1("mno-mt"),
3463flagpd1("mno-multivalue"),
3464flagpd1("mno-mutable-globals"),
3465flagpd1("mno-mwaitx"),
3466flagpd1("mno-neg-immediates"),
3467flagpd1("mno-nontrapping-fptoint"),
3468flagpd1("mno-nvj"),
3469flagpd1("mno-nvs"),
3470flagpd1("mno-odd-spreg"),
3471flagpd1("mno-omit-leaf-frame-pointer"),
3472flagpd1("mno-outline"),
3473flagpd1("mno-packed-stack"),
3474flagpd1("mno-packets"),
3475flagpd1("mno-pascal-strings"),
3476flagpd1("mno-pclmul"),
3477flagpd1("mno-pconfig"),
3478flagpd1("mno-pie-copy-relocations"),
3479flagpd1("mno-pku"),
3480flagpd1("mno-popcnt"),
3481flagpd1("mno-popcntd"),
3482flagpd1("mno-power8-vector"),
3483flagpd1("mno-power9-vector"),
3484flagpd1("mno-prefetchwt1"),
3485flagpd1("mno-prfchw"),
3486flagpd1("mno-ptwrite"),
3487flagpd1("mno-pure-code"),
3488flagpd1("mno-qpx"),
3489flagpd1("mno-rdpid"),
3490flagpd1("mno-rdrnd"),
3491flagpd1("mno-rdseed"),
3492flagpd1("mno-red-zone"),
3493flagpd1("mno-reference-types"),
3494flagpd1("mno-relax"),
3495flagpd1("mno-relax-all"),
3496flagpd1("mno-relax-pic-calls"),
3497flagpd1("mno-restrict-it"),
3498flagpd1("mno-retpoline"),
3499flagpd1("mno-retpoline-external-thunk"),
3500flagpd1("mno-rtd"),
3501flagpd1("mno-rtm"),
3502flagpd1("mno-sahf"),
3503flagpd1("mno-save-restore"),
3504flagpd1("mno-sgx"),
3505flagpd1("mno-sha"),
3506flagpd1("mno-shstk"),
3507flagpd1("mno-sign-ext"),
3508flagpd1("mno-simd128"),
3509flagpd1("mno-soft-float"),
3510flagpd1("mno-spe"),
3511flagpd1("mno-speculative-load-hardening"),
3512flagpd1("mno-sram-ecc"),
3513flagpd1("mno-sse"),
3514flagpd1("mno-sse2"),
3515flagpd1("mno-sse3"),
3516flagpd1("mno-sse4"),
3517flagpd1("mno-sse4.1"),
3518flagpd1("mno-sse4.2"),
3519flagpd1("mno-sse4a"),
3520flagpd1("mno-ssse3"),
3521flagpd1("mno-stack-arg-probe"),
3522flagpd1("mno-stackrealign"),
3523flagpd1("mno-tail-call"),
3524flagpd1("mno-tbm"),
3525flagpd1("mno-thumb"),
3526flagpd1("mno-tls-direct-seg-refs"),
3527flagpd1("mno-unaligned-access"),
3528flagpd1("mno-unimplemented-simd128"),
3529flagpd1("mno-vaes"),
3530flagpd1("mno-virt"),
3531flagpd1("mno-vpclmulqdq"),
3532flagpd1("mno-vsx"),
3533flagpd1("mno-vx"),
3534flagpd1("mno-vzeroupper"),
3535flagpd1("mno-waitpkg"),
3536flagpd1("mno-warn-nonportable-cfstrings"),
3537flagpd1("mno-wavefrontsize64"),
3538flagpd1("mno-wbnoinvd"),
3539flagpd1("mno-x87"),
3540flagpd1("mno-xgot"),
3541flagpd1("mno-xnack"),
3542flagpd1("mno-xop"),
3543flagpd1("mno-xsave"),
3544flagpd1("mno-xsavec"),
3545flagpd1("mno-xsaveopt"),
3546flagpd1("mno-xsaves"),
3547flagpd1("mno-zero-initialized-in-bss"),
3548flagpd1("mno-zvector"),
3549flagpd1("mnocrc"),
3550flagpd1("mno-direct-move"),
3551flagpd1("mnontrapping-fptoint"),
3552flagpd1("mnop-mcount"),
3553flagpd1("mno-crypto"),
3554flagpd1("mnvj"),
3555flagpd1("mnvs"),
3556flagpd1("modd-spreg"),
3557sepd1("module-dependency-dir"),
3558flagpd1("module-file-deps"),
3559flagpd1("module-file-info"),
3560flagpd1("fmodule-private"),
3561flagpd1("fno-module-private"),
3562flagpd1("fmodulo-sched-allow-regmoves"),
3563flagpd1("fno-modulo-sched-allow-regmoves"),
3564flagpd1("fmodulo-sched"),
3565flagpd1("fno-modulo-sched"),
3566flagpd1("momit-leaf-frame-pointer"),
3567flagpd1("moutline"),
3568flagpd1("mpacked-stack"),
3569flagpd1("mpackets"),
3570flagpd1("mpascal-strings"),
3571flagpd1("mpclmul"),
3572flagpd1("mpconfig"),
3573flagpd1("mpie-copy-relocations"),
3574flagpd1("mpku"),
3575flagpd1("mpopcnt"),
3576flagpd1("mpopcntd"),
3577flagpd1("mcrypto"),
3578flagpd1("mpower8-vector"),
3579flagpd1("mpower9-vector"),
3580flagpd1("mprefetchwt1"),
3581flagpd1("mprfchw"),
3582flagpd1("mptwrite"),
3583flagpd1("mpure-code"),
3584flagpd1("mqdsp6-compat"),
3585flagpd1("mqpx"),
3586flagpd1("mrdpid"),
3587flagpd1("mrdrnd"),
3588flagpd1("mrdseed"),
3589flagpd1("mreassociate"),
3590flagpd1("mrecip"),
3591flagpd1("mrecord-mcount"),
3592flagpd1("mred-zone"),
3593flagpd1("mreference-types"),
3594sepd1("mregparm"),
3595flagpd1("mrelax"),
3596flagpd1("mrelax-all"),
3597flagpd1("mrelax-pic-calls"),
3598.{
3599 .name = "mrelax-relocations",
3600 .syntax = .flag,
3601 .zig_equivalent = .other,
3602 .pd1 = false,
3603 .pd2 = true,
3604 .psl = false,
3605},
3606sepd1("mrelocation-model"),
3607flagpd1("mrestrict-it"),
3608flagpd1("mretpoline"),
3609flagpd1("mretpoline-external-thunk"),
3610flagpd1("mrtd"),
3611flagpd1("mrtm"),
3612flagpd1("msahf"),
3613flagpd1("msave-restore"),
3614flagpd1("msave-temp-labels"),
3615flagpd1("msecure-plt"),
3616flagpd1("msgx"),
3617flagpd1("msha"),
3618flagpd1("mshstk"),
3619flagpd1("msign-ext"),
3620flagpd1("msimd128"),
3621flagpd1("msingle-float"),
3622flagpd1("msoft-float"),
3623flagpd1("mspe"),
3624flagpd1("mspeculative-load-hardening"),
3625flagpd1("msram-ecc"),
3626flagpd1("msse"),
3627flagpd1("msse2"),
3628flagpd1("msse3"),
3629flagpd1("msse4"),
3630flagpd1("msse4.1"),
3631flagpd1("msse4.2"),
3632flagpd1("msse4a"),
3633flagpd1("mssse3"),
3634flagpd1("mstack-arg-probe"),
3635flagpd1("mstackrealign"),
3636flagpd1("mstrict-align"),
3637sepd1("mt-migrate-directory"),
3638flagpd1("mtail-call"),
3639flagpd1("mtbm"),
3640sepd1("mthread-model"),
3641flagpd1("mthumb"),
3642flagpd1("mtls-direct-seg-refs"),
3643sepd1("mtp"),
3644flagpd1("mtune=?"),
3645flagpd1("muclibc"),
3646flagpd1("multi_module"),
3647sepd1("multiply_defined"),
3648sepd1("multiply_defined_unused"),
3649flagpd1("munaligned-access"),
3650flagpd1("munimplemented-simd128"),
3651flagpd1("munwind-tables"),
3652flagpd1("mv5"),
3653flagpd1("mv55"),
3654flagpd1("mv60"),
3655flagpd1("mv62"),
3656flagpd1("mv65"),
3657flagpd1("mv66"),
3658flagpd1("mvaes"),
3659flagpd1("mvirt"),
3660flagpd1("mvpclmulqdq"),
3661flagpd1("mvsx"),
3662flagpd1("mvx"),
3663flagpd1("mvzeroupper"),
3664flagpd1("mwaitpkg"),
3665flagpd1("mwarn-nonportable-cfstrings"),
3666flagpd1("mwavefrontsize64"),
3667flagpd1("mwbnoinvd"),
3668flagpd1("mx32"),
3669flagpd1("mx87"),
3670flagpd1("mxgot"),
3671flagpd1("mxnack"),
3672flagpd1("mxop"),
3673flagpd1("mxsave"),
3674flagpd1("mxsavec"),
3675flagpd1("mxsaveopt"),
3676flagpd1("mxsaves"),
3677flagpd1("mzvector"),
3678flagpd1("n"),
3679flagpd1("new-struct-path-tbaa"),
3680flagpd1("no_dead_strip_inits_and_terms"),
3681flagpd1("no-canonical-prefixes"),
3682flagpd1("no-code-completion-globals"),
3683flagpd1("no-code-completion-ns-level-decls"),
3684flagpd1("no-cpp-precomp"),
3685.{
3686 .name = "no-cuda-noopt-device-debug",
3687 .syntax = .flag,
3688 .zig_equivalent = .other,
3689 .pd1 = false,
3690 .pd2 = true,
3691 .psl = false,
3692},
3693.{
3694 .name = "no-cuda-version-check",
3695 .syntax = .flag,
3696 .zig_equivalent = .other,
3697 .pd1 = false,
3698 .pd2 = true,
3699 .psl = false,
3700},
3701flagpd1("no-emit-llvm-uselists"),
3702flagpd1("no-implicit-float"),
3703.{
3704 .name = "no-integrated-cpp",
3705 .syntax = .flag,
3706 .zig_equivalent = .other,
3707 .pd1 = true,
3708 .pd2 = true,
3709 .psl = false,
3710},
3711.{
3712 .name = "no-pedantic",
3713 .syntax = .flag,
3714 .zig_equivalent = .other,
3715 .pd1 = true,
3716 .pd2 = true,
3717 .psl = false,
3718},
3719flagpd1("no-pie"),
3720flagpd1("no-pthread"),
3721flagpd1("no-struct-path-tbaa"),
3722flagpd1("nobuiltininc"),
3723flagpd1("nocpp"),
3724flagpd1("nocudainc"),
3725flagpd1("nodefaultlibs"),
3726flagpd1("nofixprebinding"),
3727flagpd1("nogpulib"),
3728flagpd1("nolibc"),
3729flagpd1("nomultidefs"),
3730flagpd1("fnon-call-exceptions"),
3731flagpd1("fno-non-call-exceptions"),
3732flagpd1("nopie"),
3733flagpd1("noprebind"),
3734flagpd1("noprofilelib"),
3735flagpd1("noseglinkedit"),
3736flagpd1("nostartfiles"),
3737flagpd1("nostdinc"),
3738flagpd1("nostdinc++"),
3739.{
3740 .name = "nostdlib",
3741 .syntax = .flag,
3742 .zig_equivalent = .nostdlib,
3743 .pd1 = true,
3744 .pd2 = false,
3745 .psl = false,
3746},
3747flagpd1("nostdlibinc"),
3748flagpd1("nostdlib++"),
3749flagpd1("nostdsysteminc"),
3750flagpd1("objcmt-atomic-property"),
3751flagpd1("objcmt-migrate-all"),
3752flagpd1("objcmt-migrate-annotation"),
3753flagpd1("objcmt-migrate-designated-init"),
3754flagpd1("objcmt-migrate-instancetype"),
3755flagpd1("objcmt-migrate-literals"),
3756flagpd1("objcmt-migrate-ns-macros"),
3757flagpd1("objcmt-migrate-property"),
3758flagpd1("objcmt-migrate-property-dot-syntax"),
3759flagpd1("objcmt-migrate-protocol-conformance"),
3760flagpd1("objcmt-migrate-readonly-property"),
3761flagpd1("objcmt-migrate-readwrite-property"),
3762flagpd1("objcmt-migrate-subscripting"),
3763flagpd1("objcmt-ns-nonatomic-iosonly"),
3764flagpd1("objcmt-returns-innerpointer-property"),
3765flagpd1("object"),
3766sepd1("opt-record-file"),
3767sepd1("opt-record-format"),
3768sepd1("opt-record-passes"),
3769sepd1("output-asm-variant"),
3770flagpd1("p"),
3771flagpd1("fpack-derived"),
3772flagpd1("fno-pack-derived"),
3773.{
3774 .name = "pass-exit-codes",
3775 .syntax = .flag,
3776 .zig_equivalent = .other,
3777 .pd1 = true,
3778 .pd2 = true,
3779 .psl = false,
3780},
3781flagpd1("pch-through-hdrstop-create"),
3782flagpd1("pch-through-hdrstop-use"),
3783.{
3784 .name = "pedantic",
3785 .syntax = .flag,
3786 .zig_equivalent = .other,
3787 .pd1 = true,
3788 .pd2 = true,
3789 .psl = false,
3790},
3791.{
3792 .name = "pedantic-errors",
3793 .syntax = .flag,
3794 .zig_equivalent = .other,
3795 .pd1 = true,
3796 .pd2 = true,
3797 .psl = false,
3798},
3799flagpd1("fpeel-loops"),
3800flagpd1("fno-peel-loops"),
3801flagpd1("fpermissive"),
3802flagpd1("fno-permissive"),
3803flagpd1("pg"),
3804flagpd1("pic-is-pie"),
3805sepd1("pic-level"),
3806flagpd1("pie"),
3807.{
3808 .name = "pipe",
3809 .syntax = .flag,
3810 .zig_equivalent = .ignore,
3811 .pd1 = true,
3812 .pd2 = true,
3813 .psl = false,
3814},
3815sepd1("plugin"),
3816flagpd1("prebind"),
3817flagpd1("prebind_all_twolevel_modules"),
3818flagpd1("fprefetch-loop-arrays"),
3819flagpd1("fno-prefetch-loop-arrays"),
3820flagpd1("preload"),
3821flagpd1("print-dependency-directives-minimized-source"),
3822.{
3823 .name = "print-effective-triple",
3824 .syntax = .flag,
3825 .zig_equivalent = .other,
3826 .pd1 = true,
3827 .pd2 = true,
3828 .psl = false,
3829},
3830flagpd1("print-ivar-layout"),
3831.{
3832 .name = "print-libgcc-file-name",
3833 .syntax = .flag,
3834 .zig_equivalent = .other,
3835 .pd1 = true,
3836 .pd2 = true,
3837 .psl = false,
3838},
3839.{
3840 .name = "print-multi-directory",
3841 .syntax = .flag,
3842 .zig_equivalent = .other,
3843 .pd1 = true,
3844 .pd2 = true,
3845 .psl = false,
3846},
3847.{
3848 .name = "print-multi-lib",
3849 .syntax = .flag,
3850 .zig_equivalent = .other,
3851 .pd1 = true,
3852 .pd2 = true,
3853 .psl = false,
3854},
3855.{
3856 .name = "print-multi-os-directory",
3857 .syntax = .flag,
3858 .zig_equivalent = .other,
3859 .pd1 = true,
3860 .pd2 = true,
3861 .psl = false,
3862},
3863flagpd1("print-preamble"),
3864.{
3865 .name = "print-resource-dir",
3866 .syntax = .flag,
3867 .zig_equivalent = .other,
3868 .pd1 = true,
3869 .pd2 = true,
3870 .psl = false,
3871},
3872.{
3873 .name = "print-search-dirs",
3874 .syntax = .flag,
3875 .zig_equivalent = .other,
3876 .pd1 = true,
3877 .pd2 = true,
3878 .psl = false,
3879},
3880flagpd1("print-stats"),
3881.{
3882 .name = "print-supported-cpus",
3883 .syntax = .flag,
3884 .zig_equivalent = .other,
3885 .pd1 = true,
3886 .pd2 = true,
3887 .psl = false,
3888},
3889.{
3890 .name = "print-target-triple",
3891 .syntax = .flag,
3892 .zig_equivalent = .other,
3893 .pd1 = true,
3894 .pd2 = true,
3895 .psl = false,
3896},
3897flagpd1("fprintf"),
3898flagpd1("fno-printf"),
3899flagpd1("private_bundle"),
3900flagpd1("fprofile-correction"),
3901flagpd1("fno-profile-correction"),
3902flagpd1("fprofile"),
3903flagpd1("fno-profile"),
3904flagpd1("fprofile-generate-sampling"),
3905flagpd1("fno-profile-generate-sampling"),
3906flagpd1("fprofile-reusedist"),
3907flagpd1("fno-profile-reusedist"),
3908flagpd1("fprofile-values"),
3909flagpd1("fno-profile-values"),
3910flagpd1("fprotect-parens"),
3911flagpd1("fno-protect-parens"),
3912flagpd1("pthread"),
3913flagpd1("pthreads"),
3914flagpd1("r"),
3915flagpd1("frange-check"),
3916flagpd1("fno-range-check"),
3917.{
3918 .name = "rdynamic",
3919 .syntax = .flag,
3920 .zig_equivalent = .rdynamic,
3921 .pd1 = true,
3922 .pd2 = false,
3923 .psl = false,
3924},
3925sepd1("read_only_relocs"),
3926flagpd1("freal-4-real-10"),
3927flagpd1("fno-real-4-real-10"),
3928flagpd1("freal-4-real-16"),
3929flagpd1("fno-real-4-real-16"),
3930flagpd1("freal-4-real-8"),
3931flagpd1("fno-real-4-real-8"),
3932flagpd1("freal-8-real-10"),
3933flagpd1("fno-real-8-real-10"),
3934flagpd1("freal-8-real-16"),
3935flagpd1("fno-real-8-real-16"),
3936flagpd1("freal-8-real-4"),
3937flagpd1("fno-real-8-real-4"),
3938flagpd1("frealloc-lhs"),
3939flagpd1("fno-realloc-lhs"),
3940sepd1("record-command-line"),
3941flagpd1("frecursive"),
3942flagpd1("fno-recursive"),
3943flagpd1("fregs-graph"),
3944flagpd1("fno-regs-graph"),
3945flagpd1("relaxed-aliasing"),
3946.{
3947 .name = "relocatable-pch",
3948 .syntax = .flag,
3949 .zig_equivalent = .other,
3950 .pd1 = true,
3951 .pd2 = true,
3952 .psl = false,
3953},
3954flagpd1("remap"),
3955sepd1("remap-file"),
3956flagpd1("frename-registers"),
3957flagpd1("fno-rename-registers"),
3958flagpd1("freorder-blocks"),
3959flagpd1("fno-reorder-blocks"),
3960flagpd1("frepack-arrays"),
3961flagpd1("fno-repack-arrays"),
3962sepd1("resource-dir"),
3963flagpd1("rewrite-legacy-objc"),
3964flagpd1("rewrite-macros"),
3965flagpd1("rewrite-objc"),
3966flagpd1("rewrite-test"),
3967flagpd1("fripa"),
3968flagpd1("fno-ripa"),
3969sepd1("rpath"),
3970flagpd1("s"),
3971.{
3972 .name = "save-stats",
3973 .syntax = .flag,
3974 .zig_equivalent = .other,
3975 .pd1 = true,
3976 .pd2 = true,
3977 .psl = false,
3978},
3979.{
3980 .name = "save-temps",
3981 .syntax = .flag,
3982 .zig_equivalent = .other,
3983 .pd1 = true,
3984 .pd2 = true,
3985 .psl = false,
3986},
3987flagpd1("fschedule-insns2"),
3988flagpd1("fno-schedule-insns2"),
3989flagpd1("fschedule-insns"),
3990flagpd1("fno-schedule-insns"),
3991flagpd1("fsecond-underscore"),
3992flagpd1("fno-second-underscore"),
3993.{
3994 .name = "sectalign",
3995 .syntax = .{.multi_arg=3},
3996 .zig_equivalent = .other,
3997 .pd1 = true,
3998 .pd2 = false,
3999 .psl = false,
4000},
4001.{
4002 .name = "sectcreate",
4003 .syntax = .{.multi_arg=3},
4004 .zig_equivalent = .other,
4005 .pd1 = true,
4006 .pd2 = false,
4007 .psl = false,
4008},
4009.{
4010 .name = "sectobjectsymbols",
4011 .syntax = .{.multi_arg=2},
4012 .zig_equivalent = .other,
4013 .pd1 = true,
4014 .pd2 = false,
4015 .psl = false,
4016},
4017.{
4018 .name = "sectorder",
4019 .syntax = .{.multi_arg=3},
4020 .zig_equivalent = .other,
4021 .pd1 = true,
4022 .pd2 = false,
4023 .psl = false,
4024},
4025flagpd1("fsee"),
4026flagpd1("fno-see"),
4027sepd1("seg_addr_table"),
4028sepd1("seg_addr_table_filename"),
4029.{
4030 .name = "segaddr",
4031 .syntax = .{.multi_arg=2},
4032 .zig_equivalent = .other,
4033 .pd1 = true,
4034 .pd2 = false,
4035 .psl = false,
4036},
4037.{
4038 .name = "segcreate",
4039 .syntax = .{.multi_arg=3},
4040 .zig_equivalent = .other,
4041 .pd1 = true,
4042 .pd2 = false,
4043 .psl = false,
4044},
4045flagpd1("seglinkedit"),
4046.{
4047 .name = "segprot",
4048 .syntax = .{.multi_arg=3},
4049 .zig_equivalent = .other,
4050 .pd1 = true,
4051 .pd2 = false,
4052 .psl = false,
4053},
4054sepd1("segs_read_only_addr"),
4055sepd1("segs_read_write_addr"),
4056flagpd1("setup-static-analyzer"),
4057.{
4058 .name = "shared",
4059 .syntax = .flag,
4060 .zig_equivalent = .shared,
4061 .pd1 = true,
4062 .pd2 = true,
4063 .psl = false,
4064},
4065flagpd1("shared-libgcc"),
4066flagpd1("shared-libsan"),
4067flagpd1("show-encoding"),
4068.{
4069 .name = "show-includes",
4070 .syntax = .flag,
4071 .zig_equivalent = .other,
4072 .pd1 = false,
4073 .pd2 = true,
4074 .psl = false,
4075},
4076flagpd1("show-inst"),
4077flagpd1("fsign-zero"),
4078flagpd1("fno-sign-zero"),
4079flagpd1("fsignaling-nans"),
4080flagpd1("fno-signaling-nans"),
4081flagpd1("single_module"),
4082flagpd1("fsingle-precision-constant"),
4083flagpd1("fno-single-precision-constant"),
4084flagpd1("fspec-constr-count"),
4085flagpd1("fno-spec-constr-count"),
4086.{
4087 .name = "specs",
4088 .syntax = .separate,
4089 .zig_equivalent = .other,
4090 .pd1 = true,
4091 .pd2 = true,
4092 .psl = false,
4093},
4094sepd1("split-dwarf-file"),
4095sepd1("split-dwarf-output"),
4096flagpd1("split-stacks"),
4097flagpd1("fstack-arrays"),
4098flagpd1("fno-stack-arrays"),
4099flagpd1("fstack-check"),
4100flagpd1("fno-stack-check"),
4101sepd1("stack-protector"),
4102sepd1("stack-protector-buffer-size"),
4103.{
4104 .name = "static",
4105 .syntax = .flag,
4106 .zig_equivalent = .other,
4107 .pd1 = true,
4108 .pd2 = true,
4109 .psl = false,
4110},
4111flagpd1("static-define"),
4112flagpd1("static-libgcc"),
4113flagpd1("static-libgfortran"),
4114flagpd1("static-libsan"),
4115flagpd1("static-libstdc++"),
4116flagpd1("static-openmp"),
4117flagpd1("static-pie"),
4118flagpd1("fstrength-reduce"),
4119flagpd1("fno-strength-reduce"),
4120flagpd1("sys-header-deps"),
4121flagpd1("t"),
4122sepd1("target-abi"),
4123sepd1("target-cpu"),
4124sepd1("target-feature"),
4125.{
4126 .name = "target",
4127 .syntax = .separate,
4128 .zig_equivalent = .target,
4129 .pd1 = true,
4130 .pd2 = false,
4131 .psl = false,
4132},
4133sepd1("target-linker-version"),
4134flagpd1("templight-dump"),
4135flagpd1("test-coverage"),
4136flagpd1("time"),
4137flagpd1("ftls-model"),
4138flagpd1("fno-tls-model"),
4139flagpd1("ftracer"),
4140flagpd1("fno-tracer"),
4141.{
4142 .name = "traditional",
4143 .syntax = .flag,
4144 .zig_equivalent = .other,
4145 .pd1 = true,
4146 .pd2 = true,
4147 .psl = false,
4148},
4149.{
4150 .name = "traditional-cpp",
4151 .syntax = .flag,
4152 .zig_equivalent = .other,
4153 .pd1 = true,
4154 .pd2 = true,
4155 .psl = false,
4156},
4157flagpd1("ftree-dce"),
4158flagpd1("fno-tree-dce"),
4159flagpd1("ftree_loop_im"),
4160flagpd1("fno-tree_loop_im"),
4161flagpd1("ftree_loop_ivcanon"),
4162flagpd1("fno-tree_loop_ivcanon"),
4163flagpd1("ftree_loop_linear"),
4164flagpd1("fno-tree_loop_linear"),
4165flagpd1("ftree-salias"),
4166flagpd1("fno-tree-salias"),
4167flagpd1("ftree-ter"),
4168flagpd1("fno-tree-ter"),
4169flagpd1("ftree-vectorizer-verbose"),
4170flagpd1("fno-tree-vectorizer-verbose"),
4171flagpd1("ftree-vrp"),
4172flagpd1("fno-tree-vrp"),
4173.{
4174 .name = "trigraphs",
4175 .syntax = .flag,
4176 .zig_equivalent = .other,
4177 .pd1 = true,
4178 .pd2 = true,
4179 .psl = false,
4180},
4181flagpd1("trim-egraph"),
4182sepd1("triple"),
4183flagpd1("twolevel_namespace"),
4184flagpd1("twolevel_namespace_hints"),
4185sepd1("umbrella"),
4186flagpd1("undef"),
4187flagpd1("funderscoring"),
4188flagpd1("fno-underscoring"),
4189sepd1("unexported_symbols_list"),
4190flagpd1("funroll-all-loops"),
4191flagpd1("fno-unroll-all-loops"),
4192flagpd1("funsafe-loop-optimizations"),
4193flagpd1("fno-unsafe-loop-optimizations"),
4194flagpd1("funswitch-loops"),
4195flagpd1("fno-unswitch-loops"),
4196flagpd1("fuse-linker-plugin"),
4197flagpd1("fno-use-linker-plugin"),
4198flagpd1("v"),
4199flagpd1("fvariable-expansion-in-unroller"),
4200flagpd1("fno-variable-expansion-in-unroller"),
4201flagpd1("fvect-cost-model"),
4202flagpd1("fno-vect-cost-model"),
4203flagpd1("vectorize-loops"),
4204flagpd1("vectorize-slp"),
4205flagpd1("verify"),
4206.{
4207 .name = "verify-debug-info",
4208 .syntax = .flag,
4209 .zig_equivalent = .other,
4210 .pd1 = false,
4211 .pd2 = true,
4212 .psl = false,
4213},
4214flagpd1("verify-ignore-unexpected"),
4215flagpd1("verify-pch"),
4216flagpd1("version"),
4217.{
4218 .name = "via-file-asm",
4219 .syntax = .flag,
4220 .zig_equivalent = .other,
4221 .pd1 = true,
4222 .pd2 = true,
4223 .psl = false,
4224},
4225flagpd1("w"),
4226sepd1("weak_framework"),
4227sepd1("weak_library"),
4228sepd1("weak_reference_mismatches"),
4229flagpd1("fweb"),
4230flagpd1("fno-web"),
4231flagpd1("whatsloaded"),
4232flagpd1("fwhole-file"),
4233flagpd1("fno-whole-file"),
4234flagpd1("fwhole-program"),
4235flagpd1("fno-whole-program"),
4236flagpd1("whyload"),
4237sepd1("z"),
4238joinpd1("fsanitize-undefined-strip-path-components="),
4239joinpd1("fopenmp-cuda-teams-reduction-recs-num="),
4240joinpd1("analyzer-config-compatibility-mode="),
4241joinpd1("fpatchable-function-entry-offset="),
4242joinpd1("analyzer-inline-max-stack-depth="),
4243joinpd1("fsanitize-address-field-padding="),
4244joinpd1("fdiagnostics-hotness-threshold="),
4245joinpd1("fsanitize-memory-track-origins="),
4246joinpd1("mwatchos-simulator-version-min="),
4247joinpd1("mappletvsimulator-version-min="),
4248joinpd1("fobjc-nonfragile-abi-version="),
4249joinpd1("fprofile-instrument-use-path="),
4250jspd1("fxray-instrumentation-bundle="),
4251joinpd1("miphonesimulator-version-min="),
4252joinpd1("faddress-space-map-mangling="),
4253joinpd1("foptimization-record-passes="),
4254joinpd1("ftest-module-file-extension="),
4255jspd1("fxray-instruction-threshold="),
4256joinpd1("mno-default-build-attributes"),
4257joinpd1("mtvos-simulator-version-min="),
4258joinpd1("mwatchsimulator-version-min="),
4259.{
4260 .name = "include-with-prefix-before=",
4261 .syntax = .joined,
4262 .zig_equivalent = .other,
4263 .pd1 = false,
4264 .pd2 = true,
4265 .psl = false,
4266},
4267joinpd1("objcmt-white-list-dir-path="),
4268joinpd1("error-on-deserialized-decl="),
4269joinpd1("fconstexpr-backtrace-limit="),
4270joinpd1("fdiagnostics-show-category="),
4271joinpd1("fdiagnostics-show-location="),
4272joinpd1("fopenmp-cuda-blocks-per-sm="),
4273joinpd1("fsanitize-system-blacklist="),
4274jspd1("fxray-instruction-threshold"),
4275joinpd1("headerpad_max_install_names"),
4276joinpd1("mios-simulator-version-min="),
4277.{
4278 .name = "include-with-prefix-after=",
4279 .syntax = .joined,
4280 .zig_equivalent = .other,
4281 .pd1 = false,
4282 .pd2 = true,
4283 .psl = false,
4284},
4285joinpd1("fms-compatibility-version="),
4286joinpd1("fopenmp-cuda-number-of-sm="),
4287joinpd1("foptimization-record-file="),
4288joinpd1("fpatchable-function-entry="),
4289joinpd1("fsave-optimization-record="),
4290joinpd1("ftemplate-backtrace-limit="),
4291.{
4292 .name = "gpu-max-threads-per-block=",
4293 .syntax = .joined,
4294 .zig_equivalent = .other,
4295 .pd1 = false,
4296 .pd2 = true,
4297 .psl = false,
4298},
4299joinpd1("malign-branch-prefix-size="),
4300joinpd1("objcmt-whitelist-dir-path="),
4301joinpd1("Wno-nonportable-cfstrings"),
4302joinpd1("analyzer-disable-checker="),
4303joinpd1("fbuild-session-timestamp="),
4304joinpd1("fprofile-instrument-path="),
4305joinpd1("mdefault-build-attributes"),
4306joinpd1("msign-return-address-key="),
4307.{
4308 .name = "verify-ignore-unexpected=",
4309 .syntax = .comma_joined,
4310 .zig_equivalent = .other,
4311 .pd1 = true,
4312 .pd2 = false,
4313 .psl = false,
4314},
4315.{
4316 .name = "include-directory-after=",
4317 .syntax = .joined,
4318 .zig_equivalent = .other,
4319 .pd1 = false,
4320 .pd2 = true,
4321 .psl = false,
4322},
4323.{
4324 .name = "compress-debug-sections=",
4325 .syntax = .joined,
4326 .zig_equivalent = .other,
4327 .pd1 = true,
4328 .pd2 = true,
4329 .psl = false,
4330},
4331.{
4332 .name = "fcomment-block-commands=",
4333 .syntax = .comma_joined,
4334 .zig_equivalent = .other,
4335 .pd1 = true,
4336 .pd2 = false,
4337 .psl = false,
4338},
4339joinpd1("flax-vector-conversions="),
4340joinpd1("fmodules-embed-all-files"),
4341joinpd1("fmodules-prune-interval="),
4342joinpd1("foverride-record-layout="),
4343joinpd1("fprofile-instr-generate="),
4344joinpd1("fprofile-remapping-file="),
4345joinpd1("fsanitize-coverage-type="),
4346joinpd1("fsanitize-hwaddress-abi="),
4347joinpd1("ftime-trace-granularity="),
4348jspd1("fxray-always-instrument="),
4349jspd1("internal-externc-isystem"),
4350.{
4351 .name = "libomptarget-nvptx-path=",
4352 .syntax = .joined,
4353 .zig_equivalent = .other,
4354 .pd1 = false,
4355 .pd2 = true,
4356 .psl = false,
4357},
4358.{
4359 .name = "no-system-header-prefix=",
4360 .syntax = .joined,
4361 .zig_equivalent = .other,
4362 .pd1 = false,
4363 .pd2 = true,
4364 .psl = false,
4365},
4366.{
4367 .name = "output-class-directory=",
4368 .syntax = .joined,
4369 .zig_equivalent = .other,
4370 .pd1 = false,
4371 .pd2 = true,
4372 .psl = false,
4373},
4374joinpd1("analyzer-inlining-mode="),
4375joinpd1("fconstant-string-class="),
4376joinpd1("fcrash-diagnostics-dir="),
4377joinpd1("fdebug-compilation-dir="),
4378joinpd1("fdebug-default-version="),
4379joinpd1("ffp-exception-behavior="),
4380joinpd1("fmacro-backtrace-limit="),
4381joinpd1("fmax-array-constructor="),
4382joinpd1("fprofile-exclude-files="),
4383joinpd1("ftrivial-auto-var-init="),
4384jspd1("fxray-never-instrument="),
4385jspd1("interface-stub-version="),
4386joinpd1("malign-branch-boundary="),
4387joinpd1("mappletvos-version-min="),
4388joinpd1("Wnonportable-cfstrings"),
4389joinpd1("fdefault-calling-conv="),
4390joinpd1("fmax-subrecord-length="),
4391joinpd1("fmodules-ignore-macro="),
4392.{
4393 .name = "fno-sanitize-coverage=",
4394 .syntax = .comma_joined,
4395 .zig_equivalent = .other,
4396 .pd1 = true,
4397 .pd2 = false,
4398 .psl = false,
4399},
4400joinpd1("fobjc-dispatch-method="),
4401joinpd1("foperator-arrow-depth="),
4402joinpd1("fprebuilt-module-path="),
4403joinpd1("fprofile-filter-files="),
4404joinpd1("fspell-checking-limit="),
4405joinpd1("miphoneos-version-min="),
4406joinpd1("msmall-data-threshold="),
4407joinpd1("Wlarge-by-value-copy="),
4408joinpd1("analyzer-constraints="),
4409joinpd1("analyzer-dump-egraph="),
4410jspd1("compatibility_version"),
4411jspd1("dylinker_install_name"),
4412joinpd1("fcs-profile-generate="),
4413joinpd1("fmodules-prune-after="),
4414.{
4415 .name = "fno-sanitize-recover=",
4416 .syntax = .comma_joined,
4417 .zig_equivalent = .other,
4418 .pd1 = true,
4419 .pd2 = false,
4420 .psl = false,
4421},
4422jspd1("iframeworkwithsysroot"),
4423joinpd1("mamdgpu-debugger-abi="),
4424joinpd1("mprefer-vector-width="),
4425joinpd1("msign-return-address="),
4426joinpd1("mwatchos-version-min="),
4427.{
4428 .name = "system-header-prefix=",
4429 .syntax = .joined,
4430 .zig_equivalent = .other,
4431 .pd1 = false,
4432 .pd2 = true,
4433 .psl = false,
4434},
4435.{
4436 .name = "include-with-prefix=",
4437 .syntax = .joined,
4438 .zig_equivalent = .other,
4439 .pd1 = false,
4440 .pd2 = true,
4441 .psl = false,
4442},
4443joinpd1("coverage-notes-file="),
4444joinpd1("fbuild-session-file="),
4445joinpd1("fdiagnostics-format="),
4446joinpd1("fmax-stack-var-size="),
4447joinpd1("fmodules-cache-path="),
4448joinpd1("fmodules-embed-file="),
4449joinpd1("fprofile-instrument="),
4450joinpd1("fprofile-sample-use="),
4451joinpd1("fsanitize-blacklist="),
4452.{
4453 .name = "hip-device-lib-path=",
4454 .syntax = .joined,
4455 .zig_equivalent = .other,
4456 .pd1 = false,
4457 .pd2 = true,
4458 .psl = false,
4459},
4460joinpd1("mmacosx-version-min="),
4461.{
4462 .name = "no-cuda-include-ptx=",
4463 .syntax = .joined,
4464 .zig_equivalent = .other,
4465 .pd1 = false,
4466 .pd2 = true,
4467 .psl = false,
4468},
4469joinpd1("Wframe-larger-than="),
4470joinpd1("code-completion-at="),
4471joinpd1("coverage-data-file="),
4472joinpd1("fblas-matmul-limit="),
4473joinpd1("fdiagnostics-color="),
4474joinpd1("ffixed-line-length-"),
4475joinpd1("flimited-precision="),
4476joinpd1("fprofile-instr-use="),
4477.{
4478 .name = "fsanitize-coverage=",
4479 .syntax = .comma_joined,
4480 .zig_equivalent = .other,
4481 .pd1 = true,
4482 .pd2 = false,
4483 .psl = false,
4484},
4485joinpd1("fthin-link-bitcode="),
4486joinpd1("mbranch-protection="),
4487joinpd1("mmacos-version-min="),
4488joinpd1("pch-through-header="),
4489joinpd1("target-sdk-version="),
4490.{
4491 .name = "execution-charset:",
4492 .syntax = .joined,
4493 .zig_equivalent = .other,
4494 .pd1 = true,
4495 .pd2 = false,
4496 .psl = true,
4497},
4498.{
4499 .name = "include-directory=",
4500 .syntax = .joined,
4501 .zig_equivalent = .other,
4502 .pd1 = false,
4503 .pd2 = true,
4504 .psl = false,
4505},
4506.{
4507 .name = "library-directory=",
4508 .syntax = .joined,
4509 .zig_equivalent = .other,
4510 .pd1 = false,
4511 .pd2 = true,
4512 .psl = false,
4513},
4514.{
4515 .name = "config-system-dir=",
4516 .syntax = .joined,
4517 .zig_equivalent = .other,
4518 .pd1 = false,
4519 .pd2 = true,
4520 .psl = false,
4521},
4522joinpd1("fclang-abi-compat="),
4523joinpd1("fcompile-resource="),
4524joinpd1("fdebug-prefix-map="),
4525joinpd1("fdenormal-fp-math="),
4526joinpd1("fexcess-precision="),
4527joinpd1("ffree-line-length-"),
4528joinpd1("fmacro-prefix-map="),
4529.{
4530 .name = "fno-sanitize-trap=",
4531 .syntax = .comma_joined,
4532 .zig_equivalent = .other,
4533 .pd1 = true,
4534 .pd2 = false,
4535 .psl = false,
4536},
4537joinpd1("fobjc-abi-version="),
4538joinpd1("foutput-class-dir="),
4539joinpd1("fprofile-generate="),
4540joinpd1("frewrite-map-file="),
4541.{
4542 .name = "fsanitize-recover=",
4543 .syntax = .comma_joined,
4544 .zig_equivalent = .other,
4545 .pd1 = true,
4546 .pd2 = false,
4547 .psl = false,
4548},
4549joinpd1("fsymbol-partition="),
4550joinpd1("mcompact-branches="),
4551joinpd1("mstack-probe-size="),
4552joinpd1("mtvos-version-min="),
4553joinpd1("working-directory="),
4554joinpd1("analyze-function="),
4555joinpd1("analyzer-checker="),
4556joinpd1("coverage-version="),
4557.{
4558 .name = "cuda-include-ptx=",
4559 .syntax = .joined,
4560 .zig_equivalent = .other,
4561 .pd1 = false,
4562 .pd2 = true,
4563 .psl = false,
4564},
4565joinpd1("falign-functions="),
4566joinpd1("fconstexpr-depth="),
4567joinpd1("fconstexpr-steps="),
4568joinpd1("ffile-prefix-map="),
4569joinpd1("fmodule-map-file="),
4570joinpd1("fobjc-arc-cxxlib="),
4571jspd1("iwithprefixbefore"),
4572joinpd1("malign-functions="),
4573joinpd1("mios-version-min="),
4574joinpd1("mstack-alignment="),
4575.{
4576 .name = "no-cuda-gpu-arch=",
4577 .syntax = .joined,
4578 .zig_equivalent = .other,
4579 .pd1 = false,
4580 .pd2 = true,
4581 .psl = false,
4582},
4583jspd1("working-directory"),
4584joinpd1("analyzer-output="),
4585.{
4586 .name = "config-user-dir=",
4587 .syntax = .joined,
4588 .zig_equivalent = .other,
4589 .pd1 = false,
4590 .pd2 = true,
4591 .psl = false,
4592},
4593joinpd1("debug-info-kind="),
4594joinpd1("debugger-tuning="),
4595joinpd1("fcf-runtime-abi="),
4596joinpd1("finit-character="),
4597joinpd1("fmax-type-align="),
4598joinpd1("fmessage-length="),
4599.{
4600 .name = "fopenmp-targets=",
4601 .syntax = .comma_joined,
4602 .zig_equivalent = .other,
4603 .pd1 = true,
4604 .pd2 = false,
4605 .psl = false,
4606},
4607joinpd1("fopenmp-version="),
4608joinpd1("fshow-overloads="),
4609joinpd1("ftemplate-depth-"),
4610joinpd1("ftemplate-depth="),
4611jspd1("fxray-attr-list="),
4612jspd1("internal-isystem"),
4613joinpd1("mlinker-version="),
4614.{
4615 .name = "print-file-name=",
4616 .syntax = .joined,
4617 .zig_equivalent = .other,
4618 .pd1 = true,
4619 .pd2 = true,
4620 .psl = false,
4621},
4622.{
4623 .name = "print-prog-name=",
4624 .syntax = .joined,
4625 .zig_equivalent = .other,
4626 .pd1 = true,
4627 .pd2 = true,
4628 .psl = false,
4629},
4630jspd1("stdlib++-isystem"),
4631joinpd1("Rpass-analysis="),
4632.{
4633 .name = "Xopenmp-target=",
4634 .syntax = .joined_and_separate,
4635 .zig_equivalent = .other,
4636 .pd1 = true,
4637 .pd2 = false,
4638 .psl = false,
4639},
4640.{
4641 .name = "source-charset:",
4642 .syntax = .joined,
4643 .zig_equivalent = .other,
4644 .pd1 = true,
4645 .pd2 = false,
4646 .psl = true,
4647},
4648.{
4649 .name = "analyzer-output",
4650 .syntax = .joined_or_separate,
4651 .zig_equivalent = .other,
4652 .pd1 = false,
4653 .pd2 = true,
4654 .psl = false,
4655},
4656.{
4657 .name = "include-prefix=",
4658 .syntax = .joined,
4659 .zig_equivalent = .other,
4660 .pd1 = false,
4661 .pd2 = true,
4662 .psl = false,
4663},
4664.{
4665 .name = "undefine-macro=",
4666 .syntax = .joined,
4667 .zig_equivalent = .other,
4668 .pd1 = false,
4669 .pd2 = true,
4670 .psl = false,
4671},
4672joinpd1("analyzer-purge="),
4673joinpd1("analyzer-store="),
4674jspd1("current_version"),
4675joinpd1("fbootclasspath="),
4676joinpd1("fbracket-depth="),
4677joinpd1("fcf-protection="),
4678joinpd1("fdepfile-entry="),
4679joinpd1("fembed-bitcode="),
4680joinpd1("finput-charset="),
4681joinpd1("fmodule-format="),
4682joinpd1("fms-memptr-rep="),
4683joinpd1("fnew-alignment="),
4684joinpd1("frecord-marker="),
4685.{
4686 .name = "fsanitize-trap=",
4687 .syntax = .comma_joined,
4688 .zig_equivalent = .other,
4689 .pd1 = true,
4690 .pd2 = false,
4691 .psl = false,
4692},
4693joinpd1("fthinlto-index="),
4694joinpd1("ftrap-function="),
4695joinpd1("ftrapv-handler="),
4696.{
4697 .name = "hip-device-lib=",
4698 .syntax = .joined,
4699 .zig_equivalent = .other,
4700 .pd1 = false,
4701 .pd2 = true,
4702 .psl = false,
4703},
4704joinpd1("mdynamic-no-pic"),
4705joinpd1("mframe-pointer="),
4706joinpd1("mindirect-jump="),
4707joinpd1("preamble-bytes="),
4708.{
4709 .name = "bootclasspath=",
4710 .syntax = .joined,
4711 .zig_equivalent = .other,
4712 .pd1 = false,
4713 .pd2 = true,
4714 .psl = false,
4715},
4716.{
4717 .name = "cuda-gpu-arch=",
4718 .syntax = .joined,
4719 .zig_equivalent = .other,
4720 .pd1 = false,
4721 .pd2 = true,
4722 .psl = false,
4723},
4724.{
4725 .name = "dependent-lib=",
4726 .syntax = .joined,
4727 .zig_equivalent = .other,
4728 .pd1 = false,
4729 .pd2 = true,
4730 .psl = false,
4731},
4732joinpd1("dwarf-version="),
4733joinpd1("falign-labels="),
4734joinpd1("fauto-profile="),
4735joinpd1("fexec-charset="),
4736joinpd1("fgnuc-version="),
4737joinpd1("finit-integer="),
4738joinpd1("finit-logical="),
4739joinpd1("finline-limit="),
4740joinpd1("fobjc-runtime="),
4741.{
4742 .name = "gcc-toolchain=",
4743 .syntax = .joined,
4744 .zig_equivalent = .other,
4745 .pd1 = false,
4746 .pd2 = true,
4747 .psl = false,
4748},
4749.{
4750 .name = "linker-option=",
4751 .syntax = .joined,
4752 .zig_equivalent = .other,
4753 .pd1 = false,
4754 .pd2 = true,
4755 .psl = false,
4756},
4757.{
4758 .name = "malign-branch=",
4759 .syntax = .comma_joined,
4760 .zig_equivalent = .other,
4761 .pd1 = true,
4762 .pd2 = false,
4763 .psl = false,
4764},
4765jspd1("objcxx-isystem"),
4766joinpd1("vtordisp-mode="),
4767joinpd1("Rpass-missed="),
4768joinpd1("Wlarger-than-"),
4769joinpd1("Wlarger-than="),
4770.{
4771 .name = "define-macro=",
4772 .syntax = .joined,
4773 .zig_equivalent = .other,
4774 .pd1 = false,
4775 .pd2 = true,
4776 .psl = false,
4777},
4778joinpd1("ast-dump-all="),
4779.{
4780 .name = "autocomplete=",
4781 .syntax = .joined,
4782 .zig_equivalent = .other,
4783 .pd1 = false,
4784 .pd2 = true,
4785 .psl = false,
4786},
4787joinpd1("falign-jumps="),
4788joinpd1("falign-loops="),
4789joinpd1("faligned-new="),
4790joinpd1("ferror-limit="),
4791joinpd1("ffp-contract="),
4792joinpd1("fmodule-file="),
4793joinpd1("fmodule-name="),
4794joinpd1("fmsc-version="),
4795.{
4796 .name = "fno-sanitize=",
4797 .syntax = .comma_joined,
4798 .zig_equivalent = .other,
4799 .pd1 = true,
4800 .pd2 = false,
4801 .psl = false,
4802},
4803joinpd1("fpack-struct="),
4804joinpd1("fpass-plugin="),
4805joinpd1("fprofile-dir="),
4806joinpd1("fprofile-use="),
4807joinpd1("frandom-seed="),
4808joinpd1("gsplit-dwarf="),
4809jspd1("isystem-after"),
4810joinpd1("malign-jumps="),
4811joinpd1("malign-loops="),
4812joinpd1("mimplicit-it="),
4813jspd1("pagezero_size"),
4814joinpd1("resource-dir="),
4815.{
4816 .name = "dyld-prefix=",
4817 .syntax = .joined,
4818 .zig_equivalent = .other,
4819 .pd1 = false,
4820 .pd2 = true,
4821 .psl = false,
4822},
4823.{
4824 .name = "driver-mode=",
4825 .syntax = .joined,
4826 .zig_equivalent = .other,
4827 .pd1 = false,
4828 .pd2 = true,
4829 .psl = false,
4830},
4831joinpd1("fmax-errors="),
4832joinpd1("fno-builtin-"),
4833joinpd1("fvisibility="),
4834joinpd1("fwchar-type="),
4835jspd1("fxray-modes="),
4836jspd1("iwithsysroot"),
4837joinpd1("mhvx-length="),
4838jspd1("objc-isystem"),
4839.{
4840 .name = "rsp-quoting=",
4841 .syntax = .joined,
4842 .zig_equivalent = .other,
4843 .pd1 = false,
4844 .pd2 = true,
4845 .psl = false,
4846},
4847joinpd1("std-default="),
4848jspd1("sub_umbrella"),
4849.{
4850 .name = "Qpar-report",
4851 .syntax = .joined,
4852 .zig_equivalent = .other,
4853 .pd1 = true,
4854 .pd2 = false,
4855 .psl = true,
4856},
4857.{
4858 .name = "Qvec-report",
4859 .syntax = .joined,
4860 .zig_equivalent = .other,
4861 .pd1 = true,
4862 .pd2 = false,
4863 .psl = true,
4864},
4865.{
4866 .name = "errorReport",
4867 .syntax = .joined,
4868 .zig_equivalent = .other,
4869 .pd1 = true,
4870 .pd2 = false,
4871 .psl = true,
4872},
4873.{
4874 .name = "for-linker=",
4875 .syntax = .joined,
4876 .zig_equivalent = .other,
4877 .pd1 = false,
4878 .pd2 = true,
4879 .psl = false,
4880},
4881.{
4882 .name = "force-link=",
4883 .syntax = .joined,
4884 .zig_equivalent = .other,
4885 .pd1 = false,
4886 .pd2 = true,
4887 .psl = false,
4888},
4889jspd1("client_name"),
4890jspd1("cxx-isystem"),
4891joinpd1("fclasspath="),
4892joinpd1("finit-real="),
4893joinpd1("fforce-addr"),
4894joinpd1("ftls-model="),
4895jspd1("ivfsoverlay"),
4896jspd1("iwithprefix"),
4897joinpd1("mfloat-abi="),
4898.{
4899 .name = "plugin-arg-",
4900 .syntax = .joined_and_separate,
4901 .zig_equivalent = .other,
4902 .pd1 = true,
4903 .pd2 = false,
4904 .psl = false,
4905},
4906.{
4907 .name = "ptxas-path=",
4908 .syntax = .joined,
4909 .zig_equivalent = .other,
4910 .pd1 = false,
4911 .pd2 = true,
4912 .psl = false,
4913},
4914.{
4915 .name = "save-stats=",
4916 .syntax = .joined,
4917 .zig_equivalent = .other,
4918 .pd1 = true,
4919 .pd2 = true,
4920 .psl = false,
4921},
4922.{
4923 .name = "save-temps=",
4924 .syntax = .joined,
4925 .zig_equivalent = .other,
4926 .pd1 = true,
4927 .pd2 = true,
4928 .psl = false,
4929},
4930joinpd1("stats-file="),
4931jspd1("sub_library"),
4932.{
4933 .name = "CLASSPATH=",
4934 .syntax = .joined,
4935 .zig_equivalent = .other,
4936 .pd1 = false,
4937 .pd2 = true,
4938 .psl = false,
4939},
4940.{
4941 .name = "constexpr:",
4942 .syntax = .joined,
4943 .zig_equivalent = .other,
4944 .pd1 = true,
4945 .pd2 = false,
4946 .psl = true,
4947},
4948.{
4949 .name = "classpath=",
4950 .syntax = .joined,
4951 .zig_equivalent = .other,
4952 .pd1 = false,
4953 .pd2 = true,
4954 .psl = false,
4955},
4956.{
4957 .name = "cuda-path=",
4958 .syntax = .joined,
4959 .zig_equivalent = .other,
4960 .pd1 = false,
4961 .pd2 = true,
4962 .psl = false,
4963},
4964joinpd1("fencoding="),
4965joinpd1("ffp-model="),
4966joinpd1("ffpe-trap="),
4967joinpd1("flto-jobs="),
4968.{
4969 .name = "fsanitize=",
4970 .syntax = .comma_joined,
4971 .zig_equivalent = .sanitize,
4972 .pd1 = true,
4973 .pd2 = false,
4974 .psl = false,
4975},
4976jspd1("iframework"),
4977joinpd1("mtls-size="),
4978joinpd1("segs_read_"),
4979.{
4980 .name = "unwindlib=",
4981 .syntax = .joined,
4982 .zig_equivalent = .other,
4983 .pd1 = true,
4984 .pd2 = true,
4985 .psl = false,
4986},
4987.{
4988 .name = "cgthreads",
4989 .syntax = .joined,
4990 .zig_equivalent = .other,
4991 .pd1 = true,
4992 .pd2 = false,
4993 .psl = true,
4994},
4995.{
4996 .name = "encoding=",
4997 .syntax = .joined,
4998 .zig_equivalent = .other,
4999 .pd1 = false,
5000 .pd2 = true,
5001 .psl = false,
5002},
5003.{
5004 .name = "language=",
5005 .syntax = .joined,
5006 .zig_equivalent = .other,
5007 .pd1 = false,
5008 .pd2 = true,
5009 .psl = false,
5010},
5011.{
5012 .name = "optimize=",
5013 .syntax = .joined,
5014 .zig_equivalent = .optimize,
5015 .pd1 = false,
5016 .pd2 = true,
5017 .psl = false,
5018},
5019.{
5020 .name = "resource=",
5021 .syntax = .joined,
5022 .zig_equivalent = .other,
5023 .pd1 = false,
5024 .pd2 = true,
5025 .psl = false,
5026},
5027joinpd1("ast-dump="),
5028jspd1("c-isystem"),
5029joinpd1("fcoarray="),
5030joinpd1("fconvert="),
5031joinpd1("fextdirs="),
5032joinpd1("ftabstop="),
5033jspd1("idirafter"),
5034joinpd1("mregparm="),
5035jspd1("undefined"),
5036.{
5037 .name = "extdirs=",
5038 .syntax = .joined,
5039 .zig_equivalent = .other,
5040 .pd1 = false,
5041 .pd2 = true,
5042 .psl = false,
5043},
5044.{
5045 .name = "imacros=",
5046 .syntax = .joined,
5047 .zig_equivalent = .other,
5048 .pd1 = false,
5049 .pd2 = true,
5050 .psl = false,
5051},
5052.{
5053 .name = "include=",
5054 .syntax = .joined,
5055 .zig_equivalent = .other,
5056 .pd1 = false,
5057 .pd2 = true,
5058 .psl = false,
5059},
5060.{
5061 .name = "sysroot=",
5062 .syntax = .joined,
5063 .zig_equivalent = .other,
5064 .pd1 = false,
5065 .pd2 = true,
5066 .psl = false,
5067},
5068joinpd1("fopenmp="),
5069joinpd1("fplugin="),
5070joinpd1("fuse-ld="),
5071joinpd1("fveclib="),
5072jspd1("isysroot"),
5073joinpd1("mcmodel="),
5074joinpd1("mconsole"),
5075joinpd1("mfpmath="),
5076joinpd1("mhwmult="),
5077joinpd1("mthreads"),
5078joinpd1("municode"),
5079joinpd1("mwindows"),
5080jspd1("seg1addr"),
5081.{
5082 .name = "assert=",
5083 .syntax = .joined,
5084 .zig_equivalent = .other,
5085 .pd1 = false,
5086 .pd2 = true,
5087 .psl = false,
5088},
5089.{
5090 .name = "mhwdiv=",
5091 .syntax = .joined,
5092 .zig_equivalent = .other,
5093 .pd1 = false,
5094 .pd2 = true,
5095 .psl = false,
5096},
5097.{
5098 .name = "output=",
5099 .syntax = .joined,
5100 .zig_equivalent = .other,
5101 .pd1 = false,
5102 .pd2 = true,
5103 .psl = false,
5104},
5105.{
5106 .name = "prefix=",
5107 .syntax = .joined,
5108 .zig_equivalent = .other,
5109 .pd1 = false,
5110 .pd2 = true,
5111 .psl = false,
5112},
5113.{
5114 .name = "cl-ext=",
5115 .syntax = .comma_joined,
5116 .zig_equivalent = .other,
5117 .pd1 = true,
5118 .pd2 = false,
5119 .psl = false,
5120},
5121joinpd1("cl-std="),
5122joinpd1("fcheck="),
5123.{
5124 .name = "imacros",
5125 .syntax = .joined_or_separate,
5126 .zig_equivalent = .other,
5127 .pd1 = true,
5128 .pd2 = true,
5129 .psl = false,
5130},
5131.{
5132 .name = "include",
5133 .syntax = .joined_or_separate,
5134 .zig_equivalent = .other,
5135 .pd1 = true,
5136 .pd2 = true,
5137 .psl = false,
5138},
5139jspd1("iprefix"),
5140jspd1("isystem"),
5141joinpd1("mhwdiv="),
5142joinpd1("moslib="),
5143.{
5144 .name = "mrecip=",
5145 .syntax = .comma_joined,
5146 .zig_equivalent = .other,
5147 .pd1 = true,
5148 .pd2 = false,
5149 .psl = false,
5150},
5151.{
5152 .name = "stdlib=",
5153 .syntax = .joined,
5154 .zig_equivalent = .other,
5155 .pd1 = true,
5156 .pd2 = true,
5157 .psl = false,
5158},
5159.{
5160 .name = "target=",
5161 .syntax = .joined,
5162 .zig_equivalent = .target,
5163 .pd1 = false,
5164 .pd2 = true,
5165 .psl = false,
5166},
5167joinpd1("triple="),
5168.{
5169 .name = "verify=",
5170 .syntax = .comma_joined,
5171 .zig_equivalent = .other,
5172 .pd1 = true,
5173 .pd2 = false,
5174 .psl = false,
5175},
5176joinpd1("Rpass="),
5177.{
5178 .name = "Xarch_",
5179 .syntax = .joined_and_separate,
5180 .zig_equivalent = .other,
5181 .pd1 = true,
5182 .pd2 = false,
5183 .psl = false,
5184},
5185.{
5186 .name = "clang:",
5187 .syntax = .joined,
5188 .zig_equivalent = .other,
5189 .pd1 = true,
5190 .pd2 = false,
5191 .psl = true,
5192},
5193.{
5194 .name = "guard:",
5195 .syntax = .joined,
5196 .zig_equivalent = .other,
5197 .pd1 = true,
5198 .pd2 = false,
5199 .psl = true,
5200},
5201.{
5202 .name = "debug=",
5203 .syntax = .joined,
5204 .zig_equivalent = .debug,
5205 .pd1 = false,
5206 .pd2 = true,
5207 .psl = false,
5208},
5209.{
5210 .name = "param=",
5211 .syntax = .joined,
5212 .zig_equivalent = .other,
5213 .pd1 = false,
5214 .pd2 = true,
5215 .psl = false,
5216},
5217.{
5218 .name = "warn-=",
5219 .syntax = .joined,
5220 .zig_equivalent = .other,
5221 .pd1 = false,
5222 .pd2 = true,
5223 .psl = false,
5224},
5225joinpd1("fixit="),
5226joinpd1("gstabs"),
5227joinpd1("gxcoff"),
5228jspd1("iquote"),
5229joinpd1("march="),
5230joinpd1("mtune="),
5231.{
5232 .name = "rtlib=",
5233 .syntax = .joined,
5234 .zig_equivalent = .other,
5235 .pd1 = true,
5236 .pd2 = true,
5237 .psl = false,
5238},
5239.{
5240 .name = "specs=",
5241 .syntax = .joined,
5242 .zig_equivalent = .other,
5243 .pd1 = true,
5244 .pd2 = true,
5245 .psl = false,
5246},
5247joinpd1("weak-l"),
5248.{
5249 .name = "Ofast",
5250 .syntax = .joined,
5251 .zig_equivalent = .optimize,
5252 .pd1 = true,
5253 .pd2 = false,
5254 .psl = false,
5255},
5256jspd1("Tdata"),
5257jspd1("Ttext"),
5258.{
5259 .name = "arch:",
5260 .syntax = .joined,
5261 .zig_equivalent = .other,
5262 .pd1 = true,
5263 .pd2 = false,
5264 .psl = true,
5265},
5266.{
5267 .name = "favor",
5268 .syntax = .joined,
5269 .zig_equivalent = .other,
5270 .pd1 = true,
5271 .pd2 = false,
5272 .psl = true,
5273},
5274.{
5275 .name = "imsvc",
5276 .syntax = .joined_or_separate,
5277 .zig_equivalent = .other,
5278 .pd1 = true,
5279 .pd2 = false,
5280 .psl = true,
5281},
5282.{
5283 .name = "warn-",
5284 .syntax = .joined,
5285 .zig_equivalent = .other,
5286 .pd1 = false,
5287 .pd2 = true,
5288 .psl = false,
5289},
5290joinpd1("flto="),
5291joinpd1("gcoff"),
5292joinpd1("mabi="),
5293joinpd1("mabs="),
5294joinpd1("masm="),
5295joinpd1("mcpu="),
5296joinpd1("mfpu="),
5297joinpd1("mhvx="),
5298joinpd1("mmcu="),
5299joinpd1("mnan="),
5300jspd1("Tbss"),
5301.{
5302 .name = "link",
5303 .syntax = .remaining_args_joined,
5304 .zig_equivalent = .other,
5305 .pd1 = true,
5306 .pd2 = false,
5307 .psl = true,
5308},
5309.{
5310 .name = "std:",
5311 .syntax = .joined,
5312 .zig_equivalent = .other,
5313 .pd1 = true,
5314 .pd2 = false,
5315 .psl = true,
5316},
5317joinpd1("ccc-"),
5318joinpd1("gvms"),
5319joinpd1("mdll"),
5320joinpd1("mtp="),
5321.{
5322 .name = "std=",
5323 .syntax = .joined,
5324 .zig_equivalent = .other,
5325 .pd1 = true,
5326 .pd2 = true,
5327 .psl = false,
5328},
5329.{
5330 .name = "Wa,",
5331 .syntax = .comma_joined,
5332 .zig_equivalent = .other,
5333 .pd1 = true,
5334 .pd2 = false,
5335 .psl = false,
5336},
5337.{
5338 .name = "Wl,",
5339 .syntax = .comma_joined,
5340 .zig_equivalent = .wl,
5341 .pd1 = true,
5342 .pd2 = false,
5343 .psl = false,
5344},
5345.{
5346 .name = "Wp,",
5347 .syntax = .comma_joined,
5348 .zig_equivalent = .other,
5349 .pd1 = true,
5350 .pd2 = false,
5351 .psl = false,
5352},
5353.{
5354 .name = "RTC",
5355 .syntax = .joined,
5356 .zig_equivalent = .other,
5357 .pd1 = true,
5358 .pd2 = false,
5359 .psl = true,
5360},
5361.{
5362 .name = "Zc:",
5363 .syntax = .joined,
5364 .zig_equivalent = .other,
5365 .pd1 = true,
5366 .pd2 = false,
5367 .psl = true,
5368},
5369.{
5370 .name = "clr",
5371 .syntax = .joined,
5372 .zig_equivalent = .other,
5373 .pd1 = true,
5374 .pd2 = false,
5375 .psl = true,
5376},
5377.{
5378 .name = "doc",
5379 .syntax = .joined,
5380 .zig_equivalent = .other,
5381 .pd1 = true,
5382 .pd2 = false,
5383 .psl = true,
5384},
5385joinpd1("gz="),
5386joinpd1("A-"),
5387joinpd1("G="),
5388jspd1("MF"),
5389jspd1("MJ"),
5390jspd1("MQ"),
5391jspd1("MT"),
5392.{
5393 .name = "AI",
5394 .syntax = .joined_or_separate,
5395 .zig_equivalent = .other,
5396 .pd1 = true,
5397 .pd2 = false,
5398 .psl = true,
5399},
5400.{
5401 .name = "EH",
5402 .syntax = .joined,
5403 .zig_equivalent = .other,
5404 .pd1 = true,
5405 .pd2 = false,
5406 .psl = true,
5407},
5408.{
5409 .name = "FA",
5410 .syntax = .joined,
5411 .zig_equivalent = .other,
5412 .pd1 = true,
5413 .pd2 = false,
5414 .psl = true,
5415},
5416.{
5417 .name = "FI",
5418 .syntax = .joined_or_separate,
5419 .zig_equivalent = .other,
5420 .pd1 = true,
5421 .pd2 = false,
5422 .psl = true,
5423},
5424.{
5425 .name = "FR",
5426 .syntax = .joined,
5427 .zig_equivalent = .other,
5428 .pd1 = true,
5429 .pd2 = false,
5430 .psl = true,
5431},
5432.{
5433 .name = "FU",
5434 .syntax = .joined_or_separate,
5435 .zig_equivalent = .other,
5436 .pd1 = true,
5437 .pd2 = false,
5438 .psl = true,
5439},
5440.{
5441 .name = "Fa",
5442 .syntax = .joined,
5443 .zig_equivalent = .other,
5444 .pd1 = true,
5445 .pd2 = false,
5446 .psl = true,
5447},
5448.{
5449 .name = "Fd",
5450 .syntax = .joined,
5451 .zig_equivalent = .other,
5452 .pd1 = true,
5453 .pd2 = false,
5454 .psl = true,
5455},
5456.{
5457 .name = "Fe",
5458 .syntax = .joined,
5459 .zig_equivalent = .other,
5460 .pd1 = true,
5461 .pd2 = false,
5462 .psl = true,
5463},
5464.{
5465 .name = "Fi",
5466 .syntax = .joined,
5467 .zig_equivalent = .other,
5468 .pd1 = true,
5469 .pd2 = false,
5470 .psl = true,
5471},
5472.{
5473 .name = "Fm",
5474 .syntax = .joined,
5475 .zig_equivalent = .other,
5476 .pd1 = true,
5477 .pd2 = false,
5478 .psl = true,
5479},
5480.{
5481 .name = "Fo",
5482 .syntax = .joined,
5483 .zig_equivalent = .other,
5484 .pd1 = true,
5485 .pd2 = false,
5486 .psl = true,
5487},
5488.{
5489 .name = "Fp",
5490 .syntax = .joined,
5491 .zig_equivalent = .other,
5492 .pd1 = true,
5493 .pd2 = false,
5494 .psl = true,
5495},
5496.{
5497 .name = "Fr",
5498 .syntax = .joined,
5499 .zig_equivalent = .other,
5500 .pd1 = true,
5501 .pd2 = false,
5502 .psl = true,
5503},
5504.{
5505 .name = "Gs",
5506 .syntax = .joined,
5507 .zig_equivalent = .other,
5508 .pd1 = true,
5509 .pd2 = false,
5510 .psl = true,
5511},
5512.{
5513 .name = "MP",
5514 .syntax = .joined,
5515 .zig_equivalent = .other,
5516 .pd1 = true,
5517 .pd2 = false,
5518 .psl = true,
5519},
5520.{
5521 .name = "Tc",
5522 .syntax = .joined_or_separate,
5523 .zig_equivalent = .other,
5524 .pd1 = true,
5525 .pd2 = false,
5526 .psl = true,
5527},
5528.{
5529 .name = "Tp",
5530 .syntax = .joined_or_separate,
5531 .zig_equivalent = .other,
5532 .pd1 = true,
5533 .pd2 = false,
5534 .psl = true,
5535},
5536.{
5537 .name = "Yc",
5538 .syntax = .joined,
5539 .zig_equivalent = .other,
5540 .pd1 = true,
5541 .pd2 = false,
5542 .psl = true,
5543},
5544.{
5545 .name = "Yl",
5546 .syntax = .joined,
5547 .zig_equivalent = .other,
5548 .pd1 = true,
5549 .pd2 = false,
5550 .psl = true,
5551},
5552.{
5553 .name = "Yu",
5554 .syntax = .joined,
5555 .zig_equivalent = .other,
5556 .pd1 = true,
5557 .pd2 = false,
5558 .psl = true,
5559},
5560.{
5561 .name = "ZW",
5562 .syntax = .joined,
5563 .zig_equivalent = .other,
5564 .pd1 = true,
5565 .pd2 = false,
5566 .psl = true,
5567},
5568.{
5569 .name = "Zm",
5570 .syntax = .joined,
5571 .zig_equivalent = .other,
5572 .pd1 = true,
5573 .pd2 = false,
5574 .psl = true,
5575},
5576.{
5577 .name = "Zp",
5578 .syntax = .joined,
5579 .zig_equivalent = .other,
5580 .pd1 = true,
5581 .pd2 = false,
5582 .psl = true,
5583},
5584.{
5585 .name = "d2",
5586 .syntax = .joined,
5587 .zig_equivalent = .other,
5588 .pd1 = true,
5589 .pd2 = false,
5590 .psl = true,
5591},
5592.{
5593 .name = "vd",
5594 .syntax = .joined,
5595 .zig_equivalent = .other,
5596 .pd1 = true,
5597 .pd2 = false,
5598 .psl = true,
5599},
5600jspd1("A"),
5601jspd1("B"),
5602jspd1("D"),
5603jspd1("F"),
5604jspd1("G"),
5605jspd1("I"),
5606jspd1("J"),
5607jspd1("L"),
5608.{
5609 .name = "O",
5610 .syntax = .joined,
5611 .zig_equivalent = .optimize,
5612 .pd1 = true,
5613 .pd2 = false,
5614 .psl = false,
5615},
5616joinpd1("R"),
5617jspd1("T"),
5618jspd1("U"),
5619jspd1("V"),
5620joinpd1("W"),
5621joinpd1("X"),
5622joinpd1("Z"),
5623.{
5624 .name = "D",
5625 .syntax = .joined_or_separate,
5626 .zig_equivalent = .other,
5627 .pd1 = true,
5628 .pd2 = false,
5629 .psl = true,
5630},
5631.{
5632 .name = "F",
5633 .syntax = .joined_or_separate,
5634 .zig_equivalent = .other,
5635 .pd1 = true,
5636 .pd2 = false,
5637 .psl = true,
5638},
5639.{
5640 .name = "I",
5641 .syntax = .joined_or_separate,
5642 .zig_equivalent = .other,
5643 .pd1 = true,
5644 .pd2 = false,
5645 .psl = true,
5646},
5647.{
5648 .name = "O",
5649 .syntax = .joined,
5650 .zig_equivalent = .optimize,
5651 .pd1 = true,
5652 .pd2 = false,
5653 .psl = true,
5654},
5655.{
5656 .name = "U",
5657 .syntax = .joined_or_separate,
5658 .zig_equivalent = .other,
5659 .pd1 = true,
5660 .pd2 = false,
5661 .psl = true,
5662},
5663.{
5664 .name = "o",
5665 .syntax = .joined_or_separate,
5666 .zig_equivalent = .o,
5667 .pd1 = true,
5668 .pd2 = false,
5669 .psl = true,
5670},
5671.{
5672 .name = "w",
5673 .syntax = .joined,
5674 .zig_equivalent = .other,
5675 .pd1 = true,
5676 .pd2 = false,
5677 .psl = true,
5678},
5679joinpd1("a"),
5680jspd1("b"),
5681joinpd1("d"),
5682jspd1("e"),
5683.{
5684 .name = "l",
5685 .syntax = .joined_or_separate,
5686 .zig_equivalent = .l,
5687 .pd1 = true,
5688 .pd2 = false,
5689 .psl = false,
5690},
5691.{
5692 .name = "o",
5693 .syntax = .joined_or_separate,
5694 .zig_equivalent = .o,
5695 .pd1 = true,
5696 .pd2 = false,
5697 .psl = false,
5698},
5699jspd1("u"),
5700jspd1("x"),
5701joinpd1("y"),
5702};};
src-self-hosted/compilation.zig+17-16
...@@ -95,7 +95,7 @@ pub const ZigCompiler = struct {...@@ -95,7 +95,7 @@ pub const ZigCompiler = struct {
9595
96 pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {96 pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
97 if (self.native_libc.start()) |ptr| return ptr;97 if (self.native_libc.start()) |ptr| return ptr;
98 try self.native_libc.data.findNative(self.allocator);98 self.native_libc.data = try LibCInstallation.findNative(.{ .allocator = self.allocator });
99 self.native_libc.resolve();99 self.native_libc.resolve();
100 return &self.native_libc.data;100 return &self.native_libc.data;
101 }101 }
...@@ -126,7 +126,7 @@ pub const Compilation = struct {...@@ -126,7 +126,7 @@ pub const Compilation = struct {
126 name: Buffer,126 name: Buffer,
127 llvm_triple: Buffer,127 llvm_triple: Buffer,
128 root_src_path: ?[]const u8,128 root_src_path: ?[]const u8,
129 target: Target,129 target: std.Target,
130 llvm_target: *llvm.Target,130 llvm_target: *llvm.Target,
131 build_mode: builtin.Mode,131 build_mode: builtin.Mode,
132 zig_lib_dir: []const u8,132 zig_lib_dir: []const u8,
...@@ -338,7 +338,7 @@ pub const Compilation = struct {...@@ -338,7 +338,7 @@ pub const Compilation = struct {
338 zig_compiler: *ZigCompiler,338 zig_compiler: *ZigCompiler,
339 name: []const u8,339 name: []const u8,
340 root_src_path: ?[]const u8,340 root_src_path: ?[]const u8,
341 target: Target,341 target: std.zig.CrossTarget,
342 kind: Kind,342 kind: Kind,
343 build_mode: builtin.Mode,343 build_mode: builtin.Mode,
344 is_static: bool,344 is_static: bool,
...@@ -370,13 +370,18 @@ pub const Compilation = struct {...@@ -370,13 +370,18 @@ pub const Compilation = struct {
370 zig_compiler: *ZigCompiler,370 zig_compiler: *ZigCompiler,
371 name: []const u8,371 name: []const u8,
372 root_src_path: ?[]const u8,372 root_src_path: ?[]const u8,
373 target: Target,373 cross_target: std.zig.CrossTarget,
374 kind: Kind,374 kind: Kind,
375 build_mode: builtin.Mode,375 build_mode: builtin.Mode,
376 is_static: bool,376 is_static: bool,
377 zig_lib_dir: []const u8,377 zig_lib_dir: []const u8,
378 ) !void {378 ) !void {
379 const allocator = zig_compiler.allocator;379 const allocator = zig_compiler.allocator;
380
381 // TODO merge this line with stage2.zig crossTargetToTarget
382 const target_info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
383 const target = target_info.target;
384
380 var comp = Compilation{385 var comp = Compilation{
381 .arena_allocator = std.heap.ArenaAllocator.init(allocator),386 .arena_allocator = std.heap.ArenaAllocator.init(allocator),
382 .zig_compiler = zig_compiler,387 .zig_compiler = zig_compiler,
...@@ -419,7 +424,7 @@ pub const Compilation = struct {...@@ -419,7 +424,7 @@ pub const Compilation = struct {
419 .target_machine = undefined,424 .target_machine = undefined,
420 .target_data_ref = undefined,425 .target_data_ref = undefined,
421 .target_layout_str = undefined,426 .target_layout_str = undefined,
422 .target_ptr_bits = target.getArchPtrBitWidth(),427 .target_ptr_bits = target.cpu.arch.ptrBitWidth(),
423428
424 .root_package = undefined,429 .root_package = undefined,
425 .std_package = undefined,430 .std_package = undefined,
...@@ -440,7 +445,7 @@ pub const Compilation = struct {...@@ -440,7 +445,7 @@ pub const Compilation = struct {
440 }445 }
441446
442 comp.name = try Buffer.init(comp.arena(), name);447 comp.name = try Buffer.init(comp.arena(), name);
443 comp.llvm_triple = try util.getTriple(comp.arena(), target);448 comp.llvm_triple = try util.getLLVMTriple(comp.arena(), target);
444 comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple);449 comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple);
445 comp.zig_std_dir = try fs.path.join(comp.arena(), &[_][]const u8{ zig_lib_dir, "std" });450 comp.zig_std_dir = try fs.path.join(comp.arena(), &[_][]const u8{ zig_lib_dir, "std" });
446451
...@@ -451,17 +456,12 @@ pub const Compilation = struct {...@@ -451,17 +456,12 @@ pub const Compilation = struct {
451456
452 const reloc_mode = if (is_static) llvm.RelocStatic else llvm.RelocPIC;457 const reloc_mode = if (is_static) llvm.RelocStatic else llvm.RelocPIC;
453458
454 // LLVM creates invalid binaries on Windows sometimes.
455 // See https://github.com/ziglang/zig/issues/508
456 // As a workaround we do not use target native features on Windows.
457 var target_specific_cpu_args: ?[*:0]u8 = null;459 var target_specific_cpu_args: ?[*:0]u8 = null;
458 var target_specific_cpu_features: ?[*:0]u8 = null;460 var target_specific_cpu_features: ?[*:0]u8 = null;
459 defer llvm.DisposeMessage(target_specific_cpu_args);461 defer llvm.DisposeMessage(target_specific_cpu_args);
460 defer llvm.DisposeMessage(target_specific_cpu_features);462 defer llvm.DisposeMessage(target_specific_cpu_features);
461 if (target == Target.Native and !target.isWindows()) {463
462 target_specific_cpu_args = llvm.GetHostCPUName() orelse return error.OutOfMemory;464 // TODO detect native CPU & features here
463 target_specific_cpu_features = llvm.GetNativeFeatures() orelse return error.OutOfMemory;
464 }
465465
466 comp.target_machine = llvm.CreateTargetMachine(466 comp.target_machine = llvm.CreateTargetMachine(
467 comp.llvm_target,467 comp.llvm_target,
...@@ -520,8 +520,7 @@ pub const Compilation = struct {...@@ -520,8 +520,7 @@ pub const Compilation = struct {
520520
521 if (comp.tmp_dir.getOrNull()) |tmp_dir_result|521 if (comp.tmp_dir.getOrNull()) |tmp_dir_result|
522 if (tmp_dir_result.*) |tmp_dir| {522 if (tmp_dir_result.*) |tmp_dir| {
523 // TODO evented I/O?523 fs.cwd().deleteTree(tmp_dir) catch {};
524 fs.deleteTree(tmp_dir) catch {};
525 } else |_| {};524 } else |_| {};
526 }525 }
527526
...@@ -1125,7 +1124,9 @@ pub const Compilation = struct {...@@ -1125,7 +1124,9 @@ pub const Compilation = struct {
1125 self.libc_link_lib = link_lib;1124 self.libc_link_lib = link_lib;
11261125
1127 // get a head start on looking for the native libc1126 // get a head start on looking for the native libc
1128 if (self.target == Target.Native and self.override_libc == null) {1127 // TODO this is missing a bunch of logic related to whether the target is native
1128 // and whether we can build libc
1129 if (self.override_libc == null) {
1129 try self.deinit_group.call(startFindingNativeLibC, .{self});1130 try self.deinit_group.call(startFindingNativeLibC, .{self});
1130 }1131 }
1131 }1132 }
src-self-hosted/errmsg.zig+4-7
...@@ -164,8 +164,7 @@ pub const Msg = struct {...@@ -164,8 +164,7 @@ pub const Msg = struct {
164 const realpath_copy = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);164 const realpath_copy = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
165 errdefer comp.gpa().free(realpath_copy);165 errdefer comp.gpa().free(realpath_copy);
166166
167 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;167 try parse_error.render(&tree_scope.tree.tokens, text_buf.outStream());
168 try parse_error.render(&tree_scope.tree.tokens, out_stream);
169168
170 const msg = try comp.gpa().create(Msg);169 const msg = try comp.gpa().create(Msg);
171 msg.* = Msg{170 msg.* = Msg{
...@@ -204,8 +203,7 @@ pub const Msg = struct {...@@ -204,8 +203,7 @@ pub const Msg = struct {
204 const realpath_copy = try mem.dupe(allocator, u8, realpath);203 const realpath_copy = try mem.dupe(allocator, u8, realpath);
205 errdefer allocator.free(realpath_copy);204 errdefer allocator.free(realpath_copy);
206205
207 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;206 try parse_error.render(&tree.tokens, text_buf.outStream());
208 try parse_error.render(&tree.tokens, out_stream);
209207
210 const msg = try allocator.create(Msg);208 const msg = try allocator.create(Msg);
211 msg.* = Msg{209 msg.* = Msg{
...@@ -272,7 +270,7 @@ pub const Msg = struct {...@@ -272,7 +270,7 @@ pub const Msg = struct {
272 });270 });
273 try stream.writeByteNTimes(' ', start_loc.column);271 try stream.writeByteNTimes(' ', start_loc.column);
274 try stream.writeByteNTimes('~', last_token.end - first_token.start);272 try stream.writeByteNTimes('~', last_token.end - first_token.start);
275 try stream.write("\n");273 try stream.writeAll("\n");
276 }274 }
277275
278 pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {276 pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {
...@@ -281,7 +279,6 @@ pub const Msg = struct {...@@ -281,7 +279,6 @@ pub const Msg = struct {
281 .On => true,279 .On => true,
282 .Off => false,280 .Off => false,
283 };281 };
284 var stream = &file.outStream().stream;282 return msg.printToStream(file.outStream(), color_on);
285 return msg.printToStream(stream, color_on);
286 }283 }
287};284};
src-self-hosted/ir.zig+10-7
...@@ -1099,7 +1099,6 @@ pub const Builder = struct {...@@ -1099,7 +1099,6 @@ pub const Builder = struct {
1099 .Await => return error.Unimplemented,1099 .Await => return error.Unimplemented,
1100 .BitNot => return error.Unimplemented,1100 .BitNot => return error.Unimplemented,
1101 .BoolNot => return error.Unimplemented,1101 .BoolNot => return error.Unimplemented,
1102 .Cancel => return error.Unimplemented,
1103 .OptionalType => return error.Unimplemented,1102 .OptionalType => return error.Unimplemented,
1104 .Negation => return error.Unimplemented,1103 .Negation => return error.Unimplemented,
1105 .NegationWrap => return error.Unimplemented,1104 .NegationWrap => return error.Unimplemented,
...@@ -1188,6 +1187,7 @@ pub const Builder = struct {...@@ -1188,6 +1187,7 @@ pub const Builder = struct {
1188 .ParamDecl => return error.Unimplemented,1187 .ParamDecl => return error.Unimplemented,
1189 .FieldInitializer => return error.Unimplemented,1188 .FieldInitializer => return error.Unimplemented,
1190 .EnumLiteral => return error.Unimplemented,1189 .EnumLiteral => return error.Unimplemented,
1190 .Noasync => return error.Unimplemented,
1191 }1191 }
1192 }1192 }
11931193
...@@ -1311,13 +1311,16 @@ pub const Builder = struct {...@@ -1311,13 +1311,16 @@ pub const Builder = struct {
1311 var base: u8 = undefined;1311 var base: u8 = undefined;
1312 var rest: []const u8 = undefined;1312 var rest: []const u8 = undefined;
1313 if (int_token.len >= 3 and int_token[0] == '0') {1313 if (int_token.len >= 3 and int_token[0] == '0') {
1314 base = switch (int_token[1]) {
1315 'b' => 2,
1316 'o' => 8,
1317 'x' => 16,
1318 else => unreachable,
1319 };
1320 rest = int_token[2..];1314 rest = int_token[2..];
1315 switch (int_token[1]) {
1316 'b' => base = 2,
1317 'o' => base = 8,
1318 'x' => base = 16,
1319 else => {
1320 base = 10;
1321 rest = int_token;
1322 },
1323 }
1321 } else {1324 } else {
1322 base = 10;1325 base = 10;
1323 rest = int_token;1326 rest = int_token;
src-self-hosted/libc_installation.zig+5-5
...@@ -280,7 +280,7 @@ pub const LibCInstallation = struct {...@@ -280,7 +280,7 @@ pub const LibCInstallation = struct {
280 // search in reverse order280 // search in reverse order
281 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);281 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
282 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");282 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
283 var search_dir = fs.cwd().openDirList(search_path) catch |err| switch (err) {283 var search_dir = fs.cwd().openDir(search_path, .{}) catch |err| switch (err) {
284 error.FileNotFound,284 error.FileNotFound,
285 error.NotDir,285 error.NotDir,
286 error.NoDevice,286 error.NoDevice,
...@@ -335,7 +335,7 @@ pub const LibCInstallation = struct {...@@ -335,7 +335,7 @@ pub const LibCInstallation = struct {
335 const stream = result_buf.outStream();335 const stream = result_buf.outStream();
336 try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version });336 try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version });
337337
338 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {338 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
339 error.FileNotFound,339 error.FileNotFound,
340 error.NotDir,340 error.NotDir,
341 error.NoDevice,341 error.NoDevice,
...@@ -382,7 +382,7 @@ pub const LibCInstallation = struct {...@@ -382,7 +382,7 @@ pub const LibCInstallation = struct {
382 const stream = result_buf.outStream();382 const stream = result_buf.outStream();
383 try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir });383 try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir });
384384
385 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {385 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
386 error.FileNotFound,386 error.FileNotFound,
387 error.NotDir,387 error.NotDir,
388 error.NoDevice,388 error.NoDevice,
...@@ -437,7 +437,7 @@ pub const LibCInstallation = struct {...@@ -437,7 +437,7 @@ pub const LibCInstallation = struct {
437 const stream = result_buf.outStream();437 const stream = result_buf.outStream();
438 try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir });438 try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir });
439439
440 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {440 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
441 error.FileNotFound,441 error.FileNotFound,
442 error.NotDir,442 error.NotDir,
443 error.NoDevice,443 error.NoDevice,
...@@ -475,7 +475,7 @@ pub const LibCInstallation = struct {...@@ -475,7 +475,7 @@ pub const LibCInstallation = struct {
475475
476 try result_buf.append("\\include");476 try result_buf.append("\\include");
477477
478 var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {478 var dir = fs.cwd().openDir(result_buf.toSliceConst(), .{}) catch |err| switch (err) {
479 error.FileNotFound,479 error.FileNotFound,
480 error.NotDir,480 error.NotDir,
481 error.NoDevice,481 error.NoDevice,
src-self-hosted/link.zig+54-58
...@@ -56,12 +56,13 @@ pub fn link(comp: *Compilation) !void {...@@ -56,12 +56,13 @@ pub fn link(comp: *Compilation) !void {
56 if (comp.haveLibC()) {56 if (comp.haveLibC()) {
57 // TODO https://github.com/ziglang/zig/issues/319057 // TODO https://github.com/ziglang/zig/issues/3190
58 var libc = ctx.comp.override_libc orelse blk: {58 var libc = ctx.comp.override_libc orelse blk: {
59 switch (comp.target) {59 @panic("this code has bitrotted");
60 Target.Native => {60 //switch (comp.target) {
61 break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;61 // Target.Native => {
62 },62 // break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
63 else => return error.LibCRequiredButNotProvidedOrFound,63 // },
64 }64 // else => return error.LibCRequiredButNotProvidedOrFound,
65 //}
65 };66 };
66 ctx.libc = libc;67 ctx.libc = libc;
67 }68 }
...@@ -155,11 +156,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -155,11 +156,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
155 //bool shared = !g->is_static && is_lib;156 //bool shared = !g->is_static && is_lib;
156 //Buf *soname = nullptr;157 //Buf *soname = nullptr;
157 if (ctx.comp.is_static) {158 if (ctx.comp.is_static) {
158 if (util.isArmOrThumb(ctx.comp.target)) {159 //if (util.isArmOrThumb(ctx.comp.target)) {
159 try ctx.args.append("-Bstatic");160 // try ctx.args.append("-Bstatic");
160 } else {161 //} else {
161 try ctx.args.append("-static");162 // try ctx.args.append("-static");
162 }163 //}
163 }164 }
164 //} else if (shared) {165 //} else if (shared) {
165 // lj->args.append("-shared");166 // lj->args.append("-shared");
...@@ -176,29 +177,24 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -176,29 +177,24 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
176177
177 if (ctx.link_in_crt) {178 if (ctx.link_in_crt) {
178 const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";179 const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
179 const crtbegino = if (ctx.comp.is_static) "crtbeginT.o" else "crtbegin.o";180 try addPathJoin(ctx, ctx.libc.crt_dir.?, crt1o);
180 try addPathJoin(ctx, ctx.libc.lib_dir.?, crt1o);181 try addPathJoin(ctx, ctx.libc.crt_dir.?, "crti.o");
181 try addPathJoin(ctx, ctx.libc.lib_dir.?, "crti.o");
182 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
183 }182 }
184183
185 if (ctx.comp.haveLibC()) {184 if (ctx.comp.haveLibC()) {
186 try ctx.args.append("-L");185 try ctx.args.append("-L");
187 // TODO addNullByte should probably return [:0]u8186 // TODO addNullByte should probably return [:0]u8
188 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr));187 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.crt_dir.?)).ptr));
189188
190 try ctx.args.append("-L");189 //if (!ctx.comp.is_static) {
191 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr));190 // const dl = blk: {
192191 // //if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
193 if (!ctx.comp.is_static) {192 // //if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
194 const dl = blk: {193 // return error.LibCMissingDynamicLinker;
195 if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;194 // };
196 if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;195 // try ctx.args.append("-dynamic-linker");
197 return error.LibCMissingDynamicLinker;196 // try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
198 };197 //}
199 try ctx.args.append("-dynamic-linker");
200 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
201 }
202 }198 }
203199
204 //if (shared) {200 //if (shared) {
...@@ -265,13 +261,12 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -265,13 +261,12 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
265261
266 // crt end262 // crt end
267 if (ctx.link_in_crt) {263 if (ctx.link_in_crt) {
268 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, "crtend.o");264 try addPathJoin(ctx, ctx.libc.crt_dir.?, "crtn.o");
269 try addPathJoin(ctx, ctx.libc.lib_dir.?, "crtn.o");
270 }265 }
271266
272 if (ctx.comp.target != Target.Native) {267 //if (ctx.comp.target != Target.Native) {
273 try ctx.args.append("--allow-shlib-undefined");268 // try ctx.args.append("--allow-shlib-undefined");
274 }269 //}
275}270}
276271
277fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {272fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
...@@ -287,7 +282,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -287,7 +282,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
287 try ctx.args.append("-DEBUG");282 try ctx.args.append("-DEBUG");
288 }283 }
289284
290 switch (ctx.comp.target.getArch()) {285 switch (ctx.comp.target.cpu.arch) {
291 .i386 => try ctx.args.append("-MACHINE:X86"),286 .i386 => try ctx.args.append("-MACHINE:X86"),
292 .x86_64 => try ctx.args.append("-MACHINE:X64"),287 .x86_64 => try ctx.args.append("-MACHINE:X64"),
293 .aarch64 => try ctx.args.append("-MACHINE:ARM"),288 .aarch64 => try ctx.args.append("-MACHINE:ARM"),
...@@ -302,7 +297,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -302,7 +297,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
302 if (ctx.comp.haveLibC()) {297 if (ctx.comp.haveLibC()) {
303 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));298 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
304 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));299 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
305 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));300 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.crt_dir.?})).ptr));
306 }301 }
307302
308 if (ctx.link_in_crt) {303 if (ctx.link_in_crt) {
...@@ -417,7 +412,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -417,7 +412,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
417 }412 }
418 },413 },
419 .IPhoneOS => {414 .IPhoneOS => {
420 if (ctx.comp.target.getArch() == .aarch64) {415 if (ctx.comp.target.cpu.arch == .aarch64) {
421 // iOS does not need any crt1 files for arm64416 // iOS does not need any crt1 files for arm64
422 } else if (platform.versionLessThan(3, 1)) {417 } else if (platform.versionLessThan(3, 1)) {
423 try ctx.args.append("-lcrt1.o");418 try ctx.args.append("-lcrt1.o");
...@@ -435,28 +430,29 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -435,28 +430,29 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
435 }430 }
436 try addFnObjects(ctx);431 try addFnObjects(ctx);
437432
438 if (ctx.comp.target == Target.Native) {433 // TODO
439 for (ctx.comp.link_libs_list.toSliceConst()) |lib| {434 //if (ctx.comp.target == Target.Native) {
440 if (mem.eql(u8, lib.name, "c")) {435 // for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
441 // on Darwin, libSystem has libc in it, but also you have to use it436 // if (mem.eql(u8, lib.name, "c")) {
442 // to make syscalls because the syscall numbers are not documented437 // // on Darwin, libSystem has libc in it, but also you have to use it
443 // and change between versions.438 // // to make syscalls because the syscall numbers are not documented
444 // so we always link against libSystem439 // // and change between versions.
445 try ctx.args.append("-lSystem");440 // // so we always link against libSystem
446 } else {441 // try ctx.args.append("-lSystem");
447 if (mem.indexOfScalar(u8, lib.name, '/') == null) {442 // } else {
448 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});443 // if (mem.indexOfScalar(u8, lib.name, '/') == null) {
449 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));444 // const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
450 } else {445 // try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
451 const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);446 // } else {
452 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));447 // const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
453 }448 // try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
454 }449 // }
455 }450 // }
456 } else {451 // }
457 try ctx.args.append("-undefined");452 //} else {
458 try ctx.args.append("dynamic_lookup");453 // try ctx.args.append("-undefined");
459 }454 // try ctx.args.append("dynamic_lookup");
455 //}
460456
461 if (platform.kind == .MacOS) {457 if (platform.kind == .MacOS) {
462 if (platform.versionLessThan(10, 5)) {458 if (platform.versionLessThan(10, 5)) {
src-self-hosted/main.zig+56-47
...@@ -18,10 +18,6 @@ const Target = std.Target;...@@ -18,10 +18,6 @@ const Target = std.Target;
18const errmsg = @import("errmsg.zig");18const errmsg = @import("errmsg.zig");
19const LibCInstallation = @import("libc_installation.zig").LibCInstallation;19const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
2020
21var stderr_file: fs.File = undefined;
22var stderr: *io.OutStream(fs.File.WriteError) = undefined;
23var stdout: *io.OutStream(fs.File.WriteError) = undefined;
24
25pub const io_mode = .evented;21pub const io_mode = .evented;
2622
27pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB23pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
...@@ -51,17 +47,14 @@ const Command = struct {...@@ -51,17 +47,14 @@ const Command = struct {
51pub fn main() !void {47pub fn main() !void {
52 const allocator = std.heap.c_allocator;48 const allocator = std.heap.c_allocator;
5349
54 stdout = &std.io.getStdOut().outStream().stream;50 const stderr = io.getStdErr().outStream();
55
56 stderr_file = std.io.getStdErr();
57 stderr = &stderr_file.outStream().stream;
5851
59 const args = try process.argsAlloc(allocator);52 const args = try process.argsAlloc(allocator);
60 defer process.argsFree(allocator, args);53 defer process.argsFree(allocator, args);
6154
62 if (args.len <= 1) {55 if (args.len <= 1) {
63 try stderr.write("expected command argument\n\n");56 try stderr.writeAll("expected command argument\n\n");
64 try stderr.write(usage);57 try stderr.writeAll(usage);
65 process.exit(1);58 process.exit(1);
66 }59 }
6760
...@@ -78,8 +71,8 @@ pub fn main() !void {...@@ -78,8 +71,8 @@ pub fn main() !void {
78 } else if (mem.eql(u8, cmd, "libc")) {71 } else if (mem.eql(u8, cmd, "libc")) {
79 return cmdLibC(allocator, cmd_args);72 return cmdLibC(allocator, cmd_args);
80 } else if (mem.eql(u8, cmd, "targets")) {73 } else if (mem.eql(u8, cmd, "targets")) {
81 const info = try std.zig.system.NativeTargetInfo.detect(allocator);74 const info = try std.zig.system.NativeTargetInfo.detect(allocator, .{});
82 defer info.deinit(allocator);75 const stdout = io.getStdOut().outStream();
83 return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, info.target);76 return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, info.target);
84 } else if (mem.eql(u8, cmd, "version")) {77 } else if (mem.eql(u8, cmd, "version")) {
85 return cmdVersion(allocator, cmd_args);78 return cmdVersion(allocator, cmd_args);
...@@ -91,7 +84,7 @@ pub fn main() !void {...@@ -91,7 +84,7 @@ pub fn main() !void {
91 return cmdInternal(allocator, cmd_args);84 return cmdInternal(allocator, cmd_args);
92 } else {85 } else {
93 try stderr.print("unknown command: {}\n\n", .{args[1]});86 try stderr.print("unknown command: {}\n\n", .{args[1]});
94 try stderr.write(usage);87 try stderr.writeAll(usage);
95 process.exit(1);88 process.exit(1);
96 }89 }
97}90}
...@@ -156,6 +149,8 @@ const usage_build_generic =...@@ -156,6 +149,8 @@ const usage_build_generic =
156;149;
157150
158fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {151fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
152 const stderr = io.getStdErr().outStream();
153
159 var color: errmsg.Color = .Auto;154 var color: errmsg.Color = .Auto;
160 var build_mode: std.builtin.Mode = .Debug;155 var build_mode: std.builtin.Mode = .Debug;
161 var emit_bin = true;156 var emit_bin = true;
...@@ -208,11 +203,11 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -208,11 +203,11 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
208 const arg = args[i];203 const arg = args[i];
209 if (mem.startsWith(u8, arg, "-")) {204 if (mem.startsWith(u8, arg, "-")) {
210 if (mem.eql(u8, arg, "--help")) {205 if (mem.eql(u8, arg, "--help")) {
211 try stdout.write(usage_build_generic);206 try io.getStdOut().writeAll(usage_build_generic);
212 process.exit(0);207 process.exit(0);
213 } else if (mem.eql(u8, arg, "--color")) {208 } else if (mem.eql(u8, arg, "--color")) {
214 if (i + 1 >= args.len) {209 if (i + 1 >= args.len) {
215 try stderr.write("expected [auto|on|off] after --color\n");210 try stderr.writeAll("expected [auto|on|off] after --color\n");
216 process.exit(1);211 process.exit(1);
217 }212 }
218 i += 1;213 i += 1;
...@@ -229,7 +224,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -229,7 +224,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
229 }224 }
230 } else if (mem.eql(u8, arg, "--mode")) {225 } else if (mem.eql(u8, arg, "--mode")) {
231 if (i + 1 >= args.len) {226 if (i + 1 >= args.len) {
232 try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");227 try stderr.writeAll("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");
233 process.exit(1);228 process.exit(1);
234 }229 }
235 i += 1;230 i += 1;
...@@ -248,49 +243,49 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -248,49 +243,49 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
248 }243 }
249 } else if (mem.eql(u8, arg, "--name")) {244 } else if (mem.eql(u8, arg, "--name")) {
250 if (i + 1 >= args.len) {245 if (i + 1 >= args.len) {
251 try stderr.write("expected parameter after --name\n");246 try stderr.writeAll("expected parameter after --name\n");
252 process.exit(1);247 process.exit(1);
253 }248 }
254 i += 1;249 i += 1;
255 provided_name = args[i];250 provided_name = args[i];
256 } else if (mem.eql(u8, arg, "--ver-major")) {251 } else if (mem.eql(u8, arg, "--ver-major")) {
257 if (i + 1 >= args.len) {252 if (i + 1 >= args.len) {
258 try stderr.write("expected parameter after --ver-major\n");253 try stderr.writeAll("expected parameter after --ver-major\n");
259 process.exit(1);254 process.exit(1);
260 }255 }
261 i += 1;256 i += 1;
262 version.major = try std.fmt.parseInt(u32, args[i], 10);257 version.major = try std.fmt.parseInt(u32, args[i], 10);
263 } else if (mem.eql(u8, arg, "--ver-minor")) {258 } else if (mem.eql(u8, arg, "--ver-minor")) {
264 if (i + 1 >= args.len) {259 if (i + 1 >= args.len) {
265 try stderr.write("expected parameter after --ver-minor\n");260 try stderr.writeAll("expected parameter after --ver-minor\n");
266 process.exit(1);261 process.exit(1);
267 }262 }
268 i += 1;263 i += 1;
269 version.minor = try std.fmt.parseInt(u32, args[i], 10);264 version.minor = try std.fmt.parseInt(u32, args[i], 10);
270 } else if (mem.eql(u8, arg, "--ver-patch")) {265 } else if (mem.eql(u8, arg, "--ver-patch")) {
271 if (i + 1 >= args.len) {266 if (i + 1 >= args.len) {
272 try stderr.write("expected parameter after --ver-patch\n");267 try stderr.writeAll("expected parameter after --ver-patch\n");
273 process.exit(1);268 process.exit(1);
274 }269 }
275 i += 1;270 i += 1;
276 version.patch = try std.fmt.parseInt(u32, args[i], 10);271 version.patch = try std.fmt.parseInt(u32, args[i], 10);
277 } else if (mem.eql(u8, arg, "--linker-script")) {272 } else if (mem.eql(u8, arg, "--linker-script")) {
278 if (i + 1 >= args.len) {273 if (i + 1 >= args.len) {
279 try stderr.write("expected parameter after --linker-script\n");274 try stderr.writeAll("expected parameter after --linker-script\n");
280 process.exit(1);275 process.exit(1);
281 }276 }
282 i += 1;277 i += 1;
283 linker_script = args[i];278 linker_script = args[i];
284 } else if (mem.eql(u8, arg, "--libc")) {279 } else if (mem.eql(u8, arg, "--libc")) {
285 if (i + 1 >= args.len) {280 if (i + 1 >= args.len) {
286 try stderr.write("expected parameter after --libc\n");281 try stderr.writeAll("expected parameter after --libc\n");
287 process.exit(1);282 process.exit(1);
288 }283 }
289 i += 1;284 i += 1;
290 libc_arg = args[i];285 libc_arg = args[i];
291 } else if (mem.eql(u8, arg, "-mllvm")) {286 } else if (mem.eql(u8, arg, "-mllvm")) {
292 if (i + 1 >= args.len) {287 if (i + 1 >= args.len) {
293 try stderr.write("expected parameter after -mllvm\n");288 try stderr.writeAll("expected parameter after -mllvm\n");
294 process.exit(1);289 process.exit(1);
295 }290 }
296 i += 1;291 i += 1;
...@@ -300,14 +295,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -300,14 +295,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
300 try mllvm_flags.append(args[i]);295 try mllvm_flags.append(args[i]);
301 } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {296 } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
302 if (i + 1 >= args.len) {297 if (i + 1 >= args.len) {
303 try stderr.write("expected parameter after -mmacosx-version-min\n");298 try stderr.writeAll("expected parameter after -mmacosx-version-min\n");
304 process.exit(1);299 process.exit(1);
305 }300 }
306 i += 1;301 i += 1;
307 macosx_version_min = args[i];302 macosx_version_min = args[i];
308 } else if (mem.eql(u8, arg, "-mios-version-min")) {303 } else if (mem.eql(u8, arg, "-mios-version-min")) {
309 if (i + 1 >= args.len) {304 if (i + 1 >= args.len) {
310 try stderr.write("expected parameter after -mios-version-min\n");305 try stderr.writeAll("expected parameter after -mios-version-min\n");
311 process.exit(1);306 process.exit(1);
312 }307 }
313 i += 1;308 i += 1;
...@@ -348,7 +343,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -348,7 +343,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
348 linker_rdynamic = true;343 linker_rdynamic = true;
349 } else if (mem.eql(u8, arg, "--pkg-begin")) {344 } else if (mem.eql(u8, arg, "--pkg-begin")) {
350 if (i + 2 >= args.len) {345 if (i + 2 >= args.len) {
351 try stderr.write("expected [name] [path] after --pkg-begin\n");346 try stderr.writeAll("expected [name] [path] after --pkg-begin\n");
352 process.exit(1);347 process.exit(1);
353 }348 }
354 i += 1;349 i += 1;
...@@ -363,7 +358,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -363,7 +358,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
363 if (cur_pkg.parent) |parent| {358 if (cur_pkg.parent) |parent| {
364 cur_pkg = parent;359 cur_pkg = parent;
365 } else {360 } else {
366 try stderr.write("encountered --pkg-end with no matching --pkg-begin\n");361 try stderr.writeAll("encountered --pkg-end with no matching --pkg-begin\n");
367 process.exit(1);362 process.exit(1);
368 }363 }
369 } else if (mem.startsWith(u8, arg, "-l")) {364 } else if (mem.startsWith(u8, arg, "-l")) {
...@@ -411,18 +406,18 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -411,18 +406,18 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
411 var it = mem.separate(basename, ".");406 var it = mem.separate(basename, ".");
412 break :blk it.next() orelse basename;407 break :blk it.next() orelse basename;
413 } else {408 } else {
414 try stderr.write("--name [name] not provided and unable to infer\n");409 try stderr.writeAll("--name [name] not provided and unable to infer\n");
415 process.exit(1);410 process.exit(1);
416 }411 }
417 };412 };
418413
419 if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) {414 if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) {
420 try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");415 try stderr.writeAll("Expected source file argument or at least one --object or --assembly argument\n");
421 process.exit(1);416 process.exit(1);
422 }417 }
423418
424 if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {419 if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {
425 try stderr.write("When building an object file, --object arguments are invalid\n");420 try stderr.writeAll("When building an object file, --object arguments are invalid\n");
426 process.exit(1);421 process.exit(1);
427 }422 }
428423
...@@ -440,7 +435,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -440,7 +435,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
440 &zig_compiler,435 &zig_compiler,
441 root_name,436 root_name,
442 root_src_file,437 root_src_file,
443 Target.Native,438 .{},
444 out_type,439 out_type,
445 build_mode,440 build_mode,
446 !is_dynamic,441 !is_dynamic,
...@@ -478,7 +473,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -478,7 +473,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
478 comp.linker_rdynamic = linker_rdynamic;473 comp.linker_rdynamic = linker_rdynamic;
479474
480 if (macosx_version_min != null and ios_version_min != null) {475 if (macosx_version_min != null and ios_version_min != null) {
481 try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");476 try stderr.writeAll("-mmacosx-version-min and -mios-version-min options not allowed together\n");
482 process.exit(1);477 process.exit(1);
483 }478 }
484479
...@@ -501,6 +496,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -501,6 +496,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
501}496}
502497
503fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {498fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
499 const stderr_file = io.getStdErr();
500 const stderr = stderr_file.outStream();
504 var count: usize = 0;501 var count: usize = 0;
505 while (!comp.cancelled) {502 while (!comp.cancelled) {
506 const build_event = comp.events.get();503 const build_event = comp.events.get();
...@@ -551,7 +548,8 @@ const Fmt = struct {...@@ -551,7 +548,8 @@ const Fmt = struct {
551};548};
552549
553fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {550fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {
554 libc.parse(allocator, libc_paths_file, stderr) catch |err| {551 const stderr = io.getStdErr().outStream();
552 libc.* = LibCInstallation.parse(allocator, libc_paths_file, stderr) catch |err| {
555 stderr.print("Unable to parse libc path file '{}': {}.\n" ++553 stderr.print("Unable to parse libc path file '{}': {}.\n" ++
556 "Try running `zig libc` to see an example for the native target.\n", .{554 "Try running `zig libc` to see an example for the native target.\n", .{
557 libc_paths_file,555 libc_paths_file,
...@@ -562,6 +560,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil...@@ -562,6 +560,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil
562}560}
563561
564fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {562fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
563 const stderr = io.getStdErr().outStream();
565 switch (args.len) {564 switch (args.len) {
566 0 => {},565 0 => {},
567 1 => {566 1 => {
...@@ -582,10 +581,12 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {...@@ -582,10 +581,12 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
582 stderr.print("unable to find libc: {}\n", .{@errorName(err)}) catch {};581 stderr.print("unable to find libc: {}\n", .{@errorName(err)}) catch {};
583 process.exit(1);582 process.exit(1);
584 };583 };
585 libc.render(stdout) catch process.exit(1);584 libc.render(io.getStdOut().outStream()) catch process.exit(1);
586}585}
587586
588fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {587fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
588 const stderr_file = io.getStdErr();
589 const stderr = stderr_file.outStream();
589 var color: errmsg.Color = .Auto;590 var color: errmsg.Color = .Auto;
590 var stdin_flag: bool = false;591 var stdin_flag: bool = false;
591 var check_flag: bool = false;592 var check_flag: bool = false;
...@@ -597,11 +598,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -597,11 +598,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
597 const arg = args[i];598 const arg = args[i];
598 if (mem.startsWith(u8, arg, "-")) {599 if (mem.startsWith(u8, arg, "-")) {
599 if (mem.eql(u8, arg, "--help")) {600 if (mem.eql(u8, arg, "--help")) {
600 try stdout.write(usage_fmt);601 const stdout = io.getStdOut().outStream();
602 try stdout.writeAll(usage_fmt);
601 process.exit(0);603 process.exit(0);
602 } else if (mem.eql(u8, arg, "--color")) {604 } else if (mem.eql(u8, arg, "--color")) {
603 if (i + 1 >= args.len) {605 if (i + 1 >= args.len) {
604 try stderr.write("expected [auto|on|off] after --color\n");606 try stderr.writeAll("expected [auto|on|off] after --color\n");
605 process.exit(1);607 process.exit(1);
606 }608 }
607 i += 1;609 i += 1;
...@@ -632,14 +634,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -632,14 +634,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
632634
633 if (stdin_flag) {635 if (stdin_flag) {
634 if (input_files.len != 0) {636 if (input_files.len != 0) {
635 try stderr.write("cannot use --stdin with positional arguments\n");637 try stderr.writeAll("cannot use --stdin with positional arguments\n");
636 process.exit(1);638 process.exit(1);
637 }639 }
638640
639 var stdin_file = io.getStdIn();641 const stdin = io.getStdIn().inStream();
640 var stdin = stdin_file.inStream();
641642
642 const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);643 const source_code = try stdin.readAllAlloc(allocator, max_src_size);
643 defer allocator.free(source_code);644 defer allocator.free(source_code);
644645
645 const tree = std.zig.parse(allocator, source_code) catch |err| {646 const tree = std.zig.parse(allocator, source_code) catch |err| {
...@@ -653,7 +654,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -653,7 +654,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
653 const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>");654 const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>");
654 defer msg.destroy();655 defer msg.destroy();
655656
656 try msg.printToFile(stderr_file, color);657 try msg.printToFile(io.getStdErr(), color);
657 }658 }
658 if (tree.errors.len != 0) {659 if (tree.errors.len != 0) {
659 process.exit(1);660 process.exit(1);
...@@ -664,12 +665,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -664,12 +665,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
664 process.exit(code);665 process.exit(code);
665 }666 }
666667
668 const stdout = io.getStdOut().outStream();
667 _ = try std.zig.render(allocator, stdout, tree);669 _ = try std.zig.render(allocator, stdout, tree);
668 return;670 return;
669 }671 }
670672
671 if (input_files.len == 0) {673 if (input_files.len == 0) {
672 try stderr.write("expected at least one source file argument\n");674 try stderr.writeAll("expected at least one source file argument\n");
673 process.exit(1);675 process.exit(1);
674 }676 }
675677
...@@ -713,6 +715,9 @@ const FmtError = error{...@@ -713,6 +715,9 @@ const FmtError = error{
713} || fs.File.OpenError;715} || fs.File.OpenError;
714716
715async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {717async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
718 const stderr_file = io.getStdErr();
719 const stderr = stderr_file.outStream();
720
716 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);721 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
717 defer fmt.allocator.free(file_path);722 defer fmt.allocator.free(file_path);
718723
...@@ -729,7 +734,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -729,7 +734,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
729 max_src_size,734 max_src_size,
730 ) catch |err| switch (err) {735 ) catch |err| switch (err) {
731 error.IsDir, error.AccessDenied => {736 error.IsDir, error.AccessDenied => {
732 var dir = try fs.cwd().openDirList(file_path);737 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
733 defer dir.close();738 defer dir.close();
734739
735 var group = event.Group(FmtError!void).init(fmt.allocator);740 var group = event.Group(FmtError!void).init(fmt.allocator);
...@@ -791,11 +796,13 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -791,11 +796,13 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
791}796}
792797
793fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {798fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
799 const stdout = io.getStdOut().outStream();
794 try stdout.print("{}\n", .{c.ZIG_VERSION_STRING});800 try stdout.print("{}\n", .{c.ZIG_VERSION_STRING});
795}801}
796802
797fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {803fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
798 try stdout.write(usage);804 const stdout = io.getStdOut();
805 try stdout.writeAll(usage);
799}806}
800807
801pub const info_zen =808pub const info_zen =
...@@ -816,7 +823,7 @@ pub const info_zen =...@@ -816,7 +823,7 @@ pub const info_zen =
816;823;
817824
818fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {825fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {
819 try stdout.write(info_zen);826 try io.getStdOut().writeAll(info_zen);
820}827}
821828
822const usage_internal =829const usage_internal =
...@@ -829,8 +836,9 @@ const usage_internal =...@@ -829,8 +836,9 @@ const usage_internal =
829;836;
830837
831fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {838fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
839 const stderr = io.getStdErr().outStream();
832 if (args.len == 0) {840 if (args.len == 0) {
833 try stderr.write(usage_internal);841 try stderr.writeAll(usage_internal);
834 process.exit(1);842 process.exit(1);
835 }843 }
836844
...@@ -849,10 +857,11 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {...@@ -849,10 +857,11 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
849 }857 }
850858
851 try stderr.print("unknown sub command: {}\n\n", .{args[0]});859 try stderr.print("unknown sub command: {}\n\n", .{args[0]});
852 try stderr.write(usage_internal);860 try stderr.writeAll(usage_internal);
853}861}
854862
855fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {863fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
864 const stdout = io.getStdOut().outStream();
856 try stdout.print(865 try stdout.print(
857 \\ZIG_CMAKE_BINARY_DIR {}866 \\ZIG_CMAKE_BINARY_DIR {}
858 \\ZIG_CXX_COMPILER {}867 \\ZIG_CXX_COMPILER {}
src-self-hosted/print_targets.zig+1-1
...@@ -72,7 +72,7 @@ pub fn cmdTargets(...@@ -72,7 +72,7 @@ pub fn cmdTargets(
72 };72 };
73 defer allocator.free(zig_lib_dir);73 defer allocator.free(zig_lib_dir);
7474
75 var dir = try std.fs.cwd().openDirList(zig_lib_dir);75 var dir = try std.fs.cwd().openDir(zig_lib_dir, .{});
76 defer dir.close();76 defer dir.close();
7777
78 const vers_txt = try dir.readFileAlloc(allocator, "libc/glibc/vers.txt", 10 * 1024);78 const vers_txt = try dir.readFileAlloc(allocator, "libc/glibc/vers.txt", 10 * 1024);
src-self-hosted/stage2.zig+187-2
...@@ -113,6 +113,10 @@ const Error = extern enum {...@@ -113,6 +113,10 @@ const Error = extern enum {
113 TargetHasNoDynamicLinker,113 TargetHasNoDynamicLinker,
114 InvalidAbiVersion,114 InvalidAbiVersion,
115 InvalidOperatingSystemVersion,115 InvalidOperatingSystemVersion,
116 UnknownClangOption,
117 PermissionDenied,
118 FileBusy,
119 Locked,
116};120};
117121
118const FILE = std.c.FILE;122const FILE = std.c.FILE;
...@@ -128,7 +132,7 @@ export fn stage2_translate_c(...@@ -128,7 +132,7 @@ export fn stage2_translate_c(
128 args_end: [*]?[*]const u8,132 args_end: [*]?[*]const u8,
129 resources_path: [*:0]const u8,133 resources_path: [*:0]const u8,
130) Error {134) Error {
131 var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];135 var errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
132 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {136 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
133 error.SemanticAnalyzeFail => {137 error.SemanticAnalyzeFail => {
134 out_errors_ptr.* = errors.ptr;138 out_errors_ptr.* = errors.ptr;
...@@ -319,7 +323,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {...@@ -319,7 +323,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
319 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {323 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
320 error.IsDir, error.AccessDenied => {324 error.IsDir, error.AccessDenied => {
321 // TODO make event based (and dir.next())325 // TODO make event based (and dir.next())
322 var dir = try fs.cwd().openDirList(file_path);326 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
323 defer dir.close();327 defer dir.close();
324328
325 var dir_it = dir.iterate();329 var dir_it = dir.iterate();
...@@ -843,6 +847,9 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [...@@ -843,6 +847,9 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [
843 error.NoDevice => return .NoDevice,847 error.NoDevice => return .NoDevice,
844 error.NotDir => return .NotDir,848 error.NotDir => return .NotDir,
845 error.DeviceBusy => return .DeviceBusy,849 error.DeviceBusy => return .DeviceBusy,
850 error.PermissionDenied => return .PermissionDenied,
851 error.FileBusy => return .FileBusy,
852 error.Locked => return .Locked,
846 };853 };
847 stage1_libc.initFromStage2(libc);854 stage1_libc.initFromStage2(libc);
848 return .None;855 return .None;
...@@ -909,6 +916,7 @@ const Stage2Target = extern struct {...@@ -909,6 +916,7 @@ const Stage2Target = extern struct {
909 os_builtin_str: ?[*:0]const u8,916 os_builtin_str: ?[*:0]const u8,
910917
911 dynamic_linker: ?[*:0]const u8,918 dynamic_linker: ?[*:0]const u8,
919 standard_dynamic_linker_path: ?[*:0]const u8,
912920
913 fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {921 fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
914 const allocator = std.heap.c_allocator;922 const allocator = std.heap.c_allocator;
...@@ -1119,6 +1127,12 @@ const Stage2Target = extern struct {...@@ -1119,6 +1127,12 @@ const Stage2Target = extern struct {
1119 }1127 }
1120 };1128 };
11211129
1130 const std_dl = target.standardDynamicLinkerPath();
1131 const std_dl_z = if (std_dl.get()) |dl|
1132 (try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr
1133 else
1134 null;
1135
1122 const cache_hash_slice = cache_hash.toOwnedSlice();1136 const cache_hash_slice = cache_hash.toOwnedSlice();
1123 self.* = .{1137 self.* = .{
1124 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch1138 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
...@@ -1134,6 +1148,7 @@ const Stage2Target = extern struct {...@@ -1134,6 +1148,7 @@ const Stage2Target = extern struct {
1134 .is_native = cross_target.isNative(),1148 .is_native = cross_target.isNative(),
1135 .glibc_or_darwin_version = glibc_or_darwin_version,1149 .glibc_or_darwin_version = glibc_or_darwin_version,
1136 .dynamic_linker = dynamic_linker,1150 .dynamic_linker = dynamic_linker,
1151 .standard_dynamic_linker_path = std_dl_z,
1137 };1152 };
1138 }1153 }
1139};1154};
...@@ -1207,3 +1222,173 @@ fn convertSlice(slice: [][:0]u8, ptr: *[*][*:0]u8, len: *usize) !void {...@@ -1207,3 +1222,173 @@ fn convertSlice(slice: [][:0]u8, ptr: *[*][*:0]u8, len: *usize) !void {
1207 }1222 }
1208 ptr.* = new_slice.ptr;1223 ptr.* = new_slice.ptr;
1209}1224}
1225
1226const clang_args = @import("clang_options.zig").list;
1227
1228// ABI warning
1229pub const ClangArgIterator = extern struct {
1230 has_next: bool,
1231 zig_equivalent: ZigEquivalent,
1232 only_arg: [*:0]const u8,
1233 second_arg: [*:0]const u8,
1234 other_args_ptr: [*]const [*:0]const u8,
1235 other_args_len: usize,
1236 argv_ptr: [*]const [*:0]const u8,
1237 argv_len: usize,
1238 next_index: usize,
1239
1240 // ABI warning
1241 pub const ZigEquivalent = extern enum {
1242 target,
1243 o,
1244 c,
1245 other,
1246 positional,
1247 l,
1248 ignore,
1249 driver_punt,
1250 pic,
1251 no_pic,
1252 nostdlib,
1253 shared,
1254 rdynamic,
1255 wl,
1256 preprocess,
1257 optimize,
1258 debug,
1259 sanitize,
1260 };
1261
1262 fn init(argv: []const [*:0]const u8) ClangArgIterator {
1263 return .{
1264 .next_index = 2, // `zig cc foo` this points to `foo`
1265 .has_next = argv.len > 2,
1266 .zig_equivalent = undefined,
1267 .only_arg = undefined,
1268 .second_arg = undefined,
1269 .other_args_ptr = undefined,
1270 .other_args_len = undefined,
1271 .argv_ptr = argv.ptr,
1272 .argv_len = argv.len,
1273 };
1274 }
1275
1276 fn next(self: *ClangArgIterator) !void {
1277 assert(self.has_next);
1278 assert(self.next_index < self.argv_len);
1279 // In this state we know that the parameter we are looking at is a root parameter
1280 // rather than an argument to a parameter.
1281 self.other_args_ptr = self.argv_ptr + self.next_index;
1282 self.other_args_len = 1; // We adjust this value below when necessary.
1283 const arg = mem.span(self.argv_ptr[self.next_index]);
1284 self.next_index += 1;
1285 defer {
1286 if (self.next_index >= self.argv_len) self.has_next = false;
1287 }
1288
1289 if (!mem.startsWith(u8, arg, "-")) {
1290 self.zig_equivalent = .positional;
1291 self.only_arg = arg.ptr;
1292 return;
1293 }
1294
1295 find_clang_arg: for (clang_args) |clang_arg| switch (clang_arg.syntax) {
1296 .flag => {
1297 const prefix_len = clang_arg.matchEql(arg);
1298 if (prefix_len > 0) {
1299 self.zig_equivalent = clang_arg.zig_equivalent;
1300 self.only_arg = arg.ptr + prefix_len;
1301
1302 break :find_clang_arg;
1303 }
1304 },
1305 .joined, .comma_joined => {
1306 // joined example: --target=foo
1307 // comma_joined example: -Wl,-soname,libsoundio.so.2
1308 const prefix_len = clang_arg.matchStartsWith(arg);
1309 if (prefix_len != 0) {
1310 self.zig_equivalent = clang_arg.zig_equivalent;
1311 self.only_arg = arg.ptr + prefix_len; // This will skip over the "--target=" part.
1312
1313 break :find_clang_arg;
1314 }
1315 },
1316 .joined_or_separate => {
1317 // Examples: `-lfoo`, `-l foo`
1318 const prefix_len = clang_arg.matchStartsWith(arg);
1319 if (prefix_len == arg.len) {
1320 if (self.next_index >= self.argv_len) {
1321 std.debug.warn("Expected parameter after '{}'\n", .{arg});
1322 process.exit(1);
1323 }
1324 self.only_arg = self.argv_ptr[self.next_index];
1325 self.next_index += 1;
1326 self.other_args_len += 1;
1327 self.zig_equivalent = clang_arg.zig_equivalent;
1328
1329 break :find_clang_arg;
1330 } else if (prefix_len != 0) {
1331 self.zig_equivalent = clang_arg.zig_equivalent;
1332 self.only_arg = arg.ptr + prefix_len;
1333
1334 break :find_clang_arg;
1335 }
1336 },
1337 .joined_and_separate => {
1338 // Example: `-Xopenmp-target=riscv64-linux-unknown foo`
1339 const prefix_len = clang_arg.matchStartsWith(arg);
1340 if (prefix_len != 0) {
1341 self.only_arg = arg.ptr + prefix_len;
1342 if (self.next_index >= self.argv_len) {
1343 std.debug.warn("Expected parameter after '{}'\n", .{arg});
1344 process.exit(1);
1345 }
1346 self.second_arg = self.argv_ptr[self.next_index];
1347 self.next_index += 1;
1348 self.other_args_len += 1;
1349 self.zig_equivalent = clang_arg.zig_equivalent;
1350 break :find_clang_arg;
1351 }
1352 },
1353 .separate => if (clang_arg.matchEql(arg) > 0) {
1354 if (self.next_index >= self.argv_len) {
1355 std.debug.warn("Expected parameter after '{}'\n", .{arg});
1356 process.exit(1);
1357 }
1358 self.only_arg = self.argv_ptr[self.next_index];
1359 self.next_index += 1;
1360 self.other_args_len += 1;
1361 self.zig_equivalent = clang_arg.zig_equivalent;
1362 break :find_clang_arg;
1363 },
1364 .remaining_args_joined => {
1365 const prefix_len = clang_arg.matchStartsWith(arg);
1366 if (prefix_len != 0) {
1367 @panic("TODO");
1368 }
1369 },
1370 .multi_arg => if (clang_arg.matchEql(arg) > 0) {
1371 @panic("TODO");
1372 },
1373 }
1374 else {
1375 std.debug.warn("Unknown Clang option: '{}'\n", .{arg});
1376 process.exit(1);
1377 }
1378 }
1379};
1380
1381export fn stage2_clang_arg_iterator(
1382 result: *ClangArgIterator,
1383 argc: usize,
1384 argv: [*]const [*:0]const u8,
1385) void {
1386 result.* = ClangArgIterator.init(argv[0..argc]);
1387}
1388
1389export fn stage2_clang_arg_next(it: *ClangArgIterator) Error {
1390 it.next() catch |err| switch (err) {
1391 error.UnknownClangOption => return .UnknownClangOption,
1392 };
1393 return .None;
1394}
src-self-hosted/test.zig+2-2
...@@ -57,11 +57,11 @@ pub const TestContext = struct {...@@ -57,11 +57,11 @@ pub const TestContext = struct {
57 errdefer allocator.free(self.zig_lib_dir);57 errdefer allocator.free(self.zig_lib_dir);
5858
59 try std.fs.cwd().makePath(tmp_dir_name);59 try std.fs.cwd().makePath(tmp_dir_name);
60 errdefer std.fs.deleteTree(tmp_dir_name) catch {};60 errdefer std.fs.cwd().deleteTree(tmp_dir_name) catch {};
61 }61 }
6262
63 fn deinit(self: *TestContext) void {63 fn deinit(self: *TestContext) void {
64 std.fs.deleteTree(tmp_dir_name) catch {};64 std.fs.cwd().deleteTree(tmp_dir_name) catch {};
65 allocator.free(self.zig_lib_dir);65 allocator.free(self.zig_lib_dir);
66 self.zig_compiler.deinit();66 self.zig_compiler.deinit();
67 }67 }
src-self-hosted/translate_c.zig+12-14
...@@ -1744,20 +1744,18 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {...@@ -1744,20 +1744,18 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {
1744// Returns either a string literal or a slice of `buf`.1744// Returns either a string literal or a slice of `buf`.
1745fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {1745fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
1746 return switch (c) {1746 return switch (c) {
1747 '\"' => "\\\""[0..],1747 '\"' => "\\\"",
1748 '\'' => "\\'"[0..],1748 '\'' => "\\'",
1749 '\\' => "\\\\"[0..],1749 '\\' => "\\\\",
1750 '\n' => "\\n"[0..],1750 '\n' => "\\n",
1751 '\r' => "\\r"[0..],1751 '\r' => "\\r",
1752 '\t' => "\\t"[0..],1752 '\t' => "\\t",
1753 else => {1753 // Handle the remaining escapes Zig doesn't support by turning them
1754 // Handle the remaining escapes Zig doesn't support by turning them1754 // into their respective hex representation
1755 // into their respective hex representation1755 else => if (std.ascii.isCntrl(c))
1756 if (std.ascii.isCntrl(c))1756 std.fmt.bufPrint(char_buf, "\\x{x:0<2}", .{c}) catch unreachable
1757 return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable1757 else
1758 else1758 std.fmt.bufPrint(char_buf, "{c}", .{c}) catch unreachable,
1759 return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
1760 },
1761 };1759 };
1762}1760}
17631761
src-self-hosted/util.zig+13-2
...@@ -3,8 +3,7 @@ const Target = std.Target;...@@ -3,8 +3,7 @@ const Target = std.Target;
3const llvm = @import("llvm.zig");3const llvm = @import("llvm.zig");
44
5pub fn getDarwinArchString(self: Target) [:0]const u8 {5pub fn getDarwinArchString(self: Target) [:0]const u8 {
6 const arch = self.getArch();6 switch (self.cpu.arch) {
7 switch (arch) {
8 .aarch64 => return "arm64",7 .aarch64 => return "arm64",
9 .thumb,8 .thumb,
10 .arm,9 .arm,
...@@ -34,3 +33,15 @@ pub fn initializeAllTargets() void {...@@ -34,3 +33,15 @@ pub fn initializeAllTargets() void {
34 llvm.InitializeAllAsmPrinters();33 llvm.InitializeAllAsmPrinters();
35 llvm.InitializeAllAsmParsers();34 llvm.InitializeAllAsmParsers();
36}35}
36
37pub fn getLLVMTriple(allocator: *std.mem.Allocator, target: std.Target) !std.Buffer {
38 var result = try std.Buffer.initSize(allocator, 0);
39 errdefer result.deinit();
40
41 try result.outStream().print(
42 "{}-unknown-{}-{}",
43 .{ @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi) },
44 );
45
46 return result;
47}
src/all_types.hpp+10
...@@ -231,6 +231,7 @@ enum ConstPtrSpecial {...@@ -231,6 +231,7 @@ enum ConstPtrSpecial {
231 // The pointer is a reference to a single object.231 // The pointer is a reference to a single object.
232 ConstPtrSpecialRef,232 ConstPtrSpecialRef,
233 // The pointer points to an element in an underlying array.233 // The pointer points to an element in an underlying array.
234 // Not to be confused with ConstPtrSpecialSubArray.
234 ConstPtrSpecialBaseArray,235 ConstPtrSpecialBaseArray,
235 // The pointer points to a field in an underlying struct.236 // The pointer points to a field in an underlying struct.
236 ConstPtrSpecialBaseStruct,237 ConstPtrSpecialBaseStruct,
...@@ -257,6 +258,10 @@ enum ConstPtrSpecial {...@@ -257,6 +258,10 @@ enum ConstPtrSpecial {
257 // types to be the same, so all optionals of pointer types use x_ptr258 // types to be the same, so all optionals of pointer types use x_ptr
258 // instead of x_optional.259 // instead of x_optional.
259 ConstPtrSpecialNull,260 ConstPtrSpecialNull,
261 // The pointer points to a sub-array (not an individual element).
262 // Not to be confused with ConstPtrSpecialBaseArray. However, it uses the same
263 // union payload struct (base_array).
264 ConstPtrSpecialSubArray,
260};265};
261266
262enum ConstPtrMut {267enum ConstPtrMut {
...@@ -739,6 +744,7 @@ struct AstNodeReturnExpr {...@@ -739,6 +744,7 @@ struct AstNodeReturnExpr {
739744
740struct AstNodeDefer {745struct AstNodeDefer {
741 ReturnKind kind;746 ReturnKind kind;
747 AstNode *err_payload;
742 AstNode *expr;748 AstNode *expr;
743749
744 // temporary data used in IR generation750 // temporary data used in IR generation
...@@ -1997,6 +2003,7 @@ enum WantCSanitize {...@@ -1997,6 +2003,7 @@ enum WantCSanitize {
1997struct CFile {2003struct CFile {
1998 ZigList<const char *> args;2004 ZigList<const char *> args;
1999 const char *source_path;2005 const char *source_path;
2006 const char *preprocessor_only_basename;
2000};2007};
20012008
2002// When adding fields, check if they should be added to the hash computation in build_with_cache2009// When adding fields, check if they should be added to the hash computation in build_with_cache
...@@ -2141,6 +2148,7 @@ struct CodeGen {...@@ -2141,6 +2148,7 @@ struct CodeGen {
2141 // As an input parameter, mutually exclusive with enable_cache. But it gets2148 // As an input parameter, mutually exclusive with enable_cache. But it gets
2142 // populated in codegen_build_and_link.2149 // populated in codegen_build_and_link.
2143 Buf *output_dir;2150 Buf *output_dir;
2151 Buf *c_artifact_dir;
2144 const char **libc_include_dir_list;2152 const char **libc_include_dir_list;
2145 size_t libc_include_dir_len;2153 size_t libc_include_dir_len;
21462154
...@@ -2262,6 +2270,7 @@ struct CodeGen {...@@ -2262,6 +2270,7 @@ struct CodeGen {
2262 Buf *zig_lib_dir;2270 Buf *zig_lib_dir;
2263 Buf *zig_std_dir;2271 Buf *zig_std_dir;
2264 Buf *version_script_path;2272 Buf *version_script_path;
2273 Buf *override_soname;
22652274
2266 const char **llvm_argv;2275 const char **llvm_argv;
2267 size_t llvm_argv_len;2276 size_t llvm_argv_len;
...@@ -3706,6 +3715,7 @@ struct IrInstGenSlice {...@@ -3706,6 +3715,7 @@ struct IrInstGenSlice {
3706 IrInstGen *start;3715 IrInstGen *start;
3707 IrInstGen *end;3716 IrInstGen *end;
3708 IrInstGen *result_loc;3717 IrInstGen *result_loc;
3718 ZigValue *sentinel;
3709 bool safety_check_on;3719 bool safety_check_on;
3710};3720};
37113721
src/analyze.cpp+36-20
...@@ -780,6 +780,8 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa...@@ -780,6 +780,8 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
780}780}
781781
782ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ZigValue *sentinel) {782ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ZigValue *sentinel) {
783 Error err;
784
783 TypeId type_id = {};785 TypeId type_id = {};
784 type_id.id = ZigTypeIdArray;786 type_id.id = ZigTypeIdArray;
785 type_id.data.array.codegen = g;787 type_id.data.array.codegen = g;
...@@ -791,7 +793,11 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi...@@ -791,7 +793,11 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
791 return existing_entry->value;793 return existing_entry->value;
792 }794 }
793795
794 assert(type_is_resolved(child_type, ResolveStatusSizeKnown));796 size_t full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
797
798 if (full_array_size != 0 && (err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
799 codegen_report_errors_and_exit(g);
800 }
795801
796 ZigType *entry = new_type_table_entry(ZigTypeIdArray);802 ZigType *entry = new_type_table_entry(ZigTypeIdArray);
797803
...@@ -803,15 +809,8 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi...@@ -803,15 +809,8 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
803 }809 }
804 buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));810 buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));
805811
806 size_t full_array_size;
807 if (array_size == 0) {
808 full_array_size = 0;
809 } else {
810 full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
811 }
812
813 entry->size_in_bits = child_type->size_in_bits * full_array_size;812 entry->size_in_bits = child_type->size_in_bits * full_array_size;
814 entry->abi_align = child_type->abi_align;813 entry->abi_align = (full_array_size == 0) ? 0 : child_type->abi_align;
815 entry->abi_size = child_type->abi_size * full_array_size;814 entry->abi_size = child_type->abi_size * full_array_size;
816815
817 entry->data.array.child_type = child_type;816 entry->data.array.child_type = child_type;
...@@ -1197,7 +1196,8 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent...@@ -1197,7 +1196,8 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
1197 LazyValueArrayType *lazy_array_type =1196 LazyValueArrayType *lazy_array_type =
1198 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);1197 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
11991198
1200 if (lazy_array_type->length < 1) {1199 // The sentinel counts as an extra element
1200 if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) {
1201 *is_zero_bits = true;1201 *is_zero_bits = true;
1202 return ErrorNone;1202 return ErrorNone;
1203 }1203 }
...@@ -1452,7 +1452,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV...@@ -1452,7 +1452,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
1452 case LazyValueIdArrayType: {1452 case LazyValueIdArrayType: {
1453 LazyValueArrayType *lazy_array_type =1453 LazyValueArrayType *lazy_array_type =
1454 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);1454 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1455 if (lazy_array_type->length < 1)1455 if (lazy_array_type->length == 0)
1456 return OnePossibleValueYes;1456 return OnePossibleValueYes;
1457 return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);1457 return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
1458 }1458 }
...@@ -4488,7 +4488,14 @@ static uint32_t get_async_frame_align_bytes(CodeGen *g) {...@@ -4488,7 +4488,14 @@ static uint32_t get_async_frame_align_bytes(CodeGen *g) {
4488}4488}
44894489
4490uint32_t get_ptr_align(CodeGen *g, ZigType *type) {4490uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
4491 ZigType *ptr_type = get_src_ptr_type(type);4491 ZigType *ptr_type;
4492 if (type->id == ZigTypeIdStruct) {
4493 assert(type->data.structure.special == StructSpecialSlice);
4494 TypeStructField *ptr_field = type->data.structure.fields[slice_ptr_index];
4495 ptr_type = resolve_struct_field_type(g, ptr_field);
4496 } else {
4497 ptr_type = get_src_ptr_type(type);
4498 }
4492 if (ptr_type->id == ZigTypeIdPointer) {4499 if (ptr_type->id == ZigTypeIdPointer) {
4493 return (ptr_type->data.pointer.explicit_alignment == 0) ?4500 return (ptr_type->data.pointer.explicit_alignment == 0) ?
4494 get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;4501 get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
...@@ -4505,8 +4512,15 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {...@@ -4505,8 +4512,15 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
4505 }4512 }
4506}4513}
45074514
4508bool get_ptr_const(ZigType *type) {4515bool get_ptr_const(CodeGen *g, ZigType *type) {
4509 ZigType *ptr_type = get_src_ptr_type(type);4516 ZigType *ptr_type;
4517 if (type->id == ZigTypeIdStruct) {
4518 assert(type->data.structure.special == StructSpecialSlice);
4519 TypeStructField *ptr_field = type->data.structure.fields[slice_ptr_index];
4520 ptr_type = resolve_struct_field_type(g, ptr_field);
4521 } else {
4522 ptr_type = get_src_ptr_type(type);
4523 }
4510 if (ptr_type->id == ZigTypeIdPointer) {4524 if (ptr_type->id == ZigTypeIdPointer) {
4511 return ptr_type->data.pointer.is_const;4525 return ptr_type->data.pointer.is_const;
4512 } else if (ptr_type->id == ZigTypeIdFn) {4526 } else if (ptr_type->id == ZigTypeIdFn) {
...@@ -5282,6 +5296,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) {...@@ -5282,6 +5296,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) {
5282 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);5296 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
5283 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);5297 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
5284 return hash_val;5298 return hash_val;
5299 case ConstPtrSpecialSubArray:
5300 hash_val += (uint32_t)2643358777;
5301 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
5302 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
5303 return hash_val;
5285 case ConstPtrSpecialBaseStruct:5304 case ConstPtrSpecialBaseStruct:
5286 hash_val += (uint32_t)3518317043;5305 hash_val += (uint32_t)3518317043;
5287 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);5306 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
...@@ -5811,18 +5830,13 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5811,18 +5830,13 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
5811 // The elements array cannot be left unpopulated5830 // The elements array cannot be left unpopulated
5812 ZigType *array_type = result->type;5831 ZigType *array_type = result->type;
5813 ZigType *elem_type = array_type->data.array.child_type;5832 ZigType *elem_type = array_type->data.array.child_type;
5814 ZigValue *sentinel_value = array_type->data.array.sentinel;5833 const size_t elem_count = array_type->data.array.len;
5815 const size_t elem_count = array_type->data.array.len + (sentinel_value != nullptr);
58165834
5817 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);5835 result->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(elem_count);
5818 for (size_t i = 0; i < elem_count; i += 1) {5836 for (size_t i = 0; i < elem_count; i += 1) {
5819 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];5837 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
5820 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));5838 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
5821 }5839 }
5822 if (sentinel_value != nullptr) {
5823 ZigValue *last_elem_val = &result->data.x_array.data.s_none.elements[elem_count - 1];
5824 copy_const_val(g, last_elem_val, sentinel_value);
5825 }
5826 } else if (result->type->id == ZigTypeIdPointer) {5840 } else if (result->type->id == ZigTypeIdPointer) {
5827 result->data.x_ptr.special = ConstPtrSpecialRef;5841 result->data.x_ptr.special = ConstPtrSpecialRef;
5828 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);5842 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
...@@ -6753,6 +6767,7 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {...@@ -6753,6 +6767,7 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {
6753 return false;6767 return false;
6754 return true;6768 return true;
6755 case ConstPtrSpecialBaseArray:6769 case ConstPtrSpecialBaseArray:
6770 case ConstPtrSpecialSubArray:
6756 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) {6771 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) {
6757 return false;6772 return false;
6758 }6773 }
...@@ -7010,6 +7025,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT...@@ -7010,6 +7025,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT
7010 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));7025 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
7011 return;7026 return;
7012 case ConstPtrSpecialBaseArray:7027 case ConstPtrSpecialBaseArray:
7028 case ConstPtrSpecialSubArray:
7013 buf_appendf(buf, "*");7029 buf_appendf(buf, "*");
7014 // TODO we need a source node for const_ptr_pointee because it can generate compile errors7030 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
7015 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));7031 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
src/analyze.hpp+1-1
...@@ -76,7 +76,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all...@@ -76,7 +76,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all
7676
77ZigType *get_src_ptr_type(ZigType *type);77ZigType *get_src_ptr_type(ZigType *type);
78uint32_t get_ptr_align(CodeGen *g, ZigType *type);78uint32_t get_ptr_align(CodeGen *g, ZigType *type);
79bool get_ptr_const(ZigType *type);79bool get_ptr_const(CodeGen *g, ZigType *type);
80ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);80ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
81ZigType *container_ref_type(ZigType *type_entry);81ZigType *container_ref_type(ZigType *type_entry);
82bool type_is_complete(ZigType *type_entry);82bool type_is_complete(ZigType *type_entry);
src/codegen.cpp+128-55
...@@ -5418,12 +5418,16 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI...@@ -5418,12 +5418,16 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
5418 ZigType *array_type = array_ptr_type->data.pointer.child_type;5418 ZigType *array_type = array_ptr_type->data.pointer.child_type;
5419 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);5419 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
54205420
5421 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5422
5423 bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);5421 bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
54245422
5425 ZigType *res_slice_ptr_type = instruction->base.value->type->data.structure.fields[slice_ptr_index]->type_entry;5423 ZigType *result_type = instruction->base.value->type;
5426 ZigValue *sentinel = res_slice_ptr_type->data.pointer.sentinel;5424 if (!type_has_bits(g, result_type)) {
5425 return nullptr;
5426 }
5427
5428 // This is not whether the result type has a sentinel, but whether there should be a sentinel check,
5429 // e.g. if they used [a..b :s] syntax.
5430 ZigValue *sentinel = instruction->sentinel;
54275431
5428 if (array_type->id == ZigTypeIdArray ||5432 if (array_type->id == ZigTypeIdArray ||
5429 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))5433 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
...@@ -5458,6 +5462,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI...@@ -5458,6 +5462,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
5458 }5462 }
5459 }5463 }
5460 if (!type_has_bits(g, array_type)) {5464 if (!type_has_bits(g, array_type)) {
5465 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5466
5461 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");5467 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
54625468
5463 // TODO if runtime safety is on, store 0xaaaaaaa in ptr field5469 // TODO if runtime safety is on, store 0xaaaaaaa in ptr field
...@@ -5466,20 +5472,26 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI...@@ -5466,20 +5472,26 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
5466 return tmp_struct_ptr;5472 return tmp_struct_ptr;
5467 }5473 }
54685474
5469
5470 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
5471 LLVMValueRef indices[] = {5475 LLVMValueRef indices[] = {
5472 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),5476 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
5473 start_val,5477 start_val,
5474 };5478 };
5475 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");5479 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
5476 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);5480 if (result_type->id == ZigTypeIdPointer) {
5481 ir_assert(instruction->result_loc == nullptr, &instruction->base);
5482 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5483 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5484 } else {
5485 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5486 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
5487 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
54775488
5478 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");5489 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
5479 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");5490 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5480 gen_store_untyped(g, len_value, len_field_ptr, 0, false);5491 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
54815492
5482 return tmp_struct_ptr;5493 return tmp_struct_ptr;
5494 }
5483 } else if (array_type->id == ZigTypeIdPointer) {5495 } else if (array_type->id == ZigTypeIdPointer) {
5484 assert(array_type->data.pointer.ptr_len != PtrLenSingle);5496 assert(array_type->data.pointer.ptr_len != PtrLenSingle);
5485 LLVMValueRef start_val = ir_llvm_value(g, instruction->start);5497 LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
...@@ -5493,24 +5505,39 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI...@@ -5493,24 +5505,39 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
5493 }5505 }
5494 }5506 }
54955507
5496 if (type_has_bits(g, array_type)) {5508 if (!type_has_bits(g, array_type)) {
5497 size_t gen_ptr_index = instruction->base.value->type->data.structure.fields[slice_ptr_index]->gen_index;5509 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5498 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");5510 size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index;
5499 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");5511 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
5500 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);5512 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5513 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5514 return tmp_struct_ptr;
5515 }
5516
5517 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
5518 if (result_type->id == ZigTypeIdPointer) {
5519 ir_assert(instruction->result_loc == nullptr, &instruction->base);
5520 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5521 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5501 }5522 }
55025523
5503 size_t gen_len_index = instruction->base.value->type->data.structure.fields[slice_len_index]->gen_index;5524 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5525
5526 size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index;
5527 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
5528 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5529
5530 size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index;
5504 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");5531 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
5505 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");5532 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5506 gen_store_untyped(g, len_value, len_field_ptr, 0, false);5533 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
55075534
5508 return tmp_struct_ptr;5535 return tmp_struct_ptr;
5536
5509 } else if (array_type->id == ZigTypeIdStruct) {5537 } else if (array_type->id == ZigTypeIdStruct) {
5510 assert(array_type->data.structure.special == StructSpecialSlice);5538 assert(array_type->data.structure.special == StructSpecialSlice);
5511 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);5539 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
5512 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);5540 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
5513 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
55145541
5515 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;5542 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
5516 assert(ptr_index != SIZE_MAX);5543 assert(ptr_index != SIZE_MAX);
...@@ -5547,15 +5574,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI...@@ -5547,15 +5574,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
5547 }5574 }
5548 }5575 }
55495576
5550 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
5551 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");5577 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");
5552 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);5578 if (result_type->id == ZigTypeIdPointer) {
5579 ir_assert(instruction->result_loc == nullptr, &instruction->base);
5580 LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5581 return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5582 } else {
5583 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
5584 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
5585 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
55535586
5554 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, "");5587 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, "");
5555 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");5588 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5556 gen_store_untyped(g, len_value, len_field_ptr, 0, false);5589 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
55575590
5558 return tmp_struct_ptr;5591 return tmp_struct_ptr;
5592 }
5559 } else {5593 } else {
5560 zig_unreachable();5594 zig_unreachable();
5561 }5595 }
...@@ -6640,7 +6674,6 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co...@@ -6640,7 +6674,6 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co
6640 };6674 };
6641 return LLVMConstInBoundsGEP(base_ptr, indices, 2);6675 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
6642 } else {6676 } else {
6643 assert(parent->id == ConstParentIdScalar);
6644 return base_ptr;6677 return base_ptr;
6645 }6678 }
6646}6679}
...@@ -6790,6 +6823,22 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig...@@ -6790,6 +6823,22 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Zig
6790 used_bits += packed_bits_size;6823 used_bits += packed_bits_size;
6791 }6824 }
6792 }6825 }
6826
6827 if (type_entry->data.array.sentinel != nullptr) {
6828 ZigValue *elem_val = type_entry->data.array.sentinel;
6829 LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
6830
6831 if (is_big_endian) {
6832 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
6833 val = LLVMConstShl(val, shift_amt);
6834 val = LLVMConstOr(val, child_val);
6835 } else {
6836 LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
6837 LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
6838 val = LLVMConstOr(val, child_val_shifted);
6839 used_bits += packed_bits_size;
6840 }
6841 }
6793 return val;6842 return val;
6794 }6843 }
6795 case ZigTypeIdVector:6844 case ZigTypeIdVector:
...@@ -6852,24 +6901,16 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha...@@ -6852,24 +6901,16 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
6852 return const_val->llvm_value;6901 return const_val->llvm_value;
6853 }6902 }
6854 case ConstPtrSpecialBaseArray:6903 case ConstPtrSpecialBaseArray:
6904 case ConstPtrSpecialSubArray:
6855 {6905 {
6856 ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;6906 ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
6857 assert(array_const_val->type->id == ZigTypeIdArray);6907 assert(array_const_val->type->id == ZigTypeIdArray);
6858 if (!type_has_bits(g, array_const_val->type)) {6908 if (!type_has_bits(g, array_const_val->type)) {
6859 if (array_const_val->type->data.array.sentinel != nullptr) {6909 // make this a null pointer
6860 ZigValue *pointee = array_const_val->type->data.array.sentinel;6910 ZigType *usize = g->builtin_types.entry_usize;
6861 render_const_val(g, pointee, "");6911 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6862 render_const_val_global(g, pointee, "");6912 get_llvm_type(g, const_val->type));
6863 const_val->llvm_value = LLVMConstBitCast(pointee->llvm_global,6913 return const_val->llvm_value;
6864 get_llvm_type(g, const_val->type));
6865 return const_val->llvm_value;
6866 } else {
6867 // make this a null pointer
6868 ZigType *usize = g->builtin_types.entry_usize;
6869 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6870 get_llvm_type(g, const_val->type));
6871 return const_val->llvm_value;
6872 }
6873 }6914 }
6874 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;6915 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
6875 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);6916 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
...@@ -9228,6 +9269,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa...@@ -9228,6 +9269,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
9228 case BuildModeDebug:9269 case BuildModeDebug:
9229 // windows c runtime requires -D_DEBUG if using debug libraries9270 // windows c runtime requires -D_DEBUG if using debug libraries
9230 args.append("-D_DEBUG");9271 args.append("-D_DEBUG");
9272 args.append("-Og");
92319273
9232 if (g->libc_link_lib != nullptr) {9274 if (g->libc_link_lib != nullptr) {
9233 args.append("-fstack-protector-strong");9275 args.append("-fstack-protector-strong");
...@@ -9650,6 +9692,21 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose...@@ -9650,6 +9692,21 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
9650 return ErrorNone;9692 return ErrorNone;
9651}9693}
96529694
9695static bool need_llvm_module(CodeGen *g) {
9696 return buf_len(&g->main_pkg->root_src_path) != 0;
9697}
9698
9699// before gen_c_objects
9700static bool main_output_dir_is_just_one_c_object_pre(CodeGen *g) {
9701 return g->enable_cache && g->c_source_files.length == 1 && !need_llvm_module(g) &&
9702 g->out_type == OutTypeObj && g->link_objects.length == 0;
9703}
9704
9705// after gen_c_objects
9706static bool main_output_dir_is_just_one_c_object_post(CodeGen *g) {
9707 return g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g) && g->out_type == OutTypeObj;
9708}
9709
9653// returns true if it was a cache miss9710// returns true if it was a cache miss
9654static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {9711static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
9655 Error err;9712 Error err;
...@@ -9667,8 +9724,17 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {...@@ -9667,8 +9724,17 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
9667 buf_len(c_source_basename), 0);9724 buf_len(c_source_basename), 0);
96689725
9669 Buf *final_o_basename = buf_alloc();9726 Buf *final_o_basename = buf_alloc();
9670 os_path_extname(c_source_basename, final_o_basename, nullptr);9727 if (c_file->preprocessor_only_basename == nullptr) {
9671 buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));9728 // We special case when doing build-obj for just one C file
9729 if (main_output_dir_is_just_one_c_object_pre(g)) {
9730 buf_init_from_buf(final_o_basename, g->root_out_name);
9731 } else {
9732 os_path_extname(c_source_basename, final_o_basename, nullptr);
9733 }
9734 buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
9735 } else {
9736 buf_init_from_str(final_o_basename, c_file->preprocessor_only_basename);
9737 }
96729738
9673 CacheHash *cache_hash;9739 CacheHash *cache_hash;
9674 if ((err = create_c_object_cache(g, &cache_hash, true))) {9740 if ((err = create_c_object_cache(g, &cache_hash, true))) {
...@@ -9717,7 +9783,13 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {...@@ -9717,7 +9783,13 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
9717 Termination term;9783 Termination term;
9718 ZigList<const char *> args = {};9784 ZigList<const char *> args = {};
9719 args.append(buf_ptr(self_exe_path));9785 args.append(buf_ptr(self_exe_path));
9720 args.append("cc");9786 args.append("clang");
9787
9788 if (c_file->preprocessor_only_basename != nullptr) {
9789 args.append("-E");
9790 } else {
9791 args.append("-c");
9792 }
97219793
9722 Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));9794 Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
9723 add_cc_args(g, args, buf_ptr(out_dep_path), false);9795 add_cc_args(g, args, buf_ptr(out_dep_path), false);
...@@ -9725,7 +9797,6 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {...@@ -9725,7 +9797,6 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
9725 args.append("-o");9797 args.append("-o");
9726 args.append(buf_ptr(out_obj_path));9798 args.append(buf_ptr(out_obj_path));
97279799
9728 args.append("-c");
9729 args.append(buf_ptr(c_source_file));9800 args.append(buf_ptr(c_source_file));
97309801
9731 for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {9802 for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
...@@ -9780,6 +9851,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {...@@ -9780,6 +9851,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
9780 os_path_join(artifact_dir, final_o_basename, o_final_path);9851 os_path_join(artifact_dir, final_o_basename, o_final_path);
9781 }9852 }
97829853
9854 g->c_artifact_dir = artifact_dir;
9783 g->link_objects.append(o_final_path);9855 g->link_objects.append(o_final_path);
9784 g->caches_to_release.append(cache_hash);9856 g->caches_to_release.append(cache_hash);
97859857
...@@ -10449,6 +10521,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10449,6 +10521,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10449 cache_str(ch, g->libc->kernel32_lib_dir);10521 cache_str(ch, g->libc->kernel32_lib_dir);
10450 }10522 }
10451 cache_buf_opt(ch, g->version_script_path);10523 cache_buf_opt(ch, g->version_script_path);
10524 cache_buf_opt(ch, g->override_soname);
1045210525
10453 // gen_c_objects appends objects to g->link_objects which we want to include in the hash10526 // gen_c_objects appends objects to g->link_objects which we want to include in the hash
10454 gen_c_objects(g);10527 gen_c_objects(g);
...@@ -10467,10 +10540,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -10467,10 +10540,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
10467 return ErrorNone;10540 return ErrorNone;
10468}10541}
1046910542
10470static bool need_llvm_module(CodeGen *g) {
10471 return buf_len(&g->main_pkg->root_src_path) != 0;
10472}
10473
10474static void resolve_out_paths(CodeGen *g) {10543static void resolve_out_paths(CodeGen *g) {
10475 assert(g->output_dir != nullptr);10544 assert(g->output_dir != nullptr);
10476 assert(g->root_out_name != nullptr);10545 assert(g->root_out_name != nullptr);
...@@ -10482,10 +10551,6 @@ static void resolve_out_paths(CodeGen *g) {...@@ -10482,10 +10551,6 @@ static void resolve_out_paths(CodeGen *g) {
10482 case OutTypeUnknown:10551 case OutTypeUnknown:
10483 zig_unreachable();10552 zig_unreachable();
10484 case OutTypeObj:10553 case OutTypeObj:
10485 if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
10486 buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0));
10487 return;
10488 }
10489 if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&10554 if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
10490 buf_eql_buf(o_basename, out_basename))10555 buf_eql_buf(o_basename, out_basename))
10491 {10556 {
...@@ -10580,6 +10645,16 @@ static void output_type_information(CodeGen *g) {...@@ -10580,6 +10645,16 @@ static void output_type_information(CodeGen *g) {
10580 }10645 }
10581}10646}
1058210647
10648static void init_output_dir(CodeGen *g, Buf *digest) {
10649 if (main_output_dir_is_just_one_c_object_post(g)) {
10650 g->output_dir = buf_alloc();
10651 os_path_dirname(g->link_objects.at(0), g->output_dir);
10652 } else {
10653 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
10654 buf_ptr(g->cache_dir), buf_ptr(digest));
10655 }
10656}
10657
10583void codegen_build_and_link(CodeGen *g) {10658void codegen_build_and_link(CodeGen *g) {
10584 Error err;10659 Error err;
10585 assert(g->out_type != OutTypeUnknown);10660 assert(g->out_type != OutTypeUnknown);
...@@ -10622,8 +10697,7 @@ void codegen_build_and_link(CodeGen *g) {...@@ -10622,8 +10697,7 @@ void codegen_build_and_link(CodeGen *g) {
10622 }10697 }
1062310698
10624 if (g->enable_cache && buf_len(&digest) != 0) {10699 if (g->enable_cache && buf_len(&digest) != 0) {
10625 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",10700 init_output_dir(g, &digest);
10626 buf_ptr(g->cache_dir), buf_ptr(&digest));
10627 resolve_out_paths(g);10701 resolve_out_paths(g);
10628 } else {10702 } else {
10629 if (need_llvm_module(g)) {10703 if (need_llvm_module(g)) {
...@@ -10644,8 +10718,7 @@ void codegen_build_and_link(CodeGen *g) {...@@ -10644,8 +10718,7 @@ void codegen_build_and_link(CodeGen *g) {
10644 exit(1);10718 exit(1);
10645 }10719 }
10646 }10720 }
10647 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",10721 init_output_dir(g, &digest);
10648 buf_ptr(g->cache_dir), buf_ptr(&digest));
1064910722
10650 if ((err = os_make_path(g->output_dir))) {10723 if ((err = os_make_path(g->output_dir))) {
10651 fprintf(stderr, "Unable to create output directory: %s\n", err_str(err));10724 fprintf(stderr, "Unable to create output directory: %s\n", err_str(err));
src/error.cpp+4
...@@ -83,6 +83,10 @@ const char *err_str(Error err) {...@@ -83,6 +83,10 @@ const char *err_str(Error err) {
83 case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";83 case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";
84 case ErrorInvalidAbiVersion: return "invalid C ABI version";84 case ErrorInvalidAbiVersion: return "invalid C ABI version";
85 case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";85 case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";
86 case ErrorUnknownClangOption: return "unknown Clang option";
87 case ErrorPermissionDenied: return "permission is denied";
88 case ErrorFileBusy: return "file is busy";
89 case ErrorLocked: return "file is locked by another process";
86 }90 }
87 return "(invalid error)";91 return "(invalid error)";
88}92}
src/glibc.cpp+10
...@@ -16,6 +16,7 @@ static const ZigGLibCLib glibc_libs[] = {...@@ -16,6 +16,7 @@ static const ZigGLibCLib glibc_libs[] = {
16 {"pthread", 0},16 {"pthread", 0},
17 {"dl", 2},17 {"dl", 2},
18 {"rt", 1},18 {"rt", 1},
19 {"ld", 2},
19};20};
2021
21Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose) {22Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose) {
...@@ -330,6 +331,8 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con...@@ -330,6 +331,8 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
330 return err;331 return err;
331 }332 }
332333
334 bool is_ld = (strcmp(lib->name, "ld") == 0);
335
333 CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);336 CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);
334 codegen_set_lib_version(child_gen, lib->sover, 0, 0);337 codegen_set_lib_version(child_gen, lib->sover, 0, 0);
335 child_gen->is_dynamic = true;338 child_gen->is_dynamic = true;
...@@ -337,6 +340,13 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con...@@ -337,6 +340,13 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
337 child_gen->version_script_path = map_file_path;340 child_gen->version_script_path = map_file_path;
338 child_gen->enable_cache = false;341 child_gen->enable_cache = false;
339 child_gen->output_dir = dummy_dir;342 child_gen->output_dir = dummy_dir;
343 if (is_ld) {
344 assert(g->zig_target->standard_dynamic_linker_path != nullptr);
345 Buf *ld_basename = buf_alloc();
346 os_path_split(buf_create_from_str(g->zig_target->standard_dynamic_linker_path),
347 nullptr, ld_basename);
348 child_gen->override_soname = ld_basename;
349 }
340 codegen_build_and_link(child_gen);350 codegen_build_and_link(child_gen);
341 }351 }
342352
src/ir.cpp+498-130
...@@ -272,6 +272,15 @@ static ResultLoc *no_result_loc(void);...@@ -272,6 +272,15 @@ static ResultLoc *no_result_loc(void);
272static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value);272static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value);
273static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr);273static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr);
274static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty);274static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty);
275static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name,
276 bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime);
277static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var,
278 IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime);
279static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instruction,
280 AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstGen *field_result_loc,
281 IrInstGen *result_loc);
282static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* source_instr,
283 IrInstGen *struct_operand, TypeStructField *field);
275284
276static void destroy_instruction_src(IrInstSrc *inst) {285static void destroy_instruction_src(IrInstSrc *inst) {
277 switch (inst->id) {286 switch (inst->id) {
...@@ -784,14 +793,32 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_...@@ -784,14 +793,32 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_
784 break;793 break;
785 case ConstPtrSpecialBaseArray: {794 case ConstPtrSpecialBaseArray: {
786 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;795 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
787 if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {796 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
797 if (elem_index == array_val->type->data.array.len) {
788 result = array_val->type->data.array.sentinel;798 result = array_val->type->data.array.sentinel;
789 } else {799 } else {
790 expand_undef_array(g, array_val);800 expand_undef_array(g, array_val);
791 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];801 result = &array_val->data.x_array.data.s_none.elements[elem_index];
792 }802 }
793 break;803 break;
794 }804 }
805 case ConstPtrSpecialSubArray: {
806 ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
807 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
808
809 // TODO handle sentinel terminated arrays
810 expand_undef_array(g, array_val);
811 result = g->pass1_arena->create<ZigValue>();
812 result->special = array_val->special;
813 result->type = get_array_type(g, array_val->type->data.array.child_type,
814 array_val->type->data.array.len - elem_index, nullptr);
815 result->data.x_array.special = ConstArraySpecialNone;
816 result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index];
817 result->parent.id = ConstParentIdArray;
818 result->parent.data.p_array.array_val = array_val;
819 result->parent.data.p_array.elem_index = elem_index;
820 break;
821 }
795 case ConstPtrSpecialBaseStruct: {822 case ConstPtrSpecialBaseStruct: {
796 ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;823 ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
797 expand_undef_struct(g, struct_val);824 expand_undef_struct(g, struct_val);
...@@ -849,11 +876,6 @@ static bool is_slice(ZigType *type) {...@@ -849,11 +876,6 @@ static bool is_slice(ZigType *type) {
849 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice;876 return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice;
850}877}
851878
852static bool slice_is_const(ZigType *type) {
853 assert(is_slice(type));
854 return type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
855}
856
857// This function returns true when you can change the type of a ZigValue and the879// This function returns true when you can change the type of a ZigValue and the
858// value remains meaningful.880// value remains meaningful.
859static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {881static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
...@@ -3719,7 +3741,8 @@ static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *s...@@ -3719,7 +3741,8 @@ static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *s
3719}3741}
37203742
3721static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type,3743static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type,
3722 IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc)3744 IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc,
3745 ZigValue *sentinel)
3723{3746{
3724 IrInstGenSlice *instruction = ir_build_inst_gen<IrInstGenSlice>(3747 IrInstGenSlice *instruction = ir_build_inst_gen<IrInstGenSlice>(
3725 &ira->new_irb, source_instruction->scope, source_instruction->source_node);3748 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
...@@ -3729,11 +3752,12 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction,...@@ -3729,11 +3752,12 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction,
3729 instruction->end = end;3752 instruction->end = end;
3730 instruction->safety_check_on = safety_check_on;3753 instruction->safety_check_on = safety_check_on;
3731 instruction->result_loc = result_loc;3754 instruction->result_loc = result_loc;
3755 instruction->sentinel = sentinel;
37323756
3733 ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);3757 ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
3734 ir_ref_inst_gen(start, ira->new_irb.current_basic_block);3758 ir_ref_inst_gen(start, ira->new_irb.current_basic_block);
3735 if (end) ir_ref_inst_gen(end, ira->new_irb.current_basic_block);3759 if (end != nullptr) ir_ref_inst_gen(end, ira->new_irb.current_basic_block);
3736 ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);3760 if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
37373761
3738 return &instruction->base;3762 return &instruction->base;
3739}3763}
...@@ -4996,39 +5020,73 @@ static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) {...@@ -4996,39 +5020,73 @@ static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) {
4996 return instruction;5020 return instruction;
4997}5021}
49985022
4999static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {5023static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) {
5000 Scope *scope = inner_scope;5024 Scope *scope = inner_scope;
5001 bool is_noreturn = false;5025 if (is_noreturn != nullptr) *is_noreturn = false;
5002 while (scope != outer_scope) {5026 while (scope != outer_scope) {
5003 if (!scope)5027 if (!scope)
5004 return is_noreturn;5028 return true;
50055029
5006 switch (scope->id) {5030 switch (scope->id) {
5007 case ScopeIdDefer: {5031 case ScopeIdDefer: {
5008 AstNode *defer_node = scope->source_node;5032 AstNode *defer_node = scope->source_node;
5009 assert(defer_node->type == NodeTypeDefer);5033 assert(defer_node->type == NodeTypeDefer);
5010 ReturnKind defer_kind = defer_node->data.defer.kind;5034 ReturnKind defer_kind = defer_node->data.defer.kind;
5011 if (defer_kind == ReturnKindUnconditional ||5035 AstNode *defer_expr_node = defer_node->data.defer.expr;
5012 (gen_error_defers && defer_kind == ReturnKindError))5036 AstNode *defer_var_node = defer_node->data.defer.err_payload;
5013 {5037
5014 AstNode *defer_expr_node = defer_node->data.defer.expr;5038 if (defer_kind == ReturnKindError && err_value == nullptr) {
5015 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;5039 // This is an `errdefer` but we're generating code for a
5016 IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);5040 // `return` that doesn't return an error, skip it
5017 if (defer_expr_value != irb->codegen->invalid_inst_src) {5041 scope = scope->parent;
5018 if (defer_expr_value->is_noreturn) {5042 continue;
5019 is_noreturn = true;5043 }
5020 } else {5044
5021 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,5045 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
5022 defer_expr_value));5046 if (defer_var_node != nullptr) {
5023 }5047 assert(defer_kind == ReturnKindError);
5048 assert(defer_var_node->type == NodeTypeSymbol);
5049 Buf *var_name = defer_var_node->data.symbol_expr.symbol;
5050
5051 if (defer_expr_node->type == NodeTypeUnreachable) {
5052 add_node_error(irb->codegen, defer_var_node,
5053 buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
5054 return false;
5024 }5055 }
5056
5057 IrInstSrc *is_comptime;
5058 if (ir_should_inline(irb->exec, defer_expr_scope)) {
5059 is_comptime = ir_build_const_bool(irb, defer_expr_scope,
5060 defer_expr_node, true);
5061 } else {
5062 is_comptime = ir_build_test_comptime(irb, defer_expr_scope,
5063 defer_expr_node, err_value);
5064 }
5065
5066 ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope,
5067 var_name, true, true, false, is_comptime);
5068 build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value,
5069 buf_ptr(var_name), is_comptime);
5070
5071 defer_expr_scope = err_var->child_scope;
5072 }
5073
5074 IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
5075 if (defer_expr_value == irb->codegen->invalid_inst_src)
5076 return irb->codegen->invalid_inst_src;
5077
5078 if (defer_expr_value->is_noreturn) {
5079 if (is_noreturn != nullptr) *is_noreturn = true;
5080 } else {
5081 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
5082 defer_expr_value));
5025 }5083 }
5026 scope = scope->parent;5084 scope = scope->parent;
5027 continue;5085 continue;
5028 }5086 }
5029 case ScopeIdDecls:5087 case ScopeIdDecls:
5030 case ScopeIdFnDef:5088 case ScopeIdFnDef:
5031 return is_noreturn;5089 return true;
5032 case ScopeIdBlock:5090 case ScopeIdBlock:
5033 case ScopeIdVarDecl:5091 case ScopeIdVarDecl:
5034 case ScopeIdLoop:5092 case ScopeIdLoop:
...@@ -5045,7 +5103,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope...@@ -5045,7 +5103,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope
5045 zig_unreachable();5103 zig_unreachable();
5046 }5104 }
5047 }5105 }
5048 return is_noreturn;5106 return true;
5049}5107}
50505108
5051static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) {5109static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) {
...@@ -5131,7 +5189,8 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,...@@ -5131,7 +5189,8 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
5131 bool have_err_defers = defer_counts[ReturnKindError] > 0;5189 bool have_err_defers = defer_counts[ReturnKindError] > 0;
5132 if (!have_err_defers && !irb->codegen->have_err_ret_tracing) {5190 if (!have_err_defers && !irb->codegen->have_err_ret_tracing) {
5133 // only generate unconditional defers5191 // only generate unconditional defers
5134 ir_gen_defers_for_block(irb, scope, outer_scope, false);5192 if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr))
5193 return irb->codegen->invalid_inst_src;
5135 IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr);5194 IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr);
5136 result_loc_ret->base.source_instruction = result;5195 result_loc_ret->base.source_instruction = result;
5137 return result;5196 return result;
...@@ -5154,14 +5213,16 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,...@@ -5154,14 +5213,16 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
5154 IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");5213 IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
51555214
5156 ir_set_cursor_at_end_and_append_block(irb, err_block);5215 ir_set_cursor_at_end_and_append_block(irb, err_block);
5157 ir_gen_defers_for_block(irb, scope, outer_scope, true);5216 if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value))
5217 return irb->codegen->invalid_inst_src;
5158 if (irb->codegen->have_err_ret_tracing && !should_inline) {5218 if (irb->codegen->have_err_ret_tracing && !should_inline) {
5159 ir_build_save_err_ret_addr_src(irb, scope, node);5219 ir_build_save_err_ret_addr_src(irb, scope, node);
5160 }5220 }
5161 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);5221 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
51625222
5163 ir_set_cursor_at_end_and_append_block(irb, ok_block);5223 ir_set_cursor_at_end_and_append_block(irb, ok_block);
5164 ir_gen_defers_for_block(irb, scope, outer_scope, false);5224 if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr))
5225 return irb->codegen->invalid_inst_src;
5165 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);5226 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
51665227
5167 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);5228 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
...@@ -5198,7 +5259,12 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,...@@ -5198,7 +5259,12 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
5198 result_loc_ret->base.id = ResultLocIdReturn;5259 result_loc_ret->base.id = ResultLocIdReturn;
5199 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);5260 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
5200 ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);5261 ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);
5201 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {5262
5263 bool is_noreturn = false;
5264 if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) {
5265 return irb->codegen->invalid_inst_src;
5266 }
5267 if (!is_noreturn) {
5202 if (irb->codegen->have_err_ret_tracing && !should_inline) {5268 if (irb->codegen->have_err_ret_tracing && !should_inline) {
5203 ir_build_save_err_ret_addr_src(irb, scope, node);5269 ir_build_save_err_ret_addr_src(irb, scope, node);
5204 }5270 }
...@@ -5400,7 +5466,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *...@@ -5400,7 +5466,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
54005466
5401 bool is_return_from_fn = block_node == irb->main_block_node;5467 bool is_return_from_fn = block_node == irb->main_block_node;
5402 if (!is_return_from_fn) {5468 if (!is_return_from_fn) {
5403 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);5469 if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr))
5470 return irb->codegen->invalid_inst_src;
5404 }5471 }
54055472
5406 IrInstSrc *result;5473 IrInstSrc *result;
...@@ -5425,7 +5492,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *...@@ -5425,7 +5492,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
5425 result_loc_ret->base.id = ResultLocIdReturn;5492 result_loc_ret->base.id = ResultLocIdReturn;
5426 ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base);5493 ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base);
5427 ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base));5494 ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base));
5428 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);5495 if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr))
5496 return irb->codegen->invalid_inst_src;
5429 return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result));5497 return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result));
5430}5498}
54315499
...@@ -9225,7 +9293,8 @@ static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope...@@ -9225,7 +9293,8 @@ static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope
9225 }9293 }
92269294
9227 IrBasicBlockSrc *dest_block = block_scope->end_block;9295 IrBasicBlockSrc *dest_block = block_scope->end_block;
9228 ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);9296 if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr))
9297 return irb->codegen->invalid_inst_src;
92299298
9230 block_scope->incoming_blocks->append(irb->current_basic_block);9299 block_scope->incoming_blocks->append(irb->current_basic_block);
9231 block_scope->incoming_values->append(result_value);9300 block_scope->incoming_values->append(result_value);
...@@ -9299,7 +9368,8 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n...@@ -9299,7 +9368,8 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n
9299 }9368 }
93009369
9301 IrBasicBlockSrc *dest_block = loop_scope->break_block;9370 IrBasicBlockSrc *dest_block = loop_scope->break_block;
9302 ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);9371 if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr))
9372 return irb->codegen->invalid_inst_src;
93039373
9304 loop_scope->incoming_blocks->append(irb->current_basic_block);9374 loop_scope->incoming_blocks->append(irb->current_basic_block);
9305 loop_scope->incoming_values->append(result_value);9375 loop_scope->incoming_values->append(result_value);
...@@ -9358,7 +9428,8 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN...@@ -9358,7 +9428,8 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN
9358 }9428 }
93599429
9360 IrBasicBlockSrc *dest_block = loop_scope->continue_block;9430 IrBasicBlockSrc *dest_block = loop_scope->continue_block;
9361 ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);9431 if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr))
9432 return irb->codegen->invalid_inst_src;
9362 return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime));9433 return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime));
9363}9434}
93649435
...@@ -12335,11 +12406,22 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -12335,11 +12406,22 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12335 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&12406 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
12336 prev_type->data.pointer.ptr_len == PtrLenSingle &&12407 prev_type->data.pointer.ptr_len == PtrLenSingle &&
12337 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||12408 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
12338 is_slice(cur_type)))12409 (cur_type->id == ZigTypeIdOptional && is_slice(cur_type->data.maybe.child_type)) ||
12410 is_slice(cur_type)))
12339 {12411 {
12340 ZigType *array_type = prev_type->data.pointer.child_type;12412 ZigType *array_type = prev_type->data.pointer.child_type;
12341 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?12413 ZigType *slice_type;
12342 cur_type->data.error_union.payload_type : cur_type;12414 switch (cur_type->id) {
12415 case ZigTypeIdErrorUnion:
12416 slice_type = cur_type->data.error_union.payload_type;
12417 break;
12418 case ZigTypeIdOptional:
12419 slice_type = cur_type->data.maybe.child_type;
12420 break;
12421 default:
12422 slice_type = cur_type;
12423 break;
12424 }
12343 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;12425 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
12344 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||12426 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
12345 !prev_type->data.pointer.is_const) &&12427 !prev_type->data.pointer.is_const) &&
...@@ -12677,41 +12759,80 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc...@@ -12677,41 +12759,80 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc
12677 Error err;12759 Error err;
1267812760
12679 assert(array_ptr->value->type->id == ZigTypeIdPointer);12761 assert(array_ptr->value->type->id == ZigTypeIdPointer);
12762 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
12763
12764 ZigType *array_type = array_ptr->value->type->data.pointer.child_type;
12765 size_t array_len = array_type->data.array.len;
12766
12767 // A zero-sized array can be casted regardless of the destination alignment, or
12768 // whether the pointer is undefined, and the result is always comptime known.
12769 // TODO However, this is exposing a result location bug that I failed to solve on the first try.
12770 // If you want to try to fix the bug, uncomment this block and get the tests passing.
12771 //if (array_len == 0 && array_type->data.array.sentinel == nullptr) {
12772 // ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
12773 // undef_array->special = ConstValSpecialUndef;
12774 // undef_array->type = array_type;
12775
12776 // IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12777 // init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
12778 // result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
12779 // result->value->type = wanted_type;
12780 // return result;
12781 //}
1268012782
12681 if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {12783 if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
12682 return ira->codegen->invalid_inst_gen;12784 return ira->codegen->invalid_inst_gen;
12683 }12785 }
1268412786
12685 assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
12686
12687 const size_t array_len = array_ptr->value->type->data.pointer.child_type->data.array.len;
12688
12689 // A zero-sized array can always be casted irregardless of the destination
12690 // alignment
12691 if (array_len != 0) {12787 if (array_len != 0) {
12692 wanted_type = adjust_slice_align(ira->codegen, wanted_type,12788 wanted_type = adjust_slice_align(ira->codegen, wanted_type,
12693 get_ptr_align(ira->codegen, array_ptr->value->type));12789 get_ptr_align(ira->codegen, array_ptr->value->type));
12694 }12790 }
1269512791
12696 if (instr_is_comptime(array_ptr)) {12792 if (instr_is_comptime(array_ptr)) {
12697 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);12793 UndefAllowed undef_allowed = (array_len == 0) ? UndefOk : UndefBad;
12794 ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, undef_allowed);
12698 if (array_ptr_val == nullptr)12795 if (array_ptr_val == nullptr)
12699 return ira->codegen->invalid_inst_gen;12796 return ira->codegen->invalid_inst_gen;
12700 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node);12797 ir_assert(is_slice(wanted_type), source_instr);
12701 if (pointee == nullptr)12798 if (array_ptr_val->special == ConstValSpecialUndef) {
12702 return ira->codegen->invalid_inst_gen;12799 ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
12703 if (pointee->special != ConstValSpecialRuntime) {12800 undef_array->special = ConstValSpecialUndef;
12704 assert(array_ptr_val->type->id == ZigTypeIdPointer);12801 undef_array->type = array_type;
12705 ZigType *array_type = array_ptr_val->type->data.pointer.child_type;
12706 assert(is_slice(wanted_type));
12707 bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
1270812802
12709 IrInstGen *result = ir_const(ira, source_instr, wanted_type);12803 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12710 init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, is_const);12804 init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
12711 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;12805 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
12712 result->value->type = wanted_type;12806 result->value->type = wanted_type;
12713 return result;12807 return result;
12714 }12808 }
12809 bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
12810 // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee
12811 if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) {
12812 ZigValue *array_val = array_ptr_val->data.x_ptr.data.base_array.array_val;
12813 if (array_val->special != ConstValSpecialRuntime) {
12814 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12815 init_const_slice(ira->codegen, result->value, array_val,
12816 array_ptr_val->data.x_ptr.data.base_array.elem_index,
12817 array_type->data.array.len, wanted_const);
12818 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
12819 result->value->type = wanted_type;
12820 return result;
12821 }
12822 } else if (array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
12823 ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node);
12824 if (pointee == nullptr)
12825 return ira->codegen->invalid_inst_gen;
12826 if (pointee->special != ConstValSpecialRuntime) {
12827 assert(array_ptr_val->type->id == ZigTypeIdPointer);
12828
12829 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
12830 init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, wanted_const);
12831 result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
12832 result->value->type = wanted_type;
12833 return result;
12834 }
12835 }
12715 }12836 }
1271612837
12717 if (result_loc == nullptr) result_loc = no_result_loc();12838 if (result_loc == nullptr) result_loc = no_result_loc();
...@@ -14329,10 +14450,71 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -14329,10 +14450,71 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
14329}14450}
1433014451
14331static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,14452static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
14332 IrInstGen *value, ZigType *wanted_type)14453 IrInstGen *value, ZigType *union_type)
14333{14454{
14334 ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to union"));14455 Error err;
14335 return ira->codegen->invalid_inst_gen;14456 ZigType *struct_type = value->value->type;
14457
14458 assert(struct_type->id == ZigTypeIdStruct);
14459 assert(union_type->id == ZigTypeIdUnion);
14460 assert(struct_type->data.structure.src_field_count == 1);
14461
14462 TypeStructField *only_field = struct_type->data.structure.fields[0];
14463
14464 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
14465 return ira->codegen->invalid_inst_gen;
14466
14467 TypeUnionField *union_field = find_union_type_field(union_type, only_field->name);
14468 if (union_field == nullptr) {
14469 ir_add_error_node(ira, only_field->decl_node,
14470 buf_sprintf("no member named '%s' in union '%s'",
14471 buf_ptr(only_field->name), buf_ptr(&union_type->name)));
14472 return ira->codegen->invalid_inst_gen;
14473 }
14474
14475 ZigType *payload_type = resolve_union_field_type(ira->codegen, union_field);
14476 if (payload_type == nullptr)
14477 return ira->codegen->invalid_inst_gen;
14478
14479 IrInstGen *field_value = ir_analyze_struct_value_field_value(ira, source_instr, value, only_field);
14480 if (type_is_invalid(field_value->value->type))
14481 return ira->codegen->invalid_inst_gen;
14482
14483 IrInstGen *casted_value = ir_implicit_cast(ira, field_value, payload_type);
14484 if (type_is_invalid(casted_value->value->type))
14485 return ira->codegen->invalid_inst_gen;
14486
14487 if (instr_is_comptime(casted_value)) {
14488 ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad);
14489 if (val == nullptr)
14490 return ira->codegen->invalid_inst_gen;
14491
14492 IrInstGen *result = ir_const(ira, source_instr, union_type);
14493 bigint_init_bigint(&result->value->data.x_union.tag, &union_field->enum_field->value);
14494 result->value->data.x_union.payload = val;
14495
14496 val->parent.id = ConstParentIdUnion;
14497 val->parent.data.p_union.union_val = result->value;
14498
14499 return result;
14500 }
14501
14502 IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
14503 union_type, nullptr, true, true);
14504 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
14505 return ira->codegen->invalid_inst_gen;
14506 }
14507
14508 IrInstGen *payload_ptr = ir_analyze_container_field_ptr(ira, only_field->name, source_instr,
14509 result_loc_inst, source_instr, union_type, true);
14510 if (type_is_invalid(payload_ptr->value->type))
14511 return ira->codegen->invalid_inst_gen;
14512
14513 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, payload_ptr, casted_value, false);
14514 if (type_is_invalid(store_ptr_inst->value->type))
14515 return ira->codegen->invalid_inst_gen;
14516
14517 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);
14336}14518}
1433714519
14338// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,14520// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,
...@@ -14581,7 +14763,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,...@@ -14581,7 +14763,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
14581 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);14763 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
14582 }14764 }
1458314765
14584 // *[N]T to ?[]const T14766 // *[N]T to ?[]T
14585 if (wanted_type->id == ZigTypeIdOptional &&14767 if (wanted_type->id == ZigTypeIdOptional &&
14586 is_slice(wanted_type->data.maybe.child_type) &&14768 is_slice(wanted_type->data.maybe.child_type) &&
14587 actual_type->id == ZigTypeIdPointer &&14769 actual_type->id == ZigTypeIdPointer &&
...@@ -16170,6 +16352,15 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i...@@ -16170,6 +16352,15 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i
16170 IrInstGen *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2;16352 IrInstGen *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2;
16171 IrInstGen *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1;16353 IrInstGen *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1;
1617216354
16355 if (!is_tagged_union(union_val->value->type)) {
16356 ErrorMsg *msg = ir_add_error_node(ira, source_node,
16357 buf_sprintf("comparison of union and enum literal is only valid for tagged union types"));
16358 add_error_note(ira->codegen, msg, union_val->value->type->data.unionation.decl_node,
16359 buf_sprintf("type %s is not a tagged union",
16360 buf_ptr(&union_val->value->type->name)));
16361 return ira->codegen->invalid_inst_gen;
16362 }
16363
16173 ZigType *tag_type = union_val->value->type->data.unionation.tag_type;16364 ZigType *tag_type = union_val->value->type->data.unionation.tag_type;
16174 assert(tag_type != nullptr);16365 assert(tag_type != nullptr);
1617516366
...@@ -19917,6 +20108,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -19917,6 +20108,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
19917 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);20108 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
19918 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))20109 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
19919 return err;20110 return err;
20111 buf_deinit(&buf);
19920 return ErrorNone;20112 return ErrorNone;
19921 }20113 }
1992220114
...@@ -19936,6 +20128,31 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -19936,6 +20128,31 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
19936 dst_size, buf_ptr(&pointee->type->name), src_size));20128 dst_size, buf_ptr(&pointee->type->name), src_size));
19937 return ErrorSemanticAnalyzeFail;20129 return ErrorSemanticAnalyzeFail;
19938 }20130 }
20131 case ConstPtrSpecialSubArray: {
20132 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
20133 assert(array_val->type->id == ZigTypeIdArray);
20134 if (array_val->data.x_array.special != ConstArraySpecialNone)
20135 zig_panic("TODO");
20136 if (dst_size > src_size) {
20137 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
20138 opt_ir_add_error_node(ira, codegen, source_node,
20139 buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
20140 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
20141 return ErrorSemanticAnalyzeFail;
20142 }
20143 size_t elem_size = src_size;
20144 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
20145 Buf buf = BUF_INIT;
20146 buf_resize(&buf, elem_count * elem_size);
20147 for (size_t i = 0; i < elem_count; i += 1) {
20148 ZigValue *elem_val = &array_val->data.x_array.data.s_none.elements[i];
20149 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
20150 }
20151 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
20152 return err;
20153 buf_deinit(&buf);
20154 return ErrorNone;
20155 }
19939 case ConstPtrSpecialBaseArray: {20156 case ConstPtrSpecialBaseArray: {
19940 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;20157 ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
19941 assert(array_val->type->id == ZigTypeIdArray);20158 assert(array_val->type->id == ZigTypeIdArray);
...@@ -19959,6 +20176,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -19959,6 +20176,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
19959 }20176 }
19960 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))20177 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
19961 return err;20178 return err;
20179 buf_deinit(&buf);
19962 return ErrorNone;20180 return ErrorNone;
19963 }20181 }
19964 case ConstPtrSpecialBaseStruct:20182 case ConstPtrSpecialBaseStruct:
...@@ -20538,6 +20756,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_...@@ -20538,6 +20756,44 @@ static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_
20538 allow_zero);20756 allow_zero);
20539}20757}
2054020758
20759static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
20760 uint64_t elem_index, uint32_t *result)
20761{
20762 Error err;
20763
20764 if (base_ptr_align == 0) {
20765 *result = 0;
20766 return ErrorNone;
20767 }
20768
20769 // figure out the largest alignment possible
20770 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
20771 return err;
20772
20773 uint64_t elem_size = type_size(ira->codegen, elem_type);
20774 uint64_t abi_align = get_abi_alignment(ira->codegen, elem_type);
20775 uint64_t ptr_align = base_ptr_align;
20776
20777 uint64_t chosen_align = abi_align;
20778 if (ptr_align >= abi_align) {
20779 while (ptr_align > abi_align) {
20780 if ((elem_index * elem_size) % ptr_align == 0) {
20781 chosen_align = ptr_align;
20782 break;
20783 }
20784 ptr_align >>= 1;
20785 }
20786 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
20787 chosen_align = ptr_align;
20788 } else {
20789 // can't get here because guaranteed elem_size >= abi_align
20790 zig_unreachable();
20791 }
20792
20793 *result = chosen_align;
20794 return ErrorNone;
20795}
20796
20541static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) {20797static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) {
20542 Error err;20798 Error err;
20543 IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child;20799 IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child;
...@@ -20578,11 +20834,6 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20578,11 +20834,6 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20578 }20834 }
2057920835
20580 if (array_type->id == ZigTypeIdArray) {20836 if (array_type->id == ZigTypeIdArray) {
20581 if (array_type->data.array.len == 0) {
20582 ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,
20583 buf_sprintf("index 0 outside array of size 0"));
20584 return ira->codegen->invalid_inst_gen;
20585 }
20586 ZigType *child_type = array_type->data.array.child_type;20837 ZigType *child_type = array_type->data.array.child_type;
20587 if (ptr_type->data.pointer.host_int_bytes == 0) {20838 if (ptr_type->data.pointer.host_int_bytes == 0) {
20588 return_type = get_pointer_to_type_extra(ira->codegen, child_type,20839 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
...@@ -20681,29 +20932,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20681,29 +20932,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20681 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,20932 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
20682 nullptr, nullptr);20933 nullptr, nullptr);
20683 } else if (return_type->data.pointer.explicit_alignment != 0) {20934 } else if (return_type->data.pointer.explicit_alignment != 0) {
20684 // figure out the largest alignment possible20935 uint32_t chosen_align;
2068520936 if ((err = compute_elem_align(ira, return_type->data.pointer.child_type,
20686 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))20937 return_type->data.pointer.explicit_alignment, index, &chosen_align)))
20938 {
20687 return ira->codegen->invalid_inst_gen;20939 return ira->codegen->invalid_inst_gen;
20688
20689 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
20690 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
20691 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
20692
20693 uint64_t chosen_align = abi_align;
20694 if (ptr_align >= abi_align) {
20695 while (ptr_align > abi_align) {
20696 if ((index * elem_size) % ptr_align == 0) {
20697 chosen_align = ptr_align;
20698 break;
20699 }
20700 ptr_align >>= 1;
20701 }
20702 } else if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
20703 chosen_align = ptr_align;
20704 } else {
20705 // can't get here because guaranteed elem_size >= abi_align
20706 zig_unreachable();
20707 }20940 }
20708 return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);20941 return_type = adjust_ptr_align(ira->codegen, return_type, chosen_align);
20709 }20942 }
...@@ -20824,6 +21057,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20824,6 +21057,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20824 }21057 }
20825 break;21058 break;
20826 case ConstPtrSpecialBaseArray:21059 case ConstPtrSpecialBaseArray:
21060 case ConstPtrSpecialSubArray:
20827 {21061 {
20828 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;21062 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
20829 new_index = offset + index;21063 new_index = offset + index;
...@@ -20894,6 +21128,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP...@@ -20894,6 +21128,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
20894 out_val->data.x_ptr.special = ConstPtrSpecialRef;21128 out_val->data.x_ptr.special = ConstPtrSpecialRef;
20895 out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;21129 out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
20896 break;21130 break;
21131 case ConstPtrSpecialSubArray:
20897 case ConstPtrSpecialBaseArray:21132 case ConstPtrSpecialBaseArray:
20898 {21133 {
20899 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;21134 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
...@@ -22881,7 +23116,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi...@@ -22881,7 +23116,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi
22881 Error err;23116 Error err;
22882 assert(union_type->id == ZigTypeIdUnion);23117 assert(union_type->id == ZigTypeIdUnion);
2288323118
22884 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))23119 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
22885 return ira->codegen->invalid_inst_gen;23120 return ira->codegen->invalid_inst_gen;
2288623121
22887 TypeUnionField *type_field = find_union_type_field(union_type, field_name);23122 TypeUnionField *type_field = find_union_type_field(union_type, field_name);
...@@ -25445,11 +25680,22 @@ static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcE...@@ -25445,11 +25680,22 @@ static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcE
25445static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {25680static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
25446 Error err;25681 Error err;
2544725682
25448 ZigType *ptr_type = get_src_ptr_type(ty);25683 ZigType *ptr_type;
25684 if (is_slice(ty)) {
25685 TypeStructField *ptr_field = ty->data.structure.fields[slice_ptr_index];
25686 ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
25687 } else {
25688 ptr_type = get_src_ptr_type(ty);
25689 }
25449 assert(ptr_type != nullptr);25690 assert(ptr_type != nullptr);
25450 if (ptr_type->id == ZigTypeIdPointer) {25691 if (ptr_type->id == ZigTypeIdPointer) {
25451 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))25692 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
25452 return err;25693 return err;
25694 } else if (is_slice(ptr_type)) {
25695 TypeStructField *ptr_field = ptr_type->data.structure.fields[slice_ptr_index];
25696 ZigType *slice_ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
25697 if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
25698 return err;
25453 }25699 }
2545425700
25455 *result_align = get_ptr_align(ira->codegen, ty);25701 *result_align = get_ptr_align(ira->codegen, ty);
...@@ -25904,6 +26150,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset...@@ -25904,6 +26150,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset
25904 start = 0;26150 start = 0;
25905 bound_end = 1;26151 bound_end = 1;
25906 break;26152 break;
26153 case ConstPtrSpecialSubArray:
25907 case ConstPtrSpecialBaseArray:26154 case ConstPtrSpecialBaseArray:
25908 {26155 {
25909 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;26156 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
...@@ -26037,6 +26284,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy...@@ -26037,6 +26284,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
26037 dest_start = 0;26284 dest_start = 0;
26038 dest_end = 1;26285 dest_end = 1;
26039 break;26286 break;
26287 case ConstPtrSpecialSubArray:
26040 case ConstPtrSpecialBaseArray:26288 case ConstPtrSpecialBaseArray:
26041 {26289 {
26042 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;26290 ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
...@@ -26080,6 +26328,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy...@@ -26080,6 +26328,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
26080 src_start = 0;26328 src_start = 0;
26081 src_end = 1;26329 src_end = 1;
26082 break;26330 break;
26331 case ConstPtrSpecialSubArray:
26083 case ConstPtrSpecialBaseArray:26332 case ConstPtrSpecialBaseArray:
26084 {26333 {
26085 ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;26334 ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
...@@ -26123,7 +26372,19 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy...@@ -26123,7 +26372,19 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
26123 return ir_build_memcpy_gen(ira, &instruction->base.base, casted_dest_ptr, casted_src_ptr, casted_count);26372 return ir_build_memcpy_gen(ira, &instruction->base.base, casted_dest_ptr, casted_src_ptr, casted_count);
26124}26373}
2612526374
26375static ZigType *get_result_loc_type(IrAnalyze *ira, ResultLoc *result_loc) {
26376 if (result_loc == nullptr) return nullptr;
26377
26378 if (result_loc->id == ResultLocIdCast) {
26379 return ir_resolve_type(ira, result_loc->source_instruction->child);
26380 }
26381
26382 return nullptr;
26383}
26384
26126static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) {26385static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) {
26386 Error err;
26387
26127 IrInstGen *ptr_ptr = instruction->ptr->child;26388 IrInstGen *ptr_ptr = instruction->ptr->child;
26128 if (type_is_invalid(ptr_ptr->value->type))26389 if (type_is_invalid(ptr_ptr->value->type))
26129 return ira->codegen->invalid_inst_gen;26390 return ira->codegen->invalid_inst_gen;
...@@ -26153,6 +26414,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26153,6 +26414,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26153 end = nullptr;26414 end = nullptr;
26154 }26415 }
2615526416
26417 ZigValue *slice_sentinel_val = nullptr;
26156 ZigType *non_sentinel_slice_ptr_type;26418 ZigType *non_sentinel_slice_ptr_type;
26157 ZigType *elem_type;26419 ZigType *elem_type;
2615826420
...@@ -26203,6 +26465,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26203,6 +26465,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26203 }26465 }
26204 } else if (is_slice(array_type)) {26466 } else if (is_slice(array_type)) {
26205 ZigType *maybe_sentineled_slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;26467 ZigType *maybe_sentineled_slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
26468 slice_sentinel_val = maybe_sentineled_slice_ptr_type->data.pointer.sentinel;
26206 non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr);26469 non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr);
26207 elem_type = non_sentinel_slice_ptr_type->data.pointer.child_type;26470 elem_type = non_sentinel_slice_ptr_type->data.pointer.child_type;
26208 } else {26471 } else {
...@@ -26211,7 +26474,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26211,7 +26474,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26211 return ira->codegen->invalid_inst_gen;26474 return ira->codegen->invalid_inst_gen;
26212 }26475 }
2621326476
26214 ZigType *return_type;
26215 ZigValue *sentinel_val = nullptr;26477 ZigValue *sentinel_val = nullptr;
26216 if (instruction->sentinel) {26478 if (instruction->sentinel) {
26217 IrInstGen *uncasted_sentinel = instruction->sentinel->child;26479 IrInstGen *uncasted_sentinel = instruction->sentinel->child;
...@@ -26223,11 +26485,76 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26223,11 +26485,76 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26223 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);26485 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
26224 if (sentinel_val == nullptr)26486 if (sentinel_val == nullptr)
26225 return ira->codegen->invalid_inst_gen;26487 return ira->codegen->invalid_inst_gen;
26226 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);26488 }
26489
26490 ZigType *child_array_type = (array_type->id == ZigTypeIdPointer &&
26491 array_type->data.pointer.ptr_len == PtrLenSingle) ? array_type->data.pointer.child_type : array_type;
26492
26493 ZigType *return_type;
26494
26495 // If start index and end index are both comptime known, then the result type is a pointer to array
26496 // not a slice. However, if the start or end index is a lazy value, and the result location is a slice,
26497 // then the pointer-to-array would be casted to a slice anyway. So, we preserve the laziness of these
26498 // values by making the return type a slice.
26499 ZigType *res_loc_type = get_result_loc_type(ira, instruction->result_loc);
26500 bool result_loc_is_slice = (res_loc_type != nullptr && is_slice(res_loc_type));
26501 bool end_is_known = !result_loc_is_slice &&
26502 ((end != nullptr && value_is_comptime(end->value)) ||
26503 (end == nullptr && child_array_type->id == ZigTypeIdArray));
26504
26505 ZigValue *array_sentinel = sentinel_val;
26506 if (end_is_known) {
26507 uint64_t end_scalar;
26508 if (end != nullptr) {
26509 ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);
26510 if (!end_val)
26511 return ira->codegen->invalid_inst_gen;
26512 end_scalar = bigint_as_u64(&end_val->data.x_bigint);
26513 } else {
26514 end_scalar = child_array_type->data.array.len;
26515 }
26516 array_sentinel = (child_array_type->id == ZigTypeIdArray && end_scalar == child_array_type->data.array.len)
26517 ? child_array_type->data.array.sentinel : sentinel_val;
26518
26519 if (value_is_comptime(casted_start->value)) {
26520 ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
26521 if (!start_val)
26522 return ira->codegen->invalid_inst_gen;
26523
26524 uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
26525
26526 if (start_scalar > end_scalar) {
26527 ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice"));
26528 return ira->codegen->invalid_inst_gen;
26529 }
26530
26531 uint32_t base_ptr_align = non_sentinel_slice_ptr_type->data.pointer.explicit_alignment;
26532 uint32_t ptr_byte_alignment = 0;
26533 if (end_scalar > start_scalar) {
26534 if ((err = compute_elem_align(ira, elem_type, base_ptr_align, start_scalar, &ptr_byte_alignment)))
26535 return ira->codegen->invalid_inst_gen;
26536 }
26537
26538 ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
26539 array_sentinel);
26540 return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
26541 non_sentinel_slice_ptr_type->data.pointer.is_const,
26542 non_sentinel_slice_ptr_type->data.pointer.is_volatile,
26543 PtrLenSingle, ptr_byte_alignment, 0, 0, false);
26544 goto done_with_return_type;
26545 }
26546 } else if (array_sentinel == nullptr && end == nullptr) {
26547 array_sentinel = slice_sentinel_val;
26548 }
26549 if (array_sentinel != nullptr) {
26550 // TODO deal with non-abi-alignment here
26551 ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, array_sentinel);
26227 return_type = get_slice_type(ira->codegen, slice_ptr_type);26552 return_type = get_slice_type(ira->codegen, slice_ptr_type);
26228 } else {26553 } else {
26554 // TODO deal with non-abi-alignment here
26229 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);26555 return_type = get_slice_type(ira->codegen, non_sentinel_slice_ptr_type);
26230 }26556 }
26557done_with_return_type:
2623126558
26232 if (instr_is_comptime(ptr_ptr) &&26559 if (instr_is_comptime(ptr_ptr) &&
26233 value_is_comptime(casted_start->value) &&26560 value_is_comptime(casted_start->value) &&
...@@ -26238,12 +26565,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26238,12 +26565,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26238 size_t abs_offset;26565 size_t abs_offset;
26239 size_t rel_end;26566 size_t rel_end;
26240 bool ptr_is_undef = false;26567 bool ptr_is_undef = false;
26241 if (array_type->id == ZigTypeIdArray ||26568 if (child_array_type->id == ZigTypeIdArray) {
26242 (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
26243 {
26244 if (array_type->id == ZigTypeIdPointer) {26569 if (array_type->id == ZigTypeIdPointer) {
26245 ZigType *child_array_type = array_type->data.pointer.child_type;
26246 assert(child_array_type->id == ZigTypeIdArray);
26247 parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node);26570 parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node);
26248 if (parent_ptr == nullptr)26571 if (parent_ptr == nullptr)
26249 return ira->codegen->invalid_inst_gen;26572 return ira->codegen->invalid_inst_gen;
...@@ -26254,6 +26577,10 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26254,6 +26577,10 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26254 abs_offset = 0;26577 abs_offset = 0;
26255 rel_end = SIZE_MAX;26578 rel_end = SIZE_MAX;
26256 ptr_is_undef = true;26579 ptr_is_undef = true;
26580 } else if (parent_ptr->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
26581 array_val = nullptr;
26582 abs_offset = 0;
26583 rel_end = SIZE_MAX;
26257 } else {26584 } else {
26258 array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node);26585 array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node);
26259 if (array_val == nullptr)26586 if (array_val == nullptr)
...@@ -26296,6 +26623,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26296,6 +26623,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26296 rel_end = 1;26623 rel_end = 1;
26297 }26624 }
26298 break;26625 break;
26626 case ConstPtrSpecialSubArray:
26299 case ConstPtrSpecialBaseArray:26627 case ConstPtrSpecialBaseArray:
26300 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;26628 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
26301 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;26629 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
...@@ -26346,6 +26674,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26346,6 +26674,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26346 abs_offset = SIZE_MAX;26674 abs_offset = SIZE_MAX;
26347 rel_end = 1;26675 rel_end = 1;
26348 break;26676 break;
26677 case ConstPtrSpecialSubArray:
26349 case ConstPtrSpecialBaseArray:26678 case ConstPtrSpecialBaseArray:
26350 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;26679 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
26351 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;26680 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
...@@ -26406,15 +26735,28 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26406,15 +26735,28 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26406 }26735 }
2640726736
26408 IrInstGen *result = ir_const(ira, &instruction->base.base, return_type);26737 IrInstGen *result = ir_const(ira, &instruction->base.base, return_type);
26409 ZigValue *out_val = result->value;
26410 out_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
2641126738
26412 ZigValue *ptr_val = out_val->data.x_struct.fields[slice_ptr_index];26739 ZigValue *ptr_val;
26740 if (return_type->id == ZigTypeIdPointer) {
26741 // pointer to array
26742 ptr_val = result->value;
26743 } else {
26744 // slice
26745 result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
26746
26747 ptr_val = result->value->data.x_struct.fields[slice_ptr_index];
2641326748
26749 ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index];
26750 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
26751 }
26752
26753 bool return_type_is_const = non_sentinel_slice_ptr_type->data.pointer.is_const;
26414 if (array_val) {26754 if (array_val) {
26415 size_t index = abs_offset + start_scalar;26755 size_t index = abs_offset + start_scalar;
26416 bool is_const = slice_is_const(return_type);26756 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown);
26417 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const, PtrLenUnknown);26757 if (return_type->id == ZigTypeIdPointer) {
26758 ptr_val->data.x_ptr.special = ConstPtrSpecialSubArray;
26759 }
26418 if (array_type->id == ZigTypeIdArray) {26760 if (array_type->id == ZigTypeIdArray) {
26419 ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut;26761 ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut;
26420 } else if (is_slice(array_type)) {26762 } else if (is_slice(array_type)) {
...@@ -26424,16 +26766,17 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26424,16 +26766,17 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26424 }26766 }
26425 } else if (ptr_is_undef) {26767 } else if (ptr_is_undef) {
26426 ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type,26768 ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type,
26427 slice_is_const(return_type));26769 return_type_is_const);
26428 ptr_val->special = ConstValSpecialUndef;26770 ptr_val->special = ConstValSpecialUndef;
26429 } else switch (parent_ptr->data.x_ptr.special) {26771 } else switch (parent_ptr->data.x_ptr.special) {
26430 case ConstPtrSpecialInvalid:26772 case ConstPtrSpecialInvalid:
26431 case ConstPtrSpecialDiscard:26773 case ConstPtrSpecialDiscard:
26432 zig_unreachable();26774 zig_unreachable();
26433 case ConstPtrSpecialRef:26775 case ConstPtrSpecialRef:
26434 init_const_ptr_ref(ira->codegen, ptr_val,26776 init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee,
26435 parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type));26777 return_type_is_const);
26436 break;26778 break;
26779 case ConstPtrSpecialSubArray:
26437 case ConstPtrSpecialBaseArray:26780 case ConstPtrSpecialBaseArray:
26438 zig_unreachable();26781 zig_unreachable();
26439 case ConstPtrSpecialBaseStruct:26782 case ConstPtrSpecialBaseStruct:
...@@ -26448,7 +26791,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26448,7 +26791,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26448 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,26791 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
26449 parent_ptr->type->data.pointer.child_type,26792 parent_ptr->type->data.pointer.child_type,
26450 parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,26793 parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,
26451 slice_is_const(return_type));26794 return_type_is_const);
26452 break;26795 break;
26453 case ConstPtrSpecialFunction:26796 case ConstPtrSpecialFunction:
26454 zig_panic("TODO");26797 zig_panic("TODO");
...@@ -26456,26 +26799,11 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26456,26 +26799,11 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26456 zig_panic("TODO");26799 zig_panic("TODO");
26457 }26800 }
2645826801
26459 ZigValue *len_val = out_val->data.x_struct.fields[slice_len_index];26802 // In the case of pointer-to-array, we must restore this because above it overwrites ptr_val->type
26460 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);26803 result->value->type = return_type;
26461
26462 return result;26804 return result;
26463 }26805 }
2646426806
26465 IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
26466 return_type, nullptr, true, true);
26467 if (result_loc != nullptr) {
26468 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
26469 return result_loc;
26470 }
26471 IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
26472 dummy_value->value->special = ConstValSpecialRuntime;
26473 IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
26474 dummy_value, result_loc->value->type->data.pointer.child_type);
26475 if (type_is_invalid(dummy_result->value->type))
26476 return ira->codegen->invalid_inst_gen;
26477 }
26478
26479 if (generate_non_null_assert) {26807 if (generate_non_null_assert) {
26480 IrInstGen *ptr_val = ir_get_deref(ira, &instruction->base.base, ptr_ptr, nullptr);26808 IrInstGen *ptr_val = ir_get_deref(ira, &instruction->base.base, ptr_ptr, nullptr);
2648126809
...@@ -26485,8 +26813,26 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i...@@ -26485,8 +26813,26 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
26485 ir_build_assert_non_null(ira, &instruction->base.base, ptr_val);26813 ir_build_assert_non_null(ira, &instruction->base.base, ptr_val);
26486 }26814 }
2648726815
26816 IrInstGen *result_loc = nullptr;
26817
26818 if (return_type->id != ZigTypeIdPointer) {
26819 result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
26820 return_type, nullptr, true, true);
26821 if (result_loc != nullptr) {
26822 if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
26823 return result_loc;
26824 }
26825 IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
26826 dummy_value->value->special = ConstValSpecialRuntime;
26827 IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
26828 dummy_value, result_loc->value->type->data.pointer.child_type);
26829 if (type_is_invalid(dummy_result->value->type))
26830 return ira->codegen->invalid_inst_gen;
26831 }
26832 }
26833
26488 return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr,26834 return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr,
26489 casted_start, end, instruction->safety_check_on, result_loc);26835 casted_start, end, instruction->safety_check_on, result_loc, sentinel_val);
26490}26836}
2649126837
26492static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasField *instruction) {26838static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasField *instruction) {
...@@ -27512,10 +27858,18 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -27512,10 +27858,18 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
27512 // We have a check for zero bits later so we use get_src_ptr_type to27858 // We have a check for zero bits later so we use get_src_ptr_type to
27513 // validate src_type and dest_type.27859 // validate src_type and dest_type.
2751427860
27515 ZigType *src_ptr_type = get_src_ptr_type(src_type);27861 ZigType *if_slice_ptr_type;
27516 if (src_ptr_type == nullptr) {27862 if (is_slice(src_type)) {
27517 ir_add_error(ira, ptr_src, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));27863 TypeStructField *ptr_field = src_type->data.structure.fields[slice_ptr_index];
27518 return ira->codegen->invalid_inst_gen;27864 if_slice_ptr_type = resolve_struct_field_type(ira->codegen, ptr_field);
27865 } else {
27866 if_slice_ptr_type = src_type;
27867
27868 ZigType *src_ptr_type = get_src_ptr_type(src_type);
27869 if (src_ptr_type == nullptr) {
27870 ir_add_error(ira, ptr_src, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
27871 return ira->codegen->invalid_inst_gen;
27872 }
27519 }27873 }
2752027874
27521 ZigType *dest_ptr_type = get_src_ptr_type(dest_type);27875 ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
...@@ -27525,7 +27879,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -27525,7 +27879,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
27525 return ira->codegen->invalid_inst_gen;27879 return ira->codegen->invalid_inst_gen;
27526 }27880 }
2752727881
27528 if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) {27882 if (get_ptr_const(ira->codegen, src_type) && !get_ptr_const(ira->codegen, dest_type)) {
27529 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));27883 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
27530 return ira->codegen->invalid_inst_gen;27884 return ira->codegen->invalid_inst_gen;
27531 }27885 }
...@@ -27543,7 +27897,10 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -27543,7 +27897,10 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
27543 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))27897 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))
27544 return ira->codegen->invalid_inst_gen;27898 return ira->codegen->invalid_inst_gen;
2754527899
27546 if (type_has_bits(ira->codegen, dest_type) && !type_has_bits(ira->codegen, src_type) && safety_check_on) {27900 if (safety_check_on &&
27901 type_has_bits(ira->codegen, dest_type) &&
27902 !type_has_bits(ira->codegen, if_slice_ptr_type))
27903 {
27547 ErrorMsg *msg = ir_add_error(ira, source_instr,27904 ErrorMsg *msg = ir_add_error(ira, source_instr,
27548 buf_sprintf("'%s' and '%s' do not have the same in-memory representation",27905 buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
27549 buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));27906 buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
...@@ -27554,6 +27911,14 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -27554,6 +27911,14 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
27554 return ira->codegen->invalid_inst_gen;27911 return ira->codegen->invalid_inst_gen;
27555 }27912 }
2755627913
27914 // For slices, follow the `ptr` field.
27915 if (is_slice(src_type)) {
27916 TypeStructField *ptr_field = src_type->data.structure.fields[slice_ptr_index];
27917 IrInstGen *ptr_ref = ir_get_ref(ira, source_instr, ptr, true, false);
27918 IrInstGen *ptr_ptr = ir_analyze_struct_field_ptr(ira, source_instr, ptr_field, ptr_ref, src_type, false);
27919 ptr = ir_get_deref(ira, source_instr, ptr_ptr, nullptr);
27920 }
27921
27557 if (instr_is_comptime(ptr)) {27922 if (instr_is_comptime(ptr)) {
27558 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);27923 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
27559 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;27924 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
...@@ -27657,6 +28022,9 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue...@@ -27657,6 +28022,9 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue
27657 buf_write_value_bytes(codegen, &buf[buf_i], elem);28022 buf_write_value_bytes(codegen, &buf[buf_i], elem);
27658 buf_i += type_size(codegen, elem->type);28023 buf_i += type_size(codegen, elem->type);
27659 }28024 }
28025 if (val->type->id == ZigTypeIdArray && val->type->data.array.sentinel != nullptr) {
28026 buf_write_value_bytes(codegen, &buf[buf_i], val->type->data.array.sentinel);
28027 }
27660}28028}
2766128029
27662static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {28030static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) {
src/link.cpp+6-5
...@@ -566,6 +566,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil...@@ -566,6 +566,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil
566 Stage2ProgressNode *progress_node)566 Stage2ProgressNode *progress_node)
567{567{
568 CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr, name, progress_node);568 CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr, name, progress_node);
569 child_gen->root_out_name = buf_create_from_str(name);
569 ZigList<CFile *> c_source_files = {0};570 ZigList<CFile *> c_source_files = {0};
570 c_source_files.append(c_file);571 c_source_files.append(c_file);
571 child_gen->c_source_files = c_source_files;572 child_gen->c_source_files = c_source_files;
...@@ -1650,7 +1651,6 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -1650,7 +1651,6 @@ static void construct_linker_job_elf(LinkJob *lj) {
16501651
1651 bool is_lib = g->out_type == OutTypeLib;1652 bool is_lib = g->out_type == OutTypeLib;
1652 bool is_dyn_lib = g->is_dynamic && is_lib;1653 bool is_dyn_lib = g->is_dynamic && is_lib;
1653 Buf *soname = nullptr;
1654 if (!g->have_dynamic_link) {1654 if (!g->have_dynamic_link) {
1655 if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||1655 if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||
1656 g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)1656 g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)
...@@ -1661,15 +1661,13 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -1661,15 +1661,13 @@ static void construct_linker_job_elf(LinkJob *lj) {
1661 }1661 }
1662 } else if (is_dyn_lib) {1662 } else if (is_dyn_lib) {
1663 lj->args.append("-shared");1663 lj->args.append("-shared");
1664
1665 assert(buf_len(&g->bin_file_output_path) != 0);
1666 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
1667 }1664 }
16681665
1669 if (target_requires_pie(g->zig_target) && g->out_type == OutTypeExe) {1666 if (target_requires_pie(g->zig_target) && g->out_type == OutTypeExe) {
1670 lj->args.append("-pie");1667 lj->args.append("-pie");
1671 }1668 }
16721669
1670 assert(buf_len(&g->bin_file_output_path) != 0);
1673 lj->args.append("-o");1671 lj->args.append("-o");
1674 lj->args.append(buf_ptr(&g->bin_file_output_path));1672 lj->args.append(buf_ptr(&g->bin_file_output_path));
16751673
...@@ -1739,6 +1737,9 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -1739,6 +1737,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
1739 }1737 }
17401738
1741 if (is_dyn_lib) {1739 if (is_dyn_lib) {
1740 Buf *soname = (g->override_soname == nullptr) ?
1741 buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major) :
1742 g->override_soname;
1742 lj->args.append("-soname");1743 lj->args.append("-soname");
1743 lj->args.append(buf_ptr(soname));1744 lj->args.append(buf_ptr(soname));
17441745
...@@ -2007,7 +2008,7 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_fi...@@ -2007,7 +2008,7 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_fi
20072008
2008 ZigList<const char *> args = {};2009 ZigList<const char *> args = {};
2009 args.append(buf_ptr(self_exe_path));2010 args.append(buf_ptr(self_exe_path));
2010 args.append("cc");2011 args.append("clang");
2011 args.append("-x");2012 args.append("-x");
2012 args.append("c");2013 args.append("c");
2013 args.append(buf_ptr(def_in_file));2014 args.append(buf_ptr(def_in_file));
src/main.cpp+303-12
...@@ -36,7 +36,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -36,7 +36,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
36 " build-lib [source] create library from source or object files\n"36 " build-lib [source] create library from source or object files\n"
37 " build-obj [source] create object from source or assembly\n"37 " build-obj [source] create object from source or assembly\n"
38 " builtin show the source code of @import(\"builtin\")\n"38 " builtin show the source code of @import(\"builtin\")\n"
39 " cc C compiler\n"39 " cc use Zig as a drop-in C compiler\n"
40 " fmt parse files and render in canonical zig format\n"40 " fmt parse files and render in canonical zig format\n"
41 " id print the base64-encoded compiler id\n"41 " id print the base64-encoded compiler id\n"
42 " init-exe initialize a `zig build` application in the cwd\n"42 " init-exe initialize a `zig build` application in the cwd\n"
...@@ -54,7 +54,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -54,7 +54,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
54 " --cache-dir [path] override the local cache directory\n"54 " --cache-dir [path] override the local cache directory\n"
55 " --cache [auto|off|on] build in cache, print output path to stdout\n"55 " --cache [auto|off|on] build in cache, print output path to stdout\n"
56 " --color [auto|off|on] enable or disable colored error messages\n"56 " --color [auto|off|on] enable or disable colored error messages\n"
57 " --disable-gen-h do not generate a C header file (.h)\n"
58 " --disable-valgrind omit valgrind client requests in debug builds\n"57 " --disable-valgrind omit valgrind client requests in debug builds\n"
59 " --eh-frame-hdr enable C++ exception handling by passing --eh-frame-hdr to linker\n"58 " --eh-frame-hdr enable C++ exception handling by passing --eh-frame-hdr to linker\n"
60 " --enable-valgrind include valgrind client requests release builds\n"59 " --enable-valgrind include valgrind client requests release builds\n"
...@@ -77,6 +76,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -77,6 +76,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
77 " -fno-emit-asm (default) do not output .s (assembly code)\n"76 " -fno-emit-asm (default) do not output .s (assembly code)\n"
78 " -femit-llvm-ir produce a .ll file with LLVM IR\n"77 " -femit-llvm-ir produce a .ll file with LLVM IR\n"
79 " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"78 " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
79 " -femit-h generate a C header file (.h)\n"
80 " -fno-emit-h (default) do not generate a C header file (.h)\n"
80 " --libc [file] Provide a file which specifies libc paths\n"81 " --libc [file] Provide a file which specifies libc paths\n"
81 " --name [name] override output name\n"82 " --name [name] override output name\n"
82 " --output-dir [dir] override output directory (defaults to cwd)\n"83 " --output-dir [dir] override output directory (defaults to cwd)\n"
...@@ -270,7 +271,7 @@ static int main0(int argc, char **argv) {...@@ -270,7 +271,7 @@ static int main0(int argc, char **argv) {
270 return 0;271 return 0;
271 }272 }
272273
273 if (argc >= 2 && (strcmp(argv[1], "cc") == 0 ||274 if (argc >= 2 && (strcmp(argv[1], "clang") == 0 ||
274 strcmp(argv[1], "-cc1") == 0 || strcmp(argv[1], "-cc1as") == 0))275 strcmp(argv[1], "-cc1") == 0 || strcmp(argv[1], "-cc1as") == 0))
275 {276 {
276 return ZigClang_main(argc, argv);277 return ZigClang_main(argc, argv);
...@@ -429,8 +430,10 @@ static int main0(int argc, char **argv) {...@@ -429,8 +430,10 @@ static int main0(int argc, char **argv) {
429 bool enable_dump_analysis = false;430 bool enable_dump_analysis = false;
430 bool enable_doc_generation = false;431 bool enable_doc_generation = false;
431 bool emit_bin = true;432 bool emit_bin = true;
433 const char *emit_bin_override_path = nullptr;
432 bool emit_asm = false;434 bool emit_asm = false;
433 bool emit_llvm_ir = false;435 bool emit_llvm_ir = false;
436 bool emit_h = false;
434 const char *cache_dir = nullptr;437 const char *cache_dir = nullptr;
435 CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();438 CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();
436 BuildMode build_mode = BuildModeDebug;439 BuildMode build_mode = BuildModeDebug;
...@@ -439,7 +442,6 @@ static int main0(int argc, char **argv) {...@@ -439,7 +442,6 @@ static int main0(int argc, char **argv) {
439 bool system_linker_hack = false;442 bool system_linker_hack = false;
440 TargetSubsystem subsystem = TargetSubsystemAuto;443 TargetSubsystem subsystem = TargetSubsystemAuto;
441 bool want_single_threaded = false;444 bool want_single_threaded = false;
442 bool disable_gen_h = false;
443 bool bundle_compiler_rt = false;445 bool bundle_compiler_rt = false;
444 Buf *override_lib_dir = nullptr;446 Buf *override_lib_dir = nullptr;
445 Buf *main_pkg_path = nullptr;447 Buf *main_pkg_path = nullptr;
...@@ -450,6 +452,8 @@ static int main0(int argc, char **argv) {...@@ -450,6 +452,8 @@ static int main0(int argc, char **argv) {
450 bool function_sections = false;452 bool function_sections = false;
451 const char *mcpu = nullptr;453 const char *mcpu = nullptr;
452 CodeModel code_model = CodeModelDefault;454 CodeModel code_model = CodeModelDefault;
455 const char *override_soname = nullptr;
456 bool only_preprocess = false;
453457
454 ZigList<const char *> llvm_argv = {0};458 ZigList<const char *> llvm_argv = {0};
455 llvm_argv.append("zig (LLVM option parsing)");459 llvm_argv.append("zig (LLVM option parsing)");
...@@ -574,9 +578,240 @@ static int main0(int argc, char **argv) {...@@ -574,9 +578,240 @@ static int main0(int argc, char **argv) {
574 return (term.how == TerminationIdClean) ? term.code : -1;578 return (term.how == TerminationIdClean) ? term.code : -1;
575 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {579 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
576 return stage2_fmt(argc, argv);580 return stage2_fmt(argc, argv);
577 }581 } else if (argc >= 2 && strcmp(argv[1], "cc") == 0) {
582 emit_h = false;
583 strip = true;
584
585 bool c_arg = false;
586 Stage2ClangArgIterator it;
587 stage2_clang_arg_iterator(&it, argc, argv);
588 bool nostdlib = false;
589 bool is_shared_lib = false;
590 ZigList<Buf *> linker_args = {};
591 while (it.has_next) {
592 if ((err = stage2_clang_arg_next(&it))) {
593 fprintf(stderr, "unable to parse command line parameters: %s\n", err_str(err));
594 return EXIT_FAILURE;
595 }
596 switch (it.kind) {
597 case Stage2ClangArgTarget: // example: -target riscv64-linux-unknown
598 target_string = it.only_arg;
599 break;
600 case Stage2ClangArgO: // -o
601 emit_bin_override_path = it.only_arg;
602 enable_cache = CacheOptOn;
603 break;
604 case Stage2ClangArgC: // -c
605 c_arg = true;
606 break;
607 case Stage2ClangArgOther:
608 for (size_t i = 0; i < it.other_args_len; i += 1) {
609 clang_argv.append(it.other_args_ptr[i]);
610 }
611 break;
612 case Stage2ClangArgPositional: {
613 Buf *arg_buf = buf_create_from_str(it.only_arg);
614 if (buf_ends_with_str(arg_buf, ".c") ||
615 buf_ends_with_str(arg_buf, ".C") ||
616 buf_ends_with_str(arg_buf, ".cc") ||
617 buf_ends_with_str(arg_buf, ".cpp") ||
618 buf_ends_with_str(arg_buf, ".cxx") ||
619 buf_ends_with_str(arg_buf, ".s") ||
620 buf_ends_with_str(arg_buf, ".S"))
621 {
622 CFile *c_file = heap::c_allocator.create<CFile>();
623 c_file->source_path = it.only_arg;
624 c_source_files.append(c_file);
625 } else {
626 objects.append(it.only_arg);
627 }
628 break;
629 }
630 case Stage2ClangArgL: // -l
631 if (strcmp(it.only_arg, "c") == 0)
632 have_libc = true;
633 link_libs.append(it.only_arg);
634 break;
635 case Stage2ClangArgIgnore:
636 break;
637 case Stage2ClangArgDriverPunt:
638 // Never mind what we're doing, just pass the args directly. For example --help.
639 return ZigClang_main(argc, argv);
640 case Stage2ClangArgPIC:
641 want_pic = WantPICEnabled;
642 break;
643 case Stage2ClangArgNoPIC:
644 want_pic = WantPICDisabled;
645 break;
646 case Stage2ClangArgNoStdLib:
647 nostdlib = true;
648 break;
649 case Stage2ClangArgShared:
650 is_dynamic = true;
651 is_shared_lib = true;
652 break;
653 case Stage2ClangArgRDynamic:
654 rdynamic = true;
655 break;
656 case Stage2ClangArgWL: {
657 const char *arg = it.only_arg;
658 for (;;) {
659 size_t pos = 0;
660 while (arg[pos] != ',' && arg[pos] != 0) pos += 1;
661 linker_args.append(buf_create_from_mem(arg, pos));
662 if (arg[pos] == 0) break;
663 arg += pos + 1;
664 }
665 break;
666 }
667 case Stage2ClangArgPreprocess:
668 only_preprocess = true;
669 break;
670 case Stage2ClangArgOptimize:
671 // alright what release mode do they want?
672 if (strcmp(it.only_arg, "Os") == 0) {
673 build_mode = BuildModeSmallRelease;
674 } else if (strcmp(it.only_arg, "O2") == 0 ||
675 strcmp(it.only_arg, "O3") == 0 ||
676 strcmp(it.only_arg, "O4") == 0)
677 {
678 build_mode = BuildModeFastRelease;
679 } else if (strcmp(it.only_arg, "Og") == 0) {
680 build_mode = BuildModeDebug;
681 } else {
682 for (size_t i = 0; i < it.other_args_len; i += 1) {
683 clang_argv.append(it.other_args_ptr[i]);
684 }
685 }
686 break;
687 case Stage2ClangArgDebug:
688 strip = false;
689 if (strcmp(it.only_arg, "-g") == 0) {
690 // we handled with strip = false above
691 } else {
692 for (size_t i = 0; i < it.other_args_len; i += 1) {
693 clang_argv.append(it.other_args_ptr[i]);
694 }
695 }
696 break;
697 case Stage2ClangArgSanitize:
698 if (strcmp(it.only_arg, "undefined") == 0) {
699 want_sanitize_c = WantCSanitizeEnabled;
700 } else {
701 for (size_t i = 0; i < it.other_args_len; i += 1) {
702 clang_argv.append(it.other_args_ptr[i]);
703 }
704 }
705 break;
706 }
707 }
708 // Parse linker args
709 for (size_t i = 0; i < linker_args.length; i += 1) {
710 Buf *arg = linker_args.at(i);
711 if (buf_eql_str(arg, "-soname")) {
712 i += 1;
713 if (i >= linker_args.length) {
714 fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
715 return EXIT_FAILURE;
716 }
717 Buf *soname_buf = linker_args.at(i);
718 override_soname = buf_ptr(soname_buf);
719 // use it as --name
720 // example: libsoundio.so.2
721 size_t prefix = 0;
722 if (buf_starts_with_str(soname_buf, "lib")) {
723 prefix = 3;
724 }
725 size_t end = buf_len(soname_buf);
726 if (buf_ends_with_str(soname_buf, ".so")) {
727 end -= 3;
728 } else {
729 bool found_digit = false;
730 while (end > 0 && isdigit(buf_ptr(soname_buf)[end - 1])) {
731 found_digit = true;
732 end -= 1;
733 }
734 if (found_digit && end > 0 && buf_ptr(soname_buf)[end - 1] == '.') {
735 end -= 1;
736 } else {
737 end = buf_len(soname_buf);
738 }
739 if (buf_ends_with_str(buf_slice(soname_buf, prefix, end), ".so")) {
740 end -= 3;
741 }
742 }
743 out_name = buf_ptr(buf_slice(soname_buf, prefix, end));
744 } else if (buf_eql_str(arg, "-rpath")) {
745 i += 1;
746 if (i >= linker_args.length) {
747 fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
748 return EXIT_FAILURE;
749 }
750 Buf *rpath = linker_args.at(i);
751 rpath_list.append(buf_ptr(rpath));
752 } else if (buf_eql_str(arg, "-I") ||
753 buf_eql_str(arg, "--dynamic-linker") ||
754 buf_eql_str(arg, "-dynamic-linker"))
755 {
756 i += 1;
757 if (i >= linker_args.length) {
758 fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
759 return EXIT_FAILURE;
760 }
761 dynamic_linker = buf_ptr(linker_args.at(i));
762 } else {
763 fprintf(stderr, "warning: unsupported linker arg: %s\n", buf_ptr(arg));
764 }
765 }
766
767 if (want_sanitize_c == WantCSanitizeEnabled && build_mode == BuildModeFastRelease) {
768 build_mode = BuildModeSafeRelease;
769 }
578770
579 for (int i = 1; i < argc; i += 1) {771 if (!nostdlib && !have_libc) {
772 have_libc = true;
773 link_libs.append("c");
774 }
775 if (only_preprocess) {
776 cmd = CmdBuild;
777 out_type = OutTypeObj;
778 emit_bin = false;
779 // Transfer "objects" into c_source_files
780 for (size_t i = 0; i < objects.length; i += 1) {
781 CFile *c_file = heap::c_allocator.create<CFile>();
782 c_file->source_path = objects.at(i);
783 c_source_files.append(c_file);
784 }
785 for (size_t i = 0; i < c_source_files.length; i += 1) {
786 Buf *src_path;
787 if (emit_bin_override_path != nullptr) {
788 src_path = buf_create_from_str(emit_bin_override_path);
789 } else {
790 src_path = buf_create_from_str(c_source_files.at(i)->source_path);
791 }
792 Buf basename = BUF_INIT;
793 os_path_split(src_path, nullptr, &basename);
794 c_source_files.at(i)->preprocessor_only_basename = buf_ptr(&basename);
795 }
796 } else if (!c_arg) {
797 cmd = CmdBuild;
798 if (is_shared_lib) {
799 out_type = OutTypeLib;
800 } else {
801 out_type = OutTypeExe;
802 }
803 if (emit_bin_override_path == nullptr) {
804 emit_bin_override_path = "a.out";
805 }
806 } else {
807 cmd = CmdBuild;
808 out_type = OutTypeObj;
809 }
810 if (c_source_files.length == 0 && objects.length == 0) {
811 // For example `zig cc` and no args should print the "no input files" message.
812 return ZigClang_main(argc, argv);
813 }
814 } else for (int i = 1; i < argc; i += 1) {
580 char *arg = argv[i];815 char *arg = argv[i];
581816
582 if (arg[0] == '-') {817 if (arg[0] == '-') {
...@@ -660,9 +895,7 @@ static int main0(int argc, char **argv) {...@@ -660,9 +895,7 @@ static int main0(int argc, char **argv) {
660 } else if (strcmp(arg, "--system-linker-hack") == 0) {895 } else if (strcmp(arg, "--system-linker-hack") == 0) {
661 system_linker_hack = true;896 system_linker_hack = true;
662 } else if (strcmp(arg, "--single-threaded") == 0) {897 } else if (strcmp(arg, "--single-threaded") == 0) {
663 want_single_threaded = true;898 want_single_threaded = true;;
664 } else if (strcmp(arg, "--disable-gen-h") == 0) {
665 disable_gen_h = true;
666 } else if (strcmp(arg, "--bundle-compiler-rt") == 0) {899 } else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
667 bundle_compiler_rt = true;900 bundle_compiler_rt = true;
668 } else if (strcmp(arg, "--test-cmd-bin") == 0) {901 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
...@@ -719,6 +952,11 @@ static int main0(int argc, char **argv) {...@@ -719,6 +952,11 @@ static int main0(int argc, char **argv) {
719 emit_llvm_ir = true;952 emit_llvm_ir = true;
720 } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {953 } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {
721 emit_llvm_ir = false;954 emit_llvm_ir = false;
955 } else if (strcmp(arg, "-femit-h") == 0) {
956 emit_h = true;
957 } else if (strcmp(arg, "-fno-emit-h") == 0 || strcmp(arg, "--disable-gen-h") == 0) {
958 // the --disable-gen-h is there to support godbolt. once they upgrade to -fno-emit-h then we can remove this
959 emit_h = false;
722 } else if (str_starts_with(arg, "-mcpu=")) {960 } else if (str_starts_with(arg, "-mcpu=")) {
723 mcpu = arg + strlen("-mcpu=");961 mcpu = arg + strlen("-mcpu=");
724 } else if (i + 1 >= argc) {962 } else if (i + 1 >= argc) {
...@@ -1134,6 +1372,18 @@ static int main0(int argc, char **argv) {...@@ -1134,6 +1372,18 @@ static int main0(int argc, char **argv) {
1134 buf_out_name = buf_alloc();1372 buf_out_name = buf_alloc();
1135 os_path_extname(&basename, buf_out_name, nullptr);1373 os_path_extname(&basename, buf_out_name, nullptr);
1136 }1374 }
1375 if (need_name && buf_out_name == nullptr && objects.length == 1) {
1376 Buf basename = BUF_INIT;
1377 os_path_split(buf_create_from_str(objects.at(0)), nullptr, &basename);
1378 buf_out_name = buf_alloc();
1379 os_path_extname(&basename, buf_out_name, nullptr);
1380 }
1381 if (need_name && buf_out_name == nullptr && emit_bin_override_path != nullptr) {
1382 Buf basename = BUF_INIT;
1383 os_path_split(buf_create_from_str(emit_bin_override_path), nullptr, &basename);
1384 buf_out_name = buf_alloc();
1385 os_path_extname(&basename, buf_out_name, nullptr);
1386 }
11371387
1138 if (need_name && buf_out_name == nullptr) {1388 if (need_name && buf_out_name == nullptr) {
1139 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");1389 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
...@@ -1202,13 +1452,17 @@ static int main0(int argc, char **argv) {...@@ -1202,13 +1452,17 @@ static int main0(int argc, char **argv) {
1202 g->verbose_cc = verbose_cc;1452 g->verbose_cc = verbose_cc;
1203 g->verbose_llvm_cpu_features = verbose_llvm_cpu_features;1453 g->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
1204 g->output_dir = output_dir;1454 g->output_dir = output_dir;
1205 g->disable_gen_h = disable_gen_h;1455 g->disable_gen_h = !emit_h;
1206 g->bundle_compiler_rt = bundle_compiler_rt;1456 g->bundle_compiler_rt = bundle_compiler_rt;
1207 codegen_set_errmsg_color(g, color);1457 codegen_set_errmsg_color(g, color);
1208 g->system_linker_hack = system_linker_hack;1458 g->system_linker_hack = system_linker_hack;
1209 g->function_sections = function_sections;1459 g->function_sections = function_sections;
1210 g->code_model = code_model;1460 g->code_model = code_model;
12111461
1462 if (override_soname) {
1463 g->override_soname = buf_create_from_str(override_soname);
1464 }
1465
1212 for (size_t i = 0; i < lib_dirs.length; i += 1) {1466 for (size_t i = 0; i < lib_dirs.length; i += 1) {
1213 codegen_add_lib_dir(g, lib_dirs.at(i));1467 codegen_add_lib_dir(g, lib_dirs.at(i));
1214 }1468 }
...@@ -1287,9 +1541,46 @@ static int main0(int argc, char **argv) {...@@ -1287,9 +1541,46 @@ static int main0(int argc, char **argv) {
1287 os_spawn_process(args, &term);1541 os_spawn_process(args, &term);
1288 return term.code;1542 return term.code;
1289 } else if (cmd == CmdBuild) {1543 } else if (cmd == CmdBuild) {
1290 if (g->enable_cache) {1544 if (emit_bin_override_path != nullptr) {
1545#if defined(ZIG_OS_WINDOWS)
1546 buf_replace(g->output_dir, '/', '\\');
1547#endif
1548 Buf *dest_path = buf_create_from_str(emit_bin_override_path);
1549 Buf *source_path;
1550 if (only_preprocess) {
1551 source_path = buf_alloc();
1552 Buf *pp_only_basename = buf_create_from_str(
1553 c_source_files.at(0)->preprocessor_only_basename);
1554 os_path_join(g->output_dir, pp_only_basename, source_path);
1555
1556 } else {
1557 source_path = &g->bin_file_output_path;
1558 }
1559 if ((err = os_update_file(source_path, dest_path))) {
1560 fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(source_path),
1561 buf_ptr(dest_path), err_str(err));
1562 return main_exit(root_progress_node, EXIT_FAILURE);
1563 }
1564 } else if (only_preprocess) {
1565#if defined(ZIG_OS_WINDOWS)
1566 buf_replace(g->c_artifact_dir, '/', '\\');
1567#endif
1568 // dump the preprocessed output to stdout
1569 for (size_t i = 0; i < c_source_files.length; i += 1) {
1570 Buf *source_path = buf_alloc();
1571 Buf *pp_only_basename = buf_create_from_str(
1572 c_source_files.at(i)->preprocessor_only_basename);
1573 os_path_join(g->c_artifact_dir, pp_only_basename, source_path);
1574 if ((err = os_dump_file(source_path, stdout))) {
1575 fprintf(stderr, "unable to read %s: %s\n", buf_ptr(source_path),
1576 err_str(err));
1577 return main_exit(root_progress_node, EXIT_FAILURE);
1578 }
1579 }
1580 } else if (g->enable_cache) {
1291#if defined(ZIG_OS_WINDOWS)1581#if defined(ZIG_OS_WINDOWS)
1292 buf_replace(&g->bin_file_output_path, '/', '\\');1582 buf_replace(&g->bin_file_output_path, '/', '\\');
1583 buf_replace(g->output_dir, '/', '\\');
1293#endif1584#endif
1294 if (final_output_dir_step != nullptr) {1585 if (final_output_dir_step != nullptr) {
1295 Buf *dest_basename = buf_alloc();1586 Buf *dest_basename = buf_alloc();
...@@ -1303,7 +1594,7 @@ static int main0(int argc, char **argv) {...@@ -1303,7 +1594,7 @@ static int main0(int argc, char **argv) {
1303 return main_exit(root_progress_node, EXIT_FAILURE);1594 return main_exit(root_progress_node, EXIT_FAILURE);
1304 }1595 }
1305 } else {1596 } else {
1306 if (g->emit_bin && printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0)1597 if (printf("%s\n", buf_ptr(g->output_dir)) < 0)
1307 return main_exit(root_progress_node, EXIT_FAILURE);1598 return main_exit(root_progress_node, EXIT_FAILURE);
1308 }1599 }
1309 }1600 }
src/os.cpp+24
...@@ -1051,6 +1051,30 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {...@@ -1051,6 +1051,30 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
1051 }1051 }
1052}1052}
10531053
1054Error os_dump_file(Buf *src_path, FILE *dest_file) {
1055 Error err;
1056
1057 FILE *src_f = fopen(buf_ptr(src_path), "rb");
1058 if (!src_f) {
1059 int err = errno;
1060 if (err == ENOENT) {
1061 return ErrorFileNotFound;
1062 } else if (err == EACCES || err == EPERM) {
1063 return ErrorAccess;
1064 } else {
1065 return ErrorFileSystem;
1066 }
1067 }
1068 copy_open_files(src_f, dest_file);
1069 if ((err = copy_open_files(src_f, dest_file))) {
1070 fclose(src_f);
1071 return err;
1072 }
1073
1074 fclose(src_f);
1075 return ErrorNone;
1076}
1077
1054#if defined(ZIG_OS_WINDOWS)1078#if defined(ZIG_OS_WINDOWS)
1055static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {1079static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
1056 mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;1080 mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
src/os.hpp+1
...@@ -129,6 +129,7 @@ void os_file_close(OsFile *file);...@@ -129,6 +129,7 @@ void os_file_close(OsFile *file);
129Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);129Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
130Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);130Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
131Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);131Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
132Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file);
132133
133Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);134Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
134Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);135Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
src/parse_f128.c+62-17
...@@ -165,22 +165,36 @@ static long long scanexp(struct MuslFILE *f, int pok)...@@ -165,22 +165,36 @@ static long long scanexp(struct MuslFILE *f, int pok)
165 int x;165 int x;
166 long long y;166 long long y;
167 int neg = 0;167 int neg = 0;
168 168
169 c = shgetc(f);169 c = shgetc(f);
170 if (c=='+' || c=='-') {170 if (c=='+' || c=='-') {
171 neg = (c=='-');171 neg = (c=='-');
172 c = shgetc(f);172 c = shgetc(f);
173 if (c-'0'>=10U && pok) shunget(f);173 if (c-'0'>=10U && pok) shunget(f);
174 }174 }
175 if (c-'0'>=10U) {175 if (c-'0'>=10U && c!='_') {
176 shunget(f);176 shunget(f);
177 return LLONG_MIN;177 return LLONG_MIN;
178 }178 }
179 for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f))179 for (x=0; ; c = shgetc(f)) {
180 x = 10*x + c-'0';180 if (c=='_') {
181 for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f))181 continue;
182 y = 10*y + c-'0';182 } else if (c-'0'<10U && x<INT_MAX/10) {
183 for (; c-'0'<10U; c = shgetc(f));183 x = 10*x + c-'0';
184 } else {
185 break;
186 }
187 }
188 for (y=x; ; c = shgetc(f)) {
189 if (c=='_') {
190 continue;
191 } else if (c-'0'<10U && y<LLONG_MAX/100) {
192 y = 10*y + c-'0';
193 } else {
194 break;
195 }
196 }
197 for (; c-'0'<10U || c=='_'; c = shgetc(f));
184 shunget(f);198 shunget(f);
185 return neg ? -y : y;199 return neg ? -y : y;
186}200}
...@@ -450,16 +464,36 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si...@@ -450,16 +464,36 @@ static float128_t decfloat(struct MuslFILE *f, int c, int bits, int emin, int si
450 j=0;464 j=0;
451 k=0;465 k=0;
452466
453 /* Don't let leading zeros consume buffer space */467 /* Don't let leading zeros/underscores consume buffer space */
454 for (; c=='0'; c = shgetc(f)) gotdig=1;468 for (; ; c = shgetc(f)) {
469 if (c=='_') {
470 continue;
471 } else if (c=='0') {
472 gotdig=1;
473 } else {
474 break;
475 }
476 }
477
455 if (c=='.') {478 if (c=='.') {
456 gotrad = 1;479 gotrad = 1;
457 for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--;480 for (c = shgetc(f); ; c = shgetc(f)) {
481 if (c == '_') {
482 continue;
483 } else if (c=='0') {
484 gotdig=1;
485 lrp--;
486 } else {
487 break;
488 }
489 }
458 }490 }
459491
460 x[0] = 0;492 x[0] = 0;
461 for (; c-'0'<10U || c=='.'; c = shgetc(f)) {493 for (; c-'0'<10U || c=='.' || c=='_'; c = shgetc(f)) {
462 if (c == '.') {494 if (c == '_') {
495 continue;
496 } else if (c == '.') {
463 if (gotrad) break;497 if (gotrad) break;
464 gotrad = 1;498 gotrad = 1;
465 lrp = dc;499 lrp = dc;
...@@ -773,18 +807,29 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int...@@ -773,18 +807,29 @@ static float128_t hexfloat(struct MuslFILE *f, int bits, int emin, int sign, int
773807
774 c = shgetc(f);808 c = shgetc(f);
775809
776 /* Skip leading zeros */810 /* Skip leading zeros/underscores */
777 for (; c=='0'; c = shgetc(f)) gotdig = 1;811 for (; c=='0' || c=='_'; c = shgetc(f)) gotdig = 1;
778812
779 if (c=='.') {813 if (c=='.') {
780 gotrad = 1;814 gotrad = 1;
781 c = shgetc(f);815 c = shgetc(f);
782 /* Count zeros after the radix point before significand */816 /* Count zeros after the radix point before significand */
783 for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1;817 for (rp=0; ; c = shgetc(f)) {
818 if (c == '_') {
819 continue;
820 } else if (c == '0') {
821 gotdig = 1;
822 rp--;
823 } else {
824 break;
825 }
826 }
784 }827 }
785828
786 for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) {829 for (; c-'0'<10U || (c|32)-'a'<6U || c=='.' || c=='_'; c = shgetc(f)) {
787 if (c=='.') {830 if (c=='_') {
831 continue;
832 } else if (c=='.') {
788 if (gotrad) break;833 if (gotrad) break;
789 rp = dc;834 rp = dc;
790 gotrad = 1;835 gotrad = 1;
src/parser.cpp+9-2
...@@ -879,7 +879,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {...@@ -879,7 +879,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
879// / KEYWORD_noasync BlockExprStatement879// / KEYWORD_noasync BlockExprStatement
880// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)880// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
881// / KEYWORD_defer BlockExprStatement881// / KEYWORD_defer BlockExprStatement
882// / KEYWORD_errdefer BlockExprStatement882// / KEYWORD_errdefer Payload? BlockExprStatement
883// / IfStatement883// / IfStatement
884// / LabeledStatement884// / LabeledStatement
885// / SwitchExpr885// / SwitchExpr
...@@ -923,12 +923,18 @@ static AstNode *ast_parse_statement(ParseContext *pc) {...@@ -923,12 +923,18 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
923 if (defer == nullptr)923 if (defer == nullptr)
924 defer = eat_token_if(pc, TokenIdKeywordErrdefer);924 defer = eat_token_if(pc, TokenIdKeywordErrdefer);
925 if (defer != nullptr) {925 if (defer != nullptr) {
926 Token *payload = (defer->id == TokenIdKeywordErrdefer) ?
927 ast_parse_payload(pc) : nullptr;
926 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);928 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
927 AstNode *res = ast_create_node(pc, NodeTypeDefer, defer);929 AstNode *res = ast_create_node(pc, NodeTypeDefer, defer);
930
928 res->data.defer.kind = ReturnKindUnconditional;931 res->data.defer.kind = ReturnKindUnconditional;
929 res->data.defer.expr = statement;932 res->data.defer.expr = statement;
930 if (defer->id == TokenIdKeywordErrdefer)933 if (defer->id == TokenIdKeywordErrdefer) {
931 res->data.defer.kind = ReturnKindError;934 res->data.defer.kind = ReturnKindError;
935 if (payload != nullptr)
936 res->data.defer.err_payload = token_symbol(pc, payload);
937 }
932 return res;938 return res;
933 }939 }
934940
...@@ -3032,6 +3038,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3032,6 +3038,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3032 break;3038 break;
3033 case NodeTypeDefer:3039 case NodeTypeDefer:
3034 visit_field(&node->data.defer.expr, visit, context);3040 visit_field(&node->data.defer.expr, visit, context);
3041 visit_field(&node->data.defer.err_payload, visit, context);
3035 break;3042 break;
3036 case NodeTypeVariableDeclaration:3043 case NodeTypeVariableDeclaration:
3037 visit_field(&node->data.variable_declaration.type, visit, context);3044 visit_field(&node->data.variable_declaration.type, visit, context);
src/stage2.cpp+12
...@@ -304,3 +304,15 @@ enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {...@@ -304,3 +304,15 @@ enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {
304304
305 return ErrorNone;305 return ErrorNone;
306}306}
307
308void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,
309 size_t argc, char **argv)
310{
311 const char *msg = "stage0 called stage2_clang_arg_iterator";
312 stage2_panic(msg, strlen(msg));
313}
314
315enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it) {
316 const char *msg = "stage0 called stage2_clang_arg_next";
317 stage2_panic(msg, strlen(msg));
318}
src/stage2.h+47
...@@ -105,6 +105,10 @@ enum Error {...@@ -105,6 +105,10 @@ enum Error {
105 ErrorTargetHasNoDynamicLinker,105 ErrorTargetHasNoDynamicLinker,
106 ErrorInvalidAbiVersion,106 ErrorInvalidAbiVersion,
107 ErrorInvalidOperatingSystemVersion,107 ErrorInvalidOperatingSystemVersion,
108 ErrorUnknownClangOption,
109 ErrorPermissionDenied,
110 ErrorFileBusy,
111 ErrorLocked,
108};112};
109113
110// ABI warning114// ABI warning
...@@ -291,6 +295,7 @@ struct ZigTarget {...@@ -291,6 +295,7 @@ struct ZigTarget {
291 size_t cache_hash_len;295 size_t cache_hash_len;
292 const char *os_builtin_str;296 const char *os_builtin_str;
293 const char *dynamic_linker;297 const char *dynamic_linker;
298 const char *standard_dynamic_linker_path;
294};299};
295300
296// ABI warning301// ABI warning
...@@ -315,4 +320,46 @@ struct Stage2NativePaths {...@@ -315,4 +320,46 @@ struct Stage2NativePaths {
315// ABI warning320// ABI warning
316ZIG_EXTERN_C enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths);321ZIG_EXTERN_C enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths);
317322
323// ABI warning
324enum Stage2ClangArg {
325 Stage2ClangArgTarget,
326 Stage2ClangArgO,
327 Stage2ClangArgC,
328 Stage2ClangArgOther,
329 Stage2ClangArgPositional,
330 Stage2ClangArgL,
331 Stage2ClangArgIgnore,
332 Stage2ClangArgDriverPunt,
333 Stage2ClangArgPIC,
334 Stage2ClangArgNoPIC,
335 Stage2ClangArgNoStdLib,
336 Stage2ClangArgShared,
337 Stage2ClangArgRDynamic,
338 Stage2ClangArgWL,
339 Stage2ClangArgPreprocess,
340 Stage2ClangArgOptimize,
341 Stage2ClangArgDebug,
342 Stage2ClangArgSanitize,
343};
344
345// ABI warning
346struct Stage2ClangArgIterator {
347 bool has_next;
348 enum Stage2ClangArg kind;
349 const char *only_arg;
350 const char *second_arg;
351 const char **other_args_ptr;
352 size_t other_args_len;
353 const char **argv_ptr;
354 size_t argv_len;
355 size_t next_index;
356};
357
358// ABI warning
359ZIG_EXTERN_C void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,
360 size_t argc, char **argv);
361
362// ABI warning
363ZIG_EXTERN_C enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it);
364
318#endif365#endif
src/tokenizer.cpp+89-56
...@@ -177,10 +177,13 @@ enum TokenizeState {...@@ -177,10 +177,13 @@ enum TokenizeState {
177 TokenizeStateSymbol,177 TokenizeStateSymbol,
178 TokenizeStateZero, // "0", which might lead to "0x"178 TokenizeStateZero, // "0", which might lead to "0x"
179 TokenizeStateNumber, // "123", "0x123"179 TokenizeStateNumber, // "123", "0x123"
180 TokenizeStateNumberNoUnderscore, // "12_", "0x12_" next char must be digit
180 TokenizeStateNumberDot,181 TokenizeStateNumberDot,
181 TokenizeStateFloatFraction, // "123.456", "0x123.456"182 TokenizeStateFloatFraction, // "123.456", "0x123.456"
183 TokenizeStateFloatFractionNoUnderscore, // "123.45_", "0x123.45_"
182 TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p"184 TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p"
183 TokenizeStateFloatExponentNumber, // "123.456e-", "123.456e5", "123.456e5e-5"185 TokenizeStateFloatExponentNumber, // "123.456e7", "123.456e+7", "123.456e-7"
186 TokenizeStateFloatExponentNumberNoUnderscore, // "123.456e7_", "123.456e+7_", "123.456e-7_"
184 TokenizeStateString,187 TokenizeStateString,
185 TokenizeStateStringEscape,188 TokenizeStateStringEscape,
186 TokenizeStateStringEscapeUnicodeStart,189 TokenizeStateStringEscapeUnicodeStart,
...@@ -233,14 +236,10 @@ struct Tokenize {...@@ -233,14 +236,10 @@ struct Tokenize {
233 Token *cur_tok;236 Token *cur_tok;
234 Tokenization *out;237 Tokenization *out;
235 uint32_t radix;238 uint32_t radix;
236 int32_t exp_add_amt;239 bool is_trailing_underscore;
237 bool is_exp_negative;
238 size_t char_code_index;240 size_t char_code_index;
239 bool unicode;241 bool unicode;
240 uint32_t char_code;242 uint32_t char_code;
241 int exponent_in_bin_or_dec;
242 BigInt specified_exponent;
243 BigInt significand;
244 size_t remaining_code_units;243 size_t remaining_code_units;
245};244};
246245
...@@ -426,20 +425,16 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -426,20 +425,16 @@ void tokenize(Buf *buf, Tokenization *out) {
426 case '0':425 case '0':
427 t.state = TokenizeStateZero;426 t.state = TokenizeStateZero;
428 begin_token(&t, TokenIdIntLiteral);427 begin_token(&t, TokenIdIntLiteral);
428 t.is_trailing_underscore = false;
429 t.radix = 10;429 t.radix = 10;
430 t.exp_add_amt = 1;
431 t.exponent_in_bin_or_dec = 0;
432 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0);430 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0);
433 bigint_init_unsigned(&t.specified_exponent, 0);
434 break;431 break;
435 case DIGIT_NON_ZERO:432 case DIGIT_NON_ZERO:
436 t.state = TokenizeStateNumber;433 t.state = TokenizeStateNumber;
437 begin_token(&t, TokenIdIntLiteral);434 begin_token(&t, TokenIdIntLiteral);
435 t.is_trailing_underscore = false;
438 t.radix = 10;436 t.radix = 10;
439 t.exp_add_amt = 1;
440 t.exponent_in_bin_or_dec = 0;
441 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c));437 bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c));
442 bigint_init_unsigned(&t.specified_exponent, 0);
443 break;438 break;
444 case '"':439 case '"':
445 begin_token(&t, TokenIdStringLiteral);440 begin_token(&t, TokenIdStringLiteral);
...@@ -1189,17 +1184,15 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1189,17 +1184,15 @@ void tokenize(Buf *buf, Tokenization *out) {
1189 switch (c) {1184 switch (c) {
1190 case 'b':1185 case 'b':
1191 t.radix = 2;1186 t.radix = 2;
1192 t.state = TokenizeStateNumber;1187 t.state = TokenizeStateNumberNoUnderscore;
1193 break;1188 break;
1194 case 'o':1189 case 'o':
1195 t.radix = 8;1190 t.radix = 8;
1196 t.exp_add_amt = 3;1191 t.state = TokenizeStateNumberNoUnderscore;
1197 t.state = TokenizeStateNumber;
1198 break;1192 break;
1199 case 'x':1193 case 'x':
1200 t.radix = 16;1194 t.radix = 16;
1201 t.exp_add_amt = 4;1195 t.state = TokenizeStateNumberNoUnderscore;
1202 t.state = TokenizeStateNumber;
1203 break;1196 break;
1204 default:1197 default:
1205 // reinterpret as normal number1198 // reinterpret as normal number
...@@ -1208,9 +1201,27 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1208,9 +1201,27 @@ void tokenize(Buf *buf, Tokenization *out) {
1208 continue;1201 continue;
1209 }1202 }
1210 break;1203 break;
1204 case TokenizeStateNumberNoUnderscore:
1205 if (c == '_') {
1206 invalid_char_error(&t, c);
1207 break;
1208 } else if (get_digit_value(c) < t.radix) {
1209 t.is_trailing_underscore = false;
1210 t.state = TokenizeStateNumber;
1211 }
1212 // fall through
1211 case TokenizeStateNumber:1213 case TokenizeStateNumber:
1212 {1214 {
1215 if (c == '_') {
1216 t.is_trailing_underscore = true;
1217 t.state = TokenizeStateNumberNoUnderscore;
1218 break;
1219 }
1213 if (c == '.') {1220 if (c == '.') {
1221 if (t.is_trailing_underscore) {
1222 invalid_char_error(&t, c);
1223 break;
1224 }
1214 if (t.radix != 16 && t.radix != 10) {1225 if (t.radix != 16 && t.radix != 10) {
1215 invalid_char_error(&t, c);1226 invalid_char_error(&t, c);
1216 }1227 }
...@@ -1218,17 +1229,26 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1218,17 +1229,26 @@ void tokenize(Buf *buf, Tokenization *out) {
1218 break;1229 break;
1219 }1230 }
1220 if (is_exponent_signifier(c, t.radix)) {1231 if (is_exponent_signifier(c, t.radix)) {
1232 if (t.is_trailing_underscore) {
1233 invalid_char_error(&t, c);
1234 break;
1235 }
1221 if (t.radix != 16 && t.radix != 10) {1236 if (t.radix != 16 && t.radix != 10) {
1222 invalid_char_error(&t, c);1237 invalid_char_error(&t, c);
1223 }1238 }
1224 t.state = TokenizeStateFloatExponentUnsigned;1239 t.state = TokenizeStateFloatExponentUnsigned;
1240 t.radix = 10; // exponent is always base 10
1225 assert(t.cur_tok->id == TokenIdIntLiteral);1241 assert(t.cur_tok->id == TokenIdIntLiteral);
1226 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
1227 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);1242 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);
1228 break;1243 break;
1229 }1244 }
1230 uint32_t digit_value = get_digit_value(c);1245 uint32_t digit_value = get_digit_value(c);
1231 if (digit_value >= t.radix) {1246 if (digit_value >= t.radix) {
1247 if (t.is_trailing_underscore) {
1248 invalid_char_error(&t, c);
1249 break;
1250 }
1251
1232 if (is_symbol_char(c)) {1252 if (is_symbol_char(c)) {
1233 invalid_char_error(&t, c);1253 invalid_char_error(&t, c);
1234 }1254 }
...@@ -1259,20 +1279,41 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1259,20 +1279,41 @@ void tokenize(Buf *buf, Tokenization *out) {
1259 continue;1279 continue;
1260 }1280 }
1261 t.pos -= 1;1281 t.pos -= 1;
1262 t.state = TokenizeStateFloatFraction;1282 t.state = TokenizeStateFloatFractionNoUnderscore;
1263 assert(t.cur_tok->id == TokenIdIntLiteral);1283 assert(t.cur_tok->id == TokenIdIntLiteral);
1264 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
1265 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);1284 set_token_id(&t, t.cur_tok, TokenIdFloatLiteral);
1266 continue;1285 continue;
1267 }1286 }
1287 case TokenizeStateFloatFractionNoUnderscore:
1288 if (c == '_') {
1289 invalid_char_error(&t, c);
1290 } else if (get_digit_value(c) < t.radix) {
1291 t.is_trailing_underscore = false;
1292 t.state = TokenizeStateFloatFraction;
1293 }
1294 // fall through
1268 case TokenizeStateFloatFraction:1295 case TokenizeStateFloatFraction:
1269 {1296 {
1297 if (c == '_') {
1298 t.is_trailing_underscore = true;
1299 t.state = TokenizeStateFloatFractionNoUnderscore;
1300 break;
1301 }
1270 if (is_exponent_signifier(c, t.radix)) {1302 if (is_exponent_signifier(c, t.radix)) {
1303 if (t.is_trailing_underscore) {
1304 invalid_char_error(&t, c);
1305 break;
1306 }
1271 t.state = TokenizeStateFloatExponentUnsigned;1307 t.state = TokenizeStateFloatExponentUnsigned;
1308 t.radix = 10; // exponent is always base 10
1272 break;1309 break;
1273 }1310 }
1274 uint32_t digit_value = get_digit_value(c);1311 uint32_t digit_value = get_digit_value(c);
1275 if (digit_value >= t.radix) {1312 if (digit_value >= t.radix) {
1313 if (t.is_trailing_underscore) {
1314 invalid_char_error(&t, c);
1315 break;
1316 }
1276 if (is_symbol_char(c)) {1317 if (is_symbol_char(c)) {
1277 invalid_char_error(&t, c);1318 invalid_char_error(&t, c);
1278 }1319 }
...@@ -1282,46 +1323,47 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1282,46 +1323,47 @@ void tokenize(Buf *buf, Tokenization *out) {
1282 t.state = TokenizeStateStart;1323 t.state = TokenizeStateStart;
1283 continue;1324 continue;
1284 }1325 }
1285 t.exponent_in_bin_or_dec -= t.exp_add_amt;
1286 if (t.radix == 10) {
1287 // For now we use strtod to parse decimal floats, so we just have to get to the
1288 // end of the token.
1289 break;
1290 }
1291 BigInt digit_value_bi;
1292 bigint_init_unsigned(&digit_value_bi, digit_value);
1293
1294 BigInt radix_bi;
1295 bigint_init_unsigned(&radix_bi, t.radix);
1296
1297 BigInt multiplied;
1298 bigint_mul(&multiplied, &t.significand, &radix_bi);
12991326
1300 bigint_add(&t.significand, &multiplied, &digit_value_bi);1327 // we use parse_f128 to generate the float literal, so just
1301 break;1328 // need to get to the end of the token
1302 }1329 }
1330 break;
1303 case TokenizeStateFloatExponentUnsigned:1331 case TokenizeStateFloatExponentUnsigned:
1304 switch (c) {1332 switch (c) {
1305 case '+':1333 case '+':
1306 t.is_exp_negative = false;1334 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
1307 t.state = TokenizeStateFloatExponentNumber;
1308 break;1335 break;
1309 case '-':1336 case '-':
1310 t.is_exp_negative = true;1337 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
1311 t.state = TokenizeStateFloatExponentNumber;
1312 break;1338 break;
1313 default:1339 default:
1314 // reinterpret as normal exponent number1340 // reinterpret as normal exponent number
1315 t.pos -= 1;1341 t.pos -= 1;
1316 t.is_exp_negative = false;1342 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
1317 t.state = TokenizeStateFloatExponentNumber;
1318 continue;1343 continue;
1319 }1344 }
1320 break;1345 break;
1346 case TokenizeStateFloatExponentNumberNoUnderscore:
1347 if (c == '_') {
1348 invalid_char_error(&t, c);
1349 } else if (get_digit_value(c) < t.radix) {
1350 t.is_trailing_underscore = false;
1351 t.state = TokenizeStateFloatExponentNumber;
1352 }
1353 // fall through
1321 case TokenizeStateFloatExponentNumber:1354 case TokenizeStateFloatExponentNumber:
1322 {1355 {
1356 if (c == '_') {
1357 t.is_trailing_underscore = true;
1358 t.state = TokenizeStateFloatExponentNumberNoUnderscore;
1359 break;
1360 }
1323 uint32_t digit_value = get_digit_value(c);1361 uint32_t digit_value = get_digit_value(c);
1324 if (digit_value >= t.radix) {1362 if (digit_value >= t.radix) {
1363 if (t.is_trailing_underscore) {
1364 invalid_char_error(&t, c);
1365 break;
1366 }
1325 if (is_symbol_char(c)) {1367 if (is_symbol_char(c)) {
1326 invalid_char_error(&t, c);1368 invalid_char_error(&t, c);
1327 }1369 }
...@@ -1331,21 +1373,9 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1331,21 +1373,9 @@ void tokenize(Buf *buf, Tokenization *out) {
1331 t.state = TokenizeStateStart;1373 t.state = TokenizeStateStart;
1332 continue;1374 continue;
1333 }1375 }
1334 if (t.radix == 10) {
1335 // For now we use strtod to parse decimal floats, so we just have to get to the
1336 // end of the token.
1337 break;
1338 }
1339 BigInt digit_value_bi;
1340 bigint_init_unsigned(&digit_value_bi, digit_value);
1341
1342 BigInt radix_bi;
1343 bigint_init_unsigned(&radix_bi, 10);
1344
1345 BigInt multiplied;
1346 bigint_mul(&multiplied, &t.specified_exponent, &radix_bi);
13471376
1348 bigint_add(&t.specified_exponent, &multiplied, &digit_value_bi);1377 // we use parse_f128 to generate the float literal, so just
1378 // need to get to the end of the token
1349 }1379 }
1350 break;1380 break;
1351 case TokenizeStateSawDash:1381 case TokenizeStateSawDash:
...@@ -1399,6 +1429,9 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1399,6 +1429,9 @@ void tokenize(Buf *buf, Tokenization *out) {
1399 case TokenizeStateStart:1429 case TokenizeStateStart:
1400 case TokenizeStateError:1430 case TokenizeStateError:
1401 break;1431 break;
1432 case TokenizeStateNumberNoUnderscore:
1433 case TokenizeStateFloatFractionNoUnderscore:
1434 case TokenizeStateFloatExponentNumberNoUnderscore:
1402 case TokenizeStateNumberDot:1435 case TokenizeStateNumberDot:
1403 tokenize_error(&t, "unterminated number literal");1436 tokenize_error(&t, "unterminated number literal");
1404 break;1437 break;
test/cli.zig+1-1
...@@ -36,7 +36,7 @@ pub fn main() !void {...@@ -36,7 +36,7 @@ pub fn main() !void {
36 testMissingOutputPath,36 testMissingOutputPath,
37 };37 };
38 for (test_fns) |testFn| {38 for (test_fns) |testFn| {
39 try fs.deleteTree(dir_path);39 try fs.cwd().deleteTree(dir_path);
40 try fs.cwd().makeDir(dir_path);40 try fs.cwd().makeDir(dir_path);
41 try testFn(zig_exe, dir_path);41 try testFn(zig_exe, dir_path);
42 }42 }
test/compare_output.zig+1-1
...@@ -292,7 +292,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -292,7 +292,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
292 \\pub export fn main() c_int {292 \\pub export fn main() c_int {
293 \\ var array = [_]u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };293 \\ var array = [_]u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
294 \\294 \\
295 \\ c.qsort(@ptrCast(?*c_void, array[0..].ptr), @intCast(c_ulong, array.len), @sizeOf(i32), compare_fn);295 \\ c.qsort(@ptrCast(?*c_void, &array), @intCast(c_ulong, array.len), @sizeOf(i32), compare_fn);
296 \\296 \\
297 \\ for (array) |item, i| {297 \\ for (array) |item, i| {
298 \\ if (item != i) {298 \\ if (item != i) {
test/compile_errors.zig+178-15
...@@ -2,6 +2,29 @@ const tests = @import("tests.zig");...@@ -2,6 +2,29 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.addTest("unused variable error on errdefer",
6 \\fn foo() !void {
7 \\ errdefer |a| unreachable;
8 \\ return error.A;
9 \\}
10 \\export fn entry() void {
11 \\ foo() catch unreachable;
12 \\}
13 , &[_][]const u8{
14 "tmp.zig:2:15: error: unused variable: 'a'",
15 });
16
17 cases.addTest("comparison of non-tagged union and enum literal",
18 \\export fn entry() void {
19 \\ const U = union { A: u32, B: u64 };
20 \\ var u = U{ .A = 42 };
21 \\ var ok = u == .A;
22 \\}
23 , &[_][]const u8{
24 "tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types",
25 "tmp.zig:2:15: note: type U is not a tagged union",
26 });
27
5 cases.addTest("shift on type with non-power-of-two size",28 cases.addTest("shift on type with non-power-of-two size",
6 \\export fn entry() void {29 \\export fn entry() void {
7 \\ const S = struct {30 \\ const S = struct {
...@@ -103,18 +126,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -103,18 +126,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
103 "tmp.zig:3:23: error: pointer to size 0 type has no address",126 "tmp.zig:3:23: error: pointer to size 0 type has no address",
104 });127 });
105128
106 cases.addTest("slice to pointer conversion mismatch",
107 \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 {
108 \\ return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1];
109 \\}
110 \\test "bytesAsSlice" {
111 \\ const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
112 \\ const slice = bytesAsSlice(bytes[0..]);
113 \\}
114 , &[_][]const u8{
115 "tmp.zig:2:54: error: expected type '[*]align(1) const u16', found '[]align(1) const u16'",
116 });
117
118 cases.addTest("access invalid @typeInfo decl",129 cases.addTest("access invalid @typeInfo decl",
119 \\const A = B;130 \\const A = B;
120 \\test "Crash" {131 \\test "Crash" {
...@@ -384,11 +395,163 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -384,11 +395,163 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
384 \\ var bad_float :f32 = 0.0;395 \\ var bad_float :f32 = 0.0;
385 \\ bad_float = bad_float + .20;396 \\ bad_float = bad_float + .20;
386 \\ std.debug.assert(bad_float < 1.0);397 \\ std.debug.assert(bad_float < 1.0);
387 \\})398 \\}
388 , &[_][]const u8{399 , &[_][]const u8{
389 "tmp.zig:5:29: error: invalid token: '.'",400 "tmp.zig:5:29: error: invalid token: '.'",
390 });401 });
391402
403 cases.add("invalid exponent in float literal - 1",
404 \\fn main() void {
405 \\ var bad: f128 = 0x1.0p1ab1;
406 \\}
407 , &[_][]const u8{
408 "tmp.zig:2:28: error: invalid character: 'a'",
409 });
410
411 cases.add("invalid exponent in float literal - 2",
412 \\fn main() void {
413 \\ var bad: f128 = 0x1.0p50F;
414 \\}
415 , &[_][]const u8{
416 "tmp.zig:2:29: error: invalid character: 'F'",
417 });
418
419 cases.add("invalid underscore placement in float literal - 1",
420 \\fn main() void {
421 \\ var bad: f128 = 0._0;
422 \\}
423 , &[_][]const u8{
424 "tmp.zig:2:23: error: invalid character: '_'",
425 });
426
427 cases.add("invalid underscore placement in float literal - 2",
428 \\fn main() void {
429 \\ var bad: f128 = 0_.0;
430 \\}
431 , &[_][]const u8{
432 "tmp.zig:2:23: error: invalid character: '.'",
433 });
434
435 cases.add("invalid underscore placement in float literal - 3",
436 \\fn main() void {
437 \\ var bad: f128 = 0.0_;
438 \\}
439 , &[_][]const u8{
440 "tmp.zig:2:25: error: invalid character: ';'",
441 });
442
443 cases.add("invalid underscore placement in float literal - 4",
444 \\fn main() void {
445 \\ var bad: f128 = 1.0e_1;
446 \\}
447 , &[_][]const u8{
448 "tmp.zig:2:25: error: invalid character: '_'",
449 });
450
451 cases.add("invalid underscore placement in float literal - 5",
452 \\fn main() void {
453 \\ var bad: f128 = 1.0e+_1;
454 \\}
455 , &[_][]const u8{
456 "tmp.zig:2:26: error: invalid character: '_'",
457 });
458
459 cases.add("invalid underscore placement in float literal - 6",
460 \\fn main() void {
461 \\ var bad: f128 = 1.0e-_1;
462 \\}
463 , &[_][]const u8{
464 "tmp.zig:2:26: error: invalid character: '_'",
465 });
466
467 cases.add("invalid underscore placement in float literal - 7",
468 \\fn main() void {
469 \\ var bad: f128 = 1.0e-1_;
470 \\}
471 , &[_][]const u8{
472 "tmp.zig:2:28: error: invalid character: ';'",
473 });
474
475 cases.add("invalid underscore placement in float literal - 9",
476 \\fn main() void {
477 \\ var bad: f128 = 1__0.0e-1;
478 \\}
479 , &[_][]const u8{
480 "tmp.zig:2:23: error: invalid character: '_'",
481 });
482
483 cases.add("invalid underscore placement in float literal - 10",
484 \\fn main() void {
485 \\ var bad: f128 = 1.0__0e-1;
486 \\}
487 , &[_][]const u8{
488 "tmp.zig:2:25: error: invalid character: '_'",
489 });
490
491 cases.add("invalid underscore placement in float literal - 11",
492 \\fn main() void {
493 \\ var bad: f128 = 1.0e-1__0;
494 \\}
495 , &[_][]const u8{
496 "tmp.zig:2:28: error: invalid character: '_'",
497 });
498
499 cases.add("invalid underscore placement in float literal - 12",
500 \\fn main() void {
501 \\ var bad: f128 = 0_x0.0;
502 \\}
503 , &[_][]const u8{
504 "tmp.zig:2:23: error: invalid character: 'x'",
505 });
506
507 cases.add("invalid underscore placement in float literal - 13",
508 \\fn main() void {
509 \\ var bad: f128 = 0x_0.0;
510 \\}
511 , &[_][]const u8{
512 "tmp.zig:2:23: error: invalid character: '_'",
513 });
514
515 cases.add("invalid underscore placement in float literal - 14",
516 \\fn main() void {
517 \\ var bad: f128 = 0x0.0_p1;
518 \\}
519 , &[_][]const u8{
520 "tmp.zig:2:27: error: invalid character: 'p'",
521 });
522
523 cases.add("invalid underscore placement in int literal - 1",
524 \\fn main() void {
525 \\ var bad: u128 = 0010_;
526 \\}
527 , &[_][]const u8{
528 "tmp.zig:2:26: error: invalid character: ';'",
529 });
530
531 cases.add("invalid underscore placement in int literal - 2",
532 \\fn main() void {
533 \\ var bad: u128 = 0b0010_;
534 \\}
535 , &[_][]const u8{
536 "tmp.zig:2:28: error: invalid character: ';'",
537 });
538
539 cases.add("invalid underscore placement in int literal - 3",
540 \\fn main() void {
541 \\ var bad: u128 = 0o0010_;
542 \\}
543 , &[_][]const u8{
544 "tmp.zig:2:28: error: invalid character: ';'",
545 });
546
547 cases.add("invalid underscore placement in int literal - 4",
548 \\fn main() void {
549 \\ var bad: u128 = 0x0010_;
550 \\}
551 , &[_][]const u8{
552 "tmp.zig:2:28: error: invalid character: ';'",
553 });
554
392 cases.add("var args without c calling conv",555 cases.add("var args without c calling conv",
393 \\fn foo(args: ...) void {}556 \\fn foo(args: ...) void {}
394 \\comptime {557 \\comptime {
...@@ -1918,8 +2081,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1918,8 +2081,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1918 cases.add("reading past end of pointer casted array",2081 cases.add("reading past end of pointer casted array",
1919 \\comptime {2082 \\comptime {
1920 \\ const array: [4]u8 = "aoeu".*;2083 \\ const array: [4]u8 = "aoeu".*;
1921 \\ const slice = array[1..];2084 \\ const sub_array = array[1..];
1922 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);2085 \\ const int_ptr = @ptrCast(*const u24, sub_array);
1923 \\ const deref = int_ptr.*;2086 \\ const deref = int_ptr.*;
1924 \\}2087 \\}
1925 , &[_][]const u8{2088 , &[_][]const u8{
test/runtime_safety.zig+1-1
...@@ -69,7 +69,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -69,7 +69,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
69 \\}69 \\}
70 \\pub fn main() void {70 \\pub fn main() void {
71 \\ var buf: [4]u8 = undefined;71 \\ var buf: [4]u8 = undefined;
72 \\ const ptr = buf[0..].ptr;72 \\ const ptr: [*]u8 = &buf;
73 \\ const slice = ptr[0..3 :0];73 \\ const slice = ptr[0..3 :0];
74 \\}74 \\}
75 );75 );
test/stage1/behavior/align.zig+22-14
...@@ -5,10 +5,17 @@ const builtin = @import("builtin");...@@ -5,10 +5,17 @@ const builtin = @import("builtin");
5var foo: u8 align(4) = 100;5var foo: u8 align(4) = 100;
66
7test "global variable alignment" {7test "global variable alignment" {
8 expect(@TypeOf(&foo).alignment == 4);8 comptime expect(@TypeOf(&foo).alignment == 4);
9 expect(@TypeOf(&foo) == *align(4) u8);9 comptime expect(@TypeOf(&foo) == *align(4) u8);
10 const slice = @as(*[1]u8, &foo)[0..];10 {
11 expect(@TypeOf(slice) == []align(4) u8);11 const slice = @as(*[1]u8, &foo)[0..];
12 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
13 }
14 {
15 var runtime_zero: usize = 0;
16 const slice = @as(*[1]u8, &foo)[runtime_zero..];
17 comptime expect(@TypeOf(slice) == []align(4) u8);
18 }
12}19}
1320
14fn derp() align(@sizeOf(usize) * 2) i32 {21fn derp() align(@sizeOf(usize) * 2) i32 {
...@@ -171,18 +178,19 @@ test "runtime known array index has best alignment possible" {...@@ -171,18 +178,19 @@ test "runtime known array index has best alignment possible" {
171178
172 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2179 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
173 var smaller align(2) = [_]u32{ 1, 2, 3, 4 };180 var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
174 comptime expect(@TypeOf(smaller[0..]) == []align(2) u32);181 var runtime_zero: usize = 0;
175 comptime expect(@TypeOf(smaller[0..].ptr) == [*]align(2) u32);182 comptime expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
176 testIndex(smaller[0..].ptr, 0, *align(2) u32);183 comptime expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
177 testIndex(smaller[0..].ptr, 1, *align(2) u32);184 testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
178 testIndex(smaller[0..].ptr, 2, *align(2) u32);185 testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
179 testIndex(smaller[0..].ptr, 3, *align(2) u32);186 testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
187 testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
180188
181 // has to use ABI alignment because index known at runtime only189 // has to use ABI alignment because index known at runtime only
182 testIndex2(array[0..].ptr, 0, *u8);190 testIndex2(array[runtime_zero..].ptr, 0, *u8);
183 testIndex2(array[0..].ptr, 1, *u8);191 testIndex2(array[runtime_zero..].ptr, 1, *u8);
184 testIndex2(array[0..].ptr, 2, *u8);192 testIndex2(array[runtime_zero..].ptr, 2, *u8);
185 testIndex2(array[0..].ptr, 3, *u8);193 testIndex2(array[runtime_zero..].ptr, 3, *u8);
186}194}
187fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {195fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
188 comptime expect(@TypeOf(&smaller[index]) == T);196 comptime expect(@TypeOf(&smaller[index]) == T);
test/stage1/behavior/array.zig+38
...@@ -28,6 +28,24 @@ fn getArrayLen(a: []const u32) usize {...@@ -28,6 +28,24 @@ fn getArrayLen(a: []const u32) usize {
28 return a.len;28 return a.len;
29}29}
3030
31test "array with sentinels" {
32 const S = struct {
33 fn doTheTest(is_ct: bool) void {
34 var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
35 expectEqual(@as(u8, 0xde), zero_sized[0]);
36 // Disabled at runtime because of
37 // https://github.com/ziglang/zig/issues/4372
38 if (is_ct) {
39 var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
40 expectEqual(@as(u8, 0xde), reinterpreted[0]);
41 }
42 }
43 };
44
45 S.doTheTest(false);
46 comptime S.doTheTest(true);
47}
48
31test "void arrays" {49test "void arrays" {
32 var array: [4]void = undefined;50 var array: [4]void = undefined;
33 array[0] = void{};51 array[0] = void{};
...@@ -376,3 +394,23 @@ test "type deduction for array subscript expression" {...@@ -376,3 +394,23 @@ test "type deduction for array subscript expression" {
376 S.doTheTest();394 S.doTheTest();
377 comptime S.doTheTest();395 comptime S.doTheTest();
378}396}
397
398test "sentinel element count towards the ABI size calculation" {
399 const S = struct {
400 fn doTheTest() void {
401 const T = packed struct {
402 fill_pre: u8 = 0x55,
403 data: [0:0]u8 = undefined,
404 fill_post: u8 = 0xAA,
405 };
406 var x = T{};
407 var as_slice = mem.asBytes(&x);
408 expectEqual(@as(usize, 3), as_slice.len);
409 expectEqual(@as(u8, 0x55), as_slice[0]);
410 expectEqual(@as(u8, 0xAA), as_slice[2]);
411 }
412 };
413
414 S.doTheTest();
415 comptime S.doTheTest();
416}
test/stage1/behavior/cast.zig+2-1
...@@ -435,7 +435,8 @@ fn incrementVoidPtrValue(value: ?*c_void) void {...@@ -435,7 +435,8 @@ fn incrementVoidPtrValue(value: ?*c_void) void {
435435
436test "implicit cast from [*]T to ?*c_void" {436test "implicit cast from [*]T to ?*c_void" {
437 var a = [_]u8{ 3, 2, 1 };437 var a = [_]u8{ 3, 2, 1 };
438 incrementVoidPtrArray(a[0..].ptr, 3);438 var runtime_zero: usize = 0;
439 incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
439 expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));440 expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
440}441}
441442
test/stage1/behavior/defer.zig+20-1
...@@ -1,4 +1,7 @@...@@ -1,4 +1,7 @@
1const expect = @import("std").testing.expect;1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectError = std.testing.expectError;
25
3var result: [3]u8 = undefined;6var result: [3]u8 = undefined;
4var index: usize = undefined;7var index: usize = undefined;
...@@ -93,3 +96,19 @@ test "return variable while defer expression in scope to modify it" {...@@ -93,3 +96,19 @@ test "return variable while defer expression in scope to modify it" {
93 S.doTheTest();96 S.doTheTest();
94 comptime S.doTheTest();97 comptime S.doTheTest();
95}98}
99
100test "errdefer with payload" {
101 const S = struct {
102 fn foo() !i32 {
103 errdefer |a| {
104 expectEqual(error.One, a);
105 }
106 return error.One;
107 }
108 fn doTheTest() void {
109 expectError(error.One, foo());
110 }
111 };
112 S.doTheTest();
113 comptime S.doTheTest();
114}
test/stage1/behavior/eval.zig+1-1
...@@ -524,7 +524,7 @@ test "comptime slice of slice preserves comptime var" {...@@ -524,7 +524,7 @@ test "comptime slice of slice preserves comptime var" {
524test "comptime slice of pointer preserves comptime var" {524test "comptime slice of pointer preserves comptime var" {
525 comptime {525 comptime {
526 var buff: [10]u8 = undefined;526 var buff: [10]u8 = undefined;
527 var a = buff[0..].ptr;527 var a = @ptrCast([*]u8, &buff);
528 a[0..1][0] = 1;528 a[0..1][0] = 1;
529 expect(buff[0..][0..][0] == 1);529 expect(buff[0..][0..][0] == 1);
530 }530 }
test/stage1/behavior/math.zig+28
...@@ -411,6 +411,34 @@ test "quad hex float literal parsing accurate" {...@@ -411,6 +411,34 @@ test "quad hex float literal parsing accurate" {
411 comptime S.doTheTest();411 comptime S.doTheTest();
412}412}
413413
414test "underscore separator parsing" {
415 expect(0_0_0_0 == 0);
416 expect(1_234_567 == 1234567);
417 expect(001_234_567 == 1234567);
418 expect(0_0_1_2_3_4_5_6_7 == 1234567);
419
420 expect(0b0_0_0_0 == 0);
421 expect(0b1010_1010 == 0b10101010);
422 expect(0b0000_1010_1010 == 0b10101010);
423 expect(0b1_0_1_0_1_0_1_0 == 0b10101010);
424
425 expect(0o0_0_0_0 == 0);
426 expect(0o1010_1010 == 0o10101010);
427 expect(0o0000_1010_1010 == 0o10101010);
428 expect(0o1_0_1_0_1_0_1_0 == 0o10101010);
429
430 expect(0x0_0_0_0 == 0);
431 expect(0x1010_1010 == 0x10101010);
432 expect(0x0000_1010_1010 == 0x10101010);
433 expect(0x1_0_1_0_1_0_1_0 == 0x10101010);
434
435 expect(123_456.789_000e1_0 == 123456.789000e10);
436 expect(0_1_2_3_4_5_6.7_8_9_0_0_0e0_0_1_0 == 123456.789000e10);
437
438 expect(0x1234_5678.9ABC_DEF0p-1_0 == 0x12345678.9ABCDEF0p-10);
439 expect(0x1_2_3_4_5_6_7_8.9_A_B_C_D_E_F_0p-0_0_0_1_0 == 0x12345678.9ABCDEF0p-10);
440}
441
414test "hex float literal within range" {442test "hex float literal within range" {
415 const a = 0x1.0p16383;443 const a = 0x1.0p16383;
416 const b = 0x0.1p16387;444 const b = 0x0.1p16387;
test/stage1/behavior/misc.zig+9-5
...@@ -102,8 +102,8 @@ test "memcpy and memset intrinsics" {...@@ -102,8 +102,8 @@ test "memcpy and memset intrinsics" {
102 var foo: [20]u8 = undefined;102 var foo: [20]u8 = undefined;
103 var bar: [20]u8 = undefined;103 var bar: [20]u8 = undefined;
104104
105 @memset(foo[0..].ptr, 'A', foo.len);105 @memset(&foo, 'A', foo.len);
106 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);106 @memcpy(&bar, &foo, bar.len);
107107
108 if (bar[11] != 'A') unreachable;108 if (bar[11] != 'A') unreachable;
109}109}
...@@ -565,12 +565,16 @@ test "volatile load and store" {...@@ -565,12 +565,16 @@ test "volatile load and store" {
565 expect(ptr.* == 1235);565 expect(ptr.* == 1235);
566}566}
567567
568test "slice string literal has type []const u8" {568test "slice string literal has correct type" {
569 comptime {569 comptime {
570 expect(@TypeOf("aoeu"[0..]) == []const u8);570 expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
571 const array = [_]i32{ 1, 2, 3, 4 };571 const array = [_]i32{ 1, 2, 3, 4 };
572 expect(@TypeOf(array[0..]) == []const i32);572 expect(@TypeOf(array[0..]) == *const [4]i32);
573 }573 }
574 var runtime_zero: usize = 0;
575 comptime expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
576 const array = [_]i32{ 1, 2, 3, 4 };
577 comptime expect(@TypeOf(array[runtime_zero..]) == []const i32);
574}578}
575579
576test "pointer child field" {580test "pointer child field" {
test/stage1/behavior/pointers.zig+5-4
...@@ -159,12 +159,13 @@ test "allowzero pointer and slice" {...@@ -159,12 +159,13 @@ test "allowzero pointer and slice" {
159 var opt_ptr: ?[*]allowzero i32 = ptr;159 var opt_ptr: ?[*]allowzero i32 = ptr;
160 expect(opt_ptr != null);160 expect(opt_ptr != null);
161 expect(@ptrToInt(ptr) == 0);161 expect(@ptrToInt(ptr) == 0);
162 var slice = ptr[0..10];162 var runtime_zero: usize = 0;
163 expect(@TypeOf(slice) == []allowzero i32);163 var slice = ptr[runtime_zero..10];
164 comptime expect(@TypeOf(slice) == []allowzero i32);
164 expect(@ptrToInt(&slice[5]) == 20);165 expect(@ptrToInt(&slice[5]) == 20);
165166
166 expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);167 comptime expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
167 expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);168 comptime expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
168}169}
169170
170test "assign null directly to C pointer and test null equality" {171test "assign null directly to C pointer and test null equality" {
test/stage1/behavior/ptrcast.zig+1-1
...@@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void {...@@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void {
13 builtin.Endian.Little => 0xab785634,13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,14 builtin.Endian.Big => 0x345678ab,
15 };15 };
16 expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);16 expect(@ptrCast(*align(1) const u32, bytes[1..5]).* == expected);
17}17}
1818
19test "reinterpret bytes of an array into an extern struct" {19test "reinterpret bytes of an array into an extern struct" {
test/stage1/behavior/slice.zig+177-4
...@@ -7,10 +7,10 @@ const mem = std.mem;...@@ -7,10 +7,10 @@ const mem = std.mem;
7const x = @intToPtr([*]i32, 0x1000)[0..0x500];7const x = @intToPtr([*]i32, 0x1000)[0..0x500];
8const y = x[0x100..];8const y = x[0x100..];
9test "compile time slice of pointer to hard coded address" {9test "compile time slice of pointer to hard coded address" {
10 expect(@ptrToInt(x.ptr) == 0x1000);10 expect(@ptrToInt(x) == 0x1000);
11 expect(x.len == 0x500);11 expect(x.len == 0x500);
1212
13 expect(@ptrToInt(y.ptr) == 0x1100);13 expect(@ptrToInt(y) == 0x1100);
14 expect(y.len == 0x400);14 expect(y.len == 0x400);
15}15}
1616
...@@ -47,7 +47,9 @@ test "C pointer slice access" {...@@ -47,7 +47,9 @@ test "C pointer slice access" {
47 var buf: [10]u32 = [1]u32{42} ** 10;47 var buf: [10]u32 = [1]u32{42} ** 10;
48 const c_ptr = @ptrCast([*c]const u32, &buf);48 const c_ptr = @ptrCast([*c]const u32, &buf);
4949
50 comptime expectEqual([]const u32, @TypeOf(c_ptr[0..1]));50 var runtime_zero: usize = 0;
51 comptime expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
52 comptime expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
5153
52 for (c_ptr[0..5]) |*cl| {54 for (c_ptr[0..5]) |*cl| {
53 expectEqual(@as(u32, 42), cl.*);55 expectEqual(@as(u32, 42), cl.*);
...@@ -107,7 +109,9 @@ test "obtaining a null terminated slice" {...@@ -107,7 +109,9 @@ test "obtaining a null terminated slice" {
107 const ptr2 = buf[0..runtime_len :0];109 const ptr2 = buf[0..runtime_len :0];
108 // ptr2 is a null-terminated slice110 // ptr2 is a null-terminated slice
109 comptime expect(@TypeOf(ptr2) == [:0]u8);111 comptime expect(@TypeOf(ptr2) == [:0]u8);
110 comptime expect(@TypeOf(ptr2[0..2]) == []u8);112 comptime expect(@TypeOf(ptr2[0..2]) == *[2]u8);
113 var runtime_zero: usize = 0;
114 comptime expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
111}115}
112116
113test "empty array to slice" {117test "empty array to slice" {
...@@ -126,3 +130,172 @@ test "empty array to slice" {...@@ -126,3 +130,172 @@ test "empty array to slice" {
126 S.doTheTest();130 S.doTheTest();
127 comptime S.doTheTest();131 comptime S.doTheTest();
128}132}
133
134test "@ptrCast slice to pointer" {
135 const S = struct {
136 fn doTheTest() void {
137 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
138 var slice: []u8 = &array;
139 var ptr = @ptrCast(*u16, slice);
140 expect(ptr.* == 65535);
141 }
142 };
143
144 S.doTheTest();
145 comptime S.doTheTest();
146}
147
148test "slice syntax resulting in pointer-to-array" {
149 const S = struct {
150 fn doTheTest() void {
151 testArray();
152 testArrayZ();
153 testArray0();
154 testArrayAlign();
155 testPointer();
156 testPointerZ();
157 testPointer0();
158 testPointerAlign();
159 testSlice();
160 testSliceZ();
161 testSlice0();
162 testSliceOpt();
163 testSliceAlign();
164 }
165
166 fn testArray() void {
167 var array = [5]u8{ 1, 2, 3, 4, 5 };
168 var slice = array[1..3];
169 comptime expect(@TypeOf(slice) == *[2]u8);
170 expect(slice[0] == 2);
171 expect(slice[1] == 3);
172 }
173
174 fn testArrayZ() void {
175 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
176 comptime expect(@TypeOf(array[1..3]) == *[2]u8);
177 comptime expect(@TypeOf(array[1..5]) == *[4:0]u8);
178 comptime expect(@TypeOf(array[1..]) == *[4:0]u8);
179 comptime expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
180 }
181
182 fn testArray0() void {
183 {
184 var array = [0]u8{};
185 var slice = array[0..0];
186 comptime expect(@TypeOf(slice) == *[0]u8);
187 }
188 {
189 var array = [0:0]u8{};
190 var slice = array[0..0];
191 comptime expect(@TypeOf(slice) == *[0:0]u8);
192 expect(slice[0] == 0);
193 }
194 }
195
196 fn testArrayAlign() void {
197 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
198 var slice = array[4..5];
199 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
200 expect(slice[0] == 5);
201 comptime expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
202 }
203
204 fn testPointer() void {
205 var array = [5]u8{ 1, 2, 3, 4, 5 };
206 var pointer: [*]u8 = &array;
207 var slice = pointer[1..3];
208 comptime expect(@TypeOf(slice) == *[2]u8);
209 expect(slice[0] == 2);
210 expect(slice[1] == 3);
211 }
212
213 fn testPointerZ() void {
214 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
215 var pointer: [*:0]u8 = &array;
216 comptime expect(@TypeOf(pointer[1..3]) == *[2]u8);
217 comptime expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
218 }
219
220 fn testPointer0() void {
221 var pointer: [*]u0 = &[1]u0{0};
222 var slice = pointer[0..1];
223 comptime expect(@TypeOf(slice) == *[1]u0);
224 expect(slice[0] == 0);
225 }
226
227 fn testPointerAlign() void {
228 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
229 var pointer: [*]align(4) u8 = &array;
230 var slice = pointer[4..5];
231 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
232 expect(slice[0] == 5);
233 comptime expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
234 }
235
236 fn testSlice() void {
237 var array = [5]u8{ 1, 2, 3, 4, 5 };
238 var src_slice: []u8 = &array;
239 var slice = src_slice[1..3];
240 comptime expect(@TypeOf(slice) == *[2]u8);
241 expect(slice[0] == 2);
242 expect(slice[1] == 3);
243 }
244
245 fn testSliceZ() void {
246 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
247 var slice: [:0]u8 = &array;
248 comptime expect(@TypeOf(slice[1..3]) == *[2]u8);
249 comptime expect(@TypeOf(slice[1..]) == [:0]u8);
250 comptime expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
251 }
252
253 fn testSliceOpt() void {
254 var array: [2]u8 = [2]u8{ 1, 2 };
255 var slice: ?[]u8 = &array;
256 comptime expect(@TypeOf(&array, slice) == ?[]u8);
257 comptime expect(@TypeOf(slice.?[0..2]) == *[2]u8);
258 }
259
260 fn testSlice0() void {
261 {
262 var array = [0]u8{};
263 var src_slice: []u8 = &array;
264 var slice = src_slice[0..0];
265 comptime expect(@TypeOf(slice) == *[0]u8);
266 }
267 {
268 var array = [0:0]u8{};
269 var src_slice: [:0]u8 = &array;
270 var slice = src_slice[0..0];
271 comptime expect(@TypeOf(slice) == *[0]u8);
272 }
273 }
274
275 fn testSliceAlign() void {
276 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
277 var src_slice: []align(4) u8 = &array;
278 var slice = src_slice[4..5];
279 comptime expect(@TypeOf(slice) == *align(4) [1]u8);
280 expect(slice[0] == 5);
281 comptime expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
282 }
283 };
284
285 S.doTheTest();
286 comptime S.doTheTest();
287}
288
289test "slice of hardcoded address to pointer" {
290 const S = struct {
291 fn doTheTest() void {
292 const pointer = @intToPtr([*]u8, 0x04)[0..2];
293 comptime expect(@TypeOf(pointer) == *[2]u8);
294 const slice: []const u8 = pointer;
295 expect(@ptrToInt(slice.ptr) == 4);
296 expect(slice.len == 2);
297 }
298 };
299
300 S.doTheTest();
301}
test/stage1/behavior/struct.zig+2-2
...@@ -409,8 +409,8 @@ const Bitfields = packed struct {...@@ -409,8 +409,8 @@ const Bitfields = packed struct {
409test "native bit field understands endianness" {409test "native bit field understands endianness" {
410 var all: u64 = 0x7765443322221111;410 var all: u64 = 0x7765443322221111;
411 var bytes: [8]u8 = undefined;411 var bytes: [8]u8 = undefined;
412 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);412 @memcpy(&bytes, @ptrCast([*]u8, &all), 8);
413 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;413 var bitfields = @ptrCast(*Bitfields, &bytes).*;
414414
415 expect(bitfields.f1 == 0x1111);415 expect(bitfields.f1 == 0x1111);
416 expect(bitfields.f2 == 0x2222);416 expect(bitfields.f2 == 0x2222);
test/stage1/behavior/union.zig+28
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
34
4const Value = union(enum) {5const Value = union(enum) {
5 Int: u64,6 Int: u64,
...@@ -638,3 +639,30 @@ test "runtime tag name with single field" {...@@ -638,3 +639,30 @@ test "runtime tag name with single field" {
638 var v = U{ .A = 42 };639 var v = U{ .A = 42 };
639 expect(std.mem.eql(u8, @tagName(v), "A"));640 expect(std.mem.eql(u8, @tagName(v), "A"));
640}641}
642
643test "cast from anonymous struct to union" {
644 const S = struct {
645 const U = union(enum) {
646 A: u32,
647 B: []const u8,
648 C: void,
649 };
650 fn doTheTest() void {
651 var y: u32 = 42;
652 const t0 = .{ .A = 123 };
653 const t1 = .{ .B = "foo" };
654 const t2 = .{ .C = {} };
655 const t3 = .{ .A = y };
656 const x0: U = t0;
657 var x1: U = t1;
658 const x2: U = t2;
659 var x3: U = t3;
660 expect(x0.A == 123);
661 expect(std.mem.eql(u8, x1.B, "foo"));
662 expect(x2 == .C);
663 expect(x3.A == y);
664 }
665 };
666 S.doTheTest();
667 comptime S.doTheTest();
668}
test/standalone/mix_o_files/test.c+5-3
...@@ -1,10 +1,12 @@...@@ -1,10 +1,12 @@
1// This header is generated by zig from base64.zig
2#include "base64.h"
3
4#include <assert.h>1#include <assert.h>
5#include <string.h>2#include <string.h>
6#include <stdint.h>3#include <stdint.h>
74
5// TODO we would like to #include "base64.h" here but this feature has been disabled in
6// the stage1 compiler. Users will have to wait until self-hosted is available for
7// the "generate .h file" feature.
8size_t decode_base_64(uint8_t *dest_ptr, size_t dest_len, const uint8_t *source_ptr, size_t source_len);
9
8extern int *x_ptr;10extern int *x_ptr;
911
10int main(int argc, char **argv) {12int main(int argc, char **argv) {
test/standalone/shared_library/test.c+7-1
...@@ -1,6 +1,12 @@...@@ -1,6 +1,12 @@
1#include "mathtest.h"
2#include <assert.h>1#include <assert.h>
32
3// TODO we would like to #include "mathtest.h" here but this feature has been disabled in
4// the stage1 compiler. Users will have to wait until self-hosted is available for
5// the "generate .h file" feature.
6
7#include <stdint.h>
8int32_t add(int32_t a, int32_t b);
9
4int main(int argc, char **argv) {10int main(int argc, char **argv) {
5 assert(add(42, 1337) == 1379);11 assert(add(42, 1337) == 1379);
6 return 0;12 return 0;
tools/process_headers.zig+11-11
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1// To get started, run this tool with no args and read the help message.1//! To get started, run this tool with no args and read the help message.
2//2//!
3// The build systems of musl-libc and glibc require specifying a single target3//! The build systems of musl-libc and glibc require specifying a single target
4// architecture. Meanwhile, Zig supports out-of-the-box cross compilation for4//! architecture. Meanwhile, Zig supports out-of-the-box cross compilation for
5// every target. So the process to create libc headers that Zig ships is to use5//! every target. So the process to create libc headers that Zig ships is to use
6// this tool.6//! this tool.
7// First, use the musl/glibc build systems to create installations of all the7//! First, use the musl/glibc build systems to create installations of all the
8// targets in the `glibc_targets`/`musl_targets` variables.8//! targets in the `glibc_targets`/`musl_targets` variables.
9// Next, run this tool to create a new directory which puts .h files into9//! Next, run this tool to create a new directory which puts .h files into
10// <arch> subdirectories, with `generic` being files that apply to all architectures.10//! <arch> subdirectories, with `generic` being files that apply to all architectures.
11// You'll then have to manually update Zig source repo with these new files.11//! You'll then have to manually update Zig source repo with these new files.
1212
13const std = @import("std");13const std = @import("std");
14const Arch = std.Target.Cpu.Arch;14const Arch = std.Target.Cpu.Arch;
tools/update_clang_options.zig created+460
...@@ -0,0 +1,460 @@
1//! To get started, run this tool with no args and read the help message.
2//!
3//! Clang has a file "options.td" which describes all of its command line parameter options.
4//! When using `zig cc`, Zig acts as a proxy between the user and Clang. It does not need
5//! to understand all the parameters, but it does need to understand some of them, such as
6//! the target. This means that Zig must understand when a C command line parameter expects
7//! to "consume" the next parameter on the command line.
8//!
9//! For example, `-z -target` would mean to pass `-target` to the linker, whereas `-E -target`
10//! would mean that the next parameter specifies the target.
11
12const std = @import("std");
13const fs = std.fs;
14const assert = std.debug.assert;
15const json = std.json;
16
17const KnownOpt = struct {
18 name: []const u8,
19
20 /// Corresponds to stage.zig ClangArgIterator.Kind
21 ident: []const u8,
22};
23
24const known_options = [_]KnownOpt{
25 .{
26 .name = "target",
27 .ident = "target",
28 },
29 .{
30 .name = "o",
31 .ident = "o",
32 },
33 .{
34 .name = "c",
35 .ident = "c",
36 },
37 .{
38 .name = "l",
39 .ident = "l",
40 },
41 .{
42 .name = "pipe",
43 .ident = "ignore",
44 },
45 .{
46 .name = "help",
47 .ident = "driver_punt",
48 },
49 .{
50 .name = "fPIC",
51 .ident = "pic",
52 },
53 .{
54 .name = "fno-PIC",
55 .ident = "no_pic",
56 },
57 .{
58 .name = "nostdlib",
59 .ident = "nostdlib",
60 },
61 .{
62 .name = "no-standard-libraries",
63 .ident = "nostdlib",
64 },
65 .{
66 .name = "shared",
67 .ident = "shared",
68 },
69 .{
70 .name = "rdynamic",
71 .ident = "rdynamic",
72 },
73 .{
74 .name = "Wl,",
75 .ident = "wl",
76 },
77 .{
78 .name = "E",
79 .ident = "preprocess",
80 },
81 .{
82 .name = "preprocess",
83 .ident = "preprocess",
84 },
85 .{
86 .name = "S",
87 .ident = "driver_punt",
88 },
89 .{
90 .name = "assemble",
91 .ident = "driver_punt",
92 },
93 .{
94 .name = "O1",
95 .ident = "optimize",
96 },
97 .{
98 .name = "O2",
99 .ident = "optimize",
100 },
101 .{
102 .name = "Og",
103 .ident = "optimize",
104 },
105 .{
106 .name = "O",
107 .ident = "optimize",
108 },
109 .{
110 .name = "Ofast",
111 .ident = "optimize",
112 },
113 .{
114 .name = "optimize",
115 .ident = "optimize",
116 },
117 .{
118 .name = "g",
119 .ident = "debug",
120 },
121 .{
122 .name = "debug",
123 .ident = "debug",
124 },
125 .{
126 .name = "g-dwarf",
127 .ident = "debug",
128 },
129 .{
130 .name = "g-dwarf-2",
131 .ident = "debug",
132 },
133 .{
134 .name = "g-dwarf-3",
135 .ident = "debug",
136 },
137 .{
138 .name = "g-dwarf-4",
139 .ident = "debug",
140 },
141 .{
142 .name = "g-dwarf-5",
143 .ident = "debug",
144 },
145 .{
146 .name = "fsanitize",
147 .ident = "sanitize",
148 },
149};
150
151const blacklisted_options = [_][]const u8{};
152
153fn knownOption(name: []const u8) ?[]const u8 {
154 const chopped_name = if (std.mem.endsWith(u8, name, "=")) name[0 .. name.len - 1] else name;
155 for (known_options) |item| {
156 if (std.mem.eql(u8, chopped_name, item.name)) {
157 return item.ident;
158 }
159 }
160 return null;
161}
162
163pub fn main() anyerror!void {
164 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
165 defer arena.deinit();
166
167 const allocator = &arena.allocator;
168 const args = try std.process.argsAlloc(allocator);
169
170 if (args.len <= 1) {
171 usageAndExit(std.io.getStdErr(), args[0], 1);
172 }
173 if (std.mem.eql(u8, args[1], "--help")) {
174 usageAndExit(std.io.getStdOut(), args[0], 0);
175 }
176 if (args.len < 3) {
177 usageAndExit(std.io.getStdErr(), args[0], 1);
178 }
179
180 const llvm_tblgen_exe = args[1];
181 if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) {
182 usageAndExit(std.io.getStdErr(), args[0], 1);
183 }
184
185 const llvm_src_root = args[2];
186 if (std.mem.startsWith(u8, llvm_src_root, "-")) {
187 usageAndExit(std.io.getStdErr(), args[0], 1);
188 }
189
190 const child_args = [_][]const u8{
191 llvm_tblgen_exe,
192 "--dump-json",
193 try std.fmt.allocPrint(allocator, "{}/clang/include/clang/Driver/Options.td", .{llvm_src_root}),
194 try std.fmt.allocPrint(allocator, "-I={}/llvm/include", .{llvm_src_root}),
195 try std.fmt.allocPrint(allocator, "-I={}/clang/include/clang/Driver", .{llvm_src_root}),
196 };
197
198 const child_result = try std.ChildProcess.exec2(.{
199 .allocator = allocator,
200 .argv = &child_args,
201 .max_output_bytes = 100 * 1024 * 1024,
202 });
203
204 std.debug.warn("{}\n", .{child_result.stderr});
205
206 const json_text = switch (child_result.term) {
207 .Exited => |code| if (code == 0) child_result.stdout else {
208 std.debug.warn("llvm-tblgen exited with code {}\n", .{code});
209 std.process.exit(1);
210 },
211 else => {
212 std.debug.warn("llvm-tblgen crashed\n", .{});
213 std.process.exit(1);
214 },
215 };
216
217 var parser = json.Parser.init(allocator, false);
218 const tree = try parser.parse(json_text);
219 const root_map = &tree.root.Object;
220
221 var all_objects = std.ArrayList(*json.ObjectMap).init(allocator);
222 {
223 var it = root_map.iterator();
224 it_map: while (it.next()) |kv| {
225 if (kv.key.len == 0) continue;
226 if (kv.key[0] == '!') continue;
227 if (kv.value != .Object) continue;
228 if (!kv.value.Object.contains("NumArgs")) continue;
229 if (!kv.value.Object.contains("Name")) continue;
230 for (blacklisted_options) |blacklisted_key| {
231 if (std.mem.eql(u8, blacklisted_key, kv.key)) continue :it_map;
232 }
233 if (kv.value.Object.get("Name").?.value.String.len == 0) continue;
234 try all_objects.append(&kv.value.Object);
235 }
236 }
237 // Some options have multiple matches. As an example, "-Wl,foo" matches both
238 // "W" and "Wl,". So we sort this list in order of descending priority.
239 std.sort.sort(*json.ObjectMap, all_objects.span(), objectLessThan);
240
241 var stdout_bos = std.io.bufferedOutStream(std.io.getStdOut().outStream());
242 const stdout = stdout_bos.outStream();
243 try stdout.writeAll(
244 \\// This file is generated by tools/update_clang_options.zig.
245 \\// zig fmt: off
246 \\usingnamespace @import("clang_options.zig");
247 \\pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
248 \\
249 );
250
251 for (all_objects.span()) |obj| {
252 const name = obj.get("Name").?.value.String;
253 var pd1 = false;
254 var pd2 = false;
255 var pslash = false;
256 for (obj.get("Prefixes").?.value.Array.span()) |prefix_json| {
257 const prefix = prefix_json.String;
258 if (std.mem.eql(u8, prefix, "-")) {
259 pd1 = true;
260 } else if (std.mem.eql(u8, prefix, "--")) {
261 pd2 = true;
262 } else if (std.mem.eql(u8, prefix, "/")) {
263 pslash = true;
264 } else {
265 std.debug.warn("{} has unrecognized prefix '{}'\n", .{ name, prefix });
266 std.process.exit(1);
267 }
268 }
269 const syntax = objSyntax(obj);
270
271 if (knownOption(name)) |ident| {
272 try stdout.print(
273 \\.{{
274 \\ .name = "{}",
275 \\ .syntax = {},
276 \\ .zig_equivalent = .{},
277 \\ .pd1 = {},
278 \\ .pd2 = {},
279 \\ .psl = {},
280 \\}},
281 \\
282 , .{ name, syntax, ident, pd1, pd2, pslash });
283 } else if (pd1 and !pd2 and !pslash and syntax == .flag) {
284 try stdout.print("flagpd1(\"{}\"),\n", .{name});
285 } else if (pd1 and !pd2 and !pslash and syntax == .joined) {
286 try stdout.print("joinpd1(\"{}\"),\n", .{name});
287 } else if (pd1 and !pd2 and !pslash and syntax == .joined_or_separate) {
288 try stdout.print("jspd1(\"{}\"),\n", .{name});
289 } else if (pd1 and !pd2 and !pslash and syntax == .separate) {
290 try stdout.print("sepd1(\"{}\"),\n", .{name});
291 } else {
292 try stdout.print(
293 \\.{{
294 \\ .name = "{}",
295 \\ .syntax = {},
296 \\ .zig_equivalent = .other,
297 \\ .pd1 = {},
298 \\ .pd2 = {},
299 \\ .psl = {},
300 \\}},
301 \\
302 , .{ name, syntax, pd1, pd2, pslash });
303 }
304 }
305
306 try stdout.writeAll(
307 \\};};
308 \\
309 );
310
311 try stdout_bos.flush();
312}
313
314// TODO we should be able to import clang_options.zig but currently this is problematic because it will
315// import stage2.zig and that causes a bunch of stuff to get exported
316const Syntax = union(enum) {
317 /// A flag with no values.
318 flag,
319
320 /// An option which prefixes its (single) value.
321 joined,
322
323 /// An option which is followed by its value.
324 separate,
325
326 /// An option which is either joined to its (non-empty) value, or followed by its value.
327 joined_or_separate,
328
329 /// An option which is both joined to its (first) value, and followed by its (second) value.
330 joined_and_separate,
331
332 /// An option followed by its values, which are separated by commas.
333 comma_joined,
334
335 /// An option which consumes an optional joined argument and any other remaining arguments.
336 remaining_args_joined,
337
338 /// An option which is which takes multiple (separate) arguments.
339 multi_arg: u8,
340
341 pub fn format(
342 self: Syntax,
343 comptime fmt: []const u8,
344 options: std.fmt.FormatOptions,
345 out_stream: var,
346 ) !void {
347 switch (self) {
348 .multi_arg => |n| return out_stream.print(".{{.{}={}}}", .{ @tagName(self), n }),
349 else => return out_stream.print(".{}", .{@tagName(self)}),
350 }
351 }
352};
353
354fn objSyntax(obj: *json.ObjectMap) Syntax {
355 const num_args = @intCast(u8, obj.get("NumArgs").?.value.Integer);
356 for (obj.get("!superclasses").?.value.Array.span()) |superclass_json| {
357 const superclass = superclass_json.String;
358 if (std.mem.eql(u8, superclass, "Joined")) {
359 return .joined;
360 } else if (std.mem.eql(u8, superclass, "CLJoined")) {
361 return .joined;
362 } else if (std.mem.eql(u8, superclass, "CLIgnoredJoined")) {
363 return .joined;
364 } else if (std.mem.eql(u8, superclass, "CLCompileJoined")) {
365 return .joined;
366 } else if (std.mem.eql(u8, superclass, "JoinedOrSeparate")) {
367 return .joined_or_separate;
368 } else if (std.mem.eql(u8, superclass, "CLJoinedOrSeparate")) {
369 return .joined_or_separate;
370 } else if (std.mem.eql(u8, superclass, "CLCompileJoinedOrSeparate")) {
371 return .joined_or_separate;
372 } else if (std.mem.eql(u8, superclass, "Flag")) {
373 return .flag;
374 } else if (std.mem.eql(u8, superclass, "CLFlag")) {
375 return .flag;
376 } else if (std.mem.eql(u8, superclass, "CLIgnoredFlag")) {
377 return .flag;
378 } else if (std.mem.eql(u8, superclass, "Separate")) {
379 return .separate;
380 } else if (std.mem.eql(u8, superclass, "JoinedAndSeparate")) {
381 return .joined_and_separate;
382 } else if (std.mem.eql(u8, superclass, "CommaJoined")) {
383 return .comma_joined;
384 } else if (std.mem.eql(u8, superclass, "CLRemainingArgsJoined")) {
385 return .remaining_args_joined;
386 } else if (std.mem.eql(u8, superclass, "MultiArg")) {
387 return .{ .multi_arg = num_args };
388 }
389 }
390 const name = obj.get("Name").?.value.String;
391 if (std.mem.eql(u8, name, "<input>")) {
392 return .flag;
393 } else if (std.mem.eql(u8, name, "<unknown>")) {
394 return .flag;
395 }
396 const kind_def = obj.get("Kind").?.value.Object.get("def").?.value.String;
397 if (std.mem.eql(u8, kind_def, "KIND_FLAG")) {
398 return .flag;
399 }
400 const key = obj.get("!name").?.value.String;
401 std.debug.warn("{} (key {}) has unrecognized superclasses:\n", .{ name, key });
402 for (obj.get("!superclasses").?.value.Array.span()) |superclass_json| {
403 std.debug.warn(" {}\n", .{superclass_json.String});
404 }
405 std.process.exit(1);
406}
407
408fn syntaxMatchesWithEql(syntax: Syntax) bool {
409 return switch (syntax) {
410 .flag,
411 .separate,
412 .multi_arg,
413 => true,
414
415 .joined,
416 .joined_or_separate,
417 .joined_and_separate,
418 .comma_joined,
419 .remaining_args_joined,
420 => false,
421 };
422}
423
424fn objectLessThan(a: *json.ObjectMap, b: *json.ObjectMap) bool {
425 // Priority is determined by exact matches first, followed by prefix matches in descending
426 // length, with key as a final tiebreaker.
427 const a_syntax = objSyntax(a);
428 const b_syntax = objSyntax(b);
429
430 const a_match_with_eql = syntaxMatchesWithEql(a_syntax);
431 const b_match_with_eql = syntaxMatchesWithEql(b_syntax);
432
433 if (a_match_with_eql and !b_match_with_eql) {
434 return true;
435 } else if (!a_match_with_eql and b_match_with_eql) {
436 return false;
437 }
438
439 if (!a_match_with_eql and !b_match_with_eql) {
440 const a_name = a.get("Name").?.value.String;
441 const b_name = b.get("Name").?.value.String;
442 if (a_name.len != b_name.len) {
443 return a_name.len > b_name.len;
444 }
445 }
446
447 const a_key = a.get("!name").?.value.String;
448 const b_key = b.get("!name").?.value.String;
449 return std.mem.lessThan(u8, a_key, b_key);
450}
451
452fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
453 file.outStream().print(
454 \\Usage: {} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
455 \\
456 \\Prints to stdout Zig code which you can use to replace the file src-self-hosted/clang_options_data.zig.
457 \\
458 , .{arg0}) catch std.process.exit(1);
459 std.process.exit(code);
460}
tools/update_glibc.zig+16-13
...@@ -20,6 +20,7 @@ const lib_names = [_][]const u8{...@@ -20,6 +20,7 @@ const lib_names = [_][]const u8{
20 "m",20 "m",
21 "pthread",21 "pthread",
22 "rt",22 "rt",
23 "ld",
23};24};
2425
25// fpu/nofpu are hardcoded elsewhere, based on .gnueabi/.gnueabihf with an exception for .arm26// fpu/nofpu are hardcoded elsewhere, based on .gnueabi/.gnueabihf with an exception for .arm
...@@ -154,22 +155,24 @@ pub fn main() !void {...@@ -154,22 +155,24 @@ pub fn main() !void {
154 const fn_set = &target_funcs_gop.kv.value.list;155 const fn_set = &target_funcs_gop.kv.value.list;
155156
156 for (lib_names) |lib_name, lib_name_index| {157 for (lib_names) |lib_name, lib_name_index| {
157 const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name});158 const lib_prefix = if (std.mem.eql(u8, lib_name, "ld")) "" else "lib";
159 const basename = try fmt.allocPrint(allocator, "{}{}.abilist", .{ lib_prefix, lib_name });
158 const abi_list_filename = blk: {160 const abi_list_filename = blk: {
159 if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {161 const is_c = std.mem.eql(u8, lib_name, "c");
162 const is_m = std.mem.eql(u8, lib_name, "m");
163 const is_ld = std.mem.eql(u8, lib_name, "ld");
164 if (abi_list.targets[0].abi == .gnuabi64 and (is_c or is_ld)) {
160 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });165 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });
161 } else if (abi_list.targets[0].abi == .gnuabin32 and std.mem.eql(u8, lib_name, "c")) {166 } else if (abi_list.targets[0].abi == .gnuabin32 and (is_c or is_ld)) {
162 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n32", basename });167 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n32", basename });
163 } else if (abi_list.targets[0].arch != .arm and168 } else if (abi_list.targets[0].arch != .arm and
164 abi_list.targets[0].abi == .gnueabihf and169 abi_list.targets[0].abi == .gnueabihf and
165 (std.mem.eql(u8, lib_name, "c") or170 (is_c or (is_m and abi_list.targets[0].arch == .powerpc)))
166 (std.mem.eql(u8, lib_name, "m") and abi_list.targets[0].arch == .powerpc)))
167 {171 {
168 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "fpu", basename });172 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "fpu", basename });
169 } else if (abi_list.targets[0].arch != .arm and173 } else if (abi_list.targets[0].arch != .arm and
170 abi_list.targets[0].abi == .gnueabi and174 abi_list.targets[0].abi == .gnueabi and
171 (std.mem.eql(u8, lib_name, "c") or175 (is_c or (is_m and abi_list.targets[0].arch == .powerpc)))
172 (std.mem.eql(u8, lib_name, "m") and abi_list.targets[0].arch == .powerpc)))
173 {176 {
174 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "nofpu", basename });177 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "nofpu", basename });
175 } else if (abi_list.targets[0].arch == .arm) {178 } else if (abi_list.targets[0].arch == .arm) {
...@@ -234,8 +237,8 @@ pub fn main() !void {...@@ -234,8 +237,8 @@ pub fn main() !void {
234 const vers_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "vers.txt" });237 const vers_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "vers.txt" });
235 const vers_txt_file = try fs.cwd().createFile(vers_txt_path, .{});238 const vers_txt_file = try fs.cwd().createFile(vers_txt_path, .{});
236 defer vers_txt_file.close();239 defer vers_txt_file.close();
237 var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&vers_txt_file.outStream().stream);240 var buffered = std.io.bufferedOutStream(vers_txt_file.outStream());
238 const vers_txt = &buffered.stream;241 const vers_txt = buffered.outStream();
239 for (global_ver_list) |name, i| {242 for (global_ver_list) |name, i| {
240 _ = global_ver_set.put(name, i) catch unreachable;243 _ = global_ver_set.put(name, i) catch unreachable;
241 try vers_txt.print("{}\n", .{name});244 try vers_txt.print("{}\n", .{name});
...@@ -246,8 +249,8 @@ pub fn main() !void {...@@ -246,8 +249,8 @@ pub fn main() !void {
246 const fns_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "fns.txt" });249 const fns_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "fns.txt" });
247 const fns_txt_file = try fs.cwd().createFile(fns_txt_path, .{});250 const fns_txt_file = try fs.cwd().createFile(fns_txt_path, .{});
248 defer fns_txt_file.close();251 defer fns_txt_file.close();
249 var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&fns_txt_file.outStream().stream);252 var buffered = std.io.bufferedOutStream(fns_txt_file.outStream());
250 const fns_txt = &buffered.stream;253 const fns_txt = buffered.outStream();
251 for (global_fn_list) |name, i| {254 for (global_fn_list) |name, i| {
252 const kv = global_fn_set.get(name).?;255 const kv = global_fn_set.get(name).?;
253 kv.value.index = i;256 kv.value.index = i;
...@@ -277,8 +280,8 @@ pub fn main() !void {...@@ -277,8 +280,8 @@ pub fn main() !void {
277 const abilist_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "abi.txt" });280 const abilist_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "abi.txt" });
278 const abilist_txt_file = try fs.cwd().createFile(abilist_txt_path, .{});281 const abilist_txt_file = try fs.cwd().createFile(abilist_txt_path, .{});
279 defer abilist_txt_file.close();282 defer abilist_txt_file.close();
280 var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&abilist_txt_file.outStream().stream);283 var buffered = std.io.bufferedOutStream(abilist_txt_file.outStream());
281 const abilist_txt = &buffered.stream;284 const abilist_txt = buffered.outStream();
282285
283 // first iterate over the abi lists286 // first iterate over the abi lists
284 for (abi_lists) |*abi_list, abi_index| {287 for (abi_lists) |*abi_list, abi_index| {