From 6cec91d6470eebcc6dd16e15eaca09d39769a8e5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 19 Aug 2023 09:01:16 +0000 Subject: [PATCH] Support debuginfo for custom MIR. --- .../rustc_mir_build/src/build/custom/parse.rs | 57 ++++++++++++++- .../src/build/custom/parse/instruction.rs | 2 +- library/core/src/intrinsics/mir.rs | 34 ++++++--- .../custom/debuginfo.numbered.built.after.mir | 11 +++ .../custom/debuginfo.pointee.built.after.mir | 10 +++ tests/mir-opt/building/custom/debuginfo.rs | 71 +++++++++++++++++++ .../debuginfo.structured.built.after.mir | 10 +++ .../custom/debuginfo.variant.built.after.mir | 10 +++ .../debuginfo.variant_deref.built.after.mir | 11 +++ 9 files changed, 203 insertions(+), 13 deletions(-) create mode 100644 tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir create mode 100644 tests/mir-opt/building/custom/debuginfo.pointee.built.after.mir create mode 100644 tests/mir-opt/building/custom/debuginfo.rs create mode 100644 tests/mir-opt/building/custom/debuginfo.structured.built.after.mir create mode 100644 tests/mir-opt/building/custom/debuginfo.variant.built.after.mir create mode 100644 tests/mir-opt/building/custom/debuginfo.variant_deref.built.after.mir diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 60c4a041696..f83c62fd580 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -1,5 +1,6 @@ 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 super::{PResult, ParseCtxt, ParseError}; @@ -159,6 +160,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ); 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", ExprKind::Block { block } => &self.thir[*block].stmts, ); @@ -195,6 +204,52 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { Ok(()) } + fn parse_debuginfo(&mut self, stmts: impl Iterator) -> 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)> { let pattern = match &self.thir[stmt_id].kind { StmtKind::Let { pattern, .. } => pattern, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 26662f5de45..da5f2b1bcc9 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -204,7 +204,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } - fn parse_operand(&self, expr_id: ExprId) -> PResult> { + pub fn parse_operand(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "operand", @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), @call("mir_static", args) => self.parse_static(args[0]), diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index b99346b6ba6..02c6f0295fc 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -361,6 +361,11 @@ define!( #[doc(hidden)] fn __internal_make_place(place: T) -> *mut T ); +define!( + "mir_debuginfo", + #[doc(hidden)] + fn __debuginfo(name: &'static str, s: T) +); /// Macro for generating custom MIR. /// @@ -371,6 +376,7 @@ pub macro mir { ( $(type RET = $ret_ty:ty ;)? $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* + $(debug $dbg_name:ident => $dbg_data:expr ;)* { $($entry:tt)* @@ -394,26 +400,32 @@ pub macro mir { $( let $local_decl $(: $local_decl_ty)? ; )* - ::core::intrinsics::mir::__internal_extract_let!($($entry)*); $( ::core::intrinsics::mir::__internal_extract_let!($($block)*); )* { - // Finally, the contents of the basic blocks - ::core::intrinsics::mir::__internal_remove_let!({ - {} - { $($entry)* } - }); + // Now debuginfo $( - ::core::intrinsics::mir::__internal_remove_let!({ - {} - { $($block)* } - }); + __debuginfo(stringify!($dbg_name), $dbg_data); )* - RET + { + // Finally, the contents of the basic blocks + ::core::intrinsics::mir::__internal_remove_let!({ + {} + { $($entry)* } + }); + $( + ::core::intrinsics::mir::__internal_remove_let!({ + {} + { $($block)* } + }); + )* + + RET + } } } }} diff --git a/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir b/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir new file mode 100644 index 00000000000..d8639253718 --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir @@ -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; + } +} diff --git a/tests/mir-opt/building/custom/debuginfo.pointee.built.after.mir b/tests/mir-opt/building/custom/debuginfo.pointee.built.after.mir new file mode 100644 index 00000000000..86cced6f801 --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.pointee.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `pointee` after built + +fn pointee(_1: &mut Option) -> () { + debug foo => (((*_1) as variant#1).0: i32); + let mut _0: (); + + bb0: { + return; + } +} diff --git a/tests/mir-opt/building/custom/debuginfo.rs b/tests/mir-opt/building/custom/debuginfo.rs new file mode 100644 index 00000000000..bfdc3d3eacd --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.rs @@ -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) { + mir!( + debug foo => Field::(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) { + mir!( + debug inner => Field::(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)); +} diff --git a/tests/mir-opt/building/custom/debuginfo.structured.built.after.mir b/tests/mir-opt/building/custom/debuginfo.structured.built.after.mir new file mode 100644 index 00000000000..d122b6bfe29 --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.structured.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `structured` after built + +fn structured(_1: S) -> () { + debug x => (_1.0: f32); + let mut _0: (); + + bb0: { + return; + } +} diff --git a/tests/mir-opt/building/custom/debuginfo.variant.built.after.mir b/tests/mir-opt/building/custom/debuginfo.variant.built.after.mir new file mode 100644 index 00000000000..d173723fd89 --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.variant.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `variant` after built + +fn variant(_1: Option) -> () { + debug inner => ((_1 as variant#1).0: i32); + let mut _0: (); + + bb0: { + return; + } +} diff --git a/tests/mir-opt/building/custom/debuginfo.variant_deref.built.after.mir b/tests/mir-opt/building/custom/debuginfo.variant_deref.built.after.mir new file mode 100644 index 00000000000..37d5d1b2dfc --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.variant_deref.built.after.mir @@ -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; + } +}