Skip to content
Permalink
Browse files

rustc: use ReifyShim for reifying Virtual call instances.

  • Loading branch information
eddyb committed Oct 29, 2019
1 parent 4b68afe commit 39e50e2f289a58a46f46044d8e9d296b9e7ac7e6
Showing with 34 additions and 25 deletions.
  1. +20 −12 src/librustc/ty/instance.rs
  2. +7 −9 src/librustc_mir/monomorphize/collector.rs
  3. +7 −4 src/librustc_mir/shim.rs
@@ -29,10 +29,15 @@ pub enum InstanceDef<'tcx> {

/// `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
/// 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 create a single "caller location" at the site where the function is reified.
/// One example is `<dyn Trait as Trait>::fn`, where the shim contains
/// a virtual call, which codegen supports only via a direct call to the
/// `<dyn Trait as Trait>::fn` instance (an `InstanceDef::Virtual`).
///
/// 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),

/// `<fn() as FnTrait>::call_*`
@@ -194,7 +199,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
write!(f, " - intrinsic")
}
InstanceDef::Virtual(_, num) => {
write!(f, " - shim(#{})", num)
write!(f, " - virtual#{}", num)
}
InstanceDef::FnPtrShim(_, ty) => {
write!(f, " - shim({:?})", ty)
@@ -309,20 +314,23 @@ impl<'tcx> Instance<'tcx> {
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
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
.contains(CodegenFnAttrFlags::TRACK_CALLER);

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

resolved
})
}

@@ -741,23 +741,21 @@ fn visit_instance_use<'tcx>(
}

match instance.def {
ty::InstanceDef::Intrinsic(def_id) => {
ty::InstanceDef::Virtual(..) |
ty::InstanceDef::Intrinsic(_) => {
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) => {
// 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 {
output.push(create_fn_mono_item(instance));
}
}
ty::InstanceDef::DropGlue(_, Some(_)) => {
output.push(create_fn_mono_item(instance));
}
ty::InstanceDef::DropGlue(_, Some(_)) |
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::Item(..) |
ty::InstanceDef::FnPtrShim(..) |
@@ -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
// codegen backend knows to turn to an actual virtual call.
ty::InstanceDef::Virtual(def_id, _) |
// ...or we are generating a direct call to a function for which indirect calls must be
// codegen'd differently than direct ones (example: #[track_caller])
// codegen backend knows to turn to an actual call, be it
// a virtual call, or a direct call to a function for which
// indirect calls must be codegen'd differently than direct ones
// (such as `#[track_caller]`).
ty::InstanceDef::ReifyShim(def_id) => {
build_call_shim(
tcx,
@@ -109,6 +109,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
bug!("builtin clone shim {:?} not supported", instance)
}
}
ty::InstanceDef::Virtual(..) => {
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
}
ty::InstanceDef::Intrinsic(_) => {
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
}

0 comments on commit 39e50e2

Please sign in to comment.
You can’t perform that action at this time.