Skip to content

Commit 0599bfc

Browse files
---
yaml --- r: 85452 b: refs/heads/dist-snap c: 6c49c2d h: refs/heads/master v: v3
1 parent 57f14d9 commit 0599bfc

File tree

3 files changed

+159
-88
lines changed

3 files changed

+159
-88
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: 0983ebe5310d4eb6d289f636f7ed0536c08bbc0e
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: 907633b1bfc757cf9a415e4573098f58881469f2
9+
refs/heads/dist-snap: 6c49c2df763f8cf1817bc651582deba8bb35a29d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/src/librustc/middle/trans/debuginfo.rs

Lines changed: 142 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ This file consists of three conceptual sections:
5151

5252
use driver::session;
5353
use lib::llvm::llvm;
54-
use lib::llvm::{ModuleRef, ContextRef};
54+
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
5555
use lib::llvm::debuginfo::*;
5656
use middle::trans::common::*;
5757
use middle::trans::machine;
@@ -97,7 +97,7 @@ pub struct DebugContext {
9797
priv builder: DIBuilderRef,
9898
priv curr_loc: (uint, uint),
9999
priv created_files: HashMap<~str, DIFile>,
100-
priv created_functions: HashMap<ast::NodeId, DISubprogram>,
100+
priv created_functions: HashMap<FunctionCacheKey, DISubprogram>,
101101
priv created_blocks: HashMap<ast::NodeId, DILexicalBlock>,
102102
priv created_types: HashMap<uint, DIType>
103103
}
@@ -121,6 +121,19 @@ impl DebugContext {
121121
}
122122
}
123123

124+
#[deriving(Eq,IterBytes)]
125+
struct FunctionCacheKey {
126+
// Use the address of the llvm function (FunctionContext::llfn) as key for the cache. This
127+
// nicely takes care of monomorphization, where two specializations will have the same
128+
// ast::NodeId but different llvm functions (each needing its own debug description).
129+
priv llfn: ValueRef
130+
}
131+
132+
impl FunctionCacheKey {
133+
fn for_function_context(fcx: &FunctionContext) -> FunctionCacheKey {
134+
FunctionCacheKey { llfn: fcx.llfn }
135+
}
136+
}
124137

