Skip to content

Commit

Permalink
Async drop glue integration in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
azhogin committed May 20, 2024
1 parent cdf91ab commit c9aacfe
Show file tree
Hide file tree
Showing 38 changed files with 1,079 additions and 89 deletions.
76 changes: 76 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,42 @@ fn exported_symbols_provider_local(
},
));
}
MonoItem::Fn(Instance {
def: InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)),
args,
}) => {
// A little sanity-check
debug_assert_eq!(
args.non_erasable_generics(tcx, def_id).skip(1).next(),
Some(GenericArgKind::Type(ty))
);
symbols.push((
ExportedSymbol::AsyncDropGlueCtorShim(ty),
SymbolExportInfo {
level: SymbolExportLevel::Rust,
kind: SymbolExportKind::Text,
used: false,
},
));
}
MonoItem::Fn(Instance {
def: InstanceDef::AsyncDropGlue(def_id, Some(ty)),
args,
}) => {
// A little sanity-check
debug_assert_eq!(
args.non_erasable_generics(tcx, def_id).skip(1).next(),
Some(GenericArgKind::Type(ty))
);
symbols.push((
ExportedSymbol::AsyncDropGlue(ty),
SymbolExportInfo {
level: SymbolExportLevel::Rust,
kind: SymbolExportKind::Text,
used: false,
},
));
}
_ => {
// Any other symbols don't qualify for sharing
}
Expand All @@ -385,6 +421,8 @@ fn upstream_monomorphizations_provider(
let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();

let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
let async_drop_in_place_poll_fn_def_id = tcx.lang_items().async_drop_in_place_poll_fn();

for &cnum in cnums.iter() {
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
Expand All @@ -399,6 +437,26 @@ fn upstream_monomorphizations_provider(
continue;
}
}
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
(
async_drop_in_place_fn_def_id,
tcx.mk_args(&[tcx.lifetimes.re_erased.into(), ty.into()]),
)
} else {
continue;
}
}
ExportedSymbol::AsyncDropGlue(ty) => {
if let Some(poll_fn_def_id) = async_drop_in_place_poll_fn_def_id {
(
poll_fn_def_id,
tcx.mk_args(&[tcx.lifetimes.re_erased.into(), ty.into()]),
)
} else {
continue;
}
}
ExportedSymbol::NonGeneric(..)
| ExportedSymbol::ThreadLocalShim(..)
| ExportedSymbol::NoDefId(..) => {
Expand Down Expand Up @@ -534,6 +592,20 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
Instance::resolve_drop_in_place(tcx, ty),
instantiating_crate,
),
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
tcx,
Instance::resolve_async_drop_in_place(tcx, ty),
instantiating_crate,
)
}
ExportedSymbol::AsyncDropGlue(ty) => {
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
tcx,
Instance::resolve_async_drop_in_place_poll(tcx, ty),
instantiating_crate,
)
}
ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
}
}
Expand Down Expand Up @@ -581,6 +653,10 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
// DropGlue always use the Rust calling convention and thus follow the target's default
// symbol decoration scheme.
ExportedSymbol::DropGlue(..) => None,
// AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the
// target's default symbol decoration scheme.
ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
ExportedSymbol::AsyncDropGlue(..) => None,
// NoDefId always follow the target's default symbol decoration scheme.
ExportedSymbol::NoDefId(..) => None,
// ThreadLocalShim always follow the target's default symbol decoration scheme.
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
let def = instance.map(|i| i.def);

