Skip to content

Commit

Permalink
Auto merge of rust-lang#65182 - anp:reify-shim, r=eddyb
Browse files Browse the repository at this point in the history
Add `Instance::resolve_for_fn_ptr` (RFC 2091 #2/N)

Supercedes: rust-lang#65082
Depends on: rust-lang#65037
Tracking issue: rust-lang#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 rust-lang#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
  • Loading branch information
bors committed Oct 13, 2019
2 parents 3da6836 + 19f26fa commit 29b6e0f
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/librustc/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down
37 changes: 37 additions & 0 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::hir::CodegenFnAttrFlags;
use crate::hir::Unsafety;
use crate::hir::def::Namespace;
use crate::hir::def_id::DefId;
Expand Down Expand Up @@ -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>),
Expand Down Expand Up @@ -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, ) |
Expand Down Expand Up @@ -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")
}
Expand Down Expand Up @@ -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>,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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) => {
Expand Down
17 changes: 17 additions & 0 deletions src/librustc_codegen_ssa/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
>(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down
12 changes: 8 additions & 4 deletions src/librustc_mir/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand All @@ -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.
Expand All @@ -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(..) |
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/monomorphize/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down Expand Up @@ -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(..) |
Expand Down
9 changes: 6 additions & 3 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 29b6e0f

Please sign in to comment.