From 40cc89137b22099699d40230973b124e55ca21c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Tue, 10 Oct 2023 18:35:28 +0200 Subject: [PATCH 01/19] Remove from cranelift codegen LLVM intrinsics that are no longer needed --- src/intrinsics/llvm_x86.rs | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 0c9a94e1c231f..559c64bb13bdd 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -32,41 +32,6 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.write_cvalue(fx, CValue::by_val(res, fx.layout_of(fx.tcx.types.i64))); } - // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8` - "llvm.x86.sse2.pmovmskb.128" - | "llvm.x86.avx2.pmovmskb" - | "llvm.x86.sse.movmsk.ps" - | "llvm.x86.sse2.movmsk.pd" => { - intrinsic_args!(fx, args => (a); intrinsic); - - let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); - let lane_ty = fx.clif_type(lane_ty).unwrap(); - assert!(lane_count <= 32); - - let mut res = fx.bcx.ins().iconst(types::I32, 0); - - for lane in (0..lane_count).rev() { - let a_lane = a.value_lane(fx, lane).load_scalar(fx); - - // cast float to int - let a_lane = match lane_ty { - types::F32 => codegen_bitcast(fx, types::I32, a_lane), - types::F64 => codegen_bitcast(fx, types::I64, a_lane), - _ => a_lane, - }; - - // extract sign bit of an int - let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1)); - - // shift sign bit into result - let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false); - res = fx.bcx.ins().ishl_imm(res, 1); - res = fx.bcx.ins().bor(res, a_lane_sign); - } - - let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32)); - ret.write_cvalue(fx, res); - } "llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { let (x, y, kind) = match args { [x, y, kind] => (x, y, kind), From a302610016bd8299aff79c38f5a6b95ec1c112ba Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:22:23 +0000 Subject: [PATCH 02/19] Merge commit '93a5433f17ab5ed48cc88f1e69b0713b16183373' into sync_cg_clif-2023-10-24 --- .vscode/settings.json | 2 +- Cargo.lock | 52 +++---- Cargo.toml | 12 +- Readme.md | 6 +- example/mini_core_hello_world.rs | 11 ++ ...h-gets-miscompiled-with-llvm-sysroot.patch | 25 ---- src/abi/mod.rs | 35 ++--- src/abi/pass_mode.rs | 11 +- src/cast.rs | 6 +- src/common.rs | 19 +++ src/driver/aot.rs | 23 ++- src/inline_asm.rs | 22 +-- src/intrinsics/llvm_x86.rs | 137 ++++++++++++++++++ src/value_and_place.rs | 37 ++--- 14 files changed, 260 insertions(+), 138 deletions(-) delete mode 100644 patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch diff --git a/.vscode/settings.json b/.vscode/settings.json index 60cb51d566362..834a1362caf32 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -33,7 +33,7 @@ ] }, { - "sysroot_src": "./download/sysroot/sysroot_src/library", + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/std_example.rs", diff --git a/Cargo.lock b/Cargo.lock index 8079913cb0ff4..c716d50117312 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5e1df0da8488dd03b34afc134ba84b754d61862cc465932a9e5d07952f661e" +checksum = "c1512c3bb6b13018e7109fc3ac964bc87b329eaf3a77825d337558d0c7f6f1be" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a17ca4e699a0aaf49a0c88f6311a864f321048aa63f6b787cab20eb5f93f10" +checksum = "16cb8fb9220a6ea7a226705a273ab905309ee546267bdf34948d57932d7f0396" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022f2793cdade1d37a1f755ac42938a3f832f533eac6cafc8b26b209544c3c06" +checksum = "ab3a8d3b0d4745b183da5ea0792b13d79f5c23d6e69ac04761728e2532b56649" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d72dbb83c2ad788dec4ad0843070973cb48c35a3ca19b1e7437ac40834fd9c" +checksum = "524141c8e68f2abc2043de4c2b31f6d9dd42432738c246431d0572a1422a4a84" [[package]] name = "cranelift-control" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae07cf26dcc90d546826d747ac63b6c40c916f34b03e92a6ae0422c28d771b8a" +checksum = "97513b57c961c713789a03886a57b43e14ebcd204cbaa8ae50ca6c70a8e716b3" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fe6b7e49820893691aea497f36257e9d6f52061d8c4758d61d802d5f101a3d" +checksum = "e3f23d3cf3afa7e45f239702612c76d87964f652a55e28d13ed6d7e20f3479dd" [[package]] name = "cranelift-frontend" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f497576ca3674581581601b6a55ccc1b43447217648c880e5bce70db3cf659" +checksum = "554cd4947ec9209b58bf9ae5bf83581b5ddf9128bd967208e334b504a57db54e" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96aa02eac00fffee13b0cd37d17874ccdb3d5458983041accd825ef78ce6454" +checksum = "6c1892a439696b6413cb54083806f5fd9fc431768b8de74864b3d9e8b93b124f" [[package]] name = "cranelift-jit" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d6e0e308c873eefc185745a6b21daec2a10f7554c9fb67e334c2d7d756d979" +checksum = "32209252fb38acaf1662ccd0397907bbe0e92bdb13b6ddbfd2f74e437f83e685" dependencies = [ "anyhow", "cranelift-codegen", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1aa8ebb06eced4e478c3f94f1d65d4e7c93493f4640057912b27a3e34b84841" +checksum = "bf42656f5f6df7bfafc4dd7b63a1888b0627c07b43b2cb9aa54e13843fed39eb" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2870170ca44054b202c737626607b87be6e35655084bd94a6ff807a5812ba7df" +checksum = "e0c2d3badd4b9690865f5bb68a71fa94de592fa2df3f3d11a5a062c60c0a107a" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20647761742d17dabac8205da958910ede78599550e06418a16711a3ee2fc897" +checksum = "88eca54bbecea3170035168357306e9c779d4a63d8bf036c9e16bd21fdaa69b5" dependencies = [ "anyhow", "cranelift-codegen", @@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "14.0.0" +version = "14.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a5dda53ad6993f9b0a2d65fb49e0348a7232a27a8794064122870d6ee19eb2" +checksum = "9aaf2fa8fd2d6b65abae9b92edfe69254cc5d6b166e342364036c3e347de8da9" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index 5ad5e0e8140c3..f2ce714e8ff14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.101", features = ["unwind", "all-arch"] } -cranelift-frontend = { version = "0.101" } -cranelift-module = { version = "0.101" } -cranelift-native = { version = "0.101" } -cranelift-jit = { version = "0.101", optional = true } -cranelift-object = { version = "0.101" } +cranelift-codegen = { version = "0.101.1", features = ["unwind", "all-arch"] } +cranelift-frontend = { version = "0.101.1" } +cranelift-module = { version = "0.101.1" } +cranelift-native = { version = "0.101.1" } +cranelift-jit = { version = "0.101.1", optional = true } +cranelift-object = { version = "0.101.1" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/Readme.md b/Readme.md index 6f2027be96de9..5664cbe7d4fac 100644 --- a/Readme.md +++ b/Readme.md @@ -8,7 +8,7 @@ If not please open an issue. ## Building and testing ```bash -$ git clone https://github.com/bjorn3/rustc_codegen_cranelift +$ git clone https://github.com/rust-lang/rustc_codegen_cranelift $ cd rustc_codegen_cranelift $ ./y.sh prepare $ ./y.sh build @@ -29,7 +29,7 @@ Extract the `dist` directory in the archive anywhere you want. If you want to use `cargo clif build` instead of having to specify the full path to the `cargo-clif` executable, you can add the `bin` subdirectory of the extracted `dist` directory to your `PATH`. (tutorial [for Windows](https://stackoverflow.com/a/44272417), and [for Linux/MacOS](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path/26059#26059)). -[releases]: https://github.com/bjorn3/rustc_codegen_cranelift/releases/tag/dev +[releases]: https://github.com/rust-lang/rustc_codegen_cranelift/releases/tag/dev ## Usage @@ -78,7 +78,7 @@ configuration options. * Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)) * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`. -* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) +* SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) * Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default) ## License diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 91de04d97702f..afc51a47f1407 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -353,6 +353,17 @@ fn main() { let f = V([0.0, 1.0]); let _a = f.0[0]; + + stack_val_align(); +} + +#[inline(never)] +fn stack_val_align() { + #[repr(align(8192))] + struct Foo(u8); + + let a = Foo(0); + assert_eq!(&a as *const Foo as usize % 8192, 0); } #[cfg(all( diff --git a/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch b/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch deleted file mode 100644 index e6ebdcec783af..0000000000000 --- a/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 5d4afb8d807d181038b6a004d17ed055a8d191b2 Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Mon, 2 Oct 2023 13:59:00 +0000 -Subject: [PATCH] Ignore test which gets miscompiled with llvm sysroot - ---- - regex-automata/src/util/pool.rs | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/regex-automata/src/util/pool.rs b/regex-automata/src/util/pool.rs -index c03d7b0..28b233b 100644 ---- a/regex-automata/src/util/pool.rs -+++ b/regex-automata/src/util/pool.rs -@@ -1081,6 +1081,8 @@ mod tests { - // into the pool. This in turn resulted in this test producing a data race. - #[cfg(feature = "std")] - #[test] -+ // FIXME(rustc_codegen_cranelift#1395) miscompilation of thread::scope with LLVM sysroot -+ #[ignore] - fn thread_owner_sync() { - let pool = Pool::new(|| vec!['a']); - { --- -2.34.1 - diff --git a/src/abi/mod.rs b/src/abi/mod.rs index c75ad852f82d0..c4572e035258d 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -120,32 +120,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { args: &[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 (mut params, mut args): (Vec<_>, Vec<_>) = params + .into_iter() + .zip(args) + .map(|(param, &arg)| { + if param.value_type == types::I128 { + let arg_ptr = self.create_stack_slot(16, 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, - })); + let ret_ptr = self.create_stack_slot(16, 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())]); diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 7c9f8c1051cbb..0652267002910 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -189,16 +189,13 @@ pub(super) fn from_casted_value<'tcx>( let abi_params = cast_target_to_abi_params(cast); let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum(); let layout_size = u32::try_from(layout.size.bytes()).unwrap(); - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. + let ptr = fx.create_stack_slot( // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. - size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, - }); - let ptr = Pointer::stack_slot(stack_slot); + std::cmp::max(abi_param_size, layout_size), + u32::try_from(layout.align.pref.bytes()).unwrap(), + ); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); for param in abi_params { diff --git a/src/cast.rs b/src/cast.rs index 7e027c5f1b309..0b5cb1547fc69 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -104,11 +104,7 @@ pub(crate) fn clif_int_or_float_cast( &[from], )[0]; // FIXME(bytecodealliance/wasmtime#6104) 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); + let ret_ptr = fx.create_stack_slot(16, 16); ret_ptr.store(fx, ret, MemFlags::trusted()); ret_ptr.load(fx, types::I128, MemFlags::trusted()) } else { diff --git a/src/common.rs b/src/common.rs index 7a3ae6ebf52fa..9771f44f62cfb 100644 --- a/src/common.rs +++ b/src/common.rs @@ -383,6 +383,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { }) } + pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { + if align <= 16 { + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to + // specify stack slot alignment. + size: (size + 15) / 16 * 16, + }); + Pointer::stack_slot(stack_slot) + } else { + // Alignment is too big to handle using the above hack. Dynamically realign a stack slot + // instead. This wastes some space for the realignment. + let base_ptr = self.create_stack_slot(size + align, 16).get_addr(self); + let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); + let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); + Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) + } + } + pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) { if let Some(debug_context) = &mut self.cx.debug_context { let (file, line, column) = diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d3a7decc5430f..11229dd421ecc 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -361,12 +361,26 @@ pub(crate) fn run_aot( metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box { + // FIXME handle `-Ctarget-cpu=native` + let target_cpu = match tcx.sess.opts.cg.target_cpu { + Some(ref name) => name, + None => tcx.sess.target.cpu.as_ref(), + } + .to_owned(); + let cgus = if tcx.sess.opts.output_types.should_codegen() { tcx.collect_and_partition_mono_items(()).1 } else { // If only `--emit metadata` is used, we shouldn't perform any codegen. // Also `tcx.collect_and_partition_mono_items` may panic in that case. - &[] + return Box::new(OngoingCodegen { + modules: vec![], + allocator_module: None, + metadata_module: None, + metadata, + crate_info: CrateInfo::new(tcx, target_cpu), + concurrency_limiter: ConcurrencyLimiter::new(tcx.sess, 0), + }); }; if tcx.dep_graph.is_fully_enabled() { @@ -481,13 +495,6 @@ pub(crate) fn run_aot( None }; - // FIXME handle `-Ctarget-cpu=native` - let target_cpu = match tcx.sess.opts.cg.target_cpu { - Some(ref name) => name, - None => tcx.sess.target.cpu.as_ref(), - } - .to_owned(); - Box::new(OngoingCodegen { modules, allocator_module, diff --git a/src/inline_asm.rs b/src/inline_asm.rs index ed07723425481..0517c609337b9 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -878,13 +878,7 @@ fn call_inline_asm<'tcx>( inputs: Vec<(Size, Value)>, outputs: Vec<(Size, CPlace<'tcx>)>, ) { - let stack_slot = fx.bcx.func.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: u32::try_from(slot_size.bytes()).unwrap(), - }); - if fx.clif_comments.enabled() { - fx.add_comment(stack_slot, "inline asm scratch slot"); - } + let stack_slot = fx.create_stack_slot(u32::try_from(slot_size.bytes()).unwrap(), 16); let inline_asm_func = fx .module @@ -904,15 +898,23 @@ fn call_inline_asm<'tcx>( } for (offset, value) in inputs { - fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); + stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).store( + fx, + value, + MemFlags::trusted(), + ); } - let stack_slot_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0); + let stack_slot_addr = stack_slot.get_addr(fx); fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]); for (offset, place) in outputs { let ty = fx.clif_type(place.layout().ty).unwrap(); - let value = fx.bcx.ins().stack_load(ty, stack_slot, i32::try_from(offset.bytes()).unwrap()); + let value = stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).load( + fx, + ty, + MemFlags::trusted(), + ); place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 0c9a94e1c231f..35f144d7dad45 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -310,6 +310,143 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let val = CValue::by_val_pair(cb_out, c, layout); ret.write_cvalue(fx, val); } + "llvm.x86.sse2.pavg.b" | "llvm.x86.sse2.pavg.w" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + // FIXME use vector instructions when possible + simd_pair_for_each_lane( + fx, + a, + b, + ret, + &|fx, _lane_ty, _res_lane_ty, a_lane, b_lane| { + // (a + b + 1) >> 1 + let lane_ty = fx.bcx.func.dfg.value_type(a_lane); + let a_lane = fx.bcx.ins().uextend(lane_ty.double_width().unwrap(), a_lane); + let b_lane = fx.bcx.ins().uextend(lane_ty.double_width().unwrap(), b_lane); + let sum = fx.bcx.ins().iadd(a_lane, b_lane); + let num_plus_one = fx.bcx.ins().iadd_imm(sum, 1); + let res = fx.bcx.ins().ushr_imm(num_plus_one, 1); + fx.bcx.ins().ireduce(lane_ty, res) + }, + ); + } + "llvm.x86.sse2.psra.w" => { + intrinsic_args!(fx, args => (a, count); intrinsic); + + let count_lane = count.force_stack(fx).0.load(fx, types::I64, MemFlags::trusted()); + let lane_ty = fx.clif_type(a.layout().ty.simd_size_and_type(fx.tcx).1).unwrap(); + let max_count = fx.bcx.ins().iconst(types::I64, i64::from(lane_ty.bits() - 1)); + let saturated_count = fx.bcx.ins().umin(count_lane, max_count); + + // FIXME use vector instructions when possible + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, a_lane| { + fx.bcx.ins().sshr(a_lane, saturated_count) + }); + } + "llvm.x86.sse2.psad.bw" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.u8); + assert_eq!(ret_lane_ty, fx.tcx.types.u64); + assert_eq!(lane_count, ret_lane_count * 8); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.u64); + for out_lane_idx in 0..lane_count / 8 { + let mut lane_diff_acc = fx.bcx.ins().iconst(types::I64, 0); + + for lane_idx in out_lane_idx * 8..out_lane_idx * 8 + 1 { + let a_lane = a.value_lane(fx, lane_idx).load_scalar(fx); + let b_lane = b.value_lane(fx, lane_idx).load_scalar(fx); + + let lane_diff = fx.bcx.ins().isub(a_lane, b_lane); + let abs_lane_diff = fx.bcx.ins().iabs(lane_diff); + let abs_lane_diff = fx.bcx.ins().uextend(types::I64, abs_lane_diff); + lane_diff_acc = fx.bcx.ins().iadd(lane_diff_acc, abs_lane_diff); + } + + let res_lane = CValue::by_val(lane_diff_acc, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } + "llvm.x86.ssse3.pmadd.ub.sw.128" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.u8); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count, ret_lane_count * 2); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + for out_lane_idx in 0..lane_count / 2 { + let a_lane0 = a.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let a_lane0 = fx.bcx.ins().uextend(types::I16, a_lane0); + let b_lane0 = b.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let b_lane0 = fx.bcx.ins().sextend(types::I16, b_lane0); + + let a_lane1 = a.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let a_lane1 = fx.bcx.ins().uextend(types::I16, a_lane1); + let b_lane1 = b.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let b_lane1 = fx.bcx.ins().sextend(types::I16, b_lane1); + + let mul0: Value = fx.bcx.ins().imul(a_lane0, b_lane0); + let mul1 = fx.bcx.ins().imul(a_lane1, b_lane1); + + let (val, has_overflow) = fx.bcx.ins().sadd_overflow(mul0, mul1); + + let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, mul1, 0); + + let min = fx.bcx.ins().iconst(types::I16, i64::from(i16::MIN as u16)); + let max = fx.bcx.ins().iconst(types::I16, i64::from(i16::MAX as u16)); + + let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min); + let res_lane = fx.bcx.ins().select(has_overflow, sat_val, val); + + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } + "llvm.x86.sse2.pmadd.wd" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.i32); + assert_eq!(lane_count, ret_lane_count * 2); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.i32); + for out_lane_idx in 0..lane_count / 2 { + let a_lane0 = a.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let a_lane0 = fx.bcx.ins().uextend(types::I32, a_lane0); + let b_lane0 = b.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let b_lane0 = fx.bcx.ins().sextend(types::I32, b_lane0); + + let a_lane1 = a.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let a_lane1 = fx.bcx.ins().uextend(types::I32, a_lane1); + let b_lane1 = b.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let b_lane1 = fx.bcx.ins().sextend(types::I32, b_lane1); + + let mul0: Value = fx.bcx.ins().imul(a_lane0, b_lane0); + let mul1 = fx.bcx.ins().imul(a_lane1, b_lane1); + + let res_lane = fx.bcx.ins().iadd(mul0, mul1); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } _ => { fx.tcx .sess diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 3a6a6c9e3f508..5f0aa6c5581dd 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -132,18 +132,11 @@ impl<'tcx> CValue<'tcx> { (ptr.get_addr(fx), vtable) } CValueInner::ByValPair(data, vtable) => { - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15) - / 16 - * 16, - }); - let data_ptr = Pointer::stack_slot(stack_slot); - let mut flags = MemFlags::new(); - flags.set_notrap(); - data_ptr.store(fx, data, flags); + let data_ptr = fx.create_stack_slot( + u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(), + u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(), + ); + data_ptr.store(fx, data, MemFlags::trusted()); (data_ptr.get_addr(fx), vtable) } @@ -372,13 +365,11 @@ impl<'tcx> CPlace<'tcx> { .fatal(format!("values of type {} are too big to store on the stack", layout.ty)); } - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (u32::try_from(layout.size.bytes()).unwrap() + 15) / 16 * 16, - }); - CPlace { inner: CPlaceInner::Addr(Pointer::stack_slot(stack_slot), None), layout } + let stack_slot = fx.create_stack_slot( + u32::try_from(layout.size.bytes()).unwrap(), + u32::try_from(layout.align.pref.bytes()).unwrap(), + ); + CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout } } pub(crate) fn new_var( @@ -543,13 +534,7 @@ impl<'tcx> CPlace<'tcx> { _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data), _ if src_ty.is_vector() || dst_ty.is_vector() => { // FIXME(bytecodealliance/wasmtime#6104) do something more efficient for transmutes between vectors and integers. - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (src_ty.bytes() + 15) / 16 * 16, - }); - let ptr = Pointer::stack_slot(stack_slot); + let ptr = fx.create_stack_slot(src_ty.bytes(), src_ty.bytes()); ptr.store(fx, data, MemFlags::trusted()); ptr.load(fx, dst_ty, MemFlags::trusted()) } From 2c1dbed4aa049d5bb5b7d83d3c856519ee27a1dc Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 25 Oct 2023 01:05:26 +0200 Subject: [PATCH 03/19] Print variadic argument pattern in HIR pretty printer --- compiler/rustc_hir_pretty/src/lib.rs | 19 ++++++++++++------- tests/pretty/hir-fn-variadic.pp | 15 +++++++++++++++ tests/pretty/hir-fn-variadic.rs | 13 +++++++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 tests/pretty/hir-fn-variadic.pp create mode 100644 tests/pretty/hir-fn-variadic.rs diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ab6ab391484f3..1ce6bb6ca15fd 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -502,13 +502,13 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Fn(ref sig, param_names, body) => { + hir::ItemKind::Fn(ref sig, generics, body) => { self.head(""); self.print_fn( sig.decl, sig.header, Some(item.ident.name), - param_names, + generics, &[], Some(body), ); @@ -1948,11 +1948,10 @@ impl<'a> State<'a> { self.print_generic_params(generics.params); self.popen(); - let mut i = 0; // Make sure we aren't supplied *both* `arg_names` and `body_id`. assert!(arg_names.is_empty() || body_id.is_none()); - self.commasep(Inconsistent, decl.inputs, |s, ty| { - s.ibox(INDENT_UNIT); + let mut i = 0; + let mut print_arg = |s: &mut Self| { if let Some(arg_name) = arg_names.get(i) { s.word(arg_name.to_string()); s.word(":"); @@ -1963,11 +1962,17 @@ impl<'a> State<'a> { s.space(); } i += 1; + }; + self.commasep(Inconsistent, decl.inputs, |s, ty| { + s.ibox(INDENT_UNIT); + print_arg(s); s.print_type(ty); - s.end() + s.end(); }); if decl.c_variadic { - self.word(", ..."); + self.word(", "); + print_arg(self); + self.word("..."); } self.pclose(); diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp new file mode 100644 index 0000000000000..d4fadb254a6c9 --- /dev/null +++ b/tests/pretty/hir-fn-variadic.pp @@ -0,0 +1,15 @@ +// pretty-compare-only +// pretty-mode:hir +// pp-exact:hir-fn-variadic.pp + +#![feature(c_variadic)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +extern "C" { + fn foo(x: i32, ...); +} + +unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::() } diff --git a/tests/pretty/hir-fn-variadic.rs b/tests/pretty/hir-fn-variadic.rs new file mode 100644 index 0000000000000..efb2754df6230 --- /dev/null +++ b/tests/pretty/hir-fn-variadic.rs @@ -0,0 +1,13 @@ +// pretty-compare-only +// pretty-mode:hir +// pp-exact:hir-fn-variadic.pp + +#![feature(c_variadic)] + +extern "C" { + pub fn foo(x: i32, va1: ...); +} + +pub unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { + va2.arg::() +} From 6aead74ff276d249c2461962ebc3bad3ad93c955 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 25 Oct 2023 17:44:17 +0200 Subject: [PATCH 04/19] Remove unnecessary CVarArgs name skipping logic --- compiler/rustc_ast_lowering/src/lib.rs | 9 +-------- tests/pretty/hir-fn-variadic.pp | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1e51449e70cc6..f48c5fc1af5d9 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1737,14 +1737,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { - // Skip the `...` (`CVarArgs`) trailing arguments from the AST, - // as they are not explicit in HIR/Ty function signatures. - // (instead, the `c_variadic` flag is set to `true`) - let mut inputs = &decl.inputs[..]; - if decl.c_variadic() { - inputs = &inputs[..inputs.len() - 1]; - } - self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind { + self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Ident(_, ident, _) => self.lower_ident(ident), _ => Ident::new(kw::Empty, self.lower_span(param.pat.span)), })) diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index d4fadb254a6c9..577d9400ad4ed 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -9,7 +9,7 @@ extern crate std; extern "C" { - fn foo(x: i32, ...); + fn foo(x: i32, va1: ...); } unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::() } From 160b1793b2e29cfb10d7c7a5932ccb7f991f02bd Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Thu, 26 Oct 2023 08:20:23 +0200 Subject: [PATCH 05/19] Allows `#[diagnostic::on_unimplemented]` attributes to have multiple notes This commit extends the `#[diagnostic::on_unimplemented]` (and `#[rustc_on_unimplemented]`) attributes to allow multiple `note` options. This enables emitting multiple notes for custom error messages. For now I've opted to not change any of the existing usages of `#[rustc_on_unimplemented]` and just updated the relevant compile tests. --- .../error_reporting/on_unimplemented.rs | 32 +++++++------ .../error_reporting/type_err_ctxt_ext.rs | 14 +++--- library/core/src/marker.rs | 15 +++++- ...ptions_and_continue_to_use_fallback.stderr | 1 + .../on_unimplemented/multiple_notes.rs | 18 +++++++ .../on_unimplemented/multiple_notes.stderr | 47 +++++++++++++++++++ .../fn-traits.stderr | 3 ++ tests/ui/suggestions/path-display.stderr | 2 + tests/ui/traits/new-solver/fn-trait.stderr | 2 + 9 files changed, 111 insertions(+), 23 deletions(-) create mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs create mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index c96e41b88bd78..a5508c7413469 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -319,7 +319,7 @@ pub struct OnUnimplementedDirective { pub subcommands: Vec, pub message: Option, pub label: Option, - pub note: Option, + pub notes: Vec, pub parent_label: Option, pub append_const_msg: Option, } @@ -329,7 +329,7 @@ pub struct OnUnimplementedDirective { pub struct OnUnimplementedNote { pub message: Option, pub label: Option, - pub note: Option, + pub notes: Vec, pub parent_label: Option, // If none, should fall back to a generic message pub append_const_msg: Option, @@ -399,7 +399,7 @@ impl<'tcx> OnUnimplementedDirective { let mut message = None; let mut label = None; - let mut note = None; + let mut notes = Vec::new(); let mut parent_label = None; let mut subcommands = vec![]; let mut append_const_msg = None; @@ -415,10 +415,12 @@ impl<'tcx> OnUnimplementedDirective { label = parse_value(label_)?; continue; } - } else if item.has_name(sym::note) && note.is_none() { + } else if item.has_name(sym::note) { if let Some(note_) = item.value_str() { - note = parse_value(note_)?; - continue; + if let Some(note) = parse_value(note_)? { + notes.push(note); + continue; + } } } else if item.has_name(sym::parent_label) && parent_label.is_none() @@ -432,7 +434,7 @@ impl<'tcx> OnUnimplementedDirective { && is_root && message.is_none() && label.is_none() - && note.is_none() + && notes.is_empty() && !is_diagnostic_namespace_variant // FIXME(diagnostic_namespace): disallow filters for now { @@ -487,7 +489,7 @@ impl<'tcx> OnUnimplementedDirective { subcommands, message, label, - note, + notes, parent_label, append_const_msg, })) @@ -505,12 +507,14 @@ impl<'tcx> OnUnimplementedDirective { if let Some(aggr) = aggr { let mut subcommands = aggr.subcommands; subcommands.extend(directive.subcommands); + let mut notes = aggr.notes; + notes.extend(directive.notes); Ok(Some(Self { condition: aggr.condition.or(directive.condition), subcommands, message: aggr.message.or(directive.message), label: aggr.label.or(directive.label), - note: aggr.note.or(directive.note), + notes, parent_label: aggr.parent_label.or(directive.parent_label), append_const_msg: aggr.append_const_msg.or(directive.append_const_msg), })) @@ -543,7 +547,7 @@ impl<'tcx> OnUnimplementedDirective { value, attr.span, )?), - note: None, + notes: Vec::new(), parent_label: None, append_const_msg: None, })) @@ -600,7 +604,7 @@ impl<'tcx> OnUnimplementedDirective { ) -> OnUnimplementedNote { let mut message = None; let mut label = None; - let mut note = None; + let mut notes = Vec::new(); let mut parent_label = None; let mut append_const_msg = None; info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); @@ -637,9 +641,7 @@ impl<'tcx> OnUnimplementedDirective { label = Some(label_.clone()); } - if let Some(ref note_) = command.note { - note = Some(note_.clone()); - } + notes.extend(command.notes.clone()); if let Some(ref parent_label_) = command.parent_label { parent_label = Some(parent_label_.clone()); @@ -651,7 +653,7 @@ impl<'tcx> OnUnimplementedDirective { OnUnimplementedNote { label: label.map(|l| l.format(tcx, trait_ref, &options_map)), message: message.map(|m| m.format(tcx, trait_ref, &options_map)), - note: note.map(|n| n.format(tcx, trait_ref, &options_map)), + notes: notes.into_iter().map(|n| n.format(tcx, trait_ref, &options_map)).collect(), parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), append_const_msg, } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 353a69ef6d324..ce7510cccb4fa 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -428,7 +428,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let OnUnimplementedNote { message, label, - note, + notes, parent_label, append_const_msg, } = self.on_unimplemented_note(trait_ref, &obligation); @@ -436,21 +436,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); - let (message, note, append_const_msg) = if is_try_conversion { + let (message, notes, append_const_msg) = if is_try_conversion { ( Some(format!( "`?` couldn't convert the error to `{}`", trait_ref.skip_binder().self_ty(), )), - Some( + vec![ "the question mark operation (`?`) implicitly performs a \ conversion on the error value using the `From` trait" .to_owned(), - ), + ], Some(AppendConstMessage::Default), ) } else { - (message, note, append_const_msg) + (message, notes, append_const_msg) }; let err_msg = self.get_standard_error_message( @@ -569,9 +569,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some((msg, span)) = type_def { err.span_label(span, msg); } - if let Some(s) = note { + for note in notes { // If it has a custom `#[rustc_on_unimplemented]` note, let's display it - err.note(s); + err.note(note); } if let Some(s) = parent_label { let body = obligation.cause.body_id; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index f1594501d408b..d396a707b55da 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -621,7 +621,20 @@ impl Copy for &T {} note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead", ), on( - _Self = "core::cell::Cell", + all( + _Self = "core::cell::Cell", + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell"), + not(_Self = "core::cell::Cell") + ), note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`", ), on( diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr index 7860e540589db..906472beb49df 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr @@ -26,6 +26,7 @@ LL | takes_foo(()); | = help: the trait `Foo` is not implemented for `()` = note: custom note + = note: fallback note help: this trait has no implementations, consider adding one --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1 | diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs new file mode 100644 index 0000000000000..34cdb99c754b1 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs @@ -0,0 +1,18 @@ +#![feature(diagnostic_namespace)] + +#[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")] +trait Foo {} + +#[diagnostic::on_unimplemented(message = "Bar", label = "Foo", note = "Baz")] +#[diagnostic::on_unimplemented(note = "Baz2")] +trait Bar {} + +fn takes_foo(_: impl Foo) {} +fn takes_bar(_: impl Bar) {} + +fn main() { + takes_foo(()); + //~^ERROR Foo + takes_bar(()); + //~^ERROR Bar +} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr new file mode 100644 index 0000000000000..c72321d4617f0 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr @@ -0,0 +1,47 @@ +error[E0277]: Foo + --> $DIR/multiple_notes.rs:14:15 + | +LL | takes_foo(()); + | --------- ^^ Bar + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is not implemented for `()` + = note: Baz + = note: Boom +help: this trait has no implementations, consider adding one + --> $DIR/multiple_notes.rs:4:1 + | +LL | trait Foo {} + | ^^^^^^^^^ +note: required by a bound in `takes_foo` + --> $DIR/multiple_notes.rs:10:22 + | +LL | fn takes_foo(_: impl Foo) {} + | ^^^ required by this bound in `takes_foo` + +error[E0277]: Bar + --> $DIR/multiple_notes.rs:16:15 + | +LL | takes_bar(()); + | --------- ^^ Foo + | | + | required by a bound introduced by this call + | + = help: the trait `Bar` is not implemented for `()` + = note: Baz + = note: Baz2 +help: this trait has no implementations, consider adding one + --> $DIR/multiple_notes.rs:8:1 + | +LL | trait Bar {} + | ^^^^^^^^^ +note: required by a bound in `takes_bar` + --> $DIR/multiple_notes.rs:11:22 + | +LL | fn takes_bar(_: impl Bar) {} + | ^^^ required by this bound in `takes_bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index fc7bf22775dd7..4fb0d43d1b798 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -58,6 +58,7 @@ LL | call(foo_unsafe); | required by a bound introduced by this call | = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` @@ -75,6 +76,7 @@ LL | call_mut(foo_unsafe); | required by a bound introduced by this call | = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` @@ -92,6 +94,7 @@ LL | call_once(foo_unsafe); | required by a bound introduced by this call | = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr index 8359b36588e6b..46d0b35825bca 100644 --- a/tests/ui/suggestions/path-display.stderr +++ b/tests/ui/suggestions/path-display.stderr @@ -5,6 +5,7 @@ LL | println!("{}", path); | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it | = help: the trait `std::fmt::Display` is not implemented for `Path` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -15,6 +16,7 @@ LL | println!("{}", path); | ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it | = help: the trait `std::fmt::Display` is not implemented for `PathBuf` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/traits/new-solver/fn-trait.stderr b/tests/ui/traits/new-solver/fn-trait.stderr index d52bcaf25b87c..ff6903c5dbf25 100644 --- a/tests/ui/traits/new-solver/fn-trait.stderr +++ b/tests/ui/traits/new-solver/fn-trait.stderr @@ -7,6 +7,7 @@ LL | require_fn(f as unsafe fn() -> i32); | required by a bound introduced by this call | = help: the trait `Fn<()>` is not implemented for `unsafe fn() -> i32` + = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() -> i32` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `require_fn` --> $DIR/fn-trait.rs:3:23 @@ -97,6 +98,7 @@ LL | require_fn(h); | required by a bound introduced by this call | = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() -> i32 {h}` + = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() -> i32 {h}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `require_fn` --> $DIR/fn-trait.rs:3:23 From 1e39bbf74c69f64f570d378d7cd68b314b1bae93 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 25 Oct 2023 17:19:49 +0000 Subject: [PATCH 06/19] Update Cranelift to 0.101.2 and disable host-arch feature of cranelift-codegen This ensures that cg_clif can be built for targets that aren't natively supported by Cranelift. It will not be possible to compile for the host in this case, but cross-compilation will still be possible. We won't distribute cg_clif as rustup component for any targets that aren't natively supported by Cranelift, but will still build it if codegen-backends lists "cranelift". --- Cargo.lock | 52 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 12 ++++++------ 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c716d50117312..e8558198b94fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1512c3bb6b13018e7109fc3ac964bc87b329eaf3a77825d337558d0c7f6f1be" +checksum = "f773437307980ac0f424bf9b9a5d0cd21a0f17248c6860c9a65bec8b5975f3fe" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16cb8fb9220a6ea7a226705a273ab905309ee546267bdf34948d57932d7f0396" +checksum = "443c2ac50e97fb7de1a0f862753fce3f27215558811a6fcee508eb0c3747fa79" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3a8d3b0d4745b183da5ea0792b13d79f5c23d6e69ac04761728e2532b56649" +checksum = "c5b174c411480c79ce0793c55042fa51bec27e486381d103a53cab3b480cb2db" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524141c8e68f2abc2043de4c2b31f6d9dd42432738c246431d0572a1422a4a84" +checksum = "73fa0151a528066a369de6debeea4d4b23a32aba68b5add8c46d3dc8091ff434" [[package]] name = "cranelift-control" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97513b57c961c713789a03886a57b43e14ebcd204cbaa8ae50ca6c70a8e716b3" +checksum = "b8adf1e6398493c9bea1190e37d28a0eb0eca5fddbc80e01e506cda34db92b1f" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f23d3cf3afa7e45f239702612c76d87964f652a55e28d13ed6d7e20f3479dd" +checksum = "4917e2ed3bb5fe87d0ed88395ca6d644018d119a034faedd1f3e1f2c33cd52b2" [[package]] name = "cranelift-frontend" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554cd4947ec9209b58bf9ae5bf83581b5ddf9128bd967208e334b504a57db54e" +checksum = "9aaadf1e7cf28886bbf046eaf7ef538997bc8a7e020e578ea4957b39da87d5a1" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c1892a439696b6413cb54083806f5fd9fc431768b8de74864b3d9e8b93b124f" +checksum = "a67fda31b9d69eaa1c49a2081939454c45857596a9d45af6744680541c628b4c" [[package]] name = "cranelift-jit" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32209252fb38acaf1662ccd0397907bbe0e92bdb13b6ddbfd2f74e437f83e685" +checksum = "d6bf32710628e7ff298739f1ed80a0bfdafc0c6a3e284c4540b23f18e8889d4b" dependencies = [ "anyhow", "cranelift-codegen", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf42656f5f6df7bfafc4dd7b63a1888b0627c07b43b2cb9aa54e13843fed39eb" +checksum = "4d693e93a0fbf56b4bc93cffe6b107c2e52f070e1111950505fc8c83ac440b9d" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c2d3badd4b9690865f5bb68a71fa94de592fa2df3f3d11a5a062c60c0a107a" +checksum = "76fb52ba71be98312f35e798d9e98e45ab2586f27584231bf7c644fa9501e8af" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88eca54bbecea3170035168357306e9c779d4a63d8bf036c9e16bd21fdaa69b5" +checksum = "2551b2e185022b89e9efa5e04c0f17f679b86ef73d9f7feabc48b608ff23120d" dependencies = [ "anyhow", "cranelift-codegen", @@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "14.0.1" +version = "14.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aaf2fa8fd2d6b65abae9b92edfe69254cc5d6b166e342364036c3e347de8da9" +checksum = "0980a96b16abbdaf829858d2389697b1d6cfc6a903873fd74b7e47a6b1045584" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index f2ce714e8ff14..b5e6f431123e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.101.1", features = ["unwind", "all-arch"] } -cranelift-frontend = { version = "0.101.1" } -cranelift-module = { version = "0.101.1" } -cranelift-native = { version = "0.101.1" } -cranelift-jit = { version = "0.101.1", optional = true } -cranelift-object = { version = "0.101.1" } +cranelift-codegen = { version = "0.101.2", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.101.2" } +cranelift-module = { version = "0.101.2" } +cranelift-native = { version = "0.101.2" } +cranelift-jit = { version = "0.101.2", optional = true } +cranelift-object = { version = "0.101.2" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } From 1cb7bdb757d35d51a39219351d688e4631b86ff9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 26 Oct 2023 17:38:52 +0000 Subject: [PATCH 07/19] Update target-lexicon to 0.12.12 This adds support for loongarch and a bunch of other targets --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8558198b94fc..dcb6cc57584cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -362,9 +362,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "target-lexicon" -version = "0.12.5" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "version_check" From 827a6d8d9f0b84fec8fd15c336d845a05435889d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 29 Oct 2023 16:06:32 +0000 Subject: [PATCH 08/19] Use the LLVM rustc backend as external assembler The LLVM backend is generally available, while the gnu assembler is not on Windows and many other platforms by default. --- src/global_asm.rs | 70 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 6692d1b85eac0..7c2138bf0cfda 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -134,20 +134,66 @@ pub(crate) fn compile_global_asm( .join("\n"); global_asm.push('\n'); - let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); + let global_asm_object_file = add_file_stem_postfix( + config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)), + ".asm", + ); // Assemble `global_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) - .stdin(Stdio::piped()) - .spawn() - .expect("Failed to spawn `as`."); - child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); - let status = child.wait().expect("Failed to wait for `as`."); - if !status.success() { - return Err(format!("Failed to assemble `{}`", global_asm)); + if false { + let mut child = Command::new(&config.assembler) + .arg("-o") + .arg(&global_asm_object_file) + .stdin(Stdio::piped()) + .spawn() + .expect("Failed to spawn `as`."); + child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); + let status = child.wait().expect("Failed to wait for `as`."); + if !status.success() { + return Err(format!("Failed to assemble `{}`", global_asm)); + } + } else { + let mut child = Command::new(std::env::current_exe().unwrap()) + .arg("--target") + .arg(&config.target) + .arg("--crate-type") + .arg("staticlib") + .arg("--emit") + .arg("obj") + .arg("-o") + .arg(&global_asm_object_file) + .arg("-") + .arg("-Abad_asm_style") + .stdin(Stdio::piped()) + .spawn() + .expect("Failed to spawn `as`."); + let mut stdin = child.stdin.take().unwrap(); + stdin + .write_all( + br####" + #![feature(decl_macro, no_core, rustc_attrs)] + #![allow(internal_features)] + #![no_core] + #[rustc_builtin_macro] + #[rustc_macro_transparency = "semitransparent"] + macro global_asm() { /* compiler built-in */ } + global_asm!(r###" + "####, + ) + .unwrap(); + stdin.write_all(global_asm.as_bytes()).unwrap(); + stdin + .write_all( + br####" + "###); + "####, + ) + .unwrap(); + std::mem::drop(stdin); + let status = child.wait().expect("Failed to wait for `as`."); + if !status.success() { + return Err(format!("Failed to assemble `{}`", global_asm)); + } } Ok(Some(global_asm_object_file)) From b1e705146a26f5b650360edf2ecf05fec1315c33 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 29 Oct 2023 16:08:16 +0000 Subject: [PATCH 09/19] Unconditionally handle int $$0x29 using a shim --- src/inline_asm.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 0517c609337b9..b2e27399055e2 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -45,6 +45,14 @@ pub(crate) fn codegen_inline_asm<'tcx>( ) { // FIXME add .eh_frame unwind info directives + // Used by panic_abort on Windows, but uses a syntax which only happens to work with + // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for + // the LLVM backend. + if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + fx.bcx.ins().trap(TrapCode::User(1)); + return; + } + if !asm_supported(fx.tcx) { if template.is_empty() { let destination_block = fx.get_block(destination.unwrap()); @@ -52,12 +60,6 @@ pub(crate) fn codegen_inline_asm<'tcx>( return; } - // Used by panic_abort - if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { - fx.bcx.ins().trap(TrapCode::User(1)); - return; - } - // Used by stdarch if template[0] == InlineAsmTemplatePiece::String("mov ".to_string()) && matches!( From 35453ac0eb2fc906181903ae32a41df070f11458 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 29 Oct 2023 16:09:39 +0000 Subject: [PATCH 10/19] Stabilize inline asm usage on all platforms But exclude sym operands for now as they are somewhat broken. --- Cargo.toml | 4 +- src/global_asm.rs | 42 ++++---- src/inline_asm.rs | 206 ++-------------------------------------- src/intrinsics/cpuid.rs | 74 --------------- src/intrinsics/mod.rs | 2 - 5 files changed, 29 insertions(+), 299 deletions(-) delete mode 100644 src/intrinsics/cpuid.rs diff --git a/Cargo.toml b/Cargo.toml index f2ce714e8ff14..f422d53380fe3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,9 @@ smallvec = "1.8.1" [features] # Enable features not ready to be enabled when compiling as part of rustc -unstable-features = ["jit", "inline_asm"] +unstable-features = ["jit", "inline_asm_sym"] jit = ["cranelift-jit", "libloading"] -inline_asm = [] +inline_asm_sym = [] [package.metadata.rust-analyzer] rustc_private = true diff --git a/src/global_asm.rs b/src/global_asm.rs index 7c2138bf0cfda..332a7ca9bf249 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -46,6 +46,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, global_asm.push_str(&string); } InlineAsmOperand::SymFn { anon_const } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.sess.span_err( + item.span, + "asm! and global_asm! sym operands are not yet supported", + ); + } + let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), @@ -57,6 +64,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, global_asm.push_str(symbol.name); } InlineAsmOperand::SymStatic { path: _, def_id } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.sess.span_err( + item.span, + "asm! and global_asm! sym operands are not yet supported", + ); + } + let instance = Instance::mono(tcx, def_id).polymorphize(tcx); let symbol = tcx.symbol_name(instance); global_asm.push_str(symbol.name); @@ -81,22 +95,23 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } -pub(crate) fn asm_supported(tcx: TyCtxt<'_>) -> bool { - cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows -} - #[derive(Debug)] pub(crate) struct GlobalAsmConfig { - asm_enabled: bool, assembler: PathBuf, + target: String, pub(crate) output_filenames: Arc, } impl GlobalAsmConfig { pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { GlobalAsmConfig { - asm_enabled: asm_supported(tcx), assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), + target: match &tcx.sess.opts.target_triple { + rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(), + rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => { + path_for_rustdoc.to_str().unwrap().to_owned() + } + }, output_filenames: tcx.output_filenames(()).clone(), } } @@ -111,21 +126,6 @@ pub(crate) fn compile_global_asm( return Ok(None); } - if !config.asm_enabled { - if global_asm.contains("__rust_probestack") { - return Ok(None); - } - - if cfg!(not(feature = "inline_asm")) { - return Err( - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift" - .to_owned(), - ); - } else { - return Err("asm! and global_asm! are not yet supported on Windows".to_owned()); - } - } - // Remove all LLVM style comments let mut global_asm = global_asm .lines() diff --git a/src/inline_asm.rs b/src/inline_asm.rs index b2e27399055e2..331649b2ec24f 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -8,7 +8,6 @@ use rustc_span::sym; use rustc_target::asm::*; use target_lexicon::BinaryFormat; -use crate::global_asm::asm_supported; use crate::prelude::*; enum CInlineAsmOperand<'tcx> { @@ -53,205 +52,6 @@ pub(crate) fn codegen_inline_asm<'tcx>( return; } - if !asm_supported(fx.tcx) { - if template.is_empty() { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - // Used by stdarch - if template[0] == InlineAsmTemplatePiece::String("mov ".to_string()) - && matches!( - template[1], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[2] == InlineAsmTemplatePiece::String(", rbx".to_string()) - && template[3] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[4] == InlineAsmTemplatePiece::String("cpuid".to_string()) - && template[5] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[6] == InlineAsmTemplatePiece::String("xchg ".to_string()) - && matches!( - template[7], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[8] == InlineAsmTemplatePiece::String(", rbx".to_string()) - { - assert_eq!(operands.len(), 4); - let (leaf, eax_place) = match operands[1] { - InlineAsmOperand::InOut { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), - late: _, - ref in_value, - out_place: Some(out_place), - } => ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place), - ), - _ => unreachable!(), - }; - let ebx_place = match operands[0] { - InlineAsmOperand::Out { - reg: - InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86( - X86InlineAsmRegClass::reg, - )), - late: _, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - let (sub_leaf, ecx_place) = match operands[2] { - InlineAsmOperand::InOut { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), - late: _, - ref in_value, - out_place: Some(out_place), - } => ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place), - ), - _ => unreachable!(), - }; - let edx_place = match operands[3] { - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), - late: _, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - - let (eax, ebx, ecx, edx) = crate::intrinsics::codegen_cpuid_call(fx, leaf, sub_leaf); - - eax_place.write_cvalue(fx, CValue::by_val(eax, fx.layout_of(fx.tcx.types.u32))); - ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32))); - ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32))); - edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32))); - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - // Used by compiler-builtins - if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { - // ___chkstk, ___chkstk_ms and __alloca are only used on Windows - crate::trap::trap_unimplemented(fx, "Stack probes are not supported"); - return; - } else if fx.tcx.symbol_name(fx.instance).name == "__alloca" { - crate::trap::trap_unimplemented(fx, "Alloca is not supported"); - return; - } - - // Used by core::hint::spin_loop() - if template[0] - == InlineAsmTemplatePiece::String(".insn i 0x0F, 0, x0, x0, 0x010".to_string()) - && template.len() == 1 - { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - // Used by measureme - if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string()) - && template[1] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string()) - && matches!( - template[3], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[4] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[5] == InlineAsmTemplatePiece::String("cpuid".to_string()) - && template[6] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[7] == InlineAsmTemplatePiece::String("mov ".to_string()) - && matches!( - template[8], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string()) - { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) { - // Return zero dummy values for all performance counters - match operands[0] { - InlineAsmOperand::In { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), - value: _, - } => {} - _ => unreachable!(), - }; - let lo = match operands[1] { - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), - late: true, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - let hi = match operands[2] { - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), - late: true, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - - let u32_layout = fx.layout_of(fx.tcx.types.u32); - let zero = fx.bcx.ins().iconst(types::I32, 0); - lo.write_cvalue(fx, CValue::by_val(zero, u32_layout)); - hi.write_cvalue(fx, CValue::by_val(zero, u32_layout)); - - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string()) - && matches!( - template[1], - InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ } - ) - && template[2] == InlineAsmTemplatePiece::String(", (".to_string()) - && matches!( - template[3], - InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ } - ) - && template[4] == InlineAsmTemplatePiece::String(")".to_string()) - { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - if cfg!(not(feature = "inline_asm")) { - fx.tcx.sess.span_err( - span, - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - ); - } else { - fx.tcx.sess.span_err(span, "asm! and global_asm! are not yet supported on Windows"); - } - return; - } - let operands = operands .into_iter() .map(|operand| match *operand { @@ -282,6 +82,12 @@ pub(crate) fn codegen_inline_asm<'tcx>( CInlineAsmOperand::Const { value } } InlineAsmOperand::SymFn { ref value } => { + if cfg!(not(feature = "inline_asm_sym")) { + fx.tcx + .sess + .span_err(span, "asm! and global_asm! sym operands are not yet supported"); + } + let const_ = fx.monomorphize(value.const_); if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( diff --git a/src/intrinsics/cpuid.rs b/src/intrinsics/cpuid.rs deleted file mode 100644 index 5120b89c4e8b0..0000000000000 --- a/src/intrinsics/cpuid.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Emulation of a subset of the cpuid x86 instruction. - -use crate::prelude::*; - -/// Emulates a subset of the cpuid x86 instruction. -/// -/// This emulates an intel cpu with sse and sse2 support, but which doesn't support anything else. -pub(crate) fn codegen_cpuid_call<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - leaf: Value, - _sub_leaf: Value, -) -> (Value, Value, Value, Value) { - let leaf_0 = fx.bcx.create_block(); - let leaf_1 = fx.bcx.create_block(); - let leaf_7 = fx.bcx.create_block(); - let leaf_8000_0000 = fx.bcx.create_block(); - let leaf_8000_0001 = fx.bcx.create_block(); - let unsupported_leaf = fx.bcx.create_block(); - - let dest = fx.bcx.create_block(); - let eax = fx.bcx.append_block_param(dest, types::I32); - let ebx = fx.bcx.append_block_param(dest, types::I32); - let ecx = fx.bcx.append_block_param(dest, types::I32); - let edx = fx.bcx.append_block_param(dest, types::I32); - - let mut switch = cranelift_frontend::Switch::new(); - switch.set_entry(0, leaf_0); - switch.set_entry(1, leaf_1); - switch.set_entry(7, leaf_7); - switch.set_entry(0x8000_0000, leaf_8000_0000); - switch.set_entry(0x8000_0001, leaf_8000_0001); - switch.emit(&mut fx.bcx, leaf, unsupported_leaf); - - fx.bcx.switch_to_block(leaf_0); - let max_basic_leaf = fx.bcx.ins().iconst(types::I32, 1); - let vend0 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"Genu"))); - let vend2 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ineI"))); - let vend1 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ntel"))); - fx.bcx.ins().jump(dest, &[max_basic_leaf, vend0, vend1, vend2]); - - fx.bcx.switch_to_block(leaf_1); - let cpu_signature = fx.bcx.ins().iconst(types::I32, 0); - let additional_information = fx.bcx.ins().iconst(types::I32, 0); - let ecx_features = fx.bcx.ins().iconst(types::I32, 0); - let edx_features = fx.bcx.ins().iconst(types::I32, 1 << 25 /* sse */ | 1 << 26 /* sse2 */); - fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]); - - fx.bcx.switch_to_block(leaf_7); - // This leaf technically has subleaves, but we just return zero for all subleaves. - let zero = fx.bcx.ins().iconst(types::I32, 0); - fx.bcx.ins().jump(dest, &[zero, zero, zero, zero]); - - fx.bcx.switch_to_block(leaf_8000_0000); - let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0); - let zero = fx.bcx.ins().iconst(types::I32, 0); - fx.bcx.ins().jump(dest, &[extended_max_basic_leaf, zero, zero, zero]); - - fx.bcx.switch_to_block(leaf_8000_0001); - let zero = fx.bcx.ins().iconst(types::I32, 0); - let proc_info_ecx = fx.bcx.ins().iconst(types::I32, 0); - let proc_info_edx = fx.bcx.ins().iconst(types::I32, 0); - fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]); - - fx.bcx.switch_to_block(unsupported_leaf); - crate::trap::trap_unimplemented( - fx, - "__cpuid_count arch intrinsic doesn't yet support specified leaf", - ); - - fx.bcx.switch_to_block(dest); - fx.bcx.ins().nop(); - - (eax, ebx, ecx, edx) -} diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index e94091e6a25eb..83d5d53624eb1 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -12,7 +12,6 @@ macro_rules! intrinsic_args { } } -mod cpuid; mod llvm; mod llvm_aarch64; mod llvm_x86; @@ -25,7 +24,6 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; use rustc_span::symbol::{kw, sym, Symbol}; -pub(crate) use self::cpuid::codegen_cpuid_call; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; use crate::prelude::*; From 69c6aa560cfc1991822fdab1579153f6a25c392f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 29 Oct 2023 18:53:38 +0000 Subject: [PATCH 11/19] Avoid infinite recursion when cranelift is the default codegen backend --- scripts/setup_rust_fork.sh | 4 +++- scripts/test_bootstrap.sh | 4 +++- src/global_asm.rs | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 3e48fb006dea4..bbb8a010d965f 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -4,7 +4,9 @@ set -e # Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX. # CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass # --remap-path-prefix to handle this. -CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build +# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we +# the LLVM backend isn't compiled in here. +CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build echo "[SETUP] Rust fork" git clone https://github.com/rust-lang/rust.git || true diff --git a/scripts/test_bootstrap.sh b/scripts/test_bootstrap.sh index 791d457993de3..a8f6d7a202486 100755 --- a/scripts/test_bootstrap.sh +++ b/scripts/test_bootstrap.sh @@ -11,5 +11,7 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src} cp ../Cargo.* compiler/rustc_codegen_cranelift/ cp -r ../src compiler/rustc_codegen_cranelift/src -./x.py build --stage 1 library/std +# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we +# the LLVM backend isn't compiled in here. +CG_CLIF_FORCE_GNU_AS=1 ./x.py build --stage 1 library/std popd diff --git a/src/global_asm.rs b/src/global_asm.rs index 332a7ca9bf249..b14007f4e5232 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -140,7 +140,7 @@ pub(crate) fn compile_global_asm( ); // Assemble `global_asm` - if false { + if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() { let mut child = Command::new(&config.assembler) .arg("-o") .arg(&global_asm_object_file) @@ -164,6 +164,7 @@ pub(crate) fn compile_global_asm( .arg(&global_asm_object_file) .arg("-") .arg("-Abad_asm_style") + .arg("-Zcodegen-backend=llvm") .stdin(Stdio::piped()) .spawn() .expect("Failed to spawn `as`."); From dde58803fd6cbb270c7a437f36a8a3a29fbef679 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 29 Oct 2023 20:29:52 +0000 Subject: [PATCH 12/19] Rustup to rustc 1.75.0-nightly (e5cfc5547 2023-10-28) --- patches/stdlib-lock.toml | 17 ----------------- rust-toolchain | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index f10b4d6b9d4fa..9902bca8eab27 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -40,22 +40,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" -[[package]] -name = "auxv" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e50430f9beb8effb02399fa81c76eeaa26b05e4f03b09285cad8d079c1af5a3d" -dependencies = [ - "byteorder", - "gcc", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "cc" version = "1.0.79" @@ -388,7 +372,6 @@ dependencies = [ name = "std_detect" version = "0.1.5" dependencies = [ - "auxv", "cfg-if", "compiler_builtins", "cupid", diff --git a/rust-toolchain b/rust-toolchain index 3735ac1c17b14..7e3eaacf8ef08 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-21" +channel = "nightly-2023-10-29" components = ["rust-src", "rustc-dev", "llvm-tools"] From c5613258bb3f10907ba1127f363102bf842637cd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Oct 2023 17:45:01 -0400 Subject: [PATCH 13/19] Ignore RPIT duplicated lifetimes in opaque_types_defined_by --- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_ty_utils/src/opaque_types.rs | 9 ++++++++- ...plicate-lifetimes-from-rpit-containing-tait.rs | 13 +++++++++++++ ...licate-lifetimes-from-rpit-containing-tait2.rs | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs create mode 100644 tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait2.rs diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index d29d1902404f0..c155f83734e3e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -460,7 +460,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Checks whether each generic argument is simply a unique generic parameter. pub fn uses_unique_generic_params( self, - args: GenericArgsRef<'tcx>, + args: &[ty::GenericArg<'tcx>], ignore_regions: CheckRegions, ) -> Result<(), NotUniqueParam<'tcx>> { let mut seen = GrowableBitSet::default(); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index d1a154fe20d83..f7d54566cb704 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -154,7 +154,14 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { self.opaques.push(alias_ty.def_id.expect_local()); - match self.tcx.uses_unique_generic_params(alias_ty.args, CheckRegions::Bound) { + let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count; + // Only check that the parent generics of the TAIT/RPIT are unique. + // the args owned by the opaque are going to always be duplicate + // lifetime params for RPITs, and empty for TAITs. + match self + .tcx + .uses_unique_generic_params(&alias_ty.args[..parent_count], CheckRegions::Bound) + { Ok(()) => { // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not // supported at all, so this is sound to do, but once we want to support them, you'll diff --git a/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs b/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs new file mode 100644 index 0000000000000..4c56fe2d1dce2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type Opaque<'lt> = impl Sized + 'lt; + +fn test<'a>( + arg: impl Iterator, +) -> impl Iterator> { + arg +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait2.rs b/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait2.rs new file mode 100644 index 0000000000000..97f8c799fc566 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait2.rs @@ -0,0 +1,15 @@ +// check-pass +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + async fn new() -> () { + type T = impl Sized; + let _: T = (); + } +} + +fn main() {} From 6d69eb1f2e3d130a3e01412958f2387c1ad3b047 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 29 Oct 2023 20:50:47 +1100 Subject: [PATCH 14/19] coverage: Replace manual debug indents with nested tracing spans --- .../src/coverage/counters.rs | 84 +++++-------------- 1 file changed, 19 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index d07f59bc72af5..2e3e560975f0c 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -12,8 +12,6 @@ use rustc_middle::mir::coverage::*; use std::fmt::{self, Debug}; -const NESTED_INDENT: &str = " "; - /// The coverage counter or counter expression associated with a particular /// BCB node or BCB edge. #[derive(Clone)] @@ -347,22 +345,17 @@ impl<'a> MakeBcbCounters<'a> { } fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { - self.recursive_get_or_make_counter_operand(bcb, 1) + self.recursive_get_or_make_counter_operand(bcb) } + #[instrument(level = "debug", skip(self))] fn recursive_get_or_make_counter_operand( &mut self, bcb: BasicCoverageBlock, - debug_indent_level: usize, ) -> Result { // If the BCB already has a counter, return it. if let Some(counter_kind) = &self.coverage_counters.bcb_counters[bcb] { - debug!( - "{}{:?} already has a counter: {:?}", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - counter_kind, - ); + debug!("{bcb:?} already has a counter: {counter_kind:?}"); return Ok(counter_kind.as_term()); } @@ -373,20 +366,12 @@ impl<'a> MakeBcbCounters<'a> { if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { let counter_kind = self.coverage_counters.make_counter(); if one_path_to_target { - debug!( - "{}{:?} gets a new counter: {:?}", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - counter_kind, - ); + debug!("{bcb:?} gets a new counter: {counter_kind:?}"); } else { debug!( - "{}{:?} has itself as its own predecessor. It can't be part of its own \ - Expression sum, so it will get its own new counter: {:?}. (Note, the compiled \ - code will generate an infinite loop.)", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - counter_kind, + "{bcb:?} has itself as its own predecessor. It can't be part of its own \ + Expression sum, so it will get its own new counter: {counter_kind:?}. \ + (Note, the compiled code will generate an infinite loop.)", ); } return self.coverage_counters.set_bcb_counter(bcb, counter_kind); @@ -397,23 +382,13 @@ impl<'a> MakeBcbCounters<'a> { // counters for those incoming edges first, then call `make_expression()` to sum them up, // with additional intermediate expressions as needed. let mut predecessors = self.bcb_predecessors(bcb).to_owned().into_iter(); - debug!( - "{}{:?} has multiple incoming edges and will get an expression that sums them up...", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - ); - let first_edge_counter_operand = self.recursive_get_or_make_edge_counter_operand( - predecessors.next().unwrap(), - bcb, - debug_indent_level + 1, - )?; + debug!("{bcb:?} has multiple incoming edges and will need a sum-up expression"); + let first_edge_counter_operand = + self.recursive_get_or_make_edge_counter_operand(predecessors.next().unwrap(), bcb)?; let mut some_sumup_edge_counter_operand = None; for predecessor in predecessors { - let edge_counter_operand = self.recursive_get_or_make_edge_counter_operand( - predecessor, - bcb, - debug_indent_level + 1, - )?; + let edge_counter_operand = + self.recursive_get_or_make_edge_counter_operand(predecessor, bcb)?; if let Some(sumup_edge_counter_operand) = some_sumup_edge_counter_operand.replace(edge_counter_operand) { @@ -422,11 +397,7 @@ impl<'a> MakeBcbCounters<'a> { Op::Add, edge_counter_operand, ); - debug!( - "{}new intermediate expression: {:?}", - NESTED_INDENT.repeat(debug_indent_level), - intermediate_expression - ); + debug!("new intermediate expression: {intermediate_expression:?}"); let intermediate_expression_operand = intermediate_expression.as_term(); some_sumup_edge_counter_operand.replace(intermediate_expression_operand); } @@ -436,12 +407,7 @@ impl<'a> MakeBcbCounters<'a> { Op::Add, some_sumup_edge_counter_operand.unwrap(), ); - debug!( - "{}{:?} gets a new counter (sum of predecessor counters): {:?}", - NESTED_INDENT.repeat(debug_indent_level), - bcb, - counter_kind - ); + debug!("{bcb:?} gets a new counter (sum of predecessor counters): {counter_kind:?}"); self.coverage_counters.set_bcb_counter(bcb, counter_kind) } @@ -450,45 +416,33 @@ impl<'a> MakeBcbCounters<'a> { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, ) -> Result { - self.recursive_get_or_make_edge_counter_operand(from_bcb, to_bcb, 1) + self.recursive_get_or_make_edge_counter_operand(from_bcb, to_bcb) } + #[instrument(level = "debug", skip(self))] fn recursive_get_or_make_edge_counter_operand( &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, - debug_indent_level: usize, ) -> Result { // If the source BCB has only one successor (assumed to be the given target), an edge // counter is unnecessary. Just get or make a counter for the source BCB. let successors = self.bcb_successors(from_bcb).iter(); if successors.len() == 1 { - return self.recursive_get_or_make_counter_operand(from_bcb, debug_indent_level + 1); + return self.recursive_get_or_make_counter_operand(from_bcb); } // If the edge already has a counter, return it. if let Some(counter_kind) = self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)) { - debug!( - "{}Edge {:?}->{:?} already has a counter: {:?}", - NESTED_INDENT.repeat(debug_indent_level), - from_bcb, - to_bcb, - counter_kind - ); + debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}"); return Ok(counter_kind.as_term()); } // Make a new counter to count this edge. let counter_kind = self.coverage_counters.make_counter(); - debug!( - "{}Edge {:?}->{:?} gets a new counter: {:?}", - NESTED_INDENT.repeat(debug_indent_level), - from_bcb, - to_bcb, - counter_kind - ); + debug!("Edge {from_bcb:?}->{to_bcb:?} gets a new counter: {counter_kind:?}"); self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind) } From 2f1be08473e07e15d848b21e159be6729ffd90d2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 29 Oct 2023 20:53:17 +1100 Subject: [PATCH 15/19] coverage: Inline the "recursive" worker methods for assigning counters Now that we don't manually pass around indent levels, there's no need for these worker methods to exist separately from their main callers. --- .../src/coverage/counters.rs | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 2e3e560975f0c..8909de143335c 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -344,15 +344,8 @@ impl<'a> MakeBcbCounters<'a> { Ok(()) } - fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { - self.recursive_get_or_make_counter_operand(bcb) - } - #[instrument(level = "debug", skip(self))] - fn recursive_get_or_make_counter_operand( - &mut self, - bcb: BasicCoverageBlock, - ) -> Result { + fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> Result { // If the BCB already has a counter, return it. if let Some(counter_kind) = &self.coverage_counters.bcb_counters[bcb] { debug!("{bcb:?} already has a counter: {counter_kind:?}"); @@ -384,11 +377,10 @@ impl<'a> MakeBcbCounters<'a> { let mut predecessors = self.bcb_predecessors(bcb).to_owned().into_iter(); debug!("{bcb:?} has multiple incoming edges and will need a sum-up expression"); let first_edge_counter_operand = - self.recursive_get_or_make_edge_counter_operand(predecessors.next().unwrap(), bcb)?; + self.get_or_make_edge_counter_operand(predecessors.next().unwrap(), bcb)?; let mut some_sumup_edge_counter_operand = None; for predecessor in predecessors { - let edge_counter_operand = - self.recursive_get_or_make_edge_counter_operand(predecessor, bcb)?; + let edge_counter_operand = self.get_or_make_edge_counter_operand(predecessor, bcb)?; if let Some(sumup_edge_counter_operand) = some_sumup_edge_counter_operand.replace(edge_counter_operand) { @@ -411,16 +403,8 @@ impl<'a> MakeBcbCounters<'a> { self.coverage_counters.set_bcb_counter(bcb, counter_kind) } - fn get_or_make_edge_counter_operand( - &mut self, - from_bcb: BasicCoverageBlock, - to_bcb: BasicCoverageBlock, - ) -> Result { - self.recursive_get_or_make_edge_counter_operand(from_bcb, to_bcb) - } - #[instrument(level = "debug", skip(self))] - fn recursive_get_or_make_edge_counter_operand( + fn get_or_make_edge_counter_operand( &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, @@ -429,7 +413,7 @@ impl<'a> MakeBcbCounters<'a> { // counter is unnecessary. Just get or make a counter for the source BCB. let successors = self.bcb_successors(from_bcb).iter(); if successors.len() == 1 { - return self.recursive_get_or_make_counter_operand(from_bcb); + return self.get_or_make_counter_operand(from_bcb); } // If the edge already has a counter, return it. From 10c4734c79c7fc2cad772f0f013032ffeecbce1b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 29 Oct 2023 21:23:47 +1100 Subject: [PATCH 16/19] coverage: Use a tracing span to group the parts of a sum-up expression --- compiler/rustc_mir_transform/src/coverage/counters.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 8909de143335c..dcf603a4f77c8 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -374,8 +374,9 @@ impl<'a> MakeBcbCounters<'a> { // counters and/or expressions of its incoming edges. This will recursively get or create // counters for those incoming edges first, then call `make_expression()` to sum them up, // with additional intermediate expressions as needed. + let _sumup_debug_span = debug_span!("(preparing sum-up expression)").entered(); + let mut predecessors = self.bcb_predecessors(bcb).to_owned().into_iter(); - debug!("{bcb:?} has multiple incoming edges and will need a sum-up expression"); let first_edge_counter_operand = self.get_or_make_edge_counter_operand(predecessors.next().unwrap(), bcb)?; let mut some_sumup_edge_counter_operand = None; @@ -399,6 +400,8 @@ impl<'a> MakeBcbCounters<'a> { Op::Add, some_sumup_edge_counter_operand.unwrap(), ); + drop(_sumup_debug_span); + debug!("{bcb:?} gets a new counter (sum of predecessor counters): {counter_kind:?}"); self.coverage_counters.set_bcb_counter(bcb, counter_kind) } From 441068b613b48c8f6cb251530ef1c56039720fd3 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Wed, 25 Oct 2023 22:38:39 +0530 Subject: [PATCH 17/19] Use ImageDataType for allocation type Signed-off-by: Ayush Singh --- library/std/src/sys/uefi/alloc.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/uefi/alloc.rs b/library/std/src/sys/uefi/alloc.rs index 789e3cbd81ade..ad3904d82f3ff 100644 --- a/library/std/src/sys/uefi/alloc.rs +++ b/library/std/src/sys/uefi/alloc.rs @@ -1,13 +1,17 @@ //! Global Allocator for UEFI. //! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc) -use crate::alloc::{GlobalAlloc, Layout, System}; +use r_efi::protocols::loaded_image; -const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA; +use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::sync::OnceLock; +use crate::sys::uefi::helpers; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + static EFI_MEMORY_TYPE: OnceLock = OnceLock::new(); + // Return null pointer if boot services are not available if crate::os::uefi::env::boot_services().is_none() { return crate::ptr::null_mut(); @@ -15,8 +19,20 @@ unsafe impl GlobalAlloc for System { // If boot services is valid then SystemTable is not null. let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); + + // Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this + // will never fail. + let mem_type = EFI_MEMORY_TYPE.get_or_init(|| { + let protocol = helpers::image_handle_protocol::( + loaded_image::PROTOCOL_GUID, + ) + .unwrap(); + // Gives allocations the memory type that the data sections were loaded as. + unsafe { (*protocol.as_ptr()).image_data_type } + }); + // The caller must ensure non-0 layout - unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) } + unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) } } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { From 0c8bdd0bf33c2313ad9d0be495ffde8f4532237a Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Mon, 30 Oct 2023 13:03:40 +0530 Subject: [PATCH 18/19] Fail typeck for illegal break-with-value This is fixes the issue wherein typeck was succeeding for break-with-value at illegal locations such as inside `while`, `while let` and `for` loops which eventually caused an ICE during MIR interpetation for const eval. Now we fail typeck for such code which prevents faulty MIR from being generated and interpreted, thus fixing the ICE. --- compiler/rustc_hir_typeck/src/expr.rs | 13 ++++++--- .../issue-114529-illegal-break-with-value.rs | 20 +++++++++++++ ...sue-114529-illegal-break-with-value.stderr | 29 +++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 tests/ui/typeck/issue-114529-illegal-break-with-value.rs create mode 100644 tests/ui/typeck/issue-114529-illegal-break-with-value.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index be225ceb84321..b1d6e4f0523b6 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -625,10 +625,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - // If the loop context is not a `loop { }`, then break with - // a value is illegal, and `opt_coerce_to` will be `None`. - // Just set expectation to error in that case. - let coerce_to = opt_coerce_to.unwrap_or_else(|| Ty::new_misc_error(tcx)); + let coerce_to = match opt_coerce_to { + Some(c) => c, + None => { + // If the loop context is not a `loop { }`, then break with + // a value is illegal, and `opt_coerce_to` will be `None`. + // Return error in that case (#114529). + return Ty::new_misc_error(tcx); + } + }; // Recurse without `enclosing_breakables` borrowed. e_ty = self.check_expr_with_hint(e, coerce_to); diff --git a/tests/ui/typeck/issue-114529-illegal-break-with-value.rs b/tests/ui/typeck/issue-114529-illegal-break-with-value.rs new file mode 100644 index 0000000000000..613d1b6343a34 --- /dev/null +++ b/tests/ui/typeck/issue-114529-illegal-break-with-value.rs @@ -0,0 +1,20 @@ +// Regression test for issue #114529 +// Tests that we do not ICE during const eval for a +// break-with-value in contexts where it is illegal + +#[allow(while_true)] +fn main() { + [(); { + while true { + break 9; //~ ERROR `break` with value from a `while` loop + }; + 51 + }]; + + [(); { + while let Some(v) = Some(9) { + break v; //~ ERROR `break` with value from a `while` loop + }; + 51 + }]; +} diff --git a/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr b/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr new file mode 100644 index 0000000000000..4d6c27bbbd03b --- /dev/null +++ b/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr @@ -0,0 +1,29 @@ +error[E0571]: `break` with value from a `while` loop + --> $DIR/issue-114529-illegal-break-with-value.rs:9:13 + | +LL | while true { + | ---------- you can't `break` with a value in a `while` loop +LL | break 9; + | ^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/issue-114529-illegal-break-with-value.rs:16:13 + | +LL | while let Some(v) = Some(9) { + | --------------------------- you can't `break` with a value in a `while` loop +LL | break v; + | ^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0571`. From 3f7e50696f04e713311b841c4446dbf800ffaf6a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 30 Oct 2023 10:29:08 +0100 Subject: [PATCH 19/19] deduce_param_attrs: explain a read-only case --- compiler/rustc_mir_transform/src/deduce_param_attrs.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 79645310a3987..990cfb05e607e 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -44,6 +44,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly { // Whether mutating though a `&raw const` is allowed is still undecided, so we // disable any sketchy `readonly` optimizations for now. // But we only need to do this if the pointer would point into the argument. + // IOW: for indirect places, like `&raw (*local).field`, this surely cannot mutate `local`. !place.is_indirect() } PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {