//! comparatively expensive to construct, though, `ty::type_id()` is still used
//! additionally as an optimization for cases where the exact same type has been
//! seen before (which is most of the time).
-use self::FunctionDebugContextRepr::*;
use self::VariableAccess::*;
use self::VariableKind::*;
use self::MemberOffset::*;
}
}
-pub struct FunctionDebugContext {
- repr: FunctionDebugContextRepr,
-}
-
-enum FunctionDebugContextRepr {
- DebugInfo(Box<FunctionDebugContextData>),
+pub enum FunctionDebugContext {
+ RegularContext(Box<FunctionDebugContextData>),
DebugInfoDisabled,
FunctionWithoutDebugInfo,
}
cx: &CrateContext,
span: Span)
-> &'a FunctionDebugContextData {
- match self.repr {
- DebugInfo(box ref data) => data,
- DebugInfoDisabled => {
+ match *self {
+ FunctionDebugContext::RegularContext(box ref data) => data,
+ FunctionDebugContext::DebugInfoDisabled => {
cx.sess().span_bug(span,
FunctionDebugContext::debuginfo_disabled_message());
}
- FunctionWithoutDebugInfo => {
+ FunctionDebugContext::FunctionWithoutDebugInfo => {
cx.sess().span_bug(span,
FunctionDebugContext::should_be_ignored_message());
}
/// Creates debug information for the given local variable.
///
+/// This function assumes that there's a datum for each pattern component of the
+/// local in `bcx.fcx.lllocals`.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
if fn_should_be_ignored(bcx.fcx) {
let cx = bcx.ccx();
let def_map = &cx.tcx().def_map;
+ let locals = bcx.fcx.lllocals.borrow();
- pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path1| {
- let var_ident = path1.node;
-
- let datum = match bcx.fcx.lllocals.borrow().get(&node_id).cloned() {
+ pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
+ let datum = match locals.get(&node_id) {
Some(datum) => datum,
None => {
bcx.sess().span_bug(span,
}
};
+ if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
+ cx.sess().span_bug(span, "debuginfo::create_local_var_metadata() - \
+ Referenced variable location is not an alloca!");
+ }
+
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
declare_local(bcx,
- var_ident,
+ var_ident.node,
datum.ty,
scope_metadata,
DirectVariable { alloca: datum.val },
// for the binding. For ByRef bindings that's a `T*` but for ByMove bindings we
// actually have `T**`. So to get the actual variable we need to dereference once
// more. For ByCopy we just use the stack slot we created for the binding.
- let var_type = match binding.trmode {
+ let var_access = match binding.trmode {
TrByCopy(llbinding) => DirectVariable {
alloca: llbinding
},
variable_ident,
binding.ty,
scope_metadata,
- var_type,
+ var_access,
LocalVariable,
binding.span);
}
/// Creates debug information for the given function argument.
///
+/// This function assumes that there's a datum for each pattern component of the
+/// argument in `bcx.fcx.lllocals`.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
if fn_should_be_ignored(bcx.fcx) {
return;
}
- let fcx = bcx.fcx;
- let cx = fcx.ccx;
-
- let def_map = &cx.tcx().def_map;
- let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
-
- pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| {
- let llarg = match bcx.fcx.lllocals.borrow().get(&node_id).cloned() {
+ let def_map = &bcx.tcx().def_map;
+ let scope_metadata = bcx
+ .fcx
+ .debug_context
+ .get_ref(bcx.ccx(), arg.pat.span)
+ .fn_metadata;
+ let locals = bcx.fcx.lllocals.borrow();
+
+ pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
+ let datum = match locals.get(&node_id) {
Some(v) => v,
None => {
bcx.sess().span_bug(span,
}
};
- if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null_mut() {
- cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
- Referenced variable location is not an alloca!");
+ if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
+ bcx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
+ Referenced variable location is not an alloca!");
}
let argument_index = {
- let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
+ let counter = &bcx
+ .fcx
+ .debug_context
+ .get_ref(bcx.ccx(), span)
+ .argument_counter;
let argument_index = counter.get();
counter.set(argument_index + 1);
argument_index
};
declare_local(bcx,
- path1.node,
- llarg.ty,
+ var_ident.node,
+ datum.ty,
scope_metadata,
- DirectVariable { alloca: llarg.val },
+ DirectVariable { alloca: datum.val },
ArgumentVariable(argument_index),
span);
})
/// Creates debug information for the given for-loop variable.
///
+/// This function assumes that there's a datum for each pattern component of the
+/// loop variable in `bcx.fcx.lllocals`.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_for_loop_var_metadata(bcx: Block, pat: &ast::Pat) {
if fn_should_be_ignored(bcx.fcx) {
}
let def_map = &bcx.tcx().def_map;
+ let locals = bcx.fcx.lllocals.borrow();
- pat_util::pat_bindings(def_map, pat, |_, node_id, span, spanned_ident| {
- let datum = match bcx.fcx.lllocals.borrow().get(&node_id).cloned() {
+ pat_util::pat_bindings(def_map, pat, |_, node_id, span, var_ident| {
+ let datum = match locals.get(&node_id) {
Some(datum) => datum,
None => {
bcx.sess().span_bug(span,
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
declare_local(bcx,
- spanned_ident.node,
+ var_ident.node,
datum.ty,
scope_metadata,
DirectVariable { alloca: datum.val },
pub fn set_source_location(fcx: &FunctionContext,
node_id: ast::NodeId,
span: Span) {
- match fcx.debug_context.repr {
- DebugInfoDisabled => return,
- FunctionWithoutDebugInfo => {
+ match fcx.debug_context {
+ FunctionDebugContext::DebugInfoDisabled => return,
+ FunctionDebugContext::FunctionWithoutDebugInfo => {
set_debug_location(fcx.ccx, UnknownLocation);
return;
}
- DebugInfo(box ref function_debug_context) => {
+ FunctionDebugContext::RegularContext(box ref function_debug_context) => {
let cx = fcx.ccx;
debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
/// switches source location emitting on and must therefore be called before the
/// first real statement/expression of the function is translated.
pub fn start_emitting_source_locations(fcx: &FunctionContext) {
- match fcx.debug_context.repr {
- DebugInfo(box ref data) => {
+ match fcx.debug_context {
+ FunctionDebugContext::RegularContext(box ref data) => {
data.source_locations_enabled.set(true)
},
_ => { /* safe to ignore */ }
param_substs: &Substs<'tcx>,
llfn: ValueRef) -> FunctionDebugContext {
if cx.sess().opts.debuginfo == NoDebugInfo {
- return FunctionDebugContext { repr: DebugInfoDisabled };
+ return FunctionDebugContext::DebugInfoDisabled;
}
// Clear the debug location so we don't assign them in the function prelude.
if fn_ast_id == ast::DUMMY_NODE_ID {
// This is a function not linked to any source location, so don't
// generate debuginfo for it.
- return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
+ return FunctionDebugContext::FunctionWithoutDebugInfo;
}
let empty_generics = ast_util::empty_generics();
let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
ast_map::NodeItem(ref item) => {
if contains_nodebug_attribute(item.attrs.as_slice()) {
- return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
+ return FunctionDebugContext::FunctionWithoutDebugInfo;
}
match item.node {
match **item {
ast::MethodImplItem(ref method) => {
if contains_nodebug_attribute(method.attrs.as_slice()) {
- return FunctionDebugContext {
- repr: FunctionWithoutDebugInfo
- };
+ return FunctionDebugContext::FunctionWithoutDebugInfo;
}
(method.pe_ident(),
match **trait_method {
ast::ProvidedMethod(ref method) => {
if contains_nodebug_attribute(method.attrs.as_slice()) {
- return FunctionDebugContext {
- repr: FunctionWithoutDebugInfo
- };
+ return FunctionDebugContext::FunctionWithoutDebugInfo;
}
(method.pe_ident(),
ast_map::NodeForeignItem(..) |
ast_map::NodeVariant(..) |
ast_map::NodeStructCtor(..) => {
- return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
+ return FunctionDebugContext::FunctionWithoutDebugInfo;
}
_ => cx.sess().bug(format!("create_function_debug_context: \
unexpected sort of node: {}",
// This can be the case for functions inlined from another crate
if span == codemap::DUMMY_SP {
- return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
+ return FunctionDebugContext::FunctionWithoutDebugInfo;
}
let loc = span_start(cx, span);
})
});
+ let scope_map = create_scope_map(cx,
+ fn_decl.inputs.as_slice(),
+ &*top_level_block,
+ fn_metadata,
+ fn_ast_id);
+
// Initialize fn debug context (including scope map and namespace map)
let fn_debug_context = box FunctionDebugContextData {
- scope_map: RefCell::new(NodeMap::new()),
+ scope_map: RefCell::new(scope_map),
fn_metadata: fn_metadata,
argument_counter: Cell::new(1),
source_locations_enabled: Cell::new(false),
};
- populate_scope_map(cx,
- fn_decl.inputs.as_slice(),
- &*top_level_block,
- fn_metadata,
- fn_ast_id,
- &mut *fn_debug_context.scope_map.borrow_mut());
- return FunctionDebugContext { repr: DebugInfo(fn_debug_context) };
+
+ return FunctionDebugContext::RegularContext(fn_debug_context);
fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
fn_ast_id: ast::NodeId,
}
fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
- match fcx.debug_context.repr {
- DebugInfo(_) => false,
+ match fcx.debug_context {
+ FunctionDebugContext::RegularContext(_) => false,
_ => true
}
}
// what belongs to which scope, creating DIScope DIEs along the way, and
// introducing *artificial* lexical scope descriptors where necessary. These
// artificial scopes allow GDB to correctly handle name shadowing.
-fn populate_scope_map(cx: &CrateContext,
- args: &[ast::Arg],
- fn_entry_block: &ast::Block,
- fn_metadata: DISubprogram,
- fn_ast_id: ast::NodeId,
- scope_map: &mut NodeMap<DIScope>) {
+fn create_scope_map(cx: &CrateContext,
+ args: &[ast::Arg],
+ fn_entry_block: &ast::Block,
+ fn_metadata: DISubprogram,
+ fn_ast_id: ast::NodeId)
+ -> NodeMap<DIScope> {
+ let mut scope_map = NodeMap::new();
+
let def_map = &cx.tcx().def_map;
struct ScopeStackEntry {
with_new_scope(cx,
fn_entry_block.span,
&mut scope_stack,
- scope_map,
+ &mut scope_map,
|cx, scope_stack, scope_map| {
walk_block(cx, fn_entry_block, scope_stack, scope_map);
});
+ return scope_map;
+
+
// local helper functions for walking the AST.
fn with_new_scope<F>(cx: &CrateContext,
scope_span: Span,
}
ast::PatMac(_) => {
- cx.sess().span_bug(pat.span, "debuginfo::populate_scope_map() - \
+ cx.sess().span_bug(pat.span, "debuginfo::create_scope_map() - \
Found unexpanded macro.");
}
}
}
ast::ExprIfLet(..) => {
- cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
+ cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
Found unexpanded if-let.");
}
}
ast::ExprWhileLet(..) => {
- cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
+ cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
Found unexpanded while-let.");
}
}
ast::ExprMac(_) => {
- cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
+ cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
Found unexpanded macro.");
}