diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 6773c34c7d76d..75866e3cdaaa7 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -868,27 +868,11 @@ fn cleanup_debug_info_options(options: &Option) -> Option { "-g".to_owned(), "--debuginfo".to_owned() ]; - let mut new_options = + let new_options = split_maybe_args(options).into_iter() .filter(|x| !options_to_remove.contains(x)) .collect::>(); - let mut i = 0; - while i + 1 < new_options.len() { - if new_options[i] == "-Z" { - // FIXME #31005 MIR missing debuginfo currently. - if new_options[i + 1] == "orbit" { - // Remove "-Z" and "orbit". - new_options.remove(i); - new_options.remove(i); - continue; - } - // Always skip over -Z's argument. - i += 1; - } - i += 1; - } - Some(new_options.join(" ")) } diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 28437fa13368a..aacb3aae81c5e 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -698,6 +698,7 @@ impl ScopeId { #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct ScopeData { + pub span: Span, pub parent_scope: Option, } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 450d25b606719..87f0139104952 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -298,9 +298,11 @@ macro_rules! make_mir_visitor { fn super_scope_data(&mut self, scope_data: & $($mutability)* ScopeData) { let ScopeData { + ref $($mutability)* span, ref $($mutability)* parent_scope, } = *scope_data; + self.visit_span(span); if let Some(ref $($mutability)* parent_scope) = *parent_scope { self.visit_scope_id(parent_scope); } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index bda9cf058f6e9..84fda62067d95 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -255,7 +255,9 @@ impl<'a,'tcx> Builder<'a,'tcx> { debug!("push_scope({:?})", extent); let parent_id = self.scopes.last().map(|s| s.id); let id = ScopeId::new(self.scope_datas.len()); + let tcx = self.hir.tcx(); self.scope_datas.push(ScopeData { + span: extent.span(&tcx.region_maps, &tcx.map).unwrap_or(DUMMY_SP), parent_scope: parent_id, }); self.scopes.push(Scope { diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index d0c66b340d96e..e9c9edd118353 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -242,7 +242,11 @@ fn write_mir_intro(tcx: &TyCtxt, nid: NodeId, mir: &Mir, w: &mut Write) if var.mutability == Mutability::Mut { write!(w, "mut ")?; } - writeln!(w, "{:?}: {}; // {}", Lvalue::Var(i as u32), var.ty, var.name)?; + writeln!(w, "{:?}: {}; // {} in {}", + Lvalue::Var(i as u32), + var.ty, + var.name, + comment(tcx, var.scope, var.span))?; } // Compiler-introduced temporary types. diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 17230eff6e639..464e5c0cf1c1d 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1276,7 +1276,7 @@ pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } } - debuginfo::clear_source_location(cx.fcx); + DebugLoc::None.apply(cx.fcx); Alloca(cx, ty, name) } @@ -1400,23 +1400,23 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>, llfndecl: ValueRef, fn_ty: FnType, - def_id: Option, - param_substs: &'tcx Substs<'tcx>, + definition: Option<(Instance<'tcx>, &ty::FnSig<'tcx>, Abi)>, block_arena: &'blk TypedArena>) -> FunctionContext<'blk, 'tcx> { - common::validate_substs(param_substs); + let (param_substs, def_id) = match definition { + Some((instance, _, _)) => { + common::validate_substs(instance.substs); + (instance.substs, Some(instance.def)) + } + None => (ccx.tcx().mk_substs(Substs::empty()), None) + }; let inlined_did = def_id.and_then(|def_id| inline::get_local_instance(ccx, def_id)); let inlined_id = inlined_did.and_then(|id| ccx.tcx().map.as_local_node_id(id)); let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id)); - debug!("FunctionContext::new(path={}, def_id={:?}, param_substs={:?})", - inlined_id.map_or(String::new(), |id| ccx.tcx().node_path_str(id)), - def_id, - param_substs); - - let debug_context = debuginfo::create_function_debug_context(ccx, - inlined_id.unwrap_or(ast::DUMMY_NODE_ID), param_substs, llfndecl); + debug!("FunctionContext::new({})", + definition.map_or(String::new(), |d| d.0.to_string())); let cfg = inlined_id.map(|id| build_cfg(ccx.tcx(), id)); let nested_returns = if let Some((blk_id, Some(ref cfg))) = cfg { @@ -1428,10 +1428,11 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { let check_attrs = |attrs: &[ast::Attribute]| { let default_to_mir = ccx.sess().opts.debugging_opts.orbit; let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" }; - default_to_mir ^ attrs.iter().any(|item| item.check_name(invert)) + (default_to_mir ^ attrs.iter().any(|item| item.check_name(invert)), + attrs.iter().any(|item| item.check_name("no_debug"))) }; - let use_mir = if let Some(id) = local_id { + let (use_mir, no_debug) = if let Some(id) = local_id { check_attrs(ccx.tcx().map.attrs(id)) } else if let Some(def_id) = def_id { check_attrs(&ccx.sess().cstore.item_attrs(def_id)) @@ -1445,6 +1446,13 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { None }; + let debug_context = if let (false, Some(definition)) = (no_debug, definition) { + let (instance, sig, abi) = definition; + debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl) + } else { + debuginfo::empty_function_debug_context(ccx) + }; + FunctionContext { needs_ret_allocas: nested_returns && mir.is_none(), mir: mir, @@ -1731,7 +1739,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { self.build_return_block(ret_cx, ret_debug_loc); - debuginfo::clear_source_location(self); + DebugLoc::None.apply(self); self.cleanup(); } @@ -1810,32 +1818,34 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, decl: &hir::FnDecl, body: &hir::Block, llfndecl: ValueRef, - param_substs: &'tcx Substs<'tcx>, - def_id: DefId, + instance: Instance<'tcx>, inlined_id: ast::NodeId, - fn_ty: FnType, + sig: &ty::FnSig<'tcx>, abi: Abi, closure_env: closure::ClosureEnv) { ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1); if collector::collecting_debug_information(ccx) { - ccx.record_translation_item_as_generated( - TransItem::Fn(Instance::new(def_id, param_substs))); + ccx.record_translation_item_as_generated(TransItem::Fn(instance)); } let _icx = push_ctxt("trans_closure"); attributes::emit_uwtable(llfndecl, true); - debug!("trans_closure(..., param_substs={:?})", param_substs); + debug!("trans_closure(..., {})", instance); + + let fn_ty = FnType::new(ccx, abi, sig, &[]); let (arena, fcx): (TypedArena<_>, FunctionContext); arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some(def_id), param_substs, &arena); + fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some((instance, sig, abi)), &arena); if fcx.mir.is_some() { return mir::trans_mir(&fcx); } + debuginfo::fill_scope_map_for_function(&fcx, decl, body, inlined_id); + // cleanup scope for the incoming arguments let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node( ccx, inlined_id, body.span, true); @@ -1890,10 +1900,8 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } - let ret_debug_loc = DebugLoc::At(fn_cleanup_debug_loc.id, fn_cleanup_debug_loc.span); - // Insert the mandatory first few basic blocks before lltop. - fcx.finish(bcx, ret_debug_loc); + fcx.finish(bcx, fn_cleanup_debug_loc.debug_loc()); } /// Creates an LLVM function corresponding to a source language function. @@ -1906,25 +1914,23 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(id)); debug!("trans_fn(param_substs={:?})", param_substs); let _icx = push_ctxt("trans_fn"); - let fn_ty = ccx.tcx().node_id_to_type(id); - let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty); - let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig()); - let sig = infer::normalize_associated_type(ccx.tcx(), &sig); - let abi = fn_ty.fn_abi(); - let fn_ty = FnType::new(ccx, abi, &sig, &[]); let def_id = if let Some(&def_id) = ccx.external_srcs().borrow().get(&id) { def_id } else { ccx.tcx().map.local_def_id(id) }; + let fn_ty = ccx.tcx().lookup_item_type(def_id).ty; + let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty); + let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig()); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let abi = fn_ty.fn_abi(); trans_closure(ccx, decl, body, llfndecl, - param_substs, - def_id, + Instance::new(def_id, param_substs), id, - fn_ty, + &sig, abi, closure::ClosureEnv::NotClosure); } @@ -2015,9 +2021,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let (arena, fcx): (TypedArena<_>, FunctionContext); arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfndecl, fn_ty, - Some(ccx.tcx().map.local_def_id(ctor_id)), - param_substs, &arena); + fcx = FunctionContext::new(ccx, llfndecl, fn_ty, None, &arena); let bcx = fcx.init(false, None); assert!(!fcx.needs_ret_allocas); diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 392c40a60155c..7675e1de95827 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -24,7 +24,6 @@ use middle::cstore::LOCAL_CRATE; use rustc::hir::def_id::DefId; use rustc::infer; use rustc::ty::subst; -use rustc::ty::subst::{Substs}; use rustc::traits; use rustc::hir::map as hir_map; use abi::{Abi, FnType}; @@ -385,10 +384,9 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty); // - let empty_substs = tcx.mk_substs(Substs::empty()); let (block_arena, fcx): (TypedArena<_>, FunctionContext); block_arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena); + fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena); let mut bcx = fcx.init(false, None); let llargs = get_params(fcx.llfn); diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 6bd5fd355a731..c2031638044fb 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -234,16 +234,14 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, output: sig.output, variadic: false }; - let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]); trans_closure(ccx, decl, body, llfn, - param_substs, - closure_def_id, + Instance::new(closure_def_id, param_substs), id, - fn_ty, + &sig, Abi::RustCall, ClosureEnv::Closure(closure_def_id, id)); @@ -387,7 +385,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let (block_arena, fcx): (TypedArena<_>, FunctionContext); block_arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, substs.func_substs, &block_arena); + fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, &block_arena); let mut bcx = fcx.init(false, None); diff --git a/src/librustc_trans/controlflow.rs b/src/librustc_trans/controlflow.rs index 58971dec8a9d7..f793f0a6d553b 100644 --- a/src/librustc_trans/controlflow.rs +++ b/src/librustc_trans/controlflow.rs @@ -167,11 +167,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if cv == 1 { // if true { .. } [else { .. }] bcx = trans_block(bcx, &thn, dest); - debuginfo::clear_source_location(bcx.fcx); + DebugLoc::None.apply(bcx.fcx); } else { if let Some(elexpr) = els { bcx = expr::trans_into(bcx, &elexpr, dest); - debuginfo::clear_source_location(bcx.fcx); + DebugLoc::None.apply(bcx.fcx); } } @@ -181,7 +181,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let name = format!("then-block-{}-", thn.id); let then_bcx_in = bcx.fcx.new_id_block(&name[..], thn.id); let then_bcx_out = trans_block(then_bcx_in, &thn, dest); - debuginfo::clear_source_location(bcx.fcx); + DebugLoc::None.apply(bcx.fcx); let cond_source_loc = cond.debug_loc(); @@ -204,7 +204,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Clear the source location because it is still set to whatever has been translated // right before. - debuginfo::clear_source_location(next_bcx.fcx); + DebugLoc::None.apply(next_bcx.fcx); next_bcx } diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index b1cfeb8125bd3..3eebd1f5ea25a 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -8,19 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use super::FunctionDebugContext; use super::metadata::file_metadata; -use super::utils::DIB; +use super::utils::{DIB, span_start}; use llvm; use llvm::debuginfo::{DIScope, DISubprogram}; -use common::CrateContext; +use common::{CrateContext, FunctionContext}; use rustc::hir::pat_util; +use rustc::mir::repr::{Mir, ScopeId}; use rustc::util::nodemap::NodeMap; use libc::c_uint; +use std::ptr; + use syntax::codemap::{Span, Pos}; use syntax::{ast, codemap}; +use rustc_data_structures::bitvec::BitVector; use rustc::hir::{self, PatKind}; // This procedure builds the *scope map* for a given function, which maps any @@ -65,6 +70,74 @@ pub fn create_scope_map(cx: &CrateContext, return scope_map; } +/// Produce DIScope DIEs for each MIR Scope which has variables defined in it. +/// If debuginfo is disabled, the returned vector is empty. +pub fn create_mir_scopes(fcx: &FunctionContext) -> Vec { + let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn"); + let mut scopes = vec![ptr::null_mut(); mir.scopes.len()]; + + let fn_metadata = match fcx.debug_context { + FunctionDebugContext::RegularContext(box ref data) => data.fn_metadata, + FunctionDebugContext::DebugInfoDisabled | + FunctionDebugContext::FunctionWithoutDebugInfo => { + return scopes; + } + }; + + // Find all the scopes with variables defined in them. + let mut has_variables = BitVector::new(mir.scopes.len()); + for var in &mir.var_decls { + has_variables.insert(var.scope.index()); + } + + // Instantiate all scopes. + for idx in 0..mir.scopes.len() { + let scope = ScopeId::new(idx); + make_mir_scope(fcx.ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes); + } + + scopes +} + +fn make_mir_scope(ccx: &CrateContext, + mir: &Mir, + has_variables: &BitVector, + fn_metadata: DISubprogram, + scope: ScopeId, + scopes: &mut [DIScope]) { + let idx = scope.index(); + if !scopes[idx].is_null() { + return; + } + + let scope_data = &mir.scopes[scope]; + let parent_scope = if let Some(parent) = scope_data.parent_scope { + make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes); + scopes[parent.index()] + } else { + // The root is the function itself. + scopes[idx] = fn_metadata; + return; + }; + + scopes[idx] = if !has_variables.contains(idx) { + // Do not create a DIScope if there are no variables + // defined in this MIR Scope, to avoid debuginfo bloat. + parent_scope + } else { + let loc = span_start(ccx, scope_data.span); + let file_metadata = file_metadata(ccx, &loc.file.name); + unsafe { + llvm::LLVMDIBuilderCreateLexicalBlock( + DIB(ccx), + parent_scope, + file_metadata, + loc.line as c_uint, + loc.col.to_usize() as c_uint) + } + }; +} + // local helper functions for walking the AST. fn with_new_scope(cx: &CrateContext, scope_span: Span, @@ -74,7 +147,7 @@ fn with_new_scope(cx: &CrateContext, F: FnOnce(&CrateContext, &mut Vec, &mut NodeMap), { // Create a new lexical scope and push it onto the stack - let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo); + let loc = span_start(cx, scope_span); let file_metadata = file_metadata(cx, &loc.file.name); let parent_scope = scope_stack.last().unwrap().scope_metadata; @@ -199,7 +272,7 @@ fn walk_pattern(cx: &CrateContext, if need_new_scope { // Create a new lexical scope and push it onto the stack - let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo); + let loc = span_start(cx, pat.span); let file_metadata = file_metadata(cx, &loc.file.name); let parent_scope = scope_stack.last().unwrap().scope_metadata; diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 8471b6a274c26..de403732269fe 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -16,7 +16,7 @@ use self::EnumDiscriminantInfo::*; use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, get_namespace_and_span_for_item, create_DIArray, fn_should_be_ignored, is_node_local_to_unit}; -use super::namespace::namespace_for_item; +use super::namespace::mangled_name_of_item; use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name}; use super::{declare_local, VariableKind, VariableAccess}; @@ -68,8 +68,8 @@ pub const UNKNOWN_LINE_NUMBER: c_uint = 0; pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; // ptr::null() doesn't work :( -const NO_FILE_METADATA: DIFile = (0 as DIFile); -const NO_SCOPE_METADATA: DIScope = (0 as DIScope); +pub const NO_FILE_METADATA: DIFile = (0 as DIFile); +pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope); const FLAGS_NONE: c_uint = 0; @@ -1846,28 +1846,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, return; } - let var_item = cx.tcx().map.get(node_id); - - let (name, span) = match var_item { - hir_map::NodeItem(item) => { - match item.node { - hir::ItemStatic(..) => (item.name, item.span), - hir::ItemConst(..) => (item.name, item.span), - _ => { - span_bug!(item.span, - "debuginfo::\ - create_global_var_metadata() - - Captured var-id refers to \ - unexpected ast_item variant: {:?}", - var_item) - } - } - }, - _ => bug!("debuginfo::create_global_var_metadata() \ - - Captured var-id refers to unexpected \ - hir_map variant: {:?}", - var_item) - }; + let node_def_id = cx.tcx().map.local_def_id(node_id); + let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); let (file_metadata, line_number) = if span != codemap::DUMMY_SP { let loc = span_start(cx, span); @@ -1879,12 +1859,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, let is_local_to_unit = is_node_local_to_unit(cx, node_id); let variable_type = cx.tcx().node_id_to_type(node_id); let type_metadata = type_metadata(cx, variable_type, span); - let node_def_id = cx.tcx().map.local_def_id(node_id); - let namespace_node = namespace_for_item(cx, node_def_id); - let var_name = name.to_string(); - let linkage_name = - namespace_node.mangled_name_of_contained_item(&var_name[..]); - let var_scope = namespace_node.scope; + let var_name = cx.tcx().item_name(node_def_id).to_string(); + let linkage_name = mangled_name_of_item(cx, node_def_id, ""); let var_name = CString::new(var_name).unwrap(); let linkage_name = CString::new(linkage_name).unwrap(); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index bb999c31ffb5e..371f6b5efaa94 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -14,42 +14,38 @@ mod doc; use self::VariableAccess::*; use self::VariableKind::*; -use self::utils::{DIB, span_start, assert_type_for_node_id, contains_nodebug_attribute, - create_DIArray, is_node_local_to_unit}; -use self::namespace::{namespace_for_item, NamespaceTreeNode}; +use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit, + get_namespace_and_span_for_item}; +use self::namespace::mangled_name_of_item; use self::type_names::compute_debuginfo_type_name; use self::metadata::{type_metadata, diverging_type_metadata}; use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata}; -use self::source_loc::InternalDebugLocation; +use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use llvm; use llvm::{ModuleRef, ContextRef, ValueRef}; use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, - DIDescriptor, FlagPrototyped}; + FlagPrototyped}; use rustc::hir::def_id::DefId; -use rustc::infer::normalize_associated_type; -use rustc::ty::subst::{self, Substs}; +use rustc::hir::map::DefPathData; +use rustc::ty::subst::Substs; use rustc::hir; use abi::Abi; -use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block}; -use monomorphize; -use rustc::infer; +use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder}; +use monomorphize::Instance; use rustc::ty::{self, Ty}; use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; -use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet}; -use rustc::hir::map as hir_map; +use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet}; use libc::c_uint; use std::cell::{Cell, RefCell}; use std::ffi::CString; use std::ptr; -use std::rc::Rc; use syntax::codemap::{Span, Pos}; use syntax::{ast, codemap}; use syntax::attr::IntType; -use syntax::parse::token::{self, special_idents}; pub mod gdb; mod utils; @@ -59,8 +55,7 @@ mod metadata; mod create_scope_map; mod source_loc; -pub use self::source_loc::set_source_location; -pub use self::source_loc::clear_source_location; +pub use self::create_scope_map::create_mir_scopes; pub use self::source_loc::start_emitting_source_locations; pub use self::source_loc::get_cleanup_debug_loc_for_ast_node; pub use self::source_loc::with_source_location_override; @@ -84,7 +79,7 @@ pub struct CrateDebugContext<'tcx> { created_enum_disr_types: RefCell>, type_map: RefCell>, - namespace_map: RefCell, Rc>>, + namespace_map: RefCell>, // This collection is used to assert that composite types (structs, enums, // ...) have their members only set once: @@ -104,7 +99,7 @@ impl<'tcx> CrateDebugContext<'tcx> { created_files: RefCell::new(FnvHashMap()), created_enum_disr_types: RefCell::new(FnvHashMap()), type_map: RefCell::new(TypeMap::new()), - namespace_map: RefCell::new(FnvHashMap()), + namespace_map: RefCell::new(DefIdMap()), composite_types_completed: RefCell::new(FnvHashSet()), }; } @@ -214,6 +209,18 @@ pub fn finalize(cx: &CrateContext) { }; } +/// Creates a function-specific debug context for a function w/o debuginfo. +pub fn empty_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>) + -> FunctionDebugContext { + if cx.sess().opts.debuginfo == NoDebugInfo { + return FunctionDebugContext::DebugInfoDisabled; + } + + // Clear the debug location so we don't assign them in the function prelude. + source_loc::set_debug_location(cx, None, UnknownLocation); + FunctionDebugContext::FunctionWithoutDebugInfo +} + /// Creates the function-specific debug context. /// /// Returns the FunctionDebugContext for the function which holds state needed @@ -221,8 +228,9 @@ pub fn finalize(cx: &CrateContext) { /// FunctionDebugContext enum which indicates why no debuginfo should be created /// for the function. pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - fn_ast_id: ast::NodeId, - param_substs: &Substs<'tcx>, + instance: Instance<'tcx>, + sig: &ty::FnSig<'tcx>, + abi: Abi, llfn: ValueRef) -> FunctionDebugContext { if cx.sess().opts.debuginfo == NoDebugInfo { return FunctionDebugContext::DebugInfoDisabled; @@ -230,105 +238,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Clear the debug location so we don't assign them in the function prelude. // Do this here already, in case we do an early exit from this function. - source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation); - - 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::FunctionWithoutDebugInfo; - } - - let empty_generics = hir::Generics::empty(); - - let fnitem = cx.tcx().map.get(fn_ast_id); - - let (name, fn_decl, generics, top_level_block, span, has_path) = match fnitem { - hir_map::NodeItem(ref item) => { - if contains_nodebug_attribute(&item.attrs) { - return FunctionDebugContext::FunctionWithoutDebugInfo; - } - - match item.node { - hir::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => { - (item.name, fn_decl, generics, top_level_block, item.span, true) - } - _ => { - span_bug!(item.span, - "create_function_debug_context: item bound to non-function"); - } - } - } - hir_map::NodeImplItem(impl_item) => { - match impl_item.node { - hir::ImplItemKind::Method(ref sig, ref body) => { - if contains_nodebug_attribute(&impl_item.attrs) { - return FunctionDebugContext::FunctionWithoutDebugInfo; - } - - (impl_item.name, - &sig.decl, - &sig.generics, - body, - impl_item.span, - true) - } - _ => { - span_bug!(impl_item.span, - "create_function_debug_context() \ - called on non-method impl item?!") - } - } - } - hir_map::NodeExpr(ref expr) => { - match expr.node { - hir::ExprClosure(_, ref fn_decl, ref top_level_block) => { - let name = format!("fn{}", token::gensym("fn")); - let name = token::intern(&name[..]); - (name, fn_decl, - // This is not quite right. It should actually inherit - // the generics of the enclosing function. - &empty_generics, - top_level_block, - expr.span, - // Don't try to lookup the item path: - false) - } - _ => span_bug!(expr.span, - "create_function_debug_context: expected an expr_fn_block here") - } - } - hir_map::NodeTraitItem(trait_item) => { - match trait_item.node { - hir::MethodTraitItem(ref sig, Some(ref body)) => { - if contains_nodebug_attribute(&trait_item.attrs) { - return FunctionDebugContext::FunctionWithoutDebugInfo; - } - - (trait_item.name, - &sig.decl, - &sig.generics, - body, - trait_item.span, - true) - } - _ => { - bug!("create_function_debug_context: \ - unexpected sort of node: {:?}", - fnitem) - } - } - } - hir_map::NodeForeignItem(..) | - hir_map::NodeVariant(..) | - hir_map::NodeStructCtor(..) => { - return FunctionDebugContext::FunctionWithoutDebugInfo; - } - _ => bug!("create_function_debug_context: \ - unexpected sort of node: {:?}", - fnitem) - }; + source_loc::set_debug_location(cx, None, UnknownLocation); // This can be the case for functions inlined from another crate + let (containing_scope, span) = get_namespace_and_span_for_item(cx, instance.def); if span == codemap::DUMMY_SP { return FunctionDebugContext::FunctionWithoutDebugInfo; } @@ -337,44 +250,38 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let file_metadata = file_metadata(cx, &loc.file.name); let function_type_metadata = unsafe { - let fn_signature = get_function_signature(cx, - fn_ast_id, - param_substs, - span); + let fn_signature = get_function_signature(cx, sig, abi); llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature) }; + // Find the enclosing function, in case this is a closure. + let mut fn_def_id = instance.def; + let mut def_key = cx.tcx().def_key(fn_def_id); + let mut name = def_key.disambiguated_data.data.to_string(); + let name_len = name.len(); + while def_key.disambiguated_data.data == DefPathData::ClosureExpr { + fn_def_id.index = def_key.parent.expect("closure without a parent?"); + def_key = cx.tcx().def_key(fn_def_id); + } + // Get_template_parameters() will append a `<...>` clause to the function // name if necessary. - let mut function_name = name.to_string(); + let generics = cx.tcx().lookup_item_type(fn_def_id).generics; let template_parameters = get_template_parameters(cx, - generics, - param_substs, + &generics, + instance.substs, file_metadata, - &mut function_name); - - // There is no hir_map::Path for hir::ExprClosure-type functions. For now, - // just don't put them into a namespace. In the future this could be improved - // somehow (storing a path in the hir_map, or construct a path using the - // enclosing function). - let (linkage_name, containing_scope) = if has_path { - let fn_ast_def_id = cx.tcx().map.local_def_id(fn_ast_id); - let namespace_node = namespace_for_item(cx, fn_ast_def_id); - let linkage_name = namespace_node.mangled_name_of_contained_item( - &function_name[..]); - let containing_scope = namespace_node.scope; - (linkage_name, containing_scope) - } else { - (function_name.clone(), file_metadata) - }; + &mut name); + + // Build the linkage_name out of the item path and "template" parameters. + let linkage_name = mangled_name_of_item(cx, instance.def, &name[name_len..]); - // Clang sets this parameter to the opening brace of the function's block, - // so let's do this too. - let scope_line = span_start(cx, top_level_block.span).line; + let scope_line = span_start(cx, span).line; - let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id); + let local_id = cx.tcx().map.as_local_node_id(instance.def); + let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id)); - let function_name = CString::new(function_name).unwrap(); + let function_name = CString::new(name).unwrap(); let linkage_name = CString::new(linkage_name).unwrap(); let fn_metadata = unsafe { llvm::LLVMDIBuilderCreateFunction( @@ -395,54 +302,24 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ptr::null_mut()) }; - let scope_map = create_scope_map::create_scope_map(cx, - &fn_decl.inputs, - &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(scope_map), + scope_map: RefCell::new(NodeMap()), fn_metadata: fn_metadata, argument_counter: Cell::new(1), source_locations_enabled: Cell::new(false), source_location_override: Cell::new(false), }; - - return FunctionDebugContext::RegularContext(fn_debug_context); fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - fn_ast_id: ast::NodeId, - param_substs: &Substs<'tcx>, - error_reporting_span: Span) -> DIArray { + sig: &ty::FnSig<'tcx>, + abi: Abi) -> DIArray { if cx.sess().opts.debuginfo == LimitedDebugInfo { return create_DIArray(DIB(cx), &[]); } - // Return type -- llvm::DIBuilder wants this at index 0 - assert_type_for_node_id(cx, fn_ast_id, error_reporting_span); - let fn_type = cx.tcx().node_id_to_type(fn_ast_id); - let fn_type = monomorphize::apply_param_substs(cx.tcx(), param_substs, &fn_type); - - let (sig, abi) = match fn_type.sty { - ty::TyFnDef(_, _, ref barefnty) | ty::TyFnPtr(ref barefnty) => { - let sig = cx.tcx().erase_late_bound_regions(&barefnty.sig); - let sig = infer::normalize_associated_type(cx.tcx(), &sig); - (sig, barefnty.abi) - } - ty::TyClosure(def_id, ref substs) => { - let closure_type = cx.tcx().closure_type(def_id, substs); - let sig = cx.tcx().erase_late_bound_regions(&closure_type.sig); - let sig = infer::normalize_associated_type(cx.tcx(), &sig); - (sig, closure_type.abi) - } - - _ => bug!("get_function_metdata: Expected a function type!") - }; - let mut signature = Vec::with_capacity(sig.inputs.len() + 1); // Return type -- llvm::DIBuilder wants this at index 0 @@ -477,86 +354,39 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - generics: &hir::Generics, + generics: &ty::Generics<'tcx>, param_substs: &Substs<'tcx>, file_metadata: DIFile, name_to_append_suffix_to: &mut String) -> DIArray { - let self_type = param_substs.self_ty(); - let self_type = normalize_associated_type(cx.tcx(), &self_type); - - // Only true for static default methods: - let has_self_type = self_type.is_some(); + let actual_types = param_substs.types.as_slice(); - if !generics.is_type_parameterized() && !has_self_type { + if actual_types.is_empty() { return create_DIArray(DIB(cx), &[]); } name_to_append_suffix_to.push('<'); - - // The list to be filled with template parameters: - let mut template_params: Vec = - Vec::with_capacity(generics.ty_params.len() + 1); - - // Handle self type - if has_self_type { - let actual_self_type = self_type.unwrap(); - // Add self type name to <...> clause of function name - let actual_self_type_name = compute_debuginfo_type_name( - cx, - actual_self_type, - true); - - name_to_append_suffix_to.push_str(&actual_self_type_name[..]); - - if generics.is_type_parameterized() { - name_to_append_suffix_to.push_str(","); - } - - // Only create type information if full debuginfo is enabled - if cx.sess().opts.debuginfo == FullDebugInfo { - let actual_self_type_metadata = type_metadata(cx, - actual_self_type, - codemap::DUMMY_SP); - - let name = special_idents::type_self.name.as_str(); - - let name = CString::new(name.as_bytes()).unwrap(); - let param_metadata = unsafe { - llvm::LLVMDIBuilderCreateTemplateTypeParameter( - DIB(cx), - ptr::null_mut(), - name.as_ptr(), - actual_self_type_metadata, - file_metadata, - 0, - 0) - }; - - template_params.push(param_metadata); - } - } - - // Handle other generic parameters - let actual_types = param_substs.types.get_slice(subst::FnSpace); - for (index, &hir::TyParam{ name, .. }) in generics.ty_params.iter().enumerate() { - let actual_type = actual_types[index]; + for (i, &actual_type) in actual_types.iter().enumerate() { // Add actual type name to <...> clause of function name let actual_type_name = compute_debuginfo_type_name(cx, actual_type, true); name_to_append_suffix_to.push_str(&actual_type_name[..]); - if index != generics.ty_params.len() - 1 { + if i != actual_types.len() - 1 { name_to_append_suffix_to.push_str(","); } + } + name_to_append_suffix_to.push('>'); - // Again, only create type information if full debuginfo is enabled - if cx.sess().opts.debuginfo == FullDebugInfo { + // Again, only create type information if full debuginfo is enabled + let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { + generics.types.as_slice().iter().enumerate().map(|(i, param)| { + let actual_type = actual_types[i]; let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP); - let name = CString::new(name.as_str().as_bytes()).unwrap(); - let param_metadata = unsafe { + let name = CString::new(param.name.as_str().as_bytes()).unwrap(); + unsafe { llvm::LLVMDIBuilderCreateTemplateTypeParameter( DIB(cx), ptr::null_mut(), @@ -565,24 +395,42 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, file_metadata, 0, 0) - }; - template_params.push(param_metadata); - } - } - - name_to_append_suffix_to.push('>'); + } + }).collect() + } else { + vec![] + }; return create_DIArray(DIB(cx), &template_params[..]); } } -fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - variable_name: ast::Name, - variable_type: Ty<'tcx>, - scope_metadata: DIScope, - variable_access: VariableAccess, - variable_kind: VariableKind, - span: Span) { +/// Computes the scope map for a function given its declaration and body. +pub fn fill_scope_map_for_function<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, + fn_decl: &hir::FnDecl, + top_level_block: &hir::Block, + fn_ast_id: ast::NodeId) { + match fcx.debug_context { + FunctionDebugContext::RegularContext(box ref data) => { + let scope_map = create_scope_map::create_scope_map(fcx.ccx, + &fn_decl.inputs, + top_level_block, + data.fn_metadata, + fn_ast_id); + *data.scope_map.borrow_mut() = scope_map; + } + FunctionDebugContext::DebugInfoDisabled | + FunctionDebugContext::FunctionWithoutDebugInfo => {} + } +} + +pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + variable_name: ast::Name, + variable_type: Ty<'tcx>, + scope_metadata: DIScope, + variable_access: VariableAccess, + variable_kind: VariableKind, + span: Span) { let cx: &CrateContext = bcx.ccx(); let filename = span_start(cx, span).file.name.clone(); @@ -616,9 +464,8 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, address_operations.len() as c_uint, argument_index) }; - source_loc::set_debug_location(cx, InternalDebugLocation::new(scope_metadata, - loc.line, - loc.col.to_usize())); + source_loc::set_debug_location(cx, None, + InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize())); unsafe { let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder()); let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( @@ -642,7 +489,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, .get_ref(span) .source_locations_enabled .get()); - source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation); + source_loc::set_debug_location(cx, None, UnknownLocation); } _ => { /* nothing to do */ } } @@ -651,19 +498,17 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum DebugLoc { At(ast::NodeId, Span), + ScopeAt(DIScope, Span), None } impl DebugLoc { - pub fn apply(&self, fcx: &FunctionContext) { - match *self { - DebugLoc::At(node_id, span) => { - source_loc::set_source_location(fcx, node_id, span); - } - DebugLoc::None => { - source_loc::clear_source_location(fcx); - } - } + pub fn apply(self, fcx: &FunctionContext) { + source_loc::set_source_location(fcx, None, self); + } + + pub fn apply_to_bcx(self, bcx: &BlockAndBuilder) { + source_loc::set_source_location(bcx.fcx(), Some(bcx), self); } } diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 5272a4fbbb76b..fc31eaa4e74a7 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -10,118 +10,82 @@ // Namespace Handling. -use super::utils::{DIB, debug_context}; +use super::metadata::{file_metadata, NO_FILE_METADATA, UNKNOWN_LINE_NUMBER}; +use super::utils::{DIB, debug_context, span_start}; use llvm; use llvm::debuginfo::DIScope; use rustc::hir::def_id::DefId; -use rustc::hir::map as hir_map; +use rustc::hir::map::DefPathData; use common::CrateContext; +use libc::c_uint; use std::ffi::CString; -use std::iter::once; use std::ptr; -use std::rc::{Rc, Weak}; -use syntax::ast; -use syntax::parse::token; - -pub struct NamespaceTreeNode { - pub name: ast::Name, - pub scope: DIScope, - pub parent: Option>, -} - -impl NamespaceTreeNode { - pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String { - fn fill_nested(node: &NamespaceTreeNode, output: &mut String) { - match node.parent { - Some(ref parent) => fill_nested(&parent.upgrade().unwrap(), output), - None => {} - } - let string = node.name.as_str(); - output.push_str(&string.len().to_string()); - output.push_str(&string); +use syntax::codemap::DUMMY_SP; + +pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String { + fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) { + let def_key = ccx.tcx().def_key(def_id); + if let Some(parent) = def_key.parent { + fill_nested(ccx, DefId { + krate: def_id.krate, + index: parent + }, "", output); } - let mut name = String::from("_ZN"); - fill_nested(self, &mut name); - name.push_str(&item_name.len().to_string()); - name.push_str(item_name); - name.push('E'); - name - } -} - -pub fn namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc { - // prepend crate name. - // This shouldn't need a roundtrip through InternedString. - let krate = token::intern(&cx.tcx().crate_name(def_id.krate)); - let krate = hir_map::DefPathData::TypeNs(krate); - let path = cx.tcx().def_path(def_id).data; - let mut path = once(krate).chain(path.into_iter().map(|e| e.data)).peekable(); - - let mut current_key = Vec::new(); - let mut parent_node: Option> = None; - - // Create/Lookup namespace for each element of the path. - loop { - // Emulate a for loop so we can use peek below. - let path_element = match path.next() { - Some(e) => e, - None => break + let name = match def_key.disambiguated_data.data { + DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate), + data => data.as_interned_str() }; - // Ignore the name of the item (the last path element). - if path.peek().is_none() { - break; - } - // This shouldn't need a roundtrip through InternedString. - let namespace_name = path_element.as_interned_str(); - let name = token::intern(&namespace_name); - current_key.push(name); - - let existing_node = debug_context(cx).namespace_map.borrow() - .get(¤t_key).cloned(); - let current_node = match existing_node { - Some(existing_node) => existing_node, - None => { - // create and insert - let parent_scope = match parent_node { - Some(ref node) => node.scope, - None => ptr::null_mut() - }; - let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); - let scope = unsafe { - llvm::LLVMDIBuilderCreateNameSpace( - DIB(cx), - parent_scope, - namespace_name.as_ptr(), - // cannot reconstruct file ... - ptr::null_mut(), - // ... or line information, but that's not so important. - 0) - }; - - let node = Rc::new(NamespaceTreeNode { - name: name, - scope: scope, - parent: parent_node.map(|parent| Rc::downgrade(&parent)), - }); - - debug_context(cx).namespace_map.borrow_mut() - .insert(current_key.clone(), node.clone()); + output.push_str(&(name.len() + extra.len()).to_string()); + output.push_str(&name); + output.push_str(extra); + } - node - } - }; + let mut name = String::from("_ZN"); + fill_nested(ccx, def_id, extra, &mut name); + name.push('E'); + name +} - parent_node = Some(current_node); +pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope { + if let Some(&scope) = debug_context(ccx).namespace_map.borrow().get(&def_id) { + return scope; } - match parent_node { - Some(node) => node, - None => { - bug!("debuginfo::namespace_for_item: path too short for {:?}", def_id); - } - } + let def_key = ccx.tcx().def_key(def_id); + let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| { + item_namespace(ccx, DefId { + krate: def_id.krate, + index: parent + }) + }); + + let namespace_name = match def_key.disambiguated_data.data { + DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate), + data => data.as_interned_str() + }; + + let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); + let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP); + let (file, line) = if span != DUMMY_SP { + let loc = span_start(ccx, span); + (file_metadata(ccx, &loc.file.name), loc.line as c_uint) + } else { + (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER) + }; + + let scope = unsafe { + llvm::LLVMDIBuilderCreateNameSpace( + DIB(ccx), + parent_scope, + namespace_name.as_ptr(), + file, + line as c_uint) + }; + + debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope); + scope } diff --git a/src/librustc_trans/debuginfo/source_loc.rs b/src/librustc_trans/debuginfo/source_loc.rs index 2879da7d03b81..6b00c1bb1a855 100644 --- a/src/librustc_trans/debuginfo/source_loc.rs +++ b/src/librustc_trans/debuginfo/source_loc.rs @@ -10,12 +10,13 @@ use self::InternalDebugLocation::*; -use super::utils::{debug_context, span_start, fn_should_be_ignored}; +use super::utils::{debug_context, span_start}; use super::metadata::{scope_metadata,UNKNOWN_COLUMN_NUMBER}; use super::{FunctionDebugContext, DebugLoc}; use llvm; use llvm::debuginfo::DIScope; +use builder::Builder; use common::{NodeIdAndSpan, CrateContext, FunctionContext}; use libc::c_uint; @@ -86,41 +87,46 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, /// Sets the current debug location at the beginning of the span. /// -/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id -/// parameter is used to reliably find the correct visibility scope for the code -/// position. +/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). pub fn set_source_location(fcx: &FunctionContext, - node_id: ast::NodeId, - span: Span) { - match fcx.debug_context { + builder: Option<&Builder>, + debug_loc: DebugLoc) { + let builder = builder.map(|b| b.llbuilder); + let function_debug_context = match fcx.debug_context { FunctionDebugContext::DebugInfoDisabled => return, FunctionDebugContext::FunctionWithoutDebugInfo => { - set_debug_location(fcx.ccx, UnknownLocation); + set_debug_location(fcx.ccx, builder, UnknownLocation); return; } - FunctionDebugContext::RegularContext(box ref function_debug_context) => { - if function_debug_context.source_location_override.get() { - // Just ignore any attempts to set a new debug location while - // the override is active. - return; - } - - let cx = fcx.ccx; - - debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span)); + FunctionDebugContext::RegularContext(box ref data) => data + }; - if function_debug_context.source_locations_enabled.get() { - let loc = span_start(cx, span); - let scope = scope_metadata(fcx, node_id, span); + if function_debug_context.source_location_override.get() { + // Just ignore any attempts to set a new debug location while + // the override is active. + return; + } - set_debug_location(cx, InternalDebugLocation::new(scope, - loc.line, - loc.col.to_usize())); - } else { - set_debug_location(cx, UnknownLocation); + let dbg_loc = if function_debug_context.source_locations_enabled.get() { + let (scope, span) = match debug_loc { + DebugLoc::At(node_id, span) => { + (scope_metadata(fcx, node_id, span), span) } - } - } + DebugLoc::ScopeAt(scope, span) => (scope, span), + DebugLoc::None => { + set_debug_location(fcx.ccx, builder, UnknownLocation); + return; + } + }; + + debug!("set_source_location: {}", + fcx.ccx.sess().codemap().span_to_string(span)); + let loc = span_start(fcx.ccx, span); + InternalDebugLocation::new(scope, loc.line, loc.col.to_usize()) + } else { + UnknownLocation + }; + set_debug_location(fcx.ccx, builder, dbg_loc); } /// This function makes sure that all debug locations emitted while executing @@ -135,7 +141,7 @@ pub fn with_source_location_override(fcx: &FunctionContext, wrapped_function() } FunctionDebugContext::FunctionWithoutDebugInfo => { - set_debug_location(fcx.ccx, UnknownLocation); + set_debug_location(fcx.ccx, None, UnknownLocation); wrapped_function() } FunctionDebugContext::RegularContext(box ref function_debug_context) => { @@ -152,17 +158,6 @@ pub fn with_source_location_override(fcx: &FunctionContext, } } -/// Clears the current debug location. -/// -/// Instructions generated hereafter won't be assigned a source location. -pub fn clear_source_location(fcx: &FunctionContext) { - if fn_should_be_ignored(fcx) { - return; - } - - set_debug_location(fcx.ccx, UnknownLocation); -} - /// Enables emitting source locations for the given functions. /// /// Since we don't want source locations to be emitted for the function prelude, @@ -195,37 +190,42 @@ impl InternalDebugLocation { } } -pub fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) { - if debug_location == debug_context(cx).current_debug_location.get() { - return; +pub fn set_debug_location(cx: &CrateContext, + builder: Option, + debug_location: InternalDebugLocation) { + if builder.is_none() { + if debug_location == debug_context(cx).current_debug_location.get() { + return; + } } - let metadata_node; - - match debug_location { + let metadata_node = match debug_location { KnownLocation { scope, line, .. } => { // Always set the column to zero like Clang and GCC let col = UNKNOWN_COLUMN_NUMBER; debug!("setting debug location to {} {}", line, col); unsafe { - metadata_node = llvm::LLVMDIBuilderCreateDebugLocation( + llvm::LLVMDIBuilderCreateDebugLocation( debug_context(cx).llcontext, line as c_uint, col as c_uint, scope, - ptr::null_mut()); + ptr::null_mut()) } } UnknownLocation => { debug!("clearing debug location "); - metadata_node = ptr::null_mut(); + ptr::null_mut() } }; - unsafe { - llvm::LLVMSetCurrentDebugLocation(cx.raw_builder(), metadata_node); + if builder.is_none() { + debug_context(cx).current_debug_location.set(debug_location); } - debug_context(cx).current_debug_location.set(debug_location); + let builder = builder.unwrap_or_else(|| cx.raw_builder()); + unsafe { + llvm::LLVMSetCurrentDebugLocation(builder, metadata_node); + } } diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index bef7af3aec6c8..3fd9793718434 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -11,7 +11,7 @@ // Utility Functions. use super::{FunctionDebugContext, CrateDebugContext}; -use super::namespace::namespace_for_item; +use super::namespace::item_namespace; use rustc::hir::def_id::DefId; @@ -44,16 +44,6 @@ pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { }; } -pub fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool { - attributes.iter().any(|attr| { - let meta_item: &ast::MetaItem = &attr.node.value; - match meta_item.node { - ast::MetaItemKind::Word(ref value) => &value[..] == "no_debug", - _ => false - } - }) -} - /// Return codemap::Loc corresponding to the beginning of the span pub fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc { cx.sess().codemap().lookup_char_pos(span.lo) @@ -87,21 +77,19 @@ pub fn fn_should_be_ignored(fcx: &FunctionContext) -> bool { } } -pub fn assert_type_for_node_id(cx: &CrateContext, - node_id: ast::NodeId, - error_reporting_span: Span) { - if !cx.tcx().node_types().contains_key(&node_id) { - span_bug!(error_reporting_span, - "debuginfo: Could not find type for node id!"); - } -} - pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId) -> (DIScope, Span) { - let containing_scope = namespace_for_item(cx, def_id).scope; - let definition_span = cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP /* (1) */ ); - - // (1) For external items there is no span information + let containing_scope = item_namespace(cx, DefId { + krate: def_id.krate, + index: cx.tcx().def_key(def_id).parent + .expect("get_namespace_and_span_for_item: missing parent?") + }); + + // Try to get some span information, if we have an inlined item. + let definition_span = match cx.external().borrow().get(&def_id) { + Some(&Some(node_id)) => cx.tcx().map.span(node_id), + _ => cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP) + }; (containing_scope, definition_span) } diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs index beca81da05f4c..6955d51ceccaf 100644 --- a/src/librustc_trans/expr.rs +++ b/src/librustc_trans/expr.rs @@ -115,7 +115,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, -> Block<'blk, 'tcx> { let mut bcx = bcx; - debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); + expr.debug_loc().apply(bcx.fcx); if adjustment_required(bcx, expr) { // use trans, which may be less efficient but @@ -587,7 +587,7 @@ fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("trans_unadjusted(expr={:?})", expr); let _indenter = indenter(); - debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); + expr.debug_loc().apply(bcx.fcx); return match expr_kind(bcx.tcx(), expr) { ExprKind::Lvalue | ExprKind::RvalueDatum => { @@ -923,7 +923,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } - debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); + expr.debug_loc().apply(bcx.fcx); match expr.node { hir::ExprBreak(label_opt) => { @@ -987,7 +987,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // // We could avoid this intermediary with some analysis // to determine whether `dst` may possibly own `src`. - debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); + expr.debug_loc().apply(bcx.fcx); let src_datum = unpack_datum!( bcx, src_datum.to_rvalue_datum(bcx, "ExprAssign")); let opt_hint_datum = dst_datum.kind.drop_flag_info.hint_datum(bcx); @@ -1062,7 +1062,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_rvalue_dps_unadjusted"); let mut bcx = bcx; - debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); + expr.debug_loc().apply(bcx.fcx); // Entry into the method table if this is an overloaded call/op. let method_call = MethodCall::expr(expr.id); diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 5676024ea956e..39ea25619eed0 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -272,10 +272,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let _s = StatRecorder::new(ccx, format!("drop {:?}", t)); - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); let (arena, fcx): (TypedArena<_>, FunctionContext); arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &arena); + fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &arena); let bcx = fcx.init(false, None); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 5924ae1ad84c5..d79320462430c 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -195,8 +195,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let name = tcx.item_name(def_id).as_str(); let span = match call_debug_location { - DebugLoc::At(_, span) => span, - DebugLoc::None => fcx.span.unwrap_or(DUMMY_SP) + DebugLoc::At(_, span) | DebugLoc::ScopeAt(_, span) => span, + DebugLoc::None => { + span_bug!(fcx.span.unwrap_or(DUMMY_SP), + "intrinsic `{}` called with missing span", name); + } }; let cleanup_scope = fcx.push_custom_cleanup_scope(); @@ -1319,10 +1322,9 @@ fn gen_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, sig: ty::Binder(sig) }); let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty); - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); let (fcx, block_arena); block_arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena); + fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena); let bcx = fcx.init(true, None); trans(bcx); fcx.cleanup(); diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 478094c2b87b0..9e5476ae80d47 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -93,10 +93,9 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, symbol_names::internal_name_from_type_and_suffix(ccx, method_ty, "object_shim"); let llfn = declare::define_internal_fn(ccx, &function_name, method_ty); - let empty_substs = tcx.mk_substs(Substs::empty()); let (block_arena, fcx): (TypedArena<_>, FunctionContext); block_arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena); + fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena); let mut bcx = fcx.init(false, None); assert!(!fcx.needs_ret_allocas); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 303cf61ad3379..f70dc0183fdf1 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -54,9 +54,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { bcx = self.trans_statement(bcx, statement); } - debug!("trans_block: terminator: {:?}", data.terminator()); - - match data.terminator().kind { + let terminator = data.terminator(); + debug!("trans_block: terminator: {:?}", terminator); + + let debug_loc = DebugLoc::ScopeAt(self.scopes[terminator.scope.index()], + terminator.span); + debug_loc.apply_to_bcx(&bcx); + debug_loc.apply(bcx.fcx()); + match terminator.kind { mir::TerminatorKind::Resume => { if let Some(cleanup_pad) = cleanup_pad { bcx.cleanup_ret(cleanup_pad, None); @@ -117,7 +122,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { mir::TerminatorKind::Return => { bcx.with_block(|bcx| { - self.fcx.build_return_block(bcx, DebugLoc::None); + self.fcx.build_return_block(bcx, debug_loc); }) } @@ -144,7 +149,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { self.llblock(target), unwind.llbb(), cleanup_bundle.as_ref()); - self.bcx(target).at_start(|bcx| drop::drop_fill(bcx, lvalue.llval, ty)); + self.bcx(target).at_start(|bcx| { + debug_loc.apply_to_bcx(bcx); + drop::drop_fill(bcx, lvalue.llval, ty) + }); } else { bcx.call(drop_fn, &[llvalue], cleanup_bundle.as_ref()); drop::drop_fill(&bcx, lvalue.llval, ty); @@ -267,7 +275,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { bcx.with_block(|bcx| { trans_intrinsic_call(bcx, callee.ty, &fn_ty, ArgVals(llargs), dest, - DebugLoc::None); + debug_loc); }); if let ReturnDest::IndirectOperand(dst, _) = ret_dest { @@ -311,13 +319,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { cleanup_bundle.as_ref()); fn_ty.apply_attrs_callsite(invokeret); - landingpad.at_start(|bcx| for op in args { - self.set_operand_dropped(bcx, op); + landingpad.at_start(|bcx| { + debug_loc.apply_to_bcx(bcx); + for op in args { + self.set_operand_dropped(bcx, op); + } }); if destination.is_some() { let ret_bcx = ret_bcx.build(); ret_bcx.at_start(|ret_bcx| { + debug_loc.apply_to_bcx(ret_bcx); let op = OperandRef { val: OperandValue::Immediate(invokeret), ty: sig.output.unwrap() @@ -514,7 +526,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let use_funclets = base::wants_msvc_seh(bcx.sess()) && data.is_cleanup; let cleanup_pad = if use_funclets { bcx.set_personality_fn(self.fcx.eh_personality()); - bcx.at_start(|bcx| Some(bcx.cleanup_pad(None, &[]))) + bcx.at_start(|bcx| { + DebugLoc::None.apply_to_bcx(bcx); + Some(bcx.cleanup_pad(None, &[])) + }) } else { None }; diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 7e44b72db7f8d..1869845ccb189 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -10,11 +10,19 @@ use libc::c_uint; use llvm::{self, ValueRef}; +use llvm::debuginfo::DIScope; use rustc::ty; use rustc::mir::repr as mir; use rustc::mir::tcx::LvalueTy; +use session::config::FullDebugInfo; use base; use common::{self, Block, BlockAndBuilder, FunctionContext}; +use debuginfo::{self, declare_local, DebugLoc, VariableAccess, VariableKind}; +use machine; +use type_of; + +use syntax::codemap::DUMMY_SP; +use syntax::parse::token; use std::ops::Deref; use std::rc::Rc; @@ -44,8 +52,6 @@ impl<'mir, 'tcx: 'mir> Deref for CachedMir<'mir, 'tcx> { } } -// FIXME DebugLoc is always None right now - /// Master context for translating MIR. pub struct MirContext<'bcx, 'tcx:'bcx> { mir: CachedMir<'bcx, 'tcx>, @@ -92,6 +98,9 @@ pub struct MirContext<'bcx, 'tcx:'bcx> { /// always indirect, though we try to avoid creating an alloca /// when we can (and just reuse the pointer the caller provided). args: Vec>, + + /// Debug information for MIR scopes. + scopes: Vec } enum TempRef<'tcx> { @@ -113,11 +122,26 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { analyze::lvalue_temps(bcx, &mir) }); + // Compute debuginfo scopes from MIR scopes. + let scopes = debuginfo::create_mir_scopes(fcx); + // Allocate variable and temp allocas let vars = mir.var_decls.iter() - .map(|decl| (bcx.monomorphize(&decl.ty), decl.name)) - .map(|(mty, name)| LvalueRef::alloca(&bcx, mty, &name.as_str())) - .collect(); + .map(|decl| (bcx.monomorphize(&decl.ty), decl)) + .map(|(mty, decl)| { + let lvalue = LvalueRef::alloca(&bcx, mty, &decl.name.as_str()); + + let scope = scopes[decl.scope.index()]; + if !scope.is_null() && bcx.sess().opts.debuginfo == FullDebugInfo { + bcx.with_block(|bcx| { + declare_local(bcx, decl.name, mty, scope, + VariableAccess::DirectVariable { alloca: lvalue.llval }, + VariableKind::LocalVariable, decl.span); + }); + } + + lvalue + }).collect(); let temps = mir.temp_decls.iter() .map(|decl| bcx.monomorphize(&decl.ty)) .enumerate() @@ -132,7 +156,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { TempRef::Operand(None) }) .collect(); - let args = arg_value_refs(&bcx, &mir); + let args = arg_value_refs(&bcx, &mir, &scopes); // Allocate a `Block` for every basic block let block_bcxs: Vec> = @@ -152,6 +176,11 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { let start_bcx = block_bcxs[mir::START_BLOCK.index()]; bcx.br(start_bcx.llbb); + // Up until here, IR instructions for this function have explicitly not been annotated with + // source code location, so we don't step into call setup code. From here on, source location + // emitting should be enabled. + debuginfo::start_emitting_source_locations(fcx); + let mut mircx = MirContext { mir: mir.clone(), fcx: fcx, @@ -161,6 +190,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { vars: vars, temps: temps, args: args, + scopes: scopes }; let mut visited = BitVector::new(mir_blocks.len()); @@ -185,6 +215,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { } } + DebugLoc::None.apply(fcx); fcx.cleanup(); } @@ -192,12 +223,25 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { /// argument's value. As arguments are lvalues, these are always /// indirect. fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, - mir: &mir::Mir<'tcx>) + mir: &mir::Mir<'tcx>, + scopes: &[DIScope]) -> Vec> { let fcx = bcx.fcx(); let tcx = bcx.tcx(); let mut idx = 0; let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize; + + // Get the argument scope assuming ScopeId(0) has no parent. + let arg_scope = mir.scopes.get(0).and_then(|data| { + let scope = scopes[0]; + if data.parent_scope.is_none() && !scope.is_null() && + bcx.sess().opts.debuginfo == FullDebugInfo { + Some(scope) + } else { + None + } + }); + mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| { let arg_ty = bcx.monomorphize(&arg_decl.ty); if arg_decl.spread { @@ -211,13 +255,14 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, _ => bug!("spread argument isn't a tuple?!") }; + let lltuplety = type_of::type_of(bcx.ccx(), arg_ty); let lltemp = bcx.with_block(|bcx| { base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index)) }); for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() { let dst = bcx.struct_gep(lltemp, i); let arg = &fcx.fn_ty.args[idx]; - idx += 1; + idx += 1; if common::type_is_fat_ptr(tcx, tupled_arg_ty) { // We pass fat pointers as two words, but inside the tuple // they are the two sub-fields of a single aggregate field. @@ -228,17 +273,37 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, } else { arg.store_fn_arg(bcx, &mut llarg_idx, dst); } + + bcx.with_block(|bcx| arg_scope.map(|scope| { + let byte_offset_of_var_in_tuple = + machine::llelement_offset(bcx.ccx(), lltuplety, i); + + let address_operations = unsafe { + [llvm::LLVMDIBuilderCreateOpDeref(), + llvm::LLVMDIBuilderCreateOpPlus(), + byte_offset_of_var_in_tuple as i64] + }; + + let variable_access = VariableAccess::IndirectVariable { + alloca: lltemp, + address_operations: &address_operations + }; + declare_local(bcx, token::special_idents::invalid.name, + tupled_arg_ty, scope, variable_access, + VariableKind::ArgumentVariable(arg_index + i + 1), + bcx.fcx().span.unwrap_or(DUMMY_SP)); + })); } return LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)); } let arg = &fcx.fn_ty.args[idx]; idx += 1; - let llval = if arg.is_indirect() { + let llval = if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo { // Don't copy an indirect argument to an alloca, the caller // already put it in a temporary alloca and gave it up, unless // we emit extra-debug-info, which requires local allocas :(. - // FIXME: lifetimes, debug info + // FIXME: lifetimes let llarg = llvm::get_param(fcx.llfn, llarg_idx as c_uint); llarg_idx += 1; llarg @@ -261,6 +326,12 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>, } lltemp }; + bcx.with_block(|bcx| arg_scope.map(|scope| { + declare_local(bcx, token::special_idents::invalid.name, arg_ty, scope, + VariableAccess::DirectVariable { alloca: llval }, + VariableKind::ArgumentVariable(arg_index + 1), + bcx.fcx().span.unwrap_or(DUMMY_SP)); + })); LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty)) }).collect() } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 8e5d220b4f4e8..641603f5aaad9 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -38,7 +38,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_rvalue(&mut self, bcx: BlockAndBuilder<'bcx, 'tcx>, dest: LvalueRef<'tcx>, - rvalue: &mir::Rvalue<'tcx>) + rvalue: &mir::Rvalue<'tcx>, + debug_loc: DebugLoc) -> BlockAndBuilder<'bcx, 'tcx> { debug!("trans_rvalue(dest.llval={:?}, rvalue={:?})", @@ -58,7 +59,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { if common::type_is_fat_ptr(bcx.tcx(), cast_ty) { // into-coerce of a thin pointer to a fat pointer - just // use the operand path. - let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); + let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue, debug_loc); self.store_operand(&bcx, dest.llval, temp); return bcx; } @@ -217,7 +218,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { _ => { assert!(rvalue_creates_operand(rvalue)); - let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); + let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue, debug_loc); self.store_operand(&bcx, dest.llval, temp); bcx } @@ -226,7 +227,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_rvalue_operand(&mut self, bcx: BlockAndBuilder<'bcx, 'tcx>, - rvalue: &mir::Rvalue<'tcx>) + rvalue: &mir::Rvalue<'tcx>, + debug_loc: DebugLoc) -> (BlockAndBuilder<'bcx, 'tcx>, OperandRef<'tcx>) { assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue); @@ -419,7 +421,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { lhs_addr, lhs_extra, rhs_addr, rhs_extra, lhs.ty, op.to_hir_binop(), - DebugLoc::None) + debug_loc) }) } _ => bug!() @@ -470,7 +472,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { box_ty, llsize, llalign, - DebugLoc::None); + debug_loc); llval = Some(val); bcx }); diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 1d85ac6fb7960..e4967cead07e9 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -10,6 +10,7 @@ use rustc::mir::repr as mir; use common::BlockAndBuilder; +use debuginfo::DebugLoc; use super::MirContext; use super::TempRef; @@ -21,6 +22,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { -> BlockAndBuilder<'bcx, 'tcx> { debug!("trans_statement(statement={:?})", statement); + let debug_loc = DebugLoc::ScopeAt(self.scopes[statement.scope.index()], + statement.span); + debug_loc.apply_to_bcx(&bcx); + debug_loc.apply(bcx.fcx()); match statement.kind { mir::StatementKind::Assign(ref lvalue, ref rvalue) => { match *lvalue { @@ -28,10 +33,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let index = index as usize; match self.temps[index as usize] { TempRef::Lvalue(tr_dest) => { - self.trans_rvalue(bcx, tr_dest, rvalue) + self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc) } TempRef::Operand(None) => { - let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue); + let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue, + debug_loc); self.temps[index] = TempRef::Operand(Some(operand)); bcx } @@ -44,7 +50,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } _ => { let tr_dest = self.trans_lvalue(&bcx, lvalue); - self.trans_rvalue(bcx, tr_dest, rvalue) + self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc) } } } diff --git a/src/test/compile-fail/bad-intrinsic-monomorphization.rs b/src/test/compile-fail/bad-intrinsic-monomorphization.rs index 049552aa2d71f..cfb64f8076767 100644 --- a/src/test/compile-fail/bad-intrinsic-monomorphization.rs +++ b/src/test/compile-fail/bad-intrinsic-monomorphization.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_simd, platform_intrinsics, rustc_attrs, core_intrinsics)] +#![feature(repr_simd, platform_intrinsics, core_intrinsics)] #![allow(warnings)] // Bad monomorphizations could previously cause LLVM asserts even though the @@ -23,19 +23,16 @@ use std::intrinsics; #[derive(Copy, Clone)] struct Foo(i64); -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_cttz(v: Foo) -> Foo { intrinsics::cttz(v) //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo { intrinsics::fadd_fast(a, b) //~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo { simd_add(a, b) //~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` diff --git a/src/test/compile-fail/non-interger-atomic.rs b/src/test/compile-fail/non-interger-atomic.rs index d2376eecd9b50..0b7b33de42193 100644 --- a/src/test/compile-fail/non-interger-atomic.rs +++ b/src/test/compile-fail/non-interger-atomic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(core_intrinsics, rustc_attrs)] +#![feature(core_intrinsics)] #![allow(warnings)] use std::intrinsics; @@ -18,97 +18,81 @@ struct Foo(i64); type Bar = &'static Fn(); type Quux = [u8; 100]; -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_bool_load(p: &mut bool, v: bool) { intrinsics::atomic_load(p); //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_bool_store(p: &mut bool, v: bool) { intrinsics::atomic_store(p, v); //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_bool_xchg(p: &mut bool, v: bool) { intrinsics::atomic_xchg(p, v); //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_bool_cxchg(p: &mut bool, v: bool) { intrinsics::atomic_cxchg(p, v, v); //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Foo_load(p: &mut Foo, v: Foo) { intrinsics::atomic_load(p); //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Foo_store(p: &mut Foo, v: Foo) { intrinsics::atomic_store(p, v); //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) { intrinsics::atomic_xchg(p, v); //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) { intrinsics::atomic_cxchg(p, v, v); //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Bar_load(p: &mut Bar, v: Bar) { intrinsics::atomic_load(p); //~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Bar_store(p: &mut Bar, v: Bar) { intrinsics::atomic_store(p, v); //~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) { intrinsics::atomic_xchg(p, v); //~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) { intrinsics::atomic_cxchg(p, v, v); //~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Quux_load(p: &mut Quux, v: Quux) { intrinsics::atomic_load(p); //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Quux_store(p: &mut Quux, v: Quux) { intrinsics::atomic_store(p, v); //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) { intrinsics::atomic_xchg(p, v); //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]` } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) { intrinsics::atomic_cxchg(p, v, v); //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]` diff --git a/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs b/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs index 33954d23b19cb..35c368f4cbedb 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-arithmetic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics)] #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone)] @@ -34,7 +34,6 @@ extern "platform-intrinsic" { fn simd_xor(x: T, y: T) -> T; } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. fn main() { let x = i32x4(0, 0, 0, 0); let y = u32x4(0, 0, 0, 0); diff --git a/src/test/compile-fail/simd-intrinsic-generic-cast.rs b/src/test/compile-fail/simd-intrinsic-generic-cast.rs index cb3bed7209e2d..4999b790b130a 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-cast.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-cast.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics)] #[repr(simd)] #[derive(Copy, Clone)] @@ -35,7 +35,6 @@ extern "platform-intrinsic" { fn simd_cast(x: T) -> U; } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. fn main() { let x = i32x4(0, 0, 0, 0); diff --git a/src/test/compile-fail/simd-intrinsic-generic-comparison.rs b/src/test/compile-fail/simd-intrinsic-generic-comparison.rs index 0e7b2bd490470..617b03a87117b 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-comparison.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-comparison.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics)] #[repr(simd)] #[derive(Copy, Clone)] @@ -29,7 +29,6 @@ extern "platform-intrinsic" { fn simd_ge(x: T, y: T) -> U; } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. fn main() { let x = i32x4(0, 0, 0, 0); diff --git a/src/test/compile-fail/simd-intrinsic-generic-elements.rs b/src/test/compile-fail/simd-intrinsic-generic-elements.rs index 1f4cc72ffe717..78f7d42e25a1d 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-elements.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-elements.rs @@ -56,7 +56,6 @@ extern "platform-intrinsic" { fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; } -#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls. fn main() { let x = i32x4(0, 0, 0, 0); diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index ebaad663bb4e7..8615c8a7ef6a4 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -80,7 +80,7 @@ #![allow(unused_variables)] #![allow(dead_code)] -#![feature(omit_gdb_pretty_printer_section)] +#![feature(omit_gdb_pretty_printer_section, rustc_attrs)] #![omit_gdb_pretty_printer_section] trait TraitWithAssocType { @@ -127,6 +127,7 @@ fn assoc_tuple(arg: (T, T::Type)) { zzz(); // #break } +#[rustc_no_mir] // FIXME(#32790) MIR reuses scopes for match arms. fn assoc_enum(arg: Enum) { match arg { diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index 4eec26d335c44..dbd336d2dc688 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -157,7 +157,8 @@ fn main() { zzz(); // #break - let a = SINGLE_VARIANT; + // Borrow to avoid an eager load of the constant value in the static. + let a = &SINGLE_VARIANT; let a = unsafe { AUTO_ONE }; let a = unsafe { MANUAL_ONE }; } diff --git a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs index b5b6ca7572703..e90f7d649f599 100644 --- a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs +++ b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs @@ -247,10 +247,11 @@ // lldb-command:continue #![allow(dead_code, unused_assignments, unused_variables)] -#![feature(omit_gdb_pretty_printer_section)] +#![feature(omit_gdb_pretty_printer_section, rustc_attrs)] #![omit_gdb_pretty_printer_section] #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn immediate_args(a: isize, b: bool, c: f64) { println!(""); } @@ -267,43 +268,51 @@ struct BigStruct { } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn non_immediate_args(a: BigStruct, b: BigStruct) { println!(""); } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn binding(a: i64, b: u64, c: f64) { let x = 0; println!(""); } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn assignment(mut a: u64, b: u64, c: f64) { a = b; println!(""); } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn function_call(x: u64, y: u64, z: f64) { println!("Hi!") } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn identifier(x: u64, y: u64, z: f64) -> u64 { x } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn return_expr(x: u64, y: u64, z: f64) -> u64 { return x; } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 { x + y } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn if_expr(x: u64, y: u64, z: f64) -> u64 { if x + y < 1000 { x @@ -313,6 +322,7 @@ fn if_expr(x: u64, y: u64, z: f64) -> u64 { } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn while_expr(mut x: u64, y: u64, z: u64) -> u64 { while x + y < 1000 { x += z @@ -321,6 +331,7 @@ fn while_expr(mut x: u64, y: u64, z: u64) -> u64 { } #[no_stack_check] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names. fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 { loop { x += z; diff --git a/src/test/debuginfo/no-debug-attribute.rs b/src/test/debuginfo/no-debug-attribute.rs index 6bdd68d5e26e5..ea237e5970c55 100644 --- a/src/test/debuginfo/no-debug-attribute.rs +++ b/src/test/debuginfo/no-debug-attribute.rs @@ -23,10 +23,11 @@ // gdb-command:continue #![allow(unused_variables)] -#![feature(no_debug)] +#![feature(no_debug, rustc_attrs)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is inaccurate for returns. fn function_with_debuginfo() { let abc = 10_usize; return (); // #break diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 7090377e5db1b..d2af828a89020 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -78,7 +78,7 @@ // lldb-command:continue #![allow(unused_variables)] -#![feature(box_syntax)] +#![feature(box_syntax, rustc_attrs, stmt_expr_attributes)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -88,6 +88,7 @@ struct Struct { c: usize } +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. fn main() { let mut variable = 1; let constant = 2; @@ -101,10 +102,14 @@ fn main() { let struct_ref = &a_struct; let owned: Box<_> = box 6; - let mut closure = || { + let mut closure = + #[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. + || { let closure_local = 8; - let mut nested_closure = || { + let mut nested_closure = + #[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. + || { zzz(); // #break variable = constant + a_struct.a + struct_ref.a + *owned + closure_local; }; diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index aa269edadd8f4..26d46040c206e 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -40,7 +40,7 @@ // lldb-check:[...]$2 = 5 #![allow(unused_variables)] -#![feature(unboxed_closures, box_syntax)] +#![feature(unboxed_closures, box_syntax, rustc_attrs, stmt_expr_attributes)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -50,6 +50,7 @@ struct Struct { c: usize } +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. fn main() { let constant = 1; @@ -61,7 +62,9 @@ fn main() { let owned: Box<_> = box 5; - let closure = move || { + let closure = + #[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. + move || { zzz(); // #break do_something(&constant, &a_struct.a, &*owned); }; @@ -73,7 +76,9 @@ fn main() { // The `self` argument of the following closure should be passed by value // to FnOnce::call_once(self, args), which gets translated a bit differently // than the regular case. Let's make sure this is supported too. - let immedate_env = move || { + let immedate_env = + #[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. + move || { zzz(); // #break return constant2; }; diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index 6def5cf285934..a22fbebfd1ada 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -69,7 +69,7 @@ // lldb-command:print *owned // lldb-check:[...]$9 = 6 -#![feature(unboxed_closures, box_syntax)] +#![feature(unboxed_closures, box_syntax, rustc_attrs, stmt_expr_attributes)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -80,6 +80,7 @@ struct Struct { c: usize } +#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. fn main() { let mut variable = 1; let constant = 2; @@ -94,7 +95,9 @@ fn main() { let owned: Box<_> = box 6; { - let mut first_closure = || { + let mut first_closure = + #[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. + || { zzz(); // #break variable = constant + a_struct.a + struct_ref.a + *owned; }; @@ -103,7 +106,9 @@ fn main() { } { - let mut second_closure = || { + let mut second_closure = + #[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures. + || { zzz(); // #break variable = constant + a_struct.a + struct_ref.a + *owned; }; diff --git a/src/test/run-pass/backtrace-debuginfo-aux.rs b/src/test/run-pass/backtrace-debuginfo-aux.rs index b80c938fed5d4..48df600214ad0 100644 --- a/src/test/run-pass/backtrace-debuginfo-aux.rs +++ b/src/test/run-pass/backtrace-debuginfo-aux.rs @@ -11,7 +11,6 @@ // ignore-test: not a test, used by backtrace-debuginfo.rs to test file!() #[inline(never)] -#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently. pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { f((file!(), line!())) } @@ -21,7 +20,6 @@ pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { // this case. #[cfg_attr(not(target_env = "msvc"), inline(always))] #[cfg_attr(target_env = "msvc", inline(never))] -#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently. pub fn callback_inlined(f: F) where F: FnOnce((&'static str, u32)) { f((file!(), line!())) } diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index fd1c01723395d..8b2b26948824f 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] - // We disable tail merging here because it can't preserve debuginfo and thus // potentially breaks the backtraces. Also, subtle changes can decide whether // tail merging suceeds, so the test might work today but fail tomorrow due to a @@ -74,7 +72,6 @@ fn dump_filelines(filelines: &[Pos]) { } #[inline(never)] -#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently. fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { check!(counter; main_pos, outer_pos); check!(counter; main_pos, outer_pos); @@ -91,7 +88,6 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { // this case. #[cfg_attr(not(target_env = "msvc"), inline(always))] #[cfg_attr(target_env = "msvc", inline(never))] -#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently. fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { check!(counter; main_pos, outer_pos); check!(counter; main_pos, outer_pos); @@ -117,7 +113,6 @@ fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { } #[inline(never)] -#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently. fn outer(mut counter: i32, main_pos: Pos) { inner(&mut counter, main_pos, pos!()); inner_inlined(&mut counter, main_pos, pos!()); @@ -162,7 +157,6 @@ fn run_test(me: &str) { } #[inline(never)] -#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently. fn main() { let args: Vec = env::args().collect(); if args.len() >= 2 { diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index a2108ff041dac..5b364358a59dd 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs)] - // no-pretty-expanded FIXME #15189 // ignore-android FIXME #17520 // compile-flags:-g @@ -18,8 +16,6 @@ use std::env; use std::process::{Command, Stdio}; use std::str; -// FIXME #31005 MIR missing debuginfo currently. -#[cfg_attr(target_env = "msvc", rustc_no_mir)] #[inline(never)] fn foo() { let _v = vec![1, 2, 3]; @@ -28,8 +24,6 @@ fn foo() { } } -// FIXME #31005 MIR missing debuginfo currently. -#[cfg_attr(target_env = "msvc", rustc_no_mir)] #[inline(never)] fn double() { struct Double;