From 7b3bd56ed99d5031f57b1aaf814117b2a7ce9c84 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:41:48 +0000 Subject: [PATCH] Merge commit 'dec0daa8f6d0a0e1c702f169abb6bf3eee198c67' into sync_cg_clif-2023-03-15 --- .github/workflows/abi-cafe.yml | 64 +++ .github/workflows/main.yml | 59 +-- .gitignore | 1 + Cargo.lock | 49 +-- Cargo.toml | 14 +- build_sysroot/Cargo.lock | 15 +- build_sysroot/Cargo.toml | 2 +- build_system/build_sysroot.rs | 5 +- build_system/prepare.rs | 29 +- build_system/tests.rs | 51 +-- example/mini_core.rs | 11 + example/mini_core_hello_world.rs | 381 ++++++++++++++---- example/std_example.rs | 5 +- ...003-rand-Disable-rand-tests-on-mingw.patch | 4 +- ...retests-Disable-not-compiling-tests.patch} | 15 +- ...0023-coretests-Ignore-failing-tests.patch} | 12 +- ...7-coretests-128bit-atomic-operations.patch | 30 ++ ...027-stdlib-128bit-atomic-operations.patch} | 15 - ...oretests-Disable-long-running-tests.patch} | 6 +- rust-toolchain | 2 +- scripts/cargo-clif.rs | 7 +- scripts/rustc-clif.rs | 7 +- scripts/rustdoc-clif.rs | 7 +- scripts/rustup.sh | 37 +- scripts/setup_rust_fork.sh | 4 +- scripts/test_rustc_tests.sh | 7 +- src/abi/mod.rs | 98 +++-- src/abi/returning.rs | 3 +- src/analyze.rs | 30 +- src/base.rs | 18 +- src/cast.rs | 50 ++- src/codegen_i128.rs | 85 ++-- src/common.rs | 2 +- src/compiler_builtins.rs | 1 + src/concurrency_limiter.rs | 2 +- src/constant.rs | 4 +- src/cranelift_native.rs | 248 ------------ src/debuginfo/emit.rs | 2 +- src/driver/aot.rs | 4 +- src/driver/jit.rs | 6 +- src/global_asm.rs | 2 +- src/inline_asm.rs | 6 +- src/intrinsics/mod.rs | 155 +++---- src/intrinsics/simd.rs | 9 +- src/lib.rs | 15 +- src/main_shim.rs | 2 +- src/num.rs | 16 +- src/pointer.rs | 5 - src/pretty_clif.rs | 2 +- src/unsize.rs | 6 +- src/value_and_place.rs | 34 +- src/vtable.rs | 21 +- 52 files changed, 873 insertions(+), 792 deletions(-) create mode 100644 .github/workflows/abi-cafe.yml rename patches/{0022-sysroot-Disable-not-compiling-tests.patch => 0022-coretests-Disable-not-compiling-tests.patch} (76%) rename patches/{0023-sysroot-Ignore-failing-tests.patch => 0023-coretests-Ignore-failing-tests.patch} (85%) create mode 100644 patches/0027-coretests-128bit-atomic-operations.patch rename patches/{0027-sysroot-128bit-atomic-operations.patch => 0027-stdlib-128bit-atomic-operations.patch} (83%) rename patches/{0028-sysroot-Disable-long-running-tests.patch => 0028-coretests-Disable-long-running-tests.patch} (89%) delete mode 100644 src/cranelift_native.rs diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml new file mode 100644 index 0000000000000..5f5510a579654 --- /dev/null +++ b/.github/workflows/abi-cafe.yml @@ -0,0 +1,64 @@ +name: Abi-cafe + +on: + - push + +jobs: + abi_cafe: + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.os }}-${{ matrix.env.TARGET_TRIPLE }} + cancel-in-progress: true + + defaults: + run: + shell: bash + + strategy: + fail-fast: true + matrix: + include: + - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: macos-latest + env: + TARGET_TRIPLE: x86_64-apple-darwin + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-msvc + - os: windows-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu + + steps: + - uses: actions/checkout@v3 + + - name: Cache cargo target dir + uses: actions/cache@v3 + with: + path: build/cg_clif + key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + + - name: Set MinGW as the default toolchain + if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: rustup set default-host x86_64-pc-windows-gnu + + - name: Use sparse cargo registry + run: | + cat >> ~/.cargo/config.toml <> ~/.cargo/config.toml <>() - .join("\r\n"); let output_matches = expected.lines().eq(output.lines()); if !output_matches { @@ -192,27 +184,14 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.regex", &|runner| { REGEX.clean(&runner.dirs); - // newer aho_corasick versions throw a deprecation warning - let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags); - if runner.is_native { let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs); - run_cmd.args([ - "--tests", - "--", - "--exclude-should-panic", - "--test-threads", - "1", - "-Zunstable-options", - "-q", - ]); - run_cmd.env("RUSTFLAGS", lint_rust_flags); + run_cmd.args(["--workspace", "--", "-q"]); spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs); build_cmd.arg("--tests"); - build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); } }), diff --git a/example/mini_core.rs b/example/mini_core.rs index 1f9db1eb2a97a..73b83b89f6d91 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -518,6 +518,17 @@ pub struct Box(Unique, ()); impl, U: ?Sized> CoerceUnsized> for Box {} +impl Box { + pub fn new(val: T) -> Box { + unsafe { + let size = intrinsics::size_of::(); + let ptr = libc::malloc(size); + intrinsics::copy(&val as *const T as *const u8, ptr, size); + Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, ()) + } + } +} + impl Drop for Box { fn drop(&mut self) { // drop is currently performed by compiler. diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 04e7795bbfa16..6ad3268e70dd2 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,16 +1,16 @@ -#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local)] +#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, repr_simd)] #![no_core] #![allow(dead_code, non_camel_case_types)] extern crate mini_core; -use mini_core::*; use mini_core::libc::*; +use mini_core::*; macro_rules! assert { ($e:expr) => { if !$e { - panic(stringify!(! $e)); + panic(stringify!(!$e)); } }; } @@ -20,7 +20,7 @@ macro_rules! assert_eq { if $l != $r { panic(stringify!($l != $r)); } - } + }; } #[lang = "termination"] @@ -96,9 +96,15 @@ fn start( _sigpipe: u8, ) -> isize { if argc == 3 { - unsafe { puts(*argv as *const i8); } - unsafe { puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const i8)); } - unsafe { puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const i8)); } + unsafe { + puts(*argv as *const i8); + } + unsafe { + puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const i8)); + } + unsafe { + puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const i8)); + } } main().report() as isize @@ -107,7 +113,6 @@ fn start( static mut NUM: u8 = 6 * 7; static NUM_REF: &'static u8 = unsafe { &NUM }; - unsafe fn zeroed() -> T { let mut uninit = MaybeUninit { uninit: () }; intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1); @@ -144,10 +149,7 @@ extern "C" fn bool_struct_in_11(_arg0: bool_11) {} #[allow(unreachable_code)] // FIXME false positive fn main() { - take_unique(Unique { - pointer: unsafe { NonNull(1 as *mut ()) }, - _marker: PhantomData, - }); + take_unique(Unique { pointer: unsafe { NonNull(1 as *mut ()) }, _marker: PhantomData }); take_f32(0.1); call_return_u128_pair(); @@ -202,17 +204,17 @@ fn main() { assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4); assert_eq!(intrinsics::min_align_of::() as u8, 2); - assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8); + assert_eq!( + intrinsics::min_align_of_val(&a) as u8, + intrinsics::min_align_of::<&str>() as u8 + ); assert!(!intrinsics::needs_drop::()); assert!(!intrinsics::needs_drop::<[u8]>()); assert!(intrinsics::needs_drop::()); assert!(intrinsics::needs_drop::()); - Unique { - pointer: NonNull(1 as *mut &str), - _marker: PhantomData, - } as Unique; + Unique { pointer: NonNull(1 as *mut &str), _marker: PhantomData } as Unique; struct MyDst(T); @@ -238,19 +240,17 @@ fn main() { } } - let _ = Box::new(NoisyDrop { - text: "Boxed outer got dropped!\0", - inner: NoisyDropInner, - }) as Box; + let _ = Box::new(NoisyDrop { text: "Boxed outer got dropped!\0", inner: NoisyDropInner }) + as Box; const FUNC_REF: Option = Some(main); match FUNC_REF { - Some(_) => {}, + Some(_) => {} None => assert!(false), } match Ordering::Less { - Ordering::Less => {}, + Ordering::Less => {} _ => assert!(false), } @@ -266,19 +266,21 @@ fn main() { #[cfg(not(any(jit, windows)))] { - extern { + extern "C" { #[linkage = "extern_weak"] static ABC: *const u8; } { - extern { + extern "C" { #[linkage = "extern_weak"] static ABC: *const u8; } } - unsafe { assert_eq!(ABC as usize, 0); } + unsafe { + assert_eq!(ABC as usize, 0); + } } &mut (|| Some(0 as *const ())) as &mut dyn FnMut() -> Option<*const ()>; @@ -339,7 +341,13 @@ fn main() { assert_eq!(unsafe { intrinsics::size_of_val(x) }, 0); assert_eq!(unsafe { intrinsics::min_align_of_val(x) }, 1); -} + } + + #[repr(simd)] + struct V([f64; 2]); + + let f = V([0.0, 1.0]); + let _a = f.0[0]; } #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] @@ -392,13 +400,10 @@ extern "C" { native: *mut pthread_t, attr: *const pthread_attr_t, f: extern "C" fn(_: *mut c_void) -> *mut c_void, - value: *mut c_void + value: *mut c_void, ) -> c_int; - fn pthread_join( - native: pthread_t, - value: *mut *mut c_void - ) -> c_int; + fn pthread_join(native: pthread_t, value: *mut *mut c_void) -> c_int; } type DWORD = u32; @@ -410,10 +415,7 @@ type HANDLE = *mut c_void; #[link(name = "msvcrt")] #[cfg(windows)] extern "C" { - fn WaitForSingleObject( - hHandle: LPVOID, - dwMilliseconds: DWORD - ) -> DWORD; + fn WaitForSingleObject(hHandle: LPVOID, dwMilliseconds: DWORD) -> DWORD; fn CreateThread( lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway @@ -421,7 +423,7 @@ extern "C" { lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void, lpParameter: LPVOID, dwCreationFlags: DWORD, - lpThreadId: LPDWORD + lpThreadId: LPDWORD, ) -> HANDLE; } @@ -447,9 +449,7 @@ impl Thread { assert!(false); } - Thread { - handle: thread, - } + Thread { handle: thread } } #[cfg(windows)] @@ -460,13 +460,10 @@ impl Thread { assert!(false); } - Thread { - handle, - } + Thread { handle } } } - unsafe fn join(self) { #[cfg(unix)] { @@ -483,16 +480,15 @@ impl Thread { } } - - - #[thread_local] #[cfg(not(jit))] static mut TLS: u8 = 42; #[cfg(not(jit))] extern "C" fn mutate_tls(_: *mut c_void) -> *mut c_void { - unsafe { TLS = 0; } + unsafe { + TLS = 0; + } 0 as *mut c_void } @@ -531,44 +527,267 @@ pub enum E1 { pub enum E2 { V1 { f: bool }, - /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), - _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), - _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), - _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), - _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), - _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), - _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), - _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), - _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), - _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), - _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), - _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), - _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), - _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), - _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), - _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), - _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), - _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), - _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), - _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), - _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), - _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), - _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), - _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), - _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), - _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), - _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), - _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), - _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), - _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), - _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), - _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), + /*_00*/ _01(X), + _02(X), + _03(X), + _04(X), + _05(X), + _06(X), + _07(X), + _08(X), + _09(X), + _0A(X), + _0B(X), + _0C(X), + _0D(X), + _0E(X), + _0F(X), + _10(X), + _11(X), + _12(X), + _13(X), + _14(X), + _15(X), + _16(X), + _17(X), + _18(X), + _19(X), + _1A(X), + _1B(X), + _1C(X), + _1D(X), + _1E(X), + _1F(X), + _20(X), + _21(X), + _22(X), + _23(X), + _24(X), + _25(X), + _26(X), + _27(X), + _28(X), + _29(X), + _2A(X), + _2B(X), + _2C(X), + _2D(X), + _2E(X), + _2F(X), + _30(X), + _31(X), + _32(X), + _33(X), + _34(X), + _35(X), + _36(X), + _37(X), + _38(X), + _39(X), + _3A(X), + _3B(X), + _3C(X), + _3D(X), + _3E(X), + _3F(X), + _40(X), + _41(X), + _42(X), + _43(X), + _44(X), + _45(X), + _46(X), + _47(X), + _48(X), + _49(X), + _4A(X), + _4B(X), + _4C(X), + _4D(X), + _4E(X), + _4F(X), + _50(X), + _51(X), + _52(X), + _53(X), + _54(X), + _55(X), + _56(X), + _57(X), + _58(X), + _59(X), + _5A(X), + _5B(X), + _5C(X), + _5D(X), + _5E(X), + _5F(X), + _60(X), + _61(X), + _62(X), + _63(X), + _64(X), + _65(X), + _66(X), + _67(X), + _68(X), + _69(X), + _6A(X), + _6B(X), + _6C(X), + _6D(X), + _6E(X), + _6F(X), + _70(X), + _71(X), + _72(X), + _73(X), + _74(X), + _75(X), + _76(X), + _77(X), + _78(X), + _79(X), + _7A(X), + _7B(X), + _7C(X), + _7D(X), + _7E(X), + _7F(X), + _80(X), + _81(X), + _82(X), + _83(X), + _84(X), + _85(X), + _86(X), + _87(X), + _88(X), + _89(X), + _8A(X), + _8B(X), + _8C(X), + _8D(X), + _8E(X), + _8F(X), + _90(X), + _91(X), + _92(X), + _93(X), + _94(X), + _95(X), + _96(X), + _97(X), + _98(X), + _99(X), + _9A(X), + _9B(X), + _9C(X), + _9D(X), + _9E(X), + _9F(X), + _A0(X), + _A1(X), + _A2(X), + _A3(X), + _A4(X), + _A5(X), + _A6(X), + _A7(X), + _A8(X), + _A9(X), + _AA(X), + _AB(X), + _AC(X), + _AD(X), + _AE(X), + _AF(X), + _B0(X), + _B1(X), + _B2(X), + _B3(X), + _B4(X), + _B5(X), + _B6(X), + _B7(X), + _B8(X), + _B9(X), + _BA(X), + _BB(X), + _BC(X), + _BD(X), + _BE(X), + _BF(X), + _C0(X), + _C1(X), + _C2(X), + _C3(X), + _C4(X), + _C5(X), + _C6(X), + _C7(X), + _C8(X), + _C9(X), + _CA(X), + _CB(X), + _CC(X), + _CD(X), + _CE(X), + _CF(X), + _D0(X), + _D1(X), + _D2(X), + _D3(X), + _D4(X), + _D5(X), + _D6(X), + _D7(X), + _D8(X), + _D9(X), + _DA(X), + _DB(X), + _DC(X), + _DD(X), + _DE(X), + _DF(X), + _E0(X), + _E1(X), + _E2(X), + _E3(X), + _E4(X), + _E5(X), + _E6(X), + _E7(X), + _E8(X), + _E9(X), + _EA(X), + _EB(X), + _EC(X), + _ED(X), + _EE(X), + _EF(X), + _F0(X), + _F1(X), + _F2(X), + _F3(X), + _F4(X), + _F5(X), + _F6(X), + _F7(X), + _F8(X), + _F9(X), + _FA(X), + _FB(X), + _FC(X), + _FD(X), + _FE(X), + _FF(X), V3, V4, } -fn check_niche_behavior () { +fn check_niche_behavior() { if let E1::V2 { .. } = (E1::V1 { f: true }) { intrinsics::abort(); } diff --git a/example/std_example.rs b/example/std_example.rs index 8481d9c39a3cf..e34b35d5c4a8c 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -58,8 +58,9 @@ fn main() { assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128); - let _d = 0i128.checked_div(2i128); - let _d = 0u128.checked_div(2u128); + std::hint::black_box(std::hint::black_box(7571400400375753350092698930310845914i128) * 10); + assert!(0i128.checked_div(2i128).is_some()); + assert!(0u128.checked_div(2u128).is_some()); assert_eq!(1u128 + 2, 3); assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128); diff --git a/patches/0003-rand-Disable-rand-tests-on-mingw.patch b/patches/0003-rand-Disable-rand-tests-on-mingw.patch index d8775e2d022a0..eb452c5cd3772 100644 --- a/patches/0003-rand-Disable-rand-tests-on-mingw.patch +++ b/patches/0003-rand-Disable-rand-tests-on-mingw.patch @@ -19,8 +19,8 @@ index 217899e..9cedeb7 100644 + // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation + #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] fn value_stability() { - fn test_samples>( - distr: D, zero: F, expected: &[F], + fn test_samples>( + distr: D, thresh: F, expected: &[F], diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs index 192ba74..0101ace 100644 --- a/rand_distr/tests/value_stability.rs diff --git a/patches/0022-sysroot-Disable-not-compiling-tests.patch b/patches/0022-coretests-Disable-not-compiling-tests.patch similarity index 76% rename from patches/0022-sysroot-Disable-not-compiling-tests.patch rename to patches/0022-coretests-Disable-not-compiling-tests.patch index 865aa833a5eef..6afa5c71fe51f 100644 --- a/patches/0022-sysroot-Disable-not-compiling-tests.patch +++ b/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -13,14 +13,14 @@ Subject: [PATCH] [core] Disable not compiling tests 6 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 library/core/tests/Cargo.toml -diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml +diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..46fd999 --- /dev/null -+++ b/library/core/tests/Cargo.toml ++++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] -+name = "core" ++name = "coretests" +version = "0.0.0" +edition = "2021" + @@ -31,5 +31,14 @@ index 0000000..46fd999 +[dependencies] +rand = { version = "0.8.5", default-features = false } +rand_xorshift = { version = "0.3.0", default-features = false } +diff --git a/lib.rs b/lib.rs +index 42a26ae..5ac1042 100644 +--- a/lib.rs ++++ b/lib.rs +@@ -1,3 +1,4 @@ ++#![cfg(test)] + #![feature(alloc_layout_extra)] + #![feature(array_chunks)] + #![feature(array_methods)] -- 2.21.0 (Apple Git-122) diff --git a/patches/0023-sysroot-Ignore-failing-tests.patch b/patches/0023-coretests-Ignore-failing-tests.patch similarity index 85% rename from patches/0023-sysroot-Ignore-failing-tests.patch rename to patches/0023-coretests-Ignore-failing-tests.patch index f3cd7ee77e26e..f2cb82751f082 100644 --- a/patches/0023-sysroot-Ignore-failing-tests.patch +++ b/patches/0023-coretests-Ignore-failing-tests.patch @@ -10,10 +10,10 @@ Subject: [PATCH] [core] Ignore failing tests library/core/tests/time.rs | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) -diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs +diff --git a/array.rs b/array.rs index 4bc44e9..8e3c7a4 100644 ---- a/library/core/tests/array.rs -+++ b/library/core/tests/array.rs +--- a/array.rs ++++ b/array.rs @@ -242,6 +242,7 @@ fn iterator_drops() { assert_eq!(i.get(), 5); } @@ -46,10 +46,10 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { -diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs +diff --git a/atomic.rs b/atomic.rs index 13b12db..96fe4b9 100644 ---- a/library/core/tests/atomic.rs -+++ b/library/core/tests/atomic.rs +--- a/atomic.rs ++++ b/atomic.rs @@ -185,6 +185,7 @@ fn ptr_bitops() { } diff --git a/patches/0027-coretests-128bit-atomic-operations.patch b/patches/0027-coretests-128bit-atomic-operations.patch new file mode 100644 index 0000000000000..1d5479beddee9 --- /dev/null +++ b/patches/0027-coretests-128bit-atomic-operations.patch @@ -0,0 +1,30 @@ +From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Thu, 18 Feb 2021 18:45:28 +0100 +Subject: [PATCH] Disable 128bit atomic operations + +Cranelift doesn't support them yet +--- + library/core/src/panic/unwind_safe.rs | 6 ----- + library/core/src/sync/atomic.rs | 38 --------------------------- + library/core/tests/atomic.rs | 4 --- + 4 files changed, 4 insertions(+), 50 deletions(-) + +diff --git a/atomic.rs b/atomic.rs +index b735957..ea728b6 100644 +--- a/atomic.rs ++++ b/atomic.rs +@@ -185,10 +185,6 @@ fn atomic_alignment() { + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "64")] + assert_eq!(align_of::(), size_of::()); +- #[cfg(target_has_atomic = "128")] +- assert_eq!(align_of::(), size_of::()); +- #[cfg(target_has_atomic = "128")] +- assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "ptr")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "ptr")] +-- +2.26.2.7.g19db9cfb68 + diff --git a/patches/0027-sysroot-128bit-atomic-operations.patch b/patches/0027-stdlib-128bit-atomic-operations.patch similarity index 83% rename from patches/0027-sysroot-128bit-atomic-operations.patch rename to patches/0027-stdlib-128bit-atomic-operations.patch index 77f437974c2d6..45f73f36b9317 100644 --- a/patches/0027-sysroot-128bit-atomic-operations.patch +++ b/patches/0027-stdlib-128bit-atomic-operations.patch @@ -85,21 +85,6 @@ index d9de37e..8293fce 100644 macro_rules! atomic_int_ptr_sized { ( $($target_pointer_width:literal $align:literal)* ) => { $( -diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs -index b735957..ea728b6 100644 ---- a/library/core/tests/atomic.rs -+++ b/library/core/tests/atomic.rs -@@ -185,10 +185,6 @@ fn atomic_alignment() { - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "64")] - assert_eq!(align_of::(), size_of::()); -- #[cfg(target_has_atomic = "128")] -- assert_eq!(align_of::(), size_of::()); -- #[cfg(target_has_atomic = "128")] -- assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "ptr")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "ptr")] -- 2.26.2.7.g19db9cfb68 diff --git a/patches/0028-sysroot-Disable-long-running-tests.patch b/patches/0028-coretests-Disable-long-running-tests.patch similarity index 89% rename from patches/0028-sysroot-Disable-long-running-tests.patch rename to patches/0028-coretests-Disable-long-running-tests.patch index d804a78cc1061..440177018f428 100644 --- a/patches/0028-sysroot-Disable-long-running-tests.patch +++ b/patches/0028-coretests-Disable-long-running-tests.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Disable long running tests library/core/tests/slice.rs | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +diff --git a/slice.rs b/slice.rs index 8402833..84592e0 100644 ---- a/library/core/tests/slice.rs -+++ b/library/core/tests/slice.rs +--- a/slice.rs ++++ b/slice.rs @@ -1809,6 +1809,7 @@ fn sort_unstable() { assert!(v == [0xDEADBEEF]); } diff --git a/rust-toolchain b/rust-toolchain index 40fb54b915992..2236a6ca15521 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-02-06" +channel = "nightly-2023-03-15" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index c993430b830b6..939a1f1ca5900 100644 --- a/scripts/cargo-clif.rs +++ b/scripts/cargo-clif.rs @@ -1,11 +1,14 @@ use std::env; #[cfg(unix)] use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; fn main() { - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + let current_exe = env::current_exe().unwrap(); + let mut sysroot = current_exe.parent().unwrap(); + if sysroot.file_name().unwrap().to_str().unwrap() == "bin" { + sysroot = sysroot.parent().unwrap(); + } let mut rustflags = String::new(); rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend="); diff --git a/scripts/rustc-clif.rs b/scripts/rustc-clif.rs index c187f54a60e77..b9bba7f2e084c 100644 --- a/scripts/rustc-clif.rs +++ b/scripts/rustc-clif.rs @@ -2,11 +2,14 @@ use std::env; use std::ffi::OsString; #[cfg(unix)] use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; fn main() { - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + let current_exe = env::current_exe().unwrap(); + let mut sysroot = current_exe.parent().unwrap(); + if sysroot.file_name().unwrap().to_str().unwrap() == "bin" { + sysroot = sysroot.parent().unwrap(); + } let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join( env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, diff --git a/scripts/rustdoc-clif.rs b/scripts/rustdoc-clif.rs index a6528ac41aee0..167631eaf7ee4 100644 --- a/scripts/rustdoc-clif.rs +++ b/scripts/rustdoc-clif.rs @@ -2,11 +2,14 @@ use std::env; use std::ffi::OsString; #[cfg(unix)] use std::os::unix::process::CommandExt; -use std::path::PathBuf; use std::process::Command; fn main() { - let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap()); + let current_exe = env::current_exe().unwrap(); + let mut sysroot = current_exe.parent().unwrap(); + if sysroot.file_name().unwrap().to_str().unwrap() == "bin" { + sysroot = sysroot.parent().unwrap(); + } let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join( env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, diff --git a/scripts/rustup.sh b/scripts/rustup.sh index 34e3981b5381f..3cbeb6375de10 100755 --- a/scripts/rustup.sh +++ b/scripts/rustup.sh @@ -2,10 +2,24 @@ set -e +TOOLCHAIN=${TOOLCHAIN:-$(date +%Y-%m-%d)} + +function check_git_fixed_subtree() { + if [[ ! -e ./git-fixed-subtree.sh ]]; then + echo "Missing git-fixed-subtree.sh. Please run the following commands to download it:" + echo "curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/bjorn3/git/tqc-subtree-portable/contrib/subtree/git-subtree.sh -o git-fixed-subtree.sh" + echo "chmod u+x git-fixed-subtree.sh" + exit 1 + fi + if [[ ! -x ./git-fixed-subtree.sh ]]; then + echo "git-fixed-subtree.sh is not executable. Please run the following command to make it executable:" + echo "chmod u+x git-fixed-subtree.sh" + exit 1 + fi +} + case $1 in "prepare") - TOOLCHAIN=$(date +%Y-%m-%d) - echo "=> Installing new nightly" rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain @@ -27,28 +41,35 @@ case $1 in git commit -m "Rustup to $(rustc -V)" ;; "push") + check_git_fixed_subtree + cg_clif=$(pwd) pushd ../rust git pull origin master branch=sync_cg_clif-$(date +%Y-%m-%d) git checkout -b "$branch" - git subtree pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master + "$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master git push -u my "$branch" # immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing # from rust-lang/rust later - git subtree push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust + "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd git merge sync_from_rust ;; "pull") + check_git_fixed_subtree + + RUST_VERS=$(curl "https://static.rust-lang.org/dist/$TOOLCHAIN/channel-rust-nightly-git-commit-hash.txt") + echo "Pulling $RUST_VERS ($TOOLCHAIN)" + cg_clif=$(pwd) pushd ../rust - git pull origin master - rust_vers="$(git rev-parse HEAD)" - git subtree push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust + git fetch origin master + git checkout "$RUST_VERS" + "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd - git merge sync_from_rust -m "Sync from rust $rust_vers" + git merge sync_from_rust -m "Sync from rust $RUST_VERS" git branch -d sync_from_rust ;; *) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index a08e80dd19abc..abb09775d2135 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -10,7 +10,7 @@ git fetch git checkout -- . git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" -git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-sysroot-*.patch +git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-stdlib-*.patch git apply - <( ) -> Signature { let call_conv = conv_to_call_conv(tcx.sess, fn_abi.conv, default_call_conv); - let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten(); + let inputs = fn_abi.args.iter().flat_map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()); let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx); // Sometimes the first param is an pointer to the place where the return value needs to be stored. @@ -116,7 +118,52 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { params: Vec, returns: Vec, args: &[Value], - ) -> &[Value] { + ) -> Cow<'_, [Value]> { + if self.tcx.sess.target.is_like_windows { + let (mut params, mut args): (Vec<_>, Vec<_>) = + params + .into_iter() + .zip(args) + .map(|(param, &arg)| { + if param.value_type == types::I128 { + let arg_ptr = Pointer::stack_slot(self.bcx.create_sized_stack_slot( + StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16 }, + )); + arg_ptr.store(self, arg, MemFlags::trusted()); + (AbiParam::new(self.pointer_type), arg_ptr.get_addr(self)) + } else { + (param, arg) + } + }) + .unzip(); + + let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128; + + if indirect_ret_val { + params.insert(0, AbiParam::new(self.pointer_type)); + let ret_ptr = + Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: 16, + })); + args.insert(0, ret_ptr.get_addr(self)); + self.lib_call_unadjusted(name, params, vec![], &args); + return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]); + } else { + return self.lib_call_unadjusted(name, params, returns, &args); + } + } + + self.lib_call_unadjusted(name, params, returns, args) + } + + pub(crate) fn lib_call_unadjusted( + &mut self, + name: &str, + params: Vec, + returns: Vec, + args: &[Value], + ) -> Cow<'_, [Value]> { let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); @@ -125,41 +172,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } let call_inst = self.bcx.ins().call(func_ref, args); if self.clif_comments.enabled() { - self.add_comment(call_inst, format!("easy_call {}", name)); + self.add_comment(call_inst, format!("lib_call {}", name)); } let results = self.bcx.inst_results(call_inst); assert!(results.len() <= 2, "{}", results.len()); - results - } - - pub(crate) fn easy_call( - &mut self, - name: &str, - args: &[CValue<'tcx>], - return_ty: Ty<'tcx>, - ) -> CValue<'tcx> { - let (input_tys, args): (Vec<_>, Vec<_>) = args - .iter() - .map(|arg| { - (AbiParam::new(self.clif_type(arg.layout().ty).unwrap()), arg.load_scalar(self)) - }) - .unzip(); - let return_layout = self.layout_of(return_ty); - let return_tys = if let ty::Tuple(tup) = return_ty.kind() { - tup.iter().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect() - } else { - vec![AbiParam::new(self.clif_type(return_ty).unwrap())] - }; - let ret_vals = self.lib_call(name, input_tys, return_tys, &args); - match *ret_vals { - [] => CValue::by_ref( - Pointer::const_addr(self, i64::from(self.pointer_type.bytes())), - return_layout, - ), - [val] => CValue::by_val(val, return_layout), - [val, extra] => CValue::by_val_pair(val, extra, return_layout), - _ => unreachable!(), - } + Cow::Borrowed(results) } } @@ -275,10 +292,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ self::comments::add_locals_header_comment(fx); for (local, arg_kind, ty) in func_params { - let layout = fx.layout_of(ty); - - let is_ssa = ssa_analyzed[local] == crate::analyze::SsaKind::Ssa; - // While this is normally an optimization to prevent an unnecessary copy when an argument is // not mutated by the current function, this is necessary to support unsized arguments. if let ArgKind::Normal(Some(val)) = arg_kind { @@ -300,6 +313,8 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ } } + let layout = fx.layout_of(ty); + let is_ssa = ssa_analyzed[local].is_ssa(fx, ty); let place = make_local_place(fx, local, layout, is_ssa); assert_eq!(fx.local_map.push(place), local); @@ -323,7 +338,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ let ty = fx.monomorphize(fx.mir.local_decls[local].ty); let layout = fx.layout_of(ty); - let is_ssa = ssa_analyzed[local] == crate::analyze::SsaKind::Ssa; + let is_ssa = ssa_analyzed[local].is_ssa(fx, ty); let place = make_local_place(fx, local, layout, is_ssa); assert_eq!(fx.local_map.push(place), local); @@ -515,10 +530,9 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.into_iter() .enumerate() .skip(if first_arg_override.is_some() { 1 } else { 0 }) - .map(|(i, arg)| { + .flat_map(|(i, arg)| { adjust_arg_for_abi(fx, arg.value, &fn_abi.args[i], arg.is_owned).into_iter() - }) - .flatten(), + }), ) .collect::>(); diff --git a/src/abi/returning.rs b/src/abi/returning.rs index aaa1418767a35..6d3e8eda276a4 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -14,7 +14,8 @@ pub(super) fn codegen_return_param<'tcx>( ) -> CPlace<'tcx> { let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode { PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(..) => { - let is_ssa = ssa_analyzed[RETURN_PLACE] == crate::analyze::SsaKind::Ssa; + let is_ssa = + ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty); ( super::make_local_place( fx, diff --git a/src/analyze.rs b/src/analyze.rs index 0cbb9f3ec2d80..54d5c1c2ae9e9 100644 --- a/src/analyze.rs +++ b/src/analyze.rs @@ -4,34 +4,30 @@ use crate::prelude::*; use rustc_index::vec::IndexVec; use rustc_middle::mir::StatementKind::*; +use rustc_middle::ty::Ty; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub(crate) enum SsaKind { NotSsa, - Ssa, + MaybeSsa, +} + +impl SsaKind { + pub(crate) fn is_ssa<'tcx>(self, fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { + self == SsaKind::MaybeSsa && (fx.clif_type(ty).is_some() || fx.clif_pair_type(ty).is_some()) + } } pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec { - let mut flag_map = fx - .mir - .local_decls - .iter() - .map(|local_decl| { - let ty = fx.monomorphize(local_decl.ty); - if fx.clif_type(ty).is_some() || fx.clif_pair_type(ty).is_some() { - SsaKind::Ssa - } else { - SsaKind::NotSsa - } - }) - .collect::>(); + let mut flag_map = + fx.mir.local_decls.iter().map(|_| SsaKind::MaybeSsa).collect::>(); for bb in fx.mir.basic_blocks.iter() { for stmt in bb.statements.iter() { match &stmt.kind { Assign(place_and_rval) => match &place_and_rval.1 { Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - not_ssa(&mut flag_map, place.local) + flag_map[place.local] = SsaKind::NotSsa; } _ => {} }, @@ -42,7 +38,3 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec { flag_map } - -fn not_ssa(flag_map: &mut IndexVec, local: Local) { - flag_map[local] = SsaKind::NotSsa; -} diff --git a/src/base.rs b/src/base.rs index 230256ba5aa84..d0af3729b237c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -192,7 +192,7 @@ pub(crate) fn compile_fn( let pass_times = cranelift_codegen::timing::take_current(); // Replace newlines with | as measureme doesn't allow control characters like // newlines inside strings. - recorder.record_arg(format!("{}", pass_times).replace("\n", " | ")); + recorder.record_arg(format!("{}", pass_times).replace('\n', " | ")); recording_args = true; }, ) @@ -365,11 +365,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { fx.bcx.set_cold_block(failure); if *expected { - fx.bcx.ins().brz(cond, failure, &[]); + fx.bcx.ins().brif(cond, target, &[], failure, &[]); } else { - fx.bcx.ins().brnz(cond, failure, &[]); + fx.bcx.ins().brif(cond, failure, &[], target, &[]); }; - fx.bcx.ins().jump(target, &[]); fx.bcx.switch_to_block(failure); fx.bcx.ins().nop(); @@ -425,11 +424,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } } else { if test_zero { - fx.bcx.ins().brz(discr, then_block, &[]); - fx.bcx.ins().jump(else_block, &[]); + fx.bcx.ins().brif(discr, else_block, &[], then_block, &[]); } else { - fx.bcx.ins().brnz(discr, then_block, &[]); - fx.bcx.ins().jump(else_block, &[]); + fx.bcx.ins().brif(discr, then_block, &[], else_block, &[]); } } } else { @@ -750,8 +747,7 @@ fn codegen_stmt<'tcx>( fx.bcx.switch_to_block(loop_block); let done = fx.bcx.ins().icmp_imm(IntCC::Equal, index, times as i64); - fx.bcx.ins().brnz(done, done_block, &[]); - fx.bcx.ins().jump(loop_block2, &[]); + fx.bcx.ins().brif(done, done_block, &[], loop_block2, &[]); fx.bcx.switch_to_block(loop_block2); let to = lval.place_index(fx, index); @@ -997,7 +993,7 @@ fn codegen_panic_inner<'tcx>( let symbol_name = fx.tcx.symbol_name(instance).name; fx.lib_call( - &*symbol_name, + symbol_name, args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(), vec![], args, diff --git a/src/cast.rs b/src/cast.rs index 5091c5a9fedac..032d1151041db 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -64,17 +64,12 @@ pub(crate) fn clif_int_or_float_cast( }, ); - let from_rust_ty = if from_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - - let to_rust_ty = match to_ty { - types::F32 => fx.tcx.types.f32, - types::F64 => fx.tcx.types.f64, - _ => unreachable!(), - }; - - return fx - .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) - .load_scalar(fx); + return fx.lib_call( + &name, + vec![AbiParam::new(types::I128)], + vec![AbiParam::new(to_ty)], + &[from], + )[0]; } // int-like -> float @@ -101,16 +96,29 @@ pub(crate) fn clif_int_or_float_cast( }, ); - let from_rust_ty = match from_ty { - types::F32 => fx.tcx.types.f32, - types::F64 => fx.tcx.types.f64, - _ => unreachable!(), - }; - - let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - - fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty) - .load_scalar(fx) + if fx.tcx.sess.target.is_like_windows { + let ret = fx.lib_call( + &name, + vec![AbiParam::new(from_ty)], + vec![AbiParam::new(types::I64X2)], + &[from], + )[0]; + // FIXME use bitcast instead of store to get from i64x2 to i128 + let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: 16, + }); + let ret_ptr = Pointer::stack_slot(stack_slot); + ret_ptr.store(fx, ret, MemFlags::trusted()); + ret_ptr.load(fx, types::I128, MemFlags::trusted()) + } else { + fx.lib_call( + &name, + vec![AbiParam::new(from_ty)], + vec![AbiParam::new(types::I128)], + &[from], + )[0] + } } else if to_ty == types::I8 || to_ty == types::I16 { // FIXME implement fcvt_to_*int_sat.i8/i16 let val = if to_signed { diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index 40bfe70771c19..f674ce776a686 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -29,39 +29,24 @@ pub(crate) fn maybe_codegen<'tcx>( BinOp::Add | BinOp::Sub if !checked => None, BinOp::Mul if !checked || is_signed => { if !checked { - let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - if fx.tcx.sess.target.is_like_windows { - let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - let args = [ - ret_place.to_ptr().get_addr(fx), - lhs_ptr.get_addr(fx), - rhs_ptr.get_addr(fx), - ]; - fx.lib_call( - "__multi3", - vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(fx.pointer_type), - AbiParam::new(fx.pointer_type), - ], - vec![], - &args, - ); - Some(ret_place.to_cvalue(fx)) - } else { - Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) - } + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret_val = fx.lib_call( + "__multi3", + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I128)], + &args, + )[0]; + Some(CValue::by_val( + ret_val, + fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }), + )) } else { let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); let lhs = lhs.load_scalar(fx); let rhs = rhs.load_scalar(fx); let oflow_ptr = oflow.to_ptr().get_addr(fx); - let res = fx.lib_call( + let res = fx.lib_call_unadjusted( "__muloti4", vec![ AbiParam::new(types::I128), @@ -80,29 +65,12 @@ pub(crate) fn maybe_codegen<'tcx>( assert!(checked); let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); - let (param_types, args) = if fx.tcx.sess.target.is_like_windows { - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - ( - vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(fx.pointer_type), - AbiParam::new(fx.pointer_type), - ], - [out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)], - ) - } else { - ( - vec![ - AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), - AbiParam::new(types::I128), - AbiParam::new(types::I128), - ], - [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)], - ) - }; + let param_types = vec![ + AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn), + AbiParam::new(types::I128), + AbiParam::new(types::I128), + ]; + let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; let name = match (bin_op, is_signed) { (BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, true) => "__rust_i128_addo", @@ -125,14 +93,10 @@ pub(crate) fn maybe_codegen<'tcx>( _ => unreachable!(), }; if fx.tcx.sess.target.is_like_windows { - let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); - let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); - assert!(lhs_extra.is_none()); - assert!(rhs_extra.is_none()); - let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; let ret = fx.lib_call( name, - vec![AbiParam::new(fx.pointer_type), AbiParam::new(fx.pointer_type)], + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], vec![AbiParam::new(types::I64X2)], &args, )[0]; @@ -141,7 +105,14 @@ pub(crate) fn maybe_codegen<'tcx>( ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); Some(ret_place.to_cvalue(fx)) } else { - Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty)) + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret_val = fx.lib_call( + name, + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I128)], + &args, + )[0]; + Some(CValue::by_val(ret_val, lhs.layout())) } } BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { diff --git a/src/common.rs b/src/common.rs index 722e2754e8381..d39bf700035f9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -75,7 +75,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { let (element, count) = match &tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().abi { - Abi::Vector { element, count } => (element.clone(), *count), + Abi::Vector { element, count } => (*element, *count), _ => unreachable!(), }; diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index 8a53baa763a7d..f3b963200a0fb 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -39,6 +39,7 @@ builtin_functions! { // integers fn __multi3(a: i128, b: i128) -> i128; + fn __muloti4(n: i128, d: i128, oflow: &mut i32) -> i128; fn __udivti3(n: u128, d: u128) -> u128; fn __divti3(n: i128, d: i128) -> i128; fn __umodti3(n: u128, d: u128) -> u128; diff --git a/src/concurrency_limiter.rs b/src/concurrency_limiter.rs index f855e20e0a1a3..203219a8a754a 100644 --- a/src/concurrency_limiter.rs +++ b/src/concurrency_limiter.rs @@ -32,7 +32,7 @@ impl ConcurrencyLimiter { ConcurrencyLimiter { helper_thread: Some(helper_thread), state, - available_token_condvar: Arc::new(Condvar::new()), + available_token_condvar, finished: false, } } diff --git a/src/constant.rs b/src/constant.rs index efdf9f6d5bc02..31278f810e911 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -290,7 +290,7 @@ fn data_id_for_static( }; let data_id = match module.declare_data( - &*symbol_name, + symbol_name, linkage, is_mutable, attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL), @@ -338,7 +338,7 @@ fn data_id_for_static( }; let data_id = match module.declare_data( - &*symbol_name, + symbol_name, linkage, is_mutable, attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL), diff --git a/src/cranelift_native.rs b/src/cranelift_native.rs deleted file mode 100644 index 6c4efca442448..0000000000000 --- a/src/cranelift_native.rs +++ /dev/null @@ -1,248 +0,0 @@ -// Vendored from https://github.com/bytecodealliance/wasmtime/blob/b58a197d33f044193c3d608010f5e6ec394ac07e/cranelift/native/src/lib.rs -// which is licensed as -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// unlike rustc_codegen_cranelift itself. Also applies a small change to remove #![cfg_attr] that -// rust's CI complains about and to fix formatting to match rustc. -// FIXME revert back to the external crate with Cranelift 0.93 -#![allow(warnings)] - -//! Performs autodetection of the host for the purposes of running -//! Cranelift to generate code to run on the same machine. - -#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates, unstable_features)] -#![warn(unused_import_braces)] - -use cranelift_codegen::isa; -use target_lexicon::Triple; - -/// Return an `isa` builder configured for the current host -/// machine, or `Err(())` if the host machine is not supported -/// in the current configuration. -pub fn builder() -> Result { - builder_with_options(true) -} - -/// Return an `isa` builder configured for the current host -/// machine, or `Err(())` if the host machine is not supported -/// in the current configuration. -/// -/// Selects the given backend variant specifically; this is -/// useful when more than oen backend exists for a given target -/// (e.g., on x86-64). -pub fn builder_with_options(infer_native_flags: bool) -> Result { - let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err { - isa::LookupError::SupportDisabled => "support for architecture disabled at compile time", - isa::LookupError::Unsupported => "unsupported architecture", - })?; - - #[cfg(target_arch = "x86_64")] - { - use cranelift_codegen::settings::Configurable; - - if !std::is_x86_feature_detected!("sse2") { - return Err("x86 support requires SSE2"); - } - - if !infer_native_flags { - return Ok(isa_builder); - } - - // These are temporarily enabled by default (see #3810 for - // more) so that a default-constructed `Flags` can work with - // default Wasmtime features. Otherwise, the user must - // explicitly use native flags or turn these on when on x86-64 - // platforms to avoid a configuration panic. In order for the - // "enable if detected" logic below to work, we must turn them - // *off* (differing from the default) and then re-enable below - // if present. - isa_builder.set("has_sse3", "false").unwrap(); - isa_builder.set("has_ssse3", "false").unwrap(); - isa_builder.set("has_sse41", "false").unwrap(); - isa_builder.set("has_sse42", "false").unwrap(); - - if std::is_x86_feature_detected!("sse3") { - isa_builder.enable("has_sse3").unwrap(); - } - if std::is_x86_feature_detected!("ssse3") { - isa_builder.enable("has_ssse3").unwrap(); - } - if std::is_x86_feature_detected!("sse4.1") { - isa_builder.enable("has_sse41").unwrap(); - } - if std::is_x86_feature_detected!("sse4.2") { - isa_builder.enable("has_sse42").unwrap(); - } - if std::is_x86_feature_detected!("popcnt") { - isa_builder.enable("has_popcnt").unwrap(); - } - if std::is_x86_feature_detected!("avx") { - isa_builder.enable("has_avx").unwrap(); - } - if std::is_x86_feature_detected!("avx2") { - isa_builder.enable("has_avx2").unwrap(); - } - if std::is_x86_feature_detected!("fma") { - isa_builder.enable("has_fma").unwrap(); - } - if std::is_x86_feature_detected!("bmi1") { - isa_builder.enable("has_bmi1").unwrap(); - } - if std::is_x86_feature_detected!("bmi2") { - isa_builder.enable("has_bmi2").unwrap(); - } - if std::is_x86_feature_detected!("avx512bitalg") { - isa_builder.enable("has_avx512bitalg").unwrap(); - } - if std::is_x86_feature_detected!("avx512dq") { - isa_builder.enable("has_avx512dq").unwrap(); - } - if std::is_x86_feature_detected!("avx512f") { - isa_builder.enable("has_avx512f").unwrap(); - } - if std::is_x86_feature_detected!("avx512vl") { - isa_builder.enable("has_avx512vl").unwrap(); - } - if std::is_x86_feature_detected!("avx512vbmi") { - isa_builder.enable("has_avx512vbmi").unwrap(); - } - if std::is_x86_feature_detected!("lzcnt") { - isa_builder.enable("has_lzcnt").unwrap(); - } - } - - #[cfg(target_arch = "aarch64")] - { - use cranelift_codegen::settings::Configurable; - - if !infer_native_flags { - return Ok(isa_builder); - } - - if std::arch::is_aarch64_feature_detected!("lse") { - isa_builder.enable("has_lse").unwrap(); - } - - if std::arch::is_aarch64_feature_detected!("paca") { - isa_builder.enable("has_pauth").unwrap(); - } - - if cfg!(target_os = "macos") { - // Pointer authentication is always available on Apple Silicon. - isa_builder.enable("sign_return_address").unwrap(); - // macOS enforces the use of the B key for return addresses. - isa_builder.enable("sign_return_address_with_bkey").unwrap(); - } - } - - // There is no is_s390x_feature_detected macro yet, so for now - // we use getauxval from the libc crate directly. - #[cfg(all(target_arch = "s390x", target_os = "linux"))] - { - use cranelift_codegen::settings::Configurable; - - if !infer_native_flags { - return Ok(isa_builder); - } - - let v = unsafe { libc::getauxval(libc::AT_HWCAP) }; - const HWCAP_S390X_VXRS_EXT2: libc::c_ulong = 32768; - if (v & HWCAP_S390X_VXRS_EXT2) != 0 { - isa_builder.enable("has_vxrs_ext2").unwrap(); - // There is no separate HWCAP bit for mie2, so assume - // that any machine with vxrs_ext2 also has mie2. - isa_builder.enable("has_mie2").unwrap(); - } - } - - // `is_riscv_feature_detected` is nightly only for now, use - // getauxval from the libc crate directly as a temporary measure. - #[cfg(all(target_arch = "riscv64", target_os = "linux"))] - { - use cranelift_codegen::settings::Configurable; - - if !infer_native_flags { - return Ok(isa_builder); - } - - let v = unsafe { libc::getauxval(libc::AT_HWCAP) }; - - const HWCAP_RISCV_EXT_A: libc::c_ulong = 1 << (b'a' - b'a'); - const HWCAP_RISCV_EXT_C: libc::c_ulong = 1 << (b'c' - b'a'); - const HWCAP_RISCV_EXT_D: libc::c_ulong = 1 << (b'd' - b'a'); - const HWCAP_RISCV_EXT_F: libc::c_ulong = 1 << (b'f' - b'a'); - const HWCAP_RISCV_EXT_M: libc::c_ulong = 1 << (b'm' - b'a'); - const HWCAP_RISCV_EXT_V: libc::c_ulong = 1 << (b'v' - b'a'); - - if (v & HWCAP_RISCV_EXT_A) != 0 { - isa_builder.enable("has_a").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_C) != 0 { - isa_builder.enable("has_c").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_D) != 0 { - isa_builder.enable("has_d").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_F) != 0 { - isa_builder.enable("has_f").unwrap(); - - // TODO: There doesn't seem to be a bit associated with this extension - // rust enables it with the `f` extension: - // https://github.com/rust-lang/stdarch/blob/790411f93c4b5eada3c23abb4c9a063fb0b24d99/crates/std_detect/src/detect/os/linux/riscv.rs#L43 - isa_builder.enable("has_zicsr").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_M) != 0 { - isa_builder.enable("has_m").unwrap(); - } - - if (v & HWCAP_RISCV_EXT_V) != 0 { - isa_builder.enable("has_v").unwrap(); - } - - // TODO: ZiFencei does not have a bit associated with it - // TODO: Zbkb does not have a bit associated with it - } - - // squelch warnings about unused mut/variables on some platforms. - drop(&mut isa_builder); - drop(infer_native_flags); - - Ok(isa_builder) -} - -#[cfg(test)] -mod tests { - use super::builder; - use cranelift_codegen::isa::CallConv; - use cranelift_codegen::settings; - - #[test] - fn test() { - if let Ok(isa_builder) = builder() { - let flag_builder = settings::builder(); - let isa = isa_builder.finish(settings::Flags::new(flag_builder)).unwrap(); - - if cfg!(all(target_os = "macos", target_arch = "aarch64")) { - assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64); - } else if cfg!(any(unix, target_os = "nebulet")) { - assert_eq!(isa.default_call_conv(), CallConv::SystemV); - } else if cfg!(windows) { - assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall); - } - - if cfg!(target_pointer_width = "64") { - assert_eq!(isa.pointer_bits(), 64); - } else if cfg!(target_pointer_width = "32") { - assert_eq!(isa.pointer_bits(), 32); - } else if cfg!(target_pointer_width = "16") { - assert_eq!(isa.pointer_bits(), 16); - } - } - } -} - -/// Version number of this crate. -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index 9583cd2ec60f8..c4a5627e662f1 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -113,7 +113,7 @@ impl Writer for WriterRelocate { offset: offset as u32, size, name: DebugRelocName::Symbol(symbol), - addend: addend as i64, + addend, kind: object::RelocationKind::Absolute, }); self.write_udata(0, size) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 7c6fd9f6f1ec1..3e2e2af968860 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -377,7 +377,7 @@ pub(crate) fn run_aot( }; if tcx.dep_graph.is_fully_enabled() { - for cgu in &*cgus { + for cgu in cgus { tcx.ensure().codegen_unit(cgu.name()); } } @@ -417,7 +417,7 @@ pub(crate) fn run_aot( CguReuse::PreLto => unreachable!(), CguReuse::PostLto => { concurrency_limiter.job_already_done(); - OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, &*cgu)) + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) } } }) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 8b5a2da2c5944..f6a48e3257bc2 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -311,7 +311,11 @@ fn dep_symbol_lookup_fn( .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) .unwrap() .1; - for &cnum in &crate_info.used_crates { + // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to + // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib + // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library + // search path. + for &cnum in crate_info.used_crates.iter().rev() { let src = &crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} diff --git a/src/global_asm.rs b/src/global_asm.rs index 46c78ce6a1e34..a74f8ffa23d43 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -125,7 +125,7 @@ pub(crate) fn compile_global_asm( let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); // Assemble `global_asm` - let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); + let global_asm_object_file = add_file_stem_postfix(output_object_file, ".asm"); let mut child = Command::new(&config.assembler) .arg("-o") .arg(&global_asm_object_file) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 6206fbf7dd571..3ba530c040f7f 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -242,7 +242,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( } } InlineAsmOperand::Const { ref value } => { - let (const_value, ty) = crate::constant::eval_mir_constant(fx, &*value) + let (const_value, ty) = crate::constant::eval_mir_constant(fx, value) .unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved")); let value = rustc_codegen_ssa::common::asm_const_to_str( fx.tcx, @@ -334,13 +334,13 @@ pub(crate) fn codegen_inline_asm<'tcx>( } CInlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { - outputs.push((asm_gen.stack_slots_output[i].unwrap(), place.clone())); + outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place)); } } CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => { inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx))); if let Some(out_place) = out_place { - outputs.push((asm_gen.stack_slots_output[i].unwrap(), out_place.clone())); + outputs.push((asm_gen.stack_slots_output[i].unwrap(), *out_place)); } } CInlineAsmOperand::Const { value: _ } | CInlineAsmOperand::Symbol { symbol: _ } => {} diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 24f8d5e464e4c..fe48cac4faf1a 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -23,7 +23,7 @@ pub(crate) use llvm::codegen_llvm_intrinsic_call; use rustc_middle::ty; use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::subst::SubstsRef; use rustc_span::symbol::{kw, sym, Symbol}; @@ -252,45 +252,45 @@ fn codegen_float_intrinsic_call<'tcx>( args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, ) -> bool { - let (name, arg_count, ty) = match intrinsic { - sym::expf32 => ("expf", 1, fx.tcx.types.f32), - sym::expf64 => ("exp", 1, fx.tcx.types.f64), - sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32), - sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64), - sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32), - sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64), - sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32), // compiler-builtins - sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64), // compiler-builtins - sym::powf32 => ("powf", 2, fx.tcx.types.f32), - sym::powf64 => ("pow", 2, fx.tcx.types.f64), - sym::logf32 => ("logf", 1, fx.tcx.types.f32), - sym::logf64 => ("log", 1, fx.tcx.types.f64), - sym::log2f32 => ("log2f", 1, fx.tcx.types.f32), - sym::log2f64 => ("log2", 1, fx.tcx.types.f64), - sym::log10f32 => ("log10f", 1, fx.tcx.types.f32), - sym::log10f64 => ("log10", 1, fx.tcx.types.f64), - sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32), - sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64), - sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32), - sym::fmaf64 => ("fma", 3, fx.tcx.types.f64), - sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32), - sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64), - sym::floorf32 => ("floorf", 1, fx.tcx.types.f32), - sym::floorf64 => ("floor", 1, fx.tcx.types.f64), - sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32), - sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64), - sym::truncf32 => ("truncf", 1, fx.tcx.types.f32), - sym::truncf64 => ("trunc", 1, fx.tcx.types.f64), - sym::rintf32 => ("rintf", 1, fx.tcx.types.f32), - sym::rintf64 => ("rint", 1, fx.tcx.types.f64), - sym::roundf32 => ("roundf", 1, fx.tcx.types.f32), - sym::roundf64 => ("round", 1, fx.tcx.types.f64), - sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32), - sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64), - sym::sinf32 => ("sinf", 1, fx.tcx.types.f32), - sym::sinf64 => ("sin", 1, fx.tcx.types.f64), - sym::cosf32 => ("cosf", 1, fx.tcx.types.f32), - sym::cosf64 => ("cos", 1, fx.tcx.types.f64), + let (name, arg_count, ty, clif_ty) = match intrinsic { + sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32), + sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64), + sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32), + sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64), + sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32), + sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64), + sym::powif32 => ("__powisf2", 2, fx.tcx.types.f32, types::F32), // compiler-builtins + sym::powif64 => ("__powidf2", 2, fx.tcx.types.f64, types::F64), // compiler-builtins + sym::powf32 => ("powf", 2, fx.tcx.types.f32, types::F32), + sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64), + sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32), + sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64), + sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32), + sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64), + sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), + sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), + sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32), + sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), + sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), + sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), + sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), + sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), + sym::floorf64 => ("floor", 1, fx.tcx.types.f64, types::F64), + sym::ceilf32 => ("ceilf", 1, fx.tcx.types.f32, types::F32), + sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), + sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), + sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), + sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32), + sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64), + sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), + sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), + sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32), + sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64), + sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), + sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), + sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), + sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64), _ => return false, }; @@ -301,15 +301,19 @@ fn codegen_float_intrinsic_call<'tcx>( let (a, b, c); let args = match args { [x] => { - a = [codegen_operand(fx, x)]; + a = [codegen_operand(fx, x).load_scalar(fx)]; &a as &[_] } [x, y] => { - b = [codegen_operand(fx, x), codegen_operand(fx, y)]; + b = [codegen_operand(fx, x).load_scalar(fx), codegen_operand(fx, y).load_scalar(fx)]; &b } [x, y, z] => { - c = [codegen_operand(fx, x), codegen_operand(fx, y), codegen_operand(fx, z)]; + c = [ + codegen_operand(fx, x).load_scalar(fx), + codegen_operand(fx, y).load_scalar(fx), + codegen_operand(fx, z).load_scalar(fx), + ]; &c } _ => unreachable!(), @@ -318,15 +322,10 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { sym::fmaf32 | sym::fmaf64 => { - let a = args[0].load_scalar(fx); - let b = args[1].load_scalar(fx); - let c = args[2].load_scalar(fx); - CValue::by_val(fx.bcx.ins().fma(a, b, c), layout) + CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } sym::copysignf32 | sym::copysignf64 => { - let a = args[0].load_scalar(fx); - let b = args[1].load_scalar(fx); - CValue::by_val(fx.bcx.ins().fcopysign(a, b), layout) + CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) } sym::fabsf32 | sym::fabsf64 @@ -336,21 +335,29 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::ceilf64 | sym::truncf32 | sym::truncf64 => { - let a = args[0].load_scalar(fx); - let val = match intrinsic { - sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(a), - sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(a), - sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(a), - sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(a), + sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), _ => unreachable!(), }; CValue::by_val(val, layout) } + // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. - _ => fx.easy_call(name, &args, ty), + sym::powif32 | sym::powif64 => { + let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), AbiParam::new(types::I32)]; + let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; + CValue::by_val(ret_val, fx.layout_of(ty)) + } + _ => { + let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect(); + let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0]; + CValue::by_val(ret_val, fx.layout_of(ty)) + } }; ret.write_cvalue(fx, res); @@ -385,7 +392,7 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().debugtrap(); } - sym::copy | sym::copy_nonoverlapping => { + sym::copy => { intrinsic_args!(fx, args => (src, dst, count); intrinsic); let src = src.load_scalar(fx); let dst = dst.load_scalar(fx); @@ -397,13 +404,8 @@ fn codegen_regular_intrinsic_call<'tcx>( let byte_amount = if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; - if intrinsic == sym::copy_nonoverlapping { - // FIXME emit_small_memcpy - fx.bcx.call_memcpy(fx.target_config, dst, src, byte_amount); - } else { - // FIXME emit_small_memmove - fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); - } + // FIXME emit_small_memmove + fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => { // NOTE: the volatile variants have src and dst swapped @@ -643,26 +645,25 @@ fn codegen_regular_intrinsic_call<'tcx>( if do_panic { let layout = fx.layout_of(ty); - - with_no_trimmed_paths!({ - crate::base::codegen_panic_nounwind( - fx, - &if layout.abi.is_uninhabited() { - format!("attempted to instantiate uninhabited type `{}`", layout.ty) - } else if requirement == ValidityRequirement::Zero { + let msg_str = with_no_visible_paths!({ + with_no_trimmed_paths!({ + if layout.abi.is_uninhabited() { + // Use this error even for the other intrinsics as it is more precise. + format!("attempted to instantiate uninhabited type `{}`", ty) + } else if intrinsic == sym::assert_zero_valid { format!( "attempted to zero-initialize type `{}`, which is invalid", - layout.ty + ty ) } else { format!( "attempted to leave type `{}` uninitialized, which is invalid", - layout.ty + ty ) - }, - source_info, - ) + } + }) }); + crate::base::codegen_panic_nounwind(fx, &msg_str, source_info); return; } } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index a1d63acfb6166..034b4e8072cc5 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -279,9 +279,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); let trap_block = fx.bcx.create_block(); let true_ = fx.bcx.ins().iconst(types::I8, 1); - fx.bcx.ins().brnz(true_, trap_block, &[]); let ret_block = fx.get_block(target); - fx.bcx.ins().jump(ret_block, &[]); + fx.bcx.ins().brif(true_, trap_block, &[], ret_block, &[]); fx.bcx.switch_to_block(trap_block); crate::trap::trap_unimplemented( fx, @@ -825,8 +824,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let next = fx.bcx.create_block(); let res_lane = fx.bcx.append_block_param(next, lane_clif_ty); - fx.bcx.ins().brnz(mask_lane, if_enabled, &[]); - fx.bcx.ins().jump(if_disabled, &[]); + fx.bcx.ins().brif(mask_lane, if_enabled, &[], if_disabled, &[]); fx.bcx.seal_block(if_enabled); fx.bcx.seal_block(if_disabled); @@ -864,8 +862,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let if_enabled = fx.bcx.create_block(); let next = fx.bcx.create_block(); - fx.bcx.ins().brnz(mask_lane, if_enabled, &[]); - fx.bcx.ins().jump(next, &[]); + fx.bcx.ins().brif(mask_lane, if_enabled, &[], next, &[]); fx.bcx.seal_block(if_enabled); fx.bcx.switch_to_block(if_enabled); diff --git a/src/lib.rs b/src/lib.rs index 80ce3dc932873..bed79859f51ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,8 +57,6 @@ mod compiler_builtins; mod concurrency_limiter; mod config; mod constant; -// FIXME revert back to the external crate with Cranelift 0.93 -mod cranelift_native; mod debuginfo; mod discriminant; mod driver; @@ -251,7 +249,7 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple { } } -fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { +fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc { use target_lexicon::BinaryFormat; let target_triple = crate::target_triple(sess); @@ -285,14 +283,17 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box( BinOp::Mul => b.fmul(lhs, rhs), BinOp::Div => b.fdiv(lhs, rhs), BinOp::Rem => { - let name = match in_lhs.layout().ty.kind() { - ty::Float(FloatTy::F32) => "fmodf", - ty::Float(FloatTy::F64) => "fmod", + let (name, ty) = match in_lhs.layout().ty.kind() { + ty::Float(FloatTy::F32) => ("fmodf", types::F32), + ty::Float(FloatTy::F64) => ("fmod", types::F64), _ => bug!(), }; - return fx.easy_call(name, &[in_lhs, in_rhs], in_lhs.layout().ty); + + let ret_val = fx.lib_call( + name, + vec![AbiParam::new(ty), AbiParam::new(ty)], + vec![AbiParam::new(ty)], + &[lhs, rhs], + )[0]; + + return CValue::by_val(ret_val, in_lhs.layout()); } BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { let fltcc = match bin_op { diff --git a/src/pointer.rs b/src/pointer.rs index 31d827f83bfab..b60e56720ed5e 100644 --- a/src/pointer.rs +++ b/src/pointer.rs @@ -30,11 +30,6 @@ impl Pointer { Pointer { base: PointerBase::Stack(stack_slot), offset: Offset32::new(0) } } - pub(crate) fn const_addr(fx: &mut FunctionCx<'_, '_, '_>, addr: i64) -> Self { - let addr = fx.bcx.ins().iconst(fx.pointer_type, addr); - Pointer { base: PointerBase::Addr(addr), offset: Offset32::new(0) } - } - pub(crate) fn dangling(align: Align) -> Self { Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) } } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index a7af162687c34..e0a081c9d498b 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -245,7 +245,7 @@ pub(crate) fn write_clif_file( for flag in isa.flags().iter() { writeln!(file, "set {}", flag)?; } - write!(file, "target {}", isa.triple().architecture.to_string())?; + write!(file, "target {}", isa.triple().architecture)?; for isa_flag in isa.isa_flags().iter() { write!(file, " {}", isa_flag)?; } diff --git a/src/unsize.rs b/src/unsize.rs index a0745582d6669..ecf187a0b0fe6 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -28,9 +28,7 @@ pub(crate) fn unsized_info<'tcx>( ( &ty::Dynamic(ref data_a, _, src_dyn_kind), &ty::Dynamic(ref data_b, _, target_dyn_kind), - ) => { - assert_eq!(src_dyn_kind, target_dyn_kind); - + ) if src_dyn_kind == target_dyn_kind => { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { @@ -55,7 +53,7 @@ pub(crate) fn unsized_info<'tcx>( old_info } } - (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), + (_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } diff --git a/src/value_and_place.rs b/src/value_and_place.rs index cc1edaa97d800..58e0a498292d4 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use cranelift_codegen::ir::immediates::Offset32; +use cranelift_codegen::ir::{InstructionData, Opcode}; fn codegen_field<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -457,6 +458,7 @@ impl<'tcx> CPlace<'tcx> { } } + #[track_caller] pub(crate) fn to_ptr(self) -> Pointer { match self.to_ptr_maybe_unsized() { (ptr, None) => ptr, @@ -464,6 +466,7 @@ impl<'tcx> CPlace<'tcx> { } } + #[track_caller] pub(crate) fn to_ptr_maybe_unsized(self) -> (Pointer, Option) { match self.inner { CPlaceInner::Addr(ptr, extra) => (ptr, extra), @@ -787,7 +790,36 @@ impl<'tcx> CPlace<'tcx> { index: Value, ) -> CPlace<'tcx> { let (elem_layout, ptr) = match self.layout().ty.kind() { - ty::Array(elem_ty, _) => (fx.layout_of(*elem_ty), self.to_ptr()), + ty::Array(elem_ty, _) => { + let elem_layout = fx.layout_of(*elem_ty); + match self.inner { + CPlaceInner::Var(local, var) => { + // This is a hack to handle `vector_val.0[1]`. It doesn't allow dynamic + // indexing. + let lane_idx = match fx.bcx.func.dfg.insts + [fx.bcx.func.dfg.value_def(index).unwrap_inst()] + { + InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => imm, + _ => bug!( + "Dynamic indexing into a vector type is not supported: {self:?}[{index}]" + ), + }; + return CPlace { + inner: CPlaceInner::VarLane( + local, + var, + lane_idx.bits().try_into().unwrap(), + ), + layout: elem_layout, + }; + } + CPlaceInner::Addr(addr, None) => (elem_layout, addr), + CPlaceInner::Addr(_, Some(_)) + | CPlaceInner::VarPair(_, _, _) + | CPlaceInner::VarLane(_, _, _) => bug!("Can't index into {self:?}"), + } + // FIXME use VarLane in case of Var with simd type + } ty::Slice(elem_ty) => (fx.layout_of(*elem_ty), self.to_ptr_maybe_unsized().0), _ => bug!("place_index({:?})", self.layout().ty), }; diff --git a/src/vtable.rs b/src/vtable.rs index f04fb82de8c81..b7bfd8fd39526 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -43,10 +43,29 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) - pub(crate) fn get_ptr_and_method_ref<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - arg: CValue<'tcx>, + mut arg: CValue<'tcx>, idx: usize, ) -> (Pointer, Value) { let (ptr, vtable) = 'block: { + if let Abi::Scalar(_) = arg.layout().abi { + 'descend_newtypes: while !arg.layout().ty.is_unsafe_ptr() + && !arg.layout().ty.is_region_ptr() + { + for i in 0..arg.layout().fields.count() { + let field = arg.value_field(fx, mir::Field::new(i)); + if !field.layout().is_zst() { + // we found the one non-zero-sized field that is allowed + // now find *its* non-zero-sized field, or stop if it's a + // pointer + arg = field; + continue 'descend_newtypes; + } + } + + bug!("receiver has no non-zero-sized fields {:?}", arg); + } + } + if let ty::Ref(_, ty, _) = arg.layout().ty.kind() { if ty.is_dyn_star() { let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);