diff options
| author | Celina G. Val <celinval@amazon.com> | 2023-11-16 06:24:53 -0800 |
|---|---|---|
| committer | Celina G. Val <celinval@amazon.com> | 2023-11-20 12:43:39 -0800 |
| commit | d3fa6a0e352d979aadb56e2f260b96ecc6169d12 (patch) | |
| tree | 6bb055390dfb549d1da89c0c678317ac67bfeac2 /compiler/stable_mir/src/mir | |
| parent | 46ecc10c6951a2a0e52d93fe5d3acae9743e3ab9 (diff) | |
| download | rust-d3fa6a0e352d979aadb56e2f260b96ecc6169d12.tar.gz rust-d3fa6a0e352d979aadb56e2f260b96ecc6169d12.zip | |
Add place.ty() and Ty build from a kind to smir
Diffstat (limited to 'compiler/stable_mir/src/mir')
| -rw-r--r-- | compiler/stable_mir/src/mir/body.rs | 77 | ||||
| -rw-r--r-- | compiler/stable_mir/src/mir/mono.rs | 13 |
2 files changed, 73 insertions, 17 deletions
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index fa58a7ffe15..8cdb054de9a 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -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, Span, Opaque}; use std::io; + /// The SMIR representation of a single function. #[derive(Clone, Debug)] pub struct Body { @@ -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, @@ -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, @@ -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()), } } } @@ -666,12 +674,51 @@ 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 => { + let deref_ty = ty + .kind() + .builtin_deref(true) + .ok_or_else(|| error!("Cannot dereference type: {ty:?}"))?; + Ok(deref_ty.ty) + } + ProjectionElem::Field(_idx, fty) => Ok(*fty), + ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => ty + .kind() + .builtin_index() + .ok_or_else(|| error!("Cannot index non-array type: {ty:?}")), + ProjectionElem::Subslice { from, to, from_end } => { + 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:?}`"))), + } + } + ProjectionElem::Downcast(_) => Ok(ty), + ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty), + } + }) } } diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 8562bfd3905..8c43f2c4b8f 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -1,7 +1,7 @@ use crate::mir::Body; use crate::ty::{ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty}; use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque}; -use std::fmt::Debug; +use std::fmt::{Debug, Formatter}; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum MonoItem { @@ -10,7 +10,7 @@ pub enum MonoItem { GlobalAsm(Opaque), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Instance { /// The type of instance. pub kind: InstanceKind, @@ -83,6 +83,15 @@ impl Instance { } } +impl Debug for Instance { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Instance") + .field("kind", &self.kind) + .field("def", &self.mangled_name()) + .finish() + } +} + /// Try to convert a crate item into an instance. /// The item cannot be generic in order to be converted into an instance. impl TryFrom<CrateItem> for Instance { |
