1use std::collections::hash_map::Entry;
2use std::marker::PhantomData;
3use std::ops::Range;
4
5use rustc_abi::{BackendRepr, FieldIdx, FieldsShape, Size, VariantIdx};
6use rustc_data_structures::fx::FxHashMap;
7use rustc_index::IndexVec;
8use rustc_index::bit_set::DenseBitSet;
9use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
10use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
11use rustc_middle::ty::{Instance, Ty};
12use rustc_middle::{bug, mir, ty};
13use rustc_session::config::DebugInfo;
14use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, hygiene, sym};
15
16use super::operand::{OperandRef, OperandValue};
17use super::place::{PlaceRef, PlaceValue};
18use super::{FunctionCx, LocalRef, PerLocalVarDebugInfoIndexVec};
19use crate::traits::*;
20
21pub struct FunctionDebugContext<'tcx, S, L> {
22 pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
24
25 pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>,
27}
28
29#[derive(#[automatically_derived]
impl ::core::marker::Copy for VariableKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for VariableKind {
#[inline]
fn clone(&self) -> VariableKind {
let _: ::core::clone::AssertParamIsClone<usize>;
*self
}
}Clone)]
30pub enum VariableKind {
31 ArgumentVariable(usize ),
32 LocalVariable,
33}
34
35#[derive(#[automatically_derived]
impl<'tcx, D: ::core::clone::Clone> ::core::clone::Clone for
PerLocalVarDebugInfo<'tcx, D> {
#[inline]
fn clone(&self) -> PerLocalVarDebugInfo<'tcx, D> {
PerLocalVarDebugInfo {
name: ::core::clone::Clone::clone(&self.name),
source_info: ::core::clone::Clone::clone(&self.source_info),
dbg_var: ::core::clone::Clone::clone(&self.dbg_var),
fragment: ::core::clone::Clone::clone(&self.fragment),
projection: ::core::clone::Clone::clone(&self.projection),
}
}
}Clone)]
37pub struct PerLocalVarDebugInfo<'tcx, D> {
38 pub name: Symbol,
39 pub source_info: mir::SourceInfo,
40
41 pub dbg_var: Option<D>,
43
44 pub fragment: Option<Range<Size>>,
47
48 pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
50}
51
52pub struct ConstDebugInfo<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
54 pub name: String,
55 pub source_info: mir::SourceInfo,
56 pub operand: OperandRef<'tcx, Bx::Value>,
57 pub dbg_var: Bx::DIVariable,
58 pub dbg_loc: Bx::DILocation,
59 pub fragment: Option<Range<Size>>,
60 pub _phantom: PhantomData<&'a ()>,
61}
62
63#[derive(#[automatically_derived]
impl<S: ::core::clone::Clone, L: ::core::clone::Clone> ::core::clone::Clone
for DebugScope<S, L> {
#[inline]
fn clone(&self) -> DebugScope<S, L> {
DebugScope {
dbg_scope: ::core::clone::Clone::clone(&self.dbg_scope),
inlined_at: ::core::clone::Clone::clone(&self.inlined_at),
file_start_pos: ::core::clone::Clone::clone(&self.file_start_pos),
file_end_pos: ::core::clone::Clone::clone(&self.file_end_pos),
}
}
}Clone, #[automatically_derived]
impl<S: ::core::marker::Copy, L: ::core::marker::Copy> ::core::marker::Copy
for DebugScope<S, L> {
}Copy, #[automatically_derived]
impl<S: ::core::fmt::Debug, L: ::core::fmt::Debug> ::core::fmt::Debug for
DebugScope<S, L> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f, "DebugScope",
"dbg_scope", &self.dbg_scope, "inlined_at", &self.inlined_at,
"file_start_pos", &self.file_start_pos, "file_end_pos",
&&self.file_end_pos)
}
}Debug)]
64pub struct DebugScope<S, L> {
65 pub dbg_scope: S,
66
67 pub inlined_at: Option<L>,
69
70 pub file_start_pos: BytePos,
73 pub file_end_pos: BytePos,
74}
75
76impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
77 pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocation = L>>(
82 &self,
83 cx: &Cx,
84 span: Span,
85 ) -> S {
86 let pos = span.lo();
87 if pos < self.file_start_pos || pos >= self.file_end_pos {
88 let sm = cx.sess().source_map();
89 cx.extend_scope_to_file(self.dbg_scope, &sm.lookup_char_pos(pos).file)
90 } else {
91 self.dbg_scope
92 }
93 }
94}
95
96trait DebugInfoOffsetLocation<'tcx, Bx> {
97 fn deref(&self, bx: &mut Bx) -> Self;
98 fn layout(&self) -> TyAndLayout<'tcx>;
99 fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self;
100 fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self;
101 fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
102}
103
104impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
105 for PlaceRef<'tcx, Bx::Value>
106{
107 fn deref(&self, bx: &mut Bx) -> Self {
108 bx.load_operand(*self).deref(bx.cx())
109 }
110
111 fn layout(&self) -> TyAndLayout<'tcx> {
112 self.layout
113 }
114
115 fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self {
116 PlaceRef::project_field(*self, bx, field.index())
117 }
118
119 fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self {
120 let lloffset = bx.cx().const_usize(offset);
121 self.project_index(bx, lloffset)
122 }
123
124 fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
125 self.project_downcast(bx, variant)
126 }
127}
128
129impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
130 for TyAndLayout<'tcx>
131{
132 fn deref(&self, bx: &mut Bx) -> Self {
133 bx.cx().layout_of(
134 self.ty.builtin_deref(true).unwrap_or_else(|| ::rustc_middle::util::bug::bug_fmt(format_args!("cannot deref `{0}`",
self.ty))bug!("cannot deref `{}`", self.ty)),
135 )
136 }
137
138 fn layout(&self) -> TyAndLayout<'tcx> {
139 *self
140 }
141
142 fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self {
143 self.field(bx.cx(), field.index())
144 }
145
146 fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self {
147 self.field(bx.cx(), index as usize)
148 }
149
150 fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
151 self.for_variant(bx.cx(), variant)
152 }
153}
154
155struct DebugInfoOffset<T> {
156 direct_offset: Size,
158 indirect_offsets: Vec<Size>,
161 result: T,
163}
164
165fn calculate_debuginfo_offset<
166 'a,
167 'tcx,
168 Bx: BuilderMethods<'a, 'tcx>,
169 L: DebugInfoOffsetLocation<'tcx, Bx>,
170>(
171 bx: &mut Bx,
172 projection: &[mir::PlaceElem<'tcx>],
173 base: L,
174) -> DebugInfoOffset<L> {
175 let mut direct_offset = Size::ZERO;
176 let mut indirect_offsets = ::alloc::vec::Vec::new()vec![];
178 let mut place = base;
179
180 for elem in projection {
181 match *elem {
182 mir::ProjectionElem::Deref => {
183 indirect_offsets.push(Size::ZERO);
184 place = place.deref(bx);
185 }
186 mir::ProjectionElem::Field(field, _) => {
187 let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
188 *offset += place.layout().fields.offset(field.index());
189 place = place.project_field(bx, field);
190 }
191 mir::ProjectionElem::Downcast(_, variant) => {
192 place = place.downcast(bx, variant);
193 }
194 mir::ProjectionElem::ConstantIndex {
195 offset: index,
196 min_length: _,
197 from_end: false,
198 } => {
199 let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
200 let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
201 ::rustc_middle::util::bug::bug_fmt(format_args!("ConstantIndex on non-array type {0:?}",
place.layout()))bug!("ConstantIndex on non-array type {:?}", place.layout())
202 };
203 *offset += stride * index;
204 place = place.project_constant_index(bx, index);
205 }
206 _ => {
207 if !!elem.can_use_in_debuginfo() {
::core::panicking::panic("assertion failed: !elem.can_use_in_debuginfo()")
};assert!(!elem.can_use_in_debuginfo());
209 ::rustc_middle::util::bug::bug_fmt(format_args!("unsupported var debuginfo projection `{0:?}`",
projection))bug!("unsupported var debuginfo projection `{:?}`", projection)
210 }
211 }
212 }
213
214 DebugInfoOffset { direct_offset, indirect_offsets, result: place }
215}
216
217impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
218 pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
219 bx.set_span(source_info.span);
220 if let Some(dbg_loc) = self.dbg_loc(source_info) {
221 bx.set_dbg_loc(dbg_loc);
222 }
223 }
224
225 fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
226 let (dbg_scope, inlined_at, span) = self.adjusted_span_and_dbg_scope(source_info)?;
227 Some(self.cx.dbg_loc(dbg_scope, inlined_at, span))
228 }
229
230 fn adjusted_span_and_dbg_scope(
231 &self,
232 source_info: mir::SourceInfo,
233 ) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
234 let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
235 let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span);
236 Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
237 }
238
239 fn spill_operand_to_stack(
240 operand: OperandRef<'tcx, Bx::Value>,
241 name: Option<String>,
242 bx: &mut Bx,
243 ) -> PlaceRef<'tcx, Bx::Value> {
244 let spill_slot = PlaceRef::alloca(bx, operand.layout);
250 if let Some(name) = name {
251 bx.set_var_name(spill_slot.val.llval, &(name + ".dbg.spill"));
252 }
253 operand.val.store(bx, spill_slot);
254 spill_slot
255 }
256
257 pub(crate) fn debug_new_val_to_local(
260 &self,
261 bx: &mut Bx,
262 local: mir::Local,
263 base: PlaceRef<'tcx, Bx::Value>,
264 projection: &[mir::PlaceElem<'tcx>],
265 ) {
266 let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
267 if !full_debug_info {
268 return;
269 }
270
271 let vars = match &self.per_local_var_debug_info {
272 Some(per_local) => &per_local[local],
273 None => return,
274 };
275
276 let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
277 calculate_debuginfo_offset(bx, projection, base.layout);
278 for var in vars.iter() {
279 let Some(dbg_var) = var.dbg_var else {
280 continue;
281 };
282 let Some(dbg_loc) = self.dbg_loc(var.source_info) else {
283 continue;
284 };
285 bx.dbg_var_value(
286 dbg_var,
287 dbg_loc,
288 base.val.llval,
289 direct_offset,
290 &indirect_offsets,
291 &var.fragment,
292 );
293 }
294 }
295
296 pub(crate) fn debug_poison_to_local(&self, bx: &mut Bx, local: mir::Local) {
297 let ty = self.monomorphize(self.mir.local_decls[local].ty);
298 let layout = bx.cx().layout_of(ty);
299 let to_backend_ty = bx.cx().immediate_backend_type(layout);
300 let place_ref = PlaceRef::new_sized(bx.cx().const_poison(to_backend_ty), layout);
301 self.debug_new_val_to_local(bx, local, place_ref, &[]);
302 }
303
304 pub(crate) fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
307 let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
308
309 let vars = match &self.per_local_var_debug_info {
310 Some(per_local) => &per_local[local],
311 None => return,
312 };
313 let whole_local_var = vars.iter().find(|var| var.projection.is_empty()).cloned();
314 let has_proj = || vars.iter().any(|var| !var.projection.is_empty());
315
316 let fallback_var = if self.mir.local_kind(local) == mir::LocalKind::Arg {
317 let arg_index = local.index() - 1;
318
319 if arg_index == 0 && has_proj() {
322 None
326 } else if whole_local_var.is_some() {
327 None
333 } else {
334 let name = sym::empty;
335 let decl = &self.mir.local_decls[local];
336 let dbg_var = if full_debug_info {
337 self.adjusted_span_and_dbg_scope(decl.source_info).map(
338 |(dbg_scope, _, span)| {
339 let kind = VariableKind::ArgumentVariable(arg_index + 1);
341
342 let arg_ty = self.monomorphize(decl.ty);
343
344 self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
345 },
346 )
347 } else {
348 None
349 };
350
351 Some(PerLocalVarDebugInfo {
352 name,
353 source_info: decl.source_info,
354 dbg_var,
355 fragment: None,
356 projection: ty::List::empty(),
357 })
358 }
359 } else {
360 None
361 };
362
363 let local_ref = &self.locals[local];
364
365 let name = if bx.sess().fewer_names() {
366 None
367 } else {
368 Some(match whole_local_var.or_else(|| fallback_var.clone()) {
369 Some(var) if var.name != sym::empty => var.name.to_string(),
370 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", local))
})format!("{local:?}"),
371 })
372 };
373
374 if let Some(name) = &name {
375 match local_ref {
376 LocalRef::Place(place) | LocalRef::UnsizedPlace(place) => {
377 bx.set_var_name(place.val.llval, name);
378 }
379 LocalRef::Operand(operand) => match operand.val {
380 OperandValue::Ref(PlaceValue { llval: x, .. }) | OperandValue::Immediate(x) => {
381 bx.set_var_name(x, name);
382 }
383 OperandValue::Pair(a, b) => {
384 bx.set_var_name(a, &(name.clone() + ".0"));
387 bx.set_var_name(b, &(name.clone() + ".1"));
388 }
389 OperandValue::ZeroSized => {
390 }
392 },
393 LocalRef::PendingOperand => {}
394 }
395 }
396
397 if !full_debug_info || vars.is_empty() && fallback_var.is_none() {
398 return;
399 }
400
401 let base = match local_ref {
402 LocalRef::PendingOperand => return,
403
404 LocalRef::Operand(operand) => {
405 let attrs = bx.tcx().codegen_instance_attrs(self.instance.def);
408 if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
409 return;
410 }
411
412 if operand.layout.ty.is_scalable_vector()
440 && bx.sess().target.arch == rustc_target::spec::Arch::AArch64
441 {
442 let (count, element_ty, _) =
443 operand.layout.ty.scalable_vector_parts(bx.tcx()).unwrap();
444 if element_ty.is_bool() && count != 16 {
446 return;
447 }
448 }
449
450 Self::spill_operand_to_stack(*operand, name, bx)
451 }
452
453 LocalRef::Place(place) => *place,
454
455 LocalRef::UnsizedPlace(_) => return,
457 };
458
459 let vars = vars.iter().cloned().chain(fallback_var);
460
461 for var in vars {
462 self.debug_introduce_local_as_var(bx, local, base, var);
463 }
464 }
465
466 fn debug_introduce_local_as_var(
467 &self,
468 bx: &mut Bx,
469 local: mir::Local,
470 base: PlaceRef<'tcx, Bx::Value>,
471 var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
472 ) {
473 let Some(dbg_var) = var.dbg_var else { return };
474 let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
475
476 let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
477 calculate_debuginfo_offset(bx, var.projection, base.layout);
478
479 let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
487 && self.mir.local_kind(local) == mir::LocalKind::Arg
488 && (direct_offset != Size::ZERO || !#[allow(non_exhaustive_omitted_patterns)] match &indirect_offsets[..] {
[Size::ZERO] | [] => true,
_ => false,
}matches!(&indirect_offsets[..], [Size::ZERO] | []));
492
493 if should_create_individual_allocas {
494 let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
495 calculate_debuginfo_offset(bx, var.projection, base);
496
497 let ptr_ty = Ty::new_mut_ptr(bx.tcx(), place.layout.ty);
499 let ptr_layout = bx.layout_of(ptr_ty);
500 let alloca = PlaceRef::alloca(bx, ptr_layout);
501 bx.set_var_name(alloca.val.llval, &(var.name.to_string() + ".dbg.spill"));
502
503 bx.store_to_place(place.val.llval, alloca.val);
505
506 bx.dbg_var_addr(
508 dbg_var,
509 dbg_loc,
510 alloca.val.llval,
511 Size::ZERO,
512 &[Size::ZERO],
513 &var.fragment,
514 );
515 } else {
516 bx.dbg_var_addr(
517 dbg_var,
518 dbg_loc,
519 base.val.llval,
520 direct_offset,
521 &indirect_offsets,
522 &var.fragment,
523 );
524 }
525 }
526
527 pub(crate) fn debug_introduce_locals(
528 &self,
529 bx: &mut Bx,
530 consts: Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
531 ) {
532 if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
533 for local in self.locals.indices() {
534 self.debug_introduce_local(bx, local);
535 }
536
537 for ConstDebugInfo { name, source_info, operand, dbg_var, dbg_loc, fragment, .. } in
538 consts.into_iter()
539 {
540 self.set_debug_loc(bx, source_info);
541 let base = FunctionCx::spill_operand_to_stack(operand, Some(name), bx);
542 bx.clear_dbg_loc();
543
544 bx.dbg_var_addr(dbg_var, dbg_loc, base.val.llval, Size::ZERO, &[], &fragment);
545 }
546 }
547 }
548
549 pub(crate) fn compute_per_local_var_debug_info(
551 &self,
552 bx: &mut Bx,
553 ) -> Option<(
554 PerLocalVarDebugInfoIndexVec<'tcx, Bx::DIVariable>,
555 Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
556 )> {
557 let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
558
559 let target_is_msvc = self.cx.sess().target.is_like_msvc;
560
561 if !full_debug_info && self.cx.sess().fewer_names() {
562 return None;
563 }
564
565 let mut per_local = IndexVec::from_elem(::alloc::vec::Vec::new()vec![], &self.mir.local_decls);
566 let mut constants = ::alloc::vec::Vec::new()vec![];
567 let mut params_seen: FxHashMap<_, Bx::DIVariable> = Default::default();
568 for var in &self.mir.var_debug_info {
569 let dbg_scope_and_span = if full_debug_info {
570 self.adjusted_span_and_dbg_scope(var.source_info)
571 } else {
572 None
573 };
574
575 let var_ty = if let Some(ref fragment) = var.composite {
576 self.monomorphize(fragment.ty)
577 } else {
578 match var.value {
579 mir::VarDebugInfoContents::Place(place) => {
580 self.monomorphized_place_ty(place.as_ref())
581 }
582 mir::VarDebugInfoContents::Const(c) => self.monomorphize(c.ty()),
583 }
584 };
585
586 let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
587 let var_kind = if let Some(arg_index) = var.argument_index
588 && var.composite.is_none()
589 && let mir::VarDebugInfoContents::Place(place) = var.value
590 && place.projection.is_empty()
591 {
592 let arg_index = arg_index as usize;
593 if target_is_msvc {
594 let var_ty_layout = self.cx.layout_of(var_ty);
598 if let BackendRepr::ScalarPair(_, _) = var_ty_layout.backend_repr {
599 VariableKind::LocalVariable
600 } else {
601 VariableKind::ArgumentVariable(arg_index)
602 }
603 } else {
604 VariableKind::ArgumentVariable(arg_index)
607 }
608 } else {
609 VariableKind::LocalVariable
610 };
611
612 if let VariableKind::ArgumentVariable(arg_index) = var_kind {
613 match params_seen.entry((dbg_scope, arg_index)) {
614 Entry::Occupied(o) => o.get().clone(),
615 Entry::Vacant(v) => v
616 .insert(
617 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span),
618 )
619 .clone(),
620 }
621 } else {
622 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
623 }
624 });
625
626 let fragment = if let Some(ref fragment) = var.composite {
627 let var_layout = self.cx.layout_of(var_ty);
628
629 let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
630 calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
631 if !indirect_offsets.is_empty() {
::core::panicking::panic("assertion failed: indirect_offsets.is_empty()")
};assert!(indirect_offsets.is_empty());
632
633 if fragment_layout.size == Size::ZERO {
634 continue;
637 } else if fragment_layout.size == var_layout.size {
638 None
641 } else {
642 Some(direct_offset..direct_offset + fragment_layout.size)
643 }
644 } else {
645 None
646 };
647
648 match var.value {
649 mir::VarDebugInfoContents::Place(place) => {
650 per_local[place.local].push(PerLocalVarDebugInfo {
651 name: var.name,
652 source_info: var.source_info,
653 dbg_var,
654 fragment,
655 projection: place.projection,
656 });
657 }
658 mir::VarDebugInfoContents::Const(c) => {
659 if let Some(dbg_var) = dbg_var {
660 let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
661
662 let operand = self.eval_mir_constant_to_operand(bx, &c);
663 constants.push(ConstDebugInfo {
664 name: var.name.to_string(),
665 source_info: var.source_info,
666 operand,
667 dbg_var,
668 dbg_loc,
669 fragment,
670 _phantom: PhantomData,
671 });
672 }
673 }
674 }
675 }
676 Some((per_local, constants))
677 }
678
679 pub(super) fn fill_function_debug_context(&mut self) {
684 if self.cx.sess().opts.debuginfo == DebugInfo::None {
685 return;
686 }
687
688 self.debug_context = Some(FunctionDebugContext {
690 scopes: IndexVec::with_capacity(self.mir.source_scopes.len()),
691 inlined_function_scopes: Default::default(),
692 });
693
694 let variables = if self.cx.sess().opts.debuginfo == DebugInfo::Full {
696 let mut vars = DenseBitSet::new_empty(self.mir.source_scopes.len());
697 for var_debug_info in &self.mir.var_debug_info {
702 vars.insert(var_debug_info.source_info.scope);
703 }
704 Some(vars)
705 } else {
706 None
708 };
709
710 let mut discriminators = FxHashMap::default();
712 for scope in self.mir.source_scopes.indices() {
713 let scope_data = self.make_mir_scope(&variables, &mut discriminators, scope);
714 let _s = self.debug_context.as_mut().unwrap().scopes.push(scope_data);
715 if true {
match (&_s, &scope) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
};
};debug_assert_eq!(_s, scope);
716 }
717 }
718
719 fn make_mir_scope(
720 &mut self,
721 variables: &Option<DenseBitSet<mir::SourceScope>>,
722 discriminators: &mut FxHashMap<BytePos, u32>,
723 scope: mir::SourceScope,
724 ) -> DebugScope<Bx::DIScope, Bx::DILocation> {
725 let scope_data = &self.mir.source_scopes[scope];
726 let parent_scope = if let Some(parent) = scope_data.parent_scope {
727 if true {
if !(parent.as_u32() < scope.as_u32()) {
::core::panicking::panic("assertion failed: parent.as_u32() < scope.as_u32()")
};
};debug_assert!(parent.as_u32() < scope.as_u32());
728 self.debug_context.as_ref().unwrap().scopes[parent]
729 } else {
730 let file = self.cx.sess().source_map().lookup_source_file(self.mir.span.lo());
732 let dbg_scope = self.cx.dbg_scope_fn(self.instance, self.fn_abi, Some(self.llfn));
733 return DebugScope {
734 dbg_scope,
735 inlined_at: None,
736 file_start_pos: file.start_pos,
737 file_end_pos: file.end_position(),
738 };
739 };
740
741 if let Some(vars) = variables
742 && !vars.contains(scope)
743 && scope_data.inlined.is_none()
744 {
745 return parent_scope;
748 }
749
750 let dbg_scope = match scope_data.inlined {
751 Some((callee, _)) => {
752 let callee = self.monomorphize(callee);
753 *self
754 .debug_context
755 .as_mut()
756 .unwrap()
757 .inlined_function_scopes
758 .entry(callee)
759 .or_insert_with(|| {
760 let callee_fn_abi = self.cx.fn_abi_of_instance(callee, ty::List::empty());
761 self.cx.dbg_scope_fn(callee, callee_fn_abi, None)
762 })
763 }
764 None => self.cx.dbg_create_lexical_block(scope_data.span.lo(), parent_scope.dbg_scope),
765 };
766
767 let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
768 let callsite_span = hygiene::walk_chain_collapsed(callsite_span, self.mir.span);
769 let callsite_scope = parent_scope.adjust_dbg_scope_for_span(self.cx, callsite_span);
770 let loc = self.cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span);
771
772 match discriminators.entry(callsite_span.lo()) {
791 Entry::Occupied(mut o) => {
792 *o.get_mut() += 1;
793 self.cx.dbg_location_clone_with_discriminator(loc, *o.get()).unwrap_or_else(
797 || self.cx.dbg_loc(callsite_scope, parent_scope.inlined_at, DUMMY_SP),
798 )
799 }
800 Entry::Vacant(v) => {
801 v.insert(0);
802 loc
803 }
804 }
805 });
806
807 let file = self.cx.sess().source_map().lookup_source_file(scope_data.span.lo());
808 DebugScope {
809 dbg_scope,
810 inlined_at: inlined_at.or(parent_scope.inlined_at),
811 file_start_pos: file.start_pos,
812 file_end_pos: file.end_position(),
813 }
814 }
815}