╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ compiler_rt.zig ──────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
276 /// x86_64-linux-gnu => true 277 /// x86_64-linux-musl => true 278 /// x86_64-linux-eabi => true 279 /// arm-linux-musleabihf => true 280 /// arm-linux-gnueabihf => true 281 /// arm-linux-eabihf => false 282 /// wasm32-wasi-musl => false 283 /// wasm32-freestanding-none => false 284 /// x86_64-windows-gnu => true 285 /// x86_64-windows-msvc => true 286 /// any-macos-any => false 287 pub const gnu_f16_abi = switch (builtin.cpu.arch) { 288 .wasm32, 289 .wasm64, 290 .riscv64, 291 .riscv64be, 292 .riscv32, 293 .riscv32be, 294 => false, 295 296 .x86, .x86_64 => true, 297 298 .arm, .armeb, .thumb, .thumbeb => switch (builtin.abi) { 299 .eabi, .eabihf => false, 300 else => true, 301 }, 302 303 else => !builtin.os.tag.isDarwin(), 304 }; 305 306 pub const want_sparc64_abi = builtin.cpu.arch == .sparc64; 307 pub const want_sparc32_abi = builtin.cpu.arch == .sparc; 308 309 /// For operations converting between `f16` and another floating point type. 310 pub fn f16Conv(comptime OtherType: type) type { 311 switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { 312 .hard => {}, 313 .soft => return softFloatAbi(f16), 314 } 315 if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) { 316 else => unreachable, 317 // Starting with LLVM 16, Darwin uses different abi for f16 318 // depending on the type of the other return/argument..??? 319 f32, f64 => return softFloatAbi(f16), 320 f80, f128 => {}, 321 }; 322 return hardFloatAbi(f16); 323 } 324 pub const @"f16" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { 325 .hard => hardFloatAbi(f16), 326 .soft => softFloatAbi(f16), 327 }; 328 pub const @"f32" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 32)) { 329 .hard => hardFloatAbi(f32), 330 .soft => softFloatAbi(f32), 331 }; 332 pub const @"f64" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 64)) { 333 .hard => hardFloatAbi(f64), 334 .soft => softFloatAbi(f64), 335 }; 336 pub const @"f80" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 80)) { 337 .hard => hardFloatAbi(f80), 338 .soft => struct { 339 pub const Abi = extern struct { mantissa: u64, exponent: u16 }; 340 const Repr = packed struct { mantissa: u64, exponent: u16 }; 341 pub inline fn toAbi(raw: f80) Abi { 342 const repr: Repr = @bitCast(raw); 343 return .{ .mantissa = repr.mantissa, .exponent = repr.exponent }; 344 } 345 pub inline fn fromAbi(abi: Abi) f80 { 346 const repr: Repr = .{ .mantissa = abi.mantissa, .exponent = abi.exponent }; 347 return @bitCast(repr); 348 } 349 pub const complex = complexAbi(f80, @This()); 350 }, 351 }; 352 pub const @"f128" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 128)) { 353 .hard => hardFloatAbi(f128), 354 .soft => struct { 355 pub const Abi = switch (builtin.cpu.arch.endian()) { 356 .big => extern struct { hi: u64, lo: u64 }, 357 .little => extern struct { lo: u64, hi: u64 }, 358 }; 359 const Repr = packed struct { lo: u64, hi: u64 }; 360 pub inline fn toAbi(raw: f128) Abi { 361 const repr: Repr = @bitCast(raw); 362 return .{ .lo = repr.lo, .hi = repr.hi }; 363 } 364 pub inline fn fromAbi(abi: Abi) f128 { 365 const repr: Repr = .{ .lo = abi.lo, .hi = abi.hi }; 366 return @bitCast(repr); 367 } 368 pub const complex = complexAbi(f128, @This()); 369 }, 370 }; 371 fn hardFloatAbi(comptime Float: type) type { 372 return struct { 373 pub const Abi = Float; 374 pub inline fn toAbi(raw: Float) Abi { 375 return raw; 376 } 377 pub inline fn fromAbi(abi: Abi) Float { 378 return abi; 379 } 380 pub const complex = complexAbi(Float, @This()); 381 }; 382 } 383 fn softFloatAbi(comptime Float: type) type { 384 return struct { 385 pub const Abi = @Int(.unsigned, @bitSizeOf(Float)); 386 pub inline fn toAbi(raw: Float) Abi { 387 return @bitCast(raw); 388 } 389 pub inline fn fromAbi(abi: Abi) Float { 390 return @bitCast(abi); 391 } 392 pub const complex = complexAbi(Float, @This()); 393 }; 394 } 395 fn complexAbi(comptime Float: type, comptime float: type) type { 396 return struct { 397 pub const Abi = extern struct { real: float.Abi, imag: float.Abi }; 398 pub inline fn toAbi(raw: Complex(Float)) Abi { 399 return .{ .real = float.toAbi(raw.real), .imag = float.toAbi(raw.imag) }; 400 } 401 pub inline fn fromAbi(abi: Abi) Complex(Float) { 402 return .{ .real = float.fromAbi(abi.real), .imag = float.fromAbi(abi.imag) }; 403 } 404 }; 405 } 406 407 pub fn Complex(comptime Float: type) type { 408 return struct { real: Float, imag: Float }; 409 } 410 411 pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { 412 switch (Z) { 413 u16 => { 414 // 16x16 --> 32 bit multiply 415 const product = @as(u32, a) * @as(u32, b); 416 hi.* = @intCast(product >> 16); 417 lo.* = @truncate(product); 418 }, 419 u32 => { 420 // 32x32 --> 64 bit multiply 421 const product = @as(u64, a) * @as(u64, b); 422 hi.* = @truncate(product >> 32); 423 lo.* = @truncate(product); 424 }, 425 u64 => { 426 const S = struct { 427 fn loWord(x: u64) u64 { 428 return @as(u32, @truncate(x)); 429 } 430 fn hiWord(x: u64) u64 { 431 return @as(u32, @truncate(x >> 32)); 432 } 433 }; 434 // 64x64 -> 128 wide multiply for platforms that don't have such an operation; 435 // many 64-bit platforms have this operation, but they tend to have hardware 436 // floating-point, so we don't bother with a special case for them here. 437 // Each of the component 32x32 -> 64 products 438 const plolo: u64 = S.loWord(a) * S.loWord(b); 439 const plohi: u64 = S.loWord(a) * S.hiWord(b); 440 const philo: u64 = S.hiWord(a) * S.loWord(b); 441 const phihi: u64 = S.hiWord(a) * S.hiWord(b); 442 // Sum terms that contribute to lo in a way that allows us to get the carry 443 const r0: u64 = S.loWord(plolo); 444 const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo); 445 lo.* = r0 +% (r1 << 32); 446 // Sum terms contributing to hi with the carry from lo 447 hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi; 448 }, 449 u128 => { 450 const Word_LoMask: u64 = 0x00000000ffffffff; 451 const Word_HiMask: u64 = 0xffffffff00000000; 452 const Word_FullMask: u64 = 0xffffffffffffffff; 453 const S = struct { 454 fn Word_1(x: u128) u64 { 455 return @as(u32, @truncate(x >> 96)); 456 } 457 fn Word_2(x: u128) u64 { 458 return @as(u32, @truncate(x >> 64)); 459 } 460 fn Word_3(x: u128) u64 { 461 return @as(u32, @truncate(x >> 32)); 462 } 463 fn Word_4(x: u128) u64 { 464 return @as(u32, @truncate(x)); 465 } 466 }; 467 // 128x128 -> 256 wide multiply for platforms that don't have such an operation; 468 // many 64-bit platforms have this operation, but they tend to have hardware 469 // floating-point, so we don't bother with a special case for them here. 470 471 const product11: u64 = S.Word_1(a) * S.Word_1(b); 472 const product12: u64 = S.Word_1(a) * S.Word_2(b); 473 const product13: u64 = S.Word_1(a) * S.Word_3(b); 474 const product14: u64 = S.Word_1(a) * S.Word_4(b); 475 const product21: u64 = S.Word_2(a) * S.Word_1(b); 476 const product22: u64 = S.Word_2(a) * S.Word_2(b); 477 const product23: u64 = S.Word_2(a) * S.Word_3(b); 478 const product24: u64 = S.Word_2(a) * S.Word_4(b); 479 const product31: u64 = S.Word_3(a) * S.Word_1(b); 480 const product32: u64 = S.Word_3(a) * S.Word_2(b); 481 const product33: u64 = S.Word_3(a) * S.Word_3(b); 482 const product34: u64 = S.Word_3(a) * S.Word_4(b); 483 const product41: u64 = S.Word_4(a) * S.Word_1(b); 484 const product42: u64 = S.Word_4(a) * S.Word_2(b); 485 const product43: u64 = S.Word_4(a) * S.Word_3(b); 486 const product44: u64 = S.Word_4(a) * S.Word_4(b); 487 488 const sum0: u128 = @as(u128, product44); 489 const sum1: u128 = @as(u128, product34) +% 490 @as(u128, product43); 491 const sum2: u128 = @as(u128, product24) +% 492 @as(u128, product33) +% 493 @as(u128, product42); 494 const sum3: u128 = @as(u128, product14) +% 495 @as(u128, product23) +% 496 @as(u128, product32) +% 497 @as(u128, product41); 498 const sum4: u128 = @as(u128, product13) +% 499 @as(u128, product22) +% 500 @as(u128, product31); 501 const sum5: u128 = @as(u128, product12) +% 502 @as(u128, product21); 503 const sum6: u128 = @as(u128, product11); 504 505 const r0: u128 = (sum0 & Word_FullMask) +% 506 ((sum1 & Word_LoMask) << 32); 507 const r1: u128 = (sum0 >> 64) +% 508 ((sum1 >> 32) & Word_FullMask) +% 509 (sum2 & Word_FullMask) +% 510 ((sum3 << 32) & Word_HiMask); 511 512 lo.* = r0 +% (r1 << 64); 513 hi.* = (r1 >> 64) +% 514 (sum1 >> 96) +% 515 (sum2 >> 64) +% 516 (sum3 >> 32) +% 517 sum4 +% 518 (sum5 << 32) +% 519 (sum6 << 64); 520 }, 521 else => @compileError("unsupported"), 522 } 523 } 524 525 pub fn normalize(comptime T: type, significand: *@Int(.unsigned, @typeInfo(T).float.bits)) i32 { 526 const Z = @Int(.unsigned, @typeInfo(T).float.bits); 527 const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T); 528 529 const shift = @clz(significand.*) - @clz(integerBit); 530 significand.* <<= @as(std.math.Log2Int(Z), @intCast(shift)); 531 return @as(i32, 1) - shift; 532 } 533 534 pub inline fn fneg(a: anytype) @TypeOf(a) { 535 const F = @TypeOf(a); 536 const bits = @typeInfo(F).float.bits; 537 const U = @Int(.unsigned, bits); 538 const sign_bit_mask = @as(U, 1) << (bits - 1); 539 const negated = @as(U, @bitCast(a)) ^ sign_bit_mask; 540 return @bitCast(negated); 541 } 542 543 fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { 544 return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a))); 545 } 546 547 fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { 548 return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a))); 549 } 550 551 fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { 552 return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a))); 553 } 554 555 fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { 556 return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a))); 557 } 558 559 fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { 560 return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a))); 561 } 562 563 fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 { 564 return fneg(a); 565 } 566 567 fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { 568 return fneg(a); 569 } 570 571 /// Allows to access underlying bits as two equally sized lower and higher 572 /// signed or unsigned integers. 573 pub fn HalveInt(comptime T: type, comptime signed_half: bool) type { 574 return extern union { 575 pub const bits = @divExact(@typeInfo(T).int.bits, 2); 576 pub const HalfTU = @Int(.unsigned, bits); 577 pub const HalfTS = @Int(.signed, bits); 578 pub const HalfT = if (signed_half) HalfTS else HalfTU; 579 580 all: T, 581 s: if (native_endian == .little) 582 extern struct { low: HalfT, high: HalfT } 583 else 584 extern struct { high: HalfT, low: HalfT }, 585 }; 586 } 587 588 pub fn __negsi2(a: i32) callconv(.c) i32 { 589 return negXi2(i32, a); 590 } 591 592 pub fn __negdi2(a: i64) callconv(.c) i64 { 593 return negXi2(i64, a); 594 } 595 596 pub fn __negti2(a: i128) callconv(.c) i128 { 597 return negXi2(i128, a); 598 } 599 600 inline fn negXi2(comptime T: type, a: T) T { 601 return -a; 602 } 603 604 fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void { 605 @disableIntrinsics(); 606 607 if (size > @sizeOf(usize)) { 608 d[0..size].* = @splat(b); 609 } else { 610 const T = @Int(.unsigned, 8 * size); 611 var splatted: T = 0; // Setting this to undefined causes a memset call and thus infinite recursion in Debug test-compiler-rt. 612 @as(*[size]u8, @ptrCast(&splatted)).* = @splat(b); 613 @as(*align(1) T, @ptrCast(d)).* = splatted; 614 } 615 } 616 617 fn shortMemset( 618 log_min: comptime_int, 619 log_max: comptime_int, 620 d: [*]u8, 621 b: u8, 622 len: usize, 623 ) void { 624 @disableIntrinsics(); 625 626 if (log_min + 1 != log_max) { 627 const mid = (log_min + log_max) / 2; 628 if (len > 1 << mid) { 629 shortMemset(mid, log_max, d, b, len); 630 } else { 631 shortMemset(log_min, mid, d, b, len); 632 } 633 } else { 634 const size = 1 << log_min; 635 636 memsetSmallPowerOf2(d, b, size); 637 memsetSmallPowerOf2(d + len - size, b, size); 638 } 639 } 640 641 fn fastMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { 642 @disableIntrinsics(); 643 644 const b: u8 = @truncate(@as(c_uint, @bitCast(c))); 645 const n = std.simd.suggestVectorLength(u8) orelse @sizeOf(usize); 646 647 const d = dest.?; 648 649 if (len > 2 * n) { 650 memsetSmallPowerOf2(d, b, n); 651 652 const begin_aligned = std.mem.alignBackward(usize, @intFromPtr(d) + n, n); 653 const end_aligned = std.mem.alignForward(usize, @intFromPtr(d) + len - n, n); 654 655 const aligned_ptr: [*]align(n) u8 = @ptrFromInt(begin_aligned); 656 657 var i: usize = 0; 658 while (true) { 659 memsetSmallPowerOf2(aligned_ptr + n * i, b, n); 660 661 i += 1; 662 if (i == @divExact(end_aligned - begin_aligned, n)) 663 break; 664 } 665 666 memsetSmallPowerOf2(d + len - n, b, n); 667 } else { 668 if (len == 0) return dest; 669 670 shortMemset(0, @ctz(@as(usize, 2 * n)), d, b, len); 671 } 672 673 return dest; 674 } 675 676 fn smallMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { 677 @disableIntrinsics(); 678 679 const b: u8 = @truncate(@as(c_uint, @bitCast(c))); 680 681 if (len != 0) { 682 var d = dest.?; 683 var n = len; 684 while (true) { 685 d[0] = b; 686 n -= 1; 687 if (n == 0) break; 688 d += 1; 689 } 690 } 691 692 return dest; 693 } 694 695 pub const memset = if (builtin.optimize == .small) 696 smallMemset 697 else 698 fastMemset; 699 700 pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int { 701 @setRuntimeSafety(false); 702 703 var index: usize = 0; 704 while (index != n) : (index += 1) { 705 if (vl[index] != vr[index]) { 706 return 1; 707 } 708 } 709 710 return 0; 711 } 712 713 test "bcmp" { 714 const base_arr = &[_]u8{ 1, 1, 1 }; 715 const arr1 = &[_]u8{ 1, 1, 1 }; 716 const arr2 = &[_]u8{ 1, 0, 1 }; 717 const arr3 = &[_]u8{ 1, 2, 1 }; 718 719 try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0); 720 try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0); 721 try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0); 722 } 723 724 test { 725 _ = @import("compiler_rt/negsi2_test.zig"); 726 _ = @import("compiler_rt/negdi2_test.zig"); 727 _ = @import("compiler_rt/negti2_test.zig"); 728 } 729