| author | |
| committer | |
| log | 81fa31c05456facea1d1963a1e7f665351fb248d |
| tree | 8ea6dba0c5b8ec9e8ba9cdff48189da68c198dfd |
| parent | 850b053ea6b7d6f0f5e0e8dbcf37080ca012024f |
| parent | d94303be2bcee33e7efba22a186fd06eaa809707 |
| signature |
stage2: introduce CacheMode45 files changed, 2061 insertions(+), 1453 deletions(-)
lib/std/fs.zig+1-1| ... | ... | @@ -1361,7 +1361,7 @@ pub const Dir = struct { |
| 1361 | 1361 | .share_access = share_access, |
| 1362 | 1362 | .creation = creation, |
| 1363 | 1363 | .io_mode = .blocking, |
| 1364 | .open_dir = true, | |
| 1364 | .filter = .dir_only, | |
| 1365 | 1365 | }) catch |er| switch (er) { |
| 1366 | 1366 | error.WouldBlock => unreachable, |
| 1367 | 1367 | else => |e2| return e2, |
lib/std/fs/watch.zig+1-1| ... | ... | @@ -401,7 +401,7 @@ pub fn Watch(comptime V: type) type { |
| 401 | 401 | .access_mask = windows.FILE_LIST_DIRECTORY, |
| 402 | 402 | .creation = windows.FILE_OPEN, |
| 403 | 403 | .io_mode = .evented, |
| 404 | .open_dir = true, | |
| 404 | .filter = .dir_only, | |
| 405 | 405 | }); |
| 406 | 406 | errdefer windows.CloseHandle(dir_handle); |
| 407 | 407 |
lib/std/os.zig+6-5| ... | ... | @@ -1353,7 +1353,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions { |
| 1353 | 1353 | access_mask |= w.GENERIC_READ | w.GENERIC_WRITE; |
| 1354 | 1354 | } |
| 1355 | 1355 | |
| 1356 | const open_dir: bool = flags & O.DIRECTORY != 0; | |
| 1356 | const filter: windows.OpenFileOptions.Filter = if (flags & O.DIRECTORY != 0) .dir_only else .file_only; | |
| 1357 | 1357 | const follow_symlinks: bool = flags & O.NOFOLLOW == 0; |
| 1358 | 1358 | |
| 1359 | 1359 | const creation: w.ULONG = blk: { |
| ... | ... | @@ -1369,7 +1369,7 @@ fn openOptionsFromFlags(flags: u32) windows.OpenFileOptions { |
| 1369 | 1369 | .access_mask = access_mask, |
| 1370 | 1370 | .io_mode = .blocking, |
| 1371 | 1371 | .creation = creation, |
| 1372 | .open_dir = open_dir, | |
| 1372 | .filter = filter, | |
| 1373 | 1373 | .follow_symlinks = follow_symlinks, |
| 1374 | 1374 | }; |
| 1375 | 1375 | } |
| ... | ... | @@ -2324,6 +2324,7 @@ pub fn renameatW( |
| 2324 | 2324 | .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE, |
| 2325 | 2325 | .creation = windows.FILE_OPEN, |
| 2326 | 2326 | .io_mode = .blocking, |
| 2327 | .filter = .any, // This function is supposed to rename both files and directories. | |
| 2327 | 2328 | }) catch |err| switch (err) { |
| 2328 | 2329 | error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`. |
| 2329 | 2330 | else => |e| return e, |
| ... | ... | @@ -2435,7 +2436,7 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v |
| 2435 | 2436 | .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, |
| 2436 | 2437 | .creation = windows.FILE_CREATE, |
| 2437 | 2438 | .io_mode = .blocking, |
| 2438 | .open_dir = true, | |
| 2439 | .filter = .dir_only, | |
| 2439 | 2440 | }) catch |err| switch (err) { |
| 2440 | 2441 | error.IsDir => unreachable, |
| 2441 | 2442 | error.PipeBusy => unreachable, |
| ... | ... | @@ -2511,7 +2512,7 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void { |
| 2511 | 2512 | .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, |
| 2512 | 2513 | .creation = windows.FILE_CREATE, |
| 2513 | 2514 | .io_mode = .blocking, |
| 2514 | .open_dir = true, | |
| 2515 | .filter = .dir_only, | |
| 2515 | 2516 | }) catch |err| switch (err) { |
| 2516 | 2517 | error.IsDir => unreachable, |
| 2517 | 2518 | error.PipeBusy => unreachable, |
| ... | ... | @@ -4693,7 +4694,7 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat |
| 4693 | 4694 | .share_access = share_access, |
| 4694 | 4695 | .creation = creation, |
| 4695 | 4696 | .io_mode = .blocking, |
| 4696 | .open_dir = true, | |
| 4697 | .filter = .dir_only, | |
| 4697 | 4698 | }) catch |er| switch (er) { |
| 4698 | 4699 | error.WouldBlock => unreachable, |
| 4699 | 4700 | else => |e2| return e2, |
lib/std/os/windows.zig+18-5| ... | ... | @@ -53,17 +53,26 @@ pub const OpenFileOptions = struct { |
| 53 | 53 | io_mode: std.io.ModeOverride, |
| 54 | 54 | /// If true, tries to open path as a directory. |
| 55 | 55 | /// Defaults to false. |
| 56 | open_dir: bool = false, | |
| 56 | filter: Filter = .file_only, | |
| 57 | 57 | /// If false, tries to open path as a reparse point without dereferencing it. |
| 58 | 58 | /// Defaults to true. |
| 59 | 59 | follow_symlinks: bool = true, |
| 60 | ||
| 61 | pub const Filter = enum { | |
| 62 | /// Causes `OpenFile` to return `error.IsDir` if the opened handle would be a directory. | |
| 63 | file_only, | |
| 64 | /// Causes `OpenFile` to return `error.NotDir` if the opened handle would be a file. | |
| 65 | dir_only, | |
| 66 | /// `OpenFile` does not discriminate between opening files and directories. | |
| 67 | any, | |
| 68 | }; | |
| 60 | 69 | }; |
| 61 | 70 | |
| 62 | 71 | pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE { |
| 63 | if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and !options.open_dir) { | |
| 72 | if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and options.filter == .file_only) { | |
| 64 | 73 | return error.IsDir; |
| 65 | 74 | } |
| 66 | if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and !options.open_dir) { | |
| 75 | if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and options.filter == .file_only) { | |
| 67 | 76 | return error.IsDir; |
| 68 | 77 | } |
| 69 | 78 | |
| ... | ... | @@ -87,7 +96,11 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN |
| 87 | 96 | }; |
| 88 | 97 | var io: IO_STATUS_BLOCK = undefined; |
| 89 | 98 | const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0; |
| 90 | const file_or_dir_flag: ULONG = if (options.open_dir) FILE_DIRECTORY_FILE else FILE_NON_DIRECTORY_FILE; | |
| 99 | const file_or_dir_flag: ULONG = switch (options.filter) { | |
| 100 | .file_only => FILE_NON_DIRECTORY_FILE, | |
| 101 | .dir_only => FILE_DIRECTORY_FILE, | |
| 102 | .any => 0, | |
| 103 | }; | |
| 91 | 104 | // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. |
| 92 | 105 | const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT; |
| 93 | 106 | |
| ... | ... | @@ -695,7 +708,7 @@ pub fn CreateSymbolicLink( |
| 695 | 708 | .dir = dir, |
| 696 | 709 | .creation = FILE_CREATE, |
| 697 | 710 | .io_mode = .blocking, |
| 698 | .open_dir = is_directory, | |
| 711 | .filter = if (is_directory) .dir_only else .file_only, | |
| 699 | 712 | }) catch |err| switch (err) { |
| 700 | 713 | error.IsDir => return error.PathAlreadyExists, |
| 701 | 714 | error.NotDir => unreachable, |
lib/std/special/compiler_rt.zig+529-521| ... | ... | @@ -22,6 +22,12 @@ else |
| 22 | 22 | const long_double_is_f128 = builtin.target.longDoubleIsF128(); |
| 23 | 23 | |
| 24 | 24 | comptime { |
| 25 | // These files do their own comptime exporting logic. | |
| 26 | if (!builtin.zig_is_stage2) { | |
| 27 | _ = @import("compiler_rt/atomics.zig"); | |
| 28 | } | |
| 29 | _ = @import("compiler_rt/clear_cache.zig").clear_cache; | |
| 30 | ||
| 25 | 31 | const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2; |
| 26 | 32 | @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage }); |
| 27 | 33 | const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2; |
| ... | ... | @@ -171,16 +177,16 @@ comptime { |
| 171 | 177 | const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2; |
| 172 | 178 | @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage }); |
| 173 | 179 | |
| 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 }); | |
| 179 | 184 | |
| 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 | } | |
| 183 | 188 | |
| 189 | if (!builtin.zig_is_stage2) { | |
| 184 | 190 | switch (arch) { |
| 185 | 191 | .i386, |
| 186 | 192 | .x86_64, |
| ... | ... | @@ -193,531 +199,533 @@ comptime { |
| 193 | 199 | }, |
| 194 | 200 | else => {}, |
| 195 | 201 | } |
| 202 | } | |
| 196 | 203 | |
| 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) { | |
| 298 | 305 | const __floatundisf = @import("compiler_rt/floatundisf.zig").__floatundisf; |
| 299 | 306 | @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 | } | |
| 384 | 392 | |
| 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 | } | |
| 467 | 475 | |
| 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 }); | |
| 622 | 521 | } |
| 623 | 522 | |
| 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 | } | |
| 635 | 631 | |
| 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 | } | |
| 687 | 643 | |
| 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 | } | |
| 714 | 695 | |
| 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 }); | |
| 716 | 726 | |
| 727 | if (!builtin.zig_is_stage2) { | |
| 717 | 728 | @export(fmaq, .{ .name = "fmaq", .linkage = linkage }); |
| 718 | @export(floorf, .{ .name = "floorf", .linkage = linkage }); | |
| 719 | @export(floor, .{ .name = "floor", .linkage = linkage }); | |
| 720 | @export(floorl, .{ .name = "floorl", .linkage = linkage }); | |
| 721 | 729 | } |
| 722 | 730 | } |
| 723 | 731 |
lib/std/special/compiler_rt/absv.zig+29-24| ... | ... | @@ -2,31 +2,36 @@ |
| 2 | 2 | // * @panic, if value can not be represented |
| 3 | 3 | // - absvXi4_generic for unoptimized version |
| 4 | 4 | |
| 5 | fn 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; | |
| 5 | inline 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 | ||
| 24 | pub fn __absvsi2(a: i32) callconv(.C) i32 { | |
| 25 | return absvXi(i32, a); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn __absvdi2(a: i64) callconv(.C) i64 { | |
| 29 | return absvXi(i64, a); | |
| 30 | } | |
| 31 | ||
| 32 | pub fn __absvti2(a: i128) callconv(.C) i128 { | |
| 33 | return absvXi(i128, a); | |
| 26 | 34 | } |
| 27 | pub const __absvsi2 = absvXi_generic(i32); | |
| 28 | pub const __absvdi2 = absvXi_generic(i64); | |
| 29 | pub const __absvti2 = absvXi_generic(i128); | |
| 30 | 35 | |
| 31 | 36 | test { |
| 32 | 37 | _ = @import("absvsi2_test.zig"); |
lib/std/special/compiler_rt/atomics.zig+277-191| ... | ... | @@ -119,225 +119,311 @@ fn __atomic_compare_exchange( |
| 119 | 119 | return 0; |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | comptime { | |
| 123 | if (supports_atomic_ops) { | |
| 124 | @export(__atomic_load, .{ .name = "__atomic_load", .linkage = linkage }); | |
| 125 | @export(__atomic_store, .{ .name = "__atomic_store", .linkage = linkage }); | |
| 126 | @export(__atomic_exchange, .{ .name = "__atomic_exchange", .linkage = linkage }); | |
| 127 | @export(__atomic_compare_exchange, .{ .name = "__atomic_compare_exchange", .linkage = linkage }); | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | 122 | // Specialized versions of the GCC atomic builtin functions. |
| 132 | 123 | // LLVM emits those iff the object size is known and the pointers are correctly |
| 133 | 124 | // aligned. |
| 125 | inline 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 | } | |
| 134 | 135 | |
| 135 | fn 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; | |
| 136 | fn __atomic_load_1(src: *u8, model: i32) callconv(.C) u8 { | |
| 137 | return atomic_load_N(u8, src, model); | |
| 148 | 138 | } |
| 149 | 139 | |
| 150 | comptime { | |
| 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 | } | |
| 140 | fn __atomic_load_2(src: *u16, model: i32) callconv(.C) u16 { | |
| 141 | return atomic_load_N(u16, src, model); | |
| 161 | 142 | } |
| 162 | 143 | |
| 163 | fn 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; | |
| 144 | fn __atomic_load_4(src: *u32, model: i32) callconv(.C) u32 { | |
| 145 | return atomic_load_N(u32, src, model); | |
| 176 | 146 | } |
| 177 | 147 | |
| 178 | comptime { | |
| 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 }); | |
| 148 | fn __atomic_load_8(src: *u64, model: i32) callconv(.C) u64 { | |
| 149 | return atomic_load_N(u64, src, model); | |
| 150 | } | |
| 151 | ||
| 152 | inline 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); | |
| 188 | 160 | } |
| 189 | 161 | } |
| 190 | 162 | |
| 191 | fn 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; | |
| 163 | fn __atomic_store_1(dst: *u8, value: u8, model: i32) callconv(.C) void { | |
| 164 | return atomic_store_N(u8, dst, value, model); | |
| 206 | 165 | } |
| 207 | 166 | |
| 208 | comptime { | |
| 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 }); | |
| 167 | fn __atomic_store_2(dst: *u16, value: u16, model: i32) callconv(.C) void { | |
| 168 | return atomic_store_N(u16, dst, value, model); | |
| 169 | } | |
| 170 | ||
| 171 | fn __atomic_store_4(dst: *u32, value: u32, model: i32) callconv(.C) void { | |
| 172 | return atomic_store_N(u32, dst, value, model); | |
| 173 | } | |
| 174 | ||
| 175 | fn __atomic_store_8(dst: *u64, value: u64, model: i32) callconv(.C) void { | |
| 176 | return atomic_store_N(u64, dst, value, model); | |
| 177 | } | |
| 178 | ||
| 179 | inline fn atomic_exchange_N(comptime T: type, ptr: *T, val: T, model: i32) T { | |
| 180 | _ = model; | |
| 181 | if (@sizeOf(T) > largest_atomic_size) { | |
| 182 | var sl = spinlocks.get(@ptrToInt(ptr)); | |
| 183 | defer sl.release(); | |
| 184 | const value = ptr.*; | |
| 185 | ptr.* = val; | |
| 186 | return value; | |
| 187 | } else { | |
| 188 | return @atomicRmw(T, ptr, .Xchg, val, .SeqCst); | |
| 218 | 189 | } |
| 219 | 190 | } |
| 220 | 191 | |
| 221 | fn 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 | } | |
| 192 | fn __atomic_exchange_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 { | |
| 193 | return atomic_exchange_N(u8, ptr, val, model); | |
| 194 | } | |
| 195 | ||
| 196 | fn __atomic_exchange_2(ptr: *u16, val: u16, model: i32) callconv(.C) u16 { | |
| 197 | return atomic_exchange_N(u16, ptr, val, model); | |
| 198 | } | |
| 199 | ||
| 200 | fn __atomic_exchange_4(ptr: *u32, val: u32, model: i32) callconv(.C) u32 { | |
| 201 | return atomic_exchange_N(u32, ptr, val, model); | |
| 202 | } | |
| 203 | ||
| 204 | fn __atomic_exchange_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 { | |
| 205 | return atomic_exchange_N(u64, ptr, val, model); | |
| 206 | } | |
| 207 | ||
| 208 | inline 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; | |
| 243 | 225 | } |
| 244 | }.atomic_compare_exchange_N; | |
| 226 | expected.* = value; | |
| 227 | return 0; | |
| 228 | } else { | |
| 229 | if (@cmpxchgStrong(T, ptr, expected.*, desired, .SeqCst, .SeqCst)) |old_value| { | |
| 230 | expected.* = old_value; | |
| 231 | return 0; | |
| 232 | } | |
| 233 | return 1; | |
| 234 | } | |
| 245 | 235 | } |
| 246 | 236 | |
| 247 | comptime { | |
| 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 }); | |
| 237 | fn __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 | ||
| 241 | fn __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 | ||
| 245 | fn __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 | ||
| 249 | fn __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 | ||
| 253 | inline fn fetch_op_N(comptime T: type, comptime op: std.builtin.AtomicRmwOp, ptr: *T, val: T, model: i32) T { | |
| 254 | _ = model; | |
| 255 | if (@sizeOf(T) > largest_atomic_size) { | |
| 256 | var sl = spinlocks.get(@ptrToInt(ptr)); | |
| 257 | defer sl.release(); | |
| 258 | ||
| 259 | const value = ptr.*; | |
| 260 | ptr.* = switch (op) { | |
| 261 | .Add => value +% val, | |
| 262 | .Sub => value -% val, | |
| 263 | .And => value & val, | |
| 264 | .Nand => ~(value & val), | |
| 265 | .Or => value | val, | |
| 266 | .Xor => value ^ val, | |
| 267 | else => @compileError("unsupported atomic op"), | |
| 268 | }; | |
| 269 | ||
| 270 | return value; | |
| 257 | 271 | } |
| 272 | ||
| 273 | return @atomicRmw(T, ptr, op, val, .SeqCst); | |
| 258 | 274 | } |
| 259 | 275 | |
| 260 | fn 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 | } | |
| 276 | fn __atomic_fetch_add_1(ptr: *u8, val: u8, model: i32) callconv(.C) u8 { | |
| 277 | return fetch_op_N(u8, .Add, ptr, val, model); | |
| 278 | } | |
| 281 | 279 | |
| 282 | return @atomicRmw(T, ptr, op, val, .SeqCst); | |
| 283 | } | |
| 284 | }.fetch_op_N; | |
| 280 | fn __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 | ||
| 284 | fn __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 | ||
| 288 | fn __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 | ||
| 292 | fn __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 | ||
| 296 | fn __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 | ||
| 300 | fn __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 | ||
| 304 | fn __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 | ||
| 308 | fn __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 | ||
| 312 | fn __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 | ||
| 316 | fn __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 | ||
| 320 | fn __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 | ||
| 324 | fn __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 | ||
| 328 | fn __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 | ||
| 332 | fn __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 | ||
| 336 | fn __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 | ||
| 340 | fn __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 | ||
| 344 | fn __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 | ||
| 348 | fn __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 | ||
| 352 | fn __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 | ||
| 356 | fn __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 | ||
| 360 | fn __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 | ||
| 364 | fn __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 | ||
| 368 | fn __atomic_fetch_nand_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 { | |
| 369 | return fetch_op_N(u64, .Nand, ptr, val, model); | |
| 285 | 370 | } |
| 286 | 371 | |
| 287 | 372 | comptime { |
| 288 | 373 | 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 }); | |
| 342 | 428 | } |
| 343 | 429 | } |
lib/std/special/compiler_rt/bswap.zig+55-55| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | // bswap - byteswap |
| 5 | // - bswapXi2_generic for unoptimized big and little endian | |
| 5 | // - bswapXi2 for unoptimized big and little endian | |
| 6 | 6 | // ie for u32 |
| 7 | 7 | // DE AD BE EF <- little|big endian |
| 8 | 8 | // FE BE AD DE <- big|little endian |
| ... | ... | @@ -11,64 +11,64 @@ const builtin = @import("builtin"); |
| 11 | 11 | // 00 00 ff 00 << 1*8 (2n right byte) |
| 12 | 12 | // 00 00 00 ff << 3*8 (rightmost byte) |
| 13 | 13 | |
| 14 | fn 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; | |
| 14 | inline 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 | } | |
| 65 | 59 | } |
| 66 | 60 | |
| 67 | pub const __bswapsi2 = bswapXi2_generic(u32); | |
| 61 | pub fn __bswapsi2(a: u32) callconv(.C) u32 { | |
| 62 | return bswapXi2(u32, a); | |
| 63 | } | |
| 68 | 64 | |
| 69 | pub const __bswapdi2 = bswapXi2_generic(u64); | |
| 65 | pub fn __bswapdi2(a: u64) callconv(.C) u64 { | |
| 66 | return bswapXi2(u64, a); | |
| 67 | } | |
| 70 | 68 | |
| 71 | pub const __bswapti2 = bswapXi2_generic(u128); | |
| 69 | pub fn __bswapti2(a: u128) callconv(.C) u128 { | |
| 70 | return bswapXi2(u128, a); | |
| 71 | } | |
| 72 | 72 | |
| 73 | 73 | test { |
| 74 | 74 | _ = @import("bswapsi2_test.zig"); |
lib/std/special/compiler_rt/cmp.zig+34-22| ... | ... | @@ -11,28 +11,40 @@ const builtin = @import("builtin"); |
| 11 | 11 | // a == b => 1 |
| 12 | 12 | // a > b => 2 |
| 13 | 13 | |
| 14 | fn 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 | ||
| 29 | pub const __cmpsi2 = XcmpXi2_generic(i32); | |
| 30 | pub const __cmpdi2 = XcmpXi2_generic(i64); | |
| 31 | pub const __cmpti2 = XcmpXi2_generic(i128); | |
| 32 | ||
| 33 | pub const __ucmpsi2 = XcmpXi2_generic(u32); | |
| 34 | pub const __ucmpdi2 = XcmpXi2_generic(u64); | |
| 35 | pub const __ucmpti2 = XcmpXi2_generic(u128); | |
| 14 | inline 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 | ||
| 25 | pub fn __cmpsi2(a: i32, b: i32) callconv(.C) i32 { | |
| 26 | return XcmpXi2(i32, a, b); | |
| 27 | } | |
| 28 | ||
| 29 | pub fn __cmpdi2(a: i64, b: i64) callconv(.C) i32 { | |
| 30 | return XcmpXi2(i64, a, b); | |
| 31 | } | |
| 32 | ||
| 33 | pub fn __cmpti2(a: i128, b: i128) callconv(.C) i32 { | |
| 34 | return XcmpXi2(i128, a, b); | |
| 35 | } | |
| 36 | ||
| 37 | pub fn __ucmpsi2(a: u32, b: u32) callconv(.C) i32 { | |
| 38 | return XcmpXi2(u32, a, b); | |
| 39 | } | |
| 40 | ||
| 41 | pub fn __ucmpdi2(a: u64, b: u64) callconv(.C) i32 { | |
| 42 | return XcmpXi2(u64, a, b); | |
| 43 | } | |
| 44 | ||
| 45 | pub fn __ucmpti2(a: u128, b: u128) callconv(.C) i32 { | |
| 46 | return XcmpXi2(u128, a, b); | |
| 47 | } | |
| 36 | 48 | |
| 37 | 49 | test { |
| 38 | 50 | _ = @import("cmpsi2_test.zig"); |
lib/std/special/compiler_rt/count0bits.zig+122-116| ... | ... | @@ -2,44 +2,40 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | // clz - count leading zeroes |
| 5 | // - clzXi2_generic for unoptimized little and big endian | |
| 5 | // - clzXi2 for unoptimized little and big endian | |
| 6 | 6 | // - __clzsi2_thumb1: assume a != 0 |
| 7 | 7 | // - __clzsi2_arm32: assume a != 0 |
| 8 | 8 | |
| 9 | 9 | // ctz - count trailing zeroes |
| 10 | // - ctzXi2_generic for unoptimized little and big endian | |
| 10 | // - ctzXi2 for unoptimized little and big endian | |
| 11 | 11 | |
| 12 | 12 | // ffs - find first set |
| 13 | 13 | // * ffs = (a == 0) => 0, (a != 0) => ctz + 1 |
| 14 | 14 | // * dont pay for `if (x == 0) return shift;` inside ctz |
| 15 | // - ffsXi2_generic for unoptimized little and big endian | |
| 16 | ||
| 17 | fn 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 | ||
| 17 | inline 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; | |
| 41 | 36 | } |
| 42 | }.f; | |
| 37 | } | |
| 38 | return @intCast(i32, n - @bitCast(T, x)); | |
| 43 | 39 | } |
| 44 | 40 | |
| 45 | 41 | fn __clzsi2_thumb1() callconv(.Naked) void { |
| ... | ... | @@ -125,103 +121,113 @@ fn __clzsi2_arm32() callconv(.Naked) void { |
| 125 | 121 | unreachable; |
| 126 | 122 | } |
| 127 | 123 | |
| 128 | pub 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 | } | |
| 124 | fn clzsi2_generic(a: i32) callconv(.C) i32 { | |
| 125 | return clzXi2(i32, a); | |
| 126 | } | |
| 127 | ||
| 128 | pub 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, | |
| 148 | 146 | }; |
| 149 | 147 | |
| 150 | pub const __clzdi2 = clzXi2_generic(i64); | |
| 151 | ||
| 152 | pub const __clzti2 = clzXi2_generic(i128); | |
| 153 | ||
| 154 | fn 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))); | |
| 148 | pub fn __clzdi2(a: i64) callconv(.C) i32 { | |
| 149 | return clzXi2(i64, a); | |
| 150 | } | |
| 151 | ||
| 152 | pub fn __clzti2(a: i128) callconv(.C) i32 { | |
| 153 | return clzXi2(i128, a); | |
| 154 | } | |
| 155 | ||
| 156 | inline 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; | |
| 179 | 176 | } |
| 180 | }.f; | |
| 177 | } | |
| 178 | return @intCast(i32, n - @bitCast(T, (x & 1))); | |
| 179 | } | |
| 180 | ||
| 181 | pub fn __ctzsi2(a: i32) callconv(.C) i32 { | |
| 182 | return ctzXi2(i32, a); | |
| 181 | 183 | } |
| 182 | 184 | |
| 183 | pub const __ctzsi2 = ctzXi2_generic(i32); | |
| 184 | ||
| 185 | pub const __ctzdi2 = ctzXi2_generic(i64); | |
| 186 | ||
| 187 | pub const __ctzti2 = ctzXi2_generic(i128); | |
| 188 | ||
| 189 | fn 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); | |
| 185 | pub fn __ctzdi2(a: i64) callconv(.C) i32 { | |
| 186 | return ctzXi2(i64, a); | |
| 187 | } | |
| 188 | ||
| 189 | pub fn __ctzti2(a: i128) callconv(.C) i32 { | |
| 190 | return ctzXi2(i128, a); | |
| 191 | } | |
| 192 | ||
| 193 | inline 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; | |
| 216 | 214 | } |
| 217 | }.f; | |
| 215 | } | |
| 216 | // return ctz + 1 | |
| 217 | return @intCast(i32, n - @bitCast(T, (x & 1))) + @as(i32, 1); | |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | pub const __ffssi2 = ffsXi2_generic(i32); | |
| 220 | pub fn __ffssi2(a: i32) callconv(.C) i32 { | |
| 221 | return ffsXi2(i32, a); | |
| 222 | } | |
| 221 | 223 | |
| 222 | pub const __ffsdi2 = ffsXi2_generic(i64); | |
| 224 | pub fn __ffsdi2(a: i64) callconv(.C) i32 { | |
| 225 | return ffsXi2(i64, a); | |
| 226 | } | |
| 223 | 227 | |
| 224 | pub const __ffsti2 = ffsXi2_generic(i128); | |
| 228 | pub fn __ffsti2(a: i128) callconv(.C) i32 { | |
| 229 | return ffsXi2(i128, a); | |
| 230 | } | |
| 225 | 231 | |
| 226 | 232 | test { |
| 227 | 233 | _ = @import("clzsi2_test.zig"); |
lib/std/special/compiler_rt/divdf3.zig+1-1| ... | ... | @@ -35,7 +35,7 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 { |
| 35 | 35 | var scale: i32 = 0; |
| 36 | 36 | |
| 37 | 37 | // Detect if a or b is zero, denormal, infinity, or NaN. |
| 38 | if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { | |
| 38 | if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { | |
| 39 | 39 | const aAbs: Z = @bitCast(Z, a) & absMask; |
| 40 | 40 | const bAbs: Z = @bitCast(Z, b) & absMask; |
| 41 | 41 |
lib/std/special/compiler_rt/divsf3.zig+1-1| ... | ... | @@ -34,7 +34,7 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 { |
| 34 | 34 | var scale: i32 = 0; |
| 35 | 35 | |
| 36 | 36 | // Detect if a or b is zero, denormal, infinity, or NaN. |
| 37 | if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { | |
| 37 | if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { | |
| 38 | 38 | const aAbs: Z = @bitCast(Z, a) & absMask; |
| 39 | 39 | const bAbs: Z = @bitCast(Z, b) & absMask; |
| 40 | 40 |
lib/std/special/compiler_rt/divtf3.zig+1-1| ... | ... | @@ -33,7 +33,7 @@ pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 { |
| 33 | 33 | var scale: i32 = 0; |
| 34 | 34 | |
| 35 | 35 | // Detect if a or b is zero, denormal, infinity, or NaN. |
| 36 | if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { | |
| 36 | if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { | |
| 37 | 37 | const aAbs: Z = @bitCast(Z, a) & absMask; |
| 38 | 38 | const bAbs: Z = @bitCast(Z, b) & absMask; |
| 39 | 39 |
lib/std/special/compiler_rt/fixuint.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const is_test = @import("builtin").is_test; |
| 2 | 2 | const Log2Int = @import("std").math.Log2Int; |
| 3 | 3 | |
| 4 | pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t { | |
| 4 | pub inline fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t { | |
| 5 | 5 | @setRuntimeSafety(is_test); |
| 6 | 6 | |
| 7 | 7 | const rep_t = switch (fp_t) { |
lib/std/special/compiler_rt/floatXisf.zig+4-7| ... | ... | @@ -4,7 +4,7 @@ const maxInt = std.math.maxInt; |
| 4 | 4 | |
| 5 | 5 | const FLT_MANT_DIG = 24; |
| 6 | 6 | |
| 7 | fn __floatXisf(comptime T: type, arg: T) f32 { | |
| 7 | inline fn floatXisf(comptime T: type, arg: T) f32 { | |
| 8 | 8 | @setRuntimeSafety(builtin.is_test); |
| 9 | 9 | |
| 10 | 10 | const bits = @typeInfo(T).Int.bits; |
| ... | ... | @@ -71,18 +71,15 @@ fn __floatXisf(comptime T: type, arg: T) f32 { |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | pub 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); | |
| 76 | 75 | } |
| 77 | 76 | |
| 78 | 77 | pub 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); | |
| 81 | 79 | } |
| 82 | 80 | |
| 83 | 81 | pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 { |
| 84 | @setRuntimeSafety(false); | |
| 85 | return @call(.{ .modifier = .always_inline }, __floatdisf, .{arg}); | |
| 82 | return floatXisf(i64, arg); | |
| 86 | 83 | } |
| 87 | 84 | |
| 88 | 85 | test { |
lib/std/special/compiler_rt/floatsiXf.zig+6-6| ... | ... | @@ -2,7 +2,7 @@ const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | const maxInt = std.math.maxInt; |
| 4 | 4 | |
| 5 | fn floatsiXf(comptime T: type, a: i32) T { | |
| 5 | inline fn floatsiXf(comptime T: type, a: i32) T { | |
| 6 | 6 | @setRuntimeSafety(builtin.is_test); |
| 7 | 7 | |
| 8 | 8 | const bits = @typeInfo(T).Float.bits; |
| ... | ... | @@ -56,27 +56,27 @@ fn floatsiXf(comptime T: type, a: i32) T { |
| 56 | 56 | |
| 57 | 57 | pub fn __floatsisf(arg: i32) callconv(.C) f32 { |
| 58 | 58 | @setRuntimeSafety(builtin.is_test); |
| 59 | return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f32, arg }); | |
| 59 | return floatsiXf(f32, arg); | |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | pub fn __floatsidf(arg: i32) callconv(.C) f64 { |
| 63 | 63 | @setRuntimeSafety(builtin.is_test); |
| 64 | return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f64, arg }); | |
| 64 | return floatsiXf(f64, arg); | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | pub fn __floatsitf(arg: i32) callconv(.C) f128 { |
| 68 | 68 | @setRuntimeSafety(builtin.is_test); |
| 69 | return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f128, arg }); | |
| 69 | return floatsiXf(f128, arg); | |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 { |
| 73 | 73 | @setRuntimeSafety(false); |
| 74 | return @call(.{ .modifier = .always_inline }, __floatsidf, .{arg}); | |
| 74 | return floatsiXf(f64, arg); | |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 { |
| 78 | 78 | @setRuntimeSafety(false); |
| 79 | return @call(.{ .modifier = .always_inline }, __floatsisf, .{arg}); | |
| 79 | return floatsiXf(f32, arg); | |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | fn test_one_floatsitf(a: i32, expected: u128) !void { |
lib/std/special/compiler_rt/floatundisf.zig+6-3| ... | ... | @@ -4,7 +4,7 @@ const maxInt = std.math.maxInt; |
| 4 | 4 | |
| 5 | 5 | const FLT_MANT_DIG = 24; |
| 6 | 6 | |
| 7 | pub fn __floatundisf(arg: u64) callconv(.C) f32 { | |
| 7 | inline fn floatundisf(arg: u64) f32 { | |
| 8 | 8 | @setRuntimeSafety(builtin.is_test); |
| 9 | 9 | |
| 10 | 10 | if (arg == 0) return 0; |
| ... | ... | @@ -56,9 +56,12 @@ pub fn __floatundisf(arg: u64) callconv(.C) f32 { |
| 56 | 56 | return @bitCast(f32, result); |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | pub fn __floatundisf(arg: u64) callconv(.C) f32 { | |
| 60 | return floatundisf(arg); | |
| 61 | } | |
| 62 | ||
| 59 | 63 | pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 { |
| 60 | @setRuntimeSafety(false); | |
| 61 | return @call(.{ .modifier = .always_inline }, __floatundisf, .{arg}); | |
| 64 | return floatundisf(arg); | |
| 62 | 65 | } |
| 63 | 66 | |
| 64 | 67 | fn test__floatundisf(a: u64, expected: f32) !void { |
lib/std/special/compiler_rt/floatunsidf.zig+6-3| ... | ... | @@ -4,7 +4,7 @@ const maxInt = std.math.maxInt; |
| 4 | 4 | |
| 5 | 5 | const implicitBit = @as(u64, 1) << 52; |
| 6 | 6 | |
| 7 | pub fn __floatunsidf(arg: u32) callconv(.C) f64 { | |
| 7 | inline fn floatunsidf(arg: u32) f64 { | |
| 8 | 8 | @setRuntimeSafety(builtin.is_test); |
| 9 | 9 | |
| 10 | 10 | if (arg == 0) return 0.0; |
| ... | ... | @@ -18,9 +18,12 @@ pub fn __floatunsidf(arg: u32) callconv(.C) f64 { |
| 18 | 18 | return @bitCast(f64, mant | (exp + 1023) << 52); |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | pub fn __floatunsidf(arg: u32) callconv(.C) f64 { | |
| 22 | return floatunsidf(arg); | |
| 23 | } | |
| 24 | ||
| 21 | 25 | pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 { |
| 22 | @setRuntimeSafety(false); | |
| 23 | return @call(.{ .modifier = .always_inline }, __floatunsidf, .{arg}); | |
| 26 | return floatunsidf(arg); | |
| 24 | 27 | } |
| 25 | 28 | |
| 26 | 29 | fn test_one_floatunsidf(a: u32, expected: u64) !void { |
lib/std/special/compiler_rt/floatunsisf.zig+6-3| ... | ... | @@ -6,7 +6,7 @@ const significandBits = 23; |
| 6 | 6 | const exponentBias = 127; |
| 7 | 7 | const implicitBit = @as(u32, 1) << significandBits; |
| 8 | 8 | |
| 9 | pub fn __floatunsisf(arg: u32) callconv(.C) f32 { | |
| 9 | inline fn floatunsisf(arg: u32) f32 { | |
| 10 | 10 | @setRuntimeSafety(builtin.is_test); |
| 11 | 11 | |
| 12 | 12 | if (arg == 0) return 0.0; |
| ... | ... | @@ -38,9 +38,12 @@ pub fn __floatunsisf(arg: u32) callconv(.C) f32 { |
| 38 | 38 | return @bitCast(f32, result); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | pub fn __floatunsisf(arg: u32) callconv(.C) f32 { | |
| 42 | return floatunsisf(arg); | |
| 43 | } | |
| 44 | ||
| 41 | 45 | pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 { |
| 42 | @setRuntimeSafety(false); | |
| 43 | return @call(.{ .modifier = .always_inline }, __floatunsisf, .{arg}); | |
| 46 | return floatunsisf(arg); | |
| 44 | 47 | } |
| 45 | 48 | |
| 46 | 49 | fn test_one_floatunsisf(a: u32, expected: u32) !void { |
lib/std/special/compiler_rt/mulXf3.zig+1-1| ... | ... | @@ -56,7 +56,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T { |
| 56 | 56 | var scale: i32 = 0; |
| 57 | 57 | |
| 58 | 58 | // Detect if a or b is zero, denormal, infinity, or NaN. |
| 59 | if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { | |
| 59 | if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { | |
| 60 | 60 | const aAbs: Z = @bitCast(Z, a) & absMask; |
| 61 | 61 | const bAbs: Z = @bitCast(Z, b) & absMask; |
| 62 | 62 |
lib/std/special/compiler_rt/negXi2.zig+13-11| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | // neg - negate (the number) |
| 5 | // - negXi2_generic for unoptimized little and big endian | |
| 5 | // - negXi2 for unoptimized little and big endian | |
| 6 | 6 | |
| 7 | 7 | // sfffffff = 2^31-1 |
| 8 | 8 | // two's complement inverting bits and add 1 would result in -INT_MIN == 0 |
| ... | ... | @@ -11,20 +11,22 @@ const builtin = @import("builtin"); |
| 11 | 11 | // * size optimized builds |
| 12 | 12 | // * machines that dont support carry operations |
| 13 | 13 | |
| 14 | fn 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; | |
| 14 | inline fn negXi2(comptime T: type, a: T) T { | |
| 15 | @setRuntimeSafety(builtin.is_test); | |
| 16 | return -a; | |
| 21 | 17 | } |
| 22 | 18 | |
| 23 | pub const __negsi2 = negXi2_generic(i32); | |
| 19 | pub fn __negsi2(a: i32) callconv(.C) i32 { | |
| 20 | return negXi2(i32, a); | |
| 21 | } | |
| 24 | 22 | |
| 25 | pub const __negdi2 = negXi2_generic(i64); | |
| 23 | pub fn __negdi2(a: i64) callconv(.C) i64 { | |
| 24 | return negXi2(i64, a); | |
| 25 | } | |
| 26 | 26 | |
| 27 | pub const __negti2 = negXi2_generic(i128); | |
| 27 | pub fn __negti2(a: i128) callconv(.C) i128 { | |
| 28 | return negXi2(i128, a); | |
| 29 | } | |
| 28 | 30 | |
| 29 | 31 | test { |
| 30 | 32 | _ = @import("negsi2_test.zig"); |
lib/std/special/compiler_rt/negv.zig+24-19| ... | ... | @@ -3,26 +3,31 @@ |
| 3 | 3 | // - negvXi4_generic for unoptimized version |
| 4 | 4 | |
| 5 | 5 | // assume -0 == 0 is gracefully handled by the hardware |
| 6 | fn 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; | |
| 6 | inline 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 | ||
| 20 | pub fn __negvsi2(a: i32) callconv(.C) i32 { | |
| 21 | return negvXi(i32, a); | |
| 22 | } | |
| 23 | ||
| 24 | pub fn __negvdi2(a: i64) callconv(.C) i64 { | |
| 25 | return negvXi(i64, a); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn __negvti2(a: i128) callconv(.C) i128 { | |
| 29 | return negvXi(i128, a); | |
| 22 | 30 | } |
| 23 | pub const __negvsi2 = negvXi_generic(i32); | |
| 24 | pub const __negvdi2 = negvXi_generic(i64); | |
| 25 | pub const __negvti2 = negvXi_generic(i128); | |
| 26 | 31 | |
| 27 | 32 | test { |
| 28 | 33 | _ = @import("negvsi2_test.zig"); |
lib/std/special/compiler_rt/parity.zig+25-23| ... | ... | @@ -4,34 +4,36 @@ const builtin = @import("builtin"); |
| 4 | 4 | // parity - if number of bits set is even => 0, else => 1 |
| 5 | 5 | // - pariytXi2_generic for big and little endian |
| 6 | 6 | |
| 7 | fn 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); | |
| 7 | inline fn parityXi2(comptime T: type, a: T) i32 { | |
| 8 | @setRuntimeSafety(builtin.is_test); | |
| 11 | 9 | |
| 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 | |
| 28 | 24 | } |
| 29 | 25 | |
| 30 | pub const __paritysi2 = parityXi2_generic(i32); | |
| 26 | pub fn __paritysi2(a: i32) callconv(.C) i32 { | |
| 27 | return parityXi2(i32, a); | |
| 28 | } | |
| 31 | 29 | |
| 32 | pub const __paritydi2 = parityXi2_generic(i64); | |
| 30 | pub fn __paritydi2(a: i64) callconv(.C) i32 { | |
| 31 | return parityXi2(i64, a); | |
| 32 | } | |
| 33 | 33 | |
| 34 | pub const __parityti2 = parityXi2_generic(i128); | |
| 34 | pub fn __parityti2(a: i128) callconv(.C) i32 { | |
| 35 | return parityXi2(i128, a); | |
| 36 | } | |
| 35 | 37 | |
| 36 | 38 | test { |
| 37 | 39 | _ = @import("paritysi2_test.zig"); |
lib/std/special/compiler_rt/popcount.zig+27-25| ... | ... | @@ -10,35 +10,37 @@ const std = @import("std"); |
| 10 | 10 | // TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, |
| 11 | 11 | // subsubsection "Working with the rightmost bits" and "Sideways addition". |
| 12 | 12 | |
| 13 | fn 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; | |
| 13 | inline 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); | |
| 35 | 31 | } |
| 36 | 32 | |
| 37 | pub const __popcountsi2 = popcountXi2_generic(i32); | |
| 33 | pub fn __popcountsi2(a: i32) callconv(.C) i32 { | |
| 34 | return popcountXi2(i32, a); | |
| 35 | } | |
| 38 | 36 | |
| 39 | pub const __popcountdi2 = popcountXi2_generic(i64); | |
| 37 | pub fn __popcountdi2(a: i64) callconv(.C) i32 { | |
| 38 | return popcountXi2(i64, a); | |
| 39 | } | |
| 40 | 40 | |
| 41 | pub const __popcountti2 = popcountXi2_generic(i128); | |
| 41 | pub fn __popcountti2(a: i128) callconv(.C) i32 { | |
| 42 | return popcountXi2(i128, a); | |
| 43 | } | |
| 42 | 44 | |
| 43 | 45 | test { |
| 44 | 46 | _ = @import("popcountsi2_test.zig"); |
lib/std/special/compiler_rt/shift.zig+12-12| ... | ... | @@ -19,7 +19,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type { |
| 19 | 19 | |
| 20 | 20 | // Arithmetic shift left |
| 21 | 21 | // Precondition: 0 <= b < bits_in_dword |
| 22 | pub fn ashlXi3(comptime T: type, a: T, b: i32) T { | |
| 22 | pub inline fn ashlXi3(comptime T: type, a: T, b: i32) T { | |
| 23 | 23 | const dwords = Dwords(T, false); |
| 24 | 24 | const S = Log2Int(dwords.HalfT); |
| 25 | 25 | |
| ... | ... | @@ -42,7 +42,7 @@ pub fn ashlXi3(comptime T: type, a: T, b: i32) T { |
| 42 | 42 | |
| 43 | 43 | // Arithmetic shift right |
| 44 | 44 | // Precondition: 0 <= b < T.bit_count |
| 45 | pub fn ashrXi3(comptime T: type, a: T, b: i32) T { | |
| 45 | pub inline fn ashrXi3(comptime T: type, a: T, b: i32) T { | |
| 46 | 46 | const dwords = Dwords(T, true); |
| 47 | 47 | const S = Log2Int(dwords.HalfT); |
| 48 | 48 | |
| ... | ... | @@ -69,7 +69,7 @@ pub fn ashrXi3(comptime T: type, a: T, b: i32) T { |
| 69 | 69 | |
| 70 | 70 | // Logical shift right |
| 71 | 71 | // Precondition: 0 <= b < T.bit_count |
| 72 | pub fn lshrXi3(comptime T: type, a: T, b: i32) T { | |
| 72 | pub inline fn lshrXi3(comptime T: type, a: T, b: i32) T { | |
| 73 | 73 | const dwords = Dwords(T, false); |
| 74 | 74 | const S = Log2Int(dwords.HalfT); |
| 75 | 75 | |
| ... | ... | @@ -91,32 +91,32 @@ pub fn lshrXi3(comptime T: type, a: T, b: i32) T { |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 { |
| 94 | return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i64, a, b }); | |
| 94 | return ashlXi3(i64, a, b); | |
| 95 | 95 | } |
| 96 | 96 | pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 { |
| 97 | return @call(.{ .modifier = .always_inline }, ashlXi3, .{ i128, a, b }); | |
| 97 | return ashlXi3(i128, a, b); | |
| 98 | 98 | } |
| 99 | 99 | pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 { |
| 100 | return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i64, a, b }); | |
| 100 | return ashrXi3(i64, a, b); | |
| 101 | 101 | } |
| 102 | 102 | pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 { |
| 103 | return @call(.{ .modifier = .always_inline }, ashrXi3, .{ i128, a, b }); | |
| 103 | return ashrXi3(i128, a, b); | |
| 104 | 104 | } |
| 105 | 105 | pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 { |
| 106 | return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i64, a, b }); | |
| 106 | return lshrXi3(i64, a, b); | |
| 107 | 107 | } |
| 108 | 108 | pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { |
| 109 | return @call(.{ .modifier = .always_inline }, lshrXi3, .{ i128, a, b }); | |
| 109 | return lshrXi3(i128, a, b); | |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 { |
| 113 | return __ashldi3(a, b); | |
| 113 | return ashlXi3(i64, a, b); | |
| 114 | 114 | } |
| 115 | 115 | pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 { |
| 116 | return __ashrdi3(a, b); | |
| 116 | return ashrXi3(i64, a, b); | |
| 117 | 117 | } |
| 118 | 118 | pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 { |
| 119 | return __lshrdi3(a, b); | |
| 119 | return lshrXi3(i64, a, b); | |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | test { |
src/Cache.zig+54-3| ... | ... | @@ -47,10 +47,16 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{0} ** Hasher.key_length); |
| 47 | 47 | pub const File = struct { |
| 48 | 48 | path: ?[]const u8, |
| 49 | 49 | max_file_size: ?usize, |
| 50 | stat: fs.File.Stat, | |
| 50 | stat: Stat, | |
| 51 | 51 | bin_digest: BinDigest, |
| 52 | 52 | contents: ?[]const u8, |
| 53 | 53 | |
| 54 | pub const Stat = struct { | |
| 55 | inode: fs.File.INode, | |
| 56 | size: u64, | |
| 57 | mtime: i128, | |
| 58 | }; | |
| 59 | ||
| 54 | 60 | pub fn deinit(self: *File, allocator: Allocator) void { |
| 55 | 61 | if (self.path) |owned_slice| { |
| 56 | 62 | allocator.free(owned_slice); |
| ... | ... | @@ -424,7 +430,11 @@ pub const Manifest = struct { |
| 424 | 430 | if (!size_match or !mtime_match or !inode_match) { |
| 425 | 431 | self.manifest_dirty = true; |
| 426 | 432 | |
| 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 | }; | |
| 428 | 438 | |
| 429 | 439 | if (self.isProblematicTimestamp(cache_hash_file.stat.mtime)) { |
| 430 | 440 | // The actual file has an unreliable timestamp, force it to be hashed |
| ... | ... | @@ -530,7 +540,12 @@ pub const Manifest = struct { |
| 530 | 540 | const file = try fs.cwd().openFile(ch_file.path.?, .{}); |
| 531 | 541 | defer file.close(); |
| 532 | 542 | |
| 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 | }; | |
| 534 | 549 | |
| 535 | 550 | if (self.isProblematicTimestamp(ch_file.stat.mtime)) { |
| 536 | 551 | // The actual file has an unreliable timestamp, force it to be hashed |
| ... | ... | @@ -615,6 +630,42 @@ pub const Manifest = struct { |
| 615 | 630 | try self.populateFileHash(new_ch_file); |
| 616 | 631 | } |
| 617 | 632 | |
| 633 | /// Like `addFilePost` but when the file contents have already been loaded from disk. | |
| 634 | /// On success, cache takes ownership of `resolved_path`. | |
| 635 | pub fn addFilePostContents( | |
| 636 | self: *Manifest, | |
| 637 | resolved_path: []const u8, | |
| 638 | bytes: []const u8, | |
| 639 | stat: File.Stat, | |
| 640 | ) error{OutOfMemory}!void { | |
| 641 | assert(self.manifest_file != null); | |
| 642 | ||
| 643 | const ch_file = try self.files.addOne(self.cache.gpa); | |
| 644 | errdefer self.files.shrinkRetainingCapacity(self.files.items.len - 1); | |
| 645 | ||
| 646 | ch_file.* = .{ | |
| 647 | .path = resolved_path, | |
| 648 | .max_file_size = null, | |
| 649 | .stat = stat, | |
| 650 | .bin_digest = undefined, | |
| 651 | .contents = null, | |
| 652 | }; | |
| 653 | ||
| 654 | if (self.isProblematicTimestamp(ch_file.stat.mtime)) { | |
| 655 | // The actual file has an unreliable timestamp, force it to be hashed | |
| 656 | ch_file.stat.mtime = 0; | |
| 657 | ch_file.stat.inode = 0; | |
| 658 | } | |
| 659 | ||
| 660 | { | |
| 661 | var hasher = hasher_init; | |
| 662 | hasher.update(bytes); | |
| 663 | hasher.final(&ch_file.bin_digest); | |
| 664 | } | |
| 665 | ||
| 666 | self.hash.hasher.update(&ch_file.bin_digest); | |
| 667 | } | |
| 668 | ||
| 618 | 669 | pub fn addDepFilePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void { |
| 619 | 670 | assert(self.manifest_file != null); |
| 620 | 671 |
src/Compilation.zig+460-225| ... | ... | @@ -41,8 +41,8 @@ gpa: Allocator, |
| 41 | 41 | arena_state: std.heap.ArenaAllocator.State, |
| 42 | 42 | bin_file: *link.File, |
| 43 | 43 | c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, |
| 44 | stage1_lock: ?Cache.Lock = null, | |
| 45 | stage1_cache_manifest: *Cache.Manifest = undefined, | |
| 44 | /// This is a pointer to a local variable inside `update()`. | |
| 45 | whole_cache_manifest: ?*Cache.Manifest = null, | |
| 46 | 46 | |
| 47 | 47 | link_error_flags: link.File.ErrorFlags = .{}, |
| 48 | 48 | |
| ... | ... | @@ -98,6 +98,13 @@ clang_argv: []const []const u8, |
| 98 | 98 | cache_parent: *Cache, |
| 99 | 99 | /// Path to own executable for invoking `zig clang`. |
| 100 | 100 | self_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. | |
| 105 | whole_bin_sub_path: ?[]u8, | |
| 106 | /// Same as `whole_bin_sub_path` but for implibs. | |
| 107 | whole_implib_sub_path: ?[]u8, | |
| 101 | 108 | zig_lib_directory: Directory, |
| 102 | 109 | local_cache_directory: Directory, |
| 103 | 110 | global_cache_directory: Directory, |
| ... | ... | @@ -418,7 +425,7 @@ pub const AllErrors = struct { |
| 418 | 425 | const module_note = module_err_msg.notes[i]; |
| 419 | 426 | const source = try module_note.src_loc.file_scope.getSource(module.gpa); |
| 420 | 427 | const byte_offset = try module_note.src_loc.byteOffset(module.gpa); |
| 421 | const loc = std.zig.findLineColumn(source, byte_offset); | |
| 428 | const loc = std.zig.findLineColumn(source.bytes, byte_offset); | |
| 422 | 429 | const file_path = try module_note.src_loc.file_scope.fullPath(allocator); |
| 423 | 430 | note.* = .{ |
| 424 | 431 | .src = .{ |
| ... | ... | @@ -441,7 +448,7 @@ pub const AllErrors = struct { |
| 441 | 448 | } |
| 442 | 449 | const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa); |
| 443 | 450 | const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa); |
| 444 | const loc = std.zig.findLineColumn(source, byte_offset); | |
| 451 | const loc = std.zig.findLineColumn(source.bytes, byte_offset); | |
| 445 | 452 | const file_path = try module_err_msg.src_loc.file_scope.fullPath(allocator); |
| 446 | 453 | try errors.append(.{ |
| 447 | 454 | .src = .{ |
| ... | ... | @@ -612,6 +619,15 @@ pub const Directory = struct { |
| 612 | 619 | return std.fs.path.joinZ(allocator, paths); |
| 613 | 620 | } |
| 614 | 621 | } |
| 622 | ||
| 623 | /// Whether or not the handle should be closed, or the path should be freed | |
| 624 | /// is determined by usage, however this function is provided for convenience | |
| 625 | /// if it happens to be what the caller needs. | |
| 626 | pub fn closeAndFree(self: *Directory, gpa: Allocator) void { | |
| 627 | self.handle.close(); | |
| 628 | if (self.path) |p| gpa.free(p); | |
| 629 | self.* = undefined; | |
| 630 | } | |
| 615 | 631 | }; |
| 616 | 632 | |
| 617 | 633 | pub const EmitLoc = struct { |
| ... | ... | @@ -631,6 +647,7 @@ pub const ClangPreprocessorMode = enum { |
| 631 | 647 | }; |
| 632 | 648 | |
| 633 | 649 | pub const SystemLib = link.SystemLib; |
| 650 | pub const CacheMode = link.CacheMode; | |
| 634 | 651 | |
| 635 | 652 | pub const InitOptions = struct { |
| 636 | 653 | zig_lib_directory: Directory, |
| ... | ... | @@ -668,6 +685,7 @@ pub const InitOptions = struct { |
| 668 | 685 | /// is externally modified - essentially anything other than zig-cache - then |
| 669 | 686 | /// this flag would be set to disable this machinery to avoid false positives. |
| 670 | 687 | disable_lld_caching: bool = false, |
| 688 | cache_mode: CacheMode = .incremental, | |
| 671 | 689 | object_format: ?std.Target.ObjectFormat = null, |
| 672 | 690 | optimize_mode: std.builtin.Mode = .Debug, |
| 673 | 691 | keep_source_files_loaded: bool = false, |
| ... | ... | @@ -885,6 +903,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 885 | 903 | break :blk build_options.is_stage1; |
| 886 | 904 | }; |
| 887 | 905 | |
| 906 | const cache_mode = if (use_stage1 and !options.disable_lld_caching) | |
| 907 | CacheMode.whole | |
| 908 | else | |
| 909 | options.cache_mode; | |
| 910 | ||
| 888 | 911 | // Make a decision on whether to use LLVM or our own backend. |
| 889 | 912 | const use_llvm = build_options.have_llvm and blk: { |
| 890 | 913 | if (options.use_llvm) |explicit| |
| ... | ... | @@ -1219,39 +1242,75 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1219 | 1242 | // modified between incremental updates. |
| 1220 | 1243 | var hash = cache.hash; |
| 1221 | 1244 | |
| 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 | }, | |
| 1234 | 1265 | } |
| 1266 | ||
| 1267 | // Synchronize with other matching comments: ZigOnlyHashStuff | |
| 1235 | 1268 | hash.add(valgrind); |
| 1236 | 1269 | hash.add(single_threaded); |
| 1237 | 1270 | hash.add(use_stage1); |
| 1238 | 1271 | hash.add(use_llvm); |
| 1239 | 1272 | hash.add(dll_export_fns); |
| 1240 | 1273 | hash.add(options.is_test); |
| 1274 | hash.add(options.test_evented_io); | |
| 1275 | hash.addOptionalBytes(options.test_filter); | |
| 1276 | hash.addOptionalBytes(options.test_name_prefix); | |
| 1241 | 1277 | hash.add(options.skip_linker_dependencies); |
| 1242 | 1278 | hash.add(options.parent_compilation_link_libc); |
| 1243 | 1279 | |
| 1280 | // In the case of incremental cache mode, this `zig_cache_artifact_directory` | |
| 1281 | // is computed based on a hash of non-linker inputs, and it is where all | |
| 1282 | // build artifacts are stored (even while in-progress). | |
| 1283 | // | |
| 1284 | // For whole cache mode, it is still used for builtin.zig so that the file | |
| 1285 | // path to builtin.zig can remain consistent during a debugging session at | |
| 1286 | // runtime. However, we don't know where to put outputs from the linker | |
| 1287 | // or stage1 backend object files until the final cache hash, which is available | |
| 1288 | // after the compilation is complete. | |
| 1289 | // | |
| 1290 | // Therefore, in whole cache mode, we additionally create a temporary cache | |
| 1291 | // directory for these two kinds of build artifacts, and then rename it | |
| 1292 | // into place after the final hash is known. However, we don't want | |
| 1293 | // to create the temporary directory here, because in the case of a cache hit, | |
| 1294 | // this would have been wasted syscalls to make the directory and then not | |
| 1295 | // use it (or delete it). | |
| 1296 | // | |
| 1297 | // In summary, for whole cache mode, we simulate `-fno-emit-bin` in this | |
| 1298 | // function, and `zig_cache_artifact_directory` is *wrong* except for builtin.zig, | |
| 1299 | // and then at the beginning of `update()` when we find out whether we need | |
| 1300 | // a temporary directory, we patch up all the places that the incorrect | |
| 1301 | // `zig_cache_artifact_directory` was passed to various components of the compiler. | |
| 1302 | ||
| 1244 | 1303 | const digest = hash.final(); |
| 1245 | 1304 | const artifact_sub_dir = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); |
| 1246 | 1305 | var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{}); |
| 1247 | 1306 | errdefer artifact_dir.close(); |
| 1248 | 1307 | const zig_cache_artifact_directory: Directory = .{ |
| 1249 | 1308 | .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}), | |
| 1254 | 1310 | }; |
| 1311 | log.debug("zig_cache_artifact_directory='{s}' use_stage1={}", .{ | |
| 1312 | zig_cache_artifact_directory.path, use_stage1, | |
| 1313 | }); | |
| 1255 | 1314 | |
| 1256 | 1315 | const builtin_pkg = try Package.createWithDir( |
| 1257 | 1316 | gpa, |
| ... | ... | @@ -1374,6 +1433,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1374 | 1433 | }; |
| 1375 | 1434 | } |
| 1376 | 1435 | |
| 1436 | switch (cache_mode) { | |
| 1437 | .whole => break :blk null, | |
| 1438 | .incremental => {}, | |
| 1439 | } | |
| 1440 | ||
| 1377 | 1441 | if (module) |zm| { |
| 1378 | 1442 | break :blk link.Emit{ |
| 1379 | 1443 | .directory = zm.zig_cache_artifact_directory, |
| ... | ... | @@ -1417,6 +1481,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1417 | 1481 | }; |
| 1418 | 1482 | } |
| 1419 | 1483 | |
| 1484 | // This is here for the same reason as in `bin_file_emit` above. | |
| 1485 | switch (cache_mode) { | |
| 1486 | .whole => break :blk null, | |
| 1487 | .incremental => {}, | |
| 1488 | } | |
| 1489 | ||
| 1420 | 1490 | // Use the same directory as the bin. The CLI already emits an |
| 1421 | 1491 | // error if -fno-emit-bin is combined with -femit-implib. |
| 1422 | 1492 | break :blk link.Emit{ |
| ... | ... | @@ -1425,6 +1495,16 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1425 | 1495 | }; |
| 1426 | 1496 | }; |
| 1427 | 1497 | |
| 1498 | // This is so that when doing `CacheMode.whole`, the mechanism in update() | |
| 1499 | // can use it for communicating the result directory via `bin_file.emit`. | |
| 1500 | // This is used to distinguish between -fno-emit-bin and -femit-bin | |
| 1501 | // for `CacheMode.whole`. | |
| 1502 | // This memory will be overwritten with the real digest in update() but | |
| 1503 | // the basename will be preserved. | |
| 1504 | const whole_bin_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_bin); | |
| 1505 | // Same thing but for implibs. | |
| 1506 | const whole_implib_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_implib); | |
| 1507 | ||
| 1428 | 1508 | var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{}; |
| 1429 | 1509 | errdefer system_libs.deinit(gpa); |
| 1430 | 1510 | try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len); |
| ... | ... | @@ -1512,7 +1592,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1512 | 1592 | .skip_linker_dependencies = options.skip_linker_dependencies, |
| 1513 | 1593 | .parent_compilation_link_libc = options.parent_compilation_link_libc, |
| 1514 | 1594 | .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os, |
| 1515 | .disable_lld_caching = options.disable_lld_caching, | |
| 1595 | .cache_mode = cache_mode, | |
| 1596 | .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, | |
| 1516 | 1597 | .subsystem = options.subsystem, |
| 1517 | 1598 | .is_test = options.is_test, |
| 1518 | 1599 | .wasi_exec_model = wasi_exec_model, |
| ... | ... | @@ -1529,6 +1610,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1529 | 1610 | .local_cache_directory = options.local_cache_directory, |
| 1530 | 1611 | .global_cache_directory = options.global_cache_directory, |
| 1531 | 1612 | .bin_file = bin_file, |
| 1613 | .whole_bin_sub_path = whole_bin_sub_path, | |
| 1614 | .whole_implib_sub_path = whole_implib_sub_path, | |
| 1532 | 1615 | .emit_asm = options.emit_asm, |
| 1533 | 1616 | .emit_llvm_ir = options.emit_llvm_ir, |
| 1534 | 1617 | .emit_llvm_bc = options.emit_llvm_bc, |
| ... | ... | @@ -1593,7 +1676,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1593 | 1676 | comp.c_object_table.putAssumeCapacityNoClobber(c_object, {}); |
| 1594 | 1677 | } |
| 1595 | 1678 | |
| 1596 | if (comp.bin_file.options.emit != null and !comp.bin_file.options.skip_linker_dependencies) { | |
| 1679 | const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null; | |
| 1680 | ||
| 1681 | if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies) { | |
| 1597 | 1682 | // If we need to build glibc for the target, add work items for it. |
| 1598 | 1683 | // We go through the work queue so that building can be done in parallel. |
| 1599 | 1684 | if (comp.wantBuildGLibCFromSource()) { |
| ... | ... | @@ -1698,8 +1783,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1698 | 1783 | |
| 1699 | 1784 | if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) { |
| 1700 | 1785 | if (is_exe_or_dyn_lib) { |
| 1786 | log.debug("queuing a job to build compiler_rt_lib", .{}); | |
| 1701 | 1787 | try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} }); |
| 1702 | 1788 | } else if (options.output_mode != .Obj) { |
| 1789 | log.debug("queuing a job to build compiler_rt_obj", .{}); | |
| 1703 | 1790 | // If build-obj with -fcompiler-rt is requested, that is handled specially |
| 1704 | 1791 | // elsewhere. In this case we are making a static library, so we ask |
| 1705 | 1792 | // for a compiler-rt object to put in it. |
| ... | ... | @@ -1725,20 +1812,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1725 | 1812 | return comp; |
| 1726 | 1813 | } |
| 1727 | 1814 | |
| 1728 | fn releaseStage1Lock(comp: *Compilation) void { | |
| 1729 | if (comp.stage1_lock) |*lock| { | |
| 1730 | lock.release(); | |
| 1731 | comp.stage1_lock = null; | |
| 1732 | } | |
| 1733 | } | |
| 1734 | ||
| 1735 | 1815 | pub fn destroy(self: *Compilation) void { |
| 1736 | 1816 | const optional_module = self.bin_file.options.module; |
| 1737 | 1817 | self.bin_file.destroy(); |
| 1738 | 1818 | if (optional_module) |module| module.deinit(); |
| 1739 | 1819 | |
| 1740 | self.releaseStage1Lock(); | |
| 1741 | ||
| 1742 | 1820 | const gpa = self.gpa; |
| 1743 | 1821 | self.work_queue.deinit(); |
| 1744 | 1822 | self.anon_work_queue.deinit(); |
| ... | ... | @@ -1815,22 +1893,126 @@ pub fn getTarget(self: Compilation) Target { |
| 1815 | 1893 | return self.bin_file.options.target; |
| 1816 | 1894 | } |
| 1817 | 1895 | |
| 1896 | fn 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 | ||
| 1908 | fn cleanupTmpArtifactDirectory( | |
| 1909 | comp: *Compilation, | |
| 1910 | tmp_artifact_directory: *?Directory, | |
| 1911 | tmp_dir_sub_path: []const u8, | |
| 1912 | ) void { | |
| 1913 | comp.gpa.free(tmp_dir_sub_path); | |
| 1914 | if (tmp_artifact_directory.*) |*directory| { | |
| 1915 | directory.handle.close(); | |
| 1916 | restorePrevZigCacheArtifactDirectory(comp, directory); | |
| 1917 | } | |
| 1918 | } | |
| 1919 | ||
| 1818 | 1920 | /// Detect changes to source files, perform semantic analysis, and update the output files. |
| 1819 | pub fn update(self: *Compilation) !void { | |
| 1921 | pub fn update(comp: *Compilation) !void { | |
| 1820 | 1922 | const tracy_trace = trace(@src()); |
| 1821 | 1923 | defer tracy_trace.end(); |
| 1822 | 1924 | |
| 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 | } | |
| 1824 | 2006 | |
| 1825 | 2007 | // For compiling C objects, we rely on the cache hash system to avoid duplicating work. |
| 1826 | 2008 | // 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); | |
| 1830 | 2012 | } |
| 1831 | 2013 | |
| 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| { | |
| 1834 | 2016 | module.compile_log_text.shrinkAndFree(module.gpa, 0); |
| 1835 | 2017 | module.generation += 1; |
| 1836 | 2018 | |
| ... | ... | @@ -1845,7 +2027,7 @@ pub fn update(self: *Compilation) !void { |
| 1845 | 2027 | // import_table here. |
| 1846 | 2028 | // Likewise, in the case of `zig test`, the test runner is the root source file, |
| 1847 | 2029 | // and so there is nothing to import the main file. |
| 1848 | if (use_stage1 or self.bin_file.options.is_test) { | |
| 2030 | if (use_stage1 or comp.bin_file.options.is_test) { | |
| 1849 | 2031 | _ = try module.importPkg(module.main_pkg); |
| 1850 | 2032 | } |
| 1851 | 2033 | |
| ... | ... | @@ -1854,34 +2036,34 @@ pub fn update(self: *Compilation) !void { |
| 1854 | 2036 | // to update it. |
| 1855 | 2037 | // We still want AstGen work items for stage1 so that we expose compile errors |
| 1856 | 2038 | // that are implemented in stage2 but not stage1. |
| 1857 | try self.astgen_work_queue.ensureUnusedCapacity(module.import_table.count()); | |
| 2039 | try comp.astgen_work_queue.ensureUnusedCapacity(module.import_table.count()); | |
| 1858 | 2040 | for (module.import_table.values()) |value| { |
| 1859 | self.astgen_work_queue.writeItemAssumeCapacity(value); | |
| 2041 | comp.astgen_work_queue.writeItemAssumeCapacity(value); | |
| 1860 | 2042 | } |
| 1861 | 2043 | |
| 1862 | 2044 | if (!use_stage1) { |
| 1863 | 2045 | // Put a work item in for checking if any files used with `@embedFile` changed. |
| 1864 | 2046 | { |
| 1865 | try self.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count()); | |
| 2047 | try comp.embed_file_work_queue.ensureUnusedCapacity(module.embed_table.count()); | |
| 1866 | 2048 | var it = module.embed_table.iterator(); |
| 1867 | 2049 | while (it.next()) |entry| { |
| 1868 | 2050 | const embed_file = entry.value_ptr.*; |
| 1869 | self.embed_file_work_queue.writeItemAssumeCapacity(embed_file); | |
| 2051 | comp.embed_file_work_queue.writeItemAssumeCapacity(embed_file); | |
| 1870 | 2052 | } |
| 1871 | 2053 | } |
| 1872 | 2054 | |
| 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 }); | |
| 1876 | 2058 | } |
| 1877 | 2059 | } |
| 1878 | 2060 | } |
| 1879 | 2061 | |
| 1880 | try self.performAllTheWork(); | |
| 2062 | try comp.performAllTheWork(); | |
| 1881 | 2063 | |
| 1882 | 2064 | 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) { | |
| 1885 | 2067 | // The `test_functions` decl has been intentionally postponed until now, |
| 1886 | 2068 | // at which point we must populate it with the list of test functions that |
| 1887 | 2069 | // have been discovered and not filtered out. |
| ... | ... | @@ -1910,41 +2092,241 @@ pub fn update(self: *Compilation) !void { |
| 1910 | 2092 | } |
| 1911 | 2093 | } |
| 1912 | 2094 | |
| 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 = .{}; | |
| 1916 | 2098 | return; |
| 1917 | 2099 | } |
| 1918 | 2100 | |
| 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(); | |
| 1922 | 2107 | |
| 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(); | |
| 1926 | 2139 | } |
| 1927 | } | |
| 1928 | 2140 | |
| 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 | } | |
| 1932 | 2151 | |
| 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. | |
| 1935 | 2153 | // The ZIR needs to stay loaded in memory because (1) Decl objects contain references |
| 1936 | 2154 | // to it, and (2) generic instantiations, comptime calls, inline calls will need |
| 1937 | 2155 | // 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| { | |
| 1940 | 2158 | 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); | |
| 1943 | 2161 | } |
| 1944 | 2162 | } |
| 1945 | 2163 | } |
| 1946 | 2164 | } |
| 1947 | 2165 | |
| 2166 | fn 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. | |
| 2179 | fn 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 | ||
| 2201 | fn 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. | |
| 2213 | pub const link_hash_implementation_version = 1; | |
| 2214 | ||
| 2215 | fn 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 | ||
| 1948 | 2330 | fn emitOthers(comp: *Compilation) void { |
| 1949 | 2331 | if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or |
| 1950 | 2332 | comp.c_object_table.count() == 0) |
| ... | ... | @@ -2988,7 +3370,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { |
| 2988 | 3370 | |
| 2989 | 3371 | const dep_basename = std.fs.path.basename(out_dep_path); |
| 2990 | 3372 | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); |
| 2991 | if (build_options.is_stage1 and comp.bin_file.options.use_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); | |
| 3373 | if (comp.whole_cache_manifest) |whole_cache_manifest| { | |
| 3374 | try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); | |
| 3375 | } | |
| 2992 | 3376 | |
| 2993 | 3377 | const digest = man.final(); |
| 2994 | 3378 | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); |
| ... | ... | @@ -3351,13 +3735,13 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 3351 | 3735 | }; |
| 3352 | 3736 | } |
| 3353 | 3737 | |
| 3354 | pub fn tmpFilePath(comp: *Compilation, arena: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { | |
| 3738 | pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { | |
| 3355 | 3739 | const s = std.fs.path.sep_str; |
| 3356 | 3740 | const rand_int = std.crypto.random.int(u64); |
| 3357 | 3741 | if (comp.local_cache_directory.path) |p| { |
| 3358 | return std.fmt.allocPrint(arena, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix }); | |
| 3742 | return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix }); | |
| 3359 | 3743 | } else { |
| 3360 | return std.fmt.allocPrint(arena, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix }); | |
| 3744 | return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix }); | |
| 3361 | 3745 | } |
| 3362 | 3746 | } |
| 3363 | 3747 | |
| ... | ... | @@ -4424,6 +4808,7 @@ fn buildOutputFromZig( |
| 4424 | 4808 | .global_cache_directory = comp.global_cache_directory, |
| 4425 | 4809 | .local_cache_directory = comp.global_cache_directory, |
| 4426 | 4810 | .zig_lib_directory = comp.zig_lib_directory, |
| 4811 | .cache_mode = .whole, | |
| 4427 | 4812 | .target = target, |
| 4428 | 4813 | .root_name = root_name, |
| 4429 | 4814 | .main_pkg = &main_pkg, |
| ... | ... | @@ -4501,10 +4886,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4501 | 4886 | mod.main_pkg.root_src_path, |
| 4502 | 4887 | }); |
| 4503 | 4888 | const zig_lib_dir = comp.zig_lib_directory.path.?; |
| 4504 | const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"}); | |
| 4505 | 4889 | const target = comp.getTarget(); |
| 4506 | const id_symlink_basename = "stage1.id"; | |
| 4507 | const libs_txt_basename = "libs.txt"; | |
| 4508 | 4890 | |
| 4509 | 4891 | // The include_compiler_rt stored in the bin file options here means that we need |
| 4510 | 4892 | // compiler-rt symbols *somehow*. However, in the context of using the stage1 backend |
| ... | ... | @@ -4516,115 +4898,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4516 | 4898 | const include_compiler_rt = comp.bin_file.options.output_mode == .Obj and |
| 4517 | 4899 | comp.bin_file.options.include_compiler_rt; |
| 4518 | 4900 | |
| 4519 | // We are about to obtain this lock, so here we give other processes a chance first. | |
| 4520 | comp.releaseStage1Lock(); | |
| 4521 | ||
| 4522 | // Unlike with the self-hosted Zig module, stage1 does not support incremental compilation, | |
| 4523 | // so we input all the zig source files into the cache hash system. We're going to keep | |
| 4524 | // the artifact directory the same, however, so we take the same strategy as linking | |
| 4525 | // does where we have a file which specifies the hash of the output directory so that we can | |
| 4526 | // skip the expensive compilation step if the hash matches. | |
| 4527 | var man = comp.cache_parent.obtain(); | |
| 4528 | defer man.deinit(); | |
| 4529 | ||
| 4530 | _ = try man.addFile(main_zig_file, null); | |
| 4531 | { | |
| 4532 | var seen_table = std.AutoHashMap(*Package, void).init(arena_allocator.allocator()); | |
| 4533 | try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.main_pkg.table, &seen_table, .{ .files = &man }); | |
| 4534 | } | |
| 4535 | man.hash.add(comp.bin_file.options.valgrind); | |
| 4536 | man.hash.add(comp.bin_file.options.single_threaded); | |
| 4537 | man.hash.add(target.os.getVersionRange()); | |
| 4538 | man.hash.add(comp.bin_file.options.dll_export_fns); | |
| 4539 | man.hash.add(comp.bin_file.options.function_sections); | |
| 4540 | man.hash.add(include_compiler_rt); | |
| 4541 | man.hash.add(comp.bin_file.options.is_test); | |
| 4542 | man.hash.add(comp.bin_file.options.emit != null); | |
| 4543 | man.hash.add(mod.emit_h != null); | |
| 4544 | if (mod.emit_h) |emit_h| { | |
| 4545 | man.hash.addEmitLoc(emit_h.loc); | |
| 4546 | } | |
| 4547 | man.hash.addOptionalEmitLoc(comp.emit_asm); | |
| 4548 | man.hash.addOptionalEmitLoc(comp.emit_llvm_ir); | |
| 4549 | man.hash.addOptionalEmitLoc(comp.emit_llvm_bc); | |
| 4550 | man.hash.addOptionalEmitLoc(comp.emit_analysis); | |
| 4551 | man.hash.addOptionalEmitLoc(comp.emit_docs); | |
| 4552 | man.hash.add(comp.test_evented_io); | |
| 4553 | man.hash.addOptionalBytes(comp.test_filter); | |
| 4554 | man.hash.addOptionalBytes(comp.test_name_prefix); | |
| 4555 | man.hash.addListOfBytes(comp.clang_argv); | |
| 4556 | ||
| 4557 | // Capture the state in case we come back from this branch where the hash doesn't match. | |
| 4558 | const prev_hash_state = man.hash.peekBin(); | |
| 4559 | const input_file_count = man.files.items.len; | |
| 4560 | ||
| 4561 | const hit = man.hit() catch |err| { | |
| 4562 | const i = man.failed_file_index orelse return err; | |
| 4563 | const file_path = man.files.items[i].path orelse return err; | |
| 4564 | fatal("unable to build stage1 zig object: {s}: {s}", .{ @errorName(err), file_path }); | |
| 4565 | }; | |
| 4566 | if (hit) { | |
| 4567 | const digest = man.final(); | |
| 4568 | ||
| 4569 | // We use an extra hex-encoded byte here to store some flags. | |
| 4570 | var prev_digest_buf: [digest.len + 2]u8 = undefined; | |
| 4571 | const prev_digest: []u8 = Cache.readSmallFile( | |
| 4572 | directory.handle, | |
| 4573 | id_symlink_basename, | |
| 4574 | &prev_digest_buf, | |
| 4575 | ) catch |err| blk: { | |
| 4576 | log.debug("stage1 {s} new_digest={s} error: {s}", .{ | |
| 4577 | mod.main_pkg.root_src_path, | |
| 4578 | std.fmt.fmtSliceHexLower(&digest), | |
| 4579 | @errorName(err), | |
| 4580 | }); | |
| 4581 | // Handle this as a cache miss. | |
| 4582 | break :blk prev_digest_buf[0..0]; | |
| 4583 | }; | |
| 4584 | if (prev_digest.len >= digest.len + 2) hit: { | |
| 4585 | if (!mem.eql(u8, prev_digest[0..digest.len], &digest)) | |
| 4586 | break :hit; | |
| 4587 | ||
| 4588 | log.debug("stage1 {s} digest={s} match - skipping invocation", .{ | |
| 4589 | mod.main_pkg.root_src_path, | |
| 4590 | std.fmt.fmtSliceHexLower(&digest), | |
| 4591 | }); | |
| 4592 | var flags_bytes: [1]u8 = undefined; | |
| 4593 | _ = std.fmt.hexToBytes(&flags_bytes, prev_digest[digest.len..]) catch { | |
| 4594 | log.warn("bad cache stage1 digest: '{s}'", .{std.fmt.fmtSliceHexLower(prev_digest)}); | |
| 4595 | break :hit; | |
| 4596 | }; | |
| 4597 | ||
| 4598 | if (directory.handle.readFileAlloc(comp.gpa, libs_txt_basename, 10 * 1024 * 1024)) |libs_txt| { | |
| 4599 | var it = mem.tokenize(u8, libs_txt, "\n"); | |
| 4600 | while (it.next()) |lib_name| { | |
| 4601 | try comp.stage1AddLinkLib(lib_name); | |
| 4602 | } | |
| 4603 | } else |err| switch (err) { | |
| 4604 | error.FileNotFound => {}, // That's OK, it just means 0 libs. | |
| 4605 | else => { | |
| 4606 | log.warn("unable to read cached list of link libs: {s}", .{@errorName(err)}); | |
| 4607 | break :hit; | |
| 4608 | }, | |
| 4609 | } | |
| 4610 | comp.stage1_lock = man.toOwnedLock(); | |
| 4611 | mod.stage1_flags = @bitCast(@TypeOf(mod.stage1_flags), flags_bytes[0]); | |
| 4612 | return; | |
| 4613 | } | |
| 4614 | log.debug("stage1 {s} prev_digest={s} new_digest={s}", .{ | |
| 4615 | mod.main_pkg.root_src_path, | |
| 4616 | std.fmt.fmtSliceHexLower(prev_digest), | |
| 4617 | std.fmt.fmtSliceHexLower(&digest), | |
| 4618 | }); | |
| 4619 | man.unhit(prev_hash_state, input_file_count); | |
| 4620 | } | |
| 4621 | ||
| 4622 | // We are about to change the output file to be different, so we invalidate the build hash now. | |
| 4623 | directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) { | |
| 4624 | error.FileNotFound => {}, | |
| 4625 | else => |e| return e, | |
| 4626 | }; | |
| 4627 | ||
| 4628 | 4901 | const stage2_target = try arena.create(stage1.Stage2Target); |
| 4629 | 4902 | stage2_target.* = .{ |
| 4630 | 4903 | .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch |
| ... | ... | @@ -4637,9 +4910,9 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4637 | 4910 | .llvm_target_abi = if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, |
| 4638 | 4911 | }; |
| 4639 | 4912 | |
| 4640 | comp.stage1_cache_manifest = &man; | |
| 4641 | ||
| 4642 | 4913 | const main_pkg_path = mod.main_pkg.root_src_directory.path orelse ""; |
| 4914 | const builtin_pkg = mod.main_pkg.table.get("builtin").?; | |
| 4915 | const builtin_zig_path = try builtin_pkg.root_src_directory.join(arena, &.{builtin_pkg.root_src_path}); | |
| 4643 | 4916 | |
| 4644 | 4917 | const stage1_module = stage1.create( |
| 4645 | 4918 | @enumToInt(comp.bin_file.options.optimize_mode), |
| ... | ... | @@ -4740,19 +5013,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4740 | 5013 | .have_dllmain_crt_startup = false, |
| 4741 | 5014 | }; |
| 4742 | 5015 | |
| 4743 | const inferred_lib_start_index = comp.bin_file.options.system_libs.count(); | |
| 4744 | 5016 | stage1_module.build_object(); |
| 4745 | 5017 | |
| 4746 | if (comp.bin_file.options.system_libs.count() > inferred_lib_start_index) { | |
| 4747 | // We need to save the inferred link libs to the cache, otherwise if we get a cache hit | |
| 4748 | // next time we will be missing these libs. | |
| 4749 | var libs_txt = std.ArrayList(u8).init(arena); | |
| 4750 | for (comp.bin_file.options.system_libs.keys()[inferred_lib_start_index..]) |key| { | |
| 4751 | try libs_txt.writer().print("{s}\n", .{key}); | |
| 4752 | } | |
| 4753 | try directory.handle.writeFile(libs_txt_basename, libs_txt.items); | |
| 4754 | } | |
| 4755 | ||
| 4756 | 5018 | mod.stage1_flags = .{ |
| 4757 | 5019 | .have_c_main = stage1_module.have_c_main, |
| 4758 | 5020 | .have_winmain = stage1_module.have_winmain, |
| ... | ... | @@ -4763,34 +5025,6 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4763 | 5025 | }; |
| 4764 | 5026 | |
| 4765 | 5027 | stage1_module.destroy(); |
| 4766 | ||
| 4767 | const digest = man.final(); | |
| 4768 | ||
| 4769 | // Update the small file with the digest. If it fails we can continue; it only | |
| 4770 | // means that the next invocation will have an unnecessary cache miss. | |
| 4771 | const stage1_flags_byte = @bitCast(u8, mod.stage1_flags); | |
| 4772 | log.debug("stage1 {s} final digest={s} flags={x}", .{ | |
| 4773 | mod.main_pkg.root_src_path, std.fmt.fmtSliceHexLower(&digest), stage1_flags_byte, | |
| 4774 | }); | |
| 4775 | var digest_plus_flags: [digest.len + 2]u8 = undefined; | |
| 4776 | digest_plus_flags[0..digest.len].* = digest; | |
| 4777 | assert(std.fmt.formatIntBuf(digest_plus_flags[digest.len..], stage1_flags_byte, 16, .lower, .{ | |
| 4778 | .width = 2, | |
| 4779 | .fill = '0', | |
| 4780 | }) == 2); | |
| 4781 | log.debug("saved digest + flags: '{s}' (byte = {}) have_winmain_crt_startup={}", .{ | |
| 4782 | digest_plus_flags, stage1_flags_byte, mod.stage1_flags.have_winmain_crt_startup, | |
| 4783 | }); | |
| 4784 | Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest_plus_flags) catch |err| { | |
| 4785 | log.warn("failed to save stage1 hash digest file: {s}", .{@errorName(err)}); | |
| 4786 | }; | |
| 4787 | // Failure here only means an unnecessary cache miss. | |
| 4788 | man.writeManifest() catch |err| { | |
| 4789 | log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)}); | |
| 4790 | }; | |
| 4791 | // We hang on to this lock so that the output file path can be used without | |
| 4792 | // other processes clobbering it. | |
| 4793 | comp.stage1_lock = man.toOwnedLock(); | |
| 4794 | 5028 | } |
| 4795 | 5029 | |
| 4796 | 5030 | fn stage1LocPath(arena: Allocator, opt_loc: ?EmitLoc, cache_directory: Directory) ![]const u8 { |
| ... | ... | @@ -4862,6 +5096,7 @@ pub fn build_crt_file( |
| 4862 | 5096 | .local_cache_directory = comp.global_cache_directory, |
| 4863 | 5097 | .global_cache_directory = comp.global_cache_directory, |
| 4864 | 5098 | .zig_lib_directory = comp.zig_lib_directory, |
| 5099 | .cache_mode = .whole, | |
| 4865 | 5100 | .target = target, |
| 4866 | 5101 | .root_name = root_name, |
| 4867 | 5102 | .main_pkg = null, |
src/Module.zig+114-45| ... | ... | @@ -33,7 +33,7 @@ const build_options = @import("build_options"); |
| 33 | 33 | gpa: Allocator, |
| 34 | 34 | comp: *Compilation, |
| 35 | 35 | |
| 36 | /// Where our incremental compilation metadata serialization will go. | |
| 36 | /// Where build artifacts and incremental compilation metadata serialization go. | |
| 37 | 37 | zig_cache_artifact_directory: Compilation.Directory, |
| 38 | 38 | /// Pointer to externally managed resource. |
| 39 | 39 | root_pkg: *Package, |
| ... | ... | @@ -1463,11 +1463,7 @@ pub const File = struct { |
| 1463 | 1463 | /// Whether this is populated depends on `source_loaded`. |
| 1464 | 1464 | source: [:0]const u8, |
| 1465 | 1465 | /// 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, | |
| 1471 | 1467 | /// Whether this is populated or not depends on `tree_loaded`. |
| 1472 | 1468 | tree: Ast, |
| 1473 | 1469 | /// Whether this is populated or not depends on `zir_loaded`. |
| ... | ... | @@ -1535,8 +1531,16 @@ pub const File = struct { |
| 1535 | 1531 | file.* = undefined; |
| 1536 | 1532 | } |
| 1537 | 1533 | |
| 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 | }; | |
| 1540 | 1544 | |
| 1541 | 1545 | const root_dir_path = file.pkg.root_src_directory.path orelse "."; |
| 1542 | 1546 | log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{ |
| ... | ... | @@ -1565,14 +1569,21 @@ pub const File = struct { |
| 1565 | 1569 | |
| 1566 | 1570 | file.source = source; |
| 1567 | 1571 | file.source_loaded = true; |
| 1568 | return source; | |
| 1572 | return Source{ | |
| 1573 | .bytes = source, | |
| 1574 | .stat = .{ | |
| 1575 | .size = stat.size, | |
| 1576 | .inode = stat.inode, | |
| 1577 | .mtime = stat.mtime, | |
| 1578 | }, | |
| 1579 | }; | |
| 1569 | 1580 | } |
| 1570 | 1581 | |
| 1571 | 1582 | pub fn getTree(file: *File, gpa: Allocator) !*const Ast { |
| 1572 | 1583 | if (file.tree_loaded) return &file.tree; |
| 1573 | 1584 | |
| 1574 | 1585 | const source = try file.getSource(gpa); |
| 1575 | file.tree = try std.zig.parse(gpa, source); | |
| 1586 | file.tree = try std.zig.parse(gpa, source.bytes); | |
| 1576 | 1587 | file.tree_loaded = true; |
| 1577 | 1588 | return &file.tree; |
| 1578 | 1589 | } |
| ... | ... | @@ -1631,9 +1642,7 @@ pub const EmbedFile = struct { |
| 1631 | 1642 | /// Memory is stored in gpa, owned by EmbedFile. |
| 1632 | 1643 | sub_file_path: []const u8, |
| 1633 | 1644 | bytes: [:0]const u8, |
| 1634 | stat_size: u64, | |
| 1635 | stat_inode: std.fs.File.INode, | |
| 1636 | stat_mtime: i128, | |
| 1645 | stat: Cache.File.Stat, | |
| 1637 | 1646 | /// Package that this file is a part of, managed externally. |
| 1638 | 1647 | pkg: *Package, |
| 1639 | 1648 | /// The Decl that was created from the `@embedFile` to own this resource. |
| ... | ... | @@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2704 | 2713 | keep_zir = true; |
| 2705 | 2714 | file.zir = zir; |
| 2706 | 2715 | 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 | }; | |
| 2710 | 2721 | file.status = .success_zir; |
| 2711 | 2722 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); |
| 2712 | 2723 | |
| ... | ... | @@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2724 | 2735 | }, |
| 2725 | 2736 | .parse_failure, .astgen_failure, .success_zir => { |
| 2726 | 2737 | 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; | |
| 2730 | 2741 | |
| 2731 | 2742 | if (unchanged_metadata) { |
| 2732 | 2743 | log.debug("unmodified metadata of file: {s}", .{file.sub_file_path}); |
| ... | ... | @@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2787 | 2798 | if (amt != stat.size) |
| 2788 | 2799 | return error.UnexpectedEndOfFile; |
| 2789 | 2800 | |
| 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 | }; | |
| 2793 | 2806 | file.source = source; |
| 2794 | 2807 | file.source_loaded = true; |
| 2795 | 2808 | |
| ... | ... | @@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void { |
| 3069 | 3082 | |
| 3070 | 3083 | try writeBuiltinFile(file, builtin_pkg); |
| 3071 | 3084 | } 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 | }; | |
| 3075 | 3090 | } |
| 3076 | 3091 | } else |err| switch (err) { |
| 3077 | 3092 | error.BadPathName => unreachable, // it's always "builtin.zig" |
| ... | ... | @@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void { |
| 3099 | 3114 | try af.file.writeAll(file.source); |
| 3100 | 3115 | try af.finish(); |
| 3101 | 3116 | |
| 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 | }; | |
| 3105 | 3122 | } |
| 3106 | 3123 | |
| 3107 | 3124 | pub fn mapOldZirToNew( |
| ... | ... | @@ -3380,6 +3397,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3380 | 3397 | error.OutOfMemory => return error.OutOfMemory, |
| 3381 | 3398 | error.AnalysisFail => {}, |
| 3382 | 3399 | } |
| 3400 | ||
| 3401 | if (mod.comp.whole_cache_manifest) |man| { | |
| 3402 | const source = file.getSource(gpa) catch |err| { | |
| 3403 | try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)}); | |
| 3404 | return error.AnalysisFail; | |
| 3405 | }; | |
| 3406 | const resolved_path = try file.pkg.root_src_directory.join(gpa, &.{ | |
| 3407 | file.sub_file_path, | |
| 3408 | }); | |
| 3409 | errdefer gpa.free(resolved_path); | |
| 3410 | ||
| 3411 | try man.addFilePostContents(resolved_path, source.bytes, source.stat); | |
| 3412 | } | |
| 3383 | 3413 | } else { |
| 3384 | 3414 | new_decl.analysis = .file_failure; |
| 3385 | 3415 | } |
| ... | ... | @@ -3710,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { |
| 3710 | 3740 | .source_loaded = false, |
| 3711 | 3741 | .tree_loaded = false, |
| 3712 | 3742 | .zir_loaded = false, |
| 3713 | .stat_size = undefined, | |
| 3714 | .stat_inode = undefined, | |
| 3715 | .stat_mtime = undefined, | |
| 3743 | .stat = undefined, | |
| 3716 | 3744 | .tree = undefined, |
| 3717 | 3745 | .zir = undefined, |
| 3718 | 3746 | .status = .never_loaded, |
| ... | ... | @@ -3780,9 +3808,7 @@ pub fn importFile( |
| 3780 | 3808 | .source_loaded = false, |
| 3781 | 3809 | .tree_loaded = false, |
| 3782 | 3810 | .zir_loaded = false, |
| 3783 | .stat_size = undefined, | |
| 3784 | .stat_inode = undefined, | |
| 3785 | .stat_mtime = undefined, | |
| 3811 | .stat = undefined, | |
| 3786 | 3812 | .tree = undefined, |
| 3787 | 3813 | .zir = undefined, |
| 3788 | 3814 | .status = .never_loaded, |
| ... | ... | @@ -3827,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb |
| 3827 | 3853 | var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{}); |
| 3828 | 3854 | defer file.close(); |
| 3829 | 3855 | |
| 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); | |
| 3832 | 3863 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); |
| 3833 | 3864 | errdefer gpa.free(bytes); |
| 3834 | 3865 | |
| ... | ... | @@ -3836,14 +3867,18 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb |
| 3836 | 3867 | resolved_root_path, resolved_path, sub_file_path, rel_file_path, |
| 3837 | 3868 | }); |
| 3838 | 3869 | |
| 3870 | if (mod.comp.whole_cache_manifest) |man| { | |
| 3871 | const copied_resolved_path = try gpa.dupe(u8, resolved_path); | |
| 3872 | errdefer gpa.free(copied_resolved_path); | |
| 3873 | try man.addFilePostContents(copied_resolved_path, bytes, stat); | |
| 3874 | } | |
| 3875 | ||
| 3839 | 3876 | keep_resolved_path = true; // It's now owned by embed_table. |
| 3840 | 3877 | gop.value_ptr.* = new_file; |
| 3841 | 3878 | new_file.* = .{ |
| 3842 | 3879 | .sub_file_path = sub_file_path, |
| 3843 | 3880 | .bytes = bytes, |
| 3844 | .stat_size = stat.size, | |
| 3845 | .stat_inode = stat.inode, | |
| 3846 | .stat_mtime = stat.mtime, | |
| 3881 | .stat = stat, | |
| 3847 | 3882 | .pkg = cur_file.pkg, |
| 3848 | 3883 | .owner_decl = undefined, // Set by Sema immediately after this function returns. |
| 3849 | 3884 | }; |
| ... | ... | @@ -3857,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { |
| 3857 | 3892 | const stat = try file.stat(); |
| 3858 | 3893 | |
| 3859 | 3894 | 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; | |
| 3863 | 3898 | |
| 3864 | 3899 | if (unchanged_metadata) return; |
| 3865 | 3900 | |
| ... | ... | @@ -3868,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { |
| 3868 | 3903 | const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0); |
| 3869 | 3904 | gpa.free(embed_file.bytes); |
| 3870 | 3905 | 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 | }; | |
| 3874 | 3911 | |
| 3875 | 3912 | mod.comp.mutex.lock(); |
| 3876 | 3913 | defer mod.comp.mutex.unlock(); |
| ... | ... | @@ -5001,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void { |
| 5001 | 5038 | }, |
| 5002 | 5039 | }; |
| 5003 | 5040 | } |
| 5041 | ||
| 5042 | fn reportRetryableFileError( | |
| 5043 | mod: *Module, | |
| 5044 | file: *File, | |
| 5045 | comptime format: []const u8, | |
| 5046 | args: anytype, | |
| 5047 | ) error{OutOfMemory}!void { | |
| 5048 | file.status = .retryable_failure; | |
| 5049 | ||
| 5050 | const err_msg = try ErrorMsg.create( | |
| 5051 | mod.gpa, | |
| 5052 | .{ | |
| 5053 | .file_scope = file, | |
| 5054 | .parent_decl_node = 0, | |
| 5055 | .lazy = .entire_file, | |
| 5056 | }, | |
| 5057 | format, | |
| 5058 | args, | |
| 5059 | ); | |
| 5060 | errdefer err_msg.destroy(mod.gpa); | |
| 5061 | ||
| 5062 | mod.comp.mutex.lock(); | |
| 5063 | defer mod.comp.mutex.unlock(); | |
| 5064 | ||
| 5065 | const gop = try mod.failed_files.getOrPut(mod.gpa, file); | |
| 5066 | if (gop.found_existing) { | |
| 5067 | if (gop.value_ptr.*) |old_err_msg| { | |
| 5068 | old_err_msg.destroy(mod.gpa); | |
| 5069 | } | |
| 5070 | } | |
| 5071 | gop.value_ptr.* = err_msg; | |
| 5072 | } |
src/Sema.zig+12-11| ... | ... | @@ -14680,11 +14680,11 @@ fn resolvePeerTypes( |
| 14680 | 14680 | instructions: []Air.Inst.Ref, |
| 14681 | 14681 | candidate_srcs: Module.PeerTypeCandidateSrc, |
| 14682 | 14682 | ) !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 | } | |
| 14688 | 14688 | |
| 14689 | 14689 | const target = sema.mod.getTarget(); |
| 14690 | 14690 | |
| ... | ... | @@ -14714,13 +14714,14 @@ fn resolvePeerTypes( |
| 14714 | 14714 | continue; |
| 14715 | 14715 | }, |
| 14716 | 14716 | .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; | |
| 14723 | 14723 | } |
| 14724 | continue; | |
| 14724 | 14725 | }, |
| 14725 | 14726 | .Pointer => if (chosen_ty.ptrSize() == .C) continue, |
| 14726 | 14727 | else => {}, |
src/codegen/llvm.zig+6-4| ... | ... | @@ -324,10 +324,12 @@ pub const Object = struct { |
| 324 | 324 | const mod = comp.bin_file.options.module.?; |
| 325 | 325 | const cache_dir = mod.zig_cache_artifact_directory; |
| 326 | 326 | |
| 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; | |
| 331 | 333 | |
| 332 | 334 | const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir); |
| 333 | 335 | const emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir); |
src/glibc.zig+1| ... | ... | @@ -1062,6 +1062,7 @@ fn buildSharedLib( |
| 1062 | 1062 | .local_cache_directory = zig_cache_directory, |
| 1063 | 1063 | .global_cache_directory = comp.global_cache_directory, |
| 1064 | 1064 | .zig_lib_directory = comp.zig_lib_directory, |
| 1065 | .cache_mode = .whole, | |
| 1065 | 1066 | .target = comp.getTarget(), |
| 1066 | 1067 | .root_name = lib.name, |
| 1067 | 1068 | .main_pkg = null, |
src/libcxx.zig+8-8| ... | ... | @@ -177,6 +177,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 177 | 177 | .local_cache_directory = comp.global_cache_directory, |
| 178 | 178 | .global_cache_directory = comp.global_cache_directory, |
| 179 | 179 | .zig_lib_directory = comp.zig_lib_directory, |
| 180 | .cache_mode = .whole, | |
| 180 | 181 | .target = target, |
| 181 | 182 | .root_name = root_name, |
| 182 | 183 | .main_pkg = null, |
| ... | ... | @@ -218,10 +219,9 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 218 | 219 | |
| 219 | 220 | assert(comp.libcxx_static_lib == null); |
| 220 | 221 | 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 | }), | |
| 225 | 225 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 226 | 226 | }; |
| 227 | 227 | } |
| ... | ... | @@ -309,6 +309,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 309 | 309 | .local_cache_directory = comp.global_cache_directory, |
| 310 | 310 | .global_cache_directory = comp.global_cache_directory, |
| 311 | 311 | .zig_lib_directory = comp.zig_lib_directory, |
| 312 | .cache_mode = .whole, | |
| 312 | 313 | .target = target, |
| 313 | 314 | .root_name = root_name, |
| 314 | 315 | .main_pkg = null, |
| ... | ... | @@ -350,10 +351,9 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 350 | 351 | |
| 351 | 352 | assert(comp.libcxxabi_static_lib == null); |
| 352 | 353 | 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 | }), | |
| 357 | 357 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 358 | 358 | }; |
| 359 | 359 | } |
src/libtsan.zig+4-4| ... | ... | @@ -199,6 +199,7 @@ pub fn buildTsan(comp: *Compilation) !void { |
| 199 | 199 | .local_cache_directory = comp.global_cache_directory, |
| 200 | 200 | .global_cache_directory = comp.global_cache_directory, |
| 201 | 201 | .zig_lib_directory = comp.zig_lib_directory, |
| 202 | .cache_mode = .whole, | |
| 202 | 203 | .target = target, |
| 203 | 204 | .root_name = root_name, |
| 204 | 205 | .main_pkg = null, |
| ... | ... | @@ -237,10 +238,9 @@ pub fn buildTsan(comp: *Compilation) !void { |
| 237 | 238 | |
| 238 | 239 | assert(comp.tsan_static_lib == null); |
| 239 | 240 | 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 | }), | |
| 244 | 244 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 245 | 245 | }; |
| 246 | 246 | } |
src/libunwind.zig+5-4| ... | ... | @@ -101,6 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void { |
| 101 | 101 | .local_cache_directory = comp.global_cache_directory, |
| 102 | 102 | .global_cache_directory = comp.global_cache_directory, |
| 103 | 103 | .zig_lib_directory = comp.zig_lib_directory, |
| 104 | .cache_mode = .whole, | |
| 104 | 105 | .target = target, |
| 105 | 106 | .root_name = root_name, |
| 106 | 107 | .main_pkg = null, |
| ... | ... | @@ -141,11 +142,11 @@ pub fn buildStaticLib(comp: *Compilation) !void { |
| 141 | 142 | try sub_compilation.updateSubCompilation(); |
| 142 | 143 | |
| 143 | 144 | assert(comp.libunwind_static_lib == null); |
| 145 | ||
| 144 | 146 | 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 | }), | |
| 149 | 150 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 150 | 151 | }; |
| 151 | 152 | } |
src/link.zig+59-14| ... | ... | @@ -22,6 +22,8 @@ pub const SystemLib = struct { |
| 22 | 22 | needed: bool = false, |
| 23 | 23 | }; |
| 24 | 24 | |
| 25 | pub const CacheMode = enum { incremental, whole }; | |
| 26 | ||
| 25 | 27 | pub fn hashAddSystemLibs( |
| 26 | 28 | hh: *Cache.HashHelper, |
| 27 | 29 | hm: std.StringArrayHashMapUnmanaged(SystemLib), |
| ... | ... | @@ -44,10 +46,9 @@ pub const Emit = struct { |
| 44 | 46 | }; |
| 45 | 47 | |
| 46 | 48 | pub 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. | |
| 49 | 50 | emit: ?Emit, |
| 50 | /// This is `null` not building a Windows DLL, or when -fno-emit-implib is used. | |
| 51 | /// This is `null` not building a Windows DLL, or when `-fno-emit-implib` is used. | |
| 51 | 52 | implib_emit: ?Emit, |
| 52 | 53 | target: std.Target, |
| 53 | 54 | output_mode: std.builtin.OutputMode, |
| ... | ... | @@ -70,6 +71,7 @@ pub const Options = struct { |
| 70 | 71 | entry_addr: ?u64 = null, |
| 71 | 72 | stack_size_override: ?u64, |
| 72 | 73 | image_base_override: ?u64, |
| 74 | cache_mode: CacheMode, | |
| 73 | 75 | include_compiler_rt: bool, |
| 74 | 76 | /// Set to `true` to omit debug info. |
| 75 | 77 | strip: bool, |
| ... | ... | @@ -165,6 +167,12 @@ pub const Options = struct { |
| 165 | 167 | pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode { |
| 166 | 168 | return if (options.use_lld) .Obj else options.output_mode; |
| 167 | 169 | } |
| 170 | ||
| 171 | pub fn move(self: *Options) Options { | |
| 172 | const copied_state = self.*; | |
| 173 | self.system_libs = .{}; | |
| 174 | return copied_state; | |
| 175 | } | |
| 168 | 176 | }; |
| 169 | 177 | |
| 170 | 178 | pub const File = struct { |
| ... | ... | @@ -628,6 +636,36 @@ pub const File = struct { |
| 628 | 636 | } |
| 629 | 637 | } |
| 630 | 638 | |
| 639 | /// This function is called by the frontend before flush(). It communicates that | |
| 640 | /// `options.bin_file.emit` directory needs to be renamed from | |
| 641 | /// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`. | |
| 642 | /// The frontend would like to simply perform a file system rename, however, | |
| 643 | /// some linker backends care about the file paths of the objects they are linking. | |
| 644 | /// So this function call tells linker backends to rename the paths of object files | |
| 645 | /// to observe the new directory path. | |
| 646 | /// Linker backends which do not have this requirement can fall back to the simple | |
| 647 | /// implementation at the bottom of this function. | |
| 648 | /// This function is only called when CacheMode is `whole`. | |
| 649 | pub fn renameTmpIntoCache( | |
| 650 | base: *File, | |
| 651 | cache_directory: Compilation.Directory, | |
| 652 | tmp_dir_sub_path: []const u8, | |
| 653 | o_sub_path: []const u8, | |
| 654 | ) !void { | |
| 655 | // So far, none of the linker backends need to respond to this event, however, | |
| 656 | // it makes sense that they might want to. So we leave this mechanism here | |
| 657 | // for now. Once the linker backends get more mature, if it turns out this | |
| 658 | // is not needed we can refactor this into having the frontend do the rename | |
| 659 | // directly, and remove this function from link.zig. | |
| 660 | _ = base; | |
| 661 | try std.fs.rename( | |
| 662 | cache_directory.handle, | |
| 663 | tmp_dir_sub_path, | |
| 664 | cache_directory.handle, | |
| 665 | o_sub_path, | |
| 666 | ); | |
| 667 | } | |
| 668 | ||
| 631 | 669 | pub fn linkAsArchive(base: *File, comp: *Compilation) !void { |
| 632 | 670 | const tracy = trace(@src()); |
| 633 | 671 | defer tracy.end(); |
| ... | ... | @@ -637,9 +675,11 @@ pub const File = struct { |
| 637 | 675 | const arena = arena_allocator.allocator(); |
| 638 | 676 | |
| 639 | 677 | const directory = base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 678 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); | |
| 679 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); | |
| 640 | 680 | |
| 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. | |
| 643 | 683 | const module_obj_path: ?[]const u8 = if (base.options.module) |module| blk: { |
| 644 | 684 | const use_stage1 = build_options.is_stage1 and base.options.use_stage1; |
| 645 | 685 | if (use_stage1) { |
| ... | ... | @@ -648,20 +688,28 @@ pub const File = struct { |
| 648 | 688 | .target = base.options.target, |
| 649 | 689 | .output_mode = .Obj, |
| 650 | 690 | }); |
| 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 | } | |
| 654 | 700 | } |
| 655 | 701 | if (base.options.object_format == .macho) { |
| 656 | 702 | try base.cast(MachO).?.flushObject(comp); |
| 657 | 703 | } else { |
| 658 | 704 | try base.flushModule(comp); |
| 659 | 705 | } |
| 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 | }); | |
| 663 | 709 | } else null; |
| 664 | 710 | |
| 711 | log.debug("module_obj_path={s}", .{if (module_obj_path) |s| s else "(null)"}); | |
| 712 | ||
| 665 | 713 | const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt) |
| 666 | 714 | comp.compiler_rt_obj.?.full_object_path |
| 667 | 715 | else |
| ... | ... | @@ -734,9 +782,6 @@ pub const File = struct { |
| 734 | 782 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); |
| 735 | 783 | } |
| 736 | 784 | |
| 737 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); | |
| 738 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); | |
| 739 | ||
| 740 | 785 | if (base.options.verbose_link) { |
| 741 | 786 | std.debug.print("ar rcs {s}", .{full_out_path_z}); |
| 742 | 787 | for (object_files.items) |arg| { |
src/link/Coff.zig+16-7| ... | ... | @@ -880,6 +880,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 880 | 880 | const arena = arena_allocator.allocator(); |
| 881 | 881 | |
| 882 | 882 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 883 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 883 | 884 | |
| 884 | 885 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 885 | 886 | // will not be part of the linker line anyway. |
| ... | ... | @@ -891,15 +892,22 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 891 | 892 | .target = self.base.options.target, |
| 892 | 893 | .output_mode = .Obj, |
| 893 | 894 | }); |
| 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 | } | |
| 897 | 904 | } |
| 898 | 905 | |
| 899 | 906 | 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 | }); | |
| 903 | 911 | } else null; |
| 904 | 912 | |
| 905 | 913 | const is_lib = self.base.options.output_mode == .Lib; |
| ... | ... | @@ -920,6 +928,8 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 920 | 928 | man = comp.cache_parent.obtain(); |
| 921 | 929 | self.base.releaseLock(); |
| 922 | 930 | |
| 931 | comptime assert(Compilation.link_hash_implementation_version == 1); | |
| 932 | ||
| 923 | 933 | try man.addListOfFiles(self.base.options.objects); |
| 924 | 934 | for (comp.c_object_table.keys()) |key| { |
| 925 | 935 | _ = try man.addFile(key.status.success.object_path, null); |
| ... | ... | @@ -976,7 +986,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 976 | 986 | }; |
| 977 | 987 | } |
| 978 | 988 | |
| 979 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 980 | 989 | if (self.base.options.output_mode == .Obj) { |
| 981 | 990 | // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy |
| 982 | 991 | // here. TODO: think carefully about how we can avoid this redundant operation when doing |
src/link/Elf.zig+20-8| ... | ... | @@ -297,6 +297,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { |
| 297 | 297 | else => return error.UnsupportedELFArchitecture, |
| 298 | 298 | }; |
| 299 | 299 | const self = try gpa.create(Elf); |
| 300 | errdefer gpa.destroy(self); | |
| 300 | 301 | self.* = .{ |
| 301 | 302 | .base = .{ |
| 302 | 303 | .tag = .elf, |
| ... | ... | @@ -306,6 +307,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { |
| 306 | 307 | }, |
| 307 | 308 | .ptr_width = ptr_width, |
| 308 | 309 | }; |
| 310 | // TODO get rid of the sub_path parameter to LlvmObject.create | |
| 311 | // and create the llvm_object here. Also openPath needs to | |
| 312 | // not override this field or there will be a memory leak. | |
| 309 | 313 | return self; |
| 310 | 314 | } |
| 311 | 315 | |
| ... | ... | @@ -1298,6 +1302,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1298 | 1302 | const arena = arena_allocator.allocator(); |
| 1299 | 1303 | |
| 1300 | 1304 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 1305 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 1301 | 1306 | |
| 1302 | 1307 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 1303 | 1308 | // will not be part of the linker line anyway. |
| ... | ... | @@ -1309,15 +1314,22 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1309 | 1314 | .target = self.base.options.target, |
| 1310 | 1315 | .output_mode = .Obj, |
| 1311 | 1316 | }); |
| 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 | } | |
| 1315 | 1326 | } |
| 1316 | 1327 | |
| 1317 | 1328 | 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 | }); | |
| 1321 | 1333 | } else null; |
| 1322 | 1334 | |
| 1323 | 1335 | const is_obj = self.base.options.output_mode == .Obj; |
| ... | ... | @@ -1357,6 +1369,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1357 | 1369 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 1358 | 1370 | self.base.releaseLock(); |
| 1359 | 1371 | |
| 1372 | comptime assert(Compilation.link_hash_implementation_version == 1); | |
| 1373 | ||
| 1360 | 1374 | try man.addOptionalFile(self.base.options.linker_script); |
| 1361 | 1375 | try man.addOptionalFile(self.base.options.version_script); |
| 1362 | 1376 | try man.addListOfFiles(self.base.options.objects); |
| ... | ... | @@ -1432,8 +1446,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1432 | 1446 | }; |
| 1433 | 1447 | } |
| 1434 | 1448 | |
| 1435 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 1436 | ||
| 1437 | 1449 | // Due to a deficiency in LLD, we need to special-case BPF to a simple file copy when generating |
| 1438 | 1450 | // relocatables. Normally, we would expect `lld -r` to work. However, because LLD wants to resolve |
| 1439 | 1451 | // BPF relocations which it shouldn't, it fails before even generating the relocatable. |
src/link/MachO.zig+18-7| ... | ... | @@ -423,6 +423,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 423 | 423 | const arena = arena_allocator.allocator(); |
| 424 | 424 | |
| 425 | 425 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 426 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 426 | 427 | |
| 427 | 428 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 428 | 429 | // will not be part of the linker line anyway. |
| ... | ... | @@ -433,15 +434,24 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 433 | 434 | .target = self.base.options.target, |
| 434 | 435 | .output_mode = .Obj, |
| 435 | 436 | }); |
| 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 | } | |
| 439 | 446 | } |
| 440 | 447 | |
| 441 | 448 | const obj_basename = self.base.intermediary_basename orelse break :blk null; |
| 449 | ||
| 442 | 450 | 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 | }); | |
| 445 | 455 | } else null; |
| 446 | 456 | |
| 447 | 457 | const is_lib = self.base.options.output_mode == .Lib; |
| ... | ... | @@ -466,6 +476,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 466 | 476 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 467 | 477 | self.base.releaseLock(); |
| 468 | 478 | |
| 479 | comptime assert(Compilation.link_hash_implementation_version == 1); | |
| 480 | ||
| 469 | 481 | try man.addListOfFiles(self.base.options.objects); |
| 470 | 482 | for (comp.c_object_table.keys()) |key| { |
| 471 | 483 | _ = try man.addFile(key.status.success.object_path, null); |
| ... | ... | @@ -532,7 +544,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 532 | 544 | else => |e| return e, |
| 533 | 545 | }; |
| 534 | 546 | } |
| 535 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 536 | 547 | |
| 537 | 548 | if (self.base.options.output_mode == .Obj) { |
| 538 | 549 | // LLD's MachO driver does not support the equivalent of `-r` so we do a simple file copy |
| ... | ... | @@ -1267,7 +1278,7 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1267 | 1278 | for (files) |file_name| { |
| 1268 | 1279 | const full_path = full_path: { |
| 1269 | 1280 | var buffer: [fs.MAX_PATH_BYTES]u8 = undefined; |
| 1270 | const path = try std.fs.realpath(file_name, &buffer); | |
| 1281 | const path = try fs.realpath(file_name, &buffer); | |
| 1271 | 1282 | break :full_path try self.base.allocator.dupe(u8, path); |
| 1272 | 1283 | }; |
| 1273 | 1284 | defer self.base.allocator.free(full_path); |
src/link/Wasm.zig+16-8| ... | ... | @@ -1050,6 +1050,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1050 | 1050 | const arena = arena_allocator.allocator(); |
| 1051 | 1051 | |
| 1052 | 1052 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 1053 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 1053 | 1054 | |
| 1054 | 1055 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 1055 | 1056 | // will not be part of the linker line anyway. |
| ... | ... | @@ -1061,15 +1062,22 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1061 | 1062 | .target = self.base.options.target, |
| 1062 | 1063 | .output_mode = .Obj, |
| 1063 | 1064 | }); |
| 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 | } | |
| 1067 | 1074 | } |
| 1068 | 1075 | |
| 1069 | 1076 | 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 | }); | |
| 1073 | 1081 | } else null; |
| 1074 | 1082 | |
| 1075 | 1083 | const is_obj = self.base.options.output_mode == .Obj; |
| ... | ... | @@ -1094,6 +1102,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1094 | 1102 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 1095 | 1103 | self.base.releaseLock(); |
| 1096 | 1104 | |
| 1105 | comptime assert(Compilation.link_hash_implementation_version == 1); | |
| 1106 | ||
| 1097 | 1107 | try man.addListOfFiles(self.base.options.objects); |
| 1098 | 1108 | for (comp.c_object_table.keys()) |key| { |
| 1099 | 1109 | _ = try man.addFile(key.status.success.object_path, null); |
| ... | ... | @@ -1141,8 +1151,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1141 | 1151 | }; |
| 1142 | 1152 | } |
| 1143 | 1153 | |
| 1144 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); | |
| 1145 | ||
| 1146 | 1154 | if (self.base.options.output_mode == .Obj) { |
| 1147 | 1155 | // LLD's WASM driver does not support the equivalent of `-r` so we do a simple file copy |
| 1148 | 1156 | // here. TODO: think carefully about how we can avoid this redundant operation when doing |
src/main.zig+34-34| ... | ... | @@ -2564,9 +2564,7 @@ fn buildOutputType( |
| 2564 | 2564 | |
| 2565 | 2565 | switch (emit_bin) { |
| 2566 | 2566 | .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, | |
| 2570 | 2568 | .yes => |full_path| break :blk .{ .update = full_path }, |
| 2571 | 2569 | .yes_a_out => break :blk .{ .update = a_out_basename }, |
| 2572 | 2570 | } |
| ... | ... | @@ -2578,10 +2576,6 @@ fn buildOutputType( |
| 2578 | 2576 | }; |
| 2579 | 2577 | try comp.makeBinFileExecutable(); |
| 2580 | 2578 | |
| 2581 | if (build_options.is_stage1 and comp.stage1_lock != null and watch) { | |
| 2582 | warn("--watch is not recommended with the stage1 backend; it leaks memory and is not capable of incremental compilation", .{}); | |
| 2583 | } | |
| 2584 | ||
| 2585 | 2579 | if (test_exec_args.items.len == 0 and object_format == .c) default_exec_args: { |
| 2586 | 2580 | // Default to using `zig run` to execute the produced .c code from `zig test`. |
| 2587 | 2581 | const c_code_loc = emit_bin_loc orelse break :default_exec_args; |
| ... | ... | @@ -2602,7 +2596,6 @@ fn buildOutputType( |
| 2602 | 2596 | comp, |
| 2603 | 2597 | gpa, |
| 2604 | 2598 | arena, |
| 2605 | emit_bin_loc, | |
| 2606 | 2599 | test_exec_args.items, |
| 2607 | 2600 | self_exe_path, |
| 2608 | 2601 | arg_mode, |
| ... | ... | @@ -2675,7 +2668,6 @@ fn buildOutputType( |
| 2675 | 2668 | comp, |
| 2676 | 2669 | gpa, |
| 2677 | 2670 | arena, |
| 2678 | emit_bin_loc, | |
| 2679 | 2671 | test_exec_args.items, |
| 2680 | 2672 | self_exe_path, |
| 2681 | 2673 | arg_mode, |
| ... | ... | @@ -2701,7 +2693,6 @@ fn buildOutputType( |
| 2701 | 2693 | comp, |
| 2702 | 2694 | gpa, |
| 2703 | 2695 | arena, |
| 2704 | emit_bin_loc, | |
| 2705 | 2696 | test_exec_args.items, |
| 2706 | 2697 | self_exe_path, |
| 2707 | 2698 | arg_mode, |
| ... | ... | @@ -2766,7 +2757,6 @@ fn runOrTest( |
| 2766 | 2757 | comp: *Compilation, |
| 2767 | 2758 | gpa: Allocator, |
| 2768 | 2759 | arena: Allocator, |
| 2769 | emit_bin_loc: ?Compilation.EmitLoc, | |
| 2770 | 2760 | test_exec_args: []const ?[]const u8, |
| 2771 | 2761 | self_exe_path: []const u8, |
| 2772 | 2762 | arg_mode: ArgMode, |
| ... | ... | @@ -2777,10 +2767,11 @@ fn runOrTest( |
| 2777 | 2767 | runtime_args_start: ?usize, |
| 2778 | 2768 | link_libc: bool, |
| 2779 | 2769 | ) !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. | |
| 2782 | 2773 | const exe_path = try fs.path.join(arena, &[_][]const u8{ |
| 2783 | exe_directory.path orelse ".", exe_loc.basename, | |
| 2774 | exe_emit.directory.path orelse ".", exe_emit.sub_path, | |
| 2784 | 2775 | }); |
| 2785 | 2776 | |
| 2786 | 2777 | var argv = std.ArrayList([]const u8).init(gpa); |
| ... | ... | @@ -2884,7 +2875,7 @@ fn runOrTest( |
| 2884 | 2875 | |
| 2885 | 2876 | const AfterUpdateHook = union(enum) { |
| 2886 | 2877 | none, |
| 2887 | print: []const u8, | |
| 2878 | print_emit_bin_dir_path, | |
| 2888 | 2879 | update: []const u8, |
| 2889 | 2880 | }; |
| 2890 | 2881 | |
| ... | ... | @@ -2910,7 +2901,13 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void |
| 2910 | 2901 | return error.SemanticAnalyzeFail; |
| 2911 | 2902 | } else switch (hook) { |
| 2912 | 2903 | .none => {}, |
| 2913 | .print => |bin_path| try io.getStdOut().writer().print("{s}\n", .{bin_path}), | |
| 2904 | .print_emit_bin_dir_path => { | |
| 2905 | const emit = comp.bin_file.options.emit.?; | |
| 2906 | const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); | |
| 2907 | defer gpa.free(full_path); | |
| 2908 | const dir_path = fs.path.dirname(full_path).?; | |
| 2909 | try io.getStdOut().writer().print("{s}\n", .{dir_path}); | |
| 2910 | }, | |
| 2914 | 2911 | .update => |full_path| { |
| 2915 | 2912 | const bin_sub_path = comp.bin_file.options.emit.?.sub_path; |
| 2916 | 2913 | const cwd = fs.cwd(); |
| ... | ... | @@ -3473,9 +3470,10 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi |
| 3473 | 3470 | }; |
| 3474 | 3471 | try comp.makeBinFileExecutable(); |
| 3475 | 3472 | |
| 3476 | child_argv.items[argv_index_exe] = try comp.bin_file.options.emit.?.directory.join( | |
| 3473 | const emit = comp.bin_file.options.emit.?; | |
| 3474 | child_argv.items[argv_index_exe] = try emit.directory.join( | |
| 3477 | 3475 | arena, |
| 3478 | &[_][]const u8{exe_basename}, | |
| 3476 | &[_][]const u8{emit.sub_path}, | |
| 3479 | 3477 | ); |
| 3480 | 3478 | |
| 3481 | 3479 | break :argv child_argv.items; |
| ... | ... | @@ -3666,9 +3664,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void |
| 3666 | 3664 | .zir_loaded = false, |
| 3667 | 3665 | .sub_file_path = "<stdin>", |
| 3668 | 3666 | .source = source_code, |
| 3669 | .stat_size = undefined, | |
| 3670 | .stat_inode = undefined, | |
| 3671 | .stat_mtime = undefined, | |
| 3667 | .stat = undefined, | |
| 3672 | 3668 | .tree = tree, |
| 3673 | 3669 | .tree_loaded = true, |
| 3674 | 3670 | .zir = undefined, |
| ... | ... | @@ -3862,9 +3858,11 @@ fn fmtPathFile( |
| 3862 | 3858 | .zir_loaded = false, |
| 3863 | 3859 | .sub_file_path = file_path, |
| 3864 | 3860 | .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 | }, | |
| 3868 | 3866 | .tree = tree, |
| 3869 | 3867 | .tree_loaded = true, |
| 3870 | 3868 | .zir = undefined, |
| ... | ... | @@ -4460,9 +4458,7 @@ pub fn cmdAstCheck( |
| 4460 | 4458 | .zir_loaded = false, |
| 4461 | 4459 | .sub_file_path = undefined, |
| 4462 | 4460 | .source = undefined, |
| 4463 | .stat_size = undefined, | |
| 4464 | .stat_inode = undefined, | |
| 4465 | .stat_mtime = undefined, | |
| 4461 | .stat = undefined, | |
| 4466 | 4462 | .tree = undefined, |
| 4467 | 4463 | .zir = undefined, |
| 4468 | 4464 | .pkg = undefined, |
| ... | ... | @@ -4487,9 +4483,11 @@ pub fn cmdAstCheck( |
| 4487 | 4483 | file.sub_file_path = file_name; |
| 4488 | 4484 | file.source = source; |
| 4489 | 4485 | 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 | }; | |
| 4493 | 4491 | } else { |
| 4494 | 4492 | const stdin = io.getStdIn(); |
| 4495 | 4493 | const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| { |
| ... | ... | @@ -4498,7 +4496,7 @@ pub fn cmdAstCheck( |
| 4498 | 4496 | file.sub_file_path = "<stdin>"; |
| 4499 | 4497 | file.source = source; |
| 4500 | 4498 | file.source_loaded = true; |
| 4501 | file.stat_size = source.len; | |
| 4499 | file.stat.size = source.len; | |
| 4502 | 4500 | } |
| 4503 | 4501 | |
| 4504 | 4502 | file.pkg = try Package.create(gpa, null, file.sub_file_path); |
| ... | ... | @@ -4611,9 +4609,11 @@ pub fn cmdChangelist( |
| 4611 | 4609 | .zir_loaded = false, |
| 4612 | 4610 | .sub_file_path = old_source_file, |
| 4613 | 4611 | .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 | }, | |
| 4617 | 4617 | .tree = undefined, |
| 4618 | 4618 | .zir = undefined, |
| 4619 | 4619 | .pkg = undefined, |
src/musl.zig+1| ... | ... | @@ -203,6 +203,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 203 | 203 | const sub_compilation = try Compilation.create(comp.gpa, .{ |
| 204 | 204 | .local_cache_directory = comp.global_cache_directory, |
| 205 | 205 | .global_cache_directory = comp.global_cache_directory, |
| 206 | .cache_mode = .whole, | |
| 206 | 207 | .zig_lib_directory = comp.zig_lib_directory, |
| 207 | 208 | .target = target, |
| 208 | 209 | .root_name = "c", |
src/stage1.zig+4-1| ... | ... | @@ -458,7 +458,10 @@ export fn stage2_fetch_file( |
| 458 | 458 | const comp = @intToPtr(*Compilation, stage1.userdata); |
| 459 | 459 | const file_path = path_ptr[0..path_len]; |
| 460 | 460 | const max_file_size = std.math.maxInt(u32); |
| 461 | const contents = comp.stage1_cache_manifest.addFilePostFetch(file_path, max_file_size) catch return null; | |
| 461 | const contents = if (comp.whole_cache_manifest) |man| | |
| 462 | man.addFilePostFetch(file_path, max_file_size) catch return null | |
| 463 | else | |
| 464 | std.fs.cwd().readFileAlloc(comp.gpa, file_path, max_file_size) catch return null; | |
| 462 | 465 | result_len.* = contents.len; |
| 463 | 466 | // TODO https://github.com/ziglang/zig/issues/3328#issuecomment-716749475 |
| 464 | 467 | if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1); |
src/type.zig+14-3| ... | ... | @@ -3106,9 +3106,9 @@ pub const Type = extern union { |
| 3106 | 3106 | .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) }, |
| 3107 | 3107 | |
| 3108 | 3108 | .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty, |
| 3109 | .enum_numbered => ty = self.castTag(.enum_numbered).?.data.tag_ty, | |
| 3109 | .enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty, | |
| 3110 | 3110 | .enum_simple => { |
| 3111 | const enum_obj = self.castTag(.enum_simple).?.data; | |
| 3111 | const enum_obj = ty.castTag(.enum_simple).?.data; | |
| 3112 | 3112 | const field_count = enum_obj.fields.count(); |
| 3113 | 3113 | if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 }; |
| 3114 | 3114 | return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) }; |
| ... | ... | @@ -4603,7 +4603,18 @@ pub const CType = enum { |
| 4603 | 4603 | .longlong, |
| 4604 | 4604 | .ulonglong, |
| 4605 | 4605 | => return 64, |
| 4606 | .longdouble => @panic("TODO figure out what kind of float `long double` is on this target"), | |
| 4606 | .longdouble => switch (target.cpu.arch) { | |
| 4607 | .riscv64, | |
| 4608 | .aarch64, | |
| 4609 | .aarch64_be, | |
| 4610 | .aarch64_32, | |
| 4611 | .s390x, | |
| 4612 | .mips64, | |
| 4613 | .mips64el, | |
| 4614 | => return 128, | |
| 4615 | ||
| 4616 | else => return 80, | |
| 4617 | }, | |
| 4607 | 4618 | }, |
| 4608 | 4619 | |
| 4609 | 4620 | .windows, .uefi => switch (self) { |
test/behavior/cast.zig+9| ... | ... | @@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" { |
| 295 | 295 | const a: ??[*]u8 = @as(?[*]u8, null); |
| 296 | 296 | try expect(a != null and a.? == null); |
| 297 | 297 | } |
| 298 | ||
| 299 | test "peer type unsigned int to signed" { | |
| 300 | var w: u31 = 5; | |
| 301 | var x: u8 = 7; | |
| 302 | var y: i32 = -5; | |
| 303 | var a = w + y + x; | |
| 304 | comptime try expect(@TypeOf(a) == i32); | |
| 305 | try expect(a == 7); | |
| 306 | } |
test/behavior/cast_stage1.zig-9| ... | ... | @@ -383,15 +383,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" { |
| 383 | 383 | comptime try expect(@TypeOf("hi", slice) == [:0]const u8); |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | test "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 | ||
| 395 | 386 | test "peer type resolve array pointers, one of them const" { |
| 396 | 387 | var array1: [4]u8 = undefined; |
| 397 | 388 | const array2: [5]u8 = undefined; |