Skip to content

Commit 907633b

Browse files
debuginfo: Generate template type parameters for generic functions.
Conflicts: src/librustc/lib/llvm.rs src/librustc/middle/trans/debuginfo.rs src/rustllvm/RustWrapper.cpp src/rustllvm/rustllvm.def.in
1 parent 1dec27b commit 907633b

File tree

5 files changed

+165
-9
lines changed

5 files changed

+165
-9
lines changed

src/librustc/lib/llvm.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,16 @@ pub mod llvm {
20862086

20872087
#[fast_ffi]
20882088
pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
2089+
2090+
#[fast_ffi]
2091+
pub fn LLVMDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
2092+
Scope: ValueRef,
2093+
Name: *c_char,
2094+
Ty: ValueRef,
2095+
File: ValueRef,
2096+
LineNo: c_uint,
2097+
ColumnNo: c_uint)
2098+
-> ValueRef;
20892099
}
20902100
}
20912101

src/librustc/middle/trans/debuginfo.rs

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,11 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
271271
let cx = fcx.ccx;
272272

273273
let fnitem = cx.tcx.items.get_copy(&fcx.id);
274-
let (ident, fn_decl, id) = match fnitem {
274+
let (ident, fn_decl, id, generics) = match fnitem {
275275
ast_map::node_item(ref item, _) => {
276276
match item.node {
277-
ast::item_fn(ref fn_decl, _, _, _, _) => {
278-
(item.ident, fn_decl, item.id)
277+
ast::item_fn(ref fn_decl, _, _, ref generics, _) => {
278+
(item.ident, ty, item.id, Some(generics))
279279
}
280280
_ => fcx.ccx.sess.span_bug(item.span,
281281
"create_function_metadata: item bound to non-function")
@@ -286,17 +286,21 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
286286
decl: ref fn_decl,
287287
id: id,
288288
ident: ident,
289+
generics: ref generics,
289290
_
290291
},
291292
_,
292293
_) => {
293-
(ident, fn_decl, id)
294+
(ident, fn_decl, id, Some(generics))
294295
}
295296
ast_map::node_expr(ref expr) => {
296297
match expr.node {
297298
ast::expr_fn_block(ref fn_decl, _) => {
298299
let name = gensym_name("fn");
299-
(name, fn_decl, expr.id)
300+
(name, fn_decl, expr.id,
301+
// This is not quite right. It should actually inherit the generics of the
302+
// enclosing function.
303+
None)
300304
}
301305
_ => fcx.ccx.sess.span_bug(expr.span,
302306
"create_function_metadata: expected an expr_fn_block here")
@@ -308,11 +312,12 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
308312
decl: ref fn_decl,
309313
id: id,
310314
ident: ident,
315+
generics: ref generics,
311316
_
312317
}),
313318
_,
314319
_) => {
315-
(ident, fn_decl, id)
320+
(ident, fn_decl, id, Some(generics))
316321
}
317322
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
318323
};
@@ -336,8 +341,18 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
336341

337342
let return_type_metadata = if cx.sess.opts.extra_debuginfo {
338343
match fn_decl.output.node {
339-
ast::ty_nil => ptr::null(),
340-
_ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), fn_decl.output.span)
344+
ast::ty_nil => ptr::null(),
345+
_ => {
346+
let return_type = ty::node_id_to_type(cx.tcx, id);
347+
let return_type = match fcx.param_substs {
348+
None => return_type,
349+
Some(substs) => {
350+
ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
351+
}
352+
};
353+
354+
type_metadata(cx, return_type, ret_ty.span)
355+
}
341356
}
342357
} else {
343358
ptr::null()
@@ -350,6 +365,8 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
350365
create_DIArray(DIB(cx), [return_type_metadata]))
351366
};
352367

368+
let template_parameters: DIArray = get_template_parameters(cx, fcx, generics, file_metadata, span);
369+
353370
let fn_metadata =
354371
do cx.sess.str_of(ident).with_c_str |name| {
355372
do cx.sess.str_of(ident).with_c_str |linkage| {
@@ -368,7 +385,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
368385
FlagPrototyped as c_uint,
369386
cx.sess.opts.optimize != session::No,
370387
fcx.llfn,
371-
ptr::null(),
388+
template_parameters,
372389
ptr::null())
373390
}
374391
}};
@@ -396,6 +413,68 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
396413

