Preserve argument indexes when inlining MIR
We store argument indexes on VarDebugInfo. Unlike the previous method of relying on the variable index to know whether a variable is an argument, this survives MIR inlining. We also no longer check if var.source_info.scope is the outermost scope. When a function gets inlined, the arguments to the inner function will no longer be in the outermost scope. What we care about though is whether they were in the outermost scope prior to inlining, which we know by whether we assigned an argument index.
This commit is contained in:
parent
7cd6f55323
commit
a6292676eb
8 changed files with 67 additions and 7 deletions
|
|
@ -442,11 +442,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let (var_ty, var_kind) = match var.value {
|
||||
mir::VarDebugInfoContents::Place(place) => {
|
||||
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
||||
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
|
||||
let var_kind = if let Some(arg_index) = var.argument_index
|
||||
&& place.projection.is_empty()
|
||||
&& var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
|
||||
{
|
||||
let arg_index = place.local.index() - 1;
|
||||
let arg_index = arg_index as usize;
|
||||
if target_is_msvc {
|
||||
// ScalarPair parameters are spilled to the stack so they need to
|
||||
// be marked as a `LocalVariable` for MSVC debuggers to visualize
|
||||
|
|
@ -455,13 +454,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
|
||||
VariableKind::LocalVariable
|
||||
} else {
|
||||
VariableKind::ArgumentVariable(arg_index + 1)
|
||||
VariableKind::ArgumentVariable(arg_index)
|
||||
}
|
||||
} else {
|
||||
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
|
||||
// offset in closures to account for the hidden environment?
|
||||
// Also, is this `+ 1` needed at all?
|
||||
VariableKind::ArgumentVariable(arg_index + 1)
|
||||
VariableKind::ArgumentVariable(arg_index)
|
||||
}
|
||||
} else {
|
||||
VariableKind::LocalVariable
|
||||
|
|
|
|||
|
|
@ -1115,6 +1115,11 @@ pub struct VarDebugInfo<'tcx> {
|
|||
|
||||
/// Where the data for this user variable is to be found.
|
||||
pub value: VarDebugInfoContents<'tcx>,
|
||||
|
||||
/// When present, indicates what argument number this variable is in the function that it
|
||||
/// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
|
||||
/// argument number in the original function before it was inlined.
|
||||
pub argument_index: Option<u16>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -832,6 +832,7 @@ macro_rules! make_mir_visitor {
|
|||
name: _,
|
||||
source_info,
|
||||
value,
|
||||
argument_index: _,
|
||||
} = var_debug_info;
|
||||
|
||||
self.visit_source_info(source_info);
|
||||
|
|
|
|||
|
|
@ -2242,6 +2242,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
name,
|
||||
source_info: debug_source_info,
|
||||
value: VarDebugInfoContents::Place(for_arm_body.into()),
|
||||
argument_index: None,
|
||||
});
|
||||
let locals = if has_guard.0 {
|
||||
let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
|
||||
|
|
@ -2260,6 +2261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
name,
|
||||
source_info: debug_source_info,
|
||||
value: VarDebugInfoContents::Place(ref_for_guard.into()),
|
||||
argument_index: None,
|
||||
});
|
||||
LocalsForNode::ForGuard { ref_for_guard, for_arm_body }
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -811,6 +811,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
name,
|
||||
source_info: SourceInfo::outermost(captured_place.var_ident.span),
|
||||
value: VarDebugInfoContents::Place(use_place),
|
||||
argument_index: None,
|
||||
});
|
||||
|
||||
let capture = Capture { captured_place, use_place, mutability };
|
||||
|
|
@ -827,7 +828,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
expr: &Expr<'tcx>,
|
||||
) -> BlockAnd<()> {
|
||||
// Allocate locals for the function arguments
|
||||
for param in arguments.iter() {
|
||||
for (argument_index, param) in arguments.iter().enumerate() {
|
||||
let source_info =
|
||||
SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
|
||||
let arg_local =
|
||||
|
|
@ -839,6 +840,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
name,
|
||||
source_info,
|
||||
value: VarDebugInfoContents::Place(arg_local.into()),
|
||||
argument_index: Some(argument_index as u16 + 1),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1556,6 +1556,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
|||
body.arg_count = 2; // self, resume arg
|
||||
body.spread_arg = None;
|
||||
|
||||
// The original arguments to the function are no longer arguments, mark them as such.
|
||||
// Otherwise they'll conflict with our new arguments, which although they don't have
|
||||
// argument_index set, will get emitted as unnamed arguments.
|
||||
for var in &mut body.var_debug_info {
|
||||
var.argument_index = None;
|
||||
}
|
||||
|
||||
body.generator.as_mut().unwrap().yield_ty = None;
|
||||
body.generator.as_mut().unwrap().generator_layout = Some(layout);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue