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

Erase late bound regions from Instance::fn_sig() and add a few more details to StableMIR APIs #118927

Merged
merged 4 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

use rustc_middle::ty;
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
use rustc_middle::ty::{GenericPredicates, Instance, ParamEnv, ScalarInt, ValTree};
use rustc_middle::ty::{
GenericPredicates, Instance, ParamEnv, ScalarInt, TypeVisitableExt, ValTree,
};
use rustc_span::def_id::LOCAL_CRATE;
use stable_mir::compiler_interface::Context;
use stable_mir::mir::alloc::GlobalAlloc;
Expand Down Expand Up @@ -324,7 +326,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
instance.ty(tables.tcx, ParamEnv::empty()).stable(&mut *tables)
assert!(!instance.has_non_region_param(), "{instance:?} needs further substitution");
instance.ty(tables.tcx, ParamEnv::reveal_all()).stable(&mut *tables)
celinval marked this conversation as resolved.
Show resolved Hide resolved
}

fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_smir/src/rustc_smir/convert/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
.collect(),
self.arg_count,
self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
self.spread_arg.stable(tables),
)
}
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_smir/src/rustc_smir/convert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
stable_mir::mir::CoroutineKind::Gen(source.stable(tables))
}
CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine,
CoroutineKind::AsyncGen(_) => todo!(),
CoroutineKind::AsyncGen(source) => {
stable_mir::mir::CoroutineKind::AsyncGen(source.stable(tables))
}
}
}
}
Expand Down
69 changes: 68 additions & 1 deletion compiler/stable_mir/src/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ pub struct Body {

/// Debug information pertaining to user variables, including captures.
pub var_debug_info: Vec<VarDebugInfo>,

/// Mark an argument (which must be a tuple) as getting passed as its individual components.
///
/// This is used for the "rust-call" ABI such as closures.
pub(super) spread_arg: Option<Local>,
}

pub type BasicBlockIdx = usize;
Expand All @@ -36,14 +41,15 @@ impl Body {
locals: LocalDecls,
arg_count: usize,
var_debug_info: Vec<VarDebugInfo>,
spread_arg: Option<Local>,
) -> Self {
// If locals doesn't contain enough entries, it can lead to panics in
// `ret_local`, `arg_locals`, and `inner_locals`.
assert!(
locals.len() > arg_count,
"A Body must contain at least a local for the return value and each of the function's arguments"
);
Self { blocks, locals, arg_count, var_debug_info }
Self { blocks, locals, arg_count, var_debug_info, spread_arg }
}

/// Return local that holds this function's return value.
Expand Down Expand Up @@ -75,6 +81,11 @@ impl Body {
self.locals.get(local)
}

/// Get an iterator for all local declarations.
pub fn local_decls(&self) -> impl Iterator<Item = (Local, &LocalDecl)> {
self.locals.iter().enumerate()
}

pub fn dump<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
writeln!(w, "{}", function_body(self))?;
self.blocks
Expand All @@ -98,6 +109,10 @@ impl Body {
.collect::<Result<Vec<_>, _>>()?;
Ok(())
}

pub fn spread_arg(&self) -> Option<Local> {
self.spread_arg
}
}

type LocalDecls = Vec<LocalDecl>;
Expand Down Expand Up @@ -248,6 +263,57 @@ pub enum AssertMessage {
MisalignedPointerDereference { required: Operand, found: Operand },
}

