Rollup merge of #115540 - cjgillot:custom-debuginfo, r=oli-obk
Support debuginfo for custom MIR.
This commit is contained in:
commit
9381e5bf58
@ -1,5 +1,6 @@
|
|||||||
use rustc_index::IndexSlice;
|
use rustc_index::IndexSlice;
|
||||||
use rustc_middle::{mir::*, thir::*, ty::Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
use rustc_middle::{mir::*, thir::*};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use super::{PResult, ParseCtxt, ParseError};
|
use super::{PResult, ParseCtxt, ParseError};
|
||||||
@ -159,6 +160,14 @@ pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
|
|||||||
);
|
);
|
||||||
self.parse_local_decls(local_decls.iter().copied())?;
|
self.parse_local_decls(local_decls.iter().copied())?;
|
||||||
|
|
||||||
|
let (debuginfo, rest) = parse_by_kind!(self, rest, _, "body with debuginfo",
|
||||||
|
ExprKind::Block { block } => {
|
||||||
|
let block = &self.thir[*block];
|
||||||
|
(&block.stmts, block.expr.unwrap())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
self.parse_debuginfo(debuginfo.iter().copied())?;
|
||||||
|
|
||||||
let block_defs = parse_by_kind!(self, rest, _, "body with block defs",
|
let block_defs = parse_by_kind!(self, rest, _, "body with block defs",
|
||||||
ExprKind::Block { block } => &self.thir[*block].stmts,
|
ExprKind::Block { block } => &self.thir[*block].stmts,
|
||||||
);
|
);
|
||||||
@ -195,6 +204,52 @@ fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PRes
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_debuginfo(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
|
||||||
|
for stmt in stmts {
|
||||||
|
let stmt = &self.thir[stmt];
|
||||||
|
let expr = match stmt.kind {
|
||||||
|
StmtKind::Let { span, .. } => {
|
||||||
|
return Err(ParseError {
|
||||||
|
span,
|
||||||
|
item_description: format!("{:?}", stmt),
|
||||||
|
expected: "debuginfo".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
StmtKind::Expr { expr, .. } => expr,
|
||||||
|
};
|
||||||
|
let span = self.thir[expr].span;
|
||||||
|
let (name, operand) = parse_by_kind!(self, expr, _, "debuginfo",
|
||||||
|
@call("mir_debuginfo", args) => {
|
||||||
|
(args[0], args[1])
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let name = parse_by_kind!(self, name, _, "debuginfo",
|
||||||
|
ExprKind::Literal { lit, neg: false } => lit,
|
||||||
|
);
|
||||||
|
let Some(name) = name.node.str() else {
|
||||||
|
return Err(ParseError {
|
||||||
|
span,
|
||||||
|
item_description: format!("{:?}", name),
|
||||||
|
expected: "string".to_string(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let operand = self.parse_operand(operand)?;
|
||||||
|
let value = match operand {
|
||||||
|
Operand::Constant(c) => VarDebugInfoContents::Const(*c),
|
||||||
|
Operand::Copy(p) | Operand::Move(p) => VarDebugInfoContents::Place(p),
|
||||||
|
};
|
||||||
|
let dbginfo = VarDebugInfo {
|
||||||
|
name,
|
||||||
|
source_info: SourceInfo { span, scope: self.source_scope },
|
||||||
|
argument_index: None,
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
self.body.var_debug_info.push(dbginfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
|
fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
|
||||||
let pattern = match &self.thir[stmt_id].kind {
|
let pattern = match &self.thir[stmt_id].kind {
|
||||||
StmtKind::Let { pattern, .. } => pattern,
|
StmtKind::Let { pattern, .. } => pattern,
|
||||||
|
@ -204,7 +204,7 @@ fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
|
pub fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
|
||||||
parse_by_kind!(self, expr_id, expr, "operand",
|
parse_by_kind!(self, expr_id, expr, "operand",
|
||||||
@call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
|
@call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
|
||||||
@call("mir_static", args) => self.parse_static(args[0]),
|
@call("mir_static", args) => self.parse_static(args[0]),
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
//!
|
//!
|
||||||
//! Typical usage will look like this:
|
//! Typical usage will look like this:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
#![cfg_attr(bootstrap, doc = "```rust,ignore")]
|
||||||
|
#![cfg_attr(not(bootstrap), doc = "```rust")]
|
||||||
//! #![feature(core_intrinsics, custom_mir)]
|
//! #![feature(core_intrinsics, custom_mir)]
|
||||||
//! #![allow(internal_features)]
|
//! #![allow(internal_features)]
|
||||||
//!
|
//!
|
||||||
@ -62,7 +63,8 @@
|
|||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
#![cfg_attr(bootstrap, doc = "```rust,ignore")]
|
||||||
|
#![cfg_attr(not(bootstrap), doc = "```rust")]
|
||||||
//! #![feature(core_intrinsics, custom_mir)]
|
//! #![feature(core_intrinsics, custom_mir)]
|
||||||
//! #![allow(internal_features)]
|
//! #![allow(internal_features)]
|
||||||
//!
|
//!
|
||||||
@ -317,7 +319,8 @@ fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discrim
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
#[cfg_attr(bootstrap, doc = "```rust,ignore")]
|
||||||
|
#[cfg_attr(not(bootstrap), doc = "```rust")]
|
||||||
/// #![allow(internal_features)]
|
/// #![allow(internal_features)]
|
||||||
/// #![feature(custom_mir, core_intrinsics)]
|
/// #![feature(custom_mir, core_intrinsics)]
|
||||||
///
|
///
|
||||||
@ -361,6 +364,11 @@ fn CastTransmute<T, U>(operand: T) -> U
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn __internal_make_place<T>(place: T) -> *mut T
|
fn __internal_make_place<T>(place: T) -> *mut T
|
||||||
);
|
);
|
||||||
|
define!(
|
||||||
|
"mir_debuginfo",
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn __debuginfo<T>(name: &'static str, s: T)
|
||||||
|
);
|
||||||
|
|
||||||
/// Macro for generating custom MIR.
|
/// Macro for generating custom MIR.
|
||||||
///
|
///
|
||||||
@ -371,6 +379,7 @@ fn __internal_make_place<T>(place: T) -> *mut T
|
|||||||
(
|
(
|
||||||
$(type RET = $ret_ty:ty ;)?
|
$(type RET = $ret_ty:ty ;)?
|
||||||
$(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
|
$(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
|
||||||
|
$(debug $dbg_name:ident => $dbg_data:expr ;)*
|
||||||
|
|
||||||
{
|
{
|
||||||
$($entry:tt)*
|
$($entry:tt)*
|
||||||
@ -394,26 +403,32 @@ fn __internal_make_place<T>(place: T) -> *mut T
|
|||||||
$(
|
$(
|
||||||
let $local_decl $(: $local_decl_ty)? ;
|
let $local_decl $(: $local_decl_ty)? ;
|
||||||
)*
|
)*
|
||||||
|
|
||||||
::core::intrinsics::mir::__internal_extract_let!($($entry)*);
|
::core::intrinsics::mir::__internal_extract_let!($($entry)*);
|
||||||
$(
|
$(
|
||||||
::core::intrinsics::mir::__internal_extract_let!($($block)*);
|
::core::intrinsics::mir::__internal_extract_let!($($block)*);
|
||||||
)*
|
)*
|
||||||
|
|
||||||
{
|
{
|
||||||
// Finally, the contents of the basic blocks
|
// Now debuginfo
|
||||||
::core::intrinsics::mir::__internal_remove_let!({
|
|
||||||
{}
|
|
||||||
{ $($entry)* }
|
|
||||||
});
|
|
||||||
$(
|
$(
|
||||||
::core::intrinsics::mir::__internal_remove_let!({
|
__debuginfo(stringify!($dbg_name), $dbg_data);
|
||||||
{}
|
|
||||||
{ $($block)* }
|
|
||||||
});
|
|
||||||
)*
|
)*
|
||||||
|
|
||||||
RET
|
{
|
||||||
|
// Finally, the contents of the basic blocks
|
||||||
|
::core::intrinsics::mir::__internal_remove_let!({
|
||||||
|
{}
|
||||||
|
{ $($entry)* }
|
||||||
|
});
|
||||||
|
$(
|
||||||
|
::core::intrinsics::mir::__internal_remove_let!({
|
||||||
|
{}
|
||||||
|
{ $($block)* }
|
||||||
|
});
|
||||||
|
)*
|
||||||
|
|
||||||
|
RET
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
// MIR for `numbered` after built
|
||||||
|
|
||||||
|
fn numbered(_1: (u32, i32)) -> () {
|
||||||
|
debug first => (_1.0: u32);
|
||||||
|
debug second => (_1.0: u32);
|
||||||
|
let mut _0: ();
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// MIR for `pointee` after built
|
||||||
|
|
||||||
|
fn pointee(_1: &mut Option<i32>) -> () {
|
||||||
|
debug foo => (((*_1) as variant#1).0: i32);
|
||||||
|
let mut _0: ();
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
71
tests/mir-opt/building/custom/debuginfo.rs
Normal file
71
tests/mir-opt/building/custom/debuginfo.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#![feature(custom_mir, core_intrinsics)]
|
||||||
|
|
||||||
|
extern crate core;
|
||||||
|
use core::intrinsics::mir::*;
|
||||||
|
|
||||||
|
// EMIT_MIR debuginfo.pointee.built.after.mir
|
||||||
|
#[custom_mir(dialect = "built")]
|
||||||
|
fn pointee(opt: &mut Option<i32>) {
|
||||||
|
mir!(
|
||||||
|
debug foo => Field::<i32>(Variant(*opt, 1), 0);
|
||||||
|
{
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR debuginfo.numbered.built.after.mir
|
||||||
|
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
|
||||||
|
fn numbered(i: (u32, i32)) {
|
||||||
|
mir!(
|
||||||
|
debug first => i.0;
|
||||||
|
debug second => i.0;
|
||||||
|
{
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S { x: f32 }
|
||||||
|
|
||||||
|
// EMIT_MIR debuginfo.structured.built.after.mir
|
||||||
|
#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
|
||||||
|
fn structured(i: S) {
|
||||||
|
mir!(
|
||||||
|
debug x => i.x;
|
||||||
|
{
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR debuginfo.variant.built.after.mir
|
||||||
|
#[custom_mir(dialect = "built")]
|
||||||
|
fn variant(opt: Option<i32>) {
|
||||||
|
mir!(
|
||||||
|
debug inner => Field::<i32>(Variant(opt, 1), 0);
|
||||||
|
{
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR debuginfo.variant_deref.built.after.mir
|
||||||
|
#[custom_mir(dialect = "built")]
|
||||||
|
fn variant_deref(opt: Option<&i32>) {
|
||||||
|
mir!(
|
||||||
|
debug pointer => Field::<&i32>(Variant(opt, 1), 0);
|
||||||
|
debug deref => *Field::<&i32>(Variant(opt, 1), 0);
|
||||||
|
{
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
numbered((5, 6));
|
||||||
|
structured(S { x: 5. });
|
||||||
|
variant(Some(5));
|
||||||
|
variant_deref(Some(&5));
|
||||||
|
pointee(&mut Some(5));
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// MIR for `structured` after built
|
||||||
|
|
||||||
|
fn structured(_1: S) -> () {
|
||||||
|
debug x => (_1.0: f32);
|
||||||
|
let mut _0: ();
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// MIR for `variant` after built
|
||||||
|
|
||||||
|
fn variant(_1: Option<i32>) -> () {
|
||||||
|
debug inner => ((_1 as variant#1).0: i32);
|
||||||
|
let mut _0: ();
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
// MIR for `variant_deref` after built
|
||||||
|
|
||||||
|
fn variant_deref(_1: Option<&i32>) -> () {
|
||||||
|
debug pointer => ((_1 as variant#1).0: &i32);
|
||||||
|
debug deref => (*((_1 as variant#1).0: &i32));
|
||||||
|
let mut _0: ();
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user