Add VarDebugInfo to Stable MIR
This commit is contained in:
parent
c5af061019
commit
018b85986d
3 changed files with 116 additions and 5 deletions
|
@ -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_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
use rustc_target::abi::FieldIdx;
|
use rustc_target::abi::FieldIdx;
|
||||||
use stable_mir::mir::mono::InstanceDef;
|
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::{
|
use stable_mir::ty::{
|
||||||
AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
|
AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
|
||||||
FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
|
FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
|
||||||
|
@ -444,10 +447,50 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
self.arg_count,
|
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> {
|
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
|
||||||
type T = stable_mir::mir::Statement;
|
type T = stable_mir::mir::Statement;
|
||||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::mir::pretty::{function_body, pretty_statement};
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
|
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use crate::{Error, Opaque, Span};
|
use crate::{Error, Opaque, Span, Symbol};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
/// The SMIR representation of a single function.
|
/// The SMIR representation of a single function.
|
||||||
|
@ -19,6 +19,9 @@ pub struct Body {
|
||||||
|
|
||||||
// The number of arguments this function takes.
|
// The number of arguments this function takes.
|
||||||
pub(super) arg_count: usize,
|
pub(super) arg_count: usize,
|
||||||
|
|
||||||
|
// Debug information pertaining to user variables, including captures.
|
||||||
|
pub(super) var_debug_info: Vec<VarDebugInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Body {
|
impl Body {
|
||||||
|
@ -26,14 +29,19 @@ impl Body {
|
||||||
///
|
///
|
||||||
/// A constructor is required to build a `Body` from outside the crate
|
/// A constructor is required to build a `Body` from outside the crate
|
||||||
/// because the `arg_count` and `locals` fields are private.
|
/// 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
|
// If locals doesn't contain enough entries, it can lead to panics in
|
||||||
// `ret_local`, `arg_locals`, and `inner_locals`.
|
// `ret_local`, `arg_locals`, and `inner_locals`.
|
||||||
assert!(
|
assert!(
|
||||||
locals.len() > arg_count,
|
locals.len() > arg_count,
|
||||||
"A Body must contain at least a local for the return value and each of the function's arguments"
|
"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.
|
/// Return local that holds this function's return value.
|
||||||
|
@ -427,6 +435,42 @@ pub struct Place {
|
||||||
pub projection: Vec<ProjectionElem>,
|
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
|
// 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
|
// 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
|
// ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
|
||||||
|
|
|
@ -128,8 +128,12 @@ pub trait MirVisitor {
|
||||||
self.super_assert_msg(msg, location)
|
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) {
|
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 {
|
for bb in blocks {
|
||||||
self.visit_basic_block(bb);
|
self.visit_basic_block(bb);
|
||||||
|
@ -145,6 +149,10 @@ pub trait MirVisitor {
|
||||||
for (idx, arg) in body.inner_locals().iter().enumerate() {
|
for (idx, arg) in body.inner_locals().iter().enumerate() {
|
||||||
self.visit_local_decl(idx + local_start, arg)
|
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) {
|
fn super_basic_block(&mut self, bb: &BasicBlock) {
|
||||||
|
@ -382,6 +390,22 @@ pub trait MirVisitor {
|
||||||
let _ = args;
|
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) {
|
fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) {
|
||||||
match msg {
|
match msg {
|
||||||
AssertMessage::BoundsCheck { len, index } => {
|
AssertMessage::BoundsCheck { len, index } => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue