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 {
13611361 .share_access = share_access,
13621362 .creation = creation,
13631363 .io_mode = .blocking,
1364 .open_dir = true,
1364 .filter = .dir_only,
13651365 }) catch |er| switch (er) {
13661366 error.WouldBlock => unreachable,
13671367 else => |e2| return e2,
lib/std/fs/watch.zig+1-1
......@@ -401,7 +401,7 @@ pub fn Watch(comptime V: type) type {
401401 .access_mask = windows.FILE_LIST_DIRECTORY,
402402 .creation = windows.FILE_OPEN,
403403 .io_mode = .evented,
404 .open_dir = true,
404 .filter = .dir_only,
405405 });
406406 errdefer windows.CloseHandle(dir_handle);
407407
lib/std/os.zig+6-5
......@@ -1353,7 +1353,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions {
13531353 access_mask |= w.GENERIC_READ | w.GENERIC_WRITE;
13541354 }
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;
13571357 const follow_symlinks: bool = flags & O.NOFOLLOW == 0;
13581358
13591359 const creation: w.ULONG = blk: {
......@@ -1369,7 +1369,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions {
13691369 .access_mask = access_mask,
13701370 .io_mode = .blocking,
13711371 .creation = creation,
1372 .open_dir = open_dir,
1372 .filter = filter,
13731373 .follow_symlinks = follow_symlinks,
13741374 };
13751375}
......@@ -2324,6 +2324,7 @@ pub fn renameatW(
23242324 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,
23252325 .creation = windows.FILE_OPEN,
23262326 .io_mode = .blocking,
2327 .filter = .any, // This function is supposed to rename both files and directories.
23272328 }) catch |err| switch (err) {
23282329 error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
23292330 else => |e| return e,
......@@ -2435,7 +2436,7 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v
24352436 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
24362437 .creation = windows.FILE_CREATE,
24372438 .io_mode = .blocking,
2438 .open_dir = true,
2439 .filter = .dir_only,
24392440 }) catch |err| switch (err) {
24402441 error.IsDir => unreachable,
24412442 error.PipeBusy => unreachable,
......@@ -2511,7 +2512,7 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void {
25112512 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
25122513 .creation = windows.FILE_CREATE,
25132514 .io_mode = .blocking,
2514 .open_dir = true,
2515 .filter = .dir_only,
25152516 }) catch |err| switch (err) {
25162517 error.IsDir => unreachable,
25172518 error.PipeBusy => unreachable,
......@@ -4693,7 +4694,7 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
46934694 .share_access = share_access,
46944695 .creation = creation,
46954696 .io_mode = .blocking,
4696 .open_dir = true,
4697 .filter = .dir_only,
46974698 }) catch |er| switch (er) {
46984699 error.WouldBlock => unreachable,
46994700 else => |e2| return e2,
lib/std/os/windows.zig+18-5
......@@ -53,17 +53,26 @@ pub const OpenFileOptions = struct {
5353 io_mode: std.io.ModeOverride,
5454 /// If true, tries to open path as a directory.
5555 /// Defaults to false.
56 open_dir: bool = false,
56 filter: Filter = .file_only,
5757 /// If false, tries to open path as a reparse point without dereferencing it.
5858 /// Defaults to true.
5959 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 };
6069};
6170
6271pub 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) {
6473 return error.IsDir;
6574 }
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) {
6776 return error.IsDir;
6877 }
6978
......@@ -87,7 +96,11 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
8796 };
8897 var io: IO_STATUS_BLOCK = undefined;
8998 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 };
91104 // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.
92105 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(
695708 .dir = dir,
696709 .creation = FILE_CREATE,
697710 .io_mode = .blocking,
698 .open_dir = is_directory,
711 .filter = if (is_directory) .dir_only else .file_only,
699712 }) catch |err| switch (err) {
700713 error.IsDir => return error.PathAlreadyExists,
701714 error.NotDir => unreachable,
lib/std/special/compiler_rt.zig+529-521
......@@ -22,6 +22,12 @@ else
2222const long_double_is_f128 = builtin.target.longDoubleIsF128();
2323
2424comptime {
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
2531 const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2;
2632 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
2733 const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2;
......@@ -171,16 +177,16 @@ comptime {
171177 const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2;
172178 @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
173179
174 if (!builtin.zig_is_stage2) {
175 if (!long_double_is_f128) {
176 // TODO implement these
177 //const __extendxftf2 = @import("compiler_rt/extendXfYf2.zig").__extendxftf2;
178 //@export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = linkage });
180 if (!long_double_is_f128) {
181 // TODO implement these
182 //const __extendxftf2 = @import("compiler_rt/extendXfYf2.zig").__extendxftf2;
183 //@export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = linkage });
179184
180 //const __trunctfxf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfxf2;
181 //@export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });
182 }
185 //const __trunctfxf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfxf2;
186 //@export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });
187 }
183188
189 if (!builtin.zig_is_stage2) {
184190 switch (arch) {
185191 .i386,
186192 .x86_64,
......@@ -193,531 +199,533 @@ comptime {
193199 },
194200 else => {},
195201 }
202 }
196203
197 // __clear_cache manages its own logic about whether to be exported or not.
198 _ = @import("compiler_rt/clear_cache.zig").clear_cache;
199
200 const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2;
201 @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });
202 const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2;
203 @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });
204 const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2;
205 @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });
206
207 const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3;
208 @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage });
209 const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3;
210 @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage });
211 const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3;
212 @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage });
213 const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3;
214 @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage });
215 const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3;
216 @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage });
217 const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3;
218 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });
219
220 const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3;
221 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });
222 const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3;
223 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });
224 const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3;
225 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });
226
227 const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3;
228 @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage });
229 const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3;
230 @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage });
231 const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;
232 @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });
233
234 // Integral bit manipulation
235 const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;
236 @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
237 const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3;
238 @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
239 const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3;
240 @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
241 const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3;
242 @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
243 const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3;
244 @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
245 const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;
246 @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
247
248 const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;
249 @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
250 const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;
251 @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage });
252 const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2;
253 @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage });
254 const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2;
255 @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage });
256 const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2;
257 @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage });
258 const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2;
259 @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage });
260 const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2;
261 @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage });
262 const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2;
263 @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });
264 const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;
265 @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });
266
267 const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;
268 @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });
269 const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2;
270 @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage });
271 const __parityti2 = @import("compiler_rt/parity.zig").__parityti2;
272 @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage });
273 const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2;
274 @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage });
275 const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2;
276 @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
277 const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2;
278 @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage });
279 const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2;
280 @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage });
281 const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2;
282 @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = linkage });
283 const __bswapti2 = @import("compiler_rt/bswap.zig").__bswapti2;
284 @export(__bswapti2, .{ .name = "__bswapti2", .linkage = linkage });
285
286 // Integral / floating point conversion (part 1/2)
287 const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf;
288 @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });
289 const __floatsisf = @import("compiler_rt/floatsiXf.zig").__floatsisf;
290 @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });
291 const __floatdidf = @import("compiler_rt/floatdidf.zig").__floatdidf;
292 @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage });
293 const __floatsitf = @import("compiler_rt/floatsiXf.zig").__floatsitf;
294 @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage });
295
296 const __floatunsisf = @import("compiler_rt/floatunsisf.zig").__floatunsisf;
297 @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage });
204 const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2;
205 @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });
206 const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2;
207 @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });
208 const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2;
209 @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });
210
211 const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3;
212 @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage });
213 const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3;
214 @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage });
215 const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3;
216 @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage });
217 const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3;
218 @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage });
219 const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3;
220 @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage });
221 const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3;
222 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });
223
224 const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3;
225 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });
226 const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3;
227 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });
228 const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3;
229 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });
230
231 const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3;
232 @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage });
233 const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3;
234 @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage });
235 const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;
236 @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });
237
238 // Integral bit manipulation
239 const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;
240 @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
241 const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3;
242 @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
243 const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3;
244 @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
245 const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3;
246 @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
247 const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3;
248 @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
249 const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;
250 @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
251
252 const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;
253 @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
254 const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;
255 @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage });
256 const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2;
257 @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage });
258 const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2;
259 @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage });
260 const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2;
261 @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage });
262 const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2;
263 @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage });
264 const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2;
265 @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage });
266 const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2;
267 @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });
268 const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;
269 @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });
270
271 const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;
272 @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });
273 const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2;
274 @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage });
275 const __parityti2 = @import("compiler_rt/parity.zig").__parityti2;
276 @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage });
277
278 const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2;
279 @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage });
280 const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2;
281 @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
282 const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2;
283 @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage });
284
285 const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2;
286 @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage });
287 const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2;
288 @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = linkage });
289 const __bswapti2 = @import("compiler_rt/bswap.zig").__bswapti2;
290 @export(__bswapti2, .{ .name = "__bswapti2", .linkage = linkage });
291
292 // Integral / floating point conversion (part 1/2)
293 const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf;
294 @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });
295 const __floatsisf = @import("compiler_rt/floatsiXf.zig").__floatsisf;
296 @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });
297 const __floatdidf = @import("compiler_rt/floatdidf.zig").__floatdidf;
298 @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage });
299 const __floatsitf = @import("compiler_rt/floatsiXf.zig").__floatsitf;
300 @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage });
301
302 const __floatunsisf = @import("compiler_rt/floatunsisf.zig").__floatunsisf;
303 @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage });
304 if (!builtin.zig_is_stage2) {
298305 const __floatundisf = @import("compiler_rt/floatundisf.zig").__floatundisf;
299306 @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage });
300 const __floatunsidf = @import("compiler_rt/floatunsidf.zig").__floatunsidf;
301 @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage });
302 const __floatundidf = @import("compiler_rt/floatundidf.zig").__floatundidf;
303 @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage });
304
305 const __floatditf = @import("compiler_rt/floatditf.zig").__floatditf;
306 @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage });
307 const __floattitf = @import("compiler_rt/floattitf.zig").__floattitf;
308 @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage });
309 const __floattidf = @import("compiler_rt/floattidf.zig").__floattidf;
310 @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage });
311 const __floattisf = @import("compiler_rt/floatXisf.zig").__floattisf;
312 @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage });
313 const __floatdisf = @import("compiler_rt/floatXisf.zig").__floatdisf;
314 @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage });
315
316 const __floatunditf = @import("compiler_rt/floatunditf.zig").__floatunditf;
317 @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage });
318 const __floatunsitf = @import("compiler_rt/floatunsitf.zig").__floatunsitf;
319 @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage });
320
321 const __floatuntitf = @import("compiler_rt/floatuntitf.zig").__floatuntitf;
322 @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage });
323 const __floatuntidf = @import("compiler_rt/floatuntidf.zig").__floatuntidf;
324 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage });
325 const __floatuntisf = @import("compiler_rt/floatuntisf.zig").__floatuntisf;
326 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage });
327
328 const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2;
329 @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
330 if (!is_test) {
331 @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
332 }
333 const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2;
334 @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });
335
336 // Integral / floating point conversion (part 2/2)
337 const __fixunssfsi = @import("compiler_rt/fixunssfsi.zig").__fixunssfsi;
338 @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage });
339 const __fixunssfdi = @import("compiler_rt/fixunssfdi.zig").__fixunssfdi;
340 @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage });
341 const __fixunssfti = @import("compiler_rt/fixunssfti.zig").__fixunssfti;
342 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage });
343
344 const __fixunsdfsi = @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi;
345 @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage });
346 const __fixunsdfdi = @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi;
347 @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage });
348 const __fixunsdfti = @import("compiler_rt/fixunsdfti.zig").__fixunsdfti;
349 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage });
350
351 const __fixunstfsi = @import("compiler_rt/fixunstfsi.zig").__fixunstfsi;
352 @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage });
353 const __fixunstfdi = @import("compiler_rt/fixunstfdi.zig").__fixunstfdi;
354 @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage });
355 const __fixunstfti = @import("compiler_rt/fixunstfti.zig").__fixunstfti;
356 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage });
357
358 const __fixdfdi = @import("compiler_rt/fixdfdi.zig").__fixdfdi;
359 @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage });
360 const __fixdfsi = @import("compiler_rt/fixdfsi.zig").__fixdfsi;
361 @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage });
362 const __fixdfti = @import("compiler_rt/fixdfti.zig").__fixdfti;
363 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage });
364 const __fixsfdi = @import("compiler_rt/fixsfdi.zig").__fixsfdi;
365 @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage });
366 const __fixsfsi = @import("compiler_rt/fixsfsi.zig").__fixsfsi;
367 @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage });
368 const __fixsfti = @import("compiler_rt/fixsfti.zig").__fixsfti;
369 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage });
370 const __fixtfdi = @import("compiler_rt/fixtfdi.zig").__fixtfdi;
371 @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage });
372 const __fixtfsi = @import("compiler_rt/fixtfsi.zig").__fixtfsi;
373 @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage });
374 const __fixtfti = @import("compiler_rt/fixtfti.zig").__fixtfti;
375 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage });
376
377 const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4;
378 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });
379
380 if (is_darwin) {
381 const __isPlatformVersionAtLeast = @import("compiler_rt/os_version_check.zig").__isPlatformVersionAtLeast;
382 @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage });
383 }
307 }
308 const __floatunsidf = @import("compiler_rt/floatunsidf.zig").__floatunsidf;
309 @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage });
310 const __floatundidf = @import("compiler_rt/floatundidf.zig").__floatundidf;
311 @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage });
312
313 const __floatditf = @import("compiler_rt/floatditf.zig").__floatditf;
314 @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage });
315 const __floattitf = @import("compiler_rt/floattitf.zig").__floattitf;
316 @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage });
317 const __floattidf = @import("compiler_rt/floattidf.zig").__floattidf;
318 @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage });
319 const __floattisf = @import("compiler_rt/floatXisf.zig").__floattisf;
320 @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage });
321 const __floatdisf = @import("compiler_rt/floatXisf.zig").__floatdisf;
322 @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage });
323
324 const __floatunditf = @import("compiler_rt/floatunditf.zig").__floatunditf;
325 @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage });
326 const __floatunsitf = @import("compiler_rt/floatunsitf.zig").__floatunsitf;
327 @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage });
328
329 const __floatuntitf = @import("compiler_rt/floatuntitf.zig").__floatuntitf;
330 @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage });
331 const __floatuntidf = @import("compiler_rt/floatuntidf.zig").__floatuntidf;
332 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage });
333 const __floatuntisf = @import("compiler_rt/floatuntisf.zig").__floatuntisf;
334 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage });
335
336 const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2;
337 @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
338 if (!is_test) {
339 @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
340 }
341 const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2;
342 @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });
343
344 // Integral / floating point conversion (part 2/2)
345 const __fixunssfsi = @import("compiler_rt/fixunssfsi.zig").__fixunssfsi;
346 @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage });
347 const __fixunssfdi = @import("compiler_rt/fixunssfdi.zig").__fixunssfdi;
348 @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage });
349 const __fixunssfti = @import("compiler_rt/fixunssfti.zig").__fixunssfti;
350 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage });
351
352 const __fixunsdfsi = @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi;
353 @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage });
354 const __fixunsdfdi = @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi;
355 @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage });
356 const __fixunsdfti = @import("compiler_rt/fixunsdfti.zig").__fixunsdfti;
357 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage });
358
359 const __fixunstfsi = @import("compiler_rt/fixunstfsi.zig").__fixunstfsi;
360 @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage });
361 const __fixunstfdi = @import("compiler_rt/fixunstfdi.zig").__fixunstfdi;
362 @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage });
363 const __fixunstfti = @import("compiler_rt/fixunstfti.zig").__fixunstfti;
364 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage });
365
366 const __fixdfdi = @import("compiler_rt/fixdfdi.zig").__fixdfdi;
367 @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage });
368 const __fixdfsi = @import("compiler_rt/fixdfsi.zig").__fixdfsi;
369 @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage });
370 const __fixdfti = @import("compiler_rt/fixdfti.zig").__fixdfti;
371 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage });
372 const __fixsfdi = @import("compiler_rt/fixsfdi.zig").__fixsfdi;
373 @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage });
374 const __fixsfsi = @import("compiler_rt/fixsfsi.zig").__fixsfsi;
375 @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage });
376 const __fixsfti = @import("compiler_rt/fixsfti.zig").__fixsfti;
377 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage });
378 const __fixtfdi = @import("compiler_rt/fixtfdi.zig").__fixtfdi;
379 @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage });
380 const __fixtfsi = @import("compiler_rt/fixtfsi.zig").__fixtfsi;
381 @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage });
382 const __fixtfti = @import("compiler_rt/fixtfti.zig").__fixtfti;
383 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage });
384
385 const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4;
386 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });
387
388 if (is_darwin) {
389 const __isPlatformVersionAtLeast = @import("compiler_rt/os_version_check.zig").__isPlatformVersionAtLeast;
390 @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage });
391 }
384392
385 // Integral arithmetic
386 const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2;
387 @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage });
388 const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2;
389 @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage });
390 const __negti2 = @import("compiler_rt/negXi2.zig").__negti2;
391 @export(__negti2, .{ .name = "__negti2", .linkage = linkage });
392 const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3;
393 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
394 const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3;
395 @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage });
396 const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4;
397 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });
398 const __divsi3 = @import("compiler_rt/int.zig").__divsi3;
399 @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage });
400 const __divdi3 = @import("compiler_rt/int.zig").__divdi3;
401 @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage });
402 const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3;
403 @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage });
404 const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3;
405 @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage });
406 const __modsi3 = @import("compiler_rt/int.zig").__modsi3;
407 @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage });
408 const __moddi3 = @import("compiler_rt/int.zig").__moddi3;
409 @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage });
410 const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3;
411 @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage });
412 const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3;
413 @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage });
414 const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4;
415 @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage });
416 const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4;
417 @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage });
418
419 // Integral arithmetic with trapping overflow
420 const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2;
421 @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage });
422 const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2;
423 @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage });
424 const __absvti2 = @import("compiler_rt/absv.zig").__absvti2;
425 @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage });
426 const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2;
427 @export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage });
428 const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2;
429 @export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage });
430 const __negvti2 = @import("compiler_rt/negv.zig").__negvti2;
431 @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage });
432
433 // missing: Integral arithmetic which returns if overflow
434
435 // Integral comparison
436 // (a < b) => 0
437 // (a == b) => 1
438 // (a > b) => 2
439 const __cmpsi2 = @import("compiler_rt/cmp.zig").__cmpsi2;
440 @export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = linkage });
441 const __cmpdi2 = @import("compiler_rt/cmp.zig").__cmpdi2;
442 @export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = linkage });
443 const __cmpti2 = @import("compiler_rt/cmp.zig").__cmpti2;
444 @export(__cmpti2, .{ .name = "__cmpti2", .linkage = linkage });
445 const __ucmpsi2 = @import("compiler_rt/cmp.zig").__ucmpsi2;
446 @export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = linkage });
447 const __ucmpdi2 = @import("compiler_rt/cmp.zig").__ucmpdi2;
448 @export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = linkage });
449 const __ucmpti2 = @import("compiler_rt/cmp.zig").__ucmpti2;
450 @export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = linkage });
451
452 // missing: Floating point raised to integer power
453
454 // missing: Complex arithmetic
455 // (a + ib) * (c + id)
456 // (a + ib) / (c + id)
457
458 const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2;
459 @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage });
460 const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2;
461 @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage });
462
463 if (builtin.link_libc and os_tag == .openbsd) {
464 const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address;
465 @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage });
466 }
393 // Integral arithmetic
394 const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2;
395 @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage });
396 const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2;
397 @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage });
398 const __negti2 = @import("compiler_rt/negXi2.zig").__negti2;
399 @export(__negti2, .{ .name = "__negti2", .linkage = linkage });
400 const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3;
401 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
402 const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3;
403 @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage });
404 const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4;
405 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });
406 const __divsi3 = @import("compiler_rt/int.zig").__divsi3;
407 @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage });
408 const __divdi3 = @import("compiler_rt/int.zig").__divdi3;
409 @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage });
410 const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3;
411 @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage });
412 const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3;
413 @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage });
414 const __modsi3 = @import("compiler_rt/int.zig").__modsi3;
415 @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage });
416 const __moddi3 = @import("compiler_rt/int.zig").__moddi3;
417 @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage });
418 const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3;
419 @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage });
420 const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3;
421 @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage });
422 const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4;
423 @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage });
424 const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4;
425 @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage });
426
427 // Integral arithmetic with trapping overflow
428 const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2;
429 @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage });
430 const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2;
431 @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage });
432 const __absvti2 = @import("compiler_rt/absv.zig").__absvti2;
433 @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage });
434 const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2;
435 @export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage });
436 const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2;
437 @export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage });
438 const __negvti2 = @import("compiler_rt/negv.zig").__negvti2;
439 @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage });
440
441 // missing: Integral arithmetic which returns if overflow
442
443 // Integral comparison
444 // (a < b) => 0
445 // (a == b) => 1
446 // (a > b) => 2
447 const __cmpsi2 = @import("compiler_rt/cmp.zig").__cmpsi2;
448 @export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = linkage });
449 const __cmpdi2 = @import("compiler_rt/cmp.zig").__cmpdi2;
450 @export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = linkage });
451 const __cmpti2 = @import("compiler_rt/cmp.zig").__cmpti2;
452 @export(__cmpti2, .{ .name = "__cmpti2", .linkage = linkage });
453 const __ucmpsi2 = @import("compiler_rt/cmp.zig").__ucmpsi2;
454 @export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = linkage });
455 const __ucmpdi2 = @import("compiler_rt/cmp.zig").__ucmpdi2;
456 @export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = linkage });
457 const __ucmpti2 = @import("compiler_rt/cmp.zig").__ucmpti2;
458 @export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = linkage });
459
460 // missing: Floating point raised to integer power
461
462 // missing: Complex arithmetic
463 // (a + ib) * (c + id)
464 // (a + ib) / (c + id)
465
466 const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2;
467 @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage });
468 const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2;
469 @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage });
470
471 if (builtin.link_libc and os_tag == .openbsd) {
472 const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address;
473 @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage });
474 }
467475
468 if ((arch.isARM() or arch.isThumb()) and !is_test) {
469 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 });
471 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 });
473 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 });
475
476 @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage });
477
478 const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod;
479 @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage });
480 const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod;
481 @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage });
482
483 @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage });
484 const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod;
485 @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage });
486 @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage });
487 const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod;
488 @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage });
489
490 const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy;
491 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage });
492 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage });
493 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage });
494
495 const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove;
496 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage });
497 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage });
498 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage });
499
500 const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset;
501 @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage });
502 @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage });
503 @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage });
504
505 const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr;
506 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage });
507 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });
508 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });
509
510 if (os_tag == .linux) {
511 const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp;
512 @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 });
476 if ((arch.isARM() or arch.isThumb()) and !is_test) {
477 const __aeabi_unwind_cpp_pr0 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0;
478 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage });
479 const __aeabi_unwind_cpp_pr1 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1;
480 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage });
481 const __aeabi_unwind_cpp_pr2 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2;
482 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage });
483
484 @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage });
485
486 const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod;
487 @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage });
488 const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod;
489 @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage });
490
491 @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage });
492 const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod;
493 @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage });
494 @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage });
495 const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod;
496 @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage });
497
498 const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy;
499 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage });
500 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage });
501 @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage });
502
503 const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove;
504 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage });
505 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage });
506 @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage });
507
508 const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset;
509 @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage });
510 @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage });
511 @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage });
512
513 const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr;
514 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage });
515 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });
516 @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });
517
518 if (os_tag == .linux) {
519 const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp;
520 @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });
622521 }
623522
624 if (arch == .i386 and abi == .msvc) {
625 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins
626 const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv;
627 @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });
628 const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv;
629 @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });
630 const _allrem = @import("compiler_rt/aullrem.zig")._allrem;
631 @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage });
632 const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem;
633 @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
634 }
523 const __aeabi_f2d = @import("compiler_rt/extendXfYf2.zig").__aeabi_f2d;
524 @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage });
525 const __aeabi_i2d = @import("compiler_rt/floatsiXf.zig").__aeabi_i2d;
526 @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage });
527 const __aeabi_l2d = @import("compiler_rt/floatdidf.zig").__aeabi_l2d;
528 @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage });
529 const __aeabi_l2f = @import("compiler_rt/floatXisf.zig").__aeabi_l2f;
530 @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage });
531 const __aeabi_ui2d = @import("compiler_rt/floatunsidf.zig").__aeabi_ui2d;
532 @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage });
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()) {
637 // SPARC systems use a different naming scheme
638 const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add;
639 @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage });
640 const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div;
641 @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage });
642 const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul;
643 @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage });
644 const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub;
645 @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage });
646
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 }
632 if (arch == .i386 and abi == .msvc) {
633 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins
634 const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv;
635 @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });
636 const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv;
637 @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });
638 const _allrem = @import("compiler_rt/aullrem.zig")._allrem;
639 @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage });
640 const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem;
641 @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
642 }
687643
688 if ((arch == .powerpc or arch.isPPC64()) and !is_test) {
689 @export(__addtf3, .{ .name = "__addkf3", .linkage = linkage });
690 @export(__subtf3, .{ .name = "__subkf3", .linkage = linkage });
691 @export(__multf3, .{ .name = "__mulkf3", .linkage = linkage });
692 @export(__divtf3, .{ .name = "__divkf3", .linkage = linkage });
693 @export(__extendsftf2, .{ .name = "__extendsfkf2", .linkage = linkage });
694 @export(__extenddftf2, .{ .name = "__extenddfkf2", .linkage = linkage });
695 @export(__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = linkage });
696 @export(__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = linkage });
697 @export(__fixtfdi, .{ .name = "__fixkfdi", .linkage = linkage });
698 @export(__fixtfsi, .{ .name = "__fixkfsi", .linkage = linkage });
699 @export(__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = linkage });
700 @export(__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = linkage });
701 @export(__floatsitf, .{ .name = "__floatsikf", .linkage = linkage });
702 @export(__floatditf, .{ .name = "__floatdikf", .linkage = linkage });
703 @export(__floatunditf, .{ .name = "__floatundikf", .linkage = linkage });
704 @export(__floatunsitf, .{ .name = "__floatunsikf", .linkage = linkage });
705
706 @export(__letf2, .{ .name = "__eqkf2", .linkage = linkage });
707 @export(__letf2, .{ .name = "__nekf2", .linkage = linkage });
708 @export(__getf2, .{ .name = "__gekf2", .linkage = linkage });
709 @export(__letf2, .{ .name = "__ltkf2", .linkage = linkage });
710 @export(__letf2, .{ .name = "__lekf2", .linkage = linkage });
711 @export(__getf2, .{ .name = "__gtkf2", .linkage = linkage });
712 @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage });
713 }
644 if (arch.isSPARC()) {
645 // SPARC systems use a different naming scheme
646 const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add;
647 @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage });
648 const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div;
649 @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage });
650 const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul;
651 @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage });
652 const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub;
653 @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage });
654
655 const _Qp_cmp = @import("compiler_rt/sparc.zig")._Qp_cmp;
656 @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = linkage });
657 const _Qp_feq = @import("compiler_rt/sparc.zig")._Qp_feq;
658 @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = linkage });
659 const _Qp_fne = @import("compiler_rt/sparc.zig")._Qp_fne;
660 @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = linkage });
661 const _Qp_flt = @import("compiler_rt/sparc.zig")._Qp_flt;
662 @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = linkage });
663 const _Qp_fle = @import("compiler_rt/sparc.zig")._Qp_fle;
664 @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = linkage });
665 const _Qp_fgt = @import("compiler_rt/sparc.zig")._Qp_fgt;
666 @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage });
667 const _Qp_fge = @import("compiler_rt/sparc.zig")._Qp_fge;
668 @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage });
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) {
717728 @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 });
721729 }
722730}
723731
lib/std/special/compiler_rt/absv.zig+29-24
......@@ -2,31 +2,36 @@
22// * @panic, if value can not be represented
33// - absvXi4_generic for unoptimized version
44
5fn absvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST {
6 return struct {
7 fn f(a: ST) callconv(.C) ST {
8 const UT = switch (ST) {
9 i32 => u32,
10 i64 => u64,
11 i128 => u128,
12 else => unreachable,
13 };
14 // taken from Bit Twiddling Hacks
15 // compute the integer absolute value (abs) without branching
16 var x: ST = a;
17 const N: UT = @bitSizeOf(ST);
18 const sign: ST = a >> N - 1;
19 x +%= sign;
20 x ^= sign;
21 if (x < 0)
22 @panic("compiler_rt absv: overflow");
23 return x;
24 }
25 }.f;
5inline fn absvXi(comptime ST: type, a: ST) ST {
6 const UT = switch (ST) {
7 i32 => u32,
8 i64 => u64,
9 i128 => u128,
10 else => unreachable,
11 };
12 // taken from Bit Twiddling Hacks
13 // compute the integer absolute value (abs) without branching
14 var x: ST = a;
15 const N: UT = @bitSizeOf(ST);
16 const sign: ST = a >> N - 1;
17 x +%= sign;
18 x ^= sign;
19 if (x < 0)
20 @panic("compiler_rt absv: overflow");
21 return x;
22}
23
24pub fn __absvsi2(a: i32) callconv(.C) i32 {
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);
2634}
27pub const __absvsi2 = absvXi_generic(i32);
28pub const __absvdi2 = absvXi_generic(i64);
29pub const __absvti2 = absvXi_generic(i128);
3035
3136test {
3237 _ = @import("absvsi2_test.zig");
lib/std/special/compiler_rt/atomics.zig+277-191
......@@ -119,225 +119,311 @@ fn __atomic_compare_exchange(
119119 return 0;
120120}
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
131122// Specialized versions of the GCC atomic builtin functions.
132123// LLVM emits those iff the object size is known and the pointers are correctly
133124// 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 {
136 return struct {
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;
136fn __atomic_load_1(src: *u8, model: i32) callconv(.C) u8 {
137 return atomic_load_N(u8, src, model);
148138}
149139
150comptime {
151 if (supports_atomic_ops) {
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 }
140fn __atomic_load_2(src: *u16, model: i32) callconv(.C) u16 {
141 return atomic_load_N(u16, src, model);
161142}
162143
163fn atomicStoreFn(comptime T: type) fn (*T, T, i32) callconv(.C) void {
164 return struct {
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;
144fn __atomic_load_4(src: *u32, model: i32) callconv(.C) u32 {
145 return atomic_load_N(u32, src, model);
176146}
177147
178comptime {
179 if (supports_atomic_ops) {
180 const atomicStore_u8 = atomicStoreFn(u8);
181 const atomicStore_u16 = atomicStoreFn(u16);
182 const atomicStore_u32 = atomicStoreFn(u32);
183 const atomicStore_u64 = atomicStoreFn(u64);
184 @export(atomicStore_u8, .{ .name = "__atomic_store_1", .linkage = linkage });
185 @export(atomicStore_u16, .{ .name = "__atomic_store_2", .linkage = linkage });
186 @export(atomicStore_u32, .{ .name = "__atomic_store_4", .linkage = linkage });
187 @export(atomicStore_u64, .{ .name = "__atomic_store_8", .linkage = linkage });
148fn __atomic_load_8(src: *u64, model: i32) callconv(.C) u64 {
149 return atomic_load_N(u64, src, model);
150}
151
152inline fn atomic_store_N(comptime T: type, dst: *T, value: T, model: i32) void {
153 _ = model;
154 if (@sizeOf(T) > largest_atomic_size) {
155 var sl = spinlocks.get(@ptrToInt(dst));
156 defer sl.release();
157 dst.* = value;
158 } else {
159 @atomicStore(T, dst, value, .SeqCst);
188160 }
189161}
190162
191fn atomicExchangeFn(comptime T: type) fn (*T, T, i32) callconv(.C) T {
192 return struct {
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;
163fn __atomic_store_1(dst: *u8, value: u8, model: i32) callconv(.C) void {
164 return atomic_store_N(u8, dst, value, model);
206165}
207166
208comptime {
209 if (supports_atomic_ops) {
210 const atomicExchange_u8 = atomicExchangeFn(u8);
211 const atomicExchange_u16 = atomicExchangeFn(u16);
212 const atomicExchange_u32 = atomicExchangeFn(u32);
213 const atomicExchange_u64 = atomicExchangeFn(u64);
214 @export(atomicExchange_u8, .{ .name = "__atomic_exchange_1", .linkage = linkage });
215 @export(atomicExchange_u16, .{ .name = "__atomic_exchange_2", .linkage = linkage });
216 @export(atomicExchange_u32, .{ .name = "__atomic_exchange_4", .linkage = linkage });
217 @export(atomicExchange_u64, .{ .name = "__atomic_exchange_8", .linkage = linkage });
167fn __atomic_store_2(dst: *u16, value: u16, model: i32) callconv(.C) void {
168 return atomic_store_N(u16, dst, value, model);
169}
170
171fn __atomic_store_4(dst: *u32, value: u32, model: i32) callconv(.C) void {
172 return atomic_store_N(u32, dst, value, model);
173}
174
175fn __atomic_store_8(dst: *u64, value: u64, model: i32) callconv(.C) void {
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);
218189 }
219190}
220191
221fn atomicCompareExchangeFn(comptime T: type) fn (*T, *T, T, i32, i32) callconv(.C) i32 {
222 return struct {
223 fn atomic_compare_exchange_N(ptr: *T, expected: *T, desired: T, success: i32, failure: i32) callconv(.C) i32 {
224 _ = success;
225 _ = failure;
226 if (@sizeOf(T) > largest_atomic_size) {
227 var sl = spinlocks.get(@ptrToInt(ptr));
228 defer sl.release();
229 const value = ptr.*;
230 if (value == expected.*) {
231 ptr.* = desired;
232 return 1;
233 }
234 expected.* = value;
235 return 0;
236 } else {
237 if (@cmpxchgStrong(T, ptr, expected.*, desired, .SeqCst, .SeqCst)) |old_value| {
238 expected.* = old_value;
239 return 0;
240 }
241 return 1;
242 }
192fn __atomic_exchange_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
193 return atomic_exchange_N(u8, ptr, val, model);
194}
195
196fn __atomic_exchange_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
197 return atomic_exchange_N(u16, ptr, val, model);
198}
199
200fn __atomic_exchange_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 {
201 return atomic_exchange_N(u32, ptr, val, model);
202}
203
204fn __atomic_exchange_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
205 return atomic_exchange_N(u64, ptr, val, model);
206}
207
208inline fn atomic_compare_exchange_N(
209 comptime T: type,
210 ptr: *T,
211 expected: *T,
212 desired: T,
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;
243225 }
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 }
245235}
246236
247comptime {
248 if (supports_atomic_ops) {
249 const atomicCompareExchange_u8 = atomicCompareExchangeFn(u8);
250 const atomicCompareExchange_u16 = atomicCompareExchangeFn(u16);
251 const atomicCompareExchange_u32 = atomicCompareExchangeFn(u32);
252 const atomicCompareExchange_u64 = atomicCompareExchangeFn(u64);
253 @export(atomicCompareExchange_u8, .{ .name = "__atomic_compare_exchange_1", .linkage = linkage });
254 @export(atomicCompareExchange_u16, .{ .name = "__atomic_compare_exchange_2", .linkage = linkage });
255 @export(atomicCompareExchange_u32, .{ .name = "__atomic_compare_exchange_4", .linkage = linkage });
256 @export(atomicCompareExchange_u64, .{ .name = "__atomic_compare_exchange_8", .linkage = linkage });
237fn __atomic_compare_exchange_1(ptr: *u8, expected: *u8, desired: u8, success: i32, failure: i32) callconv(.C) i32 {
238 return atomic_compare_exchange_N(u8, ptr, expected, desired, success, failure);
239}
240
241fn __atomic_compare_exchange_2(ptr: *u16, expected: *u16, desired: u16, success: i32, failure: i32) callconv(.C) i32 {
242 return atomic_compare_exchange_N(u16, ptr, expected, desired, success, failure);
243}
244
245fn __atomic_compare_exchange_4(ptr: *u32, expected: *u32, desired: u32, success: i32, failure: i32) callconv(.C) i32 {
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;
257271 }
272
273 return @atomicRmw(T, ptr, op, val, .SeqCst);
258274}
259275
260fn fetchFn(comptime T: type, comptime op: std.builtin.AtomicRmwOp) fn (*T, T, i32) callconv(.C) T {
261 return struct {
262 pub fn fetch_op_N(ptr: *T, val: T, model: i32) callconv(.C) T {
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 }
276fn __atomic_fetch_add_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 {
277 return fetch_op_N(u8, .Add, ptr, val, model);
278}
281279
282 return @atomicRmw(T, ptr, op, val, .SeqCst);
283 }
284 }.fetch_op_N;
280fn __atomic_fetch_add_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 {
281 return fetch_op_N(u16, .Add, ptr, val, model);
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);
285370}
286371
287372comptime {
288373 if (supports_atomic_ops) {
289 const fetch_add_u8 = fetchFn(u8, .Add);
290 const fetch_add_u16 = fetchFn(u16, .Add);
291 const fetch_add_u32 = fetchFn(u32, .Add);
292 const fetch_add_u64 = fetchFn(u64, .Add);
293 @export(fetch_add_u8, .{ .name = "__atomic_fetch_add_1", .linkage = linkage });
294 @export(fetch_add_u16, .{ .name = "__atomic_fetch_add_2", .linkage = linkage });
295 @export(fetch_add_u32, .{ .name = "__atomic_fetch_add_4", .linkage = linkage });
296 @export(fetch_add_u64, .{ .name = "__atomic_fetch_add_8", .linkage = linkage });
297
298 const fetch_sub_u8 = fetchFn(u8, .Sub);
299 const fetch_sub_u16 = fetchFn(u16, .Sub);
300 const fetch_sub_u32 = fetchFn(u32, .Sub);
301 const fetch_sub_u64 = fetchFn(u64, .Sub);
302 @export(fetch_sub_u8, .{ .name = "__atomic_fetch_sub_1", .linkage = linkage });
303 @export(fetch_sub_u16, .{ .name = "__atomic_fetch_sub_2", .linkage = linkage });
304 @export(fetch_sub_u32, .{ .name = "__atomic_fetch_sub_4", .linkage = linkage });
305 @export(fetch_sub_u64, .{ .name = "__atomic_fetch_sub_8", .linkage = linkage });
306
307 const fetch_and_u8 = fetchFn(u8, .And);
308 const fetch_and_u16 = fetchFn(u16, .And);
309 const fetch_and_u32 = fetchFn(u32, .And);
310 const fetch_and_u64 = fetchFn(u64, .And);
311 @export(fetch_and_u8, .{ .name = "__atomic_fetch_and_1", .linkage = linkage });
312 @export(fetch_and_u16, .{ .name = "__atomic_fetch_and_2", .linkage = linkage });
313 @export(fetch_and_u32, .{ .name = "__atomic_fetch_and_4", .linkage = linkage });
314 @export(fetch_and_u64, .{ .name = "__atomic_fetch_and_8", .linkage = linkage });
315
316 const fetch_or_u8 = fetchFn(u8, .Or);
317 const fetch_or_u16 = fetchFn(u16, .Or);
318 const fetch_or_u32 = fetchFn(u32, .Or);
319 const fetch_or_u64 = fetchFn(u64, .Or);
320 @export(fetch_or_u8, .{ .name = "__atomic_fetch_or_1", .linkage = linkage });
321 @export(fetch_or_u16, .{ .name = "__atomic_fetch_or_2", .linkage = linkage });
322 @export(fetch_or_u32, .{ .name = "__atomic_fetch_or_4", .linkage = linkage });
323 @export(fetch_or_u64, .{ .name = "__atomic_fetch_or_8", .linkage = linkage });
324
325 const fetch_xor_u8 = fetchFn(u8, .Xor);
326 const fetch_xor_u16 = fetchFn(u16, .Xor);
327 const fetch_xor_u32 = fetchFn(u32, .Xor);
328 const fetch_xor_u64 = fetchFn(u64, .Xor);
329 @export(fetch_xor_u8, .{ .name = "__atomic_fetch_xor_1", .linkage = linkage });
330 @export(fetch_xor_u16, .{ .name = "__atomic_fetch_xor_2", .linkage = linkage });
331 @export(fetch_xor_u32, .{ .name = "__atomic_fetch_xor_4", .linkage = linkage });
332 @export(fetch_xor_u64, .{ .name = "__atomic_fetch_xor_8", .linkage = linkage });
333
334 const fetch_nand_u8 = fetchFn(u8, .Nand);
335 const fetch_nand_u16 = fetchFn(u16, .Nand);
336 const fetch_nand_u32 = fetchFn(u32, .Nand);
337 const fetch_nand_u64 = fetchFn(u64, .Nand);
338 @export(fetch_nand_u8, .{ .name = "__atomic_fetch_nand_1", .linkage = linkage });
339 @export(fetch_nand_u16, .{ .name = "__atomic_fetch_nand_2", .linkage = linkage });
340 @export(fetch_nand_u32, .{ .name = "__atomic_fetch_nand_4", .linkage = linkage });
341 @export(fetch_nand_u64, .{ .name = "__atomic_fetch_nand_8", .linkage = linkage });
374 @export(__atomic_load, .{ .name = "__atomic_load", .linkage = linkage });
375 @export(__atomic_store, .{ .name = "__atomic_store", .linkage = linkage });
376 @export(__atomic_exchange, .{ .name = "__atomic_exchange", .linkage = linkage });
377 @export(__atomic_compare_exchange, .{ .name = "__atomic_compare_exchange", .linkage = linkage });
378
379 @export(__atomic_fetch_add_1, .{ .name = "__atomic_fetch_add_1", .linkage = linkage });
380 @export(__atomic_fetch_add_2, .{ .name = "__atomic_fetch_add_2", .linkage = linkage });
381 @export(__atomic_fetch_add_4, .{ .name = "__atomic_fetch_add_4", .linkage = linkage });
382 @export(__atomic_fetch_add_8, .{ .name = "__atomic_fetch_add_8", .linkage = linkage });
383
384 @export(__atomic_fetch_sub_1, .{ .name = "__atomic_fetch_sub_1", .linkage = linkage });
385 @export(__atomic_fetch_sub_2, .{ .name = "__atomic_fetch_sub_2", .linkage = linkage });
386 @export(__atomic_fetch_sub_4, .{ .name = "__atomic_fetch_sub_4", .linkage = linkage });
387 @export(__atomic_fetch_sub_8, .{ .name = "__atomic_fetch_sub_8", .linkage = linkage });
388
389 @export(__atomic_fetch_and_1, .{ .name = "__atomic_fetch_and_1", .linkage = linkage });
390 @export(__atomic_fetch_and_2, .{ .name = "__atomic_fetch_and_2", .linkage = linkage });
391 @export(__atomic_fetch_and_4, .{ .name = "__atomic_fetch_and_4", .linkage = linkage });
392 @export(__atomic_fetch_and_8, .{ .name = "__atomic_fetch_and_8", .linkage = linkage });
393
394 @export(__atomic_fetch_or_1, .{ .name = "__atomic_fetch_or_1", .linkage = linkage });
395 @export(__atomic_fetch_or_2, .{ .name = "__atomic_fetch_or_2", .linkage = linkage });
396 @export(__atomic_fetch_or_4, .{ .name = "__atomic_fetch_or_4", .linkage = linkage });
397 @export(__atomic_fetch_or_8, .{ .name = "__atomic_fetch_or_8", .linkage = linkage });
398
399 @export(__atomic_fetch_xor_1, .{ .name = "__atomic_fetch_xor_1", .linkage = linkage });
400 @export(__atomic_fetch_xor_2, .{ .name = "__atomic_fetch_xor_2", .linkage = linkage });
401 @export(__atomic_fetch_xor_4, .{ .name = "__atomic_fetch_xor_4", .linkage = linkage });
402 @export(__atomic_fetch_xor_8, .{ .name = "__atomic_fetch_xor_8", .linkage = linkage });
403
404 @export(__atomic_fetch_nand_1, .{ .name = "__atomic_fetch_nand_1", .linkage = linkage });
405 @export(__atomic_fetch_nand_2, .{ .name = "__atomic_fetch_nand_2", .linkage = linkage });
406 @export(__atomic_fetch_nand_4, .{ .name = "__atomic_fetch_nand_4", .linkage = linkage });
407 @export(__atomic_fetch_nand_8, .{ .name = "__atomic_fetch_nand_8", .linkage = linkage });
408
409 @export(__atomic_load_1, .{ .name = "__atomic_load_1", .linkage = linkage });
410 @export(__atomic_load_2, .{ .name = "__atomic_load_2", .linkage = linkage });
411 @export(__atomic_load_4, .{ .name = "__atomic_load_4", .linkage = linkage });
412 @export(__atomic_load_8, .{ .name = "__atomic_load_8", .linkage = linkage });
413
414 @export(__atomic_store_1, .{ .name = "__atomic_store_1", .linkage = linkage });
415 @export(__atomic_store_2, .{ .name = "__atomic_store_2", .linkage = linkage });
416 @export(__atomic_store_4, .{ .name = "__atomic_store_4", .linkage = linkage });
417 @export(__atomic_store_8, .{ .name = "__atomic_store_8", .linkage = linkage });
418
419 @export(__atomic_exchange_1, .{ .name = "__atomic_exchange_1", .linkage = linkage });
420 @export(__atomic_exchange_2, .{ .name = "__atomic_exchange_2", .linkage = linkage });
421 @export(__atomic_exchange_4, .{ .name = "__atomic_exchange_4", .linkage = linkage });
422 @export(__atomic_exchange_8, .{ .name = "__atomic_exchange_8", .linkage = linkage });
423
424 @export(__atomic_compare_exchange_1, .{ .name = "__atomic_compare_exchange_1", .linkage = linkage });
425 @export(__atomic_compare_exchange_2, .{ .name = "__atomic_compare_exchange_2", .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 });
342428 }
343429}
lib/std/special/compiler_rt/bswap.zig+55-55
......@@ -2,7 +2,7 @@ const std = @import("std");
22const builtin = @import("builtin");
33
44// bswap - byteswap
5// - bswapXi2_generic for unoptimized big and little endian
5// - bswapXi2 for unoptimized big and little endian
66// ie for u32
77// DE AD BE EF <- little|big endian
88// FE BE AD DE <- big|little endian
......@@ -11,64 +11,64 @@ const builtin = @import("builtin");
1111// 00 00 ff 00 << 1*8 (2n right byte)
1212// 00 00 00 ff << 3*8 (rightmost byte)
1313
14fn bswapXi2_generic(comptime T: type) fn (a: T) callconv(.C) T {
15 return struct {
16 fn f(a: T) callconv(.C) T {
17 @setRuntimeSafety(builtin.is_test);
18 switch (@bitSizeOf(T)) {
19 32 => {
20 // zig fmt: off
21 return (((a & 0xff000000) >> 24)
22 | ((a & 0x00ff0000) >> 8 )
23 | ((a & 0x0000ff00) << 8 )
24 | ((a & 0x000000ff) << 24));
25 // zig fmt: on
26 },
27 64 => {
28 // zig fmt: off
29 return (((a & 0xff00000000000000) >> 56)
30 | ((a & 0x00ff000000000000) >> 40 )
31 | ((a & 0x0000ff0000000000) >> 24 )
32 | ((a & 0x000000ff00000000) >> 8 )
33 | ((a & 0x00000000ff000000) << 8 )
34 | ((a & 0x0000000000ff0000) << 24 )
35 | ((a & 0x000000000000ff00) << 40 )
36 | ((a & 0x00000000000000ff) << 56));
37 // zig fmt: on
38 },
39 128 => {
40 // zig fmt: off
41 return (((a & 0xff000000000000000000000000000000) >> 120)
42 | ((a & 0x00ff0000000000000000000000000000) >> 104)
43 | ((a & 0x0000ff00000000000000000000000000) >> 88 )
44 | ((a & 0x000000ff000000000000000000000000) >> 72 )
45 | ((a & 0x00000000ff0000000000000000000000) >> 56 )
46 | ((a & 0x0000000000ff00000000000000000000) >> 40 )
47 | ((a & 0x000000000000ff000000000000000000) >> 24 )
48 | ((a & 0x00000000000000ff0000000000000000) >> 8 )
49 | ((a & 0x0000000000000000ff00000000000000) << 8 )
50 | ((a & 0x000000000000000000ff000000000000) << 24 )
51 | ((a & 0x00000000000000000000ff0000000000) << 40 )
52 | ((a & 0x0000000000000000000000ff00000000) << 56 )
53 | ((a & 0x000000000000000000000000ff000000) << 72 )
54 | ((a & 0x00000000000000000000000000ff0000) << 88 )
55 | ((a & 0x0000000000000000000000000000ff00) << 104)
56 | ((a & 0x000000000000000000000000000000ff) << 120));
57 // zig fmt: on
58 },
59 else => {
60 unreachable;
61 },
62 }
63 }
64 }.f;
14inline fn bswapXi2(comptime T: type, a: T) T {
15 @setRuntimeSafety(builtin.is_test);
16 switch (@bitSizeOf(T)) {
17 32 => {
18 // zig fmt: off
19 return (((a & 0xff000000) >> 24)
20 | ((a & 0x00ff0000) >> 8 )
21 | ((a & 0x0000ff00) << 8 )
22 | ((a & 0x000000ff) << 24));
23 // zig fmt: on
24 },
25 64 => {
26 // zig fmt: off
27 return (((a & 0xff00000000000000) >> 56)
28 | ((a & 0x00ff000000000000) >> 40 )
29 | ((a & 0x0000ff0000000000) >> 24 )
30 | ((a & 0x000000ff00000000) >> 8 )
31 | ((a & 0x00000000ff000000) << 8 )
32 | ((a & 0x0000000000ff0000) << 24 )
33 | ((a & 0x000000000000ff00) << 40 )
34 | ((a & 0x00000000000000ff) << 56));
35 // zig fmt: on
36 },
37 128 => {
38 // zig fmt: off
39 return (((a & 0xff000000000000000000000000000000) >> 120)
40 | ((a & 0x00ff0000000000000000000000000000) >> 104)
41 | ((a & 0x0000ff00000000000000000000000000) >> 88 )
42 | ((a & 0x000000ff000000000000000000000000) >> 72 )
43 | ((a & 0x00000000ff0000000000000000000000) >> 56 )
44 | ((a & 0x0000000000ff00000000000000000000) >> 40 )
45 | ((a & 0x000000000000ff000000000000000000) >> 24 )
46 | ((a & 0x00000000000000ff0000000000000000) >> 8 )
47 | ((a & 0x0000000000000000ff00000000000000) << 8 )
48 | ((a & 0x000000000000000000ff000000000000) << 24 )
49 | ((a & 0x00000000000000000000ff0000000000) << 40 )
50 | ((a & 0x0000000000000000000000ff00000000) << 56 )
51 | ((a & 0x000000000000000000000000ff000000) << 72 )
52 | ((a & 0x00000000000000000000000000ff0000) << 88 )
53 | ((a & 0x0000000000000000000000000000ff00) << 104)
54 | ((a & 0x000000000000000000000000000000ff) << 120));
55 // zig fmt: on
56 },
57 else => unreachable,
58 }
6559}
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
7373test {
7474 _ = @import("bswapsi2_test.zig");
lib/std/special/compiler_rt/cmp.zig+34-22
......@@ -11,28 +11,40 @@ const builtin = @import("builtin");
1111// a == b => 1
1212// a > b => 2
1313
14fn XcmpXi2_generic(comptime T: type) fn (a: T, b: T) callconv(.C) i32 {
15 return struct {
16 fn f(a: T, b: T) callconv(.C) i32 {
17 @setRuntimeSafety(builtin.is_test);
18 var cmp1: i32 = 0;
19 var cmp2: i32 = 0;
20 if (a > b)
21 cmp1 = 1;
22 if (a < b)
23 cmp2 = 1;
24 return cmp1 - cmp2 + 1;
25 }
26 }.f;
27}
28
29pub const __cmpsi2 = XcmpXi2_generic(i32);
30pub const __cmpdi2 = XcmpXi2_generic(i64);
31pub const __cmpti2 = XcmpXi2_generic(i128);
32
33pub const __ucmpsi2 = XcmpXi2_generic(u32);
34pub const __ucmpdi2 = XcmpXi2_generic(u64);
35pub const __ucmpti2 = XcmpXi2_generic(u128);
14inline fn XcmpXi2(comptime T: type, a: T, b: T) i32 {
15 @setRuntimeSafety(builtin.is_test);
16 var cmp1: i32 = 0;
17 var cmp2: i32 = 0;
18 if (a > b)
19 cmp1 = 1;
20 if (a < b)
21 cmp2 = 1;
22 return cmp1 - cmp2 + 1;
23}
24
25pub fn __cmpsi2(a: i32, b: i32) callconv(.C) i32 {
26 return XcmpXi2(i32, a, b);
27}
28
29pub fn __cmpdi2(a: i64, b: i64) callconv(.C) i32 {
30 return XcmpXi2(i64, a, b);
31}
32
33pub fn __cmpti2(a: i128, b: i128) callconv(.C) i32 {
34 return XcmpXi2(i128, a, b);
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
3749test {
3850 _ = @import("cmpsi2_test.zig");
lib/std/special/compiler_rt/count0bits.zig+122-116
......@@ -2,44 +2,40 @@ const std = @import("std");
22const builtin = @import("builtin");
33
44// clz - count leading zeroes
5// - clzXi2_generic for unoptimized little and big endian
5// - clzXi2 for unoptimized little and big endian
66// - __clzsi2_thumb1: assume a != 0
77// - __clzsi2_arm32: assume a != 0
88
99// ctz - count trailing zeroes
10// - ctzXi2_generic for unoptimized little and big endian
10// - ctzXi2 for unoptimized little and big endian
1111
1212// ffs - find first set
1313// * ffs = (a == 0) => 0, (a != 0) => ctz + 1
1414// * dont pay for `if (x == 0) return shift;` inside ctz
15// - ffsXi2_generic for unoptimized little and big endian
16
17fn clzXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {
18 return struct {
19 fn f(a: T) callconv(.C) i32 {
20 @setRuntimeSafety(builtin.is_test);
21
22 var x = switch (@bitSizeOf(T)) {
23 32 => @bitCast(u32, a),
24 64 => @bitCast(u64, a),
25 128 => @bitCast(u128, a),
26 else => unreachable,
27 };
28 var n: T = @bitSizeOf(T);
29 // Count first bit set using binary search, from Hacker's Delight
30 var y: @TypeOf(x) = 0;
31 comptime var shift: u8 = @bitSizeOf(T);
32 inline while (shift > 0) {
33 shift = shift >> 1;
34 y = x >> shift;
35 if (y != 0) {
36 n = n - shift;
37 x = y;
38 }
39 }
40 return @intCast(i32, n - @bitCast(T, x));
15// - ffsXi2 for unoptimized little and big endian
16
17inline fn clzXi2(comptime T: type, a: T) i32 {
18 @setRuntimeSafety(builtin.is_test);
19
20 var x = switch (@bitSizeOf(T)) {
21 32 => @bitCast(u32, a),
22 64 => @bitCast(u64, a),
23 128 => @bitCast(u128, a),
24 else => unreachable,
25 };
26 var n: T = @bitSizeOf(T);
27 // Count first bit set using binary search, from Hacker's Delight
28 var y: @TypeOf(x) = 0;
29 comptime var shift: u8 = @bitSizeOf(T);
30 inline while (shift > 0) {
31 shift = shift >> 1;
32 y = x >> shift;
33 if (y != 0) {
34 n = n - shift;
35 x = y;
4136 }
42 }.f;
37 }
38 return @intCast(i32, n - @bitCast(T, x));
4339}
4440
4541fn __clzsi2_thumb1() callconv(.Naked) void {
......@@ -125,103 +121,113 @@ fn __clzsi2_arm32() callconv(.Naked) void {
125121 unreachable;
126122}
127123
128pub const __clzsi2 = impl: {
129 switch (builtin.cpu.arch) {
130 .arm, .armeb, .thumb, .thumbeb => {
131 const use_thumb1 =
132 (builtin.cpu.arch.isThumb() or
133 std.Target.arm.featureSetHas(builtin.cpu.features, .noarm)) and
134 !std.Target.arm.featureSetHas(builtin.cpu.features, .thumb2);
135
136 if (use_thumb1) {
137 break :impl __clzsi2_thumb1;
138 }
139 // From here on we're either targeting Thumb2 or ARM.
140 else if (!builtin.cpu.arch.isThumb()) {
141 break :impl __clzsi2_arm32;
142 }
143 // Use the generic implementation otherwise.
144 else break :impl clzXi2_generic(i32);
145 },
146 else => break :impl clzXi2_generic(i32),
147 }
124fn clzsi2_generic(a: i32) callconv(.C) i32 {
125 return clzXi2(i32, a);
126}
127
128pub const __clzsi2 = switch (builtin.cpu.arch) {
129 .arm, .armeb, .thumb, .thumbeb => impl: {
130 const use_thumb1 =
131 (builtin.cpu.arch.isThumb() or
132 std.Target.arm.featureSetHas(builtin.cpu.features, .noarm)) and
133 !std.Target.arm.featureSetHas(builtin.cpu.features, .thumb2);
134
135 if (use_thumb1) {
136 break :impl __clzsi2_thumb1;
137 }
138 // From here on we're either targeting Thumb2 or ARM.
139 else if (!builtin.cpu.arch.isThumb()) {
140 break :impl __clzsi2_arm32;
141 }
142 // Use the generic implementation otherwise.
143 else break :impl clzsi2_generic;
144 },
145 else => clzsi2_generic,
148146};
149147
150pub const __clzdi2 = clzXi2_generic(i64);
151
152pub const __clzti2 = clzXi2_generic(i128);
153
154fn ctzXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {
155 return struct {
156 fn f(a: T) callconv(.C) i32 {
157 @setRuntimeSafety(builtin.is_test);
158
159 var x = switch (@bitSizeOf(T)) {
160 32 => @bitCast(u32, a),
161 64 => @bitCast(u64, a),
162 128 => @bitCast(u128, a),
163 else => unreachable,
164 };
165 var n: T = 1;
166 // Number of trailing zeroes as binary search, from Hacker's Delight
167 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));
168 comptime var shift = @bitSizeOf(T);
169 if (x == 0) return shift;
170 inline while (shift > 1) {
171 shift = shift >> 1;
172 mask = mask >> shift;
173 if ((x & mask) == 0) {
174 n = n + shift;
175 x = x >> shift;
176 }
177 }
178 return @intCast(i32, n - @bitCast(T, (x & 1)));
148pub fn __clzdi2(a: i64) callconv(.C) i32 {
149 return clzXi2(i64, a);
150}
151
152pub fn __clzti2(a: i128) callconv(.C) i32 {
153 return clzXi2(i128, a);
154}
155
156inline fn ctzXi2(comptime T: type, a: T) i32 {
157 @setRuntimeSafety(builtin.is_test);
158
159 var x = switch (@bitSizeOf(T)) {
160 32 => @bitCast(u32, a),
161 64 => @bitCast(u64, a),
162 128 => @bitCast(u128, a),
163 else => unreachable,
164 };
165 var n: T = 1;
166 // Number of trailing zeroes as binary search, from Hacker's Delight
167 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));
168 comptime var shift = @bitSizeOf(T);
169 if (x == 0) return shift;
170 inline while (shift > 1) {
171 shift = shift >> 1;
172 mask = mask >> shift;
173 if ((x & mask) == 0) {
174 n = n + shift;
175 x = x >> shift;
179176 }
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);
181183}
182184
183pub const __ctzsi2 = ctzXi2_generic(i32);
184
185pub const __ctzdi2 = ctzXi2_generic(i64);
186
187pub const __ctzti2 = ctzXi2_generic(i128);
188
189fn ffsXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {
190 return struct {
191 fn f(a: T) callconv(.C) i32 {
192 @setRuntimeSafety(builtin.is_test);
193
194 var x = switch (@bitSizeOf(T)) {
195 32 => @bitCast(u32, a),
196 64 => @bitCast(u64, a),
197 128 => @bitCast(u128, a),
198 else => unreachable,
199 };
200 var n: T = 1;
201 // adapted from Number of trailing zeroes (see ctzXi2_generic)
202 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));
203 comptime var shift = @bitSizeOf(T);
204 // In contrast to ctz return 0
205 if (x == 0) return 0;
206 inline while (shift > 1) {
207 shift = shift >> 1;
208 mask = mask >> shift;
209 if ((x & mask) == 0) {
210 n = n + shift;
211 x = x >> shift;
212 }
213 }
214 // return ctz + 1
215 return @intCast(i32, n - @bitCast(T, (x & 1))) + @as(i32, 1);
185pub fn __ctzdi2(a: i64) callconv(.C) i32 {
186 return ctzXi2(i64, a);
187}
188
189pub fn __ctzti2(a: i128) callconv(.C) i32 {
190 return ctzXi2(i128, a);
191}
192
193inline fn ffsXi2(comptime T: type, a: T) i32 {
194 @setRuntimeSafety(builtin.is_test);
195
196 var x = switch (@bitSizeOf(T)) {
197 32 => @bitCast(u32, a),
198 64 => @bitCast(u64, a),
199 128 => @bitCast(u128, a),
200 else => unreachable,
201 };
202 var n: T = 1;
203 // adapted from Number of trailing zeroes (see ctzXi2)
204 var mask: @TypeOf(x) = std.math.maxInt(@TypeOf(x));
205 comptime var shift = @bitSizeOf(T);
206 // In contrast to ctz return 0
207 if (x == 0) return 0;
208 inline while (shift > 1) {
209 shift = shift >> 1;
210 mask = mask >> shift;
211 if ((x & mask) == 0) {
212 n = n + shift;
213 x = x >> shift;
216214 }
217 }.f;
215 }
216 // return ctz + 1
217 return @intCast(i32, n - @bitCast(T, (x & 1))) + @as(i32, 1);
218218}
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
226232test {
227233 _ = @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 {
3535 var scale: i32 = 0;
3636
3737 // 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) {
3939 const aAbs: Z = @bitCast(Z, a) & absMask;
4040 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 {
3434 var scale: i32 = 0;
3535
3636 // 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) {
3838 const aAbs: Z = @bitCast(Z, a) & absMask;
3939 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 {
3333 var scale: i32 = 0;
3434
3535 // 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) {
3737 const aAbs: Z = @bitCast(Z, a) & absMask;
3838 const bAbs: Z = @bitCast(Z, b) & absMask;
3939
lib/std/special/compiler_rt/fixuint.zig+1-1
......@@ -1,7 +1,7 @@
11const is_test = @import("builtin").is_test;
22const 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 {
55 @setRuntimeSafety(is_test);
66
77 const rep_t = switch (fp_t) {
lib/std/special/compiler_rt/floatXisf.zig+4-7
......@@ -4,7 +4,7 @@ const maxInt = std.math.maxInt;
44
55const FLT_MANT_DIG = 24;
66
7fn __floatXisf(comptime T: type, arg: T) f32 {
7inline fn floatXisf(comptime T: type, arg: T) f32 {
88 @setRuntimeSafety(builtin.is_test);
99
1010 const bits = @typeInfo(T).Int.bits;
......@@ -71,18 +71,15 @@ fn __floatXisf(comptime T: type, arg: T) f32 {
7171}
7272
7373pub fn __floatdisf(arg: i64) callconv(.C) f32 {
74 @setRuntimeSafety(builtin.is_test);
75 return @call(.{ .modifier = .always_inline }, __floatXisf, .{ i64, arg });
74 return floatXisf(i64, arg);
7675}
7776
7877pub fn __floattisf(arg: i128) callconv(.C) f32 {
79 @setRuntimeSafety(builtin.is_test);
80 return @call(.{ .modifier = .always_inline }, __floatXisf, .{ i128, arg });
78 return floatXisf(i128, arg);
8179}
8280
8381pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 {
84 @setRuntimeSafety(false);
85 return @call(.{ .modifier = .always_inline }, __floatdisf, .{arg});
82 return floatXisf(i64, arg);
8683}
8784
8885test {
lib/std/special/compiler_rt/floatsiXf.zig+6-6
......@@ -2,7 +2,7 @@ const builtin = @import("builtin");
22const std = @import("std");
33const maxInt = std.math.maxInt;
44
5fn floatsiXf(comptime T: type, a: i32) T {
5inline fn floatsiXf(comptime T: type, a: i32) T {
66 @setRuntimeSafety(builtin.is_test);
77
88 const bits = @typeInfo(T).Float.bits;
......@@ -56,27 +56,27 @@ fn floatsiXf(comptime T: type, a: i32) T {
5656
5757pub fn __floatsisf(arg: i32) callconv(.C) f32 {
5858 @setRuntimeSafety(builtin.is_test);
59 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f32, arg });
59 return floatsiXf(f32, arg);
6060}
6161
6262pub fn __floatsidf(arg: i32) callconv(.C) f64 {
6363 @setRuntimeSafety(builtin.is_test);
64 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f64, arg });
64 return floatsiXf(f64, arg);
6565}
6666
6767pub fn __floatsitf(arg: i32) callconv(.C) f128 {
6868 @setRuntimeSafety(builtin.is_test);
69 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f128, arg });
69 return floatsiXf(f128, arg);
7070}
7171
7272pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 {
7373 @setRuntimeSafety(false);
74 return @call(.{ .modifier = .always_inline }, __floatsidf, .{arg});
74 return floatsiXf(f64, arg);
7575}
7676
7777pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 {
7878 @setRuntimeSafety(false);
79 return @call(.{ .modifier = .always_inline }, __floatsisf, .{arg});
79 return floatsiXf(f32, arg);
8080}
8181
8282fn 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;
44
55const FLT_MANT_DIG = 24;
66
7pub fn __floatundisf(arg: u64) callconv(.C) f32 {
7inline fn floatundisf(arg: u64) f32 {
88 @setRuntimeSafety(builtin.is_test);
99
1010 if (arg == 0) return 0;
......@@ -56,9 +56,12 @@ pub fn __floatundisf(arg: u64) callconv(.C) f32 {
5656 return @bitCast(f32, result);
5757}
5858
59pub fn __floatundisf(arg: u64) callconv(.C) f32 {
60 return floatundisf(arg);
61}
62
5963pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 {
60 @setRuntimeSafety(false);
61 return @call(.{ .modifier = .always_inline }, __floatundisf, .{arg});
64 return floatundisf(arg);
6265}
6366
6467fn 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;
44
55const implicitBit = @as(u64, 1) << 52;
66
7pub fn __floatunsidf(arg: u32) callconv(.C) f64 {
7inline fn floatunsidf(arg: u32) f64 {
88 @setRuntimeSafety(builtin.is_test);
99
1010 if (arg == 0) return 0.0;
......@@ -18,9 +18,12 @@ pub fn __floatunsidf(arg: u32) callconv(.C) f64 {
1818 return @bitCast(f64, mant | (exp + 1023) << 52);
1919}
2020
21pub fn __floatunsidf(arg: u32) callconv(.C) f64 {
22 return floatunsidf(arg);
23}
24
2125pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 {
22 @setRuntimeSafety(false);
23 return @call(.{ .modifier = .always_inline }, __floatunsidf, .{arg});
26 return floatunsidf(arg);
2427}
2528
2629fn test_one_floatunsidf(a: u32, expected: u64) !void {
lib/std/special/compiler_rt/floatunsisf.zig+6-3
......@@ -6,7 +6,7 @@ const significandBits = 23;
66const exponentBias = 127;
77const implicitBit = @as(u32, 1) << significandBits;
88
9pub fn __floatunsisf(arg: u32) callconv(.C) f32 {
9inline fn floatunsisf(arg: u32) f32 {
1010 @setRuntimeSafety(builtin.is_test);
1111
1212 if (arg == 0) return 0.0;
......@@ -38,9 +38,12 @@ pub fn __floatunsisf(arg: u32) callconv(.C) f32 {
3838 return @bitCast(f32, result);
3939}
4040
41pub fn __floatunsisf(arg: u32) callconv(.C) f32 {
42 return floatunsisf(arg);
43}
44
4145pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 {
42 @setRuntimeSafety(false);
43 return @call(.{ .modifier = .always_inline }, __floatunsisf, .{arg});
46 return floatunsisf(arg);
4447}
4548
4649fn 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 {
5656 var scale: i32 = 0;
5757
5858 // 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) {
6060 const aAbs: Z = @bitCast(Z, a) & absMask;
6161 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");
22const builtin = @import("builtin");
33
44// neg - negate (the number)
5// - negXi2_generic for unoptimized little and big endian
5// - negXi2 for unoptimized little and big endian
66
77// sfffffff = 2^31-1
88// two's complement inverting bits and add 1 would result in -INT_MIN == 0
......@@ -11,20 +11,22 @@ const builtin = @import("builtin");
1111// * size optimized builds
1212// * machines that dont support carry operations
1313
14fn negXi2_generic(comptime T: type) fn (a: T) callconv(.C) T {
15 return struct {
16 fn f(a: T) callconv(.C) T {
17 @setRuntimeSafety(builtin.is_test);
18 return -a;
19 }
20 }.f;
14inline fn negXi2(comptime T: type, a: T) T {
15 @setRuntimeSafety(builtin.is_test);
16 return -a;
2117}
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
2931test {
3032 _ = @import("negsi2_test.zig");
lib/std/special/compiler_rt/negv.zig+24-19
......@@ -3,26 +3,31 @@
33// - negvXi4_generic for unoptimized version
44
55// assume -0 == 0 is gracefully handled by the hardware
6fn negvXi_generic(comptime ST: type) fn (a: ST) callconv(.C) ST {
7 return struct {
8 fn f(a: ST) callconv(.C) ST {
9 const UT = switch (ST) {
10 i32 => u32,
11 i64 => u64,
12 i128 => u128,
13 else => unreachable,
14 };
15 const N: UT = @bitSizeOf(ST);
16 const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1)));
17 if (a == min)
18 @panic("compiler_rt negv: overflow");
19 return -a;
20 }
21 }.f;
6inline fn negvXi(comptime ST: type, a: ST) ST {
7 const UT = switch (ST) {
8 i32 => u32,
9 i64 => u64,
10 i128 => u128,
11 else => unreachable,
12 };
13 const N: UT = @bitSizeOf(ST);
14 const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1)));
15 if (a == min)
16 @panic("compiler_rt negv: overflow");
17 return -a;
18}
19
20pub fn __negvsi2(a: i32) callconv(.C) i32 {
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);
2230}
23pub const __negvsi2 = negvXi_generic(i32);
24pub const __negvdi2 = negvXi_generic(i64);
25pub const __negvti2 = negvXi_generic(i128);
2631
2732test {
2833 _ = @import("negvsi2_test.zig");
lib/std/special/compiler_rt/parity.zig+25-23
......@@ -4,34 +4,36 @@ const builtin = @import("builtin");
44// parity - if number of bits set is even => 0, else => 1
55// - pariytXi2_generic for big and little endian
66
7fn parityXi2_generic(comptime T: type) fn (a: T) callconv(.C) i32 {
8 return struct {
9 fn f(a: T) callconv(.C) i32 {
10 @setRuntimeSafety(builtin.is_test);
7inline fn parityXi2(comptime T: type, a: T) i32 {
8 @setRuntimeSafety(builtin.is_test);
119
12 var x = switch (@bitSizeOf(T)) {
13 32 => @bitCast(u32, a),
14 64 => @bitCast(u64, a),
15 128 => @bitCast(u128, a),
16 else => unreachable,
17 };
18 // Bit Twiddling Hacks: Compute parity in parallel
19 comptime var shift: u8 = @bitSizeOf(T) / 2;
20 inline while (shift > 2) {
21 x ^= x >> shift;
22 shift = shift >> 1;
23 }
24 x &= 0xf;
25 return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>1
26 }
27 }.f;
10 var x = switch (@bitSizeOf(T)) {
11 32 => @bitCast(u32, a),
12 64 => @bitCast(u64, a),
13 128 => @bitCast(u128, a),
14 else => unreachable,
15 };
16 // Bit Twiddling Hacks: Compute parity in parallel
17 comptime var shift: u8 = @bitSizeOf(T) / 2;
18 inline while (shift > 2) {
19 x ^= x >> shift;
20 shift = shift >> 1;
21 }
22 x &= 0xf;
23 return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>1
2824}
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
3638test {
3739 _ = @import("paritysi2_test.zig");
lib/std/special/compiler_rt/popcount.zig+27-25
......@@ -10,35 +10,37 @@ const std = @import("std");
1010// TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques,
1111// subsubsection "Working with the rightmost bits" and "Sideways addition".
1212
13fn popcountXi2_generic(comptime ST: type) fn (a: ST) callconv(.C) i32 {
14 return struct {
15 fn f(a: ST) callconv(.C) i32 {
16 @setRuntimeSafety(builtin.is_test);
17 const UT = switch (ST) {
18 i32 => u32,
19 i64 => u64,
20 i128 => u128,
21 else => unreachable,
22 };
23 var x = @bitCast(UT, a);
24 x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos
25 x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles
26 + (x & (~@as(UT, 0) / 5));
27 x += x >> 4;
28 x &= ~@as(UT, 0) / 17; // 0x0F...0F, aggregate bytes
29 // 8 most significant bits of x + (x<<8) + (x<<16) + ..
30 x *%= ~@as(UT, 0) / 255; // 0x01...01
31 x >>= (@bitSizeOf(ST) - 8);
32 return @intCast(i32, x);
33 }
34 }.f;
13inline fn popcountXi2(comptime ST: type, a: ST) i32 {
14 @setRuntimeSafety(builtin.is_test);
15 const UT = switch (ST) {
16 i32 => u32,
17 i64 => u64,
18 i128 => u128,
19 else => unreachable,
20 };
21 var x = @bitCast(UT, a);
22 x -= (x >> 1) & (~@as(UT, 0) / 3); // 0x55...55, aggregate duos
23 x = ((x >> 2) & (~@as(UT, 0) / 5)) // 0x33...33, aggregate nibbles
24 + (x & (~@as(UT, 0) / 5));
25 x += x >> 4;
26 x &= ~@as(UT, 0) / 17; // 0x0F...0F, aggregate bytes
27 // 8 most significant bits of x + (x<<8) + (x<<16) + ..
28 x *%= ~@as(UT, 0) / 255; // 0x01...01
29 x >>= (@bitSizeOf(ST) - 8);
30 return @intCast(i32, x);
3531}
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
4345test {
4446 _ = @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 {
1919
2020// Arithmetic shift left
2121// 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 {
2323 const dwords = Dwords(T, false);
2424 const S = Log2Int(dwords.HalfT);
2525
......@@ -42,7 +42,7 @@ pub fn ashlXi3(comptime T: type, a: T, b: i32) T {
4242
4343// Arithmetic shift right
4444// 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 {
4646 const dwords = Dwords(T, true);
4747 const S = Log2Int(dwords.HalfT);
4848
......@@ -69,7 +69,7 @@ pub fn ashrXi3(comptime T: type, a: T, b: i32) T {
6969
7070// Logical shift right
7171// 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 {
7373 const dwords = Dwords(T, false);
7474 const S = Log2Int(dwords.HalfT);
7575
......@@ -91,32 +91,32 @@ pub fn lshrXi3(comptime T: type, a: T, b: i32) T {
9191}
9292
9393pub 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);
9595}
9696pub 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);
9898}
9999pub 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);
101101}
102102pub 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);
104104}
105105pub 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);
107107}
108108pub 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);
110110}
111111
112112pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {
113 return __ashldi3(a, b);
113 return ashlXi3(i64, a, b);
114114}
115115pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {
116 return __ashrdi3(a, b);
116 return ashrXi3(i64, a, b);
117117}
118118pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {
119 return __lshrdi3(a, b);
119 return lshrXi3(i64, a, b);
120120}
121121
122122test {
src/Cache.zig+54-3
......@@ -47,10 +47,16 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{0} ** Hasher.key_length);
4747pub const File = struct {
4848 path: ?[]const u8,
4949 max_file_size: ?usize,
50 stat: fs.File.Stat,
50 stat: Stat,
5151 bin_digest: BinDigest,
5252 contents: ?[]const u8,
5353
54 pub const Stat = struct {
55 inode: fs.File.INode,
56 size: u64,
57 mtime: i128,
58 };
59
5460 pub fn deinit(self: *File, allocator: Allocator) void {
5561 if (self.path) |owned_slice| {
5662 allocator.free(owned_slice);
......@@ -424,7 +430,11 @@ pub const Manifest = struct {
424430 if (!size_match or !mtime_match or !inode_match) {
425431 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
429439 if (self.isProblematicTimestamp(cache_hash_file.stat.mtime)) {
430440 // The actual file has an unreliable timestamp, force it to be hashed
......@@ -530,7 +540,12 @@ pub const Manifest = struct {
530540 const file = try fs.cwd().openFile(ch_file.path.?, .{});
531541 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
535550 if (self.isProblematicTimestamp(ch_file.stat.mtime)) {
536551 // The actual file has an unreliable timestamp, force it to be hashed
......@@ -615,6 +630,42 @@ pub const Manifest = struct {
615630 try self.populateFileHash(new_ch_file);
616631 }
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
618669 pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
619670 assert(self.manifest_file != null);
620671
src/Compilation.zig+460-225
......@@ -41,8 +41,8 @@ gpa: Allocator,
4141arena_state: std.heap.ArenaAllocator.State,
4242bin_file: *link.File,
4343c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
44stage1_lock: ?Cache.Lock = null,
45stage1_cache_manifest: *Cache.Manifest = undefined,
44/// This is a pointer to a local variable inside `update()`.
45whole_cache_manifest: ?*Cache.Manifest = null,
4646
4747link_error_flags: link.File.ErrorFlags = .{},
4848
......@@ -98,6 +98,13 @@ clang_argv: []const []const u8,
9898cache_parent: *Cache,
9999/// Path to own executable for invoking `zig clang`.
100100self_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,
101108zig_lib_directory: Directory,
102109local_cache_directory: Directory,
103110global_cache_directory: Directory,
......@@ -418,7 +425,7 @@ pub const AllErrors = struct {
418425 const module_note = module_err_msg.notes[i];
419426 const source = try module_note.src_loc.file_scope.getSource(module.gpa);
420427 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);
422429 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
423430 note.* = .{
424431 .src = .{
......@@ -441,7 +448,7 @@ pub const AllErrors = struct {
441448 }
442449 const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);
443450 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);
445452 const file_path = try module_err_msg.src_loc.file_scope.fullPath(allocator);
446453 try errors.append(.{
447454 .src = .{
......@@ -612,6 +619,15 @@ pub const Directory = struct {
612619 return std.fs.path.joinZ(allocator, paths);
613620 }
614621 }
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 }
615631};
616632
617633pub const EmitLoc = struct {
......@@ -631,6 +647,7 @@ pub const ClangPreprocessorMode = enum {
631647};
632648
633649pub const SystemLib = link.SystemLib;
650pub const CacheMode = link.CacheMode;
634651
635652pub const InitOptions = struct {
636653 zig_lib_directory: Directory,
......@@ -668,6 +685,7 @@ pub const InitOptions = struct {
668685 /// is externally modified - essentially anything other than zig-cache - then
669686 /// this flag would be set to disable this machinery to avoid false positives.
670687 disable_lld_caching: bool = false,
688 cache_mode: CacheMode = .incremental,
671689 object_format: ?std.Target.ObjectFormat = null,
672690 optimize_mode: std.builtin.Mode = .Debug,
673691 keep_source_files_loaded: bool = false,
......@@ -885,6 +903,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
885903 break :blk build_options.is_stage1;
886904 };
887905
906 const cache_mode = if (use_stage1 and !options.disable_lld_caching)
907 CacheMode.whole
908 else
909 options.cache_mode;
910
888911 // Make a decision on whether to use LLVM or our own backend.
889912 const use_llvm = build_options.have_llvm and blk: {
890913 if (options.use_llvm) |explicit|
......@@ -1219,39 +1242,75 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
12191242 // modified between incremental updates.
12201243 var hash = cache.hash;
12211244
1222 // Here we put the root source file path name, but *not* with addFile. We want the
1223 // hash to be the same regardless of the contents of the source file, because
1224 // incremental compilation will handle it, but we do want to namespace different
1225 // source file names because they are likely different compilations and therefore this
1226 // would be likely to cause cache hits.
1227 hash.addBytes(main_pkg.root_src_path);
1228 hash.addOptionalBytes(main_pkg.root_src_directory.path);
1229 {
1230 var local_arena = std.heap.ArenaAllocator.init(gpa);
1231 defer local_arena.deinit();
1232 var seen_table = std.AutoHashMap(*Package, void).init(local_arena.allocator());
1233 try addPackageTableToCacheHash(&hash, &local_arena, main_pkg.table, &seen_table, .path_bytes);
1245 switch (cache_mode) {
1246 .incremental => {
1247 // Here we put the root source file path name, but *not* with addFile.
1248 // We want the hash to be the same regardless of the contents of the
1249 // source file, because incremental compilation will handle it, but we
1250 // do want to namespace different source file names because they are
1251 // likely different compilations and therefore this would be likely to
1252 // cause cache hits.
1253 hash.addBytes(main_pkg.root_src_path);
1254 hash.addOptionalBytes(main_pkg.root_src_directory.path);
1255 {
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 },
12341265 }
1266
1267 // Synchronize with other matching comments: ZigOnlyHashStuff
12351268 hash.add(valgrind);
12361269 hash.add(single_threaded);
12371270 hash.add(use_stage1);
12381271 hash.add(use_llvm);
12391272 hash.add(dll_export_fns);
12401273 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);
12411277 hash.add(options.skip_linker_dependencies);
12421278 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
12441303 const digest = hash.final();
12451304 const artifact_sub_dir = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
12461305 var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{});
12471306 errdefer artifact_dir.close();
12481307 const zig_cache_artifact_directory: Directory = .{
12491308 .handle = artifact_dir,
1250 .path = if (options.local_cache_directory.path) |p|
1251 try std.fs.path.join(arena, &[_][]const u8{ p, artifact_sub_dir })
1252 else
1253 artifact_sub_dir,
1309 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),
12541310 };
1311 log.debug("zig_cache_artifact_directory='{s}' use_stage1={}", .{
1312 zig_cache_artifact_directory.path, use_stage1,
1313 });
12551314
12561315 const builtin_pkg = try Package.createWithDir(
12571316 gpa,
......@@ -1374,6 +1433,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
13741433 };
13751434 }
13761435
1436 switch (cache_mode) {
1437 .whole => break :blk null,
1438 .incremental => {},
1439 }
1440
13771441 if (module) |zm| {
13781442 break :blk link.Emit{
13791443 .directory = zm.zig_cache_artifact_directory,
......@@ -1417,6 +1481,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14171481 };
14181482 }
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
14201490 // Use the same directory as the bin. The CLI already emits an
14211491 // error if -fno-emit-bin is combined with -femit-implib.
14221492 break :blk link.Emit{
......@@ -1425,6 +1495,16 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14251495 };
14261496 };
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
14281508 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};
14291509 errdefer system_libs.deinit(gpa);
14301510 try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len);
......@@ -1512,7 +1592,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15121592 .skip_linker_dependencies = options.skip_linker_dependencies,
15131593 .parent_compilation_link_libc = options.parent_compilation_link_libc,
15141594 .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,
15161597 .subsystem = options.subsystem,
15171598 .is_test = options.is_test,
15181599 .wasi_exec_model = wasi_exec_model,
......@@ -1529,6 +1610,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15291610 .local_cache_directory = options.local_cache_directory,
15301611 .global_cache_directory = options.global_cache_directory,
15311612 .bin_file = bin_file,
1613 .whole_bin_sub_path = whole_bin_sub_path,
1614 .whole_implib_sub_path = whole_implib_sub_path,
15321615 .emit_asm = options.emit_asm,
15331616 .emit_llvm_ir = options.emit_llvm_ir,
15341617 .emit_llvm_bc = options.emit_llvm_bc,
......@@ -1593,7 +1676,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15931676 comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
15941677 }
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) {
15971682 // If we need to build glibc for the target, add work items for it.
15981683 // We go through the work queue so that building can be done in parallel.
15991684 if (comp.wantBuildGLibCFromSource()) {
......@@ -1698,8 +1783,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
16981783
16991784 if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {
17001785 if (is_exe_or_dyn_lib) {
1786 log.debug("queuing a job to build compiler_rt_lib", .{});
17011787 try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });
17021788 } else if (options.output_mode != .Obj) {
1789 log.debug("queuing a job to build compiler_rt_obj", .{});
17031790 // If build-obj with -fcompiler-rt is requested, that is handled specially
17041791 // elsewhere. In this case we are making a static library, so we ask
17051792 // for a compiler-rt object to put in it.
......@@ -1725,20 +1812,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
17251812 return comp;
17261813}
17271814
1728fn releaseStage1Lock(comp: *Compilation) void {
1729 if (comp.stage1_lock) |*lock| {
1730 lock.release();
1731 comp.stage1_lock = null;
1732 }
1733}
1734
17351815pub fn destroy(self: *Compilation) void {
17361816 const optional_module = self.bin_file.options.module;
17371817 self.bin_file.destroy();
17381818 if (optional_module) |module| module.deinit();
17391819
1740 self.releaseStage1Lock();
1741
17421820 const gpa = self.gpa;
17431821 self.work_queue.deinit();
17441822 self.anon_work_queue.deinit();
......@@ -1815,22 +1893,126 @@ pub fn getTarget(self: Compilation) Target {
18151893 return self.bin_file.options.target;
18161894}
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
18181920/// 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 {
18201922 const tracy_trace = trace(@src());
18211923 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
18252007 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
18262008 // Add a Job for each C object.
1827 try self.c_object_work_queue.ensureUnusedCapacity(self.c_object_table.count());
1828 for (self.c_object_table.keys()) |key| {
1829 self.c_object_work_queue.writeItemAssumeCapacity(key);
2009 try comp.c_object_work_queue.ensureUnusedCapacity(comp.c_object_table.count());
2010 for (comp.c_object_table.keys()) |key| {
2011 comp.c_object_work_queue.writeItemAssumeCapacity(key);
18302012 }
18312013
1832 const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_stage1;
1833 if (self.bin_file.options.module) |module| {
2014 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
2015 if (comp.bin_file.options.module) |module| {
18342016 module.compile_log_text.shrinkAndFree(module.gpa, 0);
18352017 module.generation += 1;
18362018
......@@ -1845,7 +2027,7 @@ pub fn update(self: *Compilation) !void {
18452027 // import_table here.
18462028 // Likewise, in the case of `zig test`, the test runner is the root source file,
18472029 // 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) {
18492031 _ = try module.importPkg(module.main_pkg);
18502032 }
18512033
......@@ -1854,34 +2036,34 @@ pub fn update(self: *Compilation) !void {
18542036 // to update it.
18552037 // We still want AstGen work items for stage1 so that we expose compile errors
18562038 // 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());
18582040 for (module.import_table.values()) |value| {
1859 self.astgen_work_queue.writeItemAssumeCapacity(value);
2041 comp.astgen_work_queue.writeItemAssumeCapacity(value);
18602042 }
18612043
18622044 if (!use_stage1) {
18632045 // Put a work item in for checking if any files used with `@embedFile` changed.
18642046 {
1865 try self.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count());
2047 try comp.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count());
18662048 var it = module.embed_table.iterator();
18672049 while (it.next()) |entry| {
18682050 const embed_file = entry.value_ptr.*;
1869 self.embed_file_work_queue.writeItemAssumeCapacity(embed_file);
2051 comp.embed_file_work_queue.writeItemAssumeCapacity(embed_file);
18702052 }
18712053 }
18722054
1873 try self.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
1874 if (self.bin_file.options.is_test) {
1875 try self.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });
2055 try comp.work_queue.writeItem(.{ .analyze_pkg = std_pkg });
2056 if (comp.bin_file.options.is_test) {
2057 try comp.work_queue.writeItem(.{ .analyze_pkg = module.main_pkg });
18762058 }
18772059 }
18782060 }
18792061
1880 try self.performAllTheWork();
2062 try comp.performAllTheWork();
18812063
18822064 if (!use_stage1) {
1883 if (self.bin_file.options.module) |module| {
1884 if (self.bin_file.options.is_test and self.totalErrorCount() == 0) {
2065 if (comp.bin_file.options.module) |module| {
2066 if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
18852067 // The `test_functions` decl has been intentionally postponed until now,
18862068 // at which point we must populate it with the list of test functions that
18872069 // have been discovered and not filtered out.
......@@ -1910,41 +2092,241 @@ pub fn update(self: *Compilation) !void {
19102092 }
19112093 }
19122094
1913 if (self.totalErrorCount() != 0) {
1914 // Skip flushing.
1915 self.link_error_flags = .{};
2095 if (comp.totalErrorCount() != 0) {
2096 // Skip flushing and keep source files loaded for error reporting.
2097 comp.link_error_flags = .{};
19162098 return;
19172099 }
19182100
1919 // This is needed before reading the error flags.
1920 try self.bin_file.flush(self);
1921 self.link_error_flags = self.bin_file.errorFlags();
2101 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and
2102 // -femit-asm to handle, in the case of C objects.
2103 comp.emitOthers();
2104
2105 if (comp.whole_cache_manifest != null) {
2106 const digest = man.final();
19222107
1923 if (!use_stage1) {
1924 if (self.bin_file.options.module) |module| {
1925 try link.File.C.flushEmitH(module);
2108 // Rename the temporary directory into place.
2109 var directory = tmp_artifact_directory.?;
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();
19262139 }
1927 }
19282140
1929 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and
1930 // -femit-asm to handle, in the case of C objects.
1931 self.emitOthers();
2141 // Failure here only means an unnecessary cache miss.
2142 man.writeManifest() catch |err| {
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 loaded
1934 // to report error messages. Otherwise we unload all source files to save memory.
2152 // Unload all source files to save memory.
19352153 // The ZIR needs to stay loaded in memory because (1) Decl objects contain references
19362154 // to it, and (2) generic instantiations, comptime calls, inline calls will need
19372155 // to reference the ZIR.
1938 if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) {
1939 if (self.bin_file.options.module) |module| {
2156 if (!comp.keep_source_files_loaded) {
2157 if (comp.bin_file.options.module) |module| {
19402158 for (module.import_table.values()) |file| {
1941 file.unloadTree(self.gpa);
1942 file.unloadSource(self.gpa);
2159 file.unloadTree(comp.gpa);
2160 file.unloadSource(comp.gpa);
19432161 }
19442162 }
19452163 }
19462164}
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
19482330fn emitOthers(comp: *Compilation) void {
19492331 if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or
19502332 comp.c_object_table.count() == 0)
......@@ -2988,7 +3370,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
29883370
29893371 const dep_basename = std.fs.path.basename(out_dep_path);
29903372 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
29933377 const digest = man.final();
29943378 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
33513735 };
33523736}
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 {
33553739 const s = std.fs.path.sep_str;
33563740 const rand_int = std.crypto.random.int(u64);
33573741 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 });
33593743 } 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 });
33613745 }
33623746}
33633747
......@@ -4424,6 +4808,7 @@ fn buildOutputFromZig(
44244808 .global_cache_directory = comp.global_cache_directory,
44254809 .local_cache_directory = comp.global_cache_directory,
44264810 .zig_lib_directory = comp.zig_lib_directory,
4811 .cache_mode = .whole,
44274812 .target = target,
44284813 .root_name = root_name,
44294814 .main_pkg = &main_pkg,
......@@ -4501,10 +4886,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
45014886 mod.main_pkg.root_src_path,
45024887 });
45034888 const zig_lib_dir = comp.zig_lib_directory.path.?;
4504 const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"});
45054889 const target = comp.getTarget();
4506 const id_symlink_basename = "stage1.id";
4507 const libs_txt_basename = "libs.txt";
45084890
45094891 // The include_compiler_rt stored in the bin file options here means that we need
45104892 // 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
45164898 const include_compiler_rt = comp.bin_file.options.output_mode == .Obj and
45174899 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
46284901 const stage2_target = try arena.create(stage1.Stage2Target);
46294902 stage2_target.* = .{
46304903 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
......@@ -4637,9 +4910,9 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
46374910 .llvm_target_abi = if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
46384911 };
46394912
4640 comp.stage1_cache_manifest = &man;
4641
46424913 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
46444917 const stage1_module = stage1.create(
46454918 @enumToInt(comp.bin_file.options.optimize_mode),
......@@ -4740,19 +5013,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
47405013 .have_dllmain_crt_startup = false,
47415014 };
47425015
4743 const inferred_lib_start_index = comp.bin_file.options.system_libs.count();
47445016 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
47565018 mod.stage1_flags = .{
47575019 .have_c_main = stage1_module.have_c_main,
47585020 .have_winmain = stage1_module.have_winmain,
......@@ -4763,34 +5025,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
47635025 };
47645026
47655027 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();
47945028}
47955029
47965030fn stage1LocPath(arena: Allocator, opt_loc: ?EmitLoc, cache_directory: Directory) ![]const u8 {
......@@ -4862,6 +5096,7 @@ pub fn build_crt_file(
48625096 .local_cache_directory = comp.global_cache_directory,
48635097 .global_cache_directory = comp.global_cache_directory,
48645098 .zig_lib_directory = comp.zig_lib_directory,
5099 .cache_mode = .whole,
48655100 .target = target,
48665101 .root_name = root_name,
48675102 .main_pkg = null,
src/Module.zig+114-45
......@@ -33,7 +33,7 @@ const build_options = @import("build_options");
3333gpa: Allocator,
3434comp: *Compilation,
3535
36/// Where our incremental compilation metadata serialization will go.
36/// Where build artifacts and incremental compilation metadata serialization go.
3737zig_cache_artifact_directory: Compilation.Directory,
3838/// Pointer to externally managed resource.
3939root_pkg: *Package,
......@@ -1463,11 +1463,7 @@ pub const File = struct {
14631463 /// Whether this is populated depends on `source_loaded`.
14641464 source: [:0]const u8,
14651465 /// Whether this is populated depends on `status`.
1466 stat_size: u64,
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,
1466 stat: Cache.File.Stat,
14711467 /// Whether this is populated or not depends on `tree_loaded`.
14721468 tree: Ast,
14731469 /// Whether this is populated or not depends on `zir_loaded`.
......@@ -1535,8 +1531,16 @@ pub const File = struct {
15351531 file.* = undefined;
15361532 }
15371533
1538 pub fn getSource(file: *File, gpa: Allocator) ![:0]const u8 {
1539 if (file.source_loaded) return file.source;
1534 pub const Source = struct {
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
15411545 const root_dir_path = file.pkg.root_src_directory.path orelse ".";
15421546 log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{
......@@ -1565,14 +1569,21 @@ pub const File = struct {
15651569
15661570 file.source = source;
15671571 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 };
15691580 }
15701581
15711582 pub fn getTree(file: *File, gpa: Allocator) !*const Ast {
15721583 if (file.tree_loaded) return &file.tree;
15731584
15741585 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);
15761587 file.tree_loaded = true;
15771588 return &file.tree;
15781589 }
......@@ -1631,9 +1642,7 @@ pub const EmbedFile = struct {
16311642 /// Memory is stored in gpa, owned by EmbedFile.
16321643 sub_file_path: []const u8,
16331644 bytes: [:0]const u8,
1634 stat_size: u64,
1635 stat_inode: std.fs.File.INode,
1636 stat_mtime: i128,
1645 stat: Cache.File.Stat,
16371646 /// Package that this file is a part of, managed externally.
16381647 pkg: *Package,
16391648 /// The Decl that was created from the `@embedFile` to own this resource.
......@@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
27042713 keep_zir = true;
27052714 file.zir = zir;
27062715 file.zir_loaded = true;
2707 file.stat_size = header.stat_size;
2708 file.stat_inode = header.stat_inode;
2709 file.stat_mtime = header.stat_mtime;
2716 file.stat = .{
2717 .size = header.stat_size,
2718 .inode = header.stat_inode,
2719 .mtime = header.stat_mtime,
2720 };
27102721 file.status = .success_zir;
27112722 log.debug("AstGen cached success: {s}", .{file.sub_file_path});
27122723
......@@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
27242735 },
27252736 .parse_failure, .astgen_failure, .success_zir => {
27262737 const unchanged_metadata =
2727 stat.size == file.stat_size and
2728 stat.mtime == file.stat_mtime and
2729 stat.inode == file.stat_inode;
2738 stat.size == file.stat.size and
2739 stat.mtime == file.stat.mtime and
2740 stat.inode == file.stat.inode;
27302741
27312742 if (unchanged_metadata) {
27322743 log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
......@@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
27872798 if (amt != stat.size)
27882799 return error.UnexpectedEndOfFile;
27892800
2790 file.stat_size = stat.size;
2791 file.stat_inode = stat.inode;
2792 file.stat_mtime = stat.mtime;
2801 file.stat = .{
2802 .size = stat.size,
2803 .inode = stat.inode,
2804 .mtime = stat.mtime,
2805 };
27932806 file.source = source;
27942807 file.source_loaded = true;
27952808
......@@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void {
30693082
30703083 try writeBuiltinFile(file, builtin_pkg);
30713084 } else {
3072 file.stat_size = stat.size;
3073 file.stat_inode = stat.inode;
3074 file.stat_mtime = stat.mtime;
3085 file.stat = .{
3086 .size = stat.size,
3087 .inode = stat.inode,
3088 .mtime = stat.mtime,
3089 };
30753090 }
30763091 } else |err| switch (err) {
30773092 error.BadPathName => unreachable, // it's always "builtin.zig"
......@@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
30993114 try af.file.writeAll(file.source);
31003115 try af.finish();
31013116
3102 file.stat_size = file.source.len;
3103 file.stat_inode = 0; // dummy value
3104 file.stat_mtime = 0; // dummy value
3117 file.stat = .{
3118 .size = file.source.len,
3119 .inode = 0, // dummy value
3120 .mtime = 0, // dummy value
3121 };
31053122}
31063123
31073124pub fn mapOldZirToNew(
......@@ -3380,6 +3397,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
33803397 error.OutOfMemory => return error.OutOfMemory,
33813398 error.AnalysisFail => {},
33823399 }
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 }
33833413 } else {
33843414 new_decl.analysis = .file_failure;
33853415 }
......@@ -3710,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
37103740 .source_loaded = false,
37113741 .tree_loaded = false,
37123742 .zir_loaded = false,
3713 .stat_size = undefined,
3714 .stat_inode = undefined,
3715 .stat_mtime = undefined,
3743 .stat = undefined,
37163744 .tree = undefined,
37173745 .zir = undefined,
37183746 .status = .never_loaded,
......@@ -3780,9 +3808,7 @@ pub fn importFile(
37803808 .source_loaded = false,
37813809 .tree_loaded = false,
37823810 .zir_loaded = false,
3783 .stat_size = undefined,
3784 .stat_inode = undefined,
3785 .stat_mtime = undefined,
3811 .stat = undefined,
37863812 .tree = undefined,
37873813 .zir = undefined,
37883814 .status = .never_loaded,
......@@ -3827,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
38273853 var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{});
38283854 defer file.close();
38293855
3830 const stat = try file.stat();
3831 const size_usize = try std.math.cast(usize, stat.size);
3856 const actual_stat = try file.stat();
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);
38323863 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
38333864 errdefer gpa.free(bytes);
38343865
......@@ -3836,14 +3867,18 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
38363867 resolved_root_path, resolved_path, sub_file_path, rel_file_path,
38373868 });
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
38393876 keep_resolved_path = true; // It's now owned by embed_table.
38403877 gop.value_ptr.* = new_file;
38413878 new_file.* = .{
38423879 .sub_file_path = sub_file_path,
38433880 .bytes = bytes,
3844 .stat_size = stat.size,
3845 .stat_inode = stat.inode,
3846 .stat_mtime = stat.mtime,
3881 .stat = stat,
38473882 .pkg = cur_file.pkg,
38483883 .owner_decl = undefined, // Set by Sema immediately after this function returns.
38493884 };
......@@ -3857,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
38573892 const stat = try file.stat();
38583893
38593894 const unchanged_metadata =
3860 stat.size == embed_file.stat_size and
3861 stat.mtime == embed_file.stat_mtime and
3862 stat.inode == embed_file.stat_inode;
3895 stat.size == embed_file.stat.size and
3896 stat.mtime == embed_file.stat.mtime and
3897 stat.inode == embed_file.stat.inode;
38633898
38643899 if (unchanged_metadata) return;
38653900
......@@ -3868,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
38683903 const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
38693904 gpa.free(embed_file.bytes);
38703905 embed_file.bytes = bytes;
3871 embed_file.stat_size = stat.size;
3872 embed_file.stat_mtime = stat.mtime;
3873 embed_file.stat_inode = stat.inode;
3906 embed_file.stat = .{
3907 .size = stat.size,
3908 .mtime = stat.mtime,
3909 .inode = stat.inode,
3910 };
38743911
38753912 mod.comp.mutex.lock();
38763913 defer mod.comp.mutex.unlock();
......@@ -5001,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void {
50015038 },
50025039 };
50035040}
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(
1468014680 instructions: []Air.Inst.Ref,
1468114681 candidate_srcs: Module.PeerTypeCandidateSrc,
1468214682) !Type {
14683 if (instructions.len == 0)
14684 return Type.initTag(.noreturn);
14685
14686 if (instructions.len == 1)
14687 return sema.typeOf(instructions[0]);
14683 switch (instructions.len) {
14684 0 => return Type.initTag(.noreturn),
14685 1 => return sema.typeOf(instructions[0]),
14686 else => {},
14687 }
1468814688
1468914689 const target = sema.mod.getTarget();
1469014690
......@@ -14714,13 +14714,14 @@ fn resolvePeerTypes(
1471414714 continue;
1471514715 },
1471614716 .Int => {
14717 if (chosen_ty.isSignedInt() == candidate_ty.isSignedInt()) {
14718 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {
14719 chosen = candidate;
14720 chosen_i = candidate_i + 1;
14721 }
14722 continue;
14717 const chosen_info = chosen_ty.intInfo(target);
14718 const candidate_info = candidate_ty.intInfo(target);
14719
14720 if (chosen_info.bits < candidate_info.bits) {
14721 chosen = candidate;
14722 chosen_i = candidate_i + 1;
1472314723 }
14724 continue;
1472414725 },
1472514726 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
1472614727 else => {},
src/codegen/llvm.zig+6-4
......@@ -324,10 +324,12 @@ pub const Object = struct {
324324 const mod = comp.bin_file.options.module.?;
325325 const cache_dir = mod.zig_cache_artifact_directory;
326326
327 const emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit|
328 try emit.directory.joinZ(arena, &[_][]const u8{self.sub_path})
329 else
330 null;
327 const emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| blk: {
328 const full_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});
329 break :blk try std.fs.path.joinZ(arena, &.{
330 std.fs.path.dirname(full_out_path).?, self.sub_path,
331 });
332 } else null;
331333
332334 const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir);
333335 const emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir);
src/glibc.zig+1
......@@ -1062,6 +1062,7 @@ fn buildSharedLib(
10621062 .local_cache_directory = zig_cache_directory,
10631063 .global_cache_directory = comp.global_cache_directory,
10641064 .zig_lib_directory = comp.zig_lib_directory,
1065 .cache_mode = .whole,
10651066 .target = comp.getTarget(),
10661067 .root_name = lib.name,
10671068 .main_pkg = null,
src/libcxx.zig+8-8
......@@ -177,6 +177,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
177177 .local_cache_directory = comp.global_cache_directory,
178178 .global_cache_directory = comp.global_cache_directory,
179179 .zig_lib_directory = comp.zig_lib_directory,
180 .cache_mode = .whole,
180181 .target = target,
181182 .root_name = root_name,
182183 .main_pkg = null,
......@@ -218,10 +219,9 @@ pub fn buildLibCXX(comp: *Compilation) !void {
218219
219220 assert(comp.libcxx_static_lib == null);
220221 comp.libcxx_static_lib = Compilation.CRTFile{
221 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(
222 comp.gpa,
223 &[_][]const u8{basename},
224 ),
222 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
223 sub_compilation.bin_file.options.emit.?.sub_path,
224 }),
225225 .lock = sub_compilation.bin_file.toOwnedLock(),
226226 };
227227}
......@@ -309,6 +309,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
309309 .local_cache_directory = comp.global_cache_directory,
310310 .global_cache_directory = comp.global_cache_directory,
311311 .zig_lib_directory = comp.zig_lib_directory,
312 .cache_mode = .whole,
312313 .target = target,
313314 .root_name = root_name,
314315 .main_pkg = null,
......@@ -350,10 +351,9 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
350351
351352 assert(comp.libcxxabi_static_lib == null);
352353 comp.libcxxabi_static_lib = Compilation.CRTFile{
353 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(
354 comp.gpa,
355 &[_][]const u8{basename},
356 ),
354 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
355 sub_compilation.bin_file.options.emit.?.sub_path,
356 }),
357357 .lock = sub_compilation.bin_file.toOwnedLock(),
358358 };
359359}
src/libtsan.zig+4-4
......@@ -199,6 +199,7 @@ pub fn buildTsan(comp: *Compilation) !void {
199199 .local_cache_directory = comp.global_cache_directory,
200200 .global_cache_directory = comp.global_cache_directory,
201201 .zig_lib_directory = comp.zig_lib_directory,
202 .cache_mode = .whole,
202203 .target = target,
203204 .root_name = root_name,
204205 .main_pkg = null,
......@@ -237,10 +238,9 @@ pub fn buildTsan(comp: *Compilation) !void {
237238
238239 assert(comp.tsan_static_lib == null);
239240 comp.tsan_static_lib = Compilation.CRTFile{
240 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(
241 comp.gpa,
242 &[_][]const u8{basename},
243 ),
241 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
242 sub_compilation.bin_file.options.emit.?.sub_path,
243 }),
244244 .lock = sub_compilation.bin_file.toOwnedLock(),
245245 };
246246}
src/libunwind.zig+5-4
......@@ -101,6 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
101101 .local_cache_directory = comp.global_cache_directory,
102102 .global_cache_directory = comp.global_cache_directory,
103103 .zig_lib_directory = comp.zig_lib_directory,
104 .cache_mode = .whole,
104105 .target = target,
105106 .root_name = root_name,
106107 .main_pkg = null,
......@@ -141,11 +142,11 @@ pub fn buildStaticLib(comp: *Compilation) !void {
141142 try sub_compilation.updateSubCompilation();
142143
143144 assert(comp.libunwind_static_lib == null);
145
144146 comp.libunwind_static_lib = Compilation.CRTFile{
145 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(
146 comp.gpa,
147 &[_][]const u8{basename},
148 ),
147 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
148 sub_compilation.bin_file.options.emit.?.sub_path,
149 }),
149150 .lock = sub_compilation.bin_file.toOwnedLock(),
150151 };
151152}
src/link.zig+59-14
......@@ -22,6 +22,8 @@ pub const SystemLib = struct {
2222 needed: bool = false,
2323};
2424
25pub const CacheMode = enum { incremental, whole };
26
2527pub fn hashAddSystemLibs(
2628 hh: *Cache.HashHelper,
2729 hm: std.StringArrayHashMapUnmanaged(SystemLib),
......@@ -44,10 +46,9 @@ pub const Emit = struct {
4446};
4547
4648pub const Options = struct {
47 /// This is `null` when -fno-emit-bin is used. When `openPath` or `flush` is called,
48 /// it will have already been null-checked.
49 /// This is `null` when `-fno-emit-bin` is used.
4950 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.
5152 implib_emit: ?Emit,
5253 target: std.Target,
5354 output_mode: std.builtin.OutputMode,
......@@ -70,6 +71,7 @@ pub const Options = struct {
7071 entry_addr: ?u64 = null,
7172 stack_size_override: ?u64,
7273 image_base_override: ?u64,
74 cache_mode: CacheMode,
7375 include_compiler_rt: bool,
7476 /// Set to `true` to omit debug info.
7577 strip: bool,
......@@ -165,6 +167,12 @@ pub const Options = struct {
165167 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
166168 return if (options.use_lld) .Obj else options.output_mode;
167169 }
170
171 pub fn move(self: *Options) Options {
172 const copied_state = self.*;
173 self.system_libs = .{};
174 return copied_state;
175 }
168176};
169177
170178pub const File = struct {
......@@ -628,6 +636,36 @@ pub const File = struct {
628636 }
629637 }
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
631669 pub fn linkAsArchive(base: *File, comp: *Compilation) !void {
632670 const tracy = trace(@src());
633671 defer tracy.end();
......@@ -637,9 +675,11 @@ pub const File = struct {
637675 const arena = arena_allocator.allocator();
638676
639677 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 it
642 // will not be part of the linker line anyway.
681 // If there is no Zig code to compile, then we should skip flushing the output file
682 // because it will not be part of the linker line anyway.
643683 const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: {
644684 const use_stage1 = build_options.is_stage1 and base.options.use_stage1;
645685 if (use_stage1) {
......@@ -648,20 +688,28 @@ pub const File = struct {
648688 .target = base.options.target,
649689 .output_mode = .Obj,
650690 });
651 const o_directory = module.zig_cache_artifact_directory;
652 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
653 break :blk full_obj_path;
691 switch (base.options.cache_mode) {
692 .incremental => break :blk try module.zig_cache_artifact_directory.join(
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 }
654700 }
655701 if (base.options.object_format == .macho) {
656702 try base.cast(MachO).?.flushObject(comp);
657703 } else {
658704 try base.flushModule(comp);
659705 }
660 const obj_basename = base.intermediary_basename.?;
661 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
662 break :blk full_obj_path;
706 break :blk try fs.path.join(arena, &.{
707 fs.path.dirname(full_out_path_z).?, base.intermediary_basename.?,
708 });
663709 } else null;
664710
711 log.debug("module_obj_path={s}", .{if (module_obj_path) |s| s else "(null)"});
712
665713 const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt)
666714 comp.compiler_rt_obj.?.full_object_path
667715 else
......@@ -734,9 +782,6 @@ pub const File = struct {
734782 object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));
735783 }
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
740785 if (base.options.verbose_link) {
741786 std.debug.print("ar rcs {s}", .{full_out_path_z});
742787 for (object_files.items) |arg| {
src/link/Coff.zig+16-7
......@@ -880,6 +880,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
880880 const arena = arena_allocator.allocator();
881881
882882 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
884885 // If there is no Zig code to compile, then we should skip flushing the output file because it
885886 // will not be part of the linker line anyway.
......@@ -891,15 +892,22 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
891892 .target = self.base.options.target,
892893 .output_mode = .Obj,
893894 });
894 const o_directory = module.zig_cache_artifact_directory;
895 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
896 break :blk full_obj_path;
895 switch (self.base.options.cache_mode) {
896 .incremental => break :blk try module.zig_cache_artifact_directory.join(
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 }
897904 }
898905
899906 try self.flushModule(comp);
900 const obj_basename = self.base.intermediary_basename.?;
901 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
902 break :blk full_obj_path;
907
908 break :blk try fs.path.join(arena, &.{
909 fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
910 });
903911 } else null;
904912
905913 const is_lib = self.base.options.output_mode == .Lib;
......@@ -920,6 +928,8 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
920928 man = comp.cache_parent.obtain();
921929 self.base.releaseLock();
922930
931 comptime assert(Compilation.link_hash_implementation_version == 1);
932
923933 try man.addListOfFiles(self.base.options.objects);
924934 for (comp.c_object_table.keys()) |key| {
925935 _ = try man.addFile(key.status.success.object_path, null);
......@@ -976,7 +986,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
976986 };
977987 }
978988
979 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
980989 if (self.base.options.output_mode == .Obj) {
981990 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
982991 // 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 {
297297 else => return error.UnsupportedELFArchitecture,
298298 };
299299 const self = try gpa.create(Elf);
300 errdefer gpa.destroy(self);
300301 self.* = .{
301302 .base = .{
302303 .tag = .elf,
......@@ -306,6 +307,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
306307 },
307308 .ptr_width = ptr_width,
308309 };
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.
309313 return self;
310314}
311315
......@@ -1298,6 +1302,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
12981302 const arena = arena_allocator.allocator();
12991303
13001304 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
13021307 // If there is no Zig code to compile, then we should skip flushing the output file because it
13031308 // will not be part of the linker line anyway.
......@@ -1309,15 +1314,22 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
13091314 .target = self.base.options.target,
13101315 .output_mode = .Obj,
13111316 });
1312 const o_directory = module.zig_cache_artifact_directory;
1313 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
1314 break :blk full_obj_path;
1317 switch (self.base.options.cache_mode) {
1318 .incremental => break :blk try module.zig_cache_artifact_directory.join(
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 }
13151326 }
13161327
13171328 try self.flushModule(comp);
1318 const obj_basename = self.base.intermediary_basename.?;
1319 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
1320 break :blk full_obj_path;
1329
1330 break :blk try fs.path.join(arena, &.{
1331 fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
1332 });
13211333 } else null;
13221334
13231335 const is_obj = self.base.options.output_mode == .Obj;
......@@ -1357,6 +1369,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
13571369 // We are about to obtain this lock, so here we give other processes a chance first.
13581370 self.base.releaseLock();
13591371
1372 comptime assert(Compilation.link_hash_implementation_version == 1);
1373
13601374 try man.addOptionalFile(self.base.options.linker_script);
13611375 try man.addOptionalFile(self.base.options.version_script);
13621376 try man.addListOfFiles(self.base.options.objects);
......@@ -1432,8 +1446,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
14321446 };
14331447 }
14341448
1435 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
1436
14371449 // Due to a deficiency in LLD, we need to special-case BPF to a simple file copy when generating
14381450 // relocatables. Normally, we would expect `lld -r` to work. However, because LLD wants to resolve
14391451 // 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 {
423423 const arena = arena_allocator.allocator();
424424
425425 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
427428 // If there is no Zig code to compile, then we should skip flushing the output file because it
428429 // will not be part of the linker line anyway.
......@@ -433,15 +434,24 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
433434 .target = self.base.options.target,
434435 .output_mode = .Obj,
435436 });
436 const o_directory = module.zig_cache_artifact_directory;
437 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
438 break :blk full_obj_path;
437 switch (self.base.options.cache_mode) {
438 .incremental => break :blk try module.zig_cache_artifact_directory.join(
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 }
439446 }
440447
441448 const obj_basename = self.base.intermediary_basename orelse break :blk null;
449
442450 try self.flushObject(comp);
443 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
444 break :blk full_obj_path;
451
452 break :blk try fs.path.join(arena, &.{
453 fs.path.dirname(full_out_path).?, obj_basename,
454 });
445455 } else null;
446456
447457 const is_lib = self.base.options.output_mode == .Lib;
......@@ -466,6 +476,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
466476 // We are about to obtain this lock, so here we give other processes a chance first.
467477 self.base.releaseLock();
468478
479 comptime assert(Compilation.link_hash_implementation_version == 1);
480
469481 try man.addListOfFiles(self.base.options.objects);
470482 for (comp.c_object_table.keys()) |key| {
471483 _ = try man.addFile(key.status.success.object_path, null);
......@@ -532,7 +544,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
532544 else => |e| return e,
533545 };
534546 }
535 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
536547
537548 if (self.base.options.output_mode == .Obj) {
538549 // 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
12671278 for (files) |file_name| {
12681279 const full_path = full_path: {
12691280 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);
12711282 break :full_path try self.base.allocator.dupe(u8, path);
12721283 };
12731284 defer self.base.allocator.free(full_path);
src/link/Wasm.zig+16-8
......@@ -1050,6 +1050,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
10501050 const arena = arena_allocator.allocator();
10511051
10521052 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
10541055 // If there is no Zig code to compile, then we should skip flushing the output file because it
10551056 // will not be part of the linker line anyway.
......@@ -1061,15 +1062,22 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
10611062 .target = self.base.options.target,
10621063 .output_mode = .Obj,
10631064 });
1064 const o_directory = module.zig_cache_artifact_directory;
1065 const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
1066 break :blk full_obj_path;
1065 switch (self.base.options.cache_mode) {
1066 .incremental => break :blk try module.zig_cache_artifact_directory.join(
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 }
10671074 }
10681075
10691076 try self.flushModule(comp);
1070 const obj_basename = self.base.intermediary_basename.?;
1071 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
1072 break :blk full_obj_path;
1077
1078 break :blk try fs.path.join(arena, &.{
1079 fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
1080 });
10731081 } else null;
10741082
10751083 const is_obj = self.base.options.output_mode == .Obj;
......@@ -1094,6 +1102,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
10941102 // We are about to obtain this lock, so here we give other processes a chance first.
10951103 self.base.releaseLock();
10961104
1105 comptime assert(Compilation.link_hash_implementation_version == 1);
1106
10971107 try man.addListOfFiles(self.base.options.objects);
10981108 for (comp.c_object_table.keys()) |key| {
10991109 _ = try man.addFile(key.status.success.object_path, null);
......@@ -1141,8 +1151,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
11411151 };
11421152 }
11431153
1144 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
1145
11461154 if (self.base.options.output_mode == .Obj) {
11471155 // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy
11481156 // 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(
25642564
25652565 switch (emit_bin) {
25662566 .no => break :blk .none,
2567 .yes_default_path => break :blk .{
2568 .print = comp.bin_file.options.emit.?.directory.path orelse ".",
2569 },
2567 .yes_default_path => break :blk .print_emit_bin_dir_path,
25702568 .yes => |full_path| break :blk .{ .update = full_path },
25712569 .yes_a_out => break :blk .{ .update = a_out_basename },
25722570 }
......@@ -2578,10 +2576,6 @@ fn buildOutputType(
25782576 };
25792577 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
25852579 if (test_exec_args.items.len == 0 and object_format == .c) default_exec_args: {
25862580 // Default to using `zig run` to execute the produced .c code from `zig test`.
25872581 const c_code_loc = emit_bin_loc orelse break :default_exec_args;
......@@ -2602,7 +2596,6 @@ fn buildOutputType(
26022596 comp,
26032597 gpa,
26042598 arena,
2605 emit_bin_loc,
26062599 test_exec_args.items,
26072600 self_exe_path,
26082601 arg_mode,
......@@ -2675,7 +2668,6 @@ fn buildOutputType(
26752668 comp,
26762669 gpa,
26772670 arena,
2678 emit_bin_loc,
26792671 test_exec_args.items,
26802672 self_exe_path,
26812673 arg_mode,
......@@ -2701,7 +2693,6 @@ fn buildOutputType(
27012693 comp,
27022694 gpa,
27032695 arena,
2704 emit_bin_loc,
27052696 test_exec_args.items,
27062697 self_exe_path,
27072698 arg_mode,
......@@ -2766,7 +2757,6 @@ fn runOrTest(
27662757 comp: *Compilation,
27672758 gpa: Allocator,
27682759 arena: Allocator,
2769 emit_bin_loc: ?Compilation.EmitLoc,
27702760 test_exec_args: []const ?[]const u8,
27712761 self_exe_path: []const u8,
27722762 arg_mode: ArgMode,
......@@ -2777,10 +2767,11 @@ fn runOrTest(
27772767 runtime_args_start: ?usize,
27782768 link_libc: bool,
27792769) !void {
2780 const exe_loc = emit_bin_loc orelse return;
2781 const exe_directory = exe_loc.directory orelse comp.bin_file.options.emit.?.directory;
2770 const exe_emit = comp.bin_file.options.emit orelse return;
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.
27822773 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,
27842775 });
27852776
27862777 var argv = std.ArrayList([]const u8).init(gpa);
......@@ -2884,7 +2875,7 @@ fn runOrTest(
28842875
28852876const AfterUpdateHook = union(enum) {
28862877 none,
2887 print: []const u8,
2878 print_emit_bin_dir_path,
28882879 update: []const u8,
28892880};
28902881
......@@ -2910,7 +2901,13 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void
29102901 return error.SemanticAnalyzeFail;
29112902 } else switch (hook) {
29122903 .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 },
29142911 .update => |full_path| {
29152912 const bin_sub_path = comp.bin_file.options.emit.?.sub_path;
29162913 const cwd = fs.cwd();
......@@ -3473,9 +3470,10 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
34733470 };
34743471 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(
34773475 arena,
3478 &[_][]const u8{exe_basename},
3476 &[_][]const u8{emit.sub_path},
34793477 );
34803478
34813479 break :argv child_argv.items;
......@@ -3666,9 +3664,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
36663664 .zir_loaded = false,
36673665 .sub_file_path = "<stdin>",
36683666 .source = source_code,
3669 .stat_size = undefined,
3670 .stat_inode = undefined,
3671 .stat_mtime = undefined,
3667 .stat = undefined,
36723668 .tree = tree,
36733669 .tree_loaded = true,
36743670 .zir = undefined,
......@@ -3862,9 +3858,11 @@ fn fmtPathFile(
38623858 .zir_loaded = false,
38633859 .sub_file_path = file_path,
38643860 .source = source_code,
3865 .stat_size = stat.size,
3866 .stat_inode = stat.inode,
3867 .stat_mtime = stat.mtime,
3861 .stat = .{
3862 .size = stat.size,
3863 .inode = stat.inode,
3864 .mtime = stat.mtime,
3865 },
38683866 .tree = tree,
38693867 .tree_loaded = true,
38703868 .zir = undefined,
......@@ -4460,9 +4458,7 @@ pub fn cmdAstCheck(
44604458 .zir_loaded = false,
44614459 .sub_file_path = undefined,
44624460 .source = undefined,
4463 .stat_size = undefined,
4464 .stat_inode = undefined,
4465 .stat_mtime = undefined,
4461 .stat = undefined,
44664462 .tree = undefined,
44674463 .zir = undefined,
44684464 .pkg = undefined,
......@@ -4487,9 +4483,11 @@ pub fn cmdAstCheck(
44874483 file.sub_file_path = file_name;
44884484 file.source = source;
44894485 file.source_loaded = true;
4490 file.stat_size = stat.size;
4491 file.stat_inode = stat.inode;
4492 file.stat_mtime = stat.mtime;
4486 file.stat = .{
4487 .size = stat.size,
4488 .inode = stat.inode,
4489 .mtime = stat.mtime,
4490 };
44934491 } else {
44944492 const stdin = io.getStdIn();
44954493 const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| {
......@@ -4498,7 +4496,7 @@ pub fn cmdAstCheck(
44984496 file.sub_file_path = "<stdin>";
44994497 file.source = source;
45004498 file.source_loaded = true;
4501 file.stat_size = source.len;
4499 file.stat.size = source.len;
45024500 }
45034501
45044502 file.pkg = try Package.create(gpa, null, file.sub_file_path);
......@@ -4611,9 +4609,11 @@ pub fn cmdChangelist(
46114609 .zir_loaded = false,
46124610 .sub_file_path = old_source_file,
46134611 .source = undefined,
4614 .stat_size = stat.size,
4615 .stat_inode = stat.inode,
4616 .stat_mtime = stat.mtime,
4612 .stat = .{
4613 .size = stat.size,
4614 .inode = stat.inode,
4615 .mtime = stat.mtime,
4616 },
46174617 .tree = undefined,
46184618 .zir = undefined,
46194619 .pkg = undefined,
src/musl.zig+1
......@@ -203,6 +203,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
203203 const sub_compilation = try Compilation.create(comp.gpa, .{
204204 .local_cache_directory = comp.global_cache_directory,
205205 .global_cache_directory = comp.global_cache_directory,
206 .cache_mode = .whole,
206207 .zig_lib_directory = comp.zig_lib_directory,
207208 .target = target,
208209 .root_name = "c",
src/stage1.zig+4-1
......@@ -458,7 +458,10 @@ export fn stage2_fetch_file(
458458 const comp = @intToPtr(*Compilation, stage1.userdata);
459459 const file_path = path_ptr[0..path_len];
460460 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;
462465 result_len.* = contents.len;
463466 // TODO https://github.com/ziglang/zig/issues/3328#issuecomment-716749475
464467 if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1);
src/type.zig+14-3
......@@ -3106,9 +3106,9 @@ pub const Type = extern union {
31063106 .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
31073107
31083108 .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,
31103110 .enum_simple => {
3111 const enum_obj = self.castTag(.enum_simple).?.data;
3111 const enum_obj = ty.castTag(.enum_simple).?.data;
31123112 const field_count = enum_obj.fields.count();
31133113 if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 };
31143114 return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };
......@@ -4603,7 +4603,18 @@ pub const CType = enum {
46034603 .longlong,
46044604 .ulonglong,
46054605 => 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 },
46074618 },
46084619
46094620 .windows, .uefi => switch (self) {
test/behavior/cast.zig+9
......@@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" {
295295 const a: ??[*]u8 = @as(?[*]u8, null);
296296 try expect(a != null and a.? == null);
297297}
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" {
383383 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
384384}
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
395386test "peer type resolve array pointers, one of them const" {
396387 var array1: [4]u8 = undefined;
397388 const array2: [5]u8 = undefined;