Skip to content

Commit 29b6e0f

Browse files
committed
Auto merge of #65182 - anp:reify-shim, r=eddyb
Add `Instance::resolve_for_fn_ptr` (RFC 2091 #2/N) Supercedes: #65082 Depends on: #65037 Tracking issue: #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
2 parents 3da6836 + 19f26fa commit 29b6e0f

File tree

11 files changed

+86
-10
lines changed

11 files changed

+86
-10
lines changed

src/librustc/mir/mono.rs

+1
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ impl<'tcx> CodegenUnit<'tcx> {
386386
tcx.hir().as_local_hir_id(def_id)
387387
}
388388
InstanceDef::VtableShim(..) |
389+
InstanceDef::ReifyShim(..) |
389390
InstanceDef::Intrinsic(..) |
390391
InstanceDef::FnPtrShim(..) |
391392
InstanceDef::Virtual(..) |

src/librustc/ty/instance.rs

+37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::hir::CodegenFnAttrFlags;
12
use crate::hir::Unsafety;
23
use crate::hir::def::Namespace;
34
use crate::hir::def_id::DefId;
@@ -25,6 +26,14 @@ pub enum InstanceDef<'tcx> {
2526
/// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
2627
VtableShim(DefId),
2728

29+
/// `fn()` pointer where the function itself cannot be turned into a pointer.
30+
///
31+
/// One example in the compiler today is functions annotated with `#[track_caller]`, which
32+
/// must have their implicit caller location argument populated for a call. Because this is a
33+
/// required part of the function's ABI but can't be tracked as a property of the function
34+
/// pointer, we create a single "caller location" at the site where the function is reified.
35+
ReifyShim(DefId),
36+
2837
/// `<fn() as FnTrait>::call_*`
2938
/// `DefId` is `FnTrait::call_*`
3039
FnPtrShim(DefId, Ty<'tcx>),
@@ -123,6 +132,7 @@ impl<'tcx> InstanceDef<'tcx> {
123132
match *self {
124133
InstanceDef::Item(def_id) |
125134
InstanceDef::VtableShim(def_id) |
135+
InstanceDef::ReifyShim(def_id) |
126136
InstanceDef::FnPtrShim(def_id, _) |
127137
InstanceDef::Virtual(def_id, _) |
128138
InstanceDef::Intrinsic(def_id, ) |
@@ -178,6 +188,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
178188
InstanceDef::VtableShim(_) => {
179189
write!(f, " - shim(vtable)")
180190
}
191+
InstanceDef::ReifyShim(_) => {
192+
write!(f, " - shim(reify)")
193+
}
181194
InstanceDef::Intrinsic(_) => {
182195
write!(f, " - intrinsic")
183196
}
@@ -290,6 +303,30 @@ impl<'tcx> Instance<'tcx> {
290303
result
291304
}
292305

306+
pub fn resolve_for_fn_ptr(
307+
tcx: TyCtxt<'tcx>,
308+
param_env: ty::ParamEnv<'tcx>,
309+
def_id: DefId,
310+
substs: SubstsRef<'tcx>,
311+
) -> Option<Instance<'tcx>> {
312+
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
313+
Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| {
314+
let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
315+
.contains(CodegenFnAttrFlags::TRACK_CALLER);
316+
317+
match resolved.def {
318+
InstanceDef::Item(def_id) if has_track_caller(def_id) => {
319+
debug!(" => fn pointer created for function with #[track_caller]");
320+
Instance {
321+
def: InstanceDef::ReifyShim(def_id),
322+
substs,
323+
}
324+
},
325+
_ => resolved,
326+
}
327+
})
328+
}
329+
293330
pub fn resolve_for_vtable(
294331
tcx: TyCtxt<'tcx>,
295332
param_env: ty::ParamEnv<'tcx>,

src/librustc/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,7 @@ impl<'tcx> TyCtxt<'tcx> {
30263026
self.optimized_mir(did)
30273027
}
30283028
ty::InstanceDef::VtableShim(..) |
3029+
ty::InstanceDef::ReifyShim(..) |
30293030
ty::InstanceDef::Intrinsic(..) |
30303031
ty::InstanceDef::FnPtrShim(..) |
30313032
ty::InstanceDef::Virtual(..) |

src/librustc/ty/structural_impls.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
761761
Some(ty::InstanceDef::Item(def_id)),
762762
ty::InstanceDef::VtableShim(def_id) =>
763763
Some(ty::InstanceDef::VtableShim(def_id)),
764+
ty::InstanceDef::ReifyShim(def_id) =>
765+
Some(ty::InstanceDef::ReifyShim(def_id)),
764766
ty::InstanceDef::Intrinsic(def_id) =>
765767
Some(ty::InstanceDef::Intrinsic(def_id)),
766768
ty::InstanceDef::FnPtrShim(def_id, ref ty) =>
@@ -966,6 +968,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
966968
def: match self.def {
967969
Item(did) => Item(did.fold_with(folder)),
968970
VtableShim(did) => VtableShim(did.fold_with(folder)),
971+
ReifyShim(did) => ReifyShim(did.fold_with(folder)),
969972
Intrinsic(did) => Intrinsic(did.fold_with(folder)),
970973
FnPtrShim(did, ty) => FnPtrShim(
971974
did.fold_with(folder),
@@ -994,7 +997,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
994997
use crate::ty::InstanceDef::*;
995998
self.substs.visit_with(visitor) ||
996999
match self.def {
997-
Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => {
1000+
Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
9981001
did.visit_with(visitor)
9991002
},
10001003
FnPtrShim(did, ty) | CloneShim(did, ty) => {

src/librustc_codegen_ssa/callee.rs

+17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@ pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
1818
)
1919
}
2020

21+
pub fn resolve_and_get_fn_for_ptr<'tcx,
22+
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
23+
>(
24+
cx: &Cx,
25+
def_id: DefId,
26+
substs: SubstsRef<'tcx>,
27+
) -> Cx::Value {
28+
cx.get_fn(
29+
ty::Instance::resolve_for_fn_ptr(
30+
cx.tcx(),
31+
ty::ParamEnv::reveal_all(),
32+
def_id,
33+
substs
34+
).unwrap()
35+
)
36+
}
37+
2138
pub fn resolve_and_get_fn_for_vtable<'tcx,
2239
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
2340
>(

src/librustc_codegen_ssa/mir/rvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
190190
bug!("reifying a fn ptr that requires const arguments");
191191
}
192192
OperandValue::Immediate(
193-
callee::resolve_and_get_fn(bx.cx(), def_id, substs))
193+
callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs))
194194
}
195195
_ => {
196196
bug!("{} cannot be reified to a fn ptr", operand.layout.ty)

src/librustc_mir/interpret/cast.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
4444
if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
4545
bug!("reifying a fn ptr that requires const arguments");
4646
}
47-
let instance = self.resolve(def_id, substs)?;
47+
48+
let instance = ty::Instance::resolve_for_fn_ptr(
49+
*self.tcx,
50+
self.param_env,
51+
def_id,
52+
substs,
53+
).ok_or_else(|| err_inval!(TooGeneric))?;
54+
4855
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
4956
self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
5057
}

src/librustc_mir/interpret/terminator.rs

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
263263
Ok(())
264264
}
265265
ty::InstanceDef::VtableShim(..) |
266+
ty::InstanceDef::ReifyShim(..) |
266267
ty::InstanceDef::ClosureOnceShim { .. } |
267268
ty::InstanceDef::FnPtrShim(..) |
268269
ty::InstanceDef::DropGlue(..) |

