Auto merge of #114904 - cjgillot:no-ref-debuginfo, r=wesleywiser
Remove references in VarDebugInfo The codegen implementation is broken, and attempted to read uninitialized memory. Fixes https://github.com/rust-lang/rust/issues/114488
This commit is contained in:
commit
ccc3ac0cae
38 changed files with 789 additions and 628 deletions
|
@ -42,9 +42,6 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
|
|||
|
||||
/// `.place.projection` from `mir::VarDebugInfo`.
|
||||
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
|
||||
|
||||
/// `references` from `mir::VarDebugInfo`.
|
||||
pub references: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -323,7 +320,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dbg_var,
|
||||
fragment: None,
|
||||
projection: ty::List::empty(),
|
||||
references: 0,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
@ -399,15 +395,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&self,
|
||||
bx: &mut Bx,
|
||||
local: mir::Local,
|
||||
mut base: PlaceRef<'tcx, Bx::Value>,
|
||||
base: PlaceRef<'tcx, Bx::Value>,
|
||||
var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
|
||||
) {
|
||||
let Some(dbg_var) = var.dbg_var else { return };
|
||||
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
|
||||
|
||||
let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
|
||||
let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
|
||||
calculate_debuginfo_offset(bx, local, &var, base.layout);
|
||||
let mut indirect_offsets = &indirect_offsets[..];
|
||||
|
||||
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
|
||||
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
|
||||
|
@ -421,9 +416,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// LLVM can handle simple things but anything more complex than just a direct
|
||||
// offset or one indirect offset of 0 is too complex for it to generate CV records
|
||||
// correctly.
|
||||
&& (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
|
||||
&& (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
|
||||
|
||||
if should_create_individual_allocas {
|
||||
let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
|
||||
calculate_debuginfo_offset(bx, local, &var, base);
|
||||
|
||||
let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
|
||||
// Create a variable which will be a pointer to the actual value
|
||||
let ptr_ty = Ty::new_ptr(
|
||||
bx.tcx(),
|
||||
|
@ -431,35 +429,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
);
|
||||
let ptr_layout = bx.layout_of(ptr_ty);
|
||||
let alloca = PlaceRef::alloca(bx, ptr_layout);
|
||||
bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
|
||||
bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
|
||||
|
||||
// Write the pointer to the variable
|
||||
bx.store(place.llval, alloca.llval, alloca.align);
|
||||
|
||||
// Point the debug info to `*alloca` for the current variable
|
||||
alloca
|
||||
};
|
||||
|
||||
if var.references > 0 {
|
||||
base = calculate_debuginfo_offset(bx, local, &var, base).result;
|
||||
|
||||
// Point the debug info to `&...&base == alloca` for the current variable
|
||||
for refcount in 0..var.references {
|
||||
base = create_alloca(bx, base, refcount);
|
||||
}
|
||||
|
||||
direct_offset = Size::ZERO;
|
||||
indirect_offsets = &[];
|
||||
} else if should_create_individual_allocas {
|
||||
let place = calculate_debuginfo_offset(bx, local, &var, base).result;
|
||||
|
||||
// Point the debug info to `*alloca` for the current variable
|
||||
base = create_alloca(bx, place, 0);
|
||||
direct_offset = Size::ZERO;
|
||||
indirect_offsets = &[Size::ZERO];
|
||||
bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
|
||||
} else {
|
||||
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
|
||||
}
|
||||
|
||||
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
|
||||
}
|
||||
|
||||
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
|
||||
|
@ -492,7 +471,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
};
|
||||
|
||||
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
|
||||
let (mut var_ty, var_kind) = match var.value {
|
||||
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 let Some(arg_index) = var.argument_index
|
||||
|
@ -529,13 +508,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
};
|
||||
|
||||
for _ in 0..var.references {
|
||||
var_ty = Ty::new_ptr(
|
||||
bx.tcx(),
|
||||
ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty },
|
||||
);
|
||||
}
|
||||
|
||||
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
|
||||
});
|
||||
|
||||
|
@ -547,7 +519,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dbg_var,
|
||||
fragment: None,
|
||||
projection: place.projection,
|
||||
references: var.references,
|
||||
});
|
||||
}
|
||||
mir::VarDebugInfoContents::Const(c) => {
|
||||
|
@ -601,7 +572,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
Some(fragment_start..fragment_start + fragment_layout.size)
|
||||
},
|
||||
projection: place.projection,
|
||||
references: var.references,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -701,12 +701,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
VarDebugInfoContents::Const(_) => {}
|
||||
VarDebugInfoContents::Place(place) => {
|
||||
check_place(self, place);
|
||||
if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
|
||||
self.fail(
|
||||
START_BLOCK.start_location(),
|
||||
format!("debuginfo {debuginfo:?}, has both ref and deref"),
|
||||
);
|
||||
}
|
||||
}
|
||||
VarDebugInfoContents::Composite { ty, ref fragments } => {
|
||||
for f in fragments {
|
||||
|
|
|
@ -1109,10 +1109,6 @@ pub struct VarDebugInfo<'tcx> {
|
|||
/// 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>,
|
||||
|
||||
/// The data represents `name` dereferenced `references` times,
|
||||
/// and not the direct value.
|
||||
pub references: u8,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -555,13 +555,8 @@ fn write_scope_tree(
|
|||
}
|
||||
|
||||
let indented_debug_info = format!(
|
||||
"{0:1$}debug {2} => {3:&<4$}{5:?};",
|
||||
INDENT,
|
||||
indent,
|
||||
var_debug_info.name,
|
||||
"",
|
||||
var_debug_info.references as usize,
|
||||
var_debug_info.value,
|
||||
"{0:1$}debug {2} => {3:?};",
|
||||
INDENT, indent, var_debug_info.name, var_debug_info.value,
|
||||
);
|
||||
|
||||
if tcx.sess.opts.unstable_opts.mir_include_spans {
|
||||
|
|
|
@ -840,7 +840,6 @@ macro_rules! make_mir_visitor {
|
|||
source_info,
|
||||
value,
|
||||
argument_index: _,
|
||||
references: _,
|
||||
} = var_debug_info;
|
||||
|
||||
self.visit_source_info(source_info);
|
||||
|
|
|
@ -438,7 +438,6 @@ CloneLiftImpls! {
|
|||
(),
|
||||
bool,
|
||||
usize,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
|
|
|
@ -2242,7 +2242,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
source_info: debug_source_info,
|
||||
references: 0,
|
||||
value: VarDebugInfoContents::Place(for_arm_body.into()),
|
||||
argument_index: None,
|
||||
});
|
||||
|
@ -2262,7 +2261,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
source_info: debug_source_info,
|
||||
references: 0,
|
||||
value: VarDebugInfoContents::Place(ref_for_guard.into()),
|
||||
argument_index: None,
|
||||
});
|
||||
|
|
|
@ -820,7 +820,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
};
|
||||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
references: 0,
|
||||
source_info: SourceInfo::outermost(captured_place.var_ident.span),
|
||||
value: VarDebugInfoContents::Place(use_place),
|
||||
argument_index: None,
|
||||
|
@ -851,7 +850,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
self.var_debug_info.push(VarDebugInfo {
|
||||
name,
|
||||
source_info,
|
||||
references: 0,
|
||||
value: VarDebugInfoContents::Place(arg_local.into()),
|
||||
argument_index: Some(argument_index as u16 + 1),
|
||||
});
|
||||
|
|
|
@ -265,7 +265,6 @@ fn compute_replacement<'tcx>(
|
|||
targets,
|
||||
storage_to_remove,
|
||||
allowed_replacements,
|
||||
fully_replacable_locals,
|
||||
any_replacement: false,
|
||||
};
|
||||
|
||||
|
@ -346,7 +345,6 @@ struct Replacer<'tcx> {
|
|||
storage_to_remove: BitSet<Local>,
|
||||
allowed_replacements: FxHashSet<(Local, Location)>,
|
||||
any_replacement: bool,
|
||||
fully_replacable_locals: BitSet<Local>,
|
||||
}
|
||||
|
||||
impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
|
||||
|
@ -366,12 +364,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
|
|||
if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
|
||||
*place = Place::from(target.local).project_deeper(rest, self.tcx);
|
||||
self.any_replacement = true;
|
||||
} else if self.fully_replacable_locals.contains(place.local)
|
||||
&& let Some(references) = debuginfo.references.checked_add(1)
|
||||
{
|
||||
debuginfo.references = references;
|
||||
*place = target;
|
||||
self.any_replacement = true;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ TrivialTypeTraversalImpls! {
|
|||
(),
|
||||
bool,
|
||||
usize,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue