X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_ty_utils%2Fsrc%2Fabi.rs;h=91a505a72fae7a6be74b31e2b2ff0909af29b877;hb=e45984b7746737feeef1dffe403475b2cc4e68cd;hp=dc1dd1bfaf8e7f30ddd14374c59375957472ed3c;hpb=dce5e29edcd3f97017b67296972d18fc0423599a;p=rust.git diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index dc1dd1bfaf8..ad5527f5a77 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -41,7 +41,7 @@ fn fn_sig_for_fn_abi<'tcx>( // We normalize the `fn_sig` again after substituting at a later point. let mut sig = match *ty.kind() { ty::FnDef(def_id, substs) => tcx - .bound_fn_sig(def_id) + .fn_sig(def_id) .map_bound(|fn_sig| { tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig) }) @@ -108,21 +108,41 @@ fn fn_sig_for_fn_abi<'tcx>( // `Generator::resume(...) -> GeneratorState` function in case we // have an ordinary generator, or the `Future::poll(...) -> Poll` // function in case this is a special generator backing an async construct. - let ret_ty = if tcx.generator_is_async(did) { - let state_did = tcx.require_lang_item(LangItem::Poll, None); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[sig.return_ty.into()]); - tcx.mk_adt(state_adt_ref, state_substs) + let (resume_ty, ret_ty) = if tcx.generator_is_async(did) { + // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll` + let poll_did = tcx.require_lang_item(LangItem::Poll, None); + let poll_adt_ref = tcx.adt_def(poll_did); + let poll_substs = tcx.intern_substs(&[sig.return_ty.into()]); + let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs); + + // We have to replace the `ResumeTy` that is used for type and borrow checking + // with `&mut Context<'_>` which is used in codegen. + #[cfg(debug_assertions)] + { + if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() { + let expected_adt = + tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None)); + assert_eq!(*resume_ty_adt, expected_adt); + } else { + panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty); + }; + } + let context_mut_ref = tcx.mk_task_context(); + + (context_mut_ref, ret_ty) } else { + // The signature should be `Generator::resume(_, Resume) -> GeneratorState` let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - tcx.mk_adt(state_adt_ref, state_substs) + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + (sig.resume_ty, ret_ty) }; ty::Binder::bind_with_vars( tcx.mk_fn_sig( - [env_ty, sig.resume_ty].iter(), + [env_ty, resume_ty].iter(), &ret_ty, false, hir::Unsafety::Normal, @@ -219,13 +239,12 @@ fn adjust_for_rust_scalar<'tcx>( return; } - // Scalars which have invalid values cannot be undef. - if !scalar.is_always_valid(&cx) { + if !scalar.is_uninit_valid() { attrs.set(ArgAttribute::NoUndef); } // Only pointer types handled below. - let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return }; + let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return }; if !valid_range.contains(0) { attrs.set(ArgAttribute::NonNull); @@ -235,22 +254,20 @@ fn adjust_for_rust_scalar<'tcx>( if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); - // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable - // for the entire duration of the function as they can be deallocated - // at any time. Same for shared mutable references. If LLVM had a - // way to say "dereferenceable on entry" we could use it here. + // `Box` are not necessarily dereferenceable for the entire duration of the function as + // they can be deallocated at any time. Same for non-frozen shared references (see + // ), and for mutable references to + // potentially self-referential types (see + // ). If LLVM had a way + // to say "dereferenceable on entry" we could use it here. attrs.pointee_size = match kind { - PointerKind::UniqueBorrowed - | PointerKind::UniqueBorrowedPinned - | PointerKind::Frozen => pointee.size, - PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO, + PointerKind::Box { .. } + | PointerKind::SharedRef { frozen: false } + | PointerKind::MutableRef { unpin: false } => Size::ZERO, + PointerKind::SharedRef { frozen: true } + | PointerKind::MutableRef { unpin: true } => pointee.size, }; - // `Box`, `&T`, and `&mut T` cannot be undef. - // Note that this only applies to the value of the pointer itself; - // this attribute doesn't make it UB for the pointed-to data to be undef. - attrs.set(ArgAttribute::NoUndef); - // The aliasing rules for `Box` are still not decided, but currently we emit // `noalias` for it. This can be turned off using an unstable flag. // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326 @@ -261,18 +278,16 @@ fn adjust_for_rust_scalar<'tcx>( // versions at all anymore. We still support turning it off using -Zmutable-noalias. let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias; - // `&mut` pointer parameters never alias other parameters, - // or mutable global data + // `&T` where `T` contains no `UnsafeCell` is immutable, and can be marked as both + // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory + // dependencies rather than pointer equality. However this only applies to arguments, + // not return values. // - // `&T` where `T` contains no `UnsafeCell` is immutable, - // and can be marked as both `readonly` and `noalias`, as - // LLVM's definition of `noalias` is based solely on memory - // dependencies rather than pointer equality + // `&mut T` and `Box` where `T: Unpin` are unique and hence `noalias`. let no_alias = match kind { - PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false, - PointerKind::UniqueBorrowed => noalias_mut_ref, - PointerKind::UniqueOwned => noalias_for_box, - PointerKind::Frozen => true, + PointerKind::SharedRef { frozen } => frozen, + PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref, + PointerKind::Box { unpin } => unpin && noalias_for_box, }; // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics // (see ). @@ -280,7 +295,7 @@ fn adjust_for_rust_scalar<'tcx>( attrs.set(ArgAttribute::NoAlias); } - if kind == PointerKind::Frozen && !is_return { + if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return { attrs.set(ArgAttribute::ReadOnly); } } @@ -465,7 +480,7 @@ fn fn_abi_adjust_for_abi<'tcx>( } let size = arg.layout.size; - if arg.layout.is_unsized() || size > Pointer.size(cx) { + if arg.layout.is_unsized() || size > Pointer(AddressSpace::DATA).size(cx) { arg.make_indirect(); } else { // We want to pass small aggregates as immediates, but using