authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-03 16:50:29-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-03 16:50:29-05:00
log81fa31c05456facea1d1963a1e7f665351fb248d
tree8ea6dba0c5b8ec9e8ba9cdff48189da68c198dfd
parent850b053ea6b7d6f0f5e0e8dbcf37080ca012024f
parentd94303be2bcee33e7efba22a186fd06eaa809707
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10451 from ziglang/cache-mode

stage2: introduce CacheMode

45 files changed, 2061 insertions(+), 1453 deletions(-)

lib/std/fs.zig+1-1
...@@ -1361,7 +1361,7 @@ pub const Dir = struct {...@@ -1361,7 +1361,7 @@ pub const Dir = struct {
1361 .share_access = share_access,1361 .share_access = share_access,
1362 .creation = creation,1362 .creation = creation,
1363 .io_mode = .blocking,1363 .io_mode = .blocking,
1364 .open_dir = true,1364 .filter = .dir_only,
1365 }) catch |er| switch (er) {1365 }) catch |er| switch (er) {
1366 error.WouldBlock => unreachable,1366 error.WouldBlock => unreachable,
1367 else => |e2| return e2,1367 else => |e2| return e2,
lib/std/fs/watch.zig+1-1
...@@ -401,7 +401,7 @@ pub fn Watch(comptime V: type) type {...@@ -401,7 +401,7 @@ pub fn Watch(comptime V: type) type {
401 .access_mask = windows.FILE_LIST_DIRECTORY,401 .access_mask = windows.FILE_LIST_DIRECTORY,
402 .creation = windows.FILE_OPEN,402 .creation = windows.FILE_OPEN,
403 .io_mode = .evented,403 .io_mode = .evented,
404 .open_dir = true,404 .filter = .dir_only,
405 });405 });
406 errdefer windows.CloseHandle(dir_handle);406 errdefer windows.CloseHandle(dir_handle);
407407
lib/std/os.zig+6-5
...@@ -1353,7 +1353,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions {...@@ -1353,7 +1353,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions {
1353 access_mask |= w.GENERIC_READ | w.GENERIC_WRITE;1353 access_mask |= w.GENERIC_READ | w.GENERIC_WRITE;
1354 }1354 }
13551355
1356 const open_dir: bool = flags & O.DIRECTORY != 0;1356 const filter: windows.OpenFileOptions.Filter = if (flags & O.DIRECTORY != 0) .dir_only else .file_only;
1357 const follow_symlinks: bool = flags & O.NOFOLLOW == 0;1357 const follow_symlinks: bool = flags & O.NOFOLLOW == 0;
13581358
1359 const creation: w.ULONG = blk: {1359 const creation: w.ULONG = blk: {
...@@ -1369,7 +1369,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions {...@@ -1369,7 +1369,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions {
1369 .access_mask = access_mask,1369 .access_mask = access_mask,
1370 .io_mode = .blocking,1370 .io_mode = .blocking,
1371 .creation = creation,1371 .creation = creation,
1372 .open_dir = open_dir,1372 .filter = filter,
1373 .follow_symlinks = follow_symlinks,1373 .follow_symlinks = follow_symlinks,
1374 };1374 };
1375}1375}
...@@ -2324,6 +2324,7 @@ pub fn renameatW(...@@ -2324,6 +2324,7 @@ pub fn renameatW(
2324 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,2324 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,
2325 .creation = windows.FILE_OPEN,2325 .creation = windows.FILE_OPEN,
2326 .io_mode = .blocking,2326 .io_mode = .blocking,
2327 .filter = .any, // This function is supposed to rename both files and directories.
2327 }) catch |err| switch (err) {2328 }) catch |err| switch (err) {
2328 error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.2329 error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
2329 else => |e| return e,2330 else => |e| return e,
...@@ -2435,7 +2436,7 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v...@@ -2435,7 +2436,7 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v
2435 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,2436 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
2436 .creation = windows.FILE_CREATE,2437 .creation = windows.FILE_CREATE,
2437 .io_mode = .blocking,2438 .io_mode = .blocking,
2438 .open_dir = true,2439 .filter = .dir_only,
2439 }) catch |err| switch (err) {2440 }) catch |err| switch (err) {
2440 error.IsDir => unreachable,2441 error.IsDir => unreachable,
2441 error.PipeBusy => unreachable,2442 error.PipeBusy => unreachable,
...@@ -2511,7 +2512,7 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void {...@@ -2511,7 +2512,7 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void {
2511 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,2512 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
2512 .creation = windows.FILE_CREATE,2513 .creation = windows.FILE_CREATE,
2513 .io_mode = .blocking,2514 .io_mode = .blocking,
2514 .open_dir = true,2515 .filter = .dir_only,
2515 }) catch |err| switch (err) {2516 }) catch |err| switch (err) {
2516 error.IsDir => unreachable,2517 error.IsDir => unreachable,
2517 error.PipeBusy => unreachable,2518 error.PipeBusy => unreachable,
...@@ -4693,7 +4694,7 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat...@@ -4693,7 +4694,7 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
4693 .share_access = share_access,4694 .share_access = share_access,
4694 .creation = creation,4695 .creation = creation,
4695 .io_mode = .blocking,4696 .io_mode = .blocking,
4696 .open_dir = true,4697 .filter = .dir_only,
4697 }) catch |er| switch (er) {4698 }) catch |er| switch (er) {
4698 error.WouldBlock => unreachable,4699 error.WouldBlock => unreachable,
4699 else => |e2| return e2,4700 else => |e2| return e2,
lib/std/os/windows.zig+18-5
...@@ -53,17 +53,26 @@ pub const OpenFileOptions = struct {...@@ -53,17 +53,26 @@ pub const OpenFileOptions = struct {
53 io_mode: std.io.ModeOverride,53 io_mode: std.io.ModeOverride,
54 /// If true, tries to open path as a directory.54 /// If true, tries to open path as a directory.
55 /// Defaults to false.55 /// Defaults to false.
56 open_dir: bool = false,56 filter: Filter = .file_only,
57 /// If false, tries to open path as a reparse point without dereferencing it.57 /// If false, tries to open path as a reparse point without dereferencing it.
58 /// Defaults to true.58 /// Defaults to true.
59 follow_symlinks: bool = true,59 follow_symlinks: bool = true,
60
61 pub const Filter = enum {
62 /// Causes `OpenFile` to return `error.IsDir` if the opened handle would be a directory.
63 file_only,
64 /// Causes `OpenFile` to return `error.NotDir` if the opened handle would be a file.
65 dir_only,
66 /// `OpenFile` does not discriminate between opening files and directories.
67 any,
68 };
60};69};
6170
62pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE {71pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE {
63 if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and !options.open_dir) {72 if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and options.filter == .file_only) {
64 return error.IsDir;73 return error.IsDir;
65 }74 }
66 if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and !options.open_dir) {75 if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and options.filter == .file_only) {
67 return error.IsDir;76 return error.IsDir;
68 }77 }
6978
...@@ -87,7 +96,11 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -87,7 +96,11 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
87 };96 };
88 var io: IO_STATUS_BLOCK = undefined;97 var io: IO_STATUS_BLOCK = undefined;
89 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;98 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
90 const file_or_dir_flag: ULONG = if (options.open_dir) FILE_DIRECTORY_FILE else FILE_NON_DIRECTORY_FILE;99 const file_or_dir_flag: ULONG = switch (options.filter) {
100 .file_only => FILE_NON_DIRECTORY_FILE,
101 .dir_only => FILE_DIRECTORY_FILE,
102 .any => 0,
103 };
91 // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.104 // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.
92 const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT;105 const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT;
93106
...@@ -695,7 +708,7 @@ pub fn CreateSymbolicLink(...@@ -695,7 +708,7 @@ pub fn CreateSymbolicLink(
695 .dir = dir,708 .dir = dir,
696 .creation = FILE_CREATE,709 .creation = FILE_CREATE,
697 .io_mode = .blocking,710 .io_mode = .blocking,
698 .open_dir = is_directory,711 .filter = if (is_directory) .dir_only else .file_only,
699 }) catch |err| switch (err) {712 }) catch |err| switch (err) {
700 error.IsDir => return error.PathAlreadyExists,713 error.IsDir => return error.PathAlreadyExists,
701 error.NotDir => unreachable,714 error.NotDir => unreachable,
lib/std/special/compiler_rt.zig+529-521
...@@ -22,6 +22,12 @@ else...@@ -22,6 +22,12 @@ else
22const long_double_is_f128 = builtin.target.longDoubleIsF128();22const long_double_is_f128 = builtin.target.longDoubleIsF128();
2323
24comptime {24comptime {
25 // These files do their own comptime exporting logic.
26 if (!builtin.zig_is_stage2) {
27 _ = @import("compiler_rt/atomics.zig");
28 }
29 _ = @import("compiler_rt/clear_cache.zig").clear_cache;
30
25 const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2;31 const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2;
26 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });32 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
27 const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2;33 const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2;
...@@ -171,16 +177,16 @@ comptime {...@@ -171,16 +177,16 @@ comptime {
171 const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;177 const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;
172 @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });178 @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
173179
174 if (!builtin.zig_is_stage2) {180 if (!long_double_is_f128) {
175 if (!long_double_is_f128) {181 // TODO implement these
176 // TODO implement these182 //const __extendxftf2 = @import("compiler_rt/extendXfYf2.zig").__extendxftf2;
177 //const __extendxftf2 = @import("compiler_rt/extendXfYf2.zig").__extendxftf2;183 //@export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = linkage });
178 //@export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = linkage });
179184
180 //const __trunctfxf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfxf2;185 //const __trunctfxf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfxf2;
181 //@export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });186 //@export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });
182 }187 }
183188
189 if (!builtin.zig_is_stage2) {
184 switch (arch) {190 switch (arch) {
185 .i386,191 .i386,
186 .x86_64,192 .x86_64,
...@@ -193,531 +199,533 @@ comptime {...@@ -193,531 +199,533 @@ comptime {
193 },199 },
194 else => {},200 else => {},
195 }201 }
202 }
196203
197 // __clear_cache manages its own logic about whether to be exported or not.204 const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2;
198 _ = @import("compiler_rt/clear_cache.zig").clear_cache;205 @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });
199206 const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2;
200 const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2;207 @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });
201 @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });208 const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2;
202 const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2;209 @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });
203 @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });210
204 const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2;211 const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3;
205 @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });212 @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage });
206213 const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3;
207 const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3;214 @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage });
208 @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage });215 const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3;
209 const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3;216 @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage });
210 @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage });217 const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3;
211 const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3;218 @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage });
212 @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage });219 const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3;
213 const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3;220 @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage });
214 @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage });221 const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3;
215 const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3;222 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });
216 @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage });223
217 const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3;224 const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3;
218 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });225 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });
219226 const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3;
220 const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3;227 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });
221 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });228 const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3;
222 const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3;229 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });
223 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });230
224 const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3;231 const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3;
225 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });232 @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage });
226233 const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3;
227 const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3;234 @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage });
228 @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage });235 const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;
229 const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3;236 @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });
230 @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage });237
231 const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;238 // Integral bit manipulation
232 @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });239 const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;
233240 @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
234 // Integral bit manipulation241 const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3;
235 const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;242 @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
236 @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });243 const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3;
237 const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3;244 @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
238 @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });245 const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3;
239 const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3;246 @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
240 @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });247 const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3;
241 const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3;248 @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
242 @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });249 const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;
243 const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3;250 @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
244 @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });251
245 const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;252 const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;
246 @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });253 @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
247254 const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;
248 const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;255 @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage });
249 @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });256 const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2;
250 const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;257 @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage });
251 @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage });258 const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2;
252 const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2;259 @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage });
253 @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage });260 const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2;
254 const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2;261 @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage });
255 @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage });262 const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2;
256 const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2;263 @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage });
257 @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage });264 const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2;
258 const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2;265 @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage });
259 @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage });266 const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2;
260 const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2;267 @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });
261 @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage });268 const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;
262 const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2;269 @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });
263 @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });270
264 const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;271 const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;
265 @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });272 @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });
266273 const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2;
267 const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;274 @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage });
268 @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });275 const __parityti2 = @import("compiler_rt/parity.zig").__parityti2;
269 const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2;276 @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage });
270 @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage });277
271 const __parityti2 = @import("compiler_rt/parity.zig").__parityti2;278 const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2;
272 @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage });279 @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage });
273 const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2;280 const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2;
274 @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage });281 @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
275 const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2;282 const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2;
276 @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });283 @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage });
277 const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2;284
278 @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage });285 const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2;
279 const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2;286 @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage });
280 @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage });287 const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2;
281 const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2;288 @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = linkage });
282 @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = linkage });289 const __bswapti2 = @import("compiler_rt/bswap.zig").__bswapti2;
283 const __bswapti2 = @import("compiler_rt/bswap.zig").__bswapti2;290 @export(__bswapti2, .{ .name = "__bswapti2", .linkage = linkage });
284 @export(__bswapti2, .{ .name = "__bswapti2", .linkage = linkage });291
285292 // Integral / floating point conversion (part 1/2)
286 // Integral / floating point conversion (part 1/2)293 const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf;
287 const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf;294 @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });
288 @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });295 const __floatsisf = @import("compiler_rt/floatsiXf.zig").__floatsisf;
289 const __floatsisf = @import("compiler_rt/floatsiXf.zig").__floatsisf;296 @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });
290 @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });297 const __floatdidf = @import("compiler_rt/floatdidf.zig").__floatdidf;
291 const __floatdidf = @import("compiler_rt/floatdidf.zig").__floatdidf;298 @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage });
292 @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage });299 const __floatsitf = @import("compiler_rt/floatsiXf.zig").__floatsitf;
293 const __floatsitf = @import("compiler_rt/floatsiXf.zig").__floatsitf;300 @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage });
294 @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage });301
295302 const __floatunsisf = @import("compiler_rt/floatunsisf.zig").__floatunsisf;
296 const __floatunsisf = @import("compiler_rt/floatunsisf.zig").__floatunsisf;303 @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage });
297 @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage });304 if (!builtin.zig_is_stage2) {
298 const __floatundisf = @import("compiler_rt/floatundisf.zig").__floatundisf;305 const __floatundisf = @import("compiler_rt/floatundisf.zig").__floatundisf;
299 @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage });306 @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage });
300 const __floatunsidf = @import("compiler_rt/floatunsidf.zig").__floatunsidf;307 }
301 @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage });308 const __floatunsidf = @import("compiler_rt/floatunsidf.zig").__floatunsidf;
302 const __floatundidf = @import("compiler_rt/floatundidf.zig").__floatundidf;309 @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage });
303 @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage });310 const __floatundidf = @import("compiler_rt/floatundidf.zig").__floatundidf;
304311 @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage });
305 const __floatditf = @import("compiler_rt/floatditf.zig").__floatditf;312
306 @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage });313 const __floatditf = @import("compiler_rt/floatditf.zig").__floatditf;
307 const __floattitf = @import("compiler_rt/floattitf.zig").__floattitf;314 @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage });
308 @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage });315 const __floattitf = @import("compiler_rt/floattitf.zig").__floattitf;
309 const __floattidf = @import("compiler_rt/floattidf.zig").__floattidf;316 @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage });
310 @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage });317 const __floattidf = @import("compiler_rt/floattidf.zig").__floattidf;
311 const __floattisf = @import("compiler_rt/floatXisf.zig").__floattisf;318 @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage });
312 @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage });319 const __floattisf = @import("compiler_rt/floatXisf.zig").__floattisf;
313 const __floatdisf = @import("compiler_rt/floatXisf.zig").__floatdisf;320 @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage });
314 @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage });321 const __floatdisf = @import("compiler_rt/floatXisf.zig").__floatdisf;
315322 @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage });
316 const __floatunditf = @import("compiler_rt/floatunditf.zig").__floatunditf;323
317 @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage });324 const __floatunditf = @import("compiler_rt/floatunditf.zig").__floatunditf;
318 const __floatunsitf = @import("compiler_rt/floatunsitf.zig").__floatunsitf;325 @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage });
319 @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage });326 const __floatunsitf = @import("compiler_rt/floatunsitf.zig").__floatunsitf;
320327 @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage });
321 const __floatuntitf = @import("compiler_rt/floatuntitf.zig").__floatuntitf;328
322 @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage });329 const __floatuntitf = @import("compiler_rt/floatuntitf.zig").__floatuntitf;
323 const __floatuntidf = @import("compiler_rt/floatuntidf.zig").__floatuntidf;330 @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage });
324 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage });331 const __floatuntidf = @import("compiler_rt/floatuntidf.zig").__floatuntidf;
325 const __floatuntisf = @import("compiler_rt/floatuntisf.zig").__floatuntisf;332 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage });
326 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage });333 const __floatuntisf = @import("compiler_rt/floatuntisf.zig").__floatuntisf;
327334 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage });
328 const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2;335
329 @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });336 const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2;
330 if (!is_test) {337 @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
331 @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });338 if (!is_test) {
332 }339 @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
333 const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2;340 }
334 @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });341 const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2;
335342 @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });
336 // Integral / floating point conversion (part 2/2)343
337 const __fixunssfsi = @import("compiler_rt/fixunssfsi.zig").__fixunssfsi;344 // Integral / floating point conversion (part 2/2)
338 @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage });345 const __fixunssfsi = @import("compiler_rt/fixunssfsi.zig").__fixunssfsi;
339 const __fixunssfdi = @import("compiler_rt/fixunssfdi.zig").__fixunssfdi;346 @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage });
340 @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage });347 const __fixunssfdi = @import("compiler_rt/fixunssfdi.zig").__fixunssfdi;
341 const __fixunssfti = @import("compiler_rt/fixunssfti.zig").__fixunssfti;348 @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage });
342 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage });349 const __fixunssfti = @import("compiler_rt/fixunssfti.zig").__fixunssfti;
343350 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage });
344 const __fixunsdfsi = @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi;351
345 @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage });352 const __fixunsdfsi = @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi;
346 const __fixunsdfdi = @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi;353 @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage });
347 @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage });354 const __fixunsdfdi = @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi;
348 const __fixunsdfti = @import("compiler_rt/fixunsdfti.zig").__fixunsdfti;355 @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage });
349 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage });356 const __fixunsdfti = @import("compiler_rt/fixunsdfti.zig").__fixunsdfti;
350357 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage });
351 const __fixunstfsi = @import("compiler_rt/fixunstfsi.zig").__fixunstfsi;358
352 @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage });359 const __fixunstfsi = @import("compiler_rt/fixunstfsi.zig").__fixunstfsi;
353 const __fixunstfdi = @import("compiler_rt/fixunstfdi.zig").__fixunstfdi;360 @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage });
354 @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage });361 const __fixunstfdi = @import("compiler_rt/fixunstfdi.zig").__fixunstfdi;
355 const __fixunstfti = @import("compiler_rt/fixunstfti.zig").__fixunstfti;362 @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage });
356 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage });363 const __fixunstfti = @import("compiler_rt/fixunstfti.zig").__fixunstfti;
357364 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage });
358 const __fixdfdi = @import("compiler_rt/fixdfdi.zig").__fixdfdi;365
359 @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage });366 const __fixdfdi = @import("compiler_rt/fixdfdi.zig").__fixdfdi;
360 const __fixdfsi = @import("compiler_rt/fixdfsi.zig").__fixdfsi;367 @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage });
361 @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage });368 const __fixdfsi = @import("compiler_rt/fixdfsi.zig").__fixdfsi;
362 const __fixdfti = @import("compiler_rt/fixdfti.zig").__fixdfti;369 @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage });
363 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage });370 const __fixdfti = @import("compiler_rt/fixdfti.zig").__fixdfti;
364 const __fixsfdi = @import("compiler_rt/fixsfdi.zig").__fixsfdi;371 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage });
365 @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage });372 const __fixsfdi = @import("compiler_rt/fixsfdi.zig").__fixsfdi;
366 const __fixsfsi = @import("compiler_rt/fixsfsi.zig").__fixsfsi;373 @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage });
367 @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage });374 const __fixsfsi = @import("compiler_rt/fixsfsi.zig").__fixsfsi;
368 const __fixsfti = @import("compiler_rt/fixsfti.zig").__fixsfti;375 @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage });
369 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage });376 const __fixsfti = @import("compiler_rt/fixsfti.zig").__fixsfti;
370 const __fixtfdi = @import("compiler_rt/fixtfdi.zig").__fixtfdi;377 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage });
371 @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage });378 const __fixtfdi = @import("compiler_rt/fixtfdi.zig").__fixtfdi;
372 const __fixtfsi = @import("compiler_rt/fixtfsi.zig").__fixtfsi;379 @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage });
373 @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage });380 const __fixtfsi = @import("compiler_rt/fixtfsi.zig").__fixtfsi;
374 const __fixtfti = @import("compiler_rt/fixtfti.zig").__fixtfti;381 @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage });
375 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage });382 const __fixtfti = @import("compiler_rt/fixtfti.zig").__fixtfti;
376383 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage });
377 const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4;384
378 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });385 const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4;
379386 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });
380 if (is_darwin) {387
381 const __isPlatformVersionAtLeast = @import("compiler_rt/os_version_check.zig").__isPlatformVersionAtLeast;388 if (is_darwin) {
382 @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage });389 const __isPlatformVersionAtLeast = @import("compiler_rt/os_version_check.zig").__isPlatformVersionAtLeast;
383 }390 @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage });
391 }
384392
385 // Integral arithmetic393 // Integral arithmetic
386 const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2;394 const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2;
387 @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage });395 @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage });
388 const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2;396 const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2;
389 @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage });397 @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage });
390 const __negti2 = @import("compiler_rt/negXi2.zig").__negti2;398 const __negti2 = @import("compiler_rt/negXi2.zig").__negti2;
391 @export(__negti2, .{ .name = "__negti2", .linkage = linkage });399 @export(__negti2, .{ .name = "__negti2", .linkage = linkage });
392 const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3;400 const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3;
393 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });401 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
394 const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3;402 const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3;
395 @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage });403 @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage });
396 const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4;404 const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4;
397 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });405 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });
398 const __divsi3 = @import("compiler_rt/int.zig").__divsi3;406 const __divsi3 = @import("compiler_rt/int.zig").__divsi3;
399 @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage });407 @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage });
400 const __divdi3 = @import("compiler_rt/int.zig").__divdi3;408 const __divdi3 = @import("compiler_rt/int.zig").__divdi3;
401 @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage });409 @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage });
402 const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3;410 const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3;
403 @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage });411 @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage });
404 const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3;412 const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3;
405 @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage });413 @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage });
406 const __modsi3 = @import("compiler_rt/int.zig").__modsi3;414 const __modsi3 = @import("compiler_rt/int.zig").__modsi3;
407 @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage });415 @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage });
408 const __moddi3 = @import("compiler_rt/int.zig").__moddi3;416 const __moddi3 = @import("compiler_rt/int.zig").__moddi3;
409 @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage });417 @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage });
410 const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3;418 const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3;
411 @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage });419 @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage });
412 const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3;420 const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3;
413 @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage });421 @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage });
414 const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4;422 const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4;
415 @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage });423 @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage });
416 const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4;424 const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4;
417 @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage });425 @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage });
418426
419 // Integral arithmetic with trapping overflow427 // Integral arithmetic with trapping overflow
420 const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2;428 const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2;
421 @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage });429 @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage });
422 const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2;430 const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2;
423 @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage });431 @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage });
424 const __absvti2 = @import("compiler_rt/absv.zig").__absvti2;432 const __absvti2 = @import("compiler_rt/absv.zig").__absvti2;
425 @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage });433 @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage });
426 const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2;434 const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2;
427 @export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage });435 @export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage });
428 const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2;436 const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2;
429 @export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage });437 @export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage });
430 const __negvti2 = @import("compiler_rt/negv.zig").__negvti2;438 const __negvti2 = @import("compiler_rt/negv.zig").__negvti2;
431 @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage });439 @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage });
432440
433 // missing: Integral arithmetic which returns if overflow441 // missing: Integral arithmetic which returns if overflow
434442
435 // Integral comparison443 // Integral comparison
436 // (a < b) => 0444 // (a < b) => 0
437 // (a == b) => 1445 // (a == b) => 1
438 // (a > b) => 2446 // (a > b) => 2
439 const __cmpsi2 = @import("compiler_rt/cmp.zig").__cmpsi2;447 const __cmpsi2 = @import("compiler_rt/cmp.zig").__cmpsi2;
440 @export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = linkage });448 @export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = linkage });
441 const __cmpdi2 = @import("compiler_rt/cmp.zig").__cmpdi2;449 const __cmpdi2 = @import("compiler_rt/cmp.zig").__cmpdi2;
442 @export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = linkage });450 @export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = linkage });
443 const __cmpti2 = @import("compiler_rt/cmp.zig").__cmpti2;451 const __cmpti2 = @import("compiler_rt/cmp.zig").__cmpti2;
444 @export(__cmpti2, .{ .name = "__cmpti2", .linkage = linkage });452 @export(__cmpti2, .{ .name = "__cmpti2", .linkage = linkage });
445 const __ucmpsi2 = @import("compiler_rt/cmp.zig").__ucmpsi2;453 const __ucmpsi2 = @import("compiler_rt/cmp.zig").__ucmpsi2;
446 @export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = linkage });454 @export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = linkage });
447 const __ucmpdi2 = @import("compiler_rt/cmp.zig").__ucmpdi2;455 const __ucmpdi2 = @import("compiler_rt/cmp.zig").__ucmpdi2;
448 @export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = linkage });456 @export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = linkage });
449 const __ucmpti2 = @import("compiler_rt/cmp.zig").__ucmpti2;457 const __ucmpti2 = @import("compiler_rt/cmp.zig").__ucmpti2;
450 @export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = linkage });458 @export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = linkage });
451459
452 // missing: Floating point raised to integer power460 // missing: Floating point raised to integer power
453461
454 // missing: Complex arithmetic462 // missing: Complex arithmetic
455 // (a + ib) * (c + id)463 // (a + ib) * (c + id)
456 // (a + ib) / (c + id)464 // (a + ib) / (c + id)
457465
458 const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2;466 const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2;
459 @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage });467 @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage });
460 const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2;468 const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2;
461 @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage });469 @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage });
462470
463 if (builtin.link_libc and os_tag == .openbsd) {471 if (builtin.link_libc and os_tag == .openbsd) {
464 const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address;472 const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address;
465 @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage });473 @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage });
466 }474 }
467475
468 if ((arch.isARM() or arch.isThumb()) and !is_test) {476 if ((arch.isARM() or arch.isThumb()) and !is_test) {
469 const __aeabi_unwind_cpp_pr0 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0;477 const __aeabi_unwind_cpp_pr0 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0;
470 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage });478 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage });
471 const __aeabi_unwind_cpp_pr1 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1;479 const __aeabi_unwind_cpp_pr1 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1;
472 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage });480 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage });
473 const __aeabi_unwind_cpp_pr2 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2;481 const __aeabi_unwind_cpp_pr2 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2;
474 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage });482 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage });
475483
476 @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage });484 @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage });
477485
478 const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod;486 const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod;
479 @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage });487 @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage });
480 const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod;488 const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod;
481 @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage });489 @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage });
482490
483 @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage });491 @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage });
484 const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod;492 const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod;
485 @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage });493 @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage });
486 @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage });494 @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage });
487 const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod;495 const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod;
488 @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage });496 @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage });
489497
490 const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy;498 const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy;
491 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage });499 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage });
492 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage });500 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage });
493 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage });501 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage });
494502
495 const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove;503 const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove;
496 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage });504 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage });
497 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage });505 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage });
498 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage });506 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage });
499507
500 const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset;508 const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset;
501 @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage });509 @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage });
502 @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage });510 @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage });
503 @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage });511 @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage });
504512
505 const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr;513 const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr;
506 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage });514 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage });
507 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });515 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });
508 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });516 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });
509517
510 if (os_tag == .linux) {518 if (os_tag == .linux) {
511 const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp;519 const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp;
512 @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });520 @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });
513 }
514
515 const __aeabi_f2d = @import("compiler_rt/extendXfYf2.zig").__aeabi_f2d;
516 @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage });
517 const __aeabi_i2d = @import("compiler_rt/floatsiXf.zig").__aeabi_i2d;
518 @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage });
519 const __aeabi_l2d = @import("compiler_rt/floatdidf.zig").__aeabi_l2d;
520 @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage });
521 const __aeabi_l2f = @import("compiler_rt/floatXisf.zig").__aeabi_l2f;
522 @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage });
523 const __aeabi_ui2d = @import("compiler_rt/floatunsidf.zig").__aeabi_ui2d;
524 @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage });
525 const __aeabi_ul2d = @import("compiler_rt/floatundidf.zig").__aeabi_ul2d;
526 @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = linkage });
527 const __aeabi_ui2f = @import("compiler_rt/floatunsisf.zig").__aeabi_ui2f;
528 @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = linkage });
529 const __aeabi_ul2f = @import("compiler_rt/floatundisf.zig").__aeabi_ul2f;
530 @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = linkage });
531
532 const __aeabi_fneg = @import("compiler_rt/negXf2.zig").__aeabi_fneg;
533 @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = linkage });
534 const __aeabi_dneg = @import("compiler_rt/negXf2.zig").__aeabi_dneg;
535 @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = linkage });
536
537 const __aeabi_fmul = @import("compiler_rt/mulXf3.zig").__aeabi_fmul;
538 @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = linkage });
539 const __aeabi_dmul = @import("compiler_rt/mulXf3.zig").__aeabi_dmul;
540 @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = linkage });
541
542 const __aeabi_d2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2h;
543 @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = linkage });
544
545 const __aeabi_f2ulz = @import("compiler_rt/fixunssfdi.zig").__aeabi_f2ulz;
546 @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = linkage });
547 const __aeabi_d2ulz = @import("compiler_rt/fixunsdfdi.zig").__aeabi_d2ulz;
548 @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = linkage });
549
550 const __aeabi_f2lz = @import("compiler_rt/fixsfdi.zig").__aeabi_f2lz;
551 @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = linkage });
552 const __aeabi_d2lz = @import("compiler_rt/fixdfdi.zig").__aeabi_d2lz;
553 @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = linkage });
554
555 const __aeabi_d2uiz = @import("compiler_rt/fixunsdfsi.zig").__aeabi_d2uiz;
556 @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = linkage });
557
558 const __aeabi_h2f = @import("compiler_rt/extendXfYf2.zig").__aeabi_h2f;
559 @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = linkage });
560 const __aeabi_f2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_f2h;
561 @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = linkage });
562
563 const __aeabi_i2f = @import("compiler_rt/floatsiXf.zig").__aeabi_i2f;
564 @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = linkage });
565 const __aeabi_d2f = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2f;
566 @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = linkage });
567
568 const __aeabi_fadd = @import("compiler_rt/addXf3.zig").__aeabi_fadd;
569 @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = linkage });
570 const __aeabi_dadd = @import("compiler_rt/addXf3.zig").__aeabi_dadd;
571 @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = linkage });
572 const __aeabi_fsub = @import("compiler_rt/addXf3.zig").__aeabi_fsub;
573 @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = linkage });
574 const __aeabi_dsub = @import("compiler_rt/addXf3.zig").__aeabi_dsub;
575 @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = linkage });
576
577 const __aeabi_f2uiz = @import("compiler_rt/fixunssfsi.zig").__aeabi_f2uiz;
578 @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = linkage });
579
580 const __aeabi_f2iz = @import("compiler_rt/fixsfsi.zig").__aeabi_f2iz;
581 @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = linkage });
582 const __aeabi_d2iz = @import("compiler_rt/fixdfsi.zig").__aeabi_d2iz;
583 @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = linkage });
584
585 const __aeabi_fdiv = @import("compiler_rt/divsf3.zig").__aeabi_fdiv;
586 @export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage });
587 const __aeabi_ddiv = @import("compiler_rt/divdf3.zig").__aeabi_ddiv;
588 @export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage });
589
590 const __aeabi_llsl = @import("compiler_rt/shift.zig").__aeabi_llsl;
591 @export(__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage });
592 const __aeabi_lasr = @import("compiler_rt/shift.zig").__aeabi_lasr;
593 @export(__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage });
594 const __aeabi_llsr = @import("compiler_rt/shift.zig").__aeabi_llsr;
595 @export(__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage });
596
597 const __aeabi_fcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq;
598 @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
599 const __aeabi_fcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmplt;
600 @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
601 const __aeabi_fcmple = @import("compiler_rt/compareXf2.zig").__aeabi_fcmple;
602 @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
603 const __aeabi_fcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpge;
604 @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage });
605 const __aeabi_fcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt;
606 @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage });
607 const __aeabi_fcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpun;
608 @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage });
609
610 const __aeabi_dcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq;
611 @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage });
612 const __aeabi_dcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmplt;
613 @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage });
614 const __aeabi_dcmple = @import("compiler_rt/compareXf2.zig").__aeabi_dcmple;
615 @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage });
616 const __aeabi_dcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpge;
617 @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage });
618 const __aeabi_dcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt;
619 @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage });
620 const __aeabi_dcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpun;
621 @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });
622 }521 }
623522
624 if (arch == .i386 and abi == .msvc) {523 const __aeabi_f2d = @import("compiler_rt/extendXfYf2.zig").__aeabi_f2d;
625 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins524 @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage });
626 const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv;525 const __aeabi_i2d = @import("compiler_rt/floatsiXf.zig").__aeabi_i2d;
627 @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });526 @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage });
628 const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv;527 const __aeabi_l2d = @import("compiler_rt/floatdidf.zig").__aeabi_l2d;
629 @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });528 @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage });
630 const _allrem = @import("compiler_rt/aullrem.zig")._allrem;529 const __aeabi_l2f = @import("compiler_rt/floatXisf.zig").__aeabi_l2f;
631 @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage });530 @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage });
632 const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem;531 const __aeabi_ui2d = @import("compiler_rt/floatunsidf.zig").__aeabi_ui2d;
633 @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });532 @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage });
634 }533 const __aeabi_ul2d = @import("compiler_rt/floatundidf.zig").__aeabi_ul2d;
534 @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = linkage });
535 const __aeabi_ui2f = @import("compiler_rt/floatunsisf.zig").__aeabi_ui2f;
536 @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = linkage });
537 const __aeabi_ul2f = @import("compiler_rt/floatundisf.zig").__aeabi_ul2f;
538 @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = linkage });
539
540 const __aeabi_fneg = @import("compiler_rt/negXf2.zig").__aeabi_fneg;
541 @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = linkage });
542 const __aeabi_dneg = @import("compiler_rt/negXf2.zig").__aeabi_dneg;
543 @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = linkage });
544
545 const __aeabi_fmul = @import("compiler_rt/mulXf3.zig").__aeabi_fmul;
546 @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = linkage });
547 const __aeabi_dmul = @import("compiler_rt/mulXf3.zig").__aeabi_dmul;
548 @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = linkage });
549
550 const __aeabi_d2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2h;
551 @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = linkage });
552
553 const __aeabi_f2ulz = @import("compiler_rt/fixunssfdi.zig").__aeabi_f2ulz;
554 @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = linkage });
555 const __aeabi_d2ulz = @import("compiler_rt/fixunsdfdi.zig").__aeabi_d2ulz;
556 @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = linkage });
557
558 const __aeabi_f2lz = @import("compiler_rt/fixsfdi.zig").__aeabi_f2lz;
559 @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = linkage });
560 const __aeabi_d2lz = @import("compiler_rt/fixdfdi.zig").__aeabi_d2lz;
561 @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = linkage });
562
563 const __aeabi_d2uiz = @import("compiler_rt/fixunsdfsi.zig").__aeabi_d2uiz;
564 @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = linkage });
565
566 const __aeabi_h2f = @import("compiler_rt/extendXfYf2.zig").__aeabi_h2f;
567 @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = linkage });
568 const __aeabi_f2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_f2h;
569 @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = linkage });
570
571 const __aeabi_i2f = @import("compiler_rt/floatsiXf.zig").__aeabi_i2f;
572 @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = linkage });
573 const __aeabi_d2f = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2f;
574 @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = linkage });
575
576 const __aeabi_fadd = @import("compiler_rt/addXf3.zig").__aeabi_fadd;
577 @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = linkage });
578 const __aeabi_dadd = @import("compiler_rt/addXf3.zig").__aeabi_dadd;
579 @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = linkage });
580 const __aeabi_fsub = @import("compiler_rt/addXf3.zig").__aeabi_fsub;
581 @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = linkage });
582 const __aeabi_dsub = @import("compiler_rt/addXf3.zig").__aeabi_dsub;
583 @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = linkage });
584
585 const __aeabi_f2uiz = @import("compiler_rt/fixunssfsi.zig").__aeabi_f2uiz;
586 @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = linkage });
587
588 const __aeabi_f2iz = @import("compiler_rt/fixsfsi.zig").__aeabi_f2iz;
589 @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = linkage });
590 const __aeabi_d2iz = @import("compiler_rt/fixdfsi.zig").__aeabi_d2iz;
591 @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = linkage });
592
593 const __aeabi_fdiv = @import("compiler_rt/divsf3.zig").__aeabi_fdiv;
594 @export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage });
595 const __aeabi_ddiv = @import("compiler_rt/divdf3.zig").__aeabi_ddiv;
596 @export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage });
597
598 const __aeabi_llsl = @import("compiler_rt/shift.zig").__aeabi_llsl;
599 @export(__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage });
600 const __aeabi_lasr = @import("compiler_rt/shift.zig").__aeabi_lasr;
601 @export(__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage });
602 const __aeabi_llsr = @import("compiler_rt/shift.zig").__aeabi_llsr;
603 @export(__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage });
604
605 const __aeabi_fcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq;
606 @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
607 const __aeabi_fcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmplt;
608 @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
609 const __aeabi_fcmple = @import("compiler_rt/compareXf2.zig").__aeabi_fcmple;
610 @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
611 const __aeabi_fcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpge;
612 @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage });
613 const __aeabi_fcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt;
614 @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage });
615 const __aeabi_fcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpun;
616 @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage });
617
618 const __aeabi_dcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq;
619 @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage });
620 const __aeabi_dcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmplt;
621 @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage });
622 const __aeabi_dcmple = @import("compiler_rt/compareXf2.zig").__aeabi_dcmple;
623 @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage });
624 const __aeabi_dcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpge;
625 @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage });
626 const __aeabi_dcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt;
627 @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage });
628 const __aeabi_dcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpun;
629 @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });
630 }
635631
636 if (arch.isSPARC()) {632 if (arch == .i386 and abi == .msvc) {
637 // SPARC systems use a different naming scheme633 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins
638 const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add;634 const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv;
639 @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage });635 @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });
640 const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div;636 const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv;
641 @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage });637 @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });
642 const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul;638 const _allrem = @import("compiler_rt/aullrem.zig")._allrem;
643 @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage });639 @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage });
644 const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub;640 const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem;
645 @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage });641 @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
646642 }
647 const _Qp_cmp = @import("compiler_rt/sparc.zig")._Qp_cmp;
648 @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = linkage });
649 const _Qp_feq = @import("compiler_rt/sparc.zig")._Qp_feq;
650 @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = linkage });
651 const _Qp_fne = @import("compiler_rt/sparc.zig")._Qp_fne;
652 @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = linkage });
653 const _Qp_flt = @import("compiler_rt/sparc.zig")._Qp_flt;
654 @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = linkage });
655 const _Qp_fle = @import("compiler_rt/sparc.zig")._Qp_fle;
656 @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = linkage });
657 const _Qp_fgt = @import("compiler_rt/sparc.zig")._Qp_fgt;
658 @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage });
659 const _Qp_fge = @import("compiler_rt/sparc.zig")._Qp_fge;
660 @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage });
661
662 const _Qp_itoq = @import("compiler_rt/sparc.zig")._Qp_itoq;
663 @export(_Qp_itoq, .{ .name = "_Qp_itoq", .linkage = linkage });
664 const _Qp_uitoq = @import("compiler_rt/sparc.zig")._Qp_uitoq;
665 @export(_Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = linkage });
666 const _Qp_xtoq = @import("compiler_rt/sparc.zig")._Qp_xtoq;
667 @export(_Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = linkage });
668 const _Qp_uxtoq = @import("compiler_rt/sparc.zig")._Qp_uxtoq;
669 @export(_Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = linkage });
670 const _Qp_stoq = @import("compiler_rt/sparc.zig")._Qp_stoq;
671 @export(_Qp_stoq, .{ .name = "_Qp_stoq", .linkage = linkage });
672 const _Qp_dtoq = @import("compiler_rt/sparc.zig")._Qp_dtoq;
673 @export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage });
674 const _Qp_qtoi = @import("compiler_rt/sparc.zig")._Qp_qtoi;
675 @export(_Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = linkage });
676 const _Qp_qtoui = @import("compiler_rt/sparc.zig")._Qp_qtoui;
677 @export(_Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = linkage });
678 const _Qp_qtox = @import("compiler_rt/sparc.zig")._Qp_qtox;
679 @export(_Qp_qtox, .{ .name = "_Qp_qtox", .linkage = linkage });
680 const _Qp_qtoux = @import("compiler_rt/sparc.zig")._Qp_qtoux;
681 @export(_Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = linkage });
682 const _Qp_qtos = @import("compiler_rt/sparc.zig")._Qp_qtos;
683 @export(_Qp_qtos, .{ .name = "_Qp_qtos", .linkage = linkage });
684 const _Qp_qtod = @import("compiler_rt/sparc.zig")._Qp_qtod;
685 @export(_Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });
686 }
687643
688 if ((arch == .powerpc or arch.isPPC64()) and !is_test) {644 if (arch.isSPARC()) {
689 @export(__addtf3, .{ .name = "__addkf3", .linkage = linkage });645 // SPARC systems use a different naming scheme
690 @export(__subtf3, .{ .name = "__subkf3", .linkage = linkage });646 const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add;
691 @export(__multf3, .{ .name = "__mulkf3", .linkage = linkage });647 @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage });
692 @export(__divtf3, .{ .name = "__divkf3", .linkage = linkage });648 const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div;
693 @export(__extendsftf2, .{ .name = "__extendsfkf2", .linkage = linkage });649 @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage });
694 @export(__extenddftf2, .{ .name = "__extenddfkf2", .linkage = linkage });650 const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul;
695 @export(__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = linkage });651 @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage });
696 @export(__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = linkage });652 const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub;
697 @export(__fixtfdi, .{ .name = "__fixkfdi", .linkage = linkage });653 @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage });
698 @export(__fixtfsi, .{ .name = "__fixkfsi", .linkage = linkage });654
699 @export(__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = linkage });655 const _Qp_cmp = @import("compiler_rt/sparc.zig")._Qp_cmp;
700 @export(__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = linkage });656 @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = linkage });
701 @export(__floatsitf, .{ .name = "__floatsikf", .linkage = linkage });657 const _Qp_feq = @import("compiler_rt/sparc.zig")._Qp_feq;
702 @export(__floatditf, .{ .name = "__floatdikf", .linkage = linkage });658 @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = linkage });
703 @export(__floatunditf, .{ .name = "__floatundikf", .linkage = linkage });659 const _Qp_fne = @import("compiler_rt/sparc.zig")._Qp_fne;
704 @export(__floatunsitf, .{ .name = "__floatunsikf", .linkage = linkage });660 @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = linkage });
705661 const _Qp_flt = @import("compiler_rt/sparc.zig")._Qp_flt;
706 @export(__letf2, .{ .name = "__eqkf2", .linkage = linkage });662 @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = linkage });
707 @export(__letf2, .{ .name = "__nekf2", .linkage = linkage });663 const _Qp_fle = @import("compiler_rt/sparc.zig")._Qp_fle;
708 @export(__getf2, .{ .name = "__gekf2", .linkage = linkage });664 @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = linkage });
709 @export(__letf2, .{ .name = "__ltkf2", .linkage = linkage });665 const _Qp_fgt = @import("compiler_rt/sparc.zig")._Qp_fgt;
710 @export(__letf2, .{ .name = "__lekf2", .linkage = linkage });666 @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage });
711 @export(__getf2, .{ .name = "__gtkf2", .linkage = linkage });667 const _Qp_fge = @import("compiler_rt/sparc.zig")._Qp_fge;
712 @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage });668 @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage });
713 }669
670 const _Qp_itoq = @import("compiler_rt/sparc.zig")._Qp_itoq;
671 @export(_Qp_itoq, .{ .name = "_Qp_itoq", .linkage = linkage });
672 const _Qp_uitoq = @import("compiler_rt/sparc.zig")._Qp_uitoq;
673 @export(_Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = linkage });
674 const _Qp_xtoq = @import("compiler_rt/sparc.zig")._Qp_xtoq;
675 @export(_Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = linkage });
676 const _Qp_uxtoq = @import("compiler_rt/sparc.zig")._Qp_uxtoq;
677 @export(_Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = linkage });
678 const _Qp_stoq = @import("compiler_rt/sparc.zig")._Qp_stoq;
679 @export(_Qp_stoq, .{ .name = "_Qp_stoq", .linkage = linkage });
680 const _Qp_dtoq = @import("compiler_rt/sparc.zig")._Qp_dtoq;
681 @export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage });
682 const _Qp_qtoi = @import("compiler_rt/sparc.zig")._Qp_qtoi;
683 @export(_Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = linkage });
684 const _Qp_qtoui = @import("compiler_rt/sparc.zig")._Qp_qtoui;
685 @export(_Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = linkage });
686 const _Qp_qtox = @import("compiler_rt/sparc.zig")._Qp_qtox;
687 @export(_Qp_qtox, .{ .name = "_Qp_qtox", .linkage = linkage });
688 const _Qp_qtoux = @import("compiler_rt/sparc.zig")._Qp_qtoux;
689 @export(_Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = linkage });
690 const _Qp_qtos = @import("compiler_rt/sparc.zig")._Qp_qtos;
691 @export(_Qp_qtos, .{ .name = "_Qp_qtos", .linkage = linkage });
692 const _Qp_qtod = @import("compiler_rt/sparc.zig")._Qp_qtod;
693 @export(_Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });
694 }
714695
715 _ = @import("compiler_rt/atomics.zig");696 if ((arch == .powerpc or arch.isPPC64()) and !is_test) {
697 @export(__addtf3, .{ .name = "__addkf3", .linkage = linkage });
698 @export(__subtf3, .{ .name = "__subkf3", .linkage = linkage });
699 @export(__multf3, .{ .name = "__mulkf3", .linkage = linkage });
700 @export(__divtf3, .{ .name = "__divkf3", .linkage = linkage });
701 @export(__extendsftf2, .{ .name = "__extendsfkf2", .linkage = linkage });
702 @export(__extenddftf2, .{ .name = "__extenddfkf2", .linkage = linkage });
703 @export(__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = linkage });
704 @export(__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = linkage });
705 @export(__fixtfdi, .{ .name = "__fixkfdi", .linkage = linkage });
706 @export(__fixtfsi, .{ .name = "__fixkfsi", .linkage = linkage });
707 @export(__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = linkage });
708 @export(__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = linkage });
709 @export(__floatsitf, .{ .name = "__floatsikf", .linkage = linkage });
710 @export(__floatditf, .{ .name = "__floatdikf", .linkage = linkage });
711 @export(__floatunditf, .{ .name = "__floatundikf", .linkage = linkage });
712 @export(__floatunsitf, .{ .name = "__floatunsikf", .linkage = linkage });
713
714 @export(__letf2, .{ .name = "__eqkf2", .linkage = linkage });
715 @export(__letf2, .{ .name = "__nekf2", .linkage = linkage });
716 @export(__getf2, .{ .name = "__gekf2", .linkage = linkage });
717 @export(__letf2, .{ .name = "__ltkf2", .linkage = linkage });
718 @export(__letf2, .{ .name = "__lekf2", .linkage = linkage });
719 @export(__getf2, .{ .name = "__gtkf2", .linkage = linkage });
720 @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage });
721 }
722
723 @export(floorf, .{ .name = "floorf", .linkage = linkage });
724 @export(floor, .{ .name = "floor", .linkage = linkage });
725 @export(floorl, .{ .name = "floorl", .linkage = linkage });
716726
727 if (!builtin.zig_is_stage2) {
717 @export(fmaq, .{ .name = "fmaq", .linkage = linkage });728 @export(fmaq, .{ .name = "fmaq", .linkage = linkage });
718 @export(floorf, .{ .name = "floorf", .linkage = linkage });
719 @export(floor, .{ .name = "floor", .linkage = linkage });
720 @export(floorl, .{ .name = "floorl", .linkage = linkage });
721 }729 }
722}730}
723731
lib/std/special/compiler_rt/absv.zig+29-24
...@@ -2,31 +2,36 @@...@@ -2,31 +2,36 @@
2// * @panic, if value can not be represented2// * @panic, if value can not be represented
3// - absvXi4_generic for unoptimized version3// - absvXi4_generic for unoptimized version
44
5fn absvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST {5inline fn absvXi(comptime ST: type, a: ST) ST {
6 return struct {6 const UT = switch (ST) {
7 fn f(a: ST) callconv(.C) ST {7 i32 => u32,
8 const UT = switch (ST) {8 i64 => u64,
9 i32 => u32,9 i128 => u128,
10 i64 => u64,10 else => unreachable,
11 i128 => u128,11 };
12 else => unreachable,12 // taken from Bit Twiddling Hacks
13 };13 // compute the integer absolute value (abs) without branching
14 // taken from Bit Twiddling Hacks14 var x: ST = a;
15 // compute the integer absolute value (abs) without branching15 const N: UT = @bitSizeOf(ST);
16 var x: ST = a;16 const sign: ST = a >> N - 1;
17 const N: UT = @bitSizeOf(ST);17 x +%= sign;
18 const sign: ST = a >> N - 1;18 x ^= sign;
19 x +%= sign;19 if (x < 0)
20 x ^= sign;20 @panic("compiler_rt absv: overflow");
21 if (x < 0)21 return x;
22 @panic("compiler_rt absv: overflow");22}
23 return x;23
24 }24pub fn __absvsi2(a: i32) callconv(.C) i32 {
25 }.f;25 return absvXi(i32, a);
26}
27
28pub fn __absvdi2(a: i64) callconv(.C) i64 {
29 return absvXi(i64, a);
30}
31
32pub fn __absvti2(a: i128) callconv(.C) i128 {
33 return absvXi(i128, a);
26}34}
27pub const __absvsi2 = absvXi_generic(i32);
28pub const __absvdi2 = absvXi_generic(i64);
29pub const __absvti2 = absvXi_generic(i128);
3035
31test {36test {
32 _ = @import("absvsi2_test.zig");37 _ = @import("absvsi2_test.zig");
lib/std/special/compiler_rt/atomics.zig+277-191
...@@ -119,225 +119,311 @@ fn __atomic_compare_exchange(...@@ -119,225 +119,311 @@ fn __atomic_compare_exchange(
119 return 0;119 return 0;
120}120}
121121
122comptime {
123 if (supports_atomic_ops) {
124 @export(__atomic_load, .{ .name = "__atomic_load", .linkage = linkage });
125 @export(__atomic_store, .{ .name = "__atomic_store", .linkage = linkage });
126 @export(__atomic_exchange, .{ .name = "__atomic_exchange", .linkage = linkage });
127 @export(__atomic_compare_exchange, .{ .name = "__atomic_compare_exchange", .linkage = linkage });
128 }
129}
130
131// Specialized versions of the GCC atomic builtin functions.122// Specialized versions of the GCC atomic builtin functions.
132// LLVM emits those iff the object size is known and the pointers are correctly123// LLVM emits those iff the object size is known and the pointers are correctly
133// aligned.124// aligned.
125inline fn atomic_load_N(comptime T: type, src: *T, model: i32) T {
126 _ = model;
127 if (@sizeOf(T) > largest_atomic_size) {
128 var sl = spinlocks.get(@ptrToInt(src));
129 defer sl.release();
130 return src.*;
131 } else {
132 return @atomicLoad(T, src, .SeqCst);
133 }
134}
134135
135fn atomicLoadFn(comptime T: type) fn (*T, i32) callconv(.C) T {136fn __atomic_load_1(src: *u8, model: i32) callconv(.C) u8 {
136 return struct {137 return atomic_load_N(u8, src, model);
137 fn atomic_load_N(src: *T, model: i32) callconv(.C) T {
138 _ = model;
139 if (@sizeOf(T) > largest_atomic_size) {
140 var sl = spinlocks.get(@ptrToInt(src));
141 defer sl.release();
142 return src.*;
143 } else {
144 return @atomicLoad(T, src, .SeqCst);
145 }
146 }
147 }.atomic_load_N;
148}138}
149139
150comptime {140fn __atomic_load_2(src: *u16, model: i32) callconv(.C) u16 {
151 if (supports_atomic_ops) {141 return atomic_load_N(u16, src, model);
152 const atomicLoad_u8 = atomicLoadFn(u8);
153 const atomicLoad_u16 = atomicLoadFn(u16);
154 const atomicLoad_u32 = atomicLoadFn(u32);
155 const atomicLoad_u64 = atomicLoadFn(u64);
156 @export(atomicLoad_u8, .{ .name = "__atomic_load_1", .linkage = linkage });
157 @export(atomicLoad_u16, .{ .name = "__atomic_load_2", .linkage = linkage });
158 @export(atomicLoad_u32, .{ .name = "__atomic_load_4", .linkage = linkage });
159 @export(atomicLoad_u64, .{ .name = "__atomic_load_8", .linkage = linkage });
160 }
161}142}
162143
163fn atomicStoreFn(comptime T: type) fn (*T, T, i32) callconv(.C) void {144fn __atomic_load_4(src: *u32, model: i32) callconv(.C) u32 {
164 return struct {145 return atomic_load_N(u32, src, model);
165 fn atomic_store_N(dst: *T, value: T, model: i32) callconv(.C) void {
166 _ = model;
167 if (@sizeOf(T) > largest_atomic_size) {
168 var sl = spinlocks.get(@ptrToInt(dst));
169 defer sl.release();
170 dst.* = value;
171 } else {
172 @atomicStore(T, dst, value, .SeqCst);
173 }
174 }
175 }.atomic_store_N;
176}146}
177147
178comptime {148fn __atomic_load_8(src: *u64, model: i32) callconv(.C) u64 {
179 if (supports_atomic_ops) {149 return atomic_load_N(u64, src, model);
180 const atomicStore_u8 = atomicStoreFn(u8);150}
181 const atomicStore_u16 = atomicStoreFn(u16);151
182 const atomicStore_u32 = atomicStoreFn(u32);152inline fn atomic_store_N(comptime T: type, dst: *T, value: T, model: i32) void {
183 const atomicStore_u64 = atomicStoreFn(u64);153 _ = model;
184 @export(atomicStore_u8, .{ .name = "__atomic_store_1", .linkage = linkage });154 if (@sizeOf(T) > largest_atomic_size) {
185 @export(atomicStore_u16, .{ .name = "__atomic_store_2", .linkage = linkage });155 var sl = spinlocks.get(@ptrToInt(dst));
186 @export(atomicStore_u32, .{ .name = "__atomic_store_4", .linkage = linkage });156 defer sl.release();
187 @export(atomicStore_u64, .{ .name = "__atomic_store_8", .linkage = linkage });157 dst.* = value;
158 } else {
159 @atomicStore(T, dst, value, .SeqCst);
188 }160 }
189}161}
190162
191fn atomicExchangeFn(comptime T: type) fn (*T, T, i32) callconv(.C) T {163fn __atomic_store_1(dst: *u8, value: u8, model: i32) callconv(.C) void {
192 return struct {164 return atomic_store_N(u8, dst, value, model);
193 fn atomic_exchange_N(ptr: *T, val: T, model: i32) callconv(.C) T {
194 _ = model;
195 if (@sizeOf(T) > largest_atomic_size) {
196 var sl = spinlocks.get(@ptrToInt(ptr));
197 defer sl.release();
198 const value = ptr.*;
199 ptr.* = val;
200 return value;
201 } else {
202 return @atomicRmw(T, ptr, .Xchg, val, .SeqCst);
203 }
204 }
205 }.atomic_exchange_N;
206}165}
207166
208comptime {167fn __atomic_store_2(dst: *u16, value: u16, model: i32) callconv(.C) void {
209 if (supports_atomic_ops) {168 return atomic_store_N(u16, dst, value, model);
210 const atomicExchange_u8 = atomicExchangeFn(u8);169}
211 const atomicExchange_u16 = atomicExchangeFn(u16);170
212 const atomicExchange_u32 = atomicExchangeFn(u32);171fn __atomic_store_4(dst: *u32, value: u32, model: i32) callconv(.C) void {
213 const atomicExchange_u64 = atomicExchangeFn(u64);172 return atomic_store_N(u32, dst, value, model);
214 @export(atomicExchange_u8, .{ .name = "__atomic_exchange_1", .linkage = linkage });173}
215 @export(atomicExchange_u16, .{ .name = "__atomic_exchange_2", .linkage = linkage });174
216 @export(atomicExchange_u32, .{ .name = "__atomic_exchange_4", .linkage = linkage });175fn __atomic_store_8(dst: *u64, value: u64, model: i32) callconv(.C) void {
217 @export(atomicExchange_u64, .{ .name = "__atomic_exchange_8", .linkage = linkage });176 return atomic_store_N(u64, dst, value, model);
177}
178
179inline fn atomic_exchange_N(comptime T: type, ptr: *T, val: T, model: i32) T {
180 _ = model;
181 if (@sizeOf(T) > largest_atomic_size) {
182 var sl = spinlocks.get(@ptrToInt(ptr));
183 defer sl.release();
184 const value = ptr.*;
185 ptr.* = val;
186 return value;
187 } else {
188 return @atomicRmw(T, ptr, .Xchg, val, .SeqCst);
218 }189 }
219}190}
220191
221fn atomicCompareExchangeFn(comptime T: type) fn (*T, *T, T, i32, i32) callconv(.C) i32 {192fn __atomic_exchange_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
222 return struct {193 return atomic_exchange_N(u8, ptr, val, model);
223 fn atomic_compare_exchange_N(ptr: *T, expected: *T, desired: T, success: i32, failure: i32) callconv(.C) i32 {194}
224 _ = success;195
225 _ = failure;196fn __atomic_exchange_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
226 if (@sizeOf(T) > largest_atomic_size) {197 return atomic_exchange_N(u16, ptr, val, model);
227 var sl = spinlocks.get(@ptrToInt(ptr));198}
228 defer sl.release();199
229 const value = ptr.*;200fn __atomic_exchange_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
230 if (value == expected.*) {201 return atomic_exchange_N(u32, ptr, val, model);
231 ptr.* = desired;202}
232 return 1;203
233 }204fn __atomic_exchange_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
234 expected.* = value;205 return atomic_exchange_N(u64, ptr, val, model);
235 return 0;206}
236 } else {207
237 if (@cmpxchgStrong(T, ptr, expected.*, desired, .SeqCst, .SeqCst)) |old_value| {208inline fn atomic_compare_exchange_N(
238 expected.* = old_value;209 comptime T: type,
239 return 0;210 ptr: *T,
240 }211 expected: *T,
241 return 1;212 desired: T,
242 }213 success: i32,
214 failure: i32,
215) i32 {
216 _ = success;
217 _ = failure;
218 if (@sizeOf(T) > largest_atomic_size) {
219 var sl = spinlocks.get(@ptrToInt(ptr));
220 defer sl.release();
221 const value = ptr.*;
222 if (value == expected.*) {
223 ptr.* = desired;
224 return 1;
243 }225 }
244 }.atomic_compare_exchange_N;226 expected.* = value;
227 return 0;
228 } else {
229 if (@cmpxchgStrong(T, ptr, expected.*, desired, .SeqCst, .SeqCst)) |old_value| {
230 expected.* = old_value;
231 return 0;
232 }
233 return 1;
234 }
245}235}
246236
247comptime {237fn __atomic_compare_exchange_1(ptr: *u8, expected: *u8, desired: u8, success: i32, failure: i32) callconv(.C) i32 {
248 if (supports_atomic_ops) {238 return atomic_compare_exchange_N(u8, ptr, expected, desired, success, failure);
249 const atomicCompareExchange_u8 = atomicCompareExchangeFn(u8);239}
250 const atomicCompareExchange_u16 = atomicCompareExchangeFn(u16);240
251 const atomicCompareExchange_u32 = atomicCompareExchangeFn(u32);241fn __atomic_compare_exchange_2(ptr: *u16, expected: *u16, desired: u16, success: i32, failure: i32) callconv(.C) i32 {
252 const atomicCompareExchange_u64 = atomicCompareExchangeFn(u64);242 return atomic_compare_exchange_N(u16, ptr, expected, desired, success, failure);
253 @export(atomicCompareExchange_u8, .{ .name = "__atomic_compare_exchange_1", .linkage = linkage });243}
254 @export(atomicCompareExchange_u16, .{ .name = "__atomic_compare_exchange_2", .linkage = linkage });244
255 @export(atomicCompareExchange_u32, .{ .name = "__atomic_compare_exchange_4", .linkage = linkage });245fn __atomic_compare_exchange_4(ptr: *u32, expected: *u32, desired: u32, success: i32, failure: i32) callconv(.C) i32 {
256 @export(atomicCompareExchange_u64, .{ .name = "__atomic_compare_exchange_8", .linkage = linkage });246 return atomic_compare_exchange_N(u32, ptr, expected, desired, success, failure);
247}
248
249fn __atomic_compare_exchange_8(ptr: *u64, expected: *u64, desired: u64, success: i32, failure: i32) callconv(.C) i32 {
250 return atomic_compare_exchange_N(u64, ptr, expected, desired, success, failure);
251}
252
253inline fn fetch_op_N(comptime T: type, comptime op: std.builtin.AtomicRmwOp, ptr: *T, val: T, model: i32) T {
254 _ = model;
255 if (@sizeOf(T) > largest_atomic_size) {
256 var sl = spinlocks.get(@ptrToInt(ptr));
257 defer sl.release();
258
259 const value = ptr.*;
260 ptr.* = switch (op) {
261 .Add => value +% val,
262 .Sub => value -% val,
263 .And => value & val,
264 .Nand => ~(value & val),
265 .Or => value | val,
266 .Xor => value ^ val,
267 else => @compileError("unsupported atomic op"),
268 };
269
270 return value;
257 }271 }
272
273 return @atomicRmw(T, ptr, op, val, .SeqCst);
258}274}
259275
260fn fetchFn(comptime T: type, comptime op: std.builtin.AtomicRmwOp) fn (*T, T, i32) callconv(.C) T {276fn __atomic_fetch_add_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
261 return struct {277 return fetch_op_N(u8, .Add, ptr, val, model);
262 pub fn fetch_op_N(ptr: *T, val: T, model: i32) callconv(.C) T {278}
263 _ = model;
264 if (@sizeOf(T) > largest_atomic_size) {
265 var sl = spinlocks.get(@ptrToInt(ptr));
266 defer sl.release();
267
268 const value = ptr.*;
269 ptr.* = switch (op) {
270 .Add => value +% val,
271 .Sub => value -% val,
272 .And => value & val,
273 .Nand => ~(value & val),
274 .Or => value | val,
275 .Xor => value ^ val,
276 else => @compileError("unsupported atomic op"),
277 };
278
279 return value;
280 }
281279
282 return @atomicRmw(T, ptr, op, val, .SeqCst);280fn __atomic_fetch_add_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
283 }281 return fetch_op_N(u16, .Add, ptr, val, model);
284 }.fetch_op_N;282}
283
284fn __atomic_fetch_add_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
285 return fetch_op_N(u32, .Add, ptr, val, model);
286}
287
288fn __atomic_fetch_add_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
289 return fetch_op_N(u64, .Add, ptr, val, model);
290}
291
292fn __atomic_fetch_sub_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
293 return fetch_op_N(u8, .Sub, ptr, val, model);
294}
295
296fn __atomic_fetch_sub_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
297 return fetch_op_N(u16, .Sub, ptr, val, model);
298}
299
300fn __atomic_fetch_sub_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
301 return fetch_op_N(u32, .Sub, ptr, val, model);
302}
303
304fn __atomic_fetch_sub_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
305 return fetch_op_N(u64, .Sub, ptr, val, model);
306}
307
308fn __atomic_fetch_and_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
309 return fetch_op_N(u8, .And, ptr, val, model);
310}
311
312fn __atomic_fetch_and_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
313 return fetch_op_N(u16, .And, ptr, val, model);
314}
315
316fn __atomic_fetch_and_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
317 return fetch_op_N(u32, .And, ptr, val, model);
318}
319
320fn __atomic_fetch_and_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
321 return fetch_op_N(u64, .And, ptr, val, model);
322}
323
324fn __atomic_fetch_or_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
325 return fetch_op_N(u8, .Or, ptr, val, model);
326}
327
328fn __atomic_fetch_or_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
329 return fetch_op_N(u16, .Or, ptr, val, model);
330}
331
332fn __atomic_fetch_or_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
333 return fetch_op_N(u32, .Or, ptr, val, model);
334}
335
336fn __atomic_fetch_or_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
337 return fetch_op_N(u64, .Or, ptr, val, model);
338}
339
340fn __atomic_fetch_xor_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
341 return fetch_op_N(u8, .Xor, ptr, val, model);
342}
343
344fn __atomic_fetch_xor_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
345 return fetch_op_N(u16, .Xor, ptr, val, model);
346}
347
348fn __atomic_fetch_xor_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
349 return fetch_op_N(u32, .Xor, ptr, val, model);
350}
351
352fn __atomic_fetch_xor_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
353 return fetch_op_N(u64, .Xor, ptr, val, model);
354}
355
356fn __atomic_fetch_nand_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
357 return fetch_op_N(u8, .Nand, ptr, val, model);
358}
359
360fn __atomic_fetch_nand_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
361 return fetch_op_N(u16, .Nand, ptr, val, model);
362}
363
364fn __atomic_fetch_nand_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
365 return fetch_op_N(u32, .Nand, ptr, val, model);
366}
367
368fn __atomic_fetch_nand_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
369 return fetch_op_N(u64, .Nand, ptr, val, model);
285}370}
286371
287comptime {372comptime {
288 if (supports_atomic_ops) {373 if (supports_atomic_ops) {
289 const fetch_add_u8 = fetchFn(u8, .Add);374 @export(__atomic_load, .{ .name = "__atomic_load", .linkage = linkage });
290 const fetch_add_u16 = fetchFn(u16, .Add);375 @export(__atomic_store, .{ .name = "__atomic_store", .linkage = linkage });
291 const fetch_add_u32 = fetchFn(u32, .Add);376 @export(__atomic_exchange, .{ .name = "__atomic_exchange", .linkage = linkage });
292 const fetch_add_u64 = fetchFn(u64, .Add);377 @export(__atomic_compare_exchange, .{ .name = "__atomic_compare_exchange", .linkage = linkage });
293 @export(fetch_add_u8, .{ .name = "__atomic_fetch_add_1", .linkage = linkage });378
294 @export(fetch_add_u16, .{ .name = "__atomic_fetch_add_2", .linkage = linkage });379 @export(__atomic_fetch_add_1, .{ .name = "__atomic_fetch_add_1", .linkage = linkage });
295 @export(fetch_add_u32, .{ .name = "__atomic_fetch_add_4", .linkage = linkage });380 @export(__atomic_fetch_add_2, .{ .name = "__atomic_fetch_add_2", .linkage = linkage });
296 @export(fetch_add_u64, .{ .name = "__atomic_fetch_add_8", .linkage = linkage });381 @export(__atomic_fetch_add_4, .{ .name = "__atomic_fetch_add_4", .linkage = linkage });
297382 @export(__atomic_fetch_add_8, .{ .name = "__atomic_fetch_add_8", .linkage = linkage });
298 const fetch_sub_u8 = fetchFn(u8, .Sub);383
299 const fetch_sub_u16 = fetchFn(u16, .Sub);384 @export(__atomic_fetch_sub_1, .{ .name = "__atomic_fetch_sub_1", .linkage = linkage });
300 const fetch_sub_u32 = fetchFn(u32, .Sub);385 @export(__atomic_fetch_sub_2, .{ .name = "__atomic_fetch_sub_2", .linkage = linkage });
301 const fetch_sub_u64 = fetchFn(u64, .Sub);386 @export(__atomic_fetch_sub_4, .{ .name = "__atomic_fetch_sub_4", .linkage = linkage });
302 @export(fetch_sub_u8, .{ .name = "__atomic_fetch_sub_1", .linkage = linkage });387 @export(__atomic_fetch_sub_8, .{ .name = "__atomic_fetch_sub_8", .linkage = linkage });
303 @export(fetch_sub_u16, .{ .name = "__atomic_fetch_sub_2", .linkage = linkage });388
304 @export(fetch_sub_u32, .{ .name = "__atomic_fetch_sub_4", .linkage = linkage });389 @export(__atomic_fetch_and_1, .{ .name = "__atomic_fetch_and_1", .linkage = linkage });
305 @export(fetch_sub_u64, .{ .name = "__atomic_fetch_sub_8", .linkage = linkage });390 @export(__atomic_fetch_and_2, .{ .name = "__atomic_fetch_and_2", .linkage = linkage });
306391 @export(__atomic_fetch_and_4, .{ .name = "__atomic_fetch_and_4", .linkage = linkage });
307 const fetch_and_u8 = fetchFn(u8, .And);392 @export(__atomic_fetch_and_8, .{ .name = "__atomic_fetch_and_8", .linkage = linkage });
308 const fetch_and_u16 = fetchFn(u16, .And);393
309 const fetch_and_u32 = fetchFn(u32, .And);394 @export(__atomic_fetch_or_1, .{ .name = "__atomic_fetch_or_1", .linkage = linkage });
310 const fetch_and_u64 = fetchFn(u64, .And);395 @export(__atomic_fetch_or_2, .{ .name = "__atomic_fetch_or_2", .linkage = linkage });
311 @export(fetch_and_u8, .{ .name = "__atomic_fetch_and_1", .linkage = linkage });396 @export(__atomic_fetch_or_4, .{ .name = "__atomic_fetch_or_4", .linkage = linkage });
312 @export(fetch_and_u16, .{ .name = "__atomic_fetch_and_2", .linkage = linkage });397 @export(__atomic_fetch_or_8, .{ .name = "__atomic_fetch_or_8", .linkage = linkage });
313 @export(fetch_and_u32, .{ .name = "__atomic_fetch_and_4", .linkage = linkage });398
314 @export(fetch_and_u64, .{ .name = "__atomic_fetch_and_8", .linkage = linkage });399 @export(__atomic_fetch_xor_1, .{ .name = "__atomic_fetch_xor_1", .linkage = linkage });
315400 @export(__atomic_fetch_xor_2, .{ .name = "__atomic_fetch_xor_2", .linkage = linkage });
316 const fetch_or_u8 = fetchFn(u8, .Or);401 @export(__atomic_fetch_xor_4, .{ .name = "__atomic_fetch_xor_4", .linkage = linkage });
317 const fetch_or_u16 = fetchFn(u16, .Or);402 @export(__atomic_fetch_xor_8, .{ .name = "__atomic_fetch_xor_8", .linkage = linkage });
318 const fetch_or_u32 = fetchFn(u32, .Or);403
319 const fetch_or_u64 = fetchFn(u64, .Or);404 @export(__atomic_fetch_nand_1, .{ .name = "__atomic_fetch_nand_1", .linkage = linkage });
320 @export(fetch_or_u8, .{ .name = "__atomic_fetch_or_1", .linkage = linkage });405 @export(__atomic_fetch_nand_2, .{ .name = "__atomic_fetch_nand_2", .linkage = linkage });
321 @export(fetch_or_u16, .{ .name = "__atomic_fetch_or_2", .linkage = linkage });406 @export(__atomic_fetch_nand_4, .{ .name = "__atomic_fetch_nand_4", .linkage = linkage });
322 @export(fetch_or_u32, .{ .name = "__atomic_fetch_or_4", .linkage = linkage });407 @export(__atomic_fetch_nand_8, .{ .name = "__atomic_fetch_nand_8", .linkage = linkage });
323 @export(fetch_or_u64, .{ .name = "__atomic_fetch_or_8", .linkage = linkage });408
324409 @export(__atomic_load_1, .{ .name = "__atomic_load_1", .linkage = linkage });
325 const fetch_xor_u8 = fetchFn(u8, .Xor);410 @export(__atomic_load_2, .{ .name = "__atomic_load_2", .linkage = linkage });
326 const fetch_xor_u16 = fetchFn(u16, .Xor);411 @export(__atomic_load_4, .{ .name = "__atomic_load_4", .linkage = linkage });
327 const fetch_xor_u32 = fetchFn(u32, .Xor);412 @export(__atomic_load_8, .{ .name = "__atomic_load_8", .linkage = linkage });
328 const fetch_xor_u64 = fetchFn(u64, .Xor);413
329 @export(fetch_xor_u8, .{ .name = "__atomic_fetch_xor_1", .linkage = linkage });414 @export(__atomic_store_1, .{ .name = "__atomic_store_1", .linkage = linkage });
330 @export(fetch_xor_u16, .{ .name = "__atomic_fetch_xor_2", .linkage = linkage });415 @export(__atomic_store_2, .{ .name = "__atomic_store_2", .linkage = linkage });
331 @export(fetch_xor_u32, .{ .name = "__atomic_fetch_xor_4", .linkage = linkage });416 @export(__atomic_store_4, .{ .name = "__atomic_store_4", .linkage = linkage });
332 @export(fetch_xor_u64, .{ .name = "__atomic_fetch_xor_8", .linkage = linkage });417 @export(__atomic_store_8, .{ .name = "__atomic_store_8", .linkage = linkage });
333418
334 const fetch_nand_u8 = fetchFn(u8, .Nand);419 @export(__atomic_exchange_1, .{ .name = "__atomic_exchange_1", .linkage = linkage });
335 const fetch_nand_u16 = fetchFn(u16, .Nand);420 @export(__atomic_exchange_2, .{ .name = "__atomic_exchange_2", .linkage = linkage });
336 const fetch_nand_u32 = fetchFn(u32, .Nand);421 @export(__atomic_exchange_4, .{ .name = "__atomic_exchange_4", .linkage = linkage });
337 const fetch_nand_u64 = fetchFn(u64, .Nand);422 @export(__atomic_exchange_8, .{ .name = "__atomic_exchange_8", .linkage = linkage });
338 @export(fetch_nand_u8, .{ .name = "__atomic_fetch_nand_1", .linkage = linkage });423
339 @export(fetch_nand_u16, .{ .name = "__atomic_fetch_nand_2", .linkage = linkage });424 @export(__atomic_compare_exchange_1, .{ .name = "__atomic_compare_exchange_1", .linkage = linkage });
340 @export(fetch_nand_u32, .{ .name = "__atomic_fetch_nand_4", .linkage = linkage });425 @export(__atomic_compare_exchange_2, .{ .name = "__atomic_compare_exchange_2", .linkage = linkage });
341 @export(fetch_nand_u64, .{ .name = "__atomic_fetch_nand_8", .linkage = linkage });426 @export(__atomic_compare_exchange_4, .{ .name = "__atomic_compare_exchange_4", .linkage = linkage });
427 @export(__atomic_compare_exchange_8, .{ .name = "__atomic_compare_exchange_8", .linkage = linkage });
342 }428 }
343}429}
lib/std/special/compiler_rt/bswap.zig+55-55
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4// bswap - byteswap4// bswap - byteswap
5// - bswapXi2_generic for unoptimized big and little endian5// - bswapXi2 for unoptimized big and little endian
6// ie for u326// ie for u32
7// DE AD BE EF <- little|big endian7// DE AD BE EF <- little|big endian
8// FE BE AD DE <- big|little endian8// FE BE AD DE <- big|little endian
...@@ -11,64 +11,64 @@ const builtin = @import("builtin");...@@ -11,64 +11,64 @@ const builtin = @import("builtin");
11// 00 00 ff 00 << 1*8 (2n right byte)11// 00 00 ff 00 << 1*8 (2n right byte)
12// 00 00 00 ff << 3*8 (rightmost byte)12// 00 00 00 ff << 3*8 (rightmost byte)
1313
14fn bswapXi2_generic(comptime T: type) fn (a: T) callconv(.C) T {14inline fn bswapXi2(comptime T: type, a: T) T {
15 return struct {15 @setRuntimeSafety(builtin.is_test);
16 fn f(a: T) callconv(.C) T {16 switch (@bitSizeOf(T)) {
17 @setRuntimeSafety(builtin.is_test);17 32 => {
18 switch (@bitSizeOf(T)) {18 // zig fmt: off
19 32 => {19 return (((a & 0xff000000) >> 24)
20 // zig fmt: off20 | ((a & 0x00ff0000) >> 8 )
21 return (((a & 0xff000000) >> 24)21 | ((a & 0x0000ff00) << 8 )
22 | ((a & 0x00ff0000) >> 8 )22 | ((a & 0x000000ff) << 24));
23 | ((a & 0x0000ff00) << 8 )23 // zig fmt: on
24 | ((a & 0x000000ff) << 24));24 },
25 // zig fmt: on25 64 => {
26 },26 // zig fmt: off
27 64 => {27 return (((a & 0xff00000000000000) >> 56)
28 // zig fmt: off28 | ((a & 0x00ff000000000000) >> 40 )
29 return (((a & 0xff00000000000000) >> 56)29 | ((a & 0x0000ff0000000000) >> 24 )
30 | ((a & 0x00ff000000000000) >> 40 )30 | ((a & 0x000000ff00000000) >> 8 )
31 | ((a & 0x0000ff0000000000) >> 24 )31 | ((a & 0x00000000ff000000) << 8 )
32 | ((a & 0x000000ff00000000) >> 8 )32 | ((a & 0x0000000000ff0000) << 24 )
33 | ((a & 0x00000000ff000000) << 8 )33 | ((a & 0x000000000000ff00) << 40 )
34 | ((a & 0x0000000000ff0000) << 24 )34 | ((a & 0x00000000000000ff) << 56));
35 | ((a & 0x000000000000ff00) << 40 )35 // zig fmt: on
36 | ((a & 0x00000000000000ff) << 56));36 },
37 // zig fmt: on37 128 => {
38 },38 // zig fmt: off
39 128 => {39 return (((a & 0xff000000000000000000000000000000) >> 120)
40 // zig fmt: off40 | ((a & 0x00ff0000000000000000000000000000) >> 104)
41 return (((a & 0xff000000000000000000000000000000) >> 120)41 | ((a & 0x0000ff00000000000000000000000000) >> 88 )
42 | ((a & 0x00ff0000000000000000000000000000) >> 104)42 | ((a & 0x000000ff000000000000000000000000) >> 72 )
43 | ((a & 0x0000ff00000000000000000000000000) >> 88 )43 | ((a & 0x00000000ff0000000000000000000000) >> 56 )
44 | ((a & 0x000000ff000000000000000000000000) >> 72 )44 | ((a & 0x0000000000ff00000000000000000000) >> 40 )
45 | ((a & 0x00000000ff0000000000000000000000) >> 56 )45 | ((a & 0x000000000000ff000000000000000000) >> 24 )
46 | ((a & 0x0000000000ff00000000000000000000) >> 40 )46 | ((a & 0x00000000000000ff0000000000000000) >> 8 )
47 | ((a & 0x000000000000ff000000000000000000) >> 24 )47 | ((a & 0x0000000000000000ff00000000000000) << 8 )
48 | ((a & 0x00000000000000ff0000000000000000) >> 8 )48 | ((a & 0x000000000000000000ff000000000000) << 24 )
49 | ((a & 0x0000000000000000ff00000000000000) << 8 )49 | ((a & 0x00000000000000000000ff0000000000) << 40 )
50 | ((a & 0x000000000000000000ff000000000000) << 24 )50 | ((a & 0x0000000000000000000000ff00000000) << 56 )
51 | ((a & 0x00000000000000000000ff0000000000) << 40 )51 | ((a & 0x000000000000000000000000ff000000) << 72 )
52 | ((a & 0x0000000000000000000000ff00000000) << 56 )52 | ((a & 0x00000000000000000000000000ff0000) << 88 )
53 | ((a & 0x000000000000000000000000ff000000) << 72 )53 | ((a & 0x0000000000000000000000000000ff00) << 104)
54 | ((a & 0x00000000000000000000000000ff0000) << 88 )54 | ((a & 0x000000000000000000000000000000ff) << 120));
55 | ((a & 0x0000000000000000000000000000ff00) << 104)55 // zig fmt: on
56 | ((a & 0x000000000000000000000000000000ff) << 120));56 },
57 // zig fmt: on57 else => unreachable,
58 },58 }
59 else => {
60 unreachable;
61 },
62 }
63 }
64 }.f;
65}59}
6660
67pub const __bswapsi2 = bswapXi2_generic(u32);61pub fn __bswapsi2(a: u32) callconv(.C) u32 {
62 return bswapXi2(u32, a);
63}
6864
69pub const __bswapdi2 = bswapXi2_generic(u64);65pub fn __bswapdi2(a: u64) callconv(.C) u64 {
66 return bswapXi2(u64, a);
67}
7068
71pub const __bswapti2 = bswapXi2_generic(u128);69pub fn __bswapti2(a: u128) callconv(.C) u128 {
70 return bswapXi2(u128, a);
71}
7272
73test {73test {
74 _ = @import("bswapsi2_test.zig");74 _ = @import("bswapsi2_test.zig");
lib/std/special/compiler_rt/cmp.zig+34-22
...@@ -11,28 +11,40 @@ const builtin = @import("builtin");...@@ -11,28 +11,40 @@ const builtin = @import("builtin");
11// a == b => 111// a == b => 1
12// a > b => 212// a > b => 2
1313
14fn XcmpXi2_generic(comptime T: type) fn (a: T, b: T) callconv(.C) i32 {14inline fn XcmpXi2(comptime T: type, a: T, b: T) i32 {
15 return struct {15 @setRuntimeSafety(builtin.is_test);
16 fn f(a: T, b: T) callconv(.C) i32 {16 var cmp1: i32 = 0;
17 @setRuntimeSafety(builtin.is_test);17 var cmp2: i32 = 0;
18 var cmp1: i32 = 0;18 if (a > b)
19 var cmp2: i32 = 0;19 cmp1 = 1;
20 if (a > b)20 if (a < b)
21 cmp1 = 1;21 cmp2 = 1;
22 if (a < b)22 return cmp1 - cmp2 + 1;
23 cmp2 = 1;23}
24 return cmp1 - cmp2 + 1;24
25 }25pub fn __cmpsi2(a: i32, b: i32) callconv(.C) i32 {
26 }.f;26 return XcmpXi2(i32, a, b);
27}27}
2828
29pub const __cmpsi2 = XcmpXi2_generic(i32);29pub fn __cmpdi2(a: i64, b: i64) callconv(.C) i32 {
30pub const __cmpdi2 = XcmpXi2_generic(i64);30 return XcmpXi2(i64, a, b);
31pub const __cmpti2 = XcmpXi2_generic(i128);31}
3232
33pub const __ucmpsi2 = XcmpXi2_generic(u32);33pub fn __cmpti2(a: i128, b: i128) callconv(.C) i32 {
34pub const __ucmpdi2 = XcmpXi2_generic(u64);34 return XcmpXi2(i128, a, b);
35pub const __ucmpti2 = XcmpXi2_generic(u128);35}
36
37pub fn __ucmpsi2(a: u32, b: u32) callconv(.C) i32 {
38 return XcmpXi2(u32, a, b);
39}
40
41pub fn __ucmpdi2(a: u64, b: u64) callconv(.C) i32 {
42 return XcmpXi2(u64, a, b);
43}
44
45pub fn __ucmpti2(a: u128, b: u128) callconv(.C) i32 {
46 return XcmpXi2(u128, a, b);
47}
3648
37test {49test {
38 _ = @import("cmpsi2_test.zig");50 _ = @import("cmpsi2_test.zig");
lib/std/special/compiler_rt/count0bits.zig+122-116
...@@ -2,44 +2,40 @@ const std = @import("std");...@@ -2,44 +2,40 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4// clz - count leading zeroes4// clz - count leading zeroes
5// - clzXi2_generic for unoptimized little and big endian5// - clzXi2 for unoptimized little and big endian
6// - __clzsi2_thumb1: assume a != 06// - __clzsi2_thumb1: assume a != 0
7// - __clzsi2_arm32: assume a != 07// - __clzsi2_arm32: assume a != 0
88
9// ctz - count trailing zeroes9// ctz - count trailing zeroes
10// - ctzXi2_generic for unoptimized little and big endian10// - ctzXi2 for unoptimized little and big endian
1111
12// ffs - find first set12// ffs - find first set
13// * ffs = (a == 0) => 0, (a != 0) => ctz + 113// * ffs = (a == 0) => 0, (a != 0) => ctz + 1
14// * dont pay for `if (x == 0) return shift;` inside ctz14// * dont pay for `if (x == 0) return shift;` inside ctz
15// - ffsXi2_generic for unoptimized little and big endian15// - ffsXi2 for unoptimized little and big endian
1616
17fn clzXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {17inline fn clzXi2(comptime T: type, a: T) i32 {
18 return struct {18 @setRuntimeSafety(builtin.is_test);
19 fn f(a: T) callconv(.C) i32 {19
20 @setRuntimeSafety(builtin.is_test);20 var x = switch (@bitSizeOf(T)) {
2121 32 => @bitCast(u32, a),
22 var x = switch (@bitSizeOf(T)) {22 64 => @bitCast(u64, a),
23 32 => @bitCast(u32, a),23 128 => @bitCast(u128, a),
24 64 => @bitCast(u64, a),24 else => unreachable,
25 128 => @bitCast(u128, a),25 };
26 else => unreachable,26 var n: T = @bitSizeOf(T);
27 };27 // Count first bit set using binary search, from Hacker's Delight
28 var n: T = @bitSizeOf(T);28 var y: @TypeOf(x) = 0;
29 // Count first bit set using binary search, from Hacker's Delight29 comptime var shift: u8 = @bitSizeOf(T);
30 var y: @TypeOf(x) = 0;30 inline while (shift > 0) {
31 comptime var shift: u8 = @bitSizeOf(T);31 shift = shift >> 1;
32 inline while (shift > 0) {32 y = x >> shift;
33 shift = shift >> 1;33 if (y != 0) {
34 y = x >> shift;34 n = n - shift;
35 if (y != 0) {35 x = y;
36 n = n - shift;
37 x = y;
38 }
39 }
40 return @intCast(i32, n - @bitCast(T, x));
41 }36 }
42 }.f;37 }
38 return @intCast(i32, n - @bitCast(T, x));
43}39}
4440
45fn __clzsi2_thumb1() callconv(.Naked) void {41fn __clzsi2_thumb1() callconv(.Naked) void {
...@@ -125,103 +121,113 @@ fn __clzsi2_arm32() callconv(.Naked) void {...@@ -125,103 +121,113 @@ fn __clzsi2_arm32() callconv(.Naked) void {
125 unreachable;121 unreachable;
126}122}
127123
128pub const __clzsi2 = impl: {124fn clzsi2_generic(a: i32) callconv(.C) i32 {
129 switch (builtin.cpu.arch) {125 return clzXi2(i32, a);
130 .arm, .armeb, .thumb, .thumbeb => {126}
131 const use_thumb1 =127
132 (builtin.cpu.arch.isThumb() or128pub const __clzsi2 = switch (builtin.cpu.arch) {
133 std.Target.arm.featureSetHas(builtin.cpu.features, .noarm)) and129 .arm, .armeb, .thumb, .thumbeb => impl: {
134 !std.Target.arm.featureSetHas(builtin.cpu.features, .thumb2);130 const use_thumb1 =
135131 (builtin.cpu.arch.isThumb() or
136 if (use_thumb1) {132 std.Target.arm.featureSetHas(builtin.cpu.features, .noarm)) and
137 break :impl __clzsi2_thumb1;133 !std.Target.arm.featureSetHas(builtin.cpu.features, .thumb2);
138 }134
139 // From here on we're either targeting Thumb2 or ARM.135 if (use_thumb1) {
140 else if (!builtin.cpu.arch.isThumb()) {136 break :impl __clzsi2_thumb1;
141 break :impl __clzsi2_arm32;137 }
142 }138 // From here on we're either targeting Thumb2 or ARM.
143 // Use the generic implementation otherwise.139 else if (!builtin.cpu.arch.isThumb()) {
144 else break :impl clzXi2_generic(i32);140 break :impl __clzsi2_arm32;
145 },141 }
146 else => break :impl clzXi2_generic(i32),142 // Use the generic implementation otherwise.
147 }143 else break :impl clzsi2_generic;
144 },
145 else => clzsi2_generic,
148};146};
149147
150pub const __clzdi2 = clzXi2_generic(i64);148pub fn __clzdi2(a: i64) callconv(.C) i32 {
151149 return clzXi2(i64, a);
152pub const __clzti2 = clzXi2_generic(i128);150}
153151
154fn ctzXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {152pub fn __clzti2(a: i128) callconv(.C) i32 {
155 return struct {153 return clzXi2(i128, a);
156 fn f(a: T) callconv(.C) i32 {154}
157 @setRuntimeSafety(builtin.is_test);155
158156inline fn ctzXi2(comptime T: type, a: T) i32 {
159 var x = switch (@bitSizeOf(T)) {157 @setRuntimeSafety(builtin.is_test);
160 32 => @bitCast(u32, a),158
161 64 => @bitCast(u64, a),159 var x = switch (@bitSizeOf(T)) {
162 128 => @bitCast(u128, a),160 32 => @bitCast(u32, a),
163 else => unreachable,161 64 => @bitCast(u64, a),
164 };162 128 => @bitCast(u128, a),
165 var n: T = 1;163 else => unreachable,
166 // Number of trailing zeroes as binary search, from Hacker's Delight164 };
167 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));165 var n: T = 1;
168 comptime var shift = @bitSizeOf(T);166 // Number of trailing zeroes as binary search, from Hacker's Delight
169 if (x == 0) return shift;167 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));
170 inline while (shift > 1) {168 comptime var shift = @bitSizeOf(T);
171 shift = shift >> 1;169 if (x == 0) return shift;
172 mask = mask >> shift;170 inline while (shift > 1) {
173 if ((x & mask) == 0) {171 shift = shift >> 1;
174 n = n + shift;172 mask = mask >> shift;
175 x = x >> shift;173 if ((x & mask) == 0) {
176 }174 n = n + shift;
177 }175 x = x >> shift;
178 return @intCast(i32, n - @bitCast(T, (x & 1)));
179 }176 }
180 }.f;177 }
178 return @intCast(i32, n - @bitCast(T, (x & 1)));
179}
180
181pub fn __ctzsi2(a: i32) callconv(.C) i32 {
182 return ctzXi2(i32, a);
181}183}
182184
183pub const __ctzsi2 = ctzXi2_generic(i32);185pub fn __ctzdi2(a: i64) callconv(.C) i32 {
184186 return ctzXi2(i64, a);
185pub const __ctzdi2 = ctzXi2_generic(i64);187}
186188
187pub const __ctzti2 = ctzXi2_generic(i128);189pub fn __ctzti2(a: i128) callconv(.C) i32 {
188190 return ctzXi2(i128, a);
189fn ffsXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {191}
190 return struct {192
191 fn f(a: T) callconv(.C) i32 {193inline fn ffsXi2(comptime T: type, a: T) i32 {
192 @setRuntimeSafety(builtin.is_test);194 @setRuntimeSafety(builtin.is_test);
193195
194 var x = switch (@bitSizeOf(T)) {196 var x = switch (@bitSizeOf(T)) {
195 32 => @bitCast(u32, a),197 32 => @bitCast(u32, a),
196 64 => @bitCast(u64, a),198 64 => @bitCast(u64, a),
197 128 => @bitCast(u128, a),199 128 => @bitCast(u128, a),
198 else => unreachable,200 else => unreachable,
199 };201 };
200 var n: T = 1;202 var n: T = 1;
201 // adapted from Number of trailing zeroes (see ctzXi2_generic)203 // adapted from Number of trailing zeroes (see ctzXi2)
202 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));204 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));
203 comptime var shift = @bitSizeOf(T);205 comptime var shift = @bitSizeOf(T);
204 // In contrast to ctz return 0206 // In contrast to ctz return 0
205 if (x == 0) return 0;207 if (x == 0) return 0;
206 inline while (shift > 1) {208 inline while (shift > 1) {
207 shift = shift >> 1;209 shift = shift >> 1;
208 mask = mask >> shift;210 mask = mask >> shift;
209 if ((x & mask) == 0) {211 if ((x & mask) == 0) {
210 n = n + shift;212 n = n + shift;
211 x = x >> shift;213 x = x >> shift;
212 }
213 }
214 // return ctz + 1
215 return @intCast(i32, n - @bitCast(T, (x & 1))) + @as(i32, 1);
216 }214 }
217 }.f;215 }
216 // return ctz + 1
217 return @intCast(i32, n - @bitCast(T, (x & 1))) + @as(i32, 1);
218}218}
219219
220pub const __ffssi2 = ffsXi2_generic(i32);220pub fn __ffssi2(a: i32) callconv(.C) i32 {
221 return ffsXi2(i32, a);
222}
221223
222pub const __ffsdi2 = ffsXi2_generic(i64);224pub fn __ffsdi2(a: i64) callconv(.C) i32 {
225 return ffsXi2(i64, a);
226}
223227
224pub const __ffsti2 = ffsXi2_generic(i128);228pub fn __ffsti2(a: i128) callconv(.C) i32 {
229 return ffsXi2(i128, a);
230}
225231
226test {232test {
227 _ = @import("clzsi2_test.zig");233 _ = @import("clzsi2_test.zig");
lib/std/special/compiler_rt/divdf3.zig+1-1
...@@ -35,7 +35,7 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {...@@ -35,7 +35,7 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
35 var scale: i32 = 0;35 var scale: i32 = 0;
3636
37 // Detect if a or b is zero, denormal, infinity, or NaN.37 // Detect if a or b is zero, denormal, infinity, or NaN.
38 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {38 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
39 const aAbs: Z = @bitCast(Z, a) & absMask;39 const aAbs: Z = @bitCast(Z, a) & absMask;
40 const bAbs: Z = @bitCast(Z, b) & absMask;40 const bAbs: Z = @bitCast(Z, b) & absMask;
4141
lib/std/special/compiler_rt/divsf3.zig+1-1
...@@ -34,7 +34,7 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {...@@ -34,7 +34,7 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
34 var scale: i32 = 0;34 var scale: i32 = 0;
3535
36 // Detect if a or b is zero, denormal, infinity, or NaN.36 // Detect if a or b is zero, denormal, infinity, or NaN.
37 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {37 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
38 const aAbs: Z = @bitCast(Z, a) & absMask;38 const aAbs: Z = @bitCast(Z, a) & absMask;
39 const bAbs: Z = @bitCast(Z, b) & absMask;39 const bAbs: Z = @bitCast(Z, b) & absMask;
4040
lib/std/special/compiler_rt/divtf3.zig+1-1
...@@ -33,7 +33,7 @@ pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {...@@ -33,7 +33,7 @@ pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {
33 var scale: i32 = 0;33 var scale: i32 = 0;
3434
35 // Detect if a or b is zero, denormal, infinity, or NaN.35 // Detect if a or b is zero, denormal, infinity, or NaN.
36 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {36 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
37 const aAbs: Z = @bitCast(Z, a) & absMask;37 const aAbs: Z = @bitCast(Z, a) & absMask;
38 const bAbs: Z = @bitCast(Z, b) & absMask;38 const bAbs: Z = @bitCast(Z, b) & absMask;
3939
lib/std/special/compiler_rt/fixuint.zig+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const is_test = @import("builtin").is_test;1const is_test = @import("builtin").is_test;
2const Log2Int = @import("std").math.Log2Int;2const Log2Int = @import("std").math.Log2Int;
33
4pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t {4pub inline fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t {
5 @setRuntimeSafety(is_test);5 @setRuntimeSafety(is_test);
66
7 const rep_t = switch (fp_t) {7 const rep_t = switch (fp_t) {
lib/std/special/compiler_rt/floatXisf.zig+4-7
...@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;...@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;
44
5const FLT_MANT_DIG = 24;5const FLT_MANT_DIG = 24;
66
7fn __floatXisf(comptime T: type, arg: T) f32 {7inline fn floatXisf(comptime T: type, arg: T) f32 {
8 @setRuntimeSafety(builtin.is_test);8 @setRuntimeSafety(builtin.is_test);
99
10 const bits = @typeInfo(T).Int.bits;10 const bits = @typeInfo(T).Int.bits;
...@@ -71,18 +71,15 @@ fn __floatXisf(comptime T: type, arg: T) f32 {...@@ -71,18 +71,15 @@ fn __floatXisf(comptime T: type, arg: T) f32 {
71}71}
7272
73pub fn __floatdisf(arg: i64) callconv(.C) f32 {73pub fn __floatdisf(arg: i64) callconv(.C) f32 {
74 @setRuntimeSafety(builtin.is_test);74 return floatXisf(i64, arg);
75 return @call(.{ .modifier = .always_inline }, __floatXisf, .{ i64, arg });
76}75}
7776
78pub fn __floattisf(arg: i128) callconv(.C) f32 {77pub fn __floattisf(arg: i128) callconv(.C) f32 {
79 @setRuntimeSafety(builtin.is_test);78 return floatXisf(i128, arg);
80 return @call(.{ .modifier = .always_inline }, __floatXisf, .{ i128, arg });
81}79}
8280
83pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 {81pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 {
84 @setRuntimeSafety(false);82 return floatXisf(i64, arg);
85 return @call(.{ .modifier = .always_inline }, __floatdisf, .{arg});
86}83}
8784
88test {85test {
lib/std/special/compiler_rt/floatsiXf.zig+6-6
...@@ -2,7 +2,7 @@ const builtin = @import("builtin");...@@ -2,7 +2,7 @@ const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const maxInt = std.math.maxInt;3const maxInt = std.math.maxInt;
44
5fn floatsiXf(comptime T: type, a: i32) T {5inline fn floatsiXf(comptime T: type, a: i32) T {
6 @setRuntimeSafety(builtin.is_test);6 @setRuntimeSafety(builtin.is_test);
77
8 const bits = @typeInfo(T).Float.bits;8 const bits = @typeInfo(T).Float.bits;
...@@ -56,27 +56,27 @@ fn floatsiXf(comptime T: type, a: i32) T {...@@ -56,27 +56,27 @@ fn floatsiXf(comptime T: type, a: i32) T {
5656
57pub fn __floatsisf(arg: i32) callconv(.C) f32 {57pub fn __floatsisf(arg: i32) callconv(.C) f32 {
58 @setRuntimeSafety(builtin.is_test);58 @setRuntimeSafety(builtin.is_test);
59 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f32, arg });59 return floatsiXf(f32, arg);
60}60}
6161
62pub fn __floatsidf(arg: i32) callconv(.C) f64 {62pub fn __floatsidf(arg: i32) callconv(.C) f64 {
63 @setRuntimeSafety(builtin.is_test);63 @setRuntimeSafety(builtin.is_test);
64 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f64, arg });64 return floatsiXf(f64, arg);
65}65}
6666
67pub fn __floatsitf(arg: i32) callconv(.C) f128 {67pub fn __floatsitf(arg: i32) callconv(.C) f128 {
68 @setRuntimeSafety(builtin.is_test);68 @setRuntimeSafety(builtin.is_test);
69 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f128, arg });69 return floatsiXf(f128, arg);
70}70}
7171
72pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 {72pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 {
73 @setRuntimeSafety(false);73 @setRuntimeSafety(false);
74 return @call(.{ .modifier = .always_inline }, __floatsidf, .{arg});74 return floatsiXf(f64, arg);
75}75}
7676
77pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 {77pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 {
78 @setRuntimeSafety(false);78 @setRuntimeSafety(false);
79 return @call(.{ .modifier = .always_inline }, __floatsisf, .{arg});79 return floatsiXf(f32, arg);
80}80}
8181
82fn test_one_floatsitf(a: i32, expected: u128) !void {82fn test_one_floatsitf(a: i32, expected: u128) !void {
lib/std/special/compiler_rt/floatundisf.zig+6-3
...@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;...@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;
44
5const FLT_MANT_DIG = 24;5const FLT_MANT_DIG = 24;
66
7pub fn __floatundisf(arg: u64) callconv(.C) f32 {7inline fn floatundisf(arg: u64) f32 {
8 @setRuntimeSafety(builtin.is_test);8 @setRuntimeSafety(builtin.is_test);
99
10 if (arg == 0) return 0;10 if (arg == 0) return 0;
...@@ -56,9 +56,12 @@ pub fn __floatundisf(arg: u64) callconv(.C) f32 {...@@ -56,9 +56,12 @@ pub fn __floatundisf(arg: u64) callconv(.C) f32 {
56 return @bitCast(f32, result);56 return @bitCast(f32, result);
57}57}
5858
59pub fn __floatundisf(arg: u64) callconv(.C) f32 {
60 return floatundisf(arg);
61}
62
59pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 {63pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 {
60 @setRuntimeSafety(false);64 return floatundisf(arg);
61 return @call(.{ .modifier = .always_inline }, __floatundisf, .{arg});
62}65}
6366
64fn test__floatundisf(a: u64, expected: f32) !void {67fn test__floatundisf(a: u64, expected: f32) !void {
lib/std/special/compiler_rt/floatunsidf.zig+6-3
...@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;...@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;
44
5const implicitBit = @as(u64, 1) << 52;5const implicitBit = @as(u64, 1) << 52;
66
7pub fn __floatunsidf(arg: u32) callconv(.C) f64 {7inline fn floatunsidf(arg: u32) f64 {
8 @setRuntimeSafety(builtin.is_test);8 @setRuntimeSafety(builtin.is_test);
99
10 if (arg == 0) return 0.0;10 if (arg == 0) return 0.0;
...@@ -18,9 +18,12 @@ pub fn __floatunsidf(arg: u32) callconv(.C) f64 {...@@ -18,9 +18,12 @@ pub fn __floatunsidf(arg: u32) callconv(.C) f64 {
18 return @bitCast(f64, mant | (exp + 1023) << 52);18 return @bitCast(f64, mant | (exp + 1023) << 52);
19}19}
2020
21pub fn __floatunsidf(arg: u32) callconv(.C) f64 {
22 return floatunsidf(arg);
23}
24
21pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 {25pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 {
22 @setRuntimeSafety(false);26 return floatunsidf(arg);
23 return @call(.{ .modifier = .always_inline }, __floatunsidf, .{arg});
24}27}
2528
26fn test_one_floatunsidf(a: u32, expected: u64) !void {29fn test_one_floatunsidf(a: u32, expected: u64) !void {
lib/std/special/compiler_rt/floatunsisf.zig+6-3
...@@ -6,7 +6,7 @@ const significandBits = 23;...@@ -6,7 +6,7 @@ const significandBits = 23;
6const exponentBias = 127;6const exponentBias = 127;
7const implicitBit = @as(u32, 1) << significandBits;7const implicitBit = @as(u32, 1) << significandBits;
88
9pub fn __floatunsisf(arg: u32) callconv(.C) f32 {9inline fn floatunsisf(arg: u32) f32 {
10 @setRuntimeSafety(builtin.is_test);10 @setRuntimeSafety(builtin.is_test);
1111
12 if (arg == 0) return 0.0;12 if (arg == 0) return 0.0;
...@@ -38,9 +38,12 @@ pub fn __floatunsisf(arg: u32) callconv(.C) f32 {...@@ -38,9 +38,12 @@ pub fn __floatunsisf(arg: u32) callconv(.C) f32 {
38 return @bitCast(f32, result);38 return @bitCast(f32, result);
39}39}
4040
41pub fn __floatunsisf(arg: u32) callconv(.C) f32 {
42 return floatunsisf(arg);
43}
44
41pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 {45pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 {
42 @setRuntimeSafety(false);46 return floatunsisf(arg);
43 return @call(.{ .modifier = .always_inline }, __floatunsisf, .{arg});
44}47}
4548
46fn test_one_floatunsisf(a: u32, expected: u32) !void {49fn test_one_floatunsisf(a: u32, expected: u32) !void {
lib/std/special/compiler_rt/mulXf3.zig+1-1
...@@ -56,7 +56,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T {...@@ -56,7 +56,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
56 var scale: i32 = 0;56 var scale: i32 = 0;
5757
58 // Detect if a or b is zero, denormal, infinity, or NaN.58 // Detect if a or b is zero, denormal, infinity, or NaN.
59 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {59 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
60 const aAbs: Z = @bitCast(Z, a) & absMask;60 const aAbs: Z = @bitCast(Z, a) & absMask;
61 const bAbs: Z = @bitCast(Z, b) & absMask;61 const bAbs: Z = @bitCast(Z, b) & absMask;
6262
lib/std/special/compiler_rt/negXi2.zig+13-11
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4// neg - negate (the number)4// neg - negate (the number)
5// - negXi2_generic for unoptimized little and big endian5// - negXi2 for unoptimized little and big endian
66
7// sfffffff = 2^31-17// sfffffff = 2^31-1
8// two's complement inverting bits and add 1 would result in -INT_MIN == 08// two's complement inverting bits and add 1 would result in -INT_MIN == 0
...@@ -11,20 +11,22 @@ const builtin = @import("builtin");...@@ -11,20 +11,22 @@ const builtin = @import("builtin");
11// * size optimized builds11// * size optimized builds
12// * machines that dont support carry operations12// * machines that dont support carry operations
1313
14fn negXi2_generic(comptime T: type) fn (a: T) callconv(.C) T {14inline fn negXi2(comptime T: type, a: T) T {
15 return struct {15 @setRuntimeSafety(builtin.is_test);
16 fn f(a: T) callconv(.C) T {16 return -a;
17 @setRuntimeSafety(builtin.is_test);
18 return -a;
19 }
20 }.f;
21}17}
2218
23pub const __negsi2 = negXi2_generic(i32);19pub fn __negsi2(a: i32) callconv(.C) i32 {
20 return negXi2(i32, a);
21}
2422
25pub const __negdi2 = negXi2_generic(i64);23pub fn __negdi2(a: i64) callconv(.C) i64 {
24 return negXi2(i64, a);
25}
2626
27pub const __negti2 = negXi2_generic(i128);27pub fn __negti2(a: i128) callconv(.C) i128 {
28 return negXi2(i128, a);
29}
2830
29test {31test {
30 _ = @import("negsi2_test.zig");32 _ = @import("negsi2_test.zig");
lib/std/special/compiler_rt/negv.zig+24-19
...@@ -3,26 +3,31 @@...@@ -3,26 +3,31 @@
3// - negvXi4_generic for unoptimized version3// - negvXi4_generic for unoptimized version
44
5// assume -0 == 0 is gracefully handled by the hardware5// assume -0 == 0 is gracefully handled by the hardware
6fn negvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST {6inline fn negvXi(comptime ST: type, a: ST) ST {
7 return struct {7 const UT = switch (ST) {
8 fn f(a: ST) callconv(.C) ST {8 i32 => u32,
9 const UT = switch (ST) {9 i64 => u64,
10 i32 => u32,10 i128 => u128,
11 i64 => u64,11 else => unreachable,
12 i128 => u128,12 };
13 else => unreachable,13 const N: UT = @bitSizeOf(ST);
14 };14 const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1)));
15 const N: UT = @bitSizeOf(ST);15 if (a == min)
16 const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1)));16 @panic("compiler_rt negv: overflow");
17 if (a == min)17 return -a;
18 @panic("compiler_rt negv: overflow");18}
19 return -a;19
20 }20pub fn __negvsi2(a: i32) callconv(.C) i32 {
21 }.f;21 return negvXi(i32, a);
22}
23
24pub fn __negvdi2(a: i64) callconv(.C) i64 {
25 return negvXi(i64, a);
26}
27
28pub fn __negvti2(a: i128) callconv(.C) i128 {
29 return negvXi(i128, a);
22}30}
23pub const __negvsi2 = negvXi_generic(i32);
24pub const __negvdi2 = negvXi_generic(i64);
25pub const __negvti2 = negvXi_generic(i128);
2631
27test {32test {
28 _ = @import("negvsi2_test.zig");33 _ = @import("negvsi2_test.zig");
lib/std/special/compiler_rt/parity.zig+25-23
...@@ -4,34 +4,36 @@ const builtin = @import("builtin");...@@ -4,34 +4,36 @@ const builtin = @import("builtin");
4// parity - if number of bits set is even => 0, else => 14// parity - if number of bits set is even => 0, else => 1
5// - pariytXi2_generic for big and little endian5// - pariytXi2_generic for big and little endian
66
7fn parityXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {7inline fn parityXi2(comptime T: type, a: T) i32 {
8 return struct {8 @setRuntimeSafety(builtin.is_test);
9 fn f(a: T) callconv(.C) i32 {
10 @setRuntimeSafety(builtin.is_test);
119
12 var x = switch (@bitSizeOf(T)) {10 var x = switch (@bitSizeOf(T)) {
13 32 => @bitCast(u32, a),11 32 => @bitCast(u32, a),
14 64 => @bitCast(u64, a),12 64 => @bitCast(u64, a),
15 128 => @bitCast(u128, a),13 128 => @bitCast(u128, a),
16 else => unreachable,14 else => unreachable,
17 };15 };
18 // Bit Twiddling Hacks: Compute parity in parallel16 // Bit Twiddling Hacks: Compute parity in parallel
19 comptime var shift: u8 = @bitSizeOf(T) / 2;17 comptime var shift: u8 = @bitSizeOf(T) / 2;
20 inline while (shift > 2) {18 inline while (shift > 2) {
21 x ^= x >> shift;19 x ^= x >> shift;
22 shift = shift >> 1;20 shift = shift >> 1;
23 }21 }
24 x &= 0xf;22 x &= 0xf;
25 return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>123 return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>1
26 }
27 }.f;
28}24}
2925
30pub const __paritysi2 = parityXi2_generic(i32);26pub fn __paritysi2(a: i32) callconv(.C) i32 {
27 return parityXi2(i32, a);
28}
3129
32pub const __paritydi2 = parityXi2_generic(i64);30pub fn __paritydi2(a: i64) callconv(.C) i32 {
31 return parityXi2(i64, a);
32}
3333
34pub const __parityti2 = parityXi2_generic(i128);34pub fn __parityti2(a: i128) callconv(.C) i32 {
35 return parityXi2(i128, a);
36}
3537
36test {38test {
37 _ = @import("paritysi2_test.zig");39 _ = @import("paritysi2_test.zig");
lib/std/special/compiler_rt/popcount.zig+27-25
...@@ -10,35 +10,37 @@ const std = @import("std");...@@ -10,35 +10,37 @@ const std = @import("std");
10// TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,10// TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,
11// subsubsection "Working with the rightmost bits" and "Sideways addition".11// subsubsection "Working with the rightmost bits" and "Sideways addition".
1212
13fn popcountXi2_generic(comptime ST: type) fn (a: ST) callconv(.C) i32 {13inline fn popcountXi2(comptime ST: type, a: ST) i32 {
14 return struct {14 @setRuntimeSafety(builtin.is_test);
15 fn f(a: ST) callconv(.C) i32 {15 const UT = switch (ST) {
16 @setRuntimeSafety(builtin.is_test);16 i32 => u32,
17 const UT = switch (ST) {17 i64 => u64,
18 i32 => u32,18 i128 => u128,
19 i64 => u64,19 else => unreachable,
20 i128 => u128,20 };
21 else => unreachable,21 var x = @bitCast(UT, a);
22 };22 x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos
23 var x = @bitCast(UT, a);23 x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles
24 x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos24 + (x & (~@as(UT, 0) / 5));
25 x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles25 x += x >> 4;
26 + (x & (~@as(UT, 0) / 5));26 x &= ~@as(UT, 0) / 17; // 0x0F...0F, aggregate bytes
27 x += x >> 4;27 // 8 most significant bits of x + (x<<8) + (x<<16) + ..
28 x &= ~@as(UT, 0) / 17; // 0x0F...0F, aggregate bytes28 x *%= ~@as(UT, 0) / 255; // 0x01...01
29 // 8 most significant bits of x + (x<<8) + (x<<16) + ..29 x >>= (@bitSizeOf(ST) - 8);
30 x *%= ~@as(UT, 0) / 255; // 0x01...0130 return @intCast(i32, x);
31 x >>= (@bitSizeOf(ST) - 8);
32 return @intCast(i32, x);
33 }
34 }.f;
35}31}
3632
37pub const __popcountsi2 = popcountXi2_generic(i32);33pub fn __popcountsi2(a: i32) callconv(.C) i32 {
34 return popcountXi2(i32, a);
35}
3836
39pub const __popcountdi2 = popcountXi2_generic(i64);37pub fn __popcountdi2(a: i64) callconv(.C) i32 {
38 return popcountXi2(i64, a);
39}
4040
41pub const __popcountti2 = popcountXi2_generic(i128);41pub fn __popcountti2(a: i128) callconv(.C) i32 {
42 return popcountXi2(i128, a);
43}
4244
43test {45test {
44 _ = @import("popcountsi2_test.zig");46 _ = @import("popcountsi2_test.zig");
lib/std/special/compiler_rt/shift.zig+12-12
...@@ -19,7 +19,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type {...@@ -19,7 +19,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type {
1919
20// Arithmetic shift left20// Arithmetic shift left
21// Precondition: 0 <= b < bits_in_dword21// Precondition: 0 <= b < bits_in_dword
22pub fn ashlXi3(comptime T: type, a: T, b: i32) T {22pub inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
23 const dwords = Dwords(T, false);23 const dwords = Dwords(T, false);
24 const S = Log2Int(dwords.HalfT);24 const S = Log2Int(dwords.HalfT);
2525
...@@ -42,7 +42,7 @@ pub fn ashlXi3(comptime T: type, a: T, b: i32) T {...@@ -42,7 +42,7 @@ pub fn ashlXi3(comptime T: type, a: T, b: i32) T {
4242
43// Arithmetic shift right43// Arithmetic shift right
44// Precondition: 0 <= b < T.bit_count44// Precondition: 0 <= b < T.bit_count
45pub fn ashrXi3(comptime T: type, a: T, b: i32) T {45pub inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
46 const dwords = Dwords(T, true);46 const dwords = Dwords(T, true);
47 const S = Log2Int(dwords.HalfT);47 const S = Log2Int(dwords.HalfT);
4848
...@@ -69,7 +69,7 @@ pub fn ashrXi3(comptime T: type, a: T, b: i32) T {...@@ -69,7 +69,7 @@ pub fn ashrXi3(comptime T: type, a: T, b: i32) T {
6969
70// Logical shift right70// Logical shift right
71// Precondition: 0 <= b < T.bit_count71// Precondition: 0 <= b < T.bit_count
72pub fn lshrXi3(comptime T: type, a: T, b: i32) T {72pub inline fn lshrXi3(comptime T: type, a: T, b: i32) T {
73 const dwords = Dwords(T, false);73 const dwords = Dwords(T, false);
74 const S = Log2Int(dwords.HalfT);74 const S = Log2Int(dwords.HalfT);
7575
...@@ -91,32 +91,32 @@ pub fn lshrXi3(comptime T: type, a: T, b: i32) T {...@@ -91,32 +91,32 @@ pub fn lshrXi3(comptime T: type, a: T, b: i32) T {
91}91}
9292
93pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 {93pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 {
94 return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i64, a, b });94 return ashlXi3(i64, a, b);
95}95}
96pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 {96pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 {
97 return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i128, a, b });97 return ashlXi3(i128, a, b);
98}98}
99pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 {99pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 {
100 return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i64, a, b });100 return ashrXi3(i64, a, b);
101}101}
102pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 {102pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 {
103 return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i128, a, b });103 return ashrXi3(i128, a, b);
104}104}
105pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 {105pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 {
106 return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i64, a, b });106 return lshrXi3(i64, a, b);
107}107}
108pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {108pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {
109 return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i128, a, b });109 return lshrXi3(i128, a, b);
110}110}
111111
112pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {112pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {
113 return __ashldi3(a, b);113 return ashlXi3(i64, a, b);
114}114}
115pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {115pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {
116 return __ashrdi3(a, b);116 return ashrXi3(i64, a, b);
117}117}
118pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {118pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {
119 return __lshrdi3(a, b);119 return lshrXi3(i64, a, b);
120}120}
121121
122test {122test {
src/Cache.zig+54-3
...@@ -47,10 +47,16 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{0} ** Hasher.key_length);...@@ -47,10 +47,16 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{0} ** Hasher.key_length);
47pub const File = struct {47pub const File = struct {
48 path: ?[]const u8,48 path: ?[]const u8,
49 max_file_size: ?usize,49 max_file_size: ?usize,
50 stat: fs.File.Stat,50 stat: Stat,
51 bin_digest: BinDigest,51 bin_digest: BinDigest,
52 contents: ?[]const u8,52 contents: ?[]const u8,
5353
54 pub const Stat = struct {
55 inode: fs.File.INode,
56 size: u64,
57 mtime: i128,
58 };
59
54 pub fn deinit(self: *File, allocator: Allocator) void {60 pub fn deinit(self: *File, allocator: Allocator) void {
55 if (self.path) |owned_slice| {61 if (self.path) |owned_slice| {
56 allocator.free(owned_slice);62 allocator.free(owned_slice);
...@@ -424,7 +430,11 @@ pub const Manifest = struct {...@@ -424,7 +430,11 @@ pub const Manifest = struct {
424 if (!size_match or !mtime_match or !inode_match) {430 if (!size_match or !mtime_match or !inode_match) {
425 self.manifest_dirty = true;431 self.manifest_dirty = true;
426432
427 cache_hash_file.stat = actual_stat;433 cache_hash_file.stat = .{
434 .size = actual_stat.size,
435 .mtime = actual_stat.mtime,
436 .inode = actual_stat.inode,
437 };
428438
429 if (self.isProblematicTimestamp(cache_hash_file.stat.mtime)) {439 if (self.isProblematicTimestamp(cache_hash_file.stat.mtime)) {
430 // The actual file has an unreliable timestamp, force it to be hashed440 // The actual file has an unreliable timestamp, force it to be hashed
...@@ -530,7 +540,12 @@ pub const Manifest = struct {...@@ -530,7 +540,12 @@ pub const Manifest = struct {
530 const file = try fs.cwd().openFile(ch_file.path.?, .{});540 const file = try fs.cwd().openFile(ch_file.path.?, .{});
531 defer file.close();541 defer file.close();
532542
533 ch_file.stat = try file.stat();543 const actual_stat = try file.stat();
544 ch_file.stat = .{
545 .size = actual_stat.size,
546 .mtime = actual_stat.mtime,
547 .inode = actual_stat.inode,
548 };
534549
535 if (self.isProblematicTimestamp(ch_file.stat.mtime)) {550 if (self.isProblematicTimestamp(ch_file.stat.mtime)) {
536 // The actual file has an unreliable timestamp, force it to be hashed551 // The actual file has an unreliable timestamp, force it to be hashed
...@@ -615,6 +630,42 @@ pub const Manifest = struct {...@@ -615,6 +630,42 @@ pub const Manifest = struct {
615 try self.populateFileHash(new_ch_file);630 try self.populateFileHash(new_ch_file);
616 }631 }
617632
633 /// Like `addFilePost` but when the file contents have already been loaded from disk.
634 /// On success, cache takes ownership of `resolved_path`.
635 pub fn addFilePostContents(
636 self: *Manifest,
637 resolved_path: []const u8,
638 bytes: []const u8,
639 stat: File.Stat,
640 ) error{OutOfMemory}!void {
641 assert(self.manifest_file != null);
642
643 const ch_file = try self.files.addOne(self.cache.gpa);
644 errdefer self.files.shrinkRetainingCapacity(self.files.items.len - 1);
645
646 ch_file.* = .{
647 .path = resolved_path,
648 .max_file_size = null,
649 .stat = stat,
650 .bin_digest = undefined,
651 .contents = null,
652 };
653
654 if (self.isProblematicTimestamp(ch_file.stat.mtime)) {
655 // The actual file has an unreliable timestamp, force it to be hashed
656 ch_file.stat.mtime = 0;
657 ch_file.stat.inode = 0;
658 }
659
660 {
661 var hasher = hasher_init;
662 hasher.update(bytes);
663 hasher.final(&ch_file.bin_digest);
664 }
665
666 self.hash.hasher.update(&ch_file.bin_digest);
667 }
668
618 pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {669 pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
619 assert(self.manifest_file != null);670 assert(self.manifest_file != null);
620671
src/Compilation.zig+460-225
...@@ -41,8 +41,8 @@ gpa: Allocator,...@@ -41,8 +41,8 @@ gpa: Allocator,
41arena_state: std.heap.ArenaAllocator.State,41arena_state: std.heap.ArenaAllocator.State,
42bin_file: *link.File,42bin_file: *link.File,
43c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},43c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
44stage1_lock: ?Cache.Lock = null,44/// This is a pointer to a local variable inside `update()`.
45stage1_cache_manifest: *Cache.Manifest = undefined,45whole_cache_manifest: ?*Cache.Manifest = null,
4646
47link_error_flags: link.File.ErrorFlags = .{},47link_error_flags: link.File.ErrorFlags = .{},
4848
...@@ -98,6 +98,13 @@ clang_argv: []const []const u8,...@@ -98,6 +98,13 @@ clang_argv: []const []const u8,
98cache_parent: *Cache,98cache_parent: *Cache,
99/// Path to own executable for invoking `zig clang`.99/// Path to own executable for invoking `zig clang`.
100self_exe_path: ?[]const u8,100self_exe_path: ?[]const u8,
101/// null means -fno-emit-bin.
102/// This is mutable memory allocated into the Compilation-lifetime arena (`arena_state`)
103/// of exactly the correct size for "o/[digest]/[basename]".
104/// The basename is of the outputted binary file in case we don't know the directory yet.
105whole_bin_sub_path: ?[]u8,
106/// Same as `whole_bin_sub_path` but for implibs.
107whole_implib_sub_path: ?[]u8,
101zig_lib_directory: Directory,108zig_lib_directory: Directory,
102local_cache_directory: Directory,109local_cache_directory: Directory,
103global_cache_directory: Directory,110global_cache_directory: Directory,
...@@ -418,7 +425,7 @@ pub const AllErrors = struct {...@@ -418,7 +425,7 @@ pub const AllErrors = struct {
418 const module_note = module_err_msg.notes[i];425 const module_note = module_err_msg.notes[i];
419 const source = try module_note.src_loc.file_scope.getSource(module.gpa);426 const source = try module_note.src_loc.file_scope.getSource(module.gpa);
420 const byte_offset = try module_note.src_loc.byteOffset(module.gpa);427 const byte_offset = try module_note.src_loc.byteOffset(module.gpa);
421 const loc = std.zig.findLineColumn(source, byte_offset);428 const loc = std.zig.findLineColumn(source.bytes, byte_offset);
422 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);429 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
423 note.* = .{430 note.* = .{
424 .src = .{431 .src = .{
...@@ -441,7 +448,7 @@ pub const AllErrors = struct {...@@ -441,7 +448,7 @@ pub const AllErrors = struct {
441 }448 }
442 const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);449 const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);
443 const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa);450 const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa);
444 const loc = std.zig.findLineColumn(source, byte_offset);451 const loc = std.zig.findLineColumn(source.bytes, byte_offset);
445 const file_path = try module_err_msg.src_loc.file_scope.fullPath(allocator);452 const file_path = try module_err_msg.src_loc.file_scope.fullPath(allocator);
446 try errors.append(.{453 try errors.append(.{
447 .src = .{454 .src = .{
...@@ -612,6 +619,15 @@ pub const Directory = struct {...@@ -612,6 +619,15 @@ pub const Directory = struct {
612 return std.fs.path.joinZ(allocator, paths);619 return std.fs.path.joinZ(allocator, paths);
613 }620 }
614 }621 }
622
623 /// Whether or not the handle should be closed, or the path should be freed
624 /// is determined by usage, however this function is provided for convenience
625 /// if it happens to be what the caller needs.
626 pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
627 self.handle.close();
628 if (self.path) |p| gpa.free(p);
629 self.* = undefined;
630 }
615};631};
616632
617pub const EmitLoc = struct {633pub const EmitLoc = struct {
...@@ -631,6 +647,7 @@ pub const ClangPreprocessorMode = enum {...@@ -631,6 +647,7 @@ pub const ClangPreprocessorMode = enum {
631};647};
632648
633pub const SystemLib = link.SystemLib;649pub const SystemLib = link.SystemLib;
650pub const CacheMode = link.CacheMode;
634651
635pub const InitOptions = struct {652pub const InitOptions = struct {
636 zig_lib_directory: Directory,653 zig_lib_directory: Directory,
...@@ -668,6 +685,7 @@ pub const InitOptions = struct {...@@ -668,6 +685,7 @@ pub const InitOptions = struct {
668 /// is externally modified - essentially anything other than zig-cache - then685 /// is externally modified - essentially anything other than zig-cache - then
669 /// this flag would be set to disable this machinery to avoid false positives.686 /// this flag would be set to disable this machinery to avoid false positives.
670 disable_lld_caching: bool = false,687 disable_lld_caching: bool = false,
688 cache_mode: CacheMode = .incremental,
671 object_format: ?std.Target.ObjectFormat = null,689 object_format: ?std.Target.ObjectFormat = null,
672 optimize_mode: std.builtin.Mode = .Debug,690 optimize_mode: std.builtin.Mode = .Debug,
673 keep_source_files_loaded: bool = false,691 keep_source_files_loaded: bool = false,
...@@ -885,6 +903,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -885,6 +903,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
885 break :blk build_options.is_stage1;903 break :blk build_options.is_stage1;
886 };904 };
887905
906 const cache_mode = if (use_stage1 and !options.disable_lld_caching)
907 CacheMode.whole
908 else
909 options.cache_mode;
910
888 // Make a decision on whether to use LLVM or our own backend.911 // Make a decision on whether to use LLVM or our own backend.
889 const use_llvm = build_options.have_llvm and blk: {912 const use_llvm = build_options.have_llvm and blk: {
890 if (options.use_llvm) |explicit|913 if (options.use_llvm) |explicit|
...@@ -1219,39 +1242,75 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1219,39 +1242,75 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1219 // modified between incremental updates.1242 // modified between incremental updates.
1220 var hash = cache.hash;1243 var hash = cache.hash;
12211244
1222 // Here we put the root source file path name, but *not* with addFile. We want the1245 switch (cache_mode) {
1223 // hash to be the same regardless of the contents of the source file, because1246 .incremental => {
1224 // incremental compilation will handle it, but we do want to namespace different1247 // Here we put the root source file path name, but *not* with addFile.
1225 // source file names because they are likely different compilations and therefore this1248 // We want the hash to be the same regardless of the contents of the
1226 // would be likely to cause cache hits.1249 // source file, because incremental compilation will handle it, but we
1227 hash.addBytes(main_pkg.root_src_path);1250 // do want to namespace different source file names because they are
1228 hash.addOptionalBytes(main_pkg.root_src_directory.path);1251 // likely different compilations and therefore this would be likely to
1229 {1252 // cause cache hits.
1230 var local_arena = std.heap.ArenaAllocator.init(gpa);1253 hash.addBytes(main_pkg.root_src_path);
1231 defer local_arena.deinit();1254 hash.addOptionalBytes(main_pkg.root_src_directory.path);
1232 var seen_table = std.AutoHashMap(*Package, void).init(local_arena.allocator());1255 {
1233 try addPackageTableToCacheHash(&hash, &local_arena, main_pkg.table, &seen_table, .path_bytes);1256 var seen_table = std.AutoHashMap(*Package, void).init(arena);
1257 try addPackageTableToCacheHash(&hash, &arena_allocator, main_pkg.table, &seen_table, .path_bytes);
1258 }
1259 },
1260 .whole => {
1261 // In this case, we postpone adding the input source file until
1262 // we create the cache manifest, in update(), because we want to
1263 // track it and packages as files.
1264 },
1234 }1265 }
1266
1267 // Synchronize with other matching comments: ZigOnlyHashStuff
1235 hash.add(valgrind);1268 hash.add(valgrind);
1236 hash.add(single_threaded);1269 hash.add(single_threaded);
1237 hash.add(use_stage1);1270 hash.add(use_stage1);
1238 hash.add(use_llvm);1271 hash.add(use_llvm);
1239 hash.add(dll_export_fns);1272 hash.add(dll_export_fns);
1240 hash.add(options.is_test);1273 hash.add(options.is_test);
1274 hash.add(options.test_evented_io);
1275 hash.addOptionalBytes(options.test_filter);
1276 hash.addOptionalBytes(options.test_name_prefix);
1241 hash.add(options.skip_linker_dependencies);1277 hash.add(options.skip_linker_dependencies);
1242 hash.add(options.parent_compilation_link_libc);1278 hash.add(options.parent_compilation_link_libc);
12431279
1280 // In the case of incremental cache mode, this `zig_cache_artifact_directory`
1281 // is computed based on a hash of non-linker inputs, and it is where all
1282 // build artifacts are stored (even while in-progress).
1283 //
1284 // For whole cache mode, it is still used for builtin.zig so that the file
1285 // path to builtin.zig can remain consistent during a debugging session at
1286 // runtime. However, we don't know where to put outputs from the linker
1287 // or stage1 backend object files until the final cache hash, which is available
1288 // after the compilation is complete.
1289 //
1290 // Therefore, in whole cache mode, we additionally create a temporary cache
1291 // directory for these two kinds of build artifacts, and then rename it
1292 // into place after the final hash is known. However, we don't want
1293 // to create the temporary directory here, because in the case of a cache hit,
1294 // this would have been wasted syscalls to make the directory and then not
1295 // use it (or delete it).
1296 //
1297 // In summary, for whole cache mode, we simulate `-fno-emit-bin` in this
1298 // function, and `zig_cache_artifact_directory` is *wrong* except for builtin.zig,
1299 // and then at the beginning of `update()` when we find out whether we need
1300 // a temporary directory, we patch up all the places that the incorrect
1301 // `zig_cache_artifact_directory` was passed to various components of the compiler.
1302
1244 const digest = hash.final();1303 const digest = hash.final();
1245 const artifact_sub_dir = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });1304 const artifact_sub_dir = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
1246 var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{});1305 var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{});
1247 errdefer artifact_dir.close();1306 errdefer artifact_dir.close();
1248 const zig_cache_artifact_directory: Directory = .{1307 const zig_cache_artifact_directory: Directory = .{
1249 .handle = artifact_dir,1308 .handle = artifact_dir,
1250 .path = if (options.local_cache_directory.path) |p|1309 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),
1251 try std.fs.path.join(arena, &[_][]const u8{ p, artifact_sub_dir })
1252 else
1253 artifact_sub_dir,
1254 };1310 };
1311 log.debug("zig_cache_artifact_directory='{s}' use_stage1={}", .{
1312 zig_cache_artifact_directory.path, use_stage1,
1313 });
12551314
1256 const builtin_pkg = try Package.createWithDir(1315 const builtin_pkg = try Package.createWithDir(
1257 gpa,1316 gpa,
...@@ -1374,6 +1433,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1374,6 +1433,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1374 };1433 };
1375 }1434 }
13761435
1436 switch (cache_mode) {
1437 .whole => break :blk null,
1438 .incremental => {},
1439 }
1440
1377 if (module) |zm| {1441 if (module) |zm| {
1378 break :blk link.Emit{1442 break :blk link.Emit{
1379 .directory = zm.zig_cache_artifact_directory,1443 .directory = zm.zig_cache_artifact_directory,
...@@ -1417,6 +1481,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1417,6 +1481,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1417 };1481 };
1418 }1482 }
14191483
1484 // This is here for the same reason as in `bin_file_emit` above.
1485 switch (cache_mode) {
1486 .whole => break :blk null,
1487 .incremental => {},
1488 }
1489
1420 // Use the same directory as the bin. The CLI already emits an1490 // Use the same directory as the bin. The CLI already emits an
1421 // error if -fno-emit-bin is combined with -femit-implib.1491 // error if -fno-emit-bin is combined with -femit-implib.
1422 break :blk link.Emit{1492 break :blk link.Emit{
...@@ -1425,6 +1495,16 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1425,6 +1495,16 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1425 };1495 };
1426 };1496 };
14271497
1498 // This is so that when doing `CacheMode.whole`, the mechanism in update()
1499 // can use it for communicating the result directory via `bin_file.emit`.
1500 // This is used to distinguish between -fno-emit-bin and -femit-bin
1501 // for `CacheMode.whole`.
1502 // This memory will be overwritten with the real digest in update() but
1503 // the basename will be preserved.
1504 const whole_bin_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_bin);
1505 // Same thing but for implibs.
1506 const whole_implib_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_implib);
1507
1428 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};1508 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};
1429 errdefer system_libs.deinit(gpa);1509 errdefer system_libs.deinit(gpa);
1430 try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len);1510 try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len);
...@@ -1512,7 +1592,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1512,7 +1592,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1512 .skip_linker_dependencies = options.skip_linker_dependencies,1592 .skip_linker_dependencies = options.skip_linker_dependencies,
1513 .parent_compilation_link_libc = options.parent_compilation_link_libc,1593 .parent_compilation_link_libc = options.parent_compilation_link_libc,
1514 .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os,1594 .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os,
1515 .disable_lld_caching = options.disable_lld_caching,1595 .cache_mode = cache_mode,
1596 .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
1516 .subsystem = options.subsystem,1597 .subsystem = options.subsystem,
1517 .is_test = options.is_test,1598 .is_test = options.is_test,
1518 .wasi_exec_model = wasi_exec_model,1599 .wasi_exec_model = wasi_exec_model,
...@@ -1529,6 +1610,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1529,6 +1610,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1529 .local_cache_directory = options.local_cache_directory,1610 .local_cache_directory = options.local_cache_directory,
1530 .global_cache_directory = options.global_cache_directory,1611 .global_cache_directory = options.global_cache_directory,
1531 .bin_file = bin_file,1612 .bin_file = bin_file,
1613 .whole_bin_sub_path = whole_bin_sub_path,
1614 .whole_implib_sub_path = whole_implib_sub_path,
1532 .emit_asm = options.emit_asm,1615 .emit_asm = options.emit_asm,
1533 .emit_llvm_ir = options.emit_llvm_ir,1616 .emit_llvm_ir = options.emit_llvm_ir,
1534 .emit_llvm_bc = options.emit_llvm_bc,1617 .emit_llvm_bc = options.emit_llvm_bc,
...@@ -1593,7 +1676,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1593,7 +1676,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1593 comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});1676 comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
1594 }1677 }
15951678
1596 if (comp.bin_file.options.emit != null and !comp.bin_file.options.skip_linker_dependencies) {1679 const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null;
1680
1681 if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies) {
1597 // If we need to build glibc for the target, add work items for it.1682 // If we need to build glibc for the target, add work items for it.
1598 // We go through the work queue so that building can be done in parallel.1683 // We go through the work queue so that building can be done in parallel.
1599 if (comp.wantBuildGLibCFromSource()) {1684 if (comp.wantBuildGLibCFromSource()) {
...@@ -1698,8 +1783,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1698,8 +1783,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
16981783
1699 if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {1784 if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {
1700 if (is_exe_or_dyn_lib) {1785 if (is_exe_or_dyn_lib) {
1786 log.debug("queuing a job to build compiler_rt_lib", .{});
1701 try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });1787 try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });
1702 } else if (options.output_mode != .Obj) {1788 } else if (options.output_mode != .Obj) {
1789 log.debug("queuing a job to build compiler_rt_obj", .{});
1703 // If build-obj with -fcompiler-rt is requested, that is handled specially1790 // If build-obj with -fcompiler-rt is requested, that is handled specially
1704 // elsewhere. In this case we are making a static library, so we ask1791 // elsewhere. In this case we are making a static library, so we ask
1705 // for a compiler-rt object to put in it.1792 // for a compiler-rt object to put in it.
...@@ -1725,20 +1812,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1725,20 +1812,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1725 return comp;1812 return comp;
1726}1813}
17271814
1728fn releaseStage1Lock(comp: *Compilation) void {
1729 if (comp.stage1_lock) |*lock| {
1730 lock.release();
1731 comp.stage1_lock = null;
1732 }
1733}
1734
1735pub fn destroy(self: *Compilation) void {1815pub fn destroy(self: *Compilation) void {
1736 const optional_module = self.bin_file.options.module;1816 const optional_module = self.bin_file.options.module;
1737 self.bin_file.destroy();1817 self.bin_file.destroy();
1738 if (optional_module) |module| module.deinit();1818 if (optional_module) |module| module.deinit();
17391819
1740 self.releaseStage1Lock();
1741
1742 const gpa = self.gpa;1820 const gpa = self.gpa;
1743 self.work_queue.deinit();1821 self.work_queue.deinit();
1744 self.anon_work_queue.deinit();1822 self.anon_work_queue.deinit();
...@@ -1815,22 +1893,126 @@ pub fn getTarget(self: Compilation) Target {...@@ -1815,22 +1893,126 @@ pub fn getTarget(self: Compilation) Target {
1815 return self.bin_file.options.target;1893 return self.bin_file.options.target;
1816}1894}
18171895
1896fn restorePrevZigCacheArtifactDirectory(comp: *Compilation, directory: *Directory) void {
1897 if (directory.path) |p| comp.gpa.free(p);
1898
1899 // Restore the Module's previous zig_cache_artifact_directory
1900 // This is only for cleanup purposes; Module.deinit calls close
1901 // on the handle of zig_cache_artifact_directory.
1902 if (comp.bin_file.options.module) |module| {
1903 const builtin_pkg = module.main_pkg.table.get("builtin").?;
1904 module.zig_cache_artifact_directory = builtin_pkg.root_src_directory;
1905 }
1906}
1907
1908fn cleanupTmpArtifactDirectory(
1909 comp: *Compilation,
1910 tmp_artifact_directory: *?Directory,
1911 tmp_dir_sub_path: []const u8,
1912) void {
1913 comp.gpa.free(tmp_dir_sub_path);
1914 if (tmp_artifact_directory.*) |*directory| {
1915 directory.handle.close();
1916 restorePrevZigCacheArtifactDirectory(comp, directory);
1917 }
1918}
1919
1818/// Detect changes to source files, perform semantic analysis, and update the output files.1920/// Detect changes to source files, perform semantic analysis, and update the output files.
1819pub fn update(self: *Compilation) !void {1921pub fn update(comp: *Compilation) !void {
1820 const tracy_trace = trace(@src());1922 const tracy_trace = trace(@src());
1821 defer tracy_trace.end();1923 defer tracy_trace.end();
18221924
1823 self.clearMiscFailures();1925 comp.clearMiscFailures();
1926
1927 var man: Cache.Manifest = undefined;
1928 defer if (comp.whole_cache_manifest != null) man.deinit();
1929
1930 var tmp_dir_sub_path: []const u8 = &.{};
1931 var tmp_artifact_directory: ?Directory = null;
1932 defer cleanupTmpArtifactDirectory(comp, &tmp_artifact_directory, tmp_dir_sub_path);
1933
1934 // If using the whole caching strategy, we check for *everything* up front, including
1935 // C source files.
1936 if (comp.bin_file.options.cache_mode == .whole) {
1937 // We are about to obtain this lock, so here we give other processes a chance first.
1938 comp.bin_file.releaseLock();
1939
1940 comp.whole_cache_manifest = &man;
1941 man = comp.cache_parent.obtain();
1942 try comp.addNonIncrementalStuffToCacheManifest(&man);
1943
1944 const is_hit = man.hit() catch |err| {
1945 // TODO properly bubble these up instead of emitting a warning
1946 const i = man.failed_file_index orelse return err;
1947 const file_path = man.files.items[i].path orelse return err;
1948 std.log.warn("{s}: {s}", .{ @errorName(err), file_path });
1949 return err;
1950 };
1951 if (is_hit) {
1952 log.debug("CacheMode.whole cache hit for {s}", .{comp.bin_file.options.root_name});
1953 const digest = man.final();
1954
1955 comp.wholeCacheModeSetBinFilePath(&digest);
1956
1957 assert(comp.bin_file.lock == null);
1958 comp.bin_file.lock = man.toOwnedLock();
1959 return;
1960 }
1961 log.debug("CacheMode.whole cache miss for {s}", .{comp.bin_file.options.root_name});
1962
1963 // Initialize `bin_file.emit` with a temporary Directory so that compilation can
1964 // continue on the same path as incremental, using the temporary Directory.
1965 tmp_artifact_directory = d: {
1966 const s = std.fs.path.sep_str;
1967 const rand_int = std.crypto.random.int(u64);
1968
1969 tmp_dir_sub_path = try std.fmt.allocPrint(comp.gpa, "tmp" ++ s ++ "{x}", .{rand_int});
1970
1971 const path = try comp.local_cache_directory.join(comp.gpa, &.{tmp_dir_sub_path});
1972 errdefer comp.gpa.free(path);
1973
1974 const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});
1975 errdefer handle.close();
1976
1977 break :d .{
1978 .path = path,
1979 .handle = handle,
1980 };
1981 };
1982
1983 // This updates the output directory for stage1 backend and linker outputs.
1984 if (comp.bin_file.options.module) |module| {
1985 module.zig_cache_artifact_directory = tmp_artifact_directory.?;
1986 }
1987
1988 // This resets the link.File to operate as if we called openPath() in create()
1989 // instead of simulating -fno-emit-bin.
1990 var options = comp.bin_file.options.move();
1991 if (comp.whole_bin_sub_path) |sub_path| {
1992 options.emit = .{
1993 .directory = tmp_artifact_directory.?,
1994 .sub_path = std.fs.path.basename(sub_path),
1995 };
1996 }
1997 if (comp.whole_implib_sub_path) |sub_path| {
1998 options.implib_emit = .{
1999 .directory = tmp_artifact_directory.?,
2000 .sub_path = std.fs.path.basename(sub_path),
2001 };
2002 }
2003 comp.bin_file.destroy();
2004 comp.bin_file = try link.File.openPath(comp.gpa, options);
2005 }
18242006
1825 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.2007 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
1826 // Add a Job for each C object.2008 // Add a Job for each C object.
1827 try self.c_object_work_queue.ensureUnusedCapacity(self.c_object_table.count());2009 try comp.c_object_work_queue.ensureUnusedCapacity(comp.c_object_table.count());
1828 for (self.c_object_table.keys()) |key| {2010 for (comp.c_object_table.keys()) |key| {
1829 self.c_object_work_queue.writeItemAssumeCapacity(key);2011 comp.c_object_work_queue.writeItemAssumeCapacity(key);
1830 }2012 }
18312013
1832 const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_stage1;2014 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
1833 if (self.bin_file.options.module) |module| {2015 if (comp.bin_file.options.module) |module| {
1834 module.compile_log_text.shrinkAndFree(module.gpa, 0);2016 module.compile_log_text.shrinkAndFree(module.gpa, 0);
1835 module.generation += 1;2017 module.generation += 1;
18362018
...@@ -1845,7 +2027,7 @@ pub fn update(self: *Compilation) !void {...@@ -1845,7 +2027,7 @@ pub fn update(self: *Compilation) !void {
1845 // import_table here.2027 // import_table here.
1846 // Likewise, in the case of `zig test`, the test runner is the root source file,2028 // Likewise, in the case of `zig test`, the test runner is the root source file,
1847 // and so there is nothing to import the main file.2029 // and so there is nothing to import the main file.
1848 if (use_stage1 or self.bin_file.options.is_test) {2030 if (use_stage1 or comp.bin_file.options.is_test) {
1849 _ = try module.importPkg(module.main_pkg);2031 _ = try module.importPkg(module.main_pkg);
1850 }2032 }
18512033
...@@ -1854,34 +2036,34 @@ pub fn update(self: *Compilation) !void {...@@ -1854,34 +2036,34 @@ pub fn update(self: *Compilation) !void {
1854 // to update it.2036 // to update it.
1855 // We still want AstGen work items for stage1 so that we expose compile errors2037 // We still want AstGen work items for stage1 so that we expose compile errors
1856 // that are implemented in stage2 but not stage1.2038 // that are implemented in stage2 but not stage1.
1857 try self.astgen_work_queue.ensureUnusedCapacity(module.import_table.count());2039 try comp.astgen_work_queue.ensureUnusedCapacity(module.import_table.count());
1858 for (module.import_table.values()) |value| {2040 for (module.import_table.values()) |value| {
1859 self.astgen_work_queue.writeItemAssumeCapacity(value);2041 comp.astgen_work_queue.writeItemAssumeCapacity(value);
1860 }2042 }
18612043
1862 if (!use_stage1) {2044 if (!use_stage1) {
1863 // Put a work item in for checking if any files used with `@embedFile` changed.2045 // Put a work item in for checking if any files used with `@embedFile` changed.
1864 {2046 {
1865 try self.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count());2047 try comp.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count());
1866 var it = module.embed_table.iterator();2048 var it = module.embed_table.iterator();
1867 while (it.next()) |entry| {2049 while (it.next()) |entry| {
1868 const embed_file = entry.value_ptr.*;2050 const embed_file = entry.value_ptr.*;
1869 self.embed_file_work_queue.writeItemAssumeCapacity(embed_file);2051 comp.embed_file_work_queue.writeItemAssumeCapacity(embed_file);
1870 }2052 }
1871 }2053 }
18722054
1873 try self.work_queue.writeItem(.{ .analyze_pkg = std_pkg });2055 try comp.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
1874 if (self.bin_file.options.is_test) {2056 if (comp.bin_file.options.is_test) {
1875 try self.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });2057 try comp.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });
1876 }2058 }
1877 }2059 }
1878 }2060 }
18792061
1880 try self.performAllTheWork();2062 try comp.performAllTheWork();
18812063
1882 if (!use_stage1) {2064 if (!use_stage1) {
1883 if (self.bin_file.options.module) |module| {2065 if (comp.bin_file.options.module) |module| {
1884 if (self.bin_file.options.is_test and self.totalErrorCount() == 0) {2066 if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
1885 // The `test_functions` decl has been intentionally postponed until now,2067 // The `test_functions` decl has been intentionally postponed until now,
1886 // at which point we must populate it with the list of test functions that2068 // at which point we must populate it with the list of test functions that
1887 // have been discovered and not filtered out.2069 // have been discovered and not filtered out.
...@@ -1910,41 +2092,241 @@ pub fn update(self: *Compilation) !void {...@@ -1910,41 +2092,241 @@ pub fn update(self: *Compilation) !void {
1910 }2092 }
1911 }2093 }
19122094
1913 if (self.totalErrorCount() != 0) {2095 if (comp.totalErrorCount() != 0) {
1914 // Skip flushing.2096 // Skip flushing and keep source files loaded for error reporting.
1915 self.link_error_flags = .{};2097 comp.link_error_flags = .{};
1916 return;2098 return;
1917 }2099 }
19182100
1919 // This is needed before reading the error flags.2101 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and
1920 try self.bin_file.flush(self);2102 // -femit-asm to handle, in the case of C objects.
1921 self.link_error_flags = self.bin_file.errorFlags();2103 comp.emitOthers();
2104
2105 if (comp.whole_cache_manifest != null) {
2106 const digest = man.final();
19222107
1923 if (!use_stage1) {2108 // Rename the temporary directory into place.
1924 if (self.bin_file.options.module) |module| {2109 var directory = tmp_artifact_directory.?;
1925 try link.File.C.flushEmitH(module);2110 tmp_artifact_directory = null;
2111
2112 directory.handle.close();
2113 defer restorePrevZigCacheArtifactDirectory(comp, &directory);
2114
2115 const o_sub_path = try std.fs.path.join(comp.gpa, &[_][]const u8{ "o", &digest });
2116 defer comp.gpa.free(o_sub_path);
2117
2118 try comp.bin_file.renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);
2119 comp.wholeCacheModeSetBinFilePath(&digest);
2120
2121 // This is intentionally sandwiched between renameTmpIntoCache() and writeManifest().
2122 if (comp.bin_file.options.module) |module| {
2123 // We need to set the zig_cache_artifact_directory for -femit-asm, -femit-llvm-ir,
2124 // etc to know where to output to.
2125 var artifact_dir = try comp.local_cache_directory.handle.openDir(o_sub_path, .{});
2126 defer artifact_dir.close();
2127
2128 var dir_path = try comp.local_cache_directory.join(comp.gpa, &.{o_sub_path});
2129 defer comp.gpa.free(dir_path);
2130
2131 module.zig_cache_artifact_directory = .{
2132 .handle = artifact_dir,
2133 .path = dir_path,
2134 };
2135
2136 try comp.flush();
2137 } else {
2138 try comp.flush();
1926 }2139 }
1927 }
19282140
1929 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and2141 // Failure here only means an unnecessary cache miss.
1930 // -femit-asm to handle, in the case of C objects.2142 man.writeManifest() catch |err| {
1931 self.emitOthers();2143 log.warn("failed to write cache manifest: {s}", .{@errorName(err)});
2144 };
2145
2146 assert(comp.bin_file.lock == null);
2147 comp.bin_file.lock = man.toOwnedLock();
2148 } else {
2149 try comp.flush();
2150 }
19322151
1933 // If there are any errors, we anticipate the source files being loaded2152 // Unload all source files to save memory.
1934 // to report error messages. Otherwise we unload all source files to save memory.
1935 // The ZIR needs to stay loaded in memory because (1) Decl objects contain references2153 // The ZIR needs to stay loaded in memory because (1) Decl objects contain references
1936 // to it, and (2) generic instantiations, comptime calls, inline calls will need2154 // to it, and (2) generic instantiations, comptime calls, inline calls will need
1937 // to reference the ZIR.2155 // to reference the ZIR.
1938 if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) {2156 if (!comp.keep_source_files_loaded) {
1939 if (self.bin_file.options.module) |module| {2157 if (comp.bin_file.options.module) |module| {
1940 for (module.import_table.values()) |file| {2158 for (module.import_table.values()) |file| {
1941 file.unloadTree(self.gpa);2159 file.unloadTree(comp.gpa);
1942 file.unloadSource(self.gpa);2160 file.unloadSource(comp.gpa);
1943 }2161 }
1944 }2162 }
1945 }2163 }
1946}2164}
19472165
2166fn flush(comp: *Compilation) !void {
2167 try comp.bin_file.flush(comp); // This is needed before reading the error flags.
2168 comp.link_error_flags = comp.bin_file.errorFlags();
2169
2170 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
2171 if (!use_stage1) {
2172 if (comp.bin_file.options.module) |module| {
2173 try link.File.C.flushEmitH(module);
2174 }
2175 }
2176}
2177
2178/// Communicate the output binary location to parent Compilations.
2179fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_digest_len]u8) void {
2180 const digest_start = 2; // "o/[digest]/[basename]"
2181
2182 if (comp.whole_bin_sub_path) |sub_path| {
2183 mem.copy(u8, sub_path[digest_start..], digest);
2184
2185 comp.bin_file.options.emit = .{
2186 .directory = comp.local_cache_directory,
2187 .sub_path = sub_path,
2188 };
2189 }
2190
2191 if (comp.whole_implib_sub_path) |sub_path| {
2192 mem.copy(u8, sub_path[digest_start..], digest);
2193
2194 comp.bin_file.options.implib_emit = .{
2195 .directory = comp.local_cache_directory,
2196 .sub_path = sub_path,
2197 };
2198 }
2199}
2200
2201fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemory}!?[]u8 {
2202 const emit = opt_emit orelse return null;
2203 if (emit.directory != null) return null;
2204 const s = std.fs.path.sep_str;
2205 const format = "o" ++ s ++ ("x" ** Cache.hex_digest_len) ++ s ++ "{s}";
2206 return try std.fmt.allocPrint(arena, format, .{emit.basename});
2207}
2208
2209/// This is only observed at compile-time and used to emit a compile error
2210/// to remind the programmer to update multiple related pieces of code that
2211/// are in different locations. Bump this number when adding or deleting
2212/// anything from the link cache manifest.
2213pub const link_hash_implementation_version = 1;
2214
2215fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
2216 const gpa = comp.gpa;
2217 const target = comp.getTarget();
2218
2219 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
2220 defer arena_allocator.deinit();
2221 const arena = arena_allocator.allocator();
2222
2223 comptime assert(link_hash_implementation_version == 1);
2224
2225 if (comp.bin_file.options.module) |mod| {
2226 const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
2227 mod.main_pkg.root_src_path,
2228 });
2229 _ = try man.addFile(main_zig_file, null);
2230 {
2231 var seen_table = std.AutoHashMap(*Package, void).init(arena);
2232
2233 // Skip builtin.zig; it is useless as an input, and we don't want to have to
2234 // write it before checking for a cache hit.
2235 const builtin_pkg = mod.main_pkg.table.get("builtin").?;
2236 try seen_table.put(builtin_pkg, {});
2237
2238 try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.main_pkg.table, &seen_table, .{ .files = man });
2239 }
2240
2241 // Synchronize with other matching comments: ZigOnlyHashStuff
2242 man.hash.add(comp.bin_file.options.valgrind);
2243 man.hash.add(comp.bin_file.options.single_threaded);
2244 man.hash.add(comp.bin_file.options.use_stage1);
2245 man.hash.add(comp.bin_file.options.use_llvm);
2246 man.hash.add(comp.bin_file.options.dll_export_fns);
2247 man.hash.add(comp.bin_file.options.is_test);
2248 man.hash.add(comp.test_evented_io);
2249 man.hash.addOptionalBytes(comp.test_filter);
2250 man.hash.addOptionalBytes(comp.test_name_prefix);
2251 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
2252 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
2253 man.hash.add(mod.emit_h != null);
2254 }
2255
2256 try man.addOptionalFile(comp.bin_file.options.linker_script);
2257 try man.addOptionalFile(comp.bin_file.options.version_script);
2258 try man.addListOfFiles(comp.bin_file.options.objects);
2259
2260 for (comp.c_object_table.keys()) |key| {
2261 _ = try man.addFile(key.src.src_path, null);
2262 man.hash.addListOfBytes(key.src.extra_flags);
2263 }
2264
2265 man.hash.addOptionalEmitLoc(comp.emit_asm);
2266 man.hash.addOptionalEmitLoc(comp.emit_llvm_ir);
2267 man.hash.addOptionalEmitLoc(comp.emit_llvm_bc);
2268 man.hash.addOptionalEmitLoc(comp.emit_analysis);
2269 man.hash.addOptionalEmitLoc(comp.emit_docs);
2270
2271 man.hash.addListOfBytes(comp.clang_argv);
2272
2273 man.hash.addOptional(comp.bin_file.options.stack_size_override);
2274 man.hash.addOptional(comp.bin_file.options.image_base_override);
2275 man.hash.addOptional(comp.bin_file.options.gc_sections);
2276 man.hash.add(comp.bin_file.options.eh_frame_hdr);
2277 man.hash.add(comp.bin_file.options.emit_relocs);
2278 man.hash.add(comp.bin_file.options.rdynamic);
2279 man.hash.addListOfBytes(comp.bin_file.options.lib_dirs);
2280 man.hash.addListOfBytes(comp.bin_file.options.rpath_list);
2281 man.hash.add(comp.bin_file.options.each_lib_rpath);
2282 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
2283 man.hash.add(comp.bin_file.options.z_nodelete);
2284 man.hash.add(comp.bin_file.options.z_notext);
2285 man.hash.add(comp.bin_file.options.z_defs);
2286 man.hash.add(comp.bin_file.options.z_origin);
2287 man.hash.add(comp.bin_file.options.z_noexecstack);
2288 man.hash.add(comp.bin_file.options.z_now);
2289 man.hash.add(comp.bin_file.options.z_relro);
2290 man.hash.add(comp.bin_file.options.include_compiler_rt);
2291 if (comp.bin_file.options.link_libc) {
2292 man.hash.add(comp.bin_file.options.libc_installation != null);
2293 if (comp.bin_file.options.libc_installation) |libc_installation| {
2294 man.hash.addBytes(libc_installation.crt_dir.?);
2295 if (target.abi == .msvc) {
2296 man.hash.addBytes(libc_installation.msvc_lib_dir.?);
2297 man.hash.addBytes(libc_installation.kernel32_lib_dir.?);
2298 }
2299 }
2300 man.hash.addOptionalBytes(comp.bin_file.options.dynamic_linker);
2301 }
2302 man.hash.addOptionalBytes(comp.bin_file.options.soname);
2303 man.hash.addOptional(comp.bin_file.options.version);
2304 link.hashAddSystemLibs(&man.hash, comp.bin_file.options.system_libs);
2305 man.hash.addOptional(comp.bin_file.options.allow_shlib_undefined);
2306 man.hash.add(comp.bin_file.options.bind_global_refs_locally);
2307 man.hash.add(comp.bin_file.options.tsan);
2308 man.hash.addOptionalBytes(comp.bin_file.options.sysroot);
2309 man.hash.add(comp.bin_file.options.linker_optimization);
2310
2311 // WASM specific stuff
2312 man.hash.add(comp.bin_file.options.import_memory);
2313 man.hash.addOptional(comp.bin_file.options.initial_memory);
2314 man.hash.addOptional(comp.bin_file.options.max_memory);
2315 man.hash.addOptional(comp.bin_file.options.global_base);
2316
2317 // Mach-O specific stuff
2318 man.hash.addListOfBytes(comp.bin_file.options.framework_dirs);
2319 man.hash.addListOfBytes(comp.bin_file.options.frameworks);
2320
2321 // COFF specific stuff
2322 man.hash.addOptional(comp.bin_file.options.subsystem);
2323 man.hash.add(comp.bin_file.options.tsaware);
2324 man.hash.add(comp.bin_file.options.nxcompat);
2325 man.hash.add(comp.bin_file.options.dynamicbase);
2326 man.hash.addOptional(comp.bin_file.options.major_subsystem_version);
2327 man.hash.addOptional(comp.bin_file.options.minor_subsystem_version);
2328}
2329
1948fn emitOthers(comp: *Compilation) void {2330fn emitOthers(comp: *Compilation) void {
1949 if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or2331 if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or
1950 comp.c_object_table.count() == 0)2332 comp.c_object_table.count() == 0)
...@@ -2988,7 +3370,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -2988,7 +3370,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
29883370
2989 const dep_basename = std.fs.path.basename(out_dep_path);3371 const dep_basename = std.fs.path.basename(out_dep_path);
2990 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);3372 try man.addDepFilePost(zig_cache_tmp_dir, dep_basename);
2991 if (build_options.is_stage1 and comp.bin_file.options.use_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);3373 if (comp.whole_cache_manifest) |whole_cache_manifest| {
3374 try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
3375 }
29923376
2993 const digest = man.final();3377 const digest = man.final();
2994 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });3378 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
...@@ -3351,13 +3735,13 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P...@@ -3351,13 +3735,13 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
3351 };3735 };
3352}3736}
33533737
3354pub fn tmpFilePath(comp: *Compilation, arena: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {3738pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
3355 const s = std.fs.path.sep_str;3739 const s = std.fs.path.sep_str;
3356 const rand_int = std.crypto.random.int(u64);3740 const rand_int = std.crypto.random.int(u64);
3357 if (comp.local_cache_directory.path) |p| {3741 if (comp.local_cache_directory.path) |p| {
3358 return std.fmt.allocPrint(arena, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });3742 return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
3359 } else {3743 } else {
3360 return std.fmt.allocPrint(arena, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });3744 return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });
3361 }3745 }
3362}3746}
33633747
...@@ -4424,6 +4808,7 @@ fn buildOutputFromZig(...@@ -4424,6 +4808,7 @@ fn buildOutputFromZig(
4424 .global_cache_directory = comp.global_cache_directory,4808 .global_cache_directory = comp.global_cache_directory,
4425 .local_cache_directory = comp.global_cache_directory,4809 .local_cache_directory = comp.global_cache_directory,
4426 .zig_lib_directory = comp.zig_lib_directory,4810 .zig_lib_directory = comp.zig_lib_directory,
4811 .cache_mode = .whole,
4427 .target = target,4812 .target = target,
4428 .root_name = root_name,4813 .root_name = root_name,
4429 .main_pkg = &main_pkg,4814 .main_pkg = &main_pkg,
...@@ -4501,10 +4886,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -4501,10 +4886,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
4501 mod.main_pkg.root_src_path,4886 mod.main_pkg.root_src_path,
4502 });4887 });
4503 const zig_lib_dir = comp.zig_lib_directory.path.?;4888 const zig_lib_dir = comp.zig_lib_directory.path.?;
4504 const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"});
4505 const target = comp.getTarget();4889 const target = comp.getTarget();
4506 const id_symlink_basename = "stage1.id";
4507 const libs_txt_basename = "libs.txt";
45084890
4509 // The include_compiler_rt stored in the bin file options here means that we need4891 // The include_compiler_rt stored in the bin file options here means that we need
4510 // compiler-rt symbols *somehow*. However, in the context of using the stage1 backend4892 // compiler-rt symbols *somehow*. However, in the context of using the stage1 backend
...@@ -4516,115 +4898,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -4516,115 +4898,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
4516 const include_compiler_rt = comp.bin_file.options.output_mode == .Obj and4898 const include_compiler_rt = comp.bin_file.options.output_mode == .Obj and
4517 comp.bin_file.options.include_compiler_rt;4899 comp.bin_file.options.include_compiler_rt;
45184900
4519 // We are about to obtain this lock, so here we give other processes a chance first.
4520 comp.releaseStage1Lock();
4521
4522 // Unlike with the self-hosted Zig module, stage1 does not support incremental compilation,
4523 // so we input all the zig source files into the cache hash system. We're going to keep
4524 // the artifact directory the same, however, so we take the same strategy as linking
4525 // does where we have a file which specifies the hash of the output directory so that we can
4526 // skip the expensive compilation step if the hash matches.
4527 var man = comp.cache_parent.obtain();
4528 defer man.deinit();
4529
4530 _ = try man.addFile(main_zig_file, null);
4531 {
4532 var seen_table = std.AutoHashMap(*Package, void).init(arena_allocator.allocator());
4533 try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.main_pkg.table, &seen_table, .{ .files = &man });
4534 }
4535 man.hash.add(comp.bin_file.options.valgrind);
4536 man.hash.add(comp.bin_file.options.single_threaded);
4537 man.hash.add(target.os.getVersionRange());
4538 man.hash.add(comp.bin_file.options.dll_export_fns);
4539 man.hash.add(comp.bin_file.options.function_sections);
4540 man.hash.add(include_compiler_rt);
4541 man.hash.add(comp.bin_file.options.is_test);
4542 man.hash.add(comp.bin_file.options.emit != null);
4543 man.hash.add(mod.emit_h != null);
4544 if (mod.emit_h) |emit_h| {
4545 man.hash.addEmitLoc(emit_h.loc);
4546 }
4547 man.hash.addOptionalEmitLoc(comp.emit_asm);
4548 man.hash.addOptionalEmitLoc(comp.emit_llvm_ir);
4549 man.hash.addOptionalEmitLoc(comp.emit_llvm_bc);
4550 man.hash.addOptionalEmitLoc(comp.emit_analysis);
4551 man.hash.addOptionalEmitLoc(comp.emit_docs);
4552 man.hash.add(comp.test_evented_io);
4553 man.hash.addOptionalBytes(comp.test_filter);
4554 man.hash.addOptionalBytes(comp.test_name_prefix);
4555 man.hash.addListOfBytes(comp.clang_argv);
4556
4557 // Capture the state in case we come back from this branch where the hash doesn't match.
4558 const prev_hash_state = man.hash.peekBin();
4559 const input_file_count = man.files.items.len;
4560
4561 const hit = man.hit() catch |err| {
4562 const i = man.failed_file_index orelse return err;
4563 const file_path = man.files.items[i].path orelse return err;
4564 fatal("unable to build stage1 zig object: {s}: {s}", .{ @errorName(err), file_path });
4565 };
4566 if (hit) {
4567 const digest = man.final();
4568
4569 // We use an extra hex-encoded byte here to store some flags.
4570 var prev_digest_buf: [digest.len + 2]u8 = undefined;
4571 const prev_digest: []u8 = Cache.readSmallFile(
4572 directory.handle,
4573 id_symlink_basename,
4574 &prev_digest_buf,
4575 ) catch |err| blk: {
4576 log.debug("stage1 {s} new_digest={s} error: {s}", .{
4577 mod.main_pkg.root_src_path,
4578 std.fmt.fmtSliceHexLower(&digest),
4579 @errorName(err),
4580 });
4581 // Handle this as a cache miss.
4582 break :blk prev_digest_buf[0..0];
4583 };
4584 if (prev_digest.len >= digest.len + 2) hit: {
4585 if (!mem.eql(u8, prev_digest[0..digest.len], &digest))
4586 break :hit;
4587
4588 log.debug("stage1 {s} digest={s} match - skipping invocation", .{
4589 mod.main_pkg.root_src_path,
4590 std.fmt.fmtSliceHexLower(&digest),
4591 });
4592 var flags_bytes: [1]u8 = undefined;
4593 _ = std.fmt.hexToBytes(&flags_bytes, prev_digest[digest.len..]) catch {
4594 log.warn("bad cache stage1 digest: '{s}'", .{std.fmt.fmtSliceHexLower(prev_digest)});
4595 break :hit;
4596 };
4597
4598 if (directory.handle.readFileAlloc(comp.gpa, libs_txt_basename, 10 * 1024 * 1024)) |libs_txt| {
4599 var it = mem.tokenize(u8, libs_txt, "\n");
4600 while (it.next()) |lib_name| {
4601 try comp.stage1AddLinkLib(lib_name);
4602 }
4603 } else |err| switch (err) {
4604 error.FileNotFound => {}, // That's OK, it just means 0 libs.
4605 else => {
4606 log.warn("unable to read cached list of link libs: {s}", .{@errorName(err)});
4607 break :hit;
4608 },
4609 }
4610 comp.stage1_lock = man.toOwnedLock();
4611 mod.stage1_flags = @bitCast(@TypeOf(mod.stage1_flags), flags_bytes[0]);
4612 return;
4613 }
4614 log.debug("stage1 {s} prev_digest={s} new_digest={s}", .{
4615 mod.main_pkg.root_src_path,
4616 std.fmt.fmtSliceHexLower(prev_digest),
4617 std.fmt.fmtSliceHexLower(&digest),
4618 });
4619 man.unhit(prev_hash_state, input_file_count);
4620 }
4621
4622 // We are about to change the output file to be different, so we invalidate the build hash now.
4623 directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
4624 error.FileNotFound => {},
4625 else => |e| return e,
4626 };
4627
4628 const stage2_target = try arena.create(stage1.Stage2Target);4901 const stage2_target = try arena.create(stage1.Stage2Target);
4629 stage2_target.* = .{4902 stage2_target.* = .{
4630 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch4903 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
...@@ -4637,9 +4910,9 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -4637,9 +4910,9 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
4637 .llvm_target_abi = if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,4910 .llvm_target_abi = if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
4638 };4911 };
46394912
4640 comp.stage1_cache_manifest = &man;
4641
4642 const main_pkg_path = mod.main_pkg.root_src_directory.path orelse "";4913 const main_pkg_path = mod.main_pkg.root_src_directory.path orelse "";
4914 const builtin_pkg = mod.main_pkg.table.get("builtin").?;
4915 const builtin_zig_path = try builtin_pkg.root_src_directory.join(arena, &.{builtin_pkg.root_src_path});
46434916
4644 const stage1_module = stage1.create(4917 const stage1_module = stage1.create(
4645 @enumToInt(comp.bin_file.options.optimize_mode),4918 @enumToInt(comp.bin_file.options.optimize_mode),
...@@ -4740,19 +5013,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -4740,19 +5013,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
4740 .have_dllmain_crt_startup = false,5013 .have_dllmain_crt_startup = false,
4741 };5014 };
47425015
4743 const inferred_lib_start_index = comp.bin_file.options.system_libs.count();
4744 stage1_module.build_object();5016 stage1_module.build_object();
47455017
4746 if (comp.bin_file.options.system_libs.count() > inferred_lib_start_index) {
4747 // We need to save the inferred link libs to the cache, otherwise if we get a cache hit
4748 // next time we will be missing these libs.
4749 var libs_txt = std.ArrayList(u8).init(arena);
4750 for (comp.bin_file.options.system_libs.keys()[inferred_lib_start_index..]) |key| {
4751 try libs_txt.writer().print("{s}\n", .{key});
4752 }
4753 try directory.handle.writeFile(libs_txt_basename, libs_txt.items);
4754 }
4755
4756 mod.stage1_flags = .{5018 mod.stage1_flags = .{
4757 .have_c_main = stage1_module.have_c_main,5019 .have_c_main = stage1_module.have_c_main,
4758 .have_winmain = stage1_module.have_winmain,5020 .have_winmain = stage1_module.have_winmain,
...@@ -4763,34 +5025,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -4763,34 +5025,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
4763 };5025 };
47645026
4765 stage1_module.destroy();5027 stage1_module.destroy();
4766
4767 const digest = man.final();
4768
4769 // Update the small file with the digest. If it fails we can continue; it only
4770 // means that the next invocation will have an unnecessary cache miss.
4771 const stage1_flags_byte = @bitCast(u8, mod.stage1_flags);
4772 log.debug("stage1 {s} final digest={s} flags={x}", .{
4773 mod.main_pkg.root_src_path, std.fmt.fmtSliceHexLower(&digest), stage1_flags_byte,
4774 });
4775 var digest_plus_flags: [digest.len + 2]u8 = undefined;
4776 digest_plus_flags[0..digest.len].* = digest;
4777 assert(std.fmt.formatIntBuf(digest_plus_flags[digest.len..], stage1_flags_byte, 16, .lower, .{
4778 .width = 2,
4779 .fill = '0',
4780 }) == 2);
4781 log.debug("saved digest + flags: '{s}' (byte = {}) have_winmain_crt_startup={}", .{
4782 digest_plus_flags, stage1_flags_byte, mod.stage1_flags.have_winmain_crt_startup,
4783 });
4784 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest_plus_flags) catch |err| {
4785 log.warn("failed to save stage1 hash digest file: {s}", .{@errorName(err)});
4786 };
4787 // Failure here only means an unnecessary cache miss.
4788 man.writeManifest() catch |err| {
4789 log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});
4790 };
4791 // We hang on to this lock so that the output file path can be used without
4792 // other processes clobbering it.
4793 comp.stage1_lock = man.toOwnedLock();
4794}5028}
47955029
4796fn stage1LocPath(arena: Allocator, opt_loc: ?EmitLoc, cache_directory: Directory) ![]const u8 {5030fn stage1LocPath(arena: Allocator, opt_loc: ?EmitLoc, cache_directory: Directory) ![]const u8 {
...@@ -4862,6 +5096,7 @@ pub fn build_crt_file(...@@ -4862,6 +5096,7 @@ pub fn build_crt_file(
4862 .local_cache_directory = comp.global_cache_directory,5096 .local_cache_directory = comp.global_cache_directory,
4863 .global_cache_directory = comp.global_cache_directory,5097 .global_cache_directory = comp.global_cache_directory,
4864 .zig_lib_directory = comp.zig_lib_directory,5098 .zig_lib_directory = comp.zig_lib_directory,
5099 .cache_mode = .whole,
4865 .target = target,5100 .target = target,
4866 .root_name = root_name,5101 .root_name = root_name,
4867 .main_pkg = null,5102 .main_pkg = null,
src/Module.zig+114-45
...@@ -33,7 +33,7 @@ const build_options = @import("build_options");...@@ -33,7 +33,7 @@ const build_options = @import("build_options");
33gpa: Allocator,33gpa: Allocator,
34comp: *Compilation,34comp: *Compilation,
3535
36/// Where our incremental compilation metadata serialization will go.36/// Where build artifacts and incremental compilation metadata serialization go.
37zig_cache_artifact_directory: Compilation.Directory,37zig_cache_artifact_directory: Compilation.Directory,
38/// Pointer to externally managed resource.38/// Pointer to externally managed resource.
39root_pkg: *Package,39root_pkg: *Package,
...@@ -1463,11 +1463,7 @@ pub const File = struct {...@@ -1463,11 +1463,7 @@ pub const File = struct {
1463 /// Whether this is populated depends on `source_loaded`.1463 /// Whether this is populated depends on `source_loaded`.
1464 source: [:0]const u8,1464 source: [:0]const u8,
1465 /// Whether this is populated depends on `status`.1465 /// Whether this is populated depends on `status`.
1466 stat_size: u64,1466 stat: Cache.File.Stat,
1467 /// Whether this is populated depends on `status`.
1468 stat_inode: std.fs.File.INode,
1469 /// Whether this is populated depends on `status`.
1470 stat_mtime: i128,
1471 /// Whether this is populated or not depends on `tree_loaded`.1467 /// Whether this is populated or not depends on `tree_loaded`.
1472 tree: Ast,1468 tree: Ast,
1473 /// Whether this is populated or not depends on `zir_loaded`.1469 /// Whether this is populated or not depends on `zir_loaded`.
...@@ -1535,8 +1531,16 @@ pub const File = struct {...@@ -1535,8 +1531,16 @@ pub const File = struct {
1535 file.* = undefined;1531 file.* = undefined;
1536 }1532 }
15371533
1538 pub fn getSource(file: *File, gpa: Allocator) ![:0]const u8 {1534 pub const Source = struct {
1539 if (file.source_loaded) return file.source;1535 bytes: [:0]const u8,
1536 stat: Cache.File.Stat,
1537 };
1538
1539 pub fn getSource(file: *File, gpa: Allocator) !Source {
1540 if (file.source_loaded) return Source{
1541 .bytes = file.source,
1542 .stat = file.stat,
1543 };
15401544
1541 const root_dir_path = file.pkg.root_src_directory.path orelse ".";1545 const root_dir_path = file.pkg.root_src_directory.path orelse ".";
1542 log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{1546 log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{
...@@ -1565,14 +1569,21 @@ pub const File = struct {...@@ -1565,14 +1569,21 @@ pub const File = struct {
15651569
1566 file.source = source;1570 file.source = source;
1567 file.source_loaded = true;1571 file.source_loaded = true;
1568 return source;1572 return Source{
1573 .bytes = source,
1574 .stat = .{
1575 .size = stat.size,
1576 .inode = stat.inode,
1577 .mtime = stat.mtime,
1578 },
1579 };
1569 }1580 }
15701581
1571 pub fn getTree(file: *File, gpa: Allocator) !*const Ast {1582 pub fn getTree(file: *File, gpa: Allocator) !*const Ast {
1572 if (file.tree_loaded) return &file.tree;1583 if (file.tree_loaded) return &file.tree;
15731584
1574 const source = try file.getSource(gpa);1585 const source = try file.getSource(gpa);
1575 file.tree = try std.zig.parse(gpa, source);1586 file.tree = try std.zig.parse(gpa, source.bytes);
1576 file.tree_loaded = true;1587 file.tree_loaded = true;
1577 return &file.tree;1588 return &file.tree;
1578 }1589 }
...@@ -1631,9 +1642,7 @@ pub const EmbedFile = struct {...@@ -1631,9 +1642,7 @@ pub const EmbedFile = struct {
1631 /// Memory is stored in gpa, owned by EmbedFile.1642 /// Memory is stored in gpa, owned by EmbedFile.
1632 sub_file_path: []const u8,1643 sub_file_path: []const u8,
1633 bytes: [:0]const u8,1644 bytes: [:0]const u8,
1634 stat_size: u64,1645 stat: Cache.File.Stat,
1635 stat_inode: std.fs.File.INode,
1636 stat_mtime: i128,
1637 /// Package that this file is a part of, managed externally.1646 /// Package that this file is a part of, managed externally.
1638 pkg: *Package,1647 pkg: *Package,
1639 /// The Decl that was created from the `@embedFile` to own this resource.1648 /// The Decl that was created from the `@embedFile` to own this resource.
...@@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2704 keep_zir = true;2713 keep_zir = true;
2705 file.zir = zir;2714 file.zir = zir;
2706 file.zir_loaded = true;2715 file.zir_loaded = true;
2707 file.stat_size = header.stat_size;2716 file.stat = .{
2708 file.stat_inode = header.stat_inode;2717 .size = header.stat_size,
2709 file.stat_mtime = header.stat_mtime;2718 .inode = header.stat_inode,
2719 .mtime = header.stat_mtime,
2720 };
2710 file.status = .success_zir;2721 file.status = .success_zir;
2711 log.debug("AstGen cached success: {s}", .{file.sub_file_path});2722 log.debug("AstGen cached success: {s}", .{file.sub_file_path});
27122723
...@@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2724 },2735 },
2725 .parse_failure, .astgen_failure, .success_zir => {2736 .parse_failure, .astgen_failure, .success_zir => {
2726 const unchanged_metadata =2737 const unchanged_metadata =
2727 stat.size == file.stat_size and2738 stat.size == file.stat.size and
2728 stat.mtime == file.stat_mtime and2739 stat.mtime == file.stat.mtime and
2729 stat.inode == file.stat_inode;2740 stat.inode == file.stat.inode;
27302741
2731 if (unchanged_metadata) {2742 if (unchanged_metadata) {
2732 log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});2743 log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
...@@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2787 if (amt != stat.size)2798 if (amt != stat.size)
2788 return error.UnexpectedEndOfFile;2799 return error.UnexpectedEndOfFile;
27892800
2790 file.stat_size = stat.size;2801 file.stat = .{
2791 file.stat_inode = stat.inode;2802 .size = stat.size,
2792 file.stat_mtime = stat.mtime;2803 .inode = stat.inode,
2804 .mtime = stat.mtime,
2805 };
2793 file.source = source;2806 file.source = source;
2794 file.source_loaded = true;2807 file.source_loaded = true;
27952808
...@@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void {...@@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void {
30693082
3070 try writeBuiltinFile(file, builtin_pkg);3083 try writeBuiltinFile(file, builtin_pkg);
3071 } else {3084 } else {
3072 file.stat_size = stat.size;3085 file.stat = .{
3073 file.stat_inode = stat.inode;3086 .size = stat.size,
3074 file.stat_mtime = stat.mtime;3087 .inode = stat.inode,
3088 .mtime = stat.mtime,
3089 };
3075 }3090 }
3076 } else |err| switch (err) {3091 } else |err| switch (err) {
3077 error.BadPathName => unreachable, // it's always "builtin.zig"3092 error.BadPathName => unreachable, // it's always "builtin.zig"
...@@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {...@@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
3099 try af.file.writeAll(file.source);3114 try af.file.writeAll(file.source);
3100 try af.finish();3115 try af.finish();
31013116
3102 file.stat_size = file.source.len;3117 file.stat = .{
3103 file.stat_inode = 0; // dummy value3118 .size = file.source.len,
3104 file.stat_mtime = 0; // dummy value3119 .inode = 0, // dummy value
3120 .mtime = 0, // dummy value
3121 };
3105}3122}
31063123
3107pub fn mapOldZirToNew(3124pub fn mapOldZirToNew(
...@@ -3380,6 +3397,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3380,6 +3397,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3380 error.OutOfMemory => return error.OutOfMemory,3397 error.OutOfMemory => return error.OutOfMemory,
3381 error.AnalysisFail => {},3398 error.AnalysisFail => {},
3382 }3399 }
3400
3401 if (mod.comp.whole_cache_manifest) |man| {
3402 const source = file.getSource(gpa) catch |err| {
3403 try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)});
3404 return error.AnalysisFail;
3405 };
3406 const resolved_path = try file.pkg.root_src_directory.join(gpa, &.{
3407 file.sub_file_path,
3408 });
3409 errdefer gpa.free(resolved_path);
3410
3411 try man.addFilePostContents(resolved_path, source.bytes, source.stat);
3412 }
3383 } else {3413 } else {
3384 new_decl.analysis = .file_failure;3414 new_decl.analysis = .file_failure;
3385 }3415 }
...@@ -3710,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {...@@ -3710,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
3710 .source_loaded = false,3740 .source_loaded = false,
3711 .tree_loaded = false,3741 .tree_loaded = false,
3712 .zir_loaded = false,3742 .zir_loaded = false,
3713 .stat_size = undefined,3743 .stat = undefined,
3714 .stat_inode = undefined,
3715 .stat_mtime = undefined,
3716 .tree = undefined,3744 .tree = undefined,
3717 .zir = undefined,3745 .zir = undefined,
3718 .status = .never_loaded,3746 .status = .never_loaded,
...@@ -3780,9 +3808,7 @@ pub fn importFile(...@@ -3780,9 +3808,7 @@ pub fn importFile(
3780 .source_loaded = false,3808 .source_loaded = false,
3781 .tree_loaded = false,3809 .tree_loaded = false,
3782 .zir_loaded = false,3810 .zir_loaded = false,
3783 .stat_size = undefined,3811 .stat = undefined,
3784 .stat_inode = undefined,
3785 .stat_mtime = undefined,
3786 .tree = undefined,3812 .tree = undefined,
3787 .zir = undefined,3813 .zir = undefined,
3788 .status = .never_loaded,3814 .status = .never_loaded,
...@@ -3827,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb...@@ -3827,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
3827 var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{});3853 var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{});
3828 defer file.close();3854 defer file.close();
38293855
3830 const stat = try file.stat();3856 const actual_stat = try file.stat();
3831 const size_usize = try std.math.cast(usize, stat.size);3857 const stat: Cache.File.Stat = .{
3858 .size = actual_stat.size,
3859 .inode = actual_stat.inode,
3860 .mtime = actual_stat.mtime,
3861 };
3862 const size_usize = try std.math.cast(usize, actual_stat.size);
3832 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);3863 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
3833 errdefer gpa.free(bytes);3864 errdefer gpa.free(bytes);
38343865
...@@ -3836,14 +3867,18 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb...@@ -3836,14 +3867,18 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
3836 resolved_root_path, resolved_path, sub_file_path, rel_file_path,3867 resolved_root_path, resolved_path, sub_file_path, rel_file_path,
3837 });3868 });
38383869
3870 if (mod.comp.whole_cache_manifest) |man| {
3871 const copied_resolved_path = try gpa.dupe(u8, resolved_path);
3872 errdefer gpa.free(copied_resolved_path);
3873 try man.addFilePostContents(copied_resolved_path, bytes, stat);
3874 }
3875
3839 keep_resolved_path = true; // It's now owned by embed_table.3876 keep_resolved_path = true; // It's now owned by embed_table.
3840 gop.value_ptr.* = new_file;3877 gop.value_ptr.* = new_file;
3841 new_file.* = .{3878 new_file.* = .{
3842 .sub_file_path = sub_file_path,3879 .sub_file_path = sub_file_path,
3843 .bytes = bytes,3880 .bytes = bytes,
3844 .stat_size = stat.size,3881 .stat = stat,
3845 .stat_inode = stat.inode,
3846 .stat_mtime = stat.mtime,
3847 .pkg = cur_file.pkg,3882 .pkg = cur_file.pkg,
3848 .owner_decl = undefined, // Set by Sema immediately after this function returns.3883 .owner_decl = undefined, // Set by Sema immediately after this function returns.
3849 };3884 };
...@@ -3857,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {...@@ -3857,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
3857 const stat = try file.stat();3892 const stat = try file.stat();
38583893
3859 const unchanged_metadata =3894 const unchanged_metadata =
3860 stat.size == embed_file.stat_size and3895 stat.size == embed_file.stat.size and
3861 stat.mtime == embed_file.stat_mtime and3896 stat.mtime == embed_file.stat.mtime and
3862 stat.inode == embed_file.stat_inode;3897 stat.inode == embed_file.stat.inode;
38633898
3864 if (unchanged_metadata) return;3899 if (unchanged_metadata) return;
38653900
...@@ -3868,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {...@@ -3868,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
3868 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);3903 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
3869 gpa.free(embed_file.bytes);3904 gpa.free(embed_file.bytes);
3870 embed_file.bytes = bytes;3905 embed_file.bytes = bytes;
3871 embed_file.stat_size = stat.size;3906 embed_file.stat = .{
3872 embed_file.stat_mtime = stat.mtime;3907 .size = stat.size,
3873 embed_file.stat_inode = stat.inode;3908 .mtime = stat.mtime,
3909 .inode = stat.inode,
3910 };
38743911
3875 mod.comp.mutex.lock();3912 mod.comp.mutex.lock();
3876 defer mod.comp.mutex.unlock();3913 defer mod.comp.mutex.unlock();
...@@ -5001,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void {...@@ -5001,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void {
5001 },5038 },
5002 };5039 };
5003}5040}
5041
5042fn reportRetryableFileError(
5043 mod: *Module,
5044 file: *File,
5045 comptime format: []const u8,
5046 args: anytype,
5047) error{OutOfMemory}!void {
5048 file.status = .retryable_failure;
5049
5050 const err_msg = try ErrorMsg.create(
5051 mod.gpa,
5052 .{
5053 .file_scope = file,
5054 .parent_decl_node = 0,
5055 .lazy = .entire_file,
5056 },
5057 format,
5058 args,
5059 );
5060 errdefer err_msg.destroy(mod.gpa);
5061
5062 mod.comp.mutex.lock();
5063 defer mod.comp.mutex.unlock();
5064
5065 const gop = try mod.failed_files.getOrPut(mod.gpa, file);
5066 if (gop.found_existing) {
5067 if (gop.value_ptr.*) |old_err_msg| {
5068 old_err_msg.destroy(mod.gpa);
5069 }
5070 }
5071 gop.value_ptr.* = err_msg;
5072}
src/Sema.zig+12-11
...@@ -14680,11 +14680,11 @@ fn resolvePeerTypes(...@@ -14680,11 +14680,11 @@ fn resolvePeerTypes(
14680 instructions: []Air.Inst.Ref,14680 instructions: []Air.Inst.Ref,
14681 candidate_srcs: Module.PeerTypeCandidateSrc,14681 candidate_srcs: Module.PeerTypeCandidateSrc,
14682) !Type {14682) !Type {
14683 if (instructions.len == 0)14683 switch (instructions.len) {
14684 return Type.initTag(.noreturn);14684 0 => return Type.initTag(.noreturn),
1468514685 1 => return sema.typeOf(instructions[0]),
14686 if (instructions.len == 1)14686 else => {},
14687 return sema.typeOf(instructions[0]);14687 }
1468814688
14689 const target = sema.mod.getTarget();14689 const target = sema.mod.getTarget();
1469014690
...@@ -14714,13 +14714,14 @@ fn resolvePeerTypes(...@@ -14714,13 +14714,14 @@ fn resolvePeerTypes(
14714 continue;14714 continue;
14715 },14715 },
14716 .Int => {14716 .Int => {
14717 if (chosen_ty.isSignedInt() == candidate_ty.isSignedInt()) {14717 const chosen_info = chosen_ty.intInfo(target);
14718 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {14718 const candidate_info = candidate_ty.intInfo(target);
14719 chosen = candidate;14719
14720 chosen_i = candidate_i + 1;14720 if (chosen_info.bits < candidate_info.bits) {
14721 }14721 chosen = candidate;
14722 continue;14722 chosen_i = candidate_i + 1;
14723 }14723 }
14724 continue;
14724 },14725 },
14725 .Pointer => if (chosen_ty.ptrSize() == .C) continue,14726 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
14726 else => {},14727 else => {},
src/codegen/llvm.zig+6-4
...@@ -324,10 +324,12 @@ pub const Object = struct {...@@ -324,10 +324,12 @@ pub const Object = struct {
324 const mod = comp.bin_file.options.module.?;324 const mod = comp.bin_file.options.module.?;
325 const cache_dir = mod.zig_cache_artifact_directory;325 const cache_dir = mod.zig_cache_artifact_directory;
326326
327 const emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|327 const emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| blk: {
328 try emit.directory.joinZ(arena, &[_][]const u8{self.sub_path})328 const full_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});
329 else329 break :blk try std.fs.path.joinZ(arena, &.{
330 null;330 std.fs.path.dirname(full_out_path).?, self.sub_path,
331 });
332 } else null;
331333
332 const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir);334 const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir);
333 const emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir);335 const emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir);
src/glibc.zig+1
...@@ -1062,6 +1062,7 @@ fn buildSharedLib(...@@ -1062,6 +1062,7 @@ fn buildSharedLib(
1062 .local_cache_directory = zig_cache_directory,1062 .local_cache_directory = zig_cache_directory,
1063 .global_cache_directory = comp.global_cache_directory,1063 .global_cache_directory = comp.global_cache_directory,
1064 .zig_lib_directory = comp.zig_lib_directory,1064 .zig_lib_directory = comp.zig_lib_directory,
1065 .cache_mode = .whole,
1065 .target = comp.getTarget(),1066 .target = comp.getTarget(),
1066 .root_name = lib.name,1067 .root_name = lib.name,
1067 .main_pkg = null,1068 .main_pkg = null,
src/libcxx.zig+8-8
...@@ -177,6 +177,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -177,6 +177,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
177 .local_cache_directory = comp.global_cache_directory,177 .local_cache_directory = comp.global_cache_directory,
178 .global_cache_directory = comp.global_cache_directory,178 .global_cache_directory = comp.global_cache_directory,
179 .zig_lib_directory = comp.zig_lib_directory,179 .zig_lib_directory = comp.zig_lib_directory,
180 .cache_mode = .whole,
180 .target = target,181 .target = target,
181 .root_name = root_name,182 .root_name = root_name,
182 .main_pkg = null,183 .main_pkg = null,
...@@ -218,10 +219,9 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -218,10 +219,9 @@ pub fn buildLibCXX(comp: *Compilation) !void {
218219
219 assert(comp.libcxx_static_lib == null);220 assert(comp.libcxx_static_lib == null);
220 comp.libcxx_static_lib = Compilation.CRTFile{221 comp.libcxx_static_lib = Compilation.CRTFile{
221 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(222 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
222 comp.gpa,223 sub_compilation.bin_file.options.emit.?.sub_path,
223 &[_][]const u8{basename},224 }),
224 ),
225 .lock = sub_compilation.bin_file.toOwnedLock(),225 .lock = sub_compilation.bin_file.toOwnedLock(),
226 };226 };
227}227}
...@@ -309,6 +309,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {...@@ -309,6 +309,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
309 .local_cache_directory = comp.global_cache_directory,309 .local_cache_directory = comp.global_cache_directory,
310 .global_cache_directory = comp.global_cache_directory,310 .global_cache_directory = comp.global_cache_directory,
311 .zig_lib_directory = comp.zig_lib_directory,311 .zig_lib_directory = comp.zig_lib_directory,
312 .cache_mode = .whole,
312 .target = target,313 .target = target,
313 .root_name = root_name,314 .root_name = root_name,
314 .main_pkg = null,315 .main_pkg = null,
...@@ -350,10 +351,9 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {...@@ -350,10 +351,9 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
350351
351 assert(comp.libcxxabi_static_lib == null);352 assert(comp.libcxxabi_static_lib == null);
352 comp.libcxxabi_static_lib = Compilation.CRTFile{353 comp.libcxxabi_static_lib = Compilation.CRTFile{
353 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(354 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
354 comp.gpa,355 sub_compilation.bin_file.options.emit.?.sub_path,
355 &[_][]const u8{basename},356 }),
356 ),
357 .lock = sub_compilation.bin_file.toOwnedLock(),357 .lock = sub_compilation.bin_file.toOwnedLock(),
358 };358 };
359}359}
src/libtsan.zig+4-4
...@@ -199,6 +199,7 @@ pub fn buildTsan(comp: *Compilation) !void {...@@ -199,6 +199,7 @@ pub fn buildTsan(comp: *Compilation) !void {
199 .local_cache_directory = comp.global_cache_directory,199 .local_cache_directory = comp.global_cache_directory,
200 .global_cache_directory = comp.global_cache_directory,200 .global_cache_directory = comp.global_cache_directory,
201 .zig_lib_directory = comp.zig_lib_directory,201 .zig_lib_directory = comp.zig_lib_directory,
202 .cache_mode = .whole,
202 .target = target,203 .target = target,
203 .root_name = root_name,204 .root_name = root_name,
204 .main_pkg = null,205 .main_pkg = null,
...@@ -237,10 +238,9 @@ pub fn buildTsan(comp: *Compilation) !void {...@@ -237,10 +238,9 @@ pub fn buildTsan(comp: *Compilation) !void {
237238
238 assert(comp.tsan_static_lib == null);239 assert(comp.tsan_static_lib == null);
239 comp.tsan_static_lib = Compilation.CRTFile{240 comp.tsan_static_lib = Compilation.CRTFile{
240 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(241 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
241 comp.gpa,242 sub_compilation.bin_file.options.emit.?.sub_path,
242 &[_][]const u8{basename},243 }),
243 ),
244 .lock = sub_compilation.bin_file.toOwnedLock(),244 .lock = sub_compilation.bin_file.toOwnedLock(),
245 };245 };
246}246}
src/libunwind.zig+5-4
...@@ -101,6 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {...@@ -101,6 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
101 .local_cache_directory = comp.global_cache_directory,101 .local_cache_directory = comp.global_cache_directory,
102 .global_cache_directory = comp.global_cache_directory,102 .global_cache_directory = comp.global_cache_directory,
103 .zig_lib_directory = comp.zig_lib_directory,103 .zig_lib_directory = comp.zig_lib_directory,
104 .cache_mode = .whole,
104 .target = target,105 .target = target,
105 .root_name = root_name,106 .root_name = root_name,
106 .main_pkg = null,107 .main_pkg = null,
...@@ -141,11 +142,11 @@ pub fn buildStaticLib(comp: *Compilation) !void {...@@ -141,11 +142,11 @@ pub fn buildStaticLib(comp: *Compilation) !void {
141 try sub_compilation.updateSubCompilation();142 try sub_compilation.updateSubCompilation();
142143
143 assert(comp.libunwind_static_lib == null);144 assert(comp.libunwind_static_lib == null);
145
144 comp.libunwind_static_lib = Compilation.CRTFile{146 comp.libunwind_static_lib = Compilation.CRTFile{
145 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(147 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
146 comp.gpa,148 sub_compilation.bin_file.options.emit.?.sub_path,
147 &[_][]const u8{basename},149 }),
148 ),
149 .lock = sub_compilation.bin_file.toOwnedLock(),150 .lock = sub_compilation.bin_file.toOwnedLock(),
150 };151 };
151}152}
src/link.zig+59-14
...@@ -22,6 +22,8 @@ pub const SystemLib = struct {...@@ -22,6 +22,8 @@ pub const SystemLib = struct {
22 needed: bool = false,22 needed: bool = false,
23};23};
2424
25pub const CacheMode = enum { incremental, whole };
26
25pub fn hashAddSystemLibs(27pub fn hashAddSystemLibs(
26 hh: *Cache.HashHelper,28 hh: *Cache.HashHelper,
27 hm: std.StringArrayHashMapUnmanaged(SystemLib),29 hm: std.StringArrayHashMapUnmanaged(SystemLib),
...@@ -44,10 +46,9 @@ pub const Emit = struct {...@@ -44,10 +46,9 @@ pub const Emit = struct {
44};46};
4547
46pub const Options = struct {48pub const Options = struct {
47 /// This is `null` when -fno-emit-bin is used. When `openPath` or `flush` is called,49 /// This is `null` when `-fno-emit-bin` is used.
48 /// it will have already been null-checked.
49 emit: ?Emit,50 emit: ?Emit,
50 /// This is `null` not building a Windows DLL, or when -fno-emit-implib is used.51 /// This is `null` not building a Windows DLL, or when `-fno-emit-implib` is used.
51 implib_emit: ?Emit,52 implib_emit: ?Emit,
52 target: std.Target,53 target: std.Target,
53 output_mode: std.builtin.OutputMode,54 output_mode: std.builtin.OutputMode,
...@@ -70,6 +71,7 @@ pub const Options = struct {...@@ -70,6 +71,7 @@ pub const Options = struct {
70 entry_addr: ?u64 = null,71 entry_addr: ?u64 = null,
71 stack_size_override: ?u64,72 stack_size_override: ?u64,
72 image_base_override: ?u64,73 image_base_override: ?u64,
74 cache_mode: CacheMode,
73 include_compiler_rt: bool,75 include_compiler_rt: bool,
74 /// Set to `true` to omit debug info.76 /// Set to `true` to omit debug info.
75 strip: bool,77 strip: bool,
...@@ -165,6 +167,12 @@ pub const Options = struct {...@@ -165,6 +167,12 @@ pub const Options = struct {
165 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {167 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
166 return if (options.use_lld) .Obj else options.output_mode;168 return if (options.use_lld) .Obj else options.output_mode;
167 }169 }
170
171 pub fn move(self: *Options) Options {
172 const copied_state = self.*;
173 self.system_libs = .{};
174 return copied_state;
175 }
168};176};
169177
170pub const File = struct {178pub const File = struct {
...@@ -628,6 +636,36 @@ pub const File = struct {...@@ -628,6 +636,36 @@ pub const File = struct {
628 }636 }
629 }637 }
630638
639 /// This function is called by the frontend before flush(). It communicates that
640 /// `options.bin_file.emit` directory needs to be renamed from
641 /// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`.
642 /// The frontend would like to simply perform a file system rename, however,
643 /// some linker backends care about the file paths of the objects they are linking.
644 /// So this function call tells linker backends to rename the paths of object files
645 /// to observe the new directory path.
646 /// Linker backends which do not have this requirement can fall back to the simple
647 /// implementation at the bottom of this function.
648 /// This function is only called when CacheMode is `whole`.
649 pub fn renameTmpIntoCache(
650 base: *File,
651 cache_directory: Compilation.Directory,
652 tmp_dir_sub_path: []const u8,
653 o_sub_path: []const u8,
654 ) !void {
655 // So far, none of the linker backends need to respond to this event, however,
656 // it makes sense that they might want to. So we leave this mechanism here
657 // for now. Once the linker backends get more mature, if it turns out this
658 // is not needed we can refactor this into having the frontend do the rename
659 // directly, and remove this function from link.zig.
660 _ = base;
661 try std.fs.rename(
662 cache_directory.handle,
663 tmp_dir_sub_path,
664 cache_directory.handle,
665 o_sub_path,
666 );
667 }
668
631 pub fn linkAsArchive(base: *File, comp: *Compilation) !void {669 pub fn linkAsArchive(base: *File, comp: *Compilation) !void {
632 const tracy = trace(@src());670 const tracy = trace(@src());
633 defer tracy.end();671 defer tracy.end();
...@@ -637,9 +675,11 @@ pub const File = struct {...@@ -637,9 +675,11 @@ pub const File = struct {
637 const arena = arena_allocator.allocator();675 const arena = arena_allocator.allocator();
638676
639 const directory = base.options.emit.?.directory; // Just an alias to make it shorter to type.677 const directory = base.options.emit.?.directory; // Just an alias to make it shorter to type.
678 const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path});
679 const full_out_path_z = try arena.dupeZ(u8, full_out_path);
640680
641 // If there is no Zig code to compile, then we should skip flushing the output file because it681 // If there is no Zig code to compile, then we should skip flushing the output file
642 // will not be part of the linker line anyway.682 // because it will not be part of the linker line anyway.
643 const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: {683 const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: {
644 const use_stage1 = build_options.is_stage1 and base.options.use_stage1;684 const use_stage1 = build_options.is_stage1 and base.options.use_stage1;
645 if (use_stage1) {685 if (use_stage1) {
...@@ -648,20 +688,28 @@ pub const File = struct {...@@ -648,20 +688,28 @@ pub const File = struct {
648 .target = base.options.target,688 .target = base.options.target,
649 .output_mode = .Obj,689 .output_mode = .Obj,
650 });690 });
651 const o_directory = module.zig_cache_artifact_directory;691 switch (base.options.cache_mode) {
652 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});692 .incremental => break :blk try module.zig_cache_artifact_directory.join(
653 break :blk full_obj_path;693 arena,
694 &[_][]const u8{obj_basename},
695 ),
696 .whole => break :blk try fs.path.join(arena, &.{
697 fs.path.dirname(full_out_path_z).?, obj_basename,
698 }),
699 }
654 }700 }
655 if (base.options.object_format == .macho) {701 if (base.options.object_format == .macho) {
656 try base.cast(MachO).?.flushObject(comp);702 try base.cast(MachO).?.flushObject(comp);
657 } else {703 } else {
658 try base.flushModule(comp);704 try base.flushModule(comp);
659 }705 }
660 const obj_basename = base.intermediary_basename.?;706 break :blk try fs.path.join(arena, &.{
661 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});707 fs.path.dirname(full_out_path_z).?, base.intermediary_basename.?,
662 break :blk full_obj_path;708 });
663 } else null;709 } else null;
664710
711 log.debug("module_obj_path={s}", .{if (module_obj_path) |s| s else "(null)"});
712
665 const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt)713 const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt)
666 comp.compiler_rt_obj.?.full_object_path714 comp.compiler_rt_obj.?.full_object_path
667 else715 else
...@@ -734,9 +782,6 @@ pub const File = struct {...@@ -734,9 +782,6 @@ pub const File = struct {
734 object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));782 object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));
735 }783 }
736784
737 const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path});
738 const full_out_path_z = try arena.dupeZ(u8, full_out_path);
739
740 if (base.options.verbose_link) {785 if (base.options.verbose_link) {
741 std.debug.print("ar rcs {s}", .{full_out_path_z});786 std.debug.print("ar rcs {s}", .{full_out_path_z});
742 for (object_files.items) |arg| {787 for (object_files.items) |arg| {
src/link/Coff.zig+16-7
...@@ -880,6 +880,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -880,6 +880,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
880 const arena = arena_allocator.allocator();880 const arena = arena_allocator.allocator();
881881
882 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.882 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
883 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
883884
884 // If there is no Zig code to compile, then we should skip flushing the output file because it885 // If there is no Zig code to compile, then we should skip flushing the output file because it
885 // will not be part of the linker line anyway.886 // will not be part of the linker line anyway.
...@@ -891,15 +892,22 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -891,15 +892,22 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
891 .target = self.base.options.target,892 .target = self.base.options.target,
892 .output_mode = .Obj,893 .output_mode = .Obj,
893 });894 });
894 const o_directory = module.zig_cache_artifact_directory;895 switch (self.base.options.cache_mode) {
895 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});896 .incremental => break :blk try module.zig_cache_artifact_directory.join(
896 break :blk full_obj_path;897 arena,
898 &[_][]const u8{obj_basename},
899 ),
900 .whole => break :blk try fs.path.join(arena, &.{
901 fs.path.dirname(full_out_path).?, obj_basename,
902 }),
903 }
897 }904 }
898905
899 try self.flushModule(comp);906 try self.flushModule(comp);
900 const obj_basename = self.base.intermediary_basename.?;907
901 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});908 break :blk try fs.path.join(arena, &.{
902 break :blk full_obj_path;909 fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
910 });
903 } else null;911 } else null;
904912
905 const is_lib = self.base.options.output_mode == .Lib;913 const is_lib = self.base.options.output_mode == .Lib;
...@@ -920,6 +928,8 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -920,6 +928,8 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
920 man = comp.cache_parent.obtain();928 man = comp.cache_parent.obtain();
921 self.base.releaseLock();929 self.base.releaseLock();
922930
931 comptime assert(Compilation.link_hash_implementation_version == 1);
932
923 try man.addListOfFiles(self.base.options.objects);933 try man.addListOfFiles(self.base.options.objects);
924 for (comp.c_object_table.keys()) |key| {934 for (comp.c_object_table.keys()) |key| {
925 _ = try man.addFile(key.status.success.object_path, null);935 _ = try man.addFile(key.status.success.object_path, null);
...@@ -976,7 +986,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -976,7 +986,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
976 };986 };
977 }987 }
978988
979 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
980 if (self.base.options.output_mode == .Obj) {989 if (self.base.options.output_mode == .Obj) {
981 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy990 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
982 // here. TODO: think carefully about how we can avoid this redundant operation when doing991 // here. TODO: think carefully about how we can avoid this redundant operation when doing
src/link/Elf.zig+20-8
...@@ -297,6 +297,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {...@@ -297,6 +297,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
297 else => return error.UnsupportedELFArchitecture,297 else => return error.UnsupportedELFArchitecture,
298 };298 };
299 const self = try gpa.create(Elf);299 const self = try gpa.create(Elf);
300 errdefer gpa.destroy(self);
300 self.* = .{301 self.* = .{
301 .base = .{302 .base = .{
302 .tag = .elf,303 .tag = .elf,
...@@ -306,6 +307,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {...@@ -306,6 +307,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
306 },307 },
307 .ptr_width = ptr_width,308 .ptr_width = ptr_width,
308 };309 };
310 // TODO get rid of the sub_path parameter to LlvmObject.create
311 // and create the llvm_object here. Also openPath needs to
312 // not override this field or there will be a memory leak.
309 return self;313 return self;
310}314}
311315
...@@ -1298,6 +1302,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1298,6 +1302,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1298 const arena = arena_allocator.allocator();1302 const arena = arena_allocator.allocator();
12991303
1300 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.1304 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
1305 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
13011306
1302 // If there is no Zig code to compile, then we should skip flushing the output file because it1307 // If there is no Zig code to compile, then we should skip flushing the output file because it
1303 // will not be part of the linker line anyway.1308 // will not be part of the linker line anyway.
...@@ -1309,15 +1314,22 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1309,15 +1314,22 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1309 .target = self.base.options.target,1314 .target = self.base.options.target,
1310 .output_mode = .Obj,1315 .output_mode = .Obj,
1311 });1316 });
1312 const o_directory = module.zig_cache_artifact_directory;1317 switch (self.base.options.cache_mode) {
1313 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});1318 .incremental => break :blk try module.zig_cache_artifact_directory.join(
1314 break :blk full_obj_path;1319 arena,
1320 &[_][]const u8{obj_basename},
1321 ),
1322 .whole => break :blk try fs.path.join(arena, &.{
1323 fs.path.dirname(full_out_path).?, obj_basename,
1324 }),
1325 }
1315 }1326 }
13161327
1317 try self.flushModule(comp);1328 try self.flushModule(comp);
1318 const obj_basename = self.base.intermediary_basename.?;1329
1319 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});1330 break :blk try fs.path.join(arena, &.{
1320 break :blk full_obj_path;1331 fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
1332 });
1321 } else null;1333 } else null;
13221334
1323 const is_obj = self.base.options.output_mode == .Obj;1335 const is_obj = self.base.options.output_mode == .Obj;
...@@ -1357,6 +1369,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1357,6 +1369,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1357 // We are about to obtain this lock, so here we give other processes a chance first.1369 // We are about to obtain this lock, so here we give other processes a chance first.
1358 self.base.releaseLock();1370 self.base.releaseLock();
13591371
1372 comptime assert(Compilation.link_hash_implementation_version == 1);
1373
1360 try man.addOptionalFile(self.base.options.linker_script);1374 try man.addOptionalFile(self.base.options.linker_script);
1361 try man.addOptionalFile(self.base.options.version_script);1375 try man.addOptionalFile(self.base.options.version_script);
1362 try man.addListOfFiles(self.base.options.objects);1376 try man.addListOfFiles(self.base.options.objects);
...@@ -1432,8 +1446,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1432,8 +1446,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1432 };1446 };
1433 }1447 }
14341448
1435 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
1436
1437 // Due to a deficiency in LLD, we need to special-case BPF to a simple file copy when generating1449 // Due to a deficiency in LLD, we need to special-case BPF to a simple file copy when generating
1438 // relocatables. Normally, we would expect `lld -r` to work. However, because LLD wants to resolve1450 // relocatables. Normally, we would expect `lld -r` to work. However, because LLD wants to resolve
1439 // BPF relocations which it shouldn't, it fails before even generating the relocatable.1451 // BPF relocations which it shouldn't, it fails before even generating the relocatable.
src/link/MachO.zig+18-7
...@@ -423,6 +423,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -423,6 +423,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
423 const arena = arena_allocator.allocator();423 const arena = arena_allocator.allocator();
424424
425 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.425 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
426 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
426427
427 // If there is no Zig code to compile, then we should skip flushing the output file because it428 // If there is no Zig code to compile, then we should skip flushing the output file because it
428 // will not be part of the linker line anyway.429 // will not be part of the linker line anyway.
...@@ -433,15 +434,24 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -433,15 +434,24 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
433 .target = self.base.options.target,434 .target = self.base.options.target,
434 .output_mode = .Obj,435 .output_mode = .Obj,
435 });436 });
436 const o_directory = module.zig_cache_artifact_directory;437 switch (self.base.options.cache_mode) {
437 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});438 .incremental => break :blk try module.zig_cache_artifact_directory.join(
438 break :blk full_obj_path;439 arena,
440 &[_][]const u8{obj_basename},
441 ),
442 .whole => break :blk try fs.path.join(arena, &.{
443 fs.path.dirname(full_out_path).?, obj_basename,
444 }),
445 }
439 }446 }
440447
441 const obj_basename = self.base.intermediary_basename orelse break :blk null;448 const obj_basename = self.base.intermediary_basename orelse break :blk null;
449
442 try self.flushObject(comp);450 try self.flushObject(comp);
443 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});451
444 break :blk full_obj_path;452 break :blk try fs.path.join(arena, &.{
453 fs.path.dirname(full_out_path).?, obj_basename,
454 });
445 } else null;455 } else null;
446456
447 const is_lib = self.base.options.output_mode == .Lib;457 const is_lib = self.base.options.output_mode == .Lib;
...@@ -466,6 +476,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -466,6 +476,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
466 // We are about to obtain this lock, so here we give other processes a chance first.476 // We are about to obtain this lock, so here we give other processes a chance first.
467 self.base.releaseLock();477 self.base.releaseLock();
468478
479 comptime assert(Compilation.link_hash_implementation_version == 1);
480
469 try man.addListOfFiles(self.base.options.objects);481 try man.addListOfFiles(self.base.options.objects);
470 for (comp.c_object_table.keys()) |key| {482 for (comp.c_object_table.keys()) |key| {
471 _ = try man.addFile(key.status.success.object_path, null);483 _ = try man.addFile(key.status.success.object_path, null);
...@@ -532,7 +544,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -532,7 +544,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
532 else => |e| return e,544 else => |e| return e,
533 };545 };
534 }546 }
535 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
536547
537 if (self.base.options.output_mode == .Obj) {548 if (self.base.options.output_mode == .Obj) {
538 // LLD's MachO driver does not support the equivalent of `-r` so we do a simple file copy549 // LLD's MachO driver does not support the equivalent of `-r` so we do a simple file copy
...@@ -1267,7 +1278,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const...@@ -1267,7 +1278,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
1267 for (files) |file_name| {1278 for (files) |file_name| {
1268 const full_path = full_path: {1279 const full_path = full_path: {
1269 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;1280 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
1270 const path = try std.fs.realpath(file_name, &buffer);1281 const path = try fs.realpath(file_name, &buffer);
1271 break :full_path try self.base.allocator.dupe(u8, path);1282 break :full_path try self.base.allocator.dupe(u8, path);
1272 };1283 };
1273 defer self.base.allocator.free(full_path);1284 defer self.base.allocator.free(full_path);
src/link/Wasm.zig+16-8
...@@ -1050,6 +1050,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1050,6 +1050,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1050 const arena = arena_allocator.allocator();1050 const arena = arena_allocator.allocator();
10511051
1052 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.1052 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
1053 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
10531054
1054 // If there is no Zig code to compile, then we should skip flushing the output file because it1055 // If there is no Zig code to compile, then we should skip flushing the output file because it
1055 // will not be part of the linker line anyway.1056 // will not be part of the linker line anyway.
...@@ -1061,15 +1062,22 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1061,15 +1062,22 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1061 .target = self.base.options.target,1062 .target = self.base.options.target,
1062 .output_mode = .Obj,1063 .output_mode = .Obj,
1063 });1064 });
1064 const o_directory = module.zig_cache_artifact_directory;1065 switch (self.base.options.cache_mode) {
1065 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});1066 .incremental => break :blk try module.zig_cache_artifact_directory.join(
1066 break :blk full_obj_path;1067 arena,
1068 &[_][]const u8{obj_basename},
1069 ),
1070 .whole => break :blk try fs.path.join(arena, &.{
1071 fs.path.dirname(full_out_path).?, obj_basename,
1072 }),
1073 }
1067 }1074 }
10681075
1069 try self.flushModule(comp);1076 try self.flushModule(comp);
1070 const obj_basename = self.base.intermediary_basename.?;1077
1071 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});1078 break :blk try fs.path.join(arena, &.{
1072 break :blk full_obj_path;1079 fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
1080 });
1073 } else null;1081 } else null;
10741082
1075 const is_obj = self.base.options.output_mode == .Obj;1083 const is_obj = self.base.options.output_mode == .Obj;
...@@ -1094,6 +1102,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1094,6 +1102,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1094 // We are about to obtain this lock, so here we give other processes a chance first.1102 // We are about to obtain this lock, so here we give other processes a chance first.
1095 self.base.releaseLock();1103 self.base.releaseLock();
10961104
1105 comptime assert(Compilation.link_hash_implementation_version == 1);
1106
1097 try man.addListOfFiles(self.base.options.objects);1107 try man.addListOfFiles(self.base.options.objects);
1098 for (comp.c_object_table.keys()) |key| {1108 for (comp.c_object_table.keys()) |key| {
1099 _ = try man.addFile(key.status.success.object_path, null);1109 _ = try man.addFile(key.status.success.object_path, null);
...@@ -1141,8 +1151,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -1141,8 +1151,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
1141 };1151 };
1142 }1152 }
11431153
1144 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
1145
1146 if (self.base.options.output_mode == .Obj) {1154 if (self.base.options.output_mode == .Obj) {
1147 // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy1155 // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy
1148 // here. TODO: think carefully about how we can avoid this redundant operation when doing1156 // here. TODO: think carefully about how we can avoid this redundant operation when doing
src/main.zig+34-34
...@@ -2564,9 +2564,7 @@ fn buildOutputType(...@@ -2564,9 +2564,7 @@ fn buildOutputType(
25642564
2565 switch (emit_bin) {2565 switch (emit_bin) {
2566 .no => break :blk .none,2566 .no => break :blk .none,
2567 .yes_default_path => break :blk .{2567 .yes_default_path => break :blk .print_emit_bin_dir_path,
2568 .print = comp.bin_file.options.emit.?.directory.path orelse ".",
2569 },
2570 .yes => |full_path| break :blk .{ .update = full_path },2568 .yes => |full_path| break :blk .{ .update = full_path },
2571 .yes_a_out => break :blk .{ .update = a_out_basename },2569 .yes_a_out => break :blk .{ .update = a_out_basename },
2572 }2570 }
...@@ -2578,10 +2576,6 @@ fn buildOutputType(...@@ -2578,10 +2576,6 @@ fn buildOutputType(
2578 };2576 };
2579 try comp.makeBinFileExecutable();2577 try comp.makeBinFileExecutable();
25802578
2581 if (build_options.is_stage1 and comp.stage1_lock != null and watch) {
2582 warn("--watch is not recommended with the stage1 backend; it leaks memory and is not capable of incremental compilation", .{});
2583 }
2584
2585 if (test_exec_args.items.len == 0 and object_format == .c) default_exec_args: {2579 if (test_exec_args.items.len == 0 and object_format == .c) default_exec_args: {
2586 // Default to using `zig run` to execute the produced .c code from `zig test`.2580 // Default to using `zig run` to execute the produced .c code from `zig test`.
2587 const c_code_loc = emit_bin_loc orelse break :default_exec_args;2581 const c_code_loc = emit_bin_loc orelse break :default_exec_args;
...@@ -2602,7 +2596,6 @@ fn buildOutputType(...@@ -2602,7 +2596,6 @@ fn buildOutputType(
2602 comp,2596 comp,
2603 gpa,2597 gpa,
2604 arena,2598 arena,
2605 emit_bin_loc,
2606 test_exec_args.items,2599 test_exec_args.items,
2607 self_exe_path,2600 self_exe_path,
2608 arg_mode,2601 arg_mode,
...@@ -2675,7 +2668,6 @@ fn buildOutputType(...@@ -2675,7 +2668,6 @@ fn buildOutputType(
2675 comp,2668 comp,
2676 gpa,2669 gpa,
2677 arena,2670 arena,
2678 emit_bin_loc,
2679 test_exec_args.items,2671 test_exec_args.items,
2680 self_exe_path,2672 self_exe_path,
2681 arg_mode,2673 arg_mode,
...@@ -2701,7 +2693,6 @@ fn buildOutputType(...@@ -2701,7 +2693,6 @@ fn buildOutputType(
2701 comp,2693 comp,
2702 gpa,2694 gpa,
2703 arena,2695 arena,
2704 emit_bin_loc,
2705 test_exec_args.items,2696 test_exec_args.items,
2706 self_exe_path,2697 self_exe_path,
2707 arg_mode,2698 arg_mode,
...@@ -2766,7 +2757,6 @@ fn runOrTest(...@@ -2766,7 +2757,6 @@ fn runOrTest(
2766 comp: *Compilation,2757 comp: *Compilation,
2767 gpa: Allocator,2758 gpa: Allocator,
2768 arena: Allocator,2759 arena: Allocator,
2769 emit_bin_loc: ?Compilation.EmitLoc,
2770 test_exec_args: []const ?[]const u8,2760 test_exec_args: []const ?[]const u8,
2771 self_exe_path: []const u8,2761 self_exe_path: []const u8,
2772 arg_mode: ArgMode,2762 arg_mode: ArgMode,
...@@ -2777,10 +2767,11 @@ fn runOrTest(...@@ -2777,10 +2767,11 @@ fn runOrTest(
2777 runtime_args_start: ?usize,2767 runtime_args_start: ?usize,
2778 link_libc: bool,2768 link_libc: bool,
2779) !void {2769) !void {
2780 const exe_loc = emit_bin_loc orelse return;2770 const exe_emit = comp.bin_file.options.emit orelse return;
2781 const exe_directory = exe_loc.directory orelse comp.bin_file.options.emit.?.directory;2771 // A naive `directory.join` here will indeed get the correct path to the binary,
2772 // however, in the case of cwd, we actually want `./foo` so that the path can be executed.
2782 const exe_path = try fs.path.join(arena, &[_][]const u8{2773 const exe_path = try fs.path.join(arena, &[_][]const u8{
2783 exe_directory.path orelse ".", exe_loc.basename,2774 exe_emit.directory.path orelse ".", exe_emit.sub_path,
2784 });2775 });
27852776
2786 var argv = std.ArrayList([]const u8).init(gpa);2777 var argv = std.ArrayList([]const u8).init(gpa);
...@@ -2884,7 +2875,7 @@ fn runOrTest(...@@ -2884,7 +2875,7 @@ fn runOrTest(
28842875
2885const AfterUpdateHook = union(enum) {2876const AfterUpdateHook = union(enum) {
2886 none,2877 none,
2887 print: []const u8,2878 print_emit_bin_dir_path,
2888 update: []const u8,2879 update: []const u8,
2889};2880};
28902881
...@@ -2910,7 +2901,13 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void...@@ -2910,7 +2901,13 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void
2910 return error.SemanticAnalyzeFail;2901 return error.SemanticAnalyzeFail;
2911 } else switch (hook) {2902 } else switch (hook) {
2912 .none => {},2903 .none => {},
2913 .print => |bin_path| try io.getStdOut().writer().print("{s}\n", .{bin_path}),2904 .print_emit_bin_dir_path => {
2905 const emit = comp.bin_file.options.emit.?;
2906 const full_path = try emit.directory.join(gpa, &.{emit.sub_path});
2907 defer gpa.free(full_path);
2908 const dir_path = fs.path.dirname(full_path).?;
2909 try io.getStdOut().writer().print("{s}\n", .{dir_path});
2910 },
2914 .update => |full_path| {2911 .update => |full_path| {
2915 const bin_sub_path = comp.bin_file.options.emit.?.sub_path;2912 const bin_sub_path = comp.bin_file.options.emit.?.sub_path;
2916 const cwd = fs.cwd();2913 const cwd = fs.cwd();
...@@ -3473,9 +3470,10 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -3473,9 +3470,10 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
3473 };3470 };
3474 try comp.makeBinFileExecutable();3471 try comp.makeBinFileExecutable();
34753472
3476 child_argv.items[argv_index_exe] = try comp.bin_file.options.emit.?.directory.join(3473 const emit = comp.bin_file.options.emit.?;
3474 child_argv.items[argv_index_exe] = try emit.directory.join(
3477 arena,3475 arena,
3478 &[_][]const u8{exe_basename},3476 &[_][]const u8{emit.sub_path},
3479 );3477 );
34803478
3481 break :argv child_argv.items;3479 break :argv child_argv.items;
...@@ -3666,9 +3664,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void...@@ -3666,9 +3664,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
3666 .zir_loaded = false,3664 .zir_loaded = false,
3667 .sub_file_path = "<stdin>",3665 .sub_file_path = "<stdin>",
3668 .source = source_code,3666 .source = source_code,
3669 .stat_size = undefined,3667 .stat = undefined,
3670 .stat_inode = undefined,
3671 .stat_mtime = undefined,
3672 .tree = tree,3668 .tree = tree,
3673 .tree_loaded = true,3669 .tree_loaded = true,
3674 .zir = undefined,3670 .zir = undefined,
...@@ -3862,9 +3858,11 @@ fn fmtPathFile(...@@ -3862,9 +3858,11 @@ fn fmtPathFile(
3862 .zir_loaded = false,3858 .zir_loaded = false,
3863 .sub_file_path = file_path,3859 .sub_file_path = file_path,
3864 .source = source_code,3860 .source = source_code,
3865 .stat_size = stat.size,3861 .stat = .{
3866 .stat_inode = stat.inode,3862 .size = stat.size,
3867 .stat_mtime = stat.mtime,3863 .inode = stat.inode,
3864 .mtime = stat.mtime,
3865 },
3868 .tree = tree,3866 .tree = tree,
3869 .tree_loaded = true,3867 .tree_loaded = true,
3870 .zir = undefined,3868 .zir = undefined,
...@@ -4460,9 +4458,7 @@ pub fn cmdAstCheck(...@@ -4460,9 +4458,7 @@ pub fn cmdAstCheck(
4460 .zir_loaded = false,4458 .zir_loaded = false,
4461 .sub_file_path = undefined,4459 .sub_file_path = undefined,
4462 .source = undefined,4460 .source = undefined,
4463 .stat_size = undefined,4461 .stat = undefined,
4464 .stat_inode = undefined,
4465 .stat_mtime = undefined,
4466 .tree = undefined,4462 .tree = undefined,
4467 .zir = undefined,4463 .zir = undefined,
4468 .pkg = undefined,4464 .pkg = undefined,
...@@ -4487,9 +4483,11 @@ pub fn cmdAstCheck(...@@ -4487,9 +4483,11 @@ pub fn cmdAstCheck(
4487 file.sub_file_path = file_name;4483 file.sub_file_path = file_name;
4488 file.source = source;4484 file.source = source;
4489 file.source_loaded = true;4485 file.source_loaded = true;
4490 file.stat_size = stat.size;4486 file.stat = .{
4491 file.stat_inode = stat.inode;4487 .size = stat.size,
4492 file.stat_mtime = stat.mtime;4488 .inode = stat.inode,
4489 .mtime = stat.mtime,
4490 };
4493 } else {4491 } else {
4494 const stdin = io.getStdIn();4492 const stdin = io.getStdIn();
4495 const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| {4493 const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| {
...@@ -4498,7 +4496,7 @@ pub fn cmdAstCheck(...@@ -4498,7 +4496,7 @@ pub fn cmdAstCheck(
4498 file.sub_file_path = "<stdin>";4496 file.sub_file_path = "<stdin>";
4499 file.source = source;4497 file.source = source;
4500 file.source_loaded = true;4498 file.source_loaded = true;
4501 file.stat_size = source.len;4499 file.stat.size = source.len;
4502 }4500 }
45034501
4504 file.pkg = try Package.create(gpa, null, file.sub_file_path);4502 file.pkg = try Package.create(gpa, null, file.sub_file_path);
...@@ -4611,9 +4609,11 @@ pub fn cmdChangelist(...@@ -4611,9 +4609,11 @@ pub fn cmdChangelist(
4611 .zir_loaded = false,4609 .zir_loaded = false,
4612 .sub_file_path = old_source_file,4610 .sub_file_path = old_source_file,
4613 .source = undefined,4611 .source = undefined,
4614 .stat_size = stat.size,4612 .stat = .{
4615 .stat_inode = stat.inode,4613 .size = stat.size,
4616 .stat_mtime = stat.mtime,4614 .inode = stat.inode,
4615 .mtime = stat.mtime,
4616 },
4617 .tree = undefined,4617 .tree = undefined,
4618 .zir = undefined,4618 .zir = undefined,
4619 .pkg = undefined,4619 .pkg = undefined,
src/musl.zig+1
...@@ -203,6 +203,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {...@@ -203,6 +203,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
203 const sub_compilation = try Compilation.create(comp.gpa, .{203 const sub_compilation = try Compilation.create(comp.gpa, .{
204 .local_cache_directory = comp.global_cache_directory,204 .local_cache_directory = comp.global_cache_directory,
205 .global_cache_directory = comp.global_cache_directory,205 .global_cache_directory = comp.global_cache_directory,
206 .cache_mode = .whole,
206 .zig_lib_directory = comp.zig_lib_directory,207 .zig_lib_directory = comp.zig_lib_directory,
207 .target = target,208 .target = target,
208 .root_name = "c",209 .root_name = "c",
src/stage1.zig+4-1
...@@ -458,7 +458,10 @@ export fn stage2_fetch_file(...@@ -458,7 +458,10 @@ export fn stage2_fetch_file(
458 const comp = @intToPtr(*Compilation, stage1.userdata);458 const comp = @intToPtr(*Compilation, stage1.userdata);
459 const file_path = path_ptr[0..path_len];459 const file_path = path_ptr[0..path_len];
460 const max_file_size = std.math.maxInt(u32);460 const max_file_size = std.math.maxInt(u32);
461 const contents = comp.stage1_cache_manifest.addFilePostFetch(file_path, max_file_size) catch return null;461 const contents = if (comp.whole_cache_manifest) |man|
462 man.addFilePostFetch(file_path, max_file_size) catch return null
463 else
464 std.fs.cwd().readFileAlloc(comp.gpa, file_path, max_file_size) catch return null;
462 result_len.* = contents.len;465 result_len.* = contents.len;
463 // TODO https://github.com/ziglang/zig/issues/3328#issuecomment-716749475466 // TODO https://github.com/ziglang/zig/issues/3328#issuecomment-716749475
464 if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1);467 if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1);
src/type.zig+14-3
...@@ -3106,9 +3106,9 @@ pub const Type = extern union {...@@ -3106,9 +3106,9 @@ pub const Type = extern union {
3106 .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },3106 .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
31073107
3108 .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,3108 .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,
3109 .enum_numbered => ty = self.castTag(.enum_numbered).?.data.tag_ty,3109 .enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty,
3110 .enum_simple => {3110 .enum_simple => {
3111 const enum_obj = self.castTag(.enum_simple).?.data;3111 const enum_obj = ty.castTag(.enum_simple).?.data;
3112 const field_count = enum_obj.fields.count();3112 const field_count = enum_obj.fields.count();
3113 if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 };3113 if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 };
3114 return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };3114 return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };
...@@ -4603,7 +4603,18 @@ pub const CType = enum {...@@ -4603,7 +4603,18 @@ pub const CType = enum {
4603 .longlong,4603 .longlong,
4604 .ulonglong,4604 .ulonglong,
4605 => return 64,4605 => return 64,
4606 .longdouble => @panic("TODO figure out what kind of float `long double` is on this target"),4606 .longdouble => switch (target.cpu.arch) {
4607 .riscv64,
4608 .aarch64,
4609 .aarch64_be,
4610 .aarch64_32,
4611 .s390x,
4612 .mips64,
4613 .mips64el,
4614 => return 128,
4615
4616 else => return 80,
4617 },
4607 },4618 },
46084619
4609 .windows, .uefi => switch (self) {4620 .windows, .uefi => switch (self) {
test/behavior/cast.zig+9
...@@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" {...@@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" {
295 const a: ??[*]u8 = @as(?[*]u8, null);295 const a: ??[*]u8 = @as(?[*]u8, null);
296 try expect(a != null and a.? == null);296 try expect(a != null and a.? == null);
297}297}
298
299test "peer type unsigned int to signed" {
300 var w: u31 = 5;
301 var x: u8 = 7;
302 var y: i32 = -5;
303 var a = w + y + x;
304 comptime try expect(@TypeOf(a) == i32);
305 try expect(a == 7);
306}
test/behavior/cast_stage1.zig-9
...@@ -383,15 +383,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" {...@@ -383,15 +383,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" {
383 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);383 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
384}384}
385385
386test "peer type unsigned int to signed" {
387 var w: u31 = 5;
388 var x: u8 = 7;
389 var y: i32 = -5;
390 var a = w + y + x;
391 comptime try expect(@TypeOf(a) == i32);
392 try expect(a == 7);
393}
394
395test "peer type resolve array pointers, one of them const" {386test "peer type resolve array pointers, one of them const" {
396 var array1: [4]u8 = undefined;387 var array1: [4]u8 = undefined;
397 const array2: [5]u8 = undefined;388 const array2: [5]u8 = undefined;