src/librustc_mir/monomorphize/collector.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -721,10 +721,12 @@ fn visit_fn_use<'tcx>(
721721
output: &mut Vec<MonoItem<'tcx>>,
722722
) {
723723
if let ty::FnDef(def_id, substs) = ty.kind {
724-
let instance = ty::Instance::resolve(tcx,
725-
ty::ParamEnv::reveal_all(),
726-
def_id,
727-
substs).unwrap();
724+
let resolver = if is_direct_call {
725+
ty::Instance::resolve
726+
} else {
727+
ty::Instance::resolve_for_fn_ptr
728+
};
729+
let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
728730
visit_instance_use(tcx, instance, is_direct_call, output);
729731
}
730732
}
@@ -747,6 +749,7 @@ fn visit_instance_use<'tcx>(
747749
}
748750
}
749751
ty::InstanceDef::VtableShim(..) |
752+
ty::InstanceDef::ReifyShim(..) |
750753
ty::InstanceDef::Virtual(..) |
751754
ty::InstanceDef::DropGlue(_, None) => {
752755
// 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
773776
let def_id = match instance.def {
774777
ty::InstanceDef::Item(def_id) => def_id,
775778
ty::InstanceDef::VtableShim(..) |
779+
ty::InstanceDef::ReifyShim(..) |
776780
ty::InstanceDef::ClosureOnceShim { .. } |
777781
ty::InstanceDef::Virtual(..) |
778782
ty::InstanceDef::FnPtrShim(..) |

src/librustc_mir/monomorphize/partitioning.rs

+2
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ fn mono_item_visibility(
339339

340340
// These are all compiler glue and such, never exported, always hidden.
341341
InstanceDef::VtableShim(..) |
342+
InstanceDef::ReifyShim(..) |
342343
InstanceDef::FnPtrShim(..) |
343344
InstanceDef::Virtual(..) |
344345
InstanceDef::Intrinsic(..) |
@@ -677,6 +678,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
677678
let def_id = match instance.def {
678679
ty::InstanceDef::Item(def_id) => def_id,
679680
ty::InstanceDef::VtableShim(..) |
681+
ty::InstanceDef::ReifyShim(..) |
680682
ty::InstanceDef::FnPtrShim(..) |
681683
ty::InstanceDef::ClosureOnceShim { .. } |
682684
ty::InstanceDef::Intrinsic(..) |

src/librustc_mir/shim.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
6666
Some(arg_tys)
6767
)
6868
}
69-
ty::InstanceDef::Virtual(def_id, _) => {
70-
// We are generating a call back to our def-id, which the
71-
// codegen backend knows to turn to an actual virtual call.
69+
// We are generating a call back to our def-id, which the
70+
// codegen backend knows to turn to an actual virtual call.
71+
ty::InstanceDef::Virtual(def_id, _) |
72+
// ...or we are generating a direct call to a function for which indirect calls must be
73+
// codegen'd differently than direct ones (example: #[track_caller])
74+
ty::InstanceDef::ReifyShim(def_id) => {
7275
build_call_shim(
7376
tcx,
7477
def_id,

0 commit comments

Comments
 (0)