impl AssertMessage {
pub fn description(&self) -> Result<&'static str, Error> {
celinval marked this conversation as resolved.
Show resolved Hide resolved
match self {
AssertMessage::Overflow(BinOp::Add, _, _) => Ok("attempt to add with overflow"),
AssertMessage::Overflow(BinOp::Sub, _, _) => Ok("attempt to subtract with overflow"),
AssertMessage::Overflow(BinOp::Mul, _, _) => Ok("attempt to multiply with overflow"),
AssertMessage::Overflow(BinOp::Div, _, _) => Ok("attempt to divide with overflow"),
AssertMessage::Overflow(BinOp::Rem, _, _) => {
Ok("attempt to calculate the remainder with overflow")
}
AssertMessage::OverflowNeg(_) => Ok("attempt to negate with overflow"),
AssertMessage::Overflow(BinOp::Shr, _, _) => Ok("attempt to shift right with overflow"),
AssertMessage::Overflow(BinOp::Shl, _, _) => Ok("attempt to shift left with overflow"),
AssertMessage::Overflow(op, _, _) => Err(error!("`{:?}` cannot overflow", op)),
AssertMessage::DivisionByZero(_) => Ok("attempt to divide by zero"),
AssertMessage::RemainderByZero(_) => {
Ok("attempt to calculate the remainder with a divisor of zero")
}
AssertMessage::ResumedAfterReturn(CoroutineKind::Coroutine) => {
Ok("coroutine resumed after completion")
}
AssertMessage::ResumedAfterReturn(CoroutineKind::Async(_)) => {
Ok("`async fn` resumed after completion")
}
AssertMessage::ResumedAfterReturn(CoroutineKind::Gen(_)) => {
Ok("`async gen fn` resumed after completion")
}
AssertMessage::ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => {
Ok("`gen fn` should just keep returning `AssertMessage::None` after completion")
}
AssertMessage::ResumedAfterPanic(CoroutineKind::Coroutine) => {
Ok("coroutine resumed after panicking")
}
AssertMessage::ResumedAfterPanic(CoroutineKind::Async(_)) => {
Ok("`async fn` resumed after panicking")
}
AssertMessage::ResumedAfterPanic(CoroutineKind::Gen(_)) => {
Ok("`async gen fn` resumed after panicking")
}
AssertMessage::ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => {
Ok("`gen fn` should just keep returning `AssertMessage::None` after panicking")
}

AssertMessage::BoundsCheck { .. } => Ok("index out of bounds"),
AssertMessage::MisalignedPointerDereference { .. } => {
Ok("misaligned pointer dereference")
}
}
}
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum BinOp {
Add,
Expand Down Expand Up @@ -325,6 +391,7 @@ pub enum CoroutineKind {
Async(CoroutineSource),
Coroutine,
Gen(CoroutineSource),
AsyncGen(CoroutineSource),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Expand Down
7 changes: 1 addition & 6 deletions compiler/stable_mir/src/mir/mono.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::crate_def::CrateDef;
use crate::mir::Body;
use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, FnSig, GenericArgs, IndexedVal, Ty};
use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol};
use std::fmt::{Debug, Formatter};

Expand Down Expand Up @@ -115,11 +115,6 @@ impl Instance {
})
}

/// Get this function signature with all types already instantiated.
pub fn fn_sig(&self) -> FnSig {
self.ty().kind().fn_sig().unwrap().skip_binder()
}

/// Check whether this instance is an empty shim.
///
/// Allow users to check if this shim can be ignored when called directly.
Expand Down
9 changes: 4 additions & 5 deletions compiler/stable_mir/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ pub fn pretty_assert_message(msg: &AssertMessage) -> String {
);
pretty
}
AssertMessage::Overflow(op, _, _) => unreachable!("`{:?}` cannot overflow", op),
AssertMessage::OverflowNeg(op) => {
let pretty_op = pretty_operand(op);
pretty.push_str(
Expand All @@ -262,17 +263,15 @@ pub fn pretty_assert_message(msg: &AssertMessage) -> String {
);
pretty
}
AssertMessage::ResumedAfterReturn(_) => {
format!("attempt to resume a generator after completion")
}
AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"),
AssertMessage::MisalignedPointerDereference { required, found } => {
let pretty_required = pretty_operand(required);
let pretty_found = pretty_operand(found);
pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str());
pretty
}
_ => todo!(),
AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => {
msg.description().unwrap().to_string()
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/stable_mir/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub trait MirVisitor {
}

fn super_body(&mut self, body: &Body) {
let Body { blocks, locals: _, arg_count, var_debug_info } = body;
let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _ } = body;

for bb in blocks {
self.visit_basic_block(bb);
Expand Down
14 changes: 11 additions & 3 deletions compiler/stable_mir/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ impl Debug for Ty {
/// Constructors for `Ty`.
impl Ty {
/// Create a new type from a given kind.
///
/// Note that not all types may be supported at this point.
fn from_rigid_kind(kind: RigidTy) -> Ty {
pub fn from_rigid_kind(kind: RigidTy) -> Ty {
with(|cx| cx.new_rigid_ty(kind))
}

Expand Down Expand Up @@ -77,6 +75,16 @@ impl Ty {
pub fn bool_ty() -> Ty {
Ty::from_rigid_kind(RigidTy::Bool)
}

/// Create a type representing a signed integer.
pub fn signed_ty(inner: IntTy) -> Ty {
Ty::from_rigid_kind(RigidTy::Int(inner))
}

/// Create a type representing an unsigned integer.
pub fn unsigned_ty(inner: UintTy) -> Ty {
Ty::from_rigid_kind(RigidTy::Uint(inner))
}
}

impl Ty {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui-fulldeps/stable-mir/check_defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn extract_elem_ty(ty: Ty) -> Ty {

/// Check signature and type of `Vec::<u8>::new` and its generic version.
fn test_vec_new(instance: mir::mono::Instance) {
let sig = instance.fn_sig();
let sig = instance.ty().kind().fn_sig().unwrap().skip_binder();
assert_matches!(sig.inputs(), &[]);
let elem_ty = extract_elem_ty(sig.output());
assert_matches!(elem_ty.kind(), TyKind::RigidTy(RigidTy::Uint(UintTy::U8)));
Expand Down
Loading