125138
pub struct FunctionDebugContext {
126139
priv scope_map: HashMap<ast::NodeId, DIScope>,
@@ -269,13 +282,22 @@ pub fn update_source_pos(fcx: &FunctionContext,
269282
/// The return value should be ignored if called from outside of the debuginfo module.
270283
pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
271284
let cx = fcx.ccx;
285+
let cache_key = FunctionCacheKey::for_function_context(fcx);
286+
287+
match dbg_cx(cx).created_functions.find_copy(&cache_key) {
288+
Some(fn_metadata) => {
289+
assert!(fcx.debug_context.is_some());
290+
return fn_metadata;
291+
}
292+
None => { /* fallthrough */}
293+
}
272294

273295
let fnitem = cx.tcx.items.get_copy(&fcx.id);
274-
let (ident, fn_decl, id, generics) = match fnitem {
296+
let (ident, fn_decl, generics, span) = match fnitem {
275297
ast_map::node_item(ref item, _) => {
276298
match item.node {
277299
ast::item_fn(ref fn_decl, _, _, ref generics, _) => {
278-
(item.ident, ty, item.id, Some(generics))
300+
(item.ident, fn_decl, Some(generics), item.span)
279301
}
280302
_ => fcx.ccx.sess.span_bug(item.span,
281303
"create_function_metadata: item bound to non-function")
@@ -284,23 +306,24 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
284306
ast_map::node_method(
285307
@ast::method {
286308
decl: ref fn_decl,
287-
id: id,
288309
ident: ident,
289310
generics: ref generics,
311+
span: span,
290312
_
291313
},
292314
_,
293315
_) => {
294-
(ident, fn_decl, id, Some(generics))
316+
(ident, fn_decl, Some(generics), span)
295317
}
296318
ast_map::node_expr(ref expr) => {
297319
match expr.node {
298320
ast::expr_fn_block(ref fn_decl, _) => {
299321
let name = gensym_name("fn");
300-
(name, fn_decl, expr.id,
322+
(name, fn_decl,
301323
// This is not quite right. It should actually inherit the generics of the
302324
// enclosing function.
303-
None)
325+
None,
326+
expr.span)
304327
}
305328
_ => fcx.ccx.sess.span_bug(expr.span,
306329
"create_function_metadata: expected an expr_fn_block here")
@@ -310,126 +333,148 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
310333
@ast::provided(
311334
@ast::method {
312335
decl: ref fn_decl,
313-
id: id,
314336
ident: ident,
315337
generics: ref generics,
338+
span: span,
316339
_
317340
}),
318341
_,
319342
_) => {
320-
(ident, fn_decl, id, Some(generics))
343+
(ident, fn_decl, Some(generics), span)
321344
}
322345
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
323346
};
324347

325-
match dbg_cx(cx).created_functions.find_copy(&id) {
326-
Some(fn_metadata) => return fn_metadata,
327-
None => ()
328-
}
329-
330-
let span = match fcx.span {
331-
Some(value) => value,
332-
None => codemap::dummy_sp()
333-
};
334-
335348
debug!("create_function_metadata: %s, %s",
336349
cx.sess.str_of(ident),
337350
cx.sess.codemap.span_to_str(span));
338351

339352
let loc = span_start(cx, span);
340353
let file_metadata = file_metadata(cx, loc.file.name);
341354

342-
let return_type_metadata = if cx.sess.opts.extra_debuginfo {
355+
let function_type_metadata = unsafe {
356+
let fn_signature = get_function_signature(fcx, fn_decl);
357+
llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
358+
};
359+
360+
let mut function_name = cx.sess.str_of(ident).to_owned();
361+
let template_parameters = get_template_parameters(fcx,
362+
generics,
363+
file_metadata,
364+
span,
365+
&mut function_name);
366+
367+
let fn_metadata = do function_name.to_c_str().with_ref |function_name| {
368+
unsafe {
369+
llvm::LLVMDIBuilderCreateFunction(
370+
DIB(cx),
371+
file_metadata,
372+
function_name,
373+
function_name,
374+
file_metadata,
375+
loc.line as c_uint,
376+
function_type_metadata,
377+
false,
378+
true,
379+
loc.line as c_uint,
380+
FlagPrototyped as c_uint,
381+
cx.sess.opts.optimize != session::No,
382+
fcx.llfn,
383+
template_parameters,
384+
ptr::null())
385+
}
386+
};
387+
388+
dbg_cx(cx).created_functions.insert(cache_key, fn_metadata);
389+
390+
// Initialize fn debug context (including scope map)
391+
{
392+
assert!(fcx.debug_context.is_none());
393+
394+
let mut fn_debug_context = ~FunctionDebugContext::new();
395+
let entry_block_id = fcx.entry_bcx.get_ref().node_info.get_ref().id;
396+
let entry_block = cx.tcx.items.get(&entry_block_id);
397+
398+
match *entry_block {
399+
ast_map::node_block(ref block) => {
400+
let scope_map = &mut fn_debug_context.scope_map;
401+
let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat };
402+
403+
populate_scope_map(cx, arg_pats, block, fn_metadata, scope_map);
404+
}
405+
_ => cx.sess.span_bug(span,
406+
fmt!("debuginfo::create_function_metadata() - \
407+
FunctionContext::entry_bcx::node_info points to wrong type of ast_map entry. \
408+
Expected: ast_map::node_block, actual: %?", *entry_block))
409+
}
410+
411+
fcx.debug_context = Some(fn_debug_context);
412+
}
413+
414+
return fn_metadata;
415+
416+
fn get_function_signature(fcx: &FunctionContext, fn_decl: &ast::fn_decl) -> DIArray {
417+
let cx = fcx.ccx;
418+
419+
if !cx.sess.opts.extra_debuginfo {
420+
return create_DIArray(DIB(cx), []);
421+
}
422+
423+
let mut signature = vec::with_capacity(fn_decl.inputs.len() + 1);
424+
425+
// Return type -- llvm::DIBuilder wants this at index 0
343426
match fn_decl.output.node {
344-
ast::ty_nil => ptr::null(),
427+
ast::ty_nil => {
428+
signature.push(ptr::null());
429+
}
345430
_ => {
346-
let return_type = ty::node_id_to_type(cx.tcx, id);
431+
let return_type = ty::node_id_to_type(cx.tcx, fcx.id);
347432
let return_type = match fcx.param_substs {
348433
None => return_type,
349434
Some(substs) => {
350435
ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
351436
}
352437
};
353438

354-
type_metadata(cx, return_type, ret_ty.span)
439+
signature.push(type_metadata(cx, return_type, codemap::dummy_sp()));
355440
}
356441
}
357-
} else {
358-
ptr::null()
359-
};
360442

361-
let fn_ty = unsafe {
362-
llvm::LLVMDIBuilderCreateSubroutineType(
363-
DIB(cx),
364-
file_metadata,
365-
create_DIArray(DIB(cx), [return_type_metadata]))
366-
};
367-
368-
let template_parameters: DIArray = get_template_parameters(cx, fcx, generics, file_metadata, span);
369-
370-
let fn_metadata =
371-
do cx.sess.str_of(ident).with_c_str |name| {
372-
do cx.sess.str_of(ident).with_c_str |linkage| {
373-
unsafe {
374-
llvm::LLVMDIBuilderCreateFunction(
375-
DIB(cx),
376-
file_metadata,
377-
name,
378-
linkage,
379-
file_metadata,
380-
loc.line as c_uint,
381-
fn_ty,
382-
false,
383-
true,
384-
loc.line as c_uint,
385-
FlagPrototyped as c_uint,
386-
cx.sess.opts.optimize != session::No,
387-
fcx.llfn,
388-
template_parameters,
389-
ptr::null())
390-
}
391-
}};
392-
393-
assert!(fcx.debug_context.is_none());
394-
395-
let mut fn_debug_context = ~FunctionDebugContext::new();
396-
let entry_block_id = fcx.entry_bcx.get_ref().node_info.get_ref().id;
397-
let entry_block = cx.tcx.items.get(&entry_block_id);
398-
399-
match *entry_block {
400-
ast_map::node_block(ref block) => {
401-
let scope_map = &mut fn_debug_context.scope_map;
402-
let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat };
443+
// arguments types
444+
for arg in fn_decl.inputs.iter() {
445+
let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id);
446+
let arg_type = match fcx.param_substs {
447+
None => arg_type,
448+
Some(substs) => {
449+
ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, arg_type)
450+
}
451+
};
403452

404-
populate_scope_map(cx, arg_pats, block, fn_metadata, scope_map);
453+
signature.push(type_metadata(cx, arg_type, codemap::dummy_sp()));
405454
}
406-
_ => cx.sess.span_bug(span,
407-
fmt!("debuginfo::create_function_metadata() - \
408-
FunctionContext::entry_bcx::node_info points to wrong type of ast_map entry. \
409-
Expected: ast_map::node_block, actual: %?", *entry_block))
410-
}
411-
412-
fcx.debug_context = Some(fn_debug_context);
413455

414-
dbg_cx(cx).created_functions.insert(id, fn_metadata);
415-
return fn_metadata;
456+
return create_DIArray(DIB(cx), signature);
457+
}
416458

417-
fn get_template_parameters(cx: &mut CrateContext,
418-
fcx: &FunctionContext,
459+
fn get_template_parameters(fcx: &FunctionContext,
419460
generics: Option<&ast::Generics>,
420461
file_metadata: DIFile,
421-
span: span) -> DIArray {
462+
span: span,
463+
name_to_append_suffix_to: &mut ~str)
464+
-> DIArray {
422465
// Normalize cases
423466
let generics = match generics {
424467
Some(generics_ref) if generics_ref.is_type_parameterized() => Some(generics_ref),
425468
_ => None
426469
};
427470

471+
let cx = fcx.ccx;
472+
428473
match generics {
429474
None => {
430475
if (fcx.param_substs.is_some()) {
431476
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
432-
Mismatch between ast::Generics and FunctionContext::param_substs 111");
477+
Mismatch between ast::Generics and FunctionContext::param_substs");
433478
}
434479

435480
return ptr::null();
@@ -442,22 +487,31 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
442487
}
443488
None => {
444489
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
445-
Mismatch between ast::Generics and FunctionContext::param_substs 222");
490+
Mismatch between ast::Generics and FunctionContext::param_substs");
446491
}
447492
};
448493

494+
name_to_append_suffix_to.push_char('<');
495+
449496
let template_params: ~[DIDescriptor] = do generics
450497
.ty_params
451498
.iter()
452499
.enumerate()
453-
.transform |(index, &ast::TyParam{ ident: ident, _ })| {
500+
.map |(index, &ast::TyParam{ ident: ident, _ })| {
454501

455502
let actual_type = actual_types[index];
456503
let actual_type_metadata = type_metadata(cx,
457504
actual_type,
458505
codemap::dummy_sp());
459506

460-
do cx.sess.str_of(ident).as_c_str |name| {
507+
// Add actual type name to <...> clause of function name
508+
let actual_type_name = ty_to_str(cx.tcx, actual_type);
509+
name_to_append_suffix_to.push_str(actual_type_name);
510+
if index != generics.ty_params.len() - 1 {
511+
name_to_append_suffix_to.push_str(", ");
512+
}
513+
514+
do cx.sess.str_of(ident).to_c_str().with_ref |name| {
461515
unsafe {
462516
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
463517
DIB(cx),
@@ -471,6 +525,8 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
471525
}
472526
}.collect();
473527

528+
name_to_append_suffix_to.push_char('>');
529+
474530
return create_DIArray(DIB(cx), template_params);
475531
}
476532
}

branches/dist-snap/src/test/debug-info/generic-function.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@
3232
// check:$6 = {{3.5, 4}, {4, 3.5}}
3333
// debugger:continue
3434

35+
// debugger:finish
36+
// debugger:print *t0
37+
// check:$7 = 5
38+
// debugger:print *t1
39+
// check:$8 = {a = 6, b = 7.5}
40+
// debugger:print ret
41+
// check:$9 = {{5, {a = 6, b = 7.5}}, {{a = 6, b = 7.5}, 5}}
42+
// debugger:continue
43+
44+
#[deriving(Clone)]
45+
struct Struct {
46+
a: int,
47+
b: float
48+
}
49+
3550
fn dup_tup<T0: Clone, T1: Clone>(t0: &T0, t1: &T1) -> ((T0, T1), (T1, T0)) {
3651
let ret = ((t0.clone(), t1.clone()), (t1.clone(), t0.clone()));
3752
zzz();
@@ -42,7 +57,7 @@ fn main() {
4257

4358
let _ = dup_tup(&1, &2.5);
4459
let _ = dup_tup(&3.5, &4_u16);
45-
60+
let _ = dup_tup(&5, &Struct { a: 6, b: 7.5 });
4661
}
4762

4863
fn zzz() {()}

0 commit comments

Comments
 (0)