about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs45
-rw-r--r--compiler/stable_mir/src/mir/body.rs50
-rw-r--r--compiler/stable_mir/src/mir/visit.rs26
3 files changed, 116 insertions, 5 deletions
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 167a01ab799..e83e301d83b 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -18,7 +18,10 @@ 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;
-use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
+use stable_mir::mir::{
+    Body, ConstOperand, CopyNonOverlapping, Statement, UserTypeProjection, VarDebugInfoFragment,
+    VariantIdx,
+};
 use stable_mir::ty::{
     AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
     FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
@@ -444,10 +447,50 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
                 })
                 .collect(),
             self.arg_count,
+            self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
         )
     }
 }
 
+impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
+    type T = stable_mir::mir::VarDebugInfo;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        stable_mir::mir::VarDebugInfo {
+            name: self.name.to_string(),
+            source_info: stable_mir::mir::SourceInfo {
+                span: self.source_info.span.stable(tables),
+                scope: self.source_info.scope.into(),
+            },
+            composite: {
+                if let Some(composite) = &self.composite {
+                    Some(VarDebugInfoFragment {
+                        ty: composite.ty.stable(tables),
+                        projection: composite.projection.iter().map(|e| e.stable(tables)).collect(),
+                    })
+                } else {
+                    None
+                }
+            },
+            value: {
+                match self.value {
+                    mir::VarDebugInfoContents::Place(place) => {
+                        stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
+                    }
+                    mir::VarDebugInfoContents::Const(const_operand) => {
+                        let op = ConstOperand {
+                            span: const_operand.span.stable(tables),
+                            user_ty: const_operand.user_ty.map(|index| index.as_usize()),
+                            const_: const_operand.const_.stable(tables),
+                        };
+                        stable_mir::mir::VarDebugInfoContents::Const(op)
+                    }
+                }
+            },
+            argument_index: self.argument_index,
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index ac07246dfd3..8d237fc9f1d 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -2,7 +2,7 @@ use crate::mir::pretty::{function_body, pretty_statement};
 use crate::ty::{
     AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
 };
-use crate::{Error, Opaque, Span};
+use crate::{Error, Opaque, Span, Symbol};
 use std::io;
 
 /// The SMIR representation of a single function.
@@ -19,6 +19,9 @@ pub struct Body {
 
     // The number of arguments this function takes.
     pub(super) arg_count: usize,
+
+    // Debug information pertaining to user variables, including captures.
+    pub(super) var_debug_info: Vec<VarDebugInfo>,
 }
 
 impl Body {
@@ -26,14 +29,19 @@ impl Body {
     ///
     /// A constructor is required to build a `Body` from outside the crate
     /// because the `arg_count` and `locals` fields are private.
-    pub fn new(blocks: Vec<BasicBlock>, locals: LocalDecls, arg_count: usize) -> Self {
+    pub fn new(
+        blocks: Vec<BasicBlock>,
+        locals: LocalDecls,
+        arg_count: usize,
+        var_debug_info: Vec<VarDebugInfo>,
+    ) -> 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 }
+        Self { blocks, locals, arg_count, var_debug_info }
     }
 
     /// Return local that holds this function's return value.
@@ -427,6 +435,42 @@ pub struct Place {
     pub projection: Vec<ProjectionElem>,
 }
 
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VarDebugInfo {
+    pub name: Symbol,
+    pub source_info: SourceInfo,
+    pub composite: Option<VarDebugInfoFragment>,
+    pub value: VarDebugInfoContents,
+    pub argument_index: Option<u16>,
+}
+
+pub type SourceScope = u32;
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct SourceInfo {
+    pub span: Span,
+    pub scope: SourceScope,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VarDebugInfoFragment {
+    pub ty: Ty,
+    pub projection: Vec<ProjectionElem>,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum VarDebugInfoContents {
+    Place(Place),
+    Const(ConstOperand),
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ConstOperand {
+    pub span: Span,
+    pub user_ty: Option<UserTypeAnnotationIndex>,
+    pub const_: Const,
+}
+
 // In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This
 // is so it can be used for both Places (for which the projection elements are of type
 // ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index 40bedd67352..488363d6a7f 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -128,8 +128,12 @@ pub trait MirVisitor {
         self.super_assert_msg(msg, location)
     }
 
+    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
+        self.super_var_debug_info(var_debug_info);
+    }
+
     fn super_body(&mut self, body: &Body) {
-        let Body { blocks, locals: _, arg_count } = body;
+        let Body { blocks, locals: _, arg_count, var_debug_info } = body;
 
         for bb in blocks {
             self.visit_basic_block(bb);
@@ -145,6 +149,10 @@ pub trait MirVisitor {
         for (idx, arg) in body.inner_locals().iter().enumerate() {
             self.visit_local_decl(idx + local_start, arg)
         }
+
+        for info in var_debug_info.iter() {
+            self.visit_var_debug_info(info);
+        }
     }
 
     fn super_basic_block(&mut self, bb: &BasicBlock) {
@@ -382,6 +390,22 @@ pub trait MirVisitor {
         let _ = args;
     }
 
+    fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
+        self.visit_span(&var_debug_info.source_info.span);
+        let location = Location(var_debug_info.source_info.span);
+        if let Some(composite) = &var_debug_info.composite {
+            self.visit_ty(&composite.ty, location);
+        }
+        match &var_debug_info.value {
+            VarDebugInfoContents::Place(place) => {
+                self.visit_place(place, PlaceContext::NON_USE, location);
+            }
+            VarDebugInfoContents::Const(constant) => {
+                self.visit_const(&constant.const_, location);
+            }
+        }
+    }
+
     fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) {
         match msg {
             AssertMessage::BoundsCheck { len, index } => {