Rollup merge of #123659 - celinval:smir-fix-intrinsic, r=oli-obk
Add support to intrinsics fallback body Before this fix, the call to `body()` would crash, since `has_body()` would return true, but we would try to retrieve the body of an intrinsic which is not allowed. Instead, the `Instance::body()` function will now convert an Intrinsic into an Item before retrieving its body. Note: I also changed how we monomorphize the instance body. Unfortunately, the call still ICE for some shims. r? `@oli-obk`
This commit is contained in:
commit
2b4c581ef9
3 changed files with 152 additions and 34 deletions
|
@ -4,9 +4,10 @@
|
|||
//! monomorphic body using internal representation.
|
||||
//! After that, we convert the internal representation into a stable one.
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::visit::MutVisitor;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
/// Builds a monomorphic body for a given instance.
|
||||
pub struct BodyBuilder<'tcx> {
|
||||
|
@ -16,46 +17,43 @@ pub struct BodyBuilder<'tcx> {
|
|||
|
||||
impl<'tcx> BodyBuilder<'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
|
||||
let instance = match instance.def {
|
||||
// To get the fallback body of an intrinsic, we need to convert it to an item.
|
||||
ty::InstanceDef::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
|
||||
_ => instance,
|
||||
};
|
||||
BodyBuilder { tcx, instance }
|
||||
}
|
||||
|
||||
/// Build a stable monomorphic body for a given instance based on the MIR body.
|
||||
///
|
||||
/// Note that we skip instantiation for static and constants. Trying to do so can cause ICE.
|
||||
///
|
||||
/// We do monomorphize non-generic functions to eval unevaluated constants.
|
||||
/// All constants are also evaluated.
|
||||
pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
|
||||
let mut body = self.tcx.instance_mir(self.instance.def).clone();
|
||||
if self.tcx.def_kind(self.instance.def_id()).is_fn_like() || !self.instance.args.is_empty()
|
||||
let body = tables.tcx.instance_mir(self.instance.def).clone();
|
||||
let mono_body = if !self.instance.args.is_empty()
|
||||
// Without the `generic_const_exprs` feature gate, anon consts in signatures do not
|
||||
// get generic parameters. Which is wrong, but also not a problem without
|
||||
// generic_const_exprs
|
||||
|| self.tcx.def_kind(self.instance.def_id()) != DefKind::AnonConst
|
||||
{
|
||||
self.visit_body(&mut body);
|
||||
}
|
||||
body.stable(tables)
|
||||
}
|
||||
|
||||
fn monomorphize<T>(&self, value: T) -> T
|
||||
where
|
||||
T: ty::TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(value),
|
||||
)
|
||||
let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||
tables.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(body),
|
||||
);
|
||||
self.visit_body(&mut mono_body);
|
||||
mono_body
|
||||
} else {
|
||||
// Already monomorphic.
|
||||
body
|
||||
};
|
||||
mono_body.stable(tables)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
||||
fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, _location: mir::Location) {
|
||||
*ct = self.monomorphize(*ct);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: mir::visit::TyContext) {
|
||||
*ty = self.monomorphize(*ty);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
|
||||
let const_ = self.monomorphize(constant.const_);
|
||||
let const_ = constant.const_;
|
||||
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) {
|
||||
Ok(v) => v,
|
||||
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
|
||||
|
@ -68,10 +66,6 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
|||
self.super_constant(constant, location);
|
||||
}
|
||||
|
||||
fn visit_args(&mut self, args: &mut GenericArgsRef<'tcx>, _: mir::Location) {
|
||||
*args = self.monomorphize(*args);
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue