2024-03-15 21:06:40 +01:00
|
|
|
use rustc_middle::mir::visit::Visitor;
|
2024-09-03 15:45:27 +10:00
|
|
|
use rustc_middle::mir::{self, Location, MentionedItem};
|
2024-03-20 11:16:11 +01:00
|
|
|
use rustc_middle::ty::adjustment::PointerCoercion;
|
|
|
|
use rustc_middle::ty::{self, TyCtxt};
|
2024-03-15 21:06:40 +01:00
|
|
|
use rustc_session::Session;
|
|
|
|
use rustc_span::source_map::Spanned;
|
|
|
|
|
2024-08-28 09:39:59 +10:00
|
|
|
pub(super) struct MentionedItems;
|
2024-03-15 21:06:40 +01:00
|
|
|
|
|
|
|
struct MentionedItemsVisitor<'a, 'tcx> {
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
body: &'a mir::Body<'tcx>,
|
2024-09-04 13:47:26 +10:00
|
|
|
mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>,
|
2024-03-15 21:06:40 +01:00
|
|
|
}
|
|
|
|
|
2024-09-03 15:45:27 +10:00
|
|
|
impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
|
2024-03-15 21:06:40 +01:00
|
|
|
fn is_enabled(&self, _sess: &Session) -> bool {
|
|
|
|
// If this pass is skipped the collector assume that nothing got mentioned! We could
|
|
|
|
// potentially skip it in opt-level 0 if we are sure that opt-level will never *remove* uses
|
|
|
|
// of anything, but that still seems fragile. Furthermore, even debug builds use level 1, so
|
|
|
|
// special-casing level 0 is just not worth it.
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
|
2024-09-04 13:47:26 +10:00
|
|
|
let mut visitor = MentionedItemsVisitor { tcx, body, mentioned_items: Vec::new() };
|
|
|
|
visitor.visit_body(body);
|
|
|
|
body.set_mentioned_items(visitor.mentioned_items);
|
2024-03-15 21:06:40 +01:00
|
|
|
}
|
2024-12-09 19:34:51 +00:00
|
|
|
|
|
|
|
fn is_required(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
2024-03-15 21:06:40 +01:00
|
|
|
}
|
|
|
|
|
2024-03-18 11:36:53 +01:00
|
|
|
// This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are
|
|
|
|
// visiting the exact same places but then instead of monomorphizing and creating `MonoItems`, we
|
|
|
|
// have to remain generic and just recording the relevant information in `mentioned_items`, where it
|
|
|
|
// will then be monomorphized later during "mentioned items" collection.
|
2024-03-15 21:06:40 +01:00
|
|
|
impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|
|
|
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
|
|
|
|
self.super_terminator(terminator, location);
|
2024-03-18 11:36:53 +01:00
|
|
|
let span = || self.body.source_info(location).span;
|
|
|
|
match &terminator.kind {
|
2024-02-15 19:54:37 +00:00
|
|
|
mir::TerminatorKind::Call { func, .. } | mir::TerminatorKind::TailCall { func, .. } => {
|
2024-03-18 11:36:53 +01:00
|
|
|
let callee_ty = func.ty(self.body, self.tcx);
|
|
|
|
self.mentioned_items
|
|
|
|
.push(Spanned { node: MentionedItem::Fn(callee_ty), span: span() });
|
|
|
|
}
|
2024-03-15 21:06:40 +01:00
|
|
|
mir::TerminatorKind::Drop { place, .. } => {
|
|
|
|
let ty = place.ty(self.body, self.tcx).ty;
|
2024-03-18 11:36:53 +01:00
|
|
|
self.mentioned_items.push(Spanned { node: MentionedItem::Drop(ty), span: span() });
|
|
|
|
}
|
|
|
|
mir::TerminatorKind::InlineAsm { ref operands, .. } => {
|
|
|
|
for op in operands {
|
|
|
|
match *op {
|
|
|
|
mir::InlineAsmOperand::SymFn { ref value } => {
|
|
|
|
self.mentioned_items.push(Spanned {
|
|
|
|
node: MentionedItem::Fn(value.const_.ty()),
|
|
|
|
span: span(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2024-03-15 21:06:40 +01:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2024-03-17 13:28:31 +01:00
|
|
|
|
|
|
|
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
|
|
|
|
self.super_rvalue(rvalue, location);
|
2024-03-18 11:36:53 +01:00
|
|
|
let span = || self.body.source_info(location).span;
|
2024-03-17 13:28:31 +01:00
|
|
|
match *rvalue {
|
|
|
|
// We need to detect unsizing casts that required vtables.
|
|
|
|
mir::Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
|
|
|
|
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
|
2024-03-17 13:28:31 +01:00
|
|
|
ref operand,
|
|
|
|
target_ty,
|
2024-09-15 16:47:42 +02:00
|
|
|
) => {
|
2024-03-18 11:36:53 +01:00
|
|
|
// This isn't monomorphized yet so we can't tell what the actual types are -- just
|
2024-03-20 11:16:11 +01:00
|
|
|
// add everything that may involve a vtable.
|
|
|
|
let source_ty = operand.ty(self.body, self.tcx);
|
|
|
|
let may_involve_vtable = match (
|
2024-05-09 22:45:14 -04:00
|
|
|
source_ty.builtin_deref(true).map(|t| t.kind()),
|
|
|
|
target_ty.builtin_deref(true).map(|t| t.kind()),
|
2024-03-20 11:16:11 +01:00
|
|
|
) {
|
2024-08-28 08:24:10 +10:00
|
|
|
// &str/&[T] unsizing
|
|
|
|
(Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false,
|
|
|
|
|
2024-03-20 11:16:11 +01:00
|
|
|
_ => true,
|
|
|
|
};
|
|
|
|
if may_involve_vtable {
|
|
|
|
self.mentioned_items.push(Spanned {
|
|
|
|
node: MentionedItem::UnsizeCast { source_ty, target_ty },
|
|
|
|
span: span(),
|
|
|
|
});
|
|
|
|
}
|
2024-03-17 13:28:31 +01:00
|
|
|
}
|
2024-03-17 13:42:54 +01:00
|
|
|
// Similarly, record closures that are turned into function pointers.
|
|
|
|
mir::Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
|
2024-03-17 13:42:54 +01:00
|
|
|
ref operand,
|
|
|
|
_,
|
|
|
|
) => {
|
|
|
|
let source_ty = operand.ty(self.body, self.tcx);
|
2024-03-18 11:36:53 +01:00
|
|
|
self.mentioned_items
|
|
|
|
.push(Spanned { node: MentionedItem::Closure(source_ty), span: span() });
|
|
|
|
}
|
|
|
|
// And finally, function pointer reification casts.
|
|
|
|
mir::Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
|
2024-03-18 11:36:53 +01:00
|
|
|
ref operand,
|
|
|
|
_,
|
|
|
|
) => {
|
|
|
|
let fn_ty = operand.ty(self.body, self.tcx);
|
|
|
|
self.mentioned_items.push(Spanned { node: MentionedItem::Fn(fn_ty), span: span() });
|
2024-03-17 13:42:54 +01:00
|
|
|
}
|
2024-03-17 13:28:31 +01:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2024-03-15 21:06:40 +01:00
|
|
|
}
|