mirror of https://github.com/rust-lang/rust.git
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:
parent
1dec27bed5
commit
907633b1bf
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -613,4 +613,5 @@ LLVMDIBuilderInsertDeclareBefore
|
|||
LLVMDIBuilderCreateEnumerator
|
||||
LLVMDIBuilderCreateEnumerationType
|
||||
LLVMDIBuilderCreateUnionType
|
||||
LLVMDIBuilderCreateTemplateTypeParameter
|
||||
LLVMSetUnnamedAddr
|
||||
|
|
|
@ -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() {()}
|
Loading…
Reference in New Issue