Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Instance::resolve_for_fn_ptr (RFC 2091 #2/N) #65182

Merged
merged 12 commits into from
Oct 13, 2019
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,
anp marked this conversation as resolved.
Show resolved Hide resolved
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))
anp marked this conversation as resolved.
Show resolved Hide resolved
}
_ => {
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();
anp marked this conversation as resolved.
Show resolved Hide resolved
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