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

Add place.ty() and Ty build from a kind to smir #118015

Merged
merged 2 commits into from
Nov 21, 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
87 changes: 85 additions & 2 deletions compiler/rustc_smir/src/rustc_internal/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
use rustc_span::Symbol;
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
use stable_mir::ty::{
Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, GenericArgKind,
GenericArgs, Region, TraitRef, Ty,
AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, FloatTy,
GenericArgKind, GenericArgs, IntTy, Region, RigidTy, TraitRef, Ty, UintTy,
};
use stable_mir::{AllocId, CrateItem, DefId};

Expand Down Expand Up @@ -63,6 +63,82 @@ impl<'tcx> RustcInternal<'tcx> for Ty {
}
}

impl<'tcx> RustcInternal<'tcx> for RigidTy {
type T = rustc_ty::TyKind<'tcx>;

fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
match self {
RigidTy::Bool => rustc_ty::TyKind::Bool,
RigidTy::Char => rustc_ty::TyKind::Char,
RigidTy::Int(int_ty) => rustc_ty::TyKind::Int(int_ty.internal(tables)),
RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables)),
RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables)),
RigidTy::Never => rustc_ty::TyKind::Never,
RigidTy::Array(ty, cnst) => {
rustc_ty::TyKind::Array(ty.internal(tables), ty_const(cnst, tables))
}
RigidTy::Adt(def, args) => {
rustc_ty::TyKind::Adt(def.internal(tables), args.internal(tables))
}
RigidTy::Str => rustc_ty::TyKind::Str,
RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables)),
RigidTy::RawPtr(..)
| RigidTy::Ref(..)
| RigidTy::Foreign(_)
| RigidTy::FnDef(_, _)
| RigidTy::FnPtr(_)
| RigidTy::Closure(..)
| RigidTy::Coroutine(..)
| RigidTy::CoroutineWitness(..)
| RigidTy::Dynamic(..)
| RigidTy::Tuple(..) => {
todo!()
}
}
}
}

impl<'tcx> RustcInternal<'tcx> for IntTy {
type T = rustc_ty::IntTy;

fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
match self {
IntTy::Isize => rustc_ty::IntTy::Isize,
IntTy::I8 => rustc_ty::IntTy::I8,
IntTy::I16 => rustc_ty::IntTy::I16,
IntTy::I32 => rustc_ty::IntTy::I32,
IntTy::I64 => rustc_ty::IntTy::I64,
IntTy::I128 => rustc_ty::IntTy::I128,
}
}
}

impl<'tcx> RustcInternal<'tcx> for UintTy {
type T = rustc_ty::UintTy;

fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
match self {
UintTy::Usize => rustc_ty::UintTy::Usize,
UintTy::U8 => rustc_ty::UintTy::U8,
UintTy::U16 => rustc_ty::UintTy::U16,
UintTy::U32 => rustc_ty::UintTy::U32,
UintTy::U64 => rustc_ty::UintTy::U64,
UintTy::U128 => rustc_ty::UintTy::U128,
}
}
}

impl<'tcx> RustcInternal<'tcx> for FloatTy {
type T = rustc_ty::FloatTy;

fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
match self {
FloatTy::F32 => rustc_ty::FloatTy::F32,
FloatTy::F64 => rustc_ty::FloatTy::F64,
}
}
}

fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Const<'tcx> {
match constant.internal(tables) {
rustc_middle::mir::Const::Ty(c) => c,
Expand Down Expand Up @@ -183,6 +259,13 @@ impl<'tcx> RustcInternal<'tcx> for ClosureKind {
}
}

impl<'tcx> RustcInternal<'tcx> for AdtDef {
type T = rustc_ty::AdtDef<'tcx>;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
tables.tcx.adt_def(self.0.internal(&mut *tables))
}
}

impl<'tcx, T> RustcInternal<'tcx> for &T
where
T: RustcInternal<'tcx>,
Expand Down
46 changes: 39 additions & 7 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{alloc_range, AllocId};
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, Variance};
use rustc_middle::ty::{self, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, Variance};
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_target::abi::FieldIdx;
use stable_mir::mir::mono::InstanceDef;
Expand All @@ -24,7 +24,7 @@ use stable_mir::ty::{
FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
TyKind, UintTy,
};
use stable_mir::{self, opaque, Context, CrateItem, Filename, ItemKind};
use stable_mir::{self, opaque, Context, CrateItem, Error, Filename, ItemKind};
use std::cell::RefCell;
use tracing::debug;

