Auto merge of #65182 - anp:reify-shim, r=eddyb
Add `Instance::resolve_for_fn_ptr` (RFC 2091 #2/N) Supercedes: https://github.com/rust-lang/rust/pull/65082 Depends on: https://github.com/rust-lang/rust/pull/65037 Tracking issue: https://github.com/rust-lang/rust/issues/47809 [RFC text](https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md) steps taken: * [x] add a `ReifyShim` that is similar to `VirtualShim` in behavior (see #54183) * [x] add `ty::Instance::resolve_for_fn_ptr` (leave `ty::Instance::resolve_vtable` alone), migrate appropriate callers * [x] `resolve_for_fn_ptr` returns the shim if calling a `#[track_caller]` function
This commit is contained in:
commit
29b6e0f0a1
11 changed files with 86 additions and 10 deletions
|
@ -386,6 +386,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
tcx.hir().as_local_hir_id(def_id)
|
||||
}
|
||||
InstanceDef::VtableShim(..) |
|
||||
InstanceDef::ReifyShim(..) |
|
||||
InstanceDef::Intrinsic(..) |
|
||||
InstanceDef::FnPtrShim(..) |
|
||||
InstanceDef::Virtual(..) |
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::hir::CodegenFnAttrFlags;
|
||||
use crate::hir::Unsafety;
|
||||
use crate::hir::def::Namespace;
|
||||
use crate::hir::def_id::DefId;
|
||||
|
@ -25,6 +26,14 @@ pub enum InstanceDef<'tcx> {
|
|||
/// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
|
||||
VtableShim(DefId),
|
||||
|
||||
/// `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.
|
||||
ReifyShim(DefId),
|
||||
|
||||
/// `<fn() as FnTrait>::call_*`
|
||||
/// `DefId` is `FnTrait::call_*`
|
||||
FnPtrShim(DefId, Ty<'tcx>),
|
||||
|
@ -123,6 +132,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
match *self {
|
||||
InstanceDef::Item(def_id) |
|
||||
InstanceDef::VtableShim(def_id) |
|
||||
InstanceDef::ReifyShim(def_id) |
|
||||
InstanceDef::FnPtrShim(def_id, _) |
|
||||
InstanceDef::Virtual(def_id, _) |
|
||||
InstanceDef::Intrinsic(def_id, ) |
|
||||
|
@ -178,6 +188,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
|
|||
InstanceDef::VtableShim(_) => {
|
||||
write!(f, " - shim(vtable)")
|
||||
}
|
||||
InstanceDef::ReifyShim(_) => {
|
||||
write!(f, " - shim(reify)")
|
||||
}
|
||||
InstanceDef::Intrinsic(_) => {
|
||||
write!(f, " - intrinsic")
|
||||
}
|
||||
|
@ -290,6 +303,30 @@ impl<'tcx> Instance<'tcx> {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn resolve_for_fn_ptr(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
) -> Option<Instance<'tcx>> {
|
||||
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
|
||||
Instance::resolve(tcx, param_env, def_id, substs).map(|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,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_for_vtable(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
|
@ -3026,6 +3026,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.optimized_mir(did)
|
||||
}
|
||||
ty::InstanceDef::VtableShim(..) |
|
||||
ty::InstanceDef::ReifyShim(..) |
|
||||
ty::InstanceDef::Intrinsic(..) |
|
||||
ty::InstanceDef::FnPtrShim(..) |
|
||||
ty::InstanceDef::Virtual(..) |
|
||||
|
|
|
@ -761,6 +761,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
|
|||
Some(ty::InstanceDef::Item(def_id)),
|
||||
ty::InstanceDef::VtableShim(def_id) =>
|
||||
Some(ty::InstanceDef::VtableShim(def_id)),
|
||||
ty::InstanceDef::ReifyShim(def_id) =>
|
||||
Some(ty::InstanceDef::ReifyShim(def_id)),
|
||||
ty::InstanceDef::Intrinsic(def_id) =>
|
||||
Some(ty::InstanceDef::Intrinsic(def_id)),
|
||||
ty::InstanceDef::FnPtrShim(def_id, ref ty) =>
|
||||
|
@ -966,6 +968,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
|
|||
def: match self.def {
|
||||
Item(did) => Item(did.fold_with(folder)),
|
||||
VtableShim(did) => VtableShim(did.fold_with(folder)),
|
||||
ReifyShim(did) => ReifyShim(did.fold_with(folder)),
|
||||
Intrinsic(did) => Intrinsic(did.fold_with(folder)),
|
||||
FnPtrShim(did, ty) => FnPtrShim(
|
||||
did.fold_with(folder),
|
||||
|
@ -994,7 +997,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
|
|||
use crate::ty::InstanceDef::*;
|
||||
self.substs.visit_with(visitor) ||
|
||||
match self.def {
|
||||
Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => {
|
||||
Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
|
||||
did.visit_with(visitor)
|
||||
},
|
||||
FnPtrShim(did, ty) | CloneShim(did, ty) => {
|
||||
|
|
|
@ -18,6 +18,23 @@ pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
|
|||
)
|
||||
}
|
||||
|
||||
pub fn resolve_and_get_fn_for_ptr<'tcx,
|
||||
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
|
||||
>(
|
||||
cx: &Cx,
|
||||
def_id: DefId,
|
||||
substs: SubstsRef<'tcx>,
|
||||
) -> Cx::Value {
|
||||
cx.get_fn(
|
||||
ty::Instance::resolve_for_fn_ptr(
|
||||
cx.tcx(),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
def_id,
|
||||
substs
|
||||
).unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_and_get_fn_for_vtable<'tcx,
|
||||
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
|
||||
>(
|
||||
|
|
|
@ -190,7 +190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bug!("reifying a fn ptr that requires const arguments");
|
||||
}
|
||||
OperandValue::Immediate(
|
||||
callee::resolve_and_get_fn(bx.cx(), def_id, substs))
|
||||
callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs))
|
||||
}
|
||||
_ => {
|
||||
bug!("{} cannot be reified to a fn ptr", operand.layout.ty)
|
||||
|
|
|
@ -44,7 +44,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
|
||||
bug!("reifying a fn ptr that requires const arguments");
|
||||
}
|
||||
let instance = self.resolve(def_id, substs)?;
|
||||
|
||||
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
).ok_or_else(|| err_inval!(TooGeneric))?;
|
||||
|
||||
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
|
||||
self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
|
||||
}
|
||||
|
|
|
@ -263,6 +263,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Ok(())
|
||||
}
|
||||
ty::InstanceDef::VtableShim(..) |
|
||||
ty::InstanceDef::ReifyShim(..) |
|
||||
ty::InstanceDef::ClosureOnceShim { .. } |
|
||||
ty::InstanceDef::FnPtrShim(..) |
|
||||
ty::InstanceDef::DropGlue(..) |
|
||||
|
|
|
@ -721,10 +721,12 @@ fn visit_fn_use<'tcx>(
|
|||
output: &mut Vec<MonoItem<'tcx>>,
|
||||
) {
|
||||
if let ty::FnDef(def_id, substs) = ty.kind {
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
def_id,
|
||||
substs).unwrap();
|
||||
let resolver = if is_direct_call {
|
||||
ty::Instance::resolve
|
||||
} else {
|
||||
ty::Instance::resolve_for_fn_ptr
|
||||
};
|
||||
let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
|
||||
visit_instance_use(tcx, instance, is_direct_call, output);
|
||||
}
|
||||
}
|
||||
|
@ -747,6 +749,7 @@ fn visit_instance_use<'tcx>(
|
|||
}
|
||||
}
|
||||
ty::InstanceDef::VtableShim(..) |
|
||||
ty::InstanceDef::ReifyShim(..) |
|
||||
ty::InstanceDef::Virtual(..) |
|
||||
ty::InstanceDef::DropGlue(_, None) => {
|
||||
// don't need to emit shim if we are calling directly.
|
||||
|
@ -773,6 +776,7 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx
|
|||
let def_id = match instance.def {
|
||||
ty::InstanceDef::Item(def_id) => def_id,
|
||||
ty::InstanceDef::VtableShim(..) |
|
||||
ty::InstanceDef::ReifyShim(..) |
|
||||
ty::InstanceDef::ClosureOnceShim { .. } |
|
||||
ty::InstanceDef::Virtual(..) |
|
||||
ty::InstanceDef::FnPtrShim(..) |
|
||||
|
|
|
@ -339,6 +339,7 @@ fn mono_item_visibility(
|
|||
|
||||
// These are all compiler glue and such, never exported, always hidden.
|
||||
InstanceDef::VtableShim(..) |
|
||||
InstanceDef::ReifyShim(..) |
|
||||
InstanceDef::FnPtrShim(..) |
|
||||
InstanceDef::Virtual(..) |
|
||||
InstanceDef::Intrinsic(..) |
|
||||
|
@ -677,6 +678,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
|
|||
let def_id = match instance.def {
|
||||
ty::InstanceDef::Item(def_id) => def_id,
|
||||
ty::InstanceDef::VtableShim(..) |
|
||||
ty::InstanceDef::ReifyShim(..) |
|
||||
ty::InstanceDef::FnPtrShim(..) |
|
||||
ty::InstanceDef::ClosureOnceShim { .. } |
|
||||
ty::InstanceDef::Intrinsic(..) |
|
||||
|
|
|
@ -66,9 +66,12 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
|||
Some(arg_tys)
|
||||
)
|
||||
}
|
||||
ty::InstanceDef::Virtual(def_id, _) => {
|
||||
// We are generating a call back to our def-id, which the
|
||||
// codegen backend knows to turn to an actual virtual call.
|
||||
// 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])
|
||||
ty::InstanceDef::ReifyShim(def_id) => {
|
||||
build_call_shim(
|
||||
tcx,
|
||||
def_id,
|
||||
|
|
Loading…
Reference in a new issue