397414
dbg_cx(cx).created_functions.insert(id, fn_metadata);
398415
return fn_metadata;
416+
417+
fn get_template_parameters(cx: &mut CrateContext,
418+
fcx: &FunctionContext,
419+
generics: Option<&ast::Generics>,
420+
file_metadata: DIFile,
421+
span: span) -> DIArray {
422+
// Normalize cases
423+
let generics = match generics {
424+
Some(generics_ref) if generics_ref.is_type_parameterized() => Some(generics_ref),
425+
_ => None
426+
};
427+
428+
match generics {
429+
None => {
430+
if (fcx.param_substs.is_some()) {
431+
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
432+
Mismatch between ast::Generics and FunctionContext::param_substs 111");
433+
}
434+
435+
return ptr::null();
436+
}
437+
438+
Some(generics) => {
439+
let actual_types = match fcx.param_substs {
440+
Some(@param_substs { tys: ref actual_types, _}) => {
441+
actual_types
442+
}
443+
None => {
444+
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
445+
Mismatch between ast::Generics and FunctionContext::param_substs 222");
446+
}
447+
};
448+
449+
let template_params: ~[DIDescriptor] = do generics
450+
.ty_params
451+
.iter()
452+
.enumerate()
453+
.transform |(index, &ast::TyParam{ ident: ident, _ })| {
454+
455+
let actual_type = actual_types[index];
456+
let actual_type_metadata = type_metadata(cx,
457+
actual_type,
458+
codemap::dummy_sp());
459+
460+
do cx.sess.str_of(ident).as_c_str |name| {
461+
unsafe {
462+
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
463+
DIB(cx),
464+
file_metadata,
465+
name,
466+
actual_type_metadata,
467+
ptr::null(),
468+
0,
469+
0)
470+
}
471+
}
472+
}.collect();
473+
474+
return create_DIArray(DIB(cx), template_params);
475+
}
476+
}
477+
}
399478
}
400479

401480

src/rustllvm/RustWrapper.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,3 +838,21 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
838838
extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
839839
unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
840840
}
841+
842+
extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter(
843+
DIBuilderRef Builder,
844+
LLVMValueRef Scope,
845+
const char* Name,
846+
LLVMValueRef Ty,
847+
LLVMValueRef File = 0,
848+
unsigned LineNo = 0,
849+
unsigned ColumnNo = 0)
850+
{
851+
return wrap(Builder->createTemplateTypeParameter(
852+
unwrapDI<DIDescriptor>(Scope),
853+
Name,
854+
unwrapDI<DIType>(Ty),
855+
unwrapDI<MDNode*>(File),
856+
LineNo,
857+
ColumnNo));
858+
}

src/rustllvm/rustllvm.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,4 +613,5 @@ LLVMDIBuilderInsertDeclareBefore
613613
LLVMDIBuilderCreateEnumerator
614614
LLVMDIBuilderCreateEnumerationType
615615
LLVMDIBuilderCreateUnionType
616+
LLVMDIBuilderCreateTemplateTypeParameter
616617
LLVMSetUnnamedAddr
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
12+
13+
// compile-flags:-Z extra-debug-info
14+
// debugger:break zzz
15+
// debugger:run
16+
17+
// debugger:finish
18+
// debugger:print *t0
19+
// check:$1 = 1
20+
// debugger:print *t1
21+
// check:$2 = 2.5
22+
// debugger:print ret
23+
// check:$3 = {{1, 2.5}, {2.5, 1}}
24+
// debugger:continue
25+
26+
// debugger:finish
27+
// debugger:print *t0
28+
// check:$4 = 3.5
29+
// debugger:print *t1
30+
// check:$5 = 4
31+
// debugger:print ret
32+
// check:$6 = {{3.5, 4}, {4, 3.5}}
33+
// debugger:continue
34+
35+
fn dup_tup<T0: Clone, T1: Clone>(t0: &T0, t1: &T1) -> ((T0, T1), (T1, T0)) {
36+
let ret = ((t0.clone(), t1.clone()), (t1.clone(), t0.clone()));
37+
zzz();
38+
ret
39+
}
40+
41+
fn main() {
42+
43+
let _ = dup_tup(&1, &2.5);
44+
let _ = dup_tup(&3.5, &4_u16);
45+
46+
}
47+
48+
fn zzz() {()}

0 commit comments

Comments
 (0)