Expand Down Expand Up @@ -91,13 +91,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
new_item_kind(tables.tcx.def_kind(tables[item.0]))
}

fn is_foreign_item(&self, item: CrateItem) -> bool {
let tables = self.0.borrow();
tables.tcx.is_foreign_item(tables[item.0])
}

fn adt_kind(&self, def: AdtDef) -> AdtKind {
let mut tables = self.0.borrow_mut();
let ty = tables.tcx.type_of(def.0.internal(&mut *tables)).instantiate_identity().kind();
let ty::TyKind::Adt(def, _) = ty else {
panic!("Expected an ADT definition, but found: {ty:?}")
};
def.adt_kind().stable(&mut *tables)
def.internal(&mut *tables).adt_kind().stable(&mut *tables)
}

fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
Expand Down Expand Up @@ -302,6 +303,37 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
let closure_kind = kind.internal(&mut *tables);
Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
}

fn adt_is_box(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
def.internal(&mut *tables).is_box()
}

fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error> {
let mut tables = self.0.borrow_mut();
let mir_const = cnst.internal(&mut *tables);
mir_const
.try_eval_target_usize(tables.tcx, ParamEnv::empty())
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
}

fn usize_to_const(&self, val: u64) -> Result<Const, Error> {
let mut tables = self.0.borrow_mut();
let ty = tables.tcx.types.usize;
let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;

let scalar = ScalarInt::try_from_uint(val, size).ok_or_else(|| {
Error::new(format!("Value overflow: cannot convert `{val}` to usize."))
})?;
Ok(ty::Const::new_value(tables.tcx, ty::ValTree::from_scalar_int(scalar), ty)
.stable(&mut *tables))
}

fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let internal_kind = kind.internal(&mut *tables);
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
}
}

pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
Expand Down
9 changes: 7 additions & 2 deletions compiler/stable_mir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ use std::convert::From;
use std::fmt::{Debug, Display, Formatter};
use std::{error, fmt};

macro_rules! error {
($fmt: literal $(,)?) => { Error(format!($fmt)) };
($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg:tt)*)) };
}

