about summary refs log tree commit diff
path: root/compiler/stable_mir/src/mir
diff options
context:
space:
mode:
authorCelina G. Val <celinval@amazon.com>2023-11-16 06:24:53 -0800
committerCelina G. Val <celinval@amazon.com>2023-11-20 12:43:39 -0800
commitd3fa6a0e352d979aadb56e2f260b96ecc6169d12 (patch)
tree6bb055390dfb549d1da89c0c678317ac67bfeac2 /compiler/stable_mir/src/mir
parent46ecc10c6951a2a0e52d93fe5d3acae9743e3ab9 (diff)
downloadrust-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.rs77
-rw-r--r--compiler/stable_mir/src/mir/mono.rs13
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 {