2019-12-22 17:42:04 -05:00
|
|
|
use crate::traits::*;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_index::vec::IndexVec;
|
2020-08-11 14:09:39 -04:00
|
|
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::mir;
|
|
|
|
|
use rustc_middle::ty;
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_session::config::DebugInfo;
|
2020-01-22 19:45:22 +02:00
|
|
|
use rustc_span::symbol::{kw, Symbol};
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::{BytePos, Span};
|
2020-03-31 18:16:47 +02:00
|
|
|
use rustc_target::abi::{LayoutOf, Size};
|
2019-09-04 19:44:58 +03:00
|
|
|
|
2020-02-08 19:24:31 +02:00
|
|
|
use super::operand::OperandValue;
|
|
|
|
|
use super::place::PlaceRef;
|
2019-12-22 17:42:04 -05:00
|
|
|
use super::{FunctionCx, LocalRef};
|
2019-09-04 19:44:58 +03:00
|
|
|
|
2020-02-11 01:27:33 +02:00
|
|
|
pub struct FunctionDebugContext<S, L> {
|
|
|
|
|
pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
|
2019-09-04 19:44:58 +03:00
|
|
|
}
|
|
|
|
|
|
2019-10-23 13:12:11 +03:00
|
|
|
#[derive(Copy, Clone)]
|
2019-09-04 19:44:58 +03:00
|
|
|
pub enum VariableKind {
|
|
|
|
|
ArgumentVariable(usize /*index*/),
|
|
|
|
|
LocalVariable,
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 19:45:22 +02:00
|
|
|
/// Like `mir::VarDebugInfo`, but within a `mir::Local`.
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
pub struct PerLocalVarDebugInfo<'tcx, D> {
|
|
|
|
|
pub name: Symbol,
|
|
|
|
|
pub source_info: mir::SourceInfo,
|
|
|
|
|
|
|
|
|
|
/// `DIVariable` returned by `create_dbg_var`.
|
|
|
|
|
pub dbg_var: Option<D>,
|
|
|
|
|
|
|
|
|
|
/// `.place.projection` from `mir::VarDebugInfo`.
|
|
|
|
|
pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-04 19:44:58 +03:00
|
|
|
#[derive(Clone, Copy, Debug)]
|
2020-02-11 01:27:33 +02:00
|
|
|
pub struct DebugScope<S, L> {
|
2020-02-10 22:52:30 +02:00
|
|
|
// FIXME(eddyb) this should never be `None`, after initialization.
|
2020-02-11 01:27:33 +02:00
|
|
|
pub dbg_scope: Option<S>,
|
|
|
|
|
|
|
|
|
|
/// Call site location, if this scope was inlined from another function.
|
|
|
|
|
pub inlined_at: Option<L>,
|
|
|
|
|
|
2019-09-04 19:44:58 +03:00
|
|
|
// Start and end offsets of the file to which this DIScope belongs.
|
|
|
|
|
// These are used to quickly determine whether some span refers to the same file.
|
|
|
|
|
pub file_start_pos: BytePos,
|
|
|
|
|
pub file_end_pos: BytePos,
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 01:27:33 +02:00
|
|
|
impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
|
|
|
|
|
/// DILocations inherit source file name from the parent DIScope. Due to macro expansions
|
|
|
|
|
/// it may so happen that the current span belongs to a different file than the DIScope
|
|
|
|
|
/// corresponding to span's containing source scope. If so, we need to create a DIScope
|
|
|
|
|
/// "extension" into that file.
|
|
|
|
|
pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocation = L>>(
|
|
|
|
|
&self,
|
|
|
|
|
cx: &Cx,
|
|
|
|
|
span: Span,
|
|
|
|
|
) -> S {
|
|
|
|
|
// FIXME(eddyb) this should never be `None`.
|
2020-10-26 12:49:49 +00:00
|
|
|
let dbg_scope = self
|
|
|
|
|
.dbg_scope
|
|
|
|
|
.unwrap_or_else(|| bug!("`dbg_scope` is only `None` during initialization"));
|
2020-02-11 01:27:33 +02:00
|
|
|
|
|
|
|
|
let pos = span.lo();
|
|
|
|
|
if pos < self.file_start_pos || pos >= self.file_end_pos {
|
|
|
|
|
let sm = cx.sess().source_map();
|
|
|
|
|
cx.extend_scope_to_file(dbg_scope, &sm.lookup_char_pos(pos).file)
|
|
|
|
|
} else {
|
|
|
|
|
dbg_scope
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-04 19:44:58 +03:00
|
|
|
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
2020-02-08 18:27:49 +02:00
|
|
|
pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
|
2020-02-10 22:52:30 +02:00
|
|
|
bx.set_span(source_info.span);
|
|
|
|
|
if let Some(dbg_loc) = self.dbg_loc(source_info) {
|
|
|
|
|
bx.set_dbg_loc(dbg_loc);
|
2019-09-11 17:52:39 +03:00
|
|
|
}
|
2019-09-04 19:44:58 +03:00
|
|
|
}
|
|
|
|
|
|
2020-02-10 22:52:30 +02:00
|
|
|
fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
|
2020-10-26 13:04:52 +00:00
|
|
|
let (dbg_scope, inlined_at, span) = self.adjusted_span_and_dbg_scope(source_info)?;
|
|
|
|
|
Some(self.cx.dbg_loc(dbg_scope, inlined_at, span))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn adjusted_span_and_dbg_scope(
|
|
|
|
|
&self,
|
|
|
|
|
source_info: mir::SourceInfo,
|
|
|
|
|
) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
|
2020-02-11 01:27:33 +02:00
|
|
|
let span = self.adjust_span_for_debugging(source_info.span);
|
|
|
|
|
let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
|
2020-10-26 13:04:52 +00:00
|
|
|
Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
|
2020-02-10 22:52:30 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-11 01:27:33 +02:00
|
|
|
/// In order to have a good line stepping behavior in debugger, we overwrite debug
|
|
|
|
|
/// locations of macro expansions with that of the outermost expansion site
|
|
|
|
|
/// (unless the crate is being compiled with `-Z debug-macros`).
|
|
|
|
|
fn adjust_span_for_debugging(&self, mut span: Span) -> Span {
|
2019-09-04 19:44:58 +03:00
|
|
|
// Bail out if debug info emission is not enabled.
|
2020-02-11 01:27:33 +02:00
|
|
|
if self.debug_context.is_none() {
|
|
|
|
|
return span;
|
|
|
|
|
}
|
2019-09-04 19:44:58 +03:00
|
|
|
|
2020-02-10 22:52:30 +02:00
|
|
|
if span.from_expansion() && !self.cx.sess().opts.debugging_opts.debug_macros {
|
2019-09-04 19:44:58 +03:00
|
|
|
// Walk up the macro expansion chain until we reach a non-expanded span.
|
|
|
|
|
// We also stop at the function body level because no line stepping can occur
|
|
|
|
|
// at the level above that.
|
|
|
|
|
// Use span of the outermost expansion site, while keeping the original lexical scope.
|
2020-02-10 22:52:30 +02:00
|
|
|
span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
|
2019-09-04 19:44:58 +03:00
|
|
|
}
|
|
|
|
|
|
2020-02-11 01:27:33 +02:00
|
|
|
span
|
2019-09-04 19:44:58 +03:00
|
|
|
}
|
2019-09-13 10:28:14 +03:00
|
|
|
|
2019-09-13 20:04:54 +03:00
|
|
|
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
|
|
|
|
|
/// or initializing the local with an operand (whichever applies).
|
|
|
|
|
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
|
2020-01-22 19:45:22 +02:00
|
|
|
let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
|
|
|
|
|
|
2019-09-13 20:04:54 +03:00
|
|
|
// FIXME(eddyb) maybe name the return place as `_0` or `return`?
|
2020-05-16 13:41:30 -07:00
|
|
|
if local == mir::RETURN_PLACE && !self.mir.local_decls[mir::RETURN_PLACE].is_user_variable()
|
|
|
|
|
{
|
2019-09-13 10:28:14 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-23 13:12:11 +03:00
|
|
|
let vars = match &self.per_local_var_debug_info {
|
|
|
|
|
Some(per_local) => &per_local[local],
|
|
|
|
|
None => return,
|
|
|
|
|
};
|
2020-01-22 19:45:22 +02:00
|
|
|
let whole_local_var = vars.iter().find(|var| var.projection.is_empty()).copied();
|
|
|
|
|
let has_proj = || vars.iter().any(|var| !var.projection.is_empty());
|
2019-10-23 13:12:11 +03:00
|
|
|
|
2020-01-22 19:45:22 +02:00
|
|
|
let fallback_var = if self.mir.local_kind(local) == mir::LocalKind::Arg {
|
2019-09-13 20:04:54 +03:00
|
|
|
let arg_index = local.index() - 1;
|
|
|
|
|
|
|
|
|
|
// Add debuginfo even to unnamed arguments.
|
|
|
|
|
// FIXME(eddyb) is this really needed?
|
2020-01-22 19:45:22 +02:00
|
|
|
if arg_index == 0 && has_proj() {
|
2019-09-13 20:04:54 +03:00
|
|
|
// Hide closure environments from debuginfo.
|
|
|
|
|
// FIXME(eddyb) shouldn't `ArgumentVariable` indices
|
|
|
|
|
// be offset to account for the hidden environment?
|
|
|
|
|
None
|
2020-01-22 19:45:22 +02:00
|
|
|
} else if whole_local_var.is_some() {
|
|
|
|
|
// No need to make up anything, there is a `mir::VarDebugInfo`
|
|
|
|
|
// covering the whole local.
|
|
|
|
|
// FIXME(eddyb) take `whole_local_var.source_info.scope` into
|
|
|
|
|
// account, just in case it doesn't use `ArgumentVariable`
|
|
|
|
|
// (after #67586 gets fixed).
|
|
|
|
|
None
|
2019-09-13 20:04:54 +03:00
|
|
|
} else {
|
2020-01-22 19:45:22 +02:00
|
|
|
let name = kw::Invalid;
|
|
|
|
|
let decl = &self.mir.local_decls[local];
|
2020-02-10 22:52:30 +02:00
|
|
|
let dbg_var = if full_debug_info {
|
2020-10-26 13:04:52 +00:00
|
|
|
self.adjusted_span_and_dbg_scope(decl.source_info).map(
|
|
|
|
|
|(dbg_scope, _, span)| {
|
|
|
|
|
// FIXME(eddyb) is this `+ 1` needed at all?
|
|
|
|
|
let kind = VariableKind::ArgumentVariable(arg_index + 1);
|
2020-02-10 22:52:30 +02:00
|
|
|
|
2020-10-24 02:21:18 +02:00
|
|
|
let arg_ty = self.monomorphize(decl.ty);
|
2020-02-11 01:27:33 +02:00
|
|
|
|
2020-10-26 13:04:52 +00:00
|
|
|
self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
|
|
|
|
|
},
|
|
|
|
|
)
|
2020-01-22 19:45:22 +02:00
|
|
|
} else {
|
2020-02-10 22:52:30 +02:00
|
|
|
None
|
2020-01-22 19:45:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Some(PerLocalVarDebugInfo {
|
|
|
|
|
name,
|
|
|
|
|
source_info: decl.source_info,
|
|
|
|
|
dbg_var,
|
|
|
|
|
projection: ty::List::empty(),
|
2019-10-23 13:12:11 +03:00
|
|
|
})
|
2020-01-22 19:45:22 +02:00
|
|
|
}
|
2019-09-13 20:04:54 +03:00
|
|
|
} else {
|
2020-01-22 19:45:22 +02:00
|
|
|
None
|
2019-09-13 20:04:54 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let local_ref = &self.locals[local];
|
|
|
|
|
|
2020-02-08 19:24:31 +02:00
|
|
|
let name = if bx.sess().fewer_names() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some(match whole_local_var.or(fallback_var) {
|
2019-10-23 13:12:11 +03:00
|
|
|
Some(var) if var.name != kw::Invalid => var.name.to_string(),
|
2019-10-22 12:36:00 +03:00
|
|
|
_ => format!("{:?}", local),
|
2020-02-08 19:24:31 +02:00
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if let Some(name) = &name {
|
2019-09-13 20:04:54 +03:00
|
|
|
match local_ref {
|
2019-12-22 17:42:04 -05:00
|
|
|
LocalRef::Place(place) | LocalRef::UnsizedPlace(place) => {
|
2020-02-08 19:24:31 +02:00
|
|
|
bx.set_var_name(place.llval, name);
|
2019-09-13 20:04:54 +03:00
|
|
|
}
|
|
|
|
|
LocalRef::Operand(Some(operand)) => match operand.val {
|
2019-12-22 17:42:04 -05:00
|
|
|
OperandValue::Ref(x, ..) | OperandValue::Immediate(x) => {
|
2020-02-08 19:24:31 +02:00
|
|
|
bx.set_var_name(x, name);
|
2019-09-13 20:04:54 +03:00
|
|
|
}
|
|
|
|
|
OperandValue::Pair(a, b) => {
|
|
|
|
|
// FIXME(eddyb) these are scalar components,
|
|
|
|
|
// maybe extract the high-level fields?
|
2019-10-22 12:36:00 +03:00
|
|
|
bx.set_var_name(a, &(name.clone() + ".0"));
|
2020-02-08 19:24:31 +02:00
|
|
|
bx.set_var_name(b, &(name.clone() + ".1"));
|
2019-09-13 20:04:54 +03:00
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
2019-09-13 20:04:54 +03:00
|
|
|
LocalRef::Operand(None) => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 19:24:31 +02:00
|
|
|
if !full_debug_info || vars.is_empty() && fallback_var.is_none() {
|
2019-10-23 13:12:11 +03:00
|
|
|
return;
|
|
|
|
|
}
|
2019-09-13 10:28:14 +03:00
|
|
|
|
2019-10-23 13:12:11 +03:00
|
|
|
let base = match local_ref {
|
2020-02-08 19:24:31 +02:00
|
|
|
LocalRef::Operand(None) => return,
|
|
|
|
|
|
|
|
|
|
LocalRef::Operand(Some(operand)) => {
|
2020-08-11 14:09:39 -04:00
|
|
|
// Don't spill operands onto the stack in naked functions.
|
|
|
|
|
// See: https://github.com/rust-lang/rust/issues/42779
|
|
|
|
|
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
|
|
|
|
|
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 19:24:31 +02:00
|
|
|
// "Spill" the value onto the stack, for debuginfo,
|
|
|
|
|
// without forcing non-debuginfo uses of the local
|
|
|
|
|
// to also load from the stack every single time.
|
|
|
|
|
// FIXME(#68817) use `llvm.dbg.value` instead,
|
|
|
|
|
// at least for the cases which LLVM handles correctly.
|
|
|
|
|
let spill_slot = PlaceRef::alloca(bx, operand.layout);
|
|
|
|
|
if let Some(name) = name {
|
|
|
|
|
bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill"));
|
|
|
|
|
}
|
|
|
|
|
operand.val.store(bx, spill_slot);
|
|
|
|
|
spill_slot
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalRef::Place(place) => *place,
|
|
|
|
|
|
|
|
|
|
// FIXME(eddyb) add debuginfo for unsized places too.
|
|
|
|
|
LocalRef::UnsizedPlace(_) => return,
|
2019-10-23 13:12:11 +03:00
|
|
|
};
|
|
|
|
|
|
2020-01-22 19:45:22 +02:00
|
|
|
let vars = vars.iter().copied().chain(fallback_var);
|
2019-09-11 17:52:39 +03:00
|
|
|
|
2019-10-23 13:12:11 +03:00
|
|
|
for var in vars {
|
2020-02-10 22:52:30 +02:00
|
|
|
let dbg_var = match var.dbg_var {
|
|
|
|
|
Some(dbg_var) => dbg_var,
|
|
|
|
|
None => continue,
|
|
|
|
|
};
|
|
|
|
|
let dbg_loc = match self.dbg_loc(var.source_info) {
|
|
|
|
|
Some(dbg_loc) => dbg_loc,
|
|
|
|
|
None => continue,
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-23 13:12:11 +03:00
|
|
|
let mut layout = base.layout;
|
|
|
|
|
let mut direct_offset = Size::ZERO;
|
|
|
|
|
// FIXME(eddyb) use smallvec here.
|
|
|
|
|
let mut indirect_offsets = vec![];
|
|
|
|
|
|
2020-01-22 19:45:22 +02:00
|
|
|
for elem in &var.projection[..] {
|
2019-10-23 13:12:11 +03:00
|
|
|
match *elem {
|
|
|
|
|
mir::ProjectionElem::Deref => {
|
|
|
|
|
indirect_offsets.push(Size::ZERO);
|
|
|
|
|
layout = bx.cx().layout_of(
|
2019-12-22 17:42:04 -05:00
|
|
|
layout
|
|
|
|
|
.ty
|
|
|
|
|
.builtin_deref(true)
|
2019-10-23 13:12:11 +03:00
|
|
|
.unwrap_or_else(|| {
|
2020-01-22 19:45:22 +02:00
|
|
|
span_bug!(var.source_info.span, "cannot deref `{}`", layout.ty)
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
|
.ty,
|
2019-10-23 13:12:11 +03:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
mir::ProjectionElem::Field(field, _) => {
|
|
|
|
|
let i = field.index();
|
2019-12-22 17:42:04 -05:00
|
|
|
let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
|
2019-10-23 13:12:11 +03:00
|
|
|
*offset += layout.fields.offset(i);
|
|
|
|
|
layout = layout.field(bx.cx(), i);
|
|
|
|
|
}
|
|
|
|
|
mir::ProjectionElem::Downcast(_, variant) => {
|
|
|
|
|
layout = layout.for_variant(bx.cx(), variant);
|
|
|
|
|
}
|
|
|
|
|
_ => span_bug!(
|
|
|
|
|
var.source_info.span,
|
|
|
|
|
"unsupported var debuginfo place `{:?}`",
|
2020-01-22 19:45:22 +02:00
|
|
|
mir::Place { local, projection: var.projection },
|
2019-10-23 13:12:11 +03:00
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-10 22:52:30 +02:00
|
|
|
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets);
|
2019-09-13 20:04:54 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
|
2019-10-23 13:12:11 +03:00
|
|
|
if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
|
|
|
|
|
for local in self.locals.indices() {
|
|
|
|
|
self.debug_introduce_local(bx, local);
|
2019-09-13 10:28:14 +03:00
|
|
|
}
|
2019-09-13 20:04:54 +03:00
|
|
|
}
|
2019-10-23 13:12:11 +03:00
|
|
|
}
|
2019-09-13 20:04:54 +03:00
|
|
|
|
2020-01-22 19:45:22 +02:00
|
|
|
/// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
|
|
|
|
|
pub fn compute_per_local_var_debug_info(
|
|
|
|
|
&self,
|
|
|
|
|
) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
|
|
|
|
|
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
|
|
|
|
|
|
2020-02-29 01:56:37 +01:00
|
|
|
if !full_debug_info && self.cx.sess().fewer_names() {
|
2020-01-22 19:45:22 +02:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
|
|
|
|
|
for var in &self.mir.var_debug_info {
|
2020-02-11 01:27:33 +02:00
|
|
|
let dbg_scope_and_span = if full_debug_info {
|
2020-10-26 13:04:52 +00:00
|
|
|
self.adjusted_span_and_dbg_scope(var.source_info)
|
2020-02-11 01:27:33 +02:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
2020-10-26 13:04:52 +00:00
|
|
|
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
|
2020-01-22 19:45:22 +02:00
|
|
|
let place = var.place;
|
|
|
|
|
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
|
|
|
|
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
|
|
|
|
|
&& place.projection.is_empty()
|
2020-02-03 19:42:39 +02:00
|
|
|
&& var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
|
2020-01-22 19:45:22 +02:00
|
|
|
{
|
|
|
|
|
let arg_index = place.local.index() - 1;
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
} else {
|
|
|
|
|
VariableKind::LocalVariable
|
|
|
|
|
};
|
2020-02-11 01:27:33 +02:00
|
|
|
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
|
2020-01-22 19:45:22 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
per_local[var.place.local].push(PerLocalVarDebugInfo {
|
|
|
|
|
name: var.name,
|
|
|
|
|
source_info: var.source_info,
|
|
|
|
|
dbg_var,
|
|
|
|
|
projection: var.place.projection,
|
|
|
|
|
});
|
2019-09-13 10:28:14 +03:00
|
|
|
}
|
2019-10-23 13:12:11 +03:00
|
|
|
Some(per_local)
|
2019-09-13 10:28:14 +03:00
|
|
|
}
|
2019-09-04 19:44:58 +03:00
|
|
|
}
|