diff options
| author | Michael Woerister <michaelwoerister@gmail> | 2013-08-16 18:46:29 +0200 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@gmail> | 2013-08-22 10:58:01 +0200 |
| commit | 8c09e2b790eeacc90ed8b9bfa4d04bf6624ad51c (patch) | |
| tree | e8b63d732f8e6ddef205eb0d1123961f84834d09 | |
| parent | f51d30d7295507d5075a61d8bf9f17be8ad3fbe9 (diff) | |
| download | rust-8c09e2b790eeacc90ed8b9bfa4d04bf6624ad51c.tar.gz rust-8c09e2b790eeacc90ed8b9bfa4d04bf6624ad51c.zip | |
debuginfo: Big cleanup refactoring and support for foreign_item_fn.
| -rw-r--r-- | src/librustc/middle/trans/base.rs | 20 | ||||
| -rw-r--r-- | src/librustc/middle/trans/debuginfo.rs | 189 |
2 files changed, 101 insertions, 108 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f19decaa38c..9d5d80373ab 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -136,6 +136,13 @@ fn fcx_has_nonzero_span(fcx: &FunctionContext) -> bool { } } +fn span_is_empty(opt_span: &Option<span>) -> bool { + match *opt_span { + None => true, + Some(span) => *span.lo == 0 && *span.hi == 0 + } +} + struct StatRecorder<'self> { ccx: @mut CrateContext, name: &'self str, @@ -1623,6 +1630,13 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, } }; let uses_outptr = type_of::return_uses_outptr(ccx.tcx, substd_output_type); + + let debug_context = if id != -1 && ccx.sess.opts.debuginfo && !span_is_empty(&sp) { + Some(debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl)) + } else { + None + }; + let fcx = @mut FunctionContext { llfn: llfndecl, llenv: unsafe { @@ -1643,7 +1657,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, span: sp, path: path, ccx: ccx, - debug_context: None, + debug_context: debug_context, }; fcx.llenv = unsafe { llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint) @@ -1880,10 +1894,6 @@ pub fn trans_closure(ccx: @mut CrateContext, set_fixed_stack_segment(fcx.llfn); } - if ccx.sess.opts.debuginfo && fcx_has_nonzero_span(fcx) { - debuginfo::create_function_metadata(fcx); - } - // Create the first basic block in the function and keep a handle on it to // pass to finish_fn later. let bcx_top = fcx.entry_bcx.unwrap(); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index f5073cc71e5..0f9fa61c668 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -98,9 +98,7 @@ pub struct DebugContext { priv builder: DIBuilderRef, priv curr_loc: (uint, uint), priv created_files: HashMap<~str, DIFile>, - priv created_functions: HashMap<FunctionCacheKey, DISubprogram>, - priv created_blocks: HashMap<ast::NodeId, DILexicalBlock>, - priv created_types: HashMap<uint, DIType> + priv created_types: HashMap<uint, DIType>, } impl DebugContext { @@ -115,29 +113,14 @@ impl DebugContext { builder: builder, curr_loc: (0, 0), created_files: HashMap::new(), - created_functions: HashMap::new(), - created_blocks: HashMap::new(), - created_types: HashMap::new() + created_types: HashMap::new(), }; } } -#[deriving(Eq,IterBytes)] -struct FunctionCacheKey { - // Use the address of the llvm function (FunctionContext::llfn) as key for the cache. This - // nicely takes care of monomorphization, where two specializations will have the same - // ast::NodeId but different llvm functions (each needing its own debug description). - priv llfn: ValueRef -} - -impl FunctionCacheKey { - fn for_function_context(fcx: &FunctionContext) -> FunctionCacheKey { - FunctionCacheKey { llfn: fcx.llfn } - } -} - pub struct FunctionDebugContext { priv scope_map: HashMap<ast::NodeId, DIScope>, + priv fn_metadata: DISubprogram, priv argument_counter: uint, } @@ -194,7 +177,14 @@ pub fn create_self_argument_metadata(bcx: @mut Block, let loc = span_start(cx, span); let type_metadata = type_metadata(cx, variable_type, span); - let scope = create_function_metadata(bcx.fcx); + let scope = bcx.fcx.debug_context.get_ref().fn_metadata; + + let argument_index = { + let counter = &mut bcx.fcx.debug_context.get_mut_ref().argument_counter; + let argument_index = *counter; + *counter += 1; + argument_index as c_uint + }; let var_metadata = do cx.sess.str_of(special_idents::self_).to_c_str().with_ref |name| { unsafe { @@ -208,7 +198,7 @@ pub fn create_self_argument_metadata(bcx: @mut Block, type_metadata, false, 0, - 1) + argument_index) } }; @@ -243,7 +233,7 @@ pub fn create_argument_metadata(bcx: @mut Block, let def_map = cx.tcx.def_map; let file_metadata = file_metadata(cx, filename); - let scope = create_function_metadata(fcx); + let scope = bcx.fcx.debug_context.get_ref().fn_metadata;//create_function_metadata(fcx); do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| { @@ -318,33 +308,25 @@ pub fn update_source_pos(fcx: &FunctionContext, set_debug_location(cx, scope, loc.line, loc.col.to_uint()); } -/// Creates debug information for the given function. -/// -/// Adds the created metadata nodes directly to the crate's IR. -/// The return value should be ignored if called from outside of the debuginfo module. -pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { - let cx = fcx.ccx; - let cache_key = FunctionCacheKey::for_function_context(fcx); - - match dbg_cx(cx).created_functions.find_copy(&cache_key) { - Some(fn_metadata) => { - assert!(fcx.debug_context.is_some()); - return fn_metadata; - } - None => { /* fallthrough */} - } +pub fn create_function_debug_context(cx: &mut CrateContext, + fn_ast_id: ast::NodeId, + param_substs: Option<@param_substs>, + llfn: ValueRef) -> ~FunctionDebugContext { + assert!(fn_ast_id != -1); let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty }; - let fnitem = cx.tcx.items.get_copy(&fcx.id); - let (ident, fn_decl, generics, span) = match fnitem { + let fnitem = cx.tcx.items.get_copy(&fn_ast_id); + let (ident, fn_decl, generics, top_level_block, span) = match fnitem { ast_map::node_item(ref item, _) => { match item.node { - ast::item_fn(ref fn_decl, _, _, ref generics, _) => { - (item.ident, fn_decl, generics, item.span) + ast::item_fn(ref fn_decl, _, _, ref generics, ref top_level_block) => { + (item.ident, fn_decl, generics, Some(top_level_block), item.span) + } + _ => { + cx.sess.span_bug(item.span, + "create_function_debug_context: item bound to non-function"); } - _ => fcx.ccx.sess.span_bug(item.span, - "create_function_metadata: item bound to non-function") } } ast_map::node_method( @@ -352,25 +334,27 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { decl: ref fn_decl, ident: ident, generics: ref generics, + body: ref top_level_block, span: span, _ }, _, _) => { - (ident, fn_decl, generics, span) + (ident, fn_decl, generics, Some(top_level_block), span) } ast_map::node_expr(ref expr) => { match expr.node { - ast::expr_fn_block(ref fn_decl, _) => { + ast::expr_fn_block(ref fn_decl, ref top_level_block) => { let name = gensym_name("fn"); (name, fn_decl, // This is not quite right. It should actually inherit the generics of the // enclosing function. &empty_generics, + Some(top_level_block), expr.span) } - _ => fcx.ccx.sess.span_bug(expr.span, - "create_function_metadata: expected an expr_fn_block here") + _ => cx.sess.span_bug(expr.span, + "create_function_debug_context: expected an expr_fn_block here") } } ast_map::node_trait_method( @@ -379,34 +363,43 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { decl: ref fn_decl, ident: ident, generics: ref generics, + body: ref top_level_block, span: span, _ }), _, _) => { - (ident, fn_decl, generics, span) + (ident, fn_decl, generics, Some(top_level_block), span) + } + ast_map::node_foreign_item(@ast::foreign_item { + ident: ident, + node: ast::foreign_item_fn(ref fn_decl, ref generics), + span: span, + _ + }, + _, + _, + _) => { + (ident, fn_decl, generics, None, span) } - _ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem)) + _ => cx.sess.bug(fmt!("create_function_debug_context: unexpected sort of node: %?", fnitem)) }; - debug!("create_function_metadata: %s, %s", - cx.sess.str_of(ident), - cx.sess.codemap.span_to_str(span)); - let loc = span_start(cx, span); let file_metadata = file_metadata(cx, loc.file.name); let function_type_metadata = unsafe { - let fn_signature = get_function_signature(fcx, fn_decl); + let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs); 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 = cx.sess.str_of(ident).to_owned(); - let template_parameters = get_template_parameters(fcx, - generics, - file_metadata, - &mut function_name); + let template_parameters = if cx.sess.opts.extra_debuginfo { + get_template_parameters(cx, generics, param_substs, file_metadata, &mut function_name) + } else { + ptr::null() + }; let fn_metadata = do function_name.to_c_str().with_ref |function_name| { unsafe { @@ -423,46 +416,29 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { loc.line as c_uint, FlagPrototyped as c_uint, cx.sess.opts.optimize != session::No, - fcx.llfn, + llfn, template_parameters, ptr::null()) } }; - dbg_cx(cx).created_functions.insert(cache_key, fn_metadata); - // Initialize fn debug context (including scope map) - { - assert!(fcx.debug_context.is_none()); - - let mut fn_debug_context = ~FunctionDebugContext { - scope_map: HashMap::new(), - argument_counter: if fcx.llself.is_some() { 2 } else { 1 } - }; - - let entry_block_id = fcx.entry_bcx.get_ref().node_info.get_ref().id; - let entry_block = cx.tcx.items.get(&entry_block_id); - - match *entry_block { - ast_map::node_block(ref block) => { - let scope_map = &mut fn_debug_context.scope_map; - let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat }; - - populate_scope_map(cx, arg_pats, block, fn_metadata, scope_map); - } - _ => cx.sess.span_bug(span, - fmt!("debuginfo::create_function_metadata() - \ - FunctionContext::entry_bcx::node_info points to wrong type of ast_map \ - entry. Expected: ast_map::node_block, actual: %?", *entry_block)) - } + let mut fn_debug_context = ~FunctionDebugContext { + scope_map: HashMap::new(), + fn_metadata: fn_metadata, + argument_counter: 1, + }; - fcx.debug_context = Some(fn_debug_context); - } + let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat }; + populate_scope_map(cx, arg_pats, top_level_block, fn_metadata, &mut fn_debug_context.scope_map); - return fn_metadata; + return fn_debug_context; - fn get_function_signature(fcx: &FunctionContext, fn_decl: &ast::fn_decl) -> DIArray { - let cx = fcx.ccx; + fn get_function_signature(cx: &mut CrateContext, + fn_ast_id: ast::NodeId, + fn_decl: &ast::fn_decl, + param_substs: Option<@param_substs>) -> DIArray { + //let cx = fcx.ccx; if !cx.sess.opts.extra_debuginfo { return create_DIArray(DIB(cx), []); @@ -476,8 +452,8 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { signature.push(ptr::null()); } _ => { - let return_type = ty::node_id_to_type(cx.tcx, fcx.id); - let return_type = match fcx.param_substs { + let return_type = ty::node_id_to_type(cx.tcx, fn_ast_id); + let return_type = match param_substs { None => return_type, Some(substs) => { ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type) @@ -491,7 +467,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { // arguments types for arg in fn_decl.inputs.iter() { let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id); - let arg_type = match fcx.param_substs { + let arg_type = match param_substs { None => arg_type, Some(substs) => { ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, arg_type) @@ -504,14 +480,13 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { return create_DIArray(DIB(cx), signature); } - fn get_template_parameters(fcx: &FunctionContext, + fn get_template_parameters(cx: &mut CrateContext, generics: &ast::Generics, + param_substs: Option<@param_substs>, file_metadata: DIFile, name_to_append_suffix_to: &mut ~str) -> DIArray { - let cx = fcx.ccx; - - let self_type = match fcx.param_substs { + let self_type = match param_substs { Some(@param_substs{ self_ty: self_type, _ }) => self_type, _ => None }; @@ -561,7 +536,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { } // Handle other generic parameters - let actual_types = match fcx.param_substs { + let actual_types = match param_substs { Some(@param_substs { tys: ref types, _ }) => types, None => { return create_DIArray(DIB(cx), template_params); @@ -604,7 +579,6 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram { - //=------------------------------------------------------------------------------------------------- // Module-Internal debug info creation functions //=------------------------------------------------------------------------------------------------- @@ -1424,7 +1398,11 @@ fn type_metadata(cx: &mut CrateContext, ty::ty_tup(ref elements) => { tuple_metadata(cx, t, *elements, span) }, - _ => cx.sess.bug("debuginfo: unexpected type in type_metadata") + ty::ty_opaque_box => { + cx.sess.span_note(span, "debuginfo for ty_opaque_box NYI"); + unimplemented_type_metadata(cx, t) + } + _ => cx.sess.bug(fmt!("debuginfo: unexpected type in type_metadata: %?", sty)) }; dbg_cx(cx).created_types.insert(type_id, type_metadata); @@ -1498,7 +1476,7 @@ fn assert_fcx_has_span(fcx: &FunctionContext) { // shadowing. fn populate_scope_map(cx: &mut CrateContext, arg_pats: &[@ast::pat], - fn_entry_block: &ast::Block, + fn_entry_block: Option<&ast::Block>, fn_metadata: DISubprogram, scope_map: &mut HashMap<ast::NodeId, DIScope>) { let def_map = cx.tcx.def_map; @@ -1519,7 +1497,10 @@ fn populate_scope_map(cx: &mut CrateContext, } } - walk_block(cx, fn_entry_block, &mut scope_stack, scope_map); + for &fn_entry_block in fn_entry_block.iter() { + walk_block(cx, fn_entry_block, &mut scope_stack, scope_map); + } + // local helper functions for walking the AST. @@ -1898,7 +1879,9 @@ fn populate_scope_map(cx: &mut CrateContext, do with_new_scope(cx, arm_span, scope_stack, scope_map) |cx, scope_stack, scope_map| { - walk_pattern(cx, arm_ref.pats[0], scope_stack, scope_map); + for &pat in arm_ref.pats.iter() { + walk_pattern(cx, pat, scope_stack, scope_map); + } for &@ref guard_exp in arm_ref.guard.iter() { walk_expr(cx, guard_exp, scope_stack, scope_map) |