if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
if let Some(
ty::InstanceDef::DropGlue(_, None)
| ty::InstanceDef::AsyncDropGlueCtorShim(_, None)
| ty::InstanceDef::AsyncDropGlue(_, None),
) = def {
// Empty drop glue; a no-op.
let target = target.unwrap();
return helper.funclet_br(self, bx, target, mergeable_succ);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_const_eval/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
| ty::InstanceDef::CloneShim(..)
| ty::InstanceDef::FnPtrAddrShim(..)
| ty::InstanceDef::ThreadLocalShim(..)
| ty::InstanceDef::AsyncDropGlueCtorShim(..)
| ty::InstanceDef::AsyncDropGlue(..)
| ty::InstanceDef::Item(_) => {
// We need MIR for this fn
let Some((body, instance)) = M::find_mir_or_eval_fn(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ language_item_table! {
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::None;
AsyncDropInPlace, sym::async_drop_in_place, async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
AsyncDropInPlacePoll, sym::async_drop_in_place_poll, async_drop_in_place_poll_fn, Target::Closure, GenericRequirement::Exact(1);
FutureDropPoll, sym::future_drop_poll, future_drop_poll_fn, Target::Fn, GenericRequirement::Exact(1);

CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
Expand Down Expand Up @@ -263,7 +264,7 @@ language_item_table! {

ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
DropInPlaceFuture, sym::drop_in_place_future,drop_in_place_future_fn, Target::Fn, GenericRequirement::Minimum(1);
DropInPlaceFuture, sym::drop_in_place_future,drop_in_place_future_fn, Target::Fn, GenericRequirement::Exact(1);
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;

Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub fn provide(providers: &mut Providers) {
wfcheck::provide(providers);
*providers = Providers {
adt_destructor,
adt_async_destructor,
region_scope_tree,
collect_return_position_impl_trait_in_trait_tys,
compare_impl_const: compare_impl_item::compare_impl_const_raw,
Expand All @@ -122,6 +123,10 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor>
tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
}

fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl)
}

/// Given a `DefId` for an opaque type in return position, find its parent item's return
/// expressions.
fn get_owner_return_paths(
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ provide! { tcx, def_id, other, cdata,
let _ = cdata;
tcx.calculate_dtor(def_id, |_,_| Ok(()))
}
adt_async_destructor => {
let _ = cdata;
tcx.calculate_async_dtor(def_id, |_,_| Ok(()))
}
associated_item_def_ids => {
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/middle/exported_symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub enum ExportedSymbol<'tcx> {
NonGeneric(DefId),
Generic(DefId, GenericArgsRef<'tcx>),
DropGlue(Ty<'tcx>),
AsyncDropGlueCtorShim(Ty<'tcx>),
AsyncDropGlue(Ty<'tcx>),
ThreadLocalShim(DefId),
NoDefId(ty::SymbolName<'tcx>),
}
Expand All @@ -59,6 +61,12 @@ impl<'tcx> ExportedSymbol<'tcx> {
ExportedSymbol::DropGlue(ty) => {
tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
}
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
tcx.symbol_name(ty::Instance::resolve_async_drop_in_place(tcx, ty))
}
ExportedSymbol::AsyncDropGlue(ty) => {
tcx.symbol_name(ty::Instance::resolve_async_drop_in_place_poll(tcx, ty))
}
ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance {
def: ty::InstanceDef::ThreadLocalShim(def_id),
args: ty::GenericArgs::empty(),
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ pub struct CoroutineInfo<'tcx> {
/// Coroutine async drop glue.
pub coroutine_drop_async: Option<Body<'tcx>>,

/// When coroutine has sync drop, this is async proxy calling `coroutine_drop` sync impl.
pub coroutine_drop_proxy_async: Option<Body<'tcx>>,

/// The layout of a coroutine. Produced by the state transformation.
pub coroutine_layout: Option<CoroutineLayout<'tcx>>,

Expand All @@ -279,6 +282,7 @@ impl<'tcx> CoroutineInfo<'tcx> {
resume_ty: Some(resume_ty),
coroutine_drop: None,
coroutine_drop_async: None,
coroutine_drop_proxy_async: None,
coroutine_layout: None,
}
}
Expand Down Expand Up @@ -587,6 +591,19 @@ impl<'tcx> Body<'tcx> {
self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop_async.as_ref())
}

#[inline]
pub fn coroutine_requires_async_drop(&self) -> bool {
self.coroutine_drop_async().is_some()
}

#[inline]
pub fn future_drop_poll(&self) -> Option<&Body<'tcx>> {
self.coroutine.as_ref().and_then(
|coroutine|
coroutine.coroutine_drop_async.as_ref().or(
coroutine.coroutine_drop_proxy_async.as_ref()))
}

#[inline]
pub fn coroutine_kind(&self) -> Option<CoroutineKind> {
self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind)
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ impl<'tcx> MonoItem<'tcx> {
match instance.def {
// "Normal" functions size estimate: the number of
// statements, plus one for the terminator.
InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
InstanceDef::Item(..)
| InstanceDef::DropGlue(..)
| InstanceDef::AsyncDropGlueCtorShim(..)
| InstanceDef::AsyncDropGlue(..) => {
let mir = tcx.instance_mir(instance.def);
mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
}
Expand Down Expand Up @@ -404,9 +407,11 @@ impl<'tcx> CodegenUnit<'tcx> {
| InstanceDef::ClosureOnceShim { .. }
| InstanceDef::FutureDropPollShim(..)
| InstanceDef::DropGlue(..)
| InstanceDef::AsyncDropGlue(..)
| InstanceDef::CloneShim(..)
| InstanceDef::ThreadLocalShim(..)
| InstanceDef::FnPtrAddrShim(..) => None,
| InstanceDef::AsyncDropGlueCtorShim(..) => None,
}
}
MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ fn dump_path<'tcx>(
}));
s
}
ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => {
// Unfortunately, pretty-printed typed are not very filename-friendly.
// We dome some filtering.
let mut s = ".".to_owned();
s.extend(ty.to_string().chars().filter_map(|c| match c {
' ' => None,
':' | '<' | '>' => Some('_'),
c => Some(c),
}));
s
}
_ => String::new(),
};

Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,13 +345,17 @@ macro_rules! make_mir_visitor {
ty::InstanceDef::Virtual(_def_id, _) |
ty::InstanceDef::ThreadLocalShim(_def_id) |
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, None) |
ty::InstanceDef::AsyncDropGlue(_def_id, None) |
ty::InstanceDef::DropGlue(_def_id, None) => {}

ty::InstanceDef::FnPtrShim(_def_id, ty) |
ty::InstanceDef::FutureDropPollShim(_def_id, ty) |
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
ty::InstanceDef::CloneShim(_def_id, ty) |
ty::InstanceDef::FnPtrAddrShim(_def_id, ty) => {
ty::InstanceDef::FnPtrAddrShim(_def_id, ty) |
ty::InstanceDef::AsyncDropGlue(_def_id, Some(ty)) |
ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
// FIXME(eddyb) use a better `TyContext` here.
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ trivial! {
Option<rustc_hir::CoroutineKind>,
Option<rustc_hir::HirId>,
Option<rustc_middle::middle::stability::DeprecationEntry>,
Option<rustc_middle::ty::AsyncDestructor>,
Option<rustc_middle::ty::Destructor>,
Option<rustc_middle::ty::ImplTraitInTraitData>,
Option<rustc_span::def_id::CrateNum>,
Expand Down Expand Up @@ -286,6 +287,7 @@ trivial! {
rustc_middle::ty::AssocItem,
rustc_middle::ty::AssocItemContainer,
rustc_middle::ty::Asyncness,
rustc_middle::ty::AsyncDestructor,
rustc_middle::ty::BoundVariableKind,
rustc_middle::ty::DeducedParamAttrs,
rustc_middle::ty::Destructor,
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,11 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
query adt_async_destructor(key: DefId) -> Option<ty::AsyncDestructor> {
desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}

query adt_sized_constraint(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
desc { |tcx| "computing `Sized` constraints for `{}`", tcx.def_path_str(key) }
Expand Down Expand Up @@ -1355,6 +1360,10 @@ rustc_queries! {
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` needs drop", env.value }
}
/// Query backing `Ty::needs_async_drop`.
query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` needs async drop", env.value }
}
/// Query backing `Ty::has_significant_drop_raw`.
query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` has a significant drop", env.value }
Expand All @@ -1379,6 +1388,14 @@ rustc_queries! {
cache_on_disk_if { true }
}

/// A list of types where the ADT requires async drop if and only if any of
/// those types require async drop. If the ADT is known to always need async drop
/// then `Err(AlwaysRequiresDrop)` is returned.
query adt_async_drop_tys(def_id: DefId) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
desc { |tcx| "computing when `{}` needs async drop", tcx.def_path_str(def_id) }
cache_on_disk_if { true }
}

/// A list of types where the ADT requires drop if and only if any of those types
/// has significant drop. A type marked with the attribute `rustc_insignificant_dtor`
/// is considered to not be significant. A drop is significant if it is implemented
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use std::hash::{Hash, Hasher};
use std::ops::Range;
use std::str;

use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr};
use super::{
AsyncDestructor, Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr
};

#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
pub struct AdtFlags(u16);
Expand Down Expand Up @@ -564,6 +566,10 @@ impl<'tcx> AdtDef<'tcx> {
tcx.adt_destructor(self.did())
}

pub fn async_destructor(self, tcx: TyCtxt<'tcx>) -> Option<AsyncDestructor> {
tcx.adt_async_destructor(self.did())
}

/// Returns a list of types such that `Self: Sized` if and only if that
/// type is `Sized`, or `ty::Error` if this type has a recursive layout.
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
Expand Down
Loading

0 comments on commit c9aacfe

Please sign in to comment.