mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-15 08:23:26 +00:00
trans: pass essential information from trans_closure to debuginfo.
This commit is contained in:
parent
35a6e6a02b
commit
e945b2852e
@ -1400,11 +1400,15 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||
pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
|
||||
llfndecl: ValueRef,
|
||||
fn_ty: FnType,
|
||||
instance: Option<Instance<'tcx>>,
|
||||
definition: Option<(Instance<'tcx>,
|
||||
&ty::FnSig<'tcx>,
|
||||
Abi,
|
||||
&ty::Generics<'tcx>,
|
||||
Option<ast::Name>)>,
|
||||
block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
|
||||
-> FunctionContext<'blk, 'tcx> {
|
||||
let (param_substs, def_id) = match instance {
|
||||
Some(instance) => {
|
||||
let (param_substs, def_id) = match definition {
|
||||
Some((instance, _, _, _, _)) => {
|
||||
common::validate_substs(instance.substs);
|
||||
(instance.substs, Some(instance.def))
|
||||
}
|
||||
@ -1416,10 +1420,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||
let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
|
||||
|
||||
debug!("FunctionContext::new({})",
|
||||
instance.map_or(String::new(), |i| i.to_string()));
|
||||
|
||||
let debug_context = debuginfo::create_function_debug_context(ccx,
|
||||
inlined_id.unwrap_or(ast::DUMMY_NODE_ID), param_substs, llfndecl);
|
||||
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 {
|
||||
@ -1431,10 +1432,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))
|
||||
@ -1448,6 +1450,18 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||
None
|
||||
};
|
||||
|
||||
let span = inlined_id.and_then(|id| ccx.tcx().map.opt_span(id));
|
||||
|
||||
let debug_context = if let (false, Some(definition)) = (no_debug, definition) {
|
||||
let (instance, sig, abi, generics, name) = definition;
|
||||
debuginfo::create_function_debug_context(ccx, instance, sig,
|
||||
abi, generics, name,
|
||||
span.unwrap_or(DUMMY_SP),
|
||||
llfndecl)
|
||||
} else {
|
||||
debuginfo::empty_function_debug_context(ccx)
|
||||
};
|
||||
|
||||
FunctionContext {
|
||||
needs_ret_allocas: nested_returns && mir.is_none(),
|
||||
mir: mir,
|
||||
@ -1462,7 +1476,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||
lldropflag_hints: RefCell::new(DropFlagHintsMap::new()),
|
||||
fn_ty: fn_ty,
|
||||
param_substs: param_substs,
|
||||
span: inlined_id.and_then(|id| ccx.tcx().map.opt_span(id)),
|
||||
span: span,
|
||||
block_arena: block_arena,
|
||||
lpad_arena: TypedArena::new(),
|
||||
ccx: ccx,
|
||||
@ -1815,8 +1829,10 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
llfndecl: ValueRef,
|
||||
instance: Instance<'tcx>,
|
||||
inlined_id: ast::NodeId,
|
||||
fn_ty: FnType,
|
||||
sig: &ty::FnSig<'tcx>,
|
||||
abi: Abi,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
name: Option<ast::Name>,
|
||||
closure_env: closure::ClosureEnv) {
|
||||
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
|
||||
|
||||
@ -1829,14 +1845,19 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
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(instance), &arena);
|
||||
fcx = FunctionContext::new(ccx, llfndecl, fn_ty,
|
||||
Some((instance, sig, abi, generics, name)), &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);
|
||||
@ -1891,10 +1912,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.
|
||||
@ -1907,25 +1926,27 @@ 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 scheme = ccx.tcx().lookup_item_type(def_id);
|
||||
let fn_ty = scheme.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,
|
||||
Instance::new(def_id, param_substs),
|
||||
id,
|
||||
fn_ty,
|
||||
&sig,
|
||||
abi,
|
||||
&scheme.generics,
|
||||
Some(ccx.tcx().item_name(def_id)),
|
||||
closure::ClosureEnv::NotClosure);
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,10 @@ 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, &[]);
|
||||
|
||||
// This is not quite right. It should actually inherit
|
||||
// the generics of the enclosing function.
|
||||
let generics = ty::Generics::empty();
|
||||
|
||||
trans_closure(ccx,
|
||||
decl,
|
||||
@ -242,8 +245,10 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
||||
llfn,
|
||||
Instance::new(closure_def_id, param_substs),
|
||||
id,
|
||||
fn_ty,
|
||||
&sig,
|
||||
Abi::RustCall,
|
||||
&generics,
|
||||
None,
|
||||
ClosureEnv::Closure(closure_def_id, id));
|
||||
|
||||
// Don't hoist this to the top of the function. It's perfectly legitimate
|
||||
|
@ -14,8 +14,7 @@ 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::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
|
||||
use self::namespace::{namespace_for_item, NamespaceTreeNode};
|
||||
use self::type_names::compute_debuginfo_type_name;
|
||||
use self::metadata::{type_metadata, diverging_type_metadata};
|
||||
@ -25,20 +24,17 @@ use self::source_loc::InternalDebugLocation;
|
||||
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::ty::subst::Substs;
|
||||
use rustc::hir;
|
||||
|
||||
use abi::Abi;
|
||||
use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
|
||||
use monomorphize;
|
||||
use rustc::infer;
|
||||
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 libc::c_uint;
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -49,7 +45,7 @@ use std::rc::Rc;
|
||||
use syntax::codemap::{Span, Pos};
|
||||
use syntax::{ast, codemap};
|
||||
use syntax::attr::IntType;
|
||||
use syntax::parse::token::{self, special_idents};
|
||||
use syntax::parse::token;
|
||||
|
||||
pub mod gdb;
|
||||
mod utils;
|
||||
@ -214,6 +210,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, InternalDebugLocation::UnknownLocation);
|
||||
FunctionDebugContext::FunctionWithoutDebugInfo
|
||||
}
|
||||
|
||||
/// Creates the function-specific debug context.
|
||||
///
|
||||
/// Returns the FunctionDebugContext for the function which holds state needed
|
||||
@ -221,8 +229,12 @@ 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,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
name: Option<ast::Name>,
|
||||
span: Span,
|
||||
llfn: ValueRef) -> FunctionDebugContext {
|
||||
if cx.sess().opts.debuginfo == NoDebugInfo {
|
||||
return FunctionDebugContext::DebugInfoDisabled;
|
||||
@ -232,102 +244,6 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
// 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)
|
||||
};
|
||||
|
||||
// This can be the case for functions inlined from another crate
|
||||
if span == codemap::DUMMY_SP {
|
||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
||||
@ -337,19 +253,19 @@ 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)
|
||||
};
|
||||
|
||||
// Get_template_parameters() will append a `<...>` clause to the function
|
||||
// name if necessary.
|
||||
let mut function_name = name.to_string();
|
||||
let mut function_name = name.map(|name| name.to_string()).unwrap_or_else(|| {
|
||||
// We do this only for closures atm.
|
||||
format!("fn{}", token::gensym("fn"))
|
||||
});
|
||||
let template_parameters = get_template_parameters(cx,
|
||||
generics,
|
||||
param_substs,
|
||||
instance.substs,
|
||||
file_metadata,
|
||||
&mut function_name);
|
||||
|
||||
@ -357,9 +273,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
// 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, containing_scope) = if name.is_some() {
|
||||
let namespace_node = namespace_for_item(cx, instance.def);
|
||||
let linkage_name = namespace_node.mangled_name_of_contained_item(
|
||||
&function_name[..]);
|
||||
let containing_scope = namespace_node.scope;
|
||||
@ -368,11 +283,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
(function_name.clone(), file_metadata)
|
||||
};
|
||||
|
||||
// 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 linkage_name = CString::new(linkage_name).unwrap();
|
||||
@ -395,54 +309,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 +361,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);
|
||||
let actual_types = param_substs.types.as_slice();
|
||||
|
||||
// Only true for static default methods:
|
||||
let has_self_type = self_type.is_some();
|
||||
|
||||
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<DIDescriptor> =
|
||||
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,17 +402,35 @@ 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[..]);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
variable_name: ast::Name,
|
||||
variable_type: Ty<'tcx>,
|
||||
|
@ -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,15 +77,6 @@ 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;
|
||||
|
Loading…
Reference in New Issue
Block a user