/// An error type used to represent an error that has already been reported by the compiler.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum CompilerError<T> {
Expand All @@ -24,10 +29,10 @@ pub enum CompilerError<T> {

/// A generic error to represent an API request that cannot be fulfilled.
#[derive(Debug)]
pub struct Error(String);
pub struct Error(pub(crate) String);

impl Error {
pub(crate) fn new(msg: String) -> Self {
pub fn new(msg: String) -> Self {
Self(msg)
}
}
Expand Down
20 changes: 18 additions & 2 deletions compiler/stable_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,18 @@ use self::ty::{
#[macro_use]
extern crate scoped_tls;

#[macro_use]
pub mod error;
pub mod mir;
pub mod ty;
pub mod visitor;

use crate::mir::pretty::function_name;
use crate::mir::Mutability;
use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind};
use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind, Const, RigidTy};
pub use error::*;
use mir::mono::Instance;
use ty::{Const, FnDef, GenericArgs};
use ty::{FnDef, GenericArgs};

/// Use String for now but we should replace it.
pub type Symbol = String;
Expand Down Expand Up @@ -224,9 +225,24 @@ pub trait Context {
/// Returns the `kind` of given `DefId`
fn item_kind(&self, item: CrateItem) -> ItemKind;

/// Returns whether this is a foreign item.
fn is_foreign_item(&self, item: CrateItem) -> bool;

/// Returns the kind of a given algebraic data type
fn adt_kind(&self, def: AdtDef) -> AdtKind;

/// Returns if the ADT is a box.
fn adt_is_box(&self, def: AdtDef) -> bool;

/// Evaluate constant as a target usize.
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error>;

/// Create a target usize constant for the given value.
fn usize_to_const(&self, val: u64) -> Result<Const, Error>;

/// Create a new type from the given kind.
fn new_rigid_ty(&self, kind: RigidTy) -> Ty;

/// Returns the type of given crate item.
fn def_ty(&self, item: DefId) -> Ty;

Expand Down
83 changes: 68 additions & 15 deletions compiler/stable_mir/src/mir/body.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::mir::pretty::{function_body, pretty_statement};
use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, Ty};
use crate::Opaque;
use crate::Span;
use crate::ty::{
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
};
use crate::{Error, Opaque, Span};
use std::io;

/// The SMIR representation of a single function.
#[derive(Clone, Debug)]
pub struct Body {
Expand Down Expand Up @@ -561,7 +563,7 @@ pub struct SwitchTarget {
pub target: usize,
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
Shared,
Expand All @@ -579,14 +581,14 @@ pub enum BorrowKind {
},
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MutBorrowKind {
Default,
TwoPhaseBorrow,
ClosureCapture,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Mutability {
Not,
Mut,
Expand Down Expand Up @@ -651,10 +653,16 @@ pub enum NullOp {
}

impl Operand {
pub fn ty(&self, locals: &[LocalDecl]) -> Ty {
/// Get the type of an operand relative to the local declaration.
///
/// In order to retrieve the correct type, the `locals` argument must match the list of all
/// locals from the function body where this operand originates from.
///
/// Errors indicate a malformed operand or incompatible locals list.
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
match self {
Operand::Copy(place) | Operand::Move(place) => place.ty(locals),
Operand::Constant(c) => c.ty(),
Operand::Constant(c) => Ok(c.ty()),
}
}
}
Expand All @@ -666,12 +674,57 @@ impl Constant {
}

impl Place {
// FIXME(klinvill): This function is expected to resolve down the chain of projections to get
// the type referenced at the end of it. E.g. calling `ty()` on `*(_1.f)` should end up
// returning the type referenced by `f`. The information needed to do this may not currently be
// present in Stable MIR since at least an implementation for AdtDef is probably needed.
pub fn ty(&self, locals: &[LocalDecl]) -> Ty {
let _start_ty = locals[self.local].ty;
todo!("Implement projection")
/// Resolve down the chain of projections to get the type referenced at the end of it.
/// E.g.:
/// Calling `ty()` on `var.field` should return the type of `field`.
///
/// In order to retrieve the correct type, the `locals` argument must match the list of all
/// locals from the function body where this place originates from.
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
let start_ty = locals[self.local].ty;
self.projection.iter().fold(Ok(start_ty), |place_ty, elem| {
let ty = place_ty?;
match elem {
ProjectionElem::Deref => Self::deref_ty(ty),
ProjectionElem::Field(_idx, fty) => Ok(*fty),
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
Self::index_ty(ty)
}
ProjectionElem::Subslice { from, to, from_end } => {
Self::subslice_ty(ty, from, to, from_end)
}
ProjectionElem::Downcast(_) => Ok(ty),
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
}
})
}

fn index_ty(ty: Ty) -> Result<Ty, Error> {
ty.kind().builtin_index().ok_or_else(|| error!("Cannot index non-array type: {ty:?}"))
}

fn subslice_ty(ty: Ty, from: &u64, to: &u64, from_end: &bool) -> Result<Ty, Error> {
let ty_kind = ty.kind();
match ty_kind {
TyKind::RigidTy(RigidTy::Slice(..)) => Ok(ty),
TyKind::RigidTy(RigidTy::Array(inner, _)) if !from_end => Ty::try_new_array(
inner,
to.checked_sub(*from).ok_or_else(|| error!("Subslice overflow: {from}..{to}"))?,
),
TyKind::RigidTy(RigidTy::Array(inner, size)) => {
let size = size.eval_target_usize()?;
let len = size - from - to;
Ty::try_new_array(inner, len)
}
_ => Err(Error(format!("Cannot subslice non-array type: `{ty_kind:?}`"))),
}
}

fn deref_ty(ty: Ty) -> Result<Ty, Error> {
let deref_ty = ty
.kind()
.builtin_deref(true)
.ok_or_else(|| error!("Cannot dereference type: {ty:?}"))?;
Ok(deref_ty.ty)
}
}
Loading
Loading