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
This commit is contained in:
Michael Woerister 2013-08-08 18:33:06 +02:00
parent 1dec27bed5
commit 907633b1bf
5 changed files with 165 additions and 9 deletions

View File

@ -2086,6 +2086,16 @@ pub mod llvm {
#[fast_ffi]
pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
#[fast_ffi]
pub fn LLVMDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef,
Scope: ValueRef,
Name: *c_char,
Ty: ValueRef,
File: ValueRef,
LineNo: c_uint,
ColumnNo: c_uint)
-> ValueRef;
}
}

View File

@ -271,11 +271,11 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
let cx = fcx.ccx;
let fnitem = cx.tcx.items.get_copy(&fcx.id);
let (ident, fn_decl, id) = match fnitem {
let (ident, fn_decl, id, generics) = match fnitem {
ast_map::node_item(ref item, _) => {
match item.node {
ast::item_fn(ref fn_decl, _, _, _, _) => {
(item.ident, fn_decl, item.id)
ast::item_fn(ref fn_decl, _, _, ref generics, _) => {
(item.ident, ty, item.id, Some(generics))
}
_ => fcx.ccx.sess.span_bug(item.span,
"create_function_metadata: item bound to non-function")
@ -286,17 +286,21 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
decl: ref fn_decl,
id: id,
ident: ident,
generics: ref generics,
_
},
_,
_) => {
(ident, fn_decl, id)
(ident, fn_decl, id, Some(generics))
}
ast_map::node_expr(ref expr) => {
match expr.node {
ast::expr_fn_block(ref fn_decl, _) => {
let name = gensym_name("fn");
(name, fn_decl, expr.id)
(name, fn_decl, expr.id,
// This is not quite right. It should actually inherit the generics of the
// enclosing function.
None)
}
_ => fcx.ccx.sess.span_bug(expr.span,
"create_function_metadata: expected an expr_fn_block here")
@ -308,11 +312,12 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
decl: ref fn_decl,
id: id,
ident: ident,
generics: ref generics,
_
}),
_,
_) => {
(ident, fn_decl, id)
(ident, fn_decl, id, Some(generics))
}
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
};
@ -336,8 +341,18 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
let return_type_metadata = if cx.sess.opts.extra_debuginfo {
match fn_decl.output.node {
ast::ty_nil => ptr::null(),
_ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), fn_decl.output.span)
ast::ty_nil => ptr::null(),
_ => {
let return_type = ty::node_id_to_type(cx.tcx, id);
let return_type = match fcx.param_substs {
None => return_type,
Some(substs) => {
ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
}
};
type_metadata(cx, return_type, ret_ty.span)
}
}
} else {
ptr::null()
@ -350,6 +365,8 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
create_DIArray(DIB(cx), [return_type_metadata]))
};
let template_parameters: DIArray = get_template_parameters(cx, fcx, generics, file_metadata, span);
let fn_metadata =
do cx.sess.str_of(ident).with_c_str |name| {
do cx.sess.str_of(ident).with_c_str |linkage| {
@ -368,7 +385,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
FlagPrototyped as c_uint,
cx.sess.opts.optimize != session::No,
fcx.llfn,
ptr::null(),
template_parameters,
ptr::null())
}
}};
@ -396,6 +413,68 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
dbg_cx(cx).created_functions.insert(id, fn_metadata);
return fn_metadata;
fn get_template_parameters(cx: &mut CrateContext,
fcx: &FunctionContext,
generics: Option<&ast::Generics>,
file_metadata: DIFile,
span: span) -> DIArray {
// Normalize cases
let generics = match generics {
Some(generics_ref) if generics_ref.is_type_parameterized() => Some(generics_ref),
_ => None
};
match generics {
None => {
if (fcx.param_substs.is_some()) {
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
Mismatch between ast::Generics and FunctionContext::param_substs 111");
}
return ptr::null();
}
Some(generics) => {
let actual_types = match fcx.param_substs {
Some(@param_substs { tys: ref actual_types, _}) => {
actual_types
}
None => {
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
Mismatch between ast::Generics and FunctionContext::param_substs 222");
}
};
let template_params: ~[DIDescriptor] = do generics
.ty_params
.iter()
.enumerate()
.transform |(index, &ast::TyParam{ ident: ident, _ })| {
let actual_type = actual_types[index];
let actual_type_metadata = type_metadata(cx,
actual_type,
codemap::dummy_sp());
do cx.sess.str_of(ident).as_c_str |name| {
unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
file_metadata,
name,
actual_type_metadata,
ptr::null(),
0,
0)
}
}
}.collect();
return create_DIArray(DIB(cx), template_params);
}
}
}
}

View File

@ -838,3 +838,21 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
}
extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter(
DIBuilderRef Builder,
LLVMValueRef Scope,
const char* Name,
LLVMValueRef Ty,
LLVMValueRef File = 0,
unsigned LineNo = 0,
unsigned ColumnNo = 0)
{
return wrap(Builder->createTemplateTypeParameter(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIType>(Ty),
unwrapDI<MDNode*>(File),
LineNo,
ColumnNo));
}

View File

@ -613,4 +613,5 @@ LLVMDIBuilderInsertDeclareBefore
LLVMDIBuilderCreateEnumerator
LLVMDIBuilderCreateEnumerationType
LLVMDIBuilderCreateUnionType
LLVMDIBuilderCreateTemplateTypeParameter
LLVMSetUnnamedAddr

View File

@ -0,0 +1,48 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
// compile-flags:-Z extra-debug-info
// debugger:break zzz
// debugger:run
// debugger:finish
// debugger:print *t0
// check:$1 = 1
// debugger:print *t1
// check:$2 = 2.5
// debugger:print ret
// check:$3 = {{1, 2.5}, {2.5, 1}}
// debugger:continue
// debugger:finish
// debugger:print *t0
// check:$4 = 3.5
// debugger:print *t1
// check:$5 = 4
// debugger:print ret
// check:$6 = {{3.5, 4}, {4, 3.5}}
// debugger:continue
fn dup_tup<T0: Clone, T1: Clone>(t0: &T0, t1: &T1) -> ((T0, T1), (T1, T0)) {
let ret = ((t0.clone(), t1.clone()), (t1.clone(), t0.clone()));
zzz();
ret
}
fn main() {
let _ = dup_tup(&1, &2.5);
let _ = dup_tup(&3.5, &4_u16);
}
fn zzz() {()}