Skip to content

Commit

Permalink
rustc: use ReifyShim for reifying Virtual call instances.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Dec 3, 2019
1 parent 4b68afe commit 39e50e2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 25 deletions.
32 changes: 20 additions & 12 deletions src/librustc/ty/instance.rs
Expand Up @@ -29,10 +29,15 @@ pub enum InstanceDef<'tcx> {


/// `fn()` pointer where the function itself cannot be turned into a pointer. /// `fn()` pointer where the function itself cannot be turned into a pointer.
/// ///
/// One example in the compiler today is functions annotated with `#[track_caller]`, which /// One example is `<dyn Trait as Trait>::fn`, where the shim contains
/// must have their implicit caller location argument populated for a call. Because this is a /// a virtual call, which codegen supports only via a direct call to the
/// required part of the function's ABI but can't be tracked as a property of the function /// `<dyn Trait as Trait>::fn` instance (an `InstanceDef::Virtual`).
/// pointer, we create a single "caller location" at the site where the function is reified. ///
/// Another example is functions annotated with `#[track_caller]`, which
/// must have their implicit caller location argument populated for a call.
/// Because this is a required part of the function's ABI but can't be tracked
/// as a property of the function pointer, we use a single "caller location"
/// (the definition of the function itself).
ReifyShim(DefId), ReifyShim(DefId),


/// `<fn() as FnTrait>::call_*` /// `<fn() as FnTrait>::call_*`
Expand Down Expand Up @@ -194,7 +199,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
write!(f, " - intrinsic") write!(f, " - intrinsic")
} }
InstanceDef::Virtual(_, num) => { InstanceDef::Virtual(_, num) => {
write!(f, " - shim(#{})", num) write!(f, " - virtual#{}", num)
} }
InstanceDef::FnPtrShim(_, ty) => { InstanceDef::FnPtrShim(_, ty) => {
write!(f, " - shim({:?})", ty) write!(f, " - shim({:?})", ty)
Expand Down Expand Up @@ -309,20 +314,23 @@ impl<'tcx> Instance<'tcx> {
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> { ) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| {
let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
.contains(CodegenFnAttrFlags::TRACK_CALLER); .contains(CodegenFnAttrFlags::TRACK_CALLER);


match resolved.def { match resolved.def {
InstanceDef::Item(def_id) if has_track_caller(def_id) => { InstanceDef::Item(def_id) if has_track_caller(def_id) => {
debug!(" => fn pointer created for function with #[track_caller]"); debug!(" => fn pointer created for function with #[track_caller]");
Instance { resolved.def = InstanceDef::ReifyShim(def_id);
def: InstanceDef::ReifyShim(def_id), }
substs, InstanceDef::Virtual(def_id, _) => {
} debug!(" => fn pointer created for virtual call");
}, resolved.def = InstanceDef::ReifyShim(def_id);
_ => resolved, }
_ => {}
} }

resolved
}) })
} }


Expand Down
16 changes: 7 additions & 9 deletions src/librustc_mir/monomorphize/collector.rs
Expand Up @@ -741,23 +741,21 @@ fn visit_instance_use<'tcx>(
} }


match instance.def { match instance.def {
ty::InstanceDef::Intrinsic(def_id) => { ty::InstanceDef::Virtual(..) |
ty::InstanceDef::Intrinsic(_) => {
if !is_direct_call { if !is_direct_call {
bug!("intrinsic {:?} being reified", def_id); bug!("{:?} being reified", instance);
} }
} }
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::Virtual(..) |
ty::InstanceDef::DropGlue(_, None) => { ty::InstanceDef::DropGlue(_, None) => {
// Don't need to emit shim if we are calling directly. // Don't need to emit noop drop glue if we are calling directly.
if !is_direct_call { if !is_direct_call {
output.push(create_fn_mono_item(instance)); output.push(create_fn_mono_item(instance));
} }
} }
ty::InstanceDef::DropGlue(_, Some(_)) => { ty::InstanceDef::DropGlue(_, Some(_)) |
output.push(create_fn_mono_item(instance)); ty::InstanceDef::VtableShim(..) |
} ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::Item(..) | ty::InstanceDef::Item(..) |
ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::FnPtrShim(..) |
Expand Down
11 changes: 7 additions & 4 deletions src/librustc_mir/shim.rs
Expand Up @@ -67,10 +67,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
) )
} }
// We are generating a call back to our def-id, which the // We are generating a call back to our def-id, which the
// codegen backend knows to turn to an actual virtual call. // codegen backend knows to turn to an actual call, be it
ty::InstanceDef::Virtual(def_id, _) | // a virtual call, or a direct call to a function for which
// ...or we are generating a direct call to a function for which indirect calls must be // indirect calls must be codegen'd differently than direct ones
// codegen'd differently than direct ones (example: #[track_caller]) // (such as `#[track_caller]`).
ty::InstanceDef::ReifyShim(def_id) => { ty::InstanceDef::ReifyShim(def_id) => {
build_call_shim( build_call_shim(
tcx, tcx,
Expand Down Expand Up @@ -109,6 +109,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
bug!("builtin clone shim {:?} not supported", instance) bug!("builtin clone shim {:?} not supported", instance)
} }
} }
ty::InstanceDef::Virtual(..) => {
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
}
ty::InstanceDef::Intrinsic(_) => { ty::InstanceDef::Intrinsic(_) => {
bug!("creating shims from intrinsics ({:?}) is unsupported", instance) bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
} }
Expand Down

0 comments on commit 39e50e2

Please sign in to comment.