1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
//! Various utilities to load MIR.
//! Allow to easily load the MIR code generated by a specific pass.
use rustc_hir::def_id::DefId;
use rustc_middle::mir::Body;
use rustc_middle::ty::TyCtxt;
use crate::translate::translate_ctx::MirLevel;
/// Indicates if the constants should be extracted in their own identifier,
/// or if they must be evaluated to a constant value, depending on the
/// MIR level which we extract.
pub fn extract_constants_at_top_level(level: MirLevel) -> bool {
match level {
MirLevel::Built => true,
MirLevel::Promoted => true,
MirLevel::Optimized => false,
}
}
/// Are boxe manipulations desugared to very low-level code using raw pointers,
/// unique and non-null pointers? See [crate::types::TyKind::RawPtr] for detailed explanations.
pub fn boxes_are_desugared(level: MirLevel) -> bool {
match level {
MirLevel::Built => false,
MirLevel::Promoted => false,
MirLevel::Optimized => true,
}
}
/// Query the MIR for a function at a specific level. Return `None` in the case of a foreign body
/// with no MIR available (e.g. because it is not available for inlining).
pub fn get_mir_for_def_id_and_level(
tcx: TyCtxt<'_>,
def_id: DefId,
level: MirLevel,
) -> Option<Body<'_>> {
// Below: we **clone** the bodies to make sure we don't have issues with
// locked values (we had in the past).
if let Some(local_def_id) = def_id.as_local() {
match level {
MirLevel::Built => {
let body = tcx.mir_built(local_def_id);
if !body.is_stolen() {
return Some(body.borrow().clone());
}
}
MirLevel::Promoted => {
let (body, _) = tcx.mir_promoted(local_def_id);
if !body.is_stolen() {
return Some(body.borrow().clone());
}
}
MirLevel::Optimized => {}
}
// We fall back to optimized MIR if the requested body was stolen.
}
// There are only two MIRs we can fetch for non-local bodies: CTFE mir for globals and
// const fns, and optimized MIR for inlinable functions. The rest don't have MIR in the
// rlib.
let body = if tcx.is_mir_available(def_id) {
if let Some(local_def_id) = def_id.as_local()
&& !matches!(
tcx.hir().body_const_context(local_def_id),
None | Some(rustc_hir::ConstContext::ConstFn)
)
{
tcx.mir_for_ctfe(def_id).clone()
} else {
tcx.optimized_mir(def_id).clone()
}
} else if tcx.is_ctfe_mir_available(def_id) {
tcx.mir_for_ctfe(def_id).clone()
} else {
return None;
};
Some(body)
}