debuginfo: Implemented support for Self type parameter in trait methods with default implementation.

This commit is contained in:
Michael Woerister 2013-08-15 12:25:35 +02:00
parent a36e53730f
commit c1734cef33
2 changed files with 264 additions and 43 deletions

View File

@ -70,7 +70,7 @@ use std::ptr;
use std::vec; use std::vec;
use syntax::codemap::span; use syntax::codemap::span;
use syntax::{ast, codemap, ast_util, ast_map}; use syntax::{ast, codemap, ast_util, ast_map};
use syntax::parse::token::keywords; use syntax::parse::token::special_idents;
static DW_LANG_RUST: int = 0x9000; static DW_LANG_RUST: int = 0x9000;
@ -195,9 +195,8 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
let loc = span_start(cx, span); let loc = span_start(cx, span);
let type_metadata = type_metadata(cx, variable_type, span); let type_metadata = type_metadata(cx, variable_type, span);
let scope = create_function_metadata(bcx.fcx); let scope = create_function_metadata(bcx.fcx);
let self_ident = keywords::Self.to_ident();
let var_metadata = do cx.sess.str_of(self_ident).to_c_str().with_ref |name| { let var_metadata = do cx.sess.str_of(special_idents::self_).to_c_str().with_ref |name| {
unsafe { unsafe {
llvm::LLVMDIBuilderCreateLocalVariable( llvm::LLVMDIBuilderCreateLocalVariable(
DIB(cx), DIB(cx),
@ -229,8 +228,7 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
/// ///
/// Adds the created metadata nodes directly to the crate's IR. /// Adds the created metadata nodes directly to the crate's IR.
pub fn create_argument_metadata(bcx: @mut Block, pub fn create_argument_metadata(bcx: @mut Block,
arg: &ast::arg, arg: &ast::arg) {
needs_deref: bool) {
let fcx = bcx.fcx; let fcx = bcx.fcx;
let cx = fcx.ccx; let cx = fcx.ccx;
@ -337,11 +335,11 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
} }
let fnitem = cx.tcx.items.get_copy(&fcx.id); let fnitem = cx.tcx.items.get_copy(&fcx.id);
let (ident, fn_decl, generics, span) = match fnitem { let (ident, fn_decl, generics, span, is_trait_default_impl) = match fnitem {
ast_map::node_item(ref item, _) => { ast_map::node_item(ref item, _) => {
match item.node { match item.node {
ast::item_fn(ref fn_decl, _, _, ref generics, _) => { ast::item_fn(ref fn_decl, _, _, ref generics, _) => {
(item.ident, fn_decl, Some(generics), item.span) (item.ident, fn_decl, Some(generics), item.span, false)
} }
_ => fcx.ccx.sess.span_bug(item.span, _ => fcx.ccx.sess.span_bug(item.span,
"create_function_metadata: item bound to non-function") "create_function_metadata: item bound to non-function")
@ -357,7 +355,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
}, },
_, _,
_) => { _) => {
(ident, fn_decl, Some(generics), span) (ident, fn_decl, Some(generics), span, false)
} }
ast_map::node_expr(ref expr) => { ast_map::node_expr(ref expr) => {
match expr.node { match expr.node {
@ -367,7 +365,8 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
// This is not quite right. It should actually inherit the generics of the // This is not quite right. It should actually inherit the generics of the
// enclosing function. // enclosing function.
None, None,
expr.span) expr.span,
false)
} }
_ => fcx.ccx.sess.span_bug(expr.span, _ => fcx.ccx.sess.span_bug(expr.span,
"create_function_metadata: expected an expr_fn_block here") "create_function_metadata: expected an expr_fn_block here")
@ -384,7 +383,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
}), }),
_, _,
_) => { _) => {
(ident, fn_decl, Some(generics), span) (ident, fn_decl, Some(generics), span, true)
} }
_ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem)) _ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem))
}; };
@ -405,6 +404,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
let mut function_name = cx.sess.str_of(ident).to_owned(); let mut function_name = cx.sess.str_of(ident).to_owned();
let template_parameters = get_template_parameters(fcx, let template_parameters = get_template_parameters(fcx,
generics, generics,
is_trait_default_impl,
file_metadata, file_metadata,
span, span,
&mut function_name); &mut function_name);
@ -507,6 +507,7 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
fn get_template_parameters(fcx: &FunctionContext, fn get_template_parameters(fcx: &FunctionContext,
generics: Option<&ast::Generics>, generics: Option<&ast::Generics>,
is_trait_default_impl: bool,
file_metadata: DIFile, file_metadata: DIFile,
span: span, span: span,
name_to_append_suffix_to: &mut ~str) name_to_append_suffix_to: &mut ~str)
@ -521,58 +522,131 @@ pub fn create_function_metadata(fcx: &mut FunctionContext) -> DISubprogram {
match generics { match generics {
None => { None => {
if (fcx.param_substs.is_some()) { if (!is_trait_default_impl && fcx.param_substs.is_some()) {
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \ cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
Mismatch between ast::Generics and FunctionContext::param_substs"); Mismatch between ast::Generics (does not exist) and \
FunctionContext::param_substs (does exist)");
} }
return ptr::null(); return ptr::null();
} }
Some(generics) => { Some(generics) => {
let actual_types = match fcx.param_substs { let (actual_types, actual_self_type) = match fcx.param_substs {
Some(@param_substs { tys: ref actual_types, _}) => { Some(@param_substs { tys: ref types, self_ty: ref self_type, _ }) => {
actual_types if is_trait_default_impl && self_type.is_none() {
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
Expected self type parameter substitution for default \
implementation of trait method");
}
(types, self_type)
} }
None => { None => {
cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \ cx.sess.span_bug(span, "debuginfo::create_function_metadata() - \
Mismatch between ast::Generics and FunctionContext::param_substs"); Mismatch between ast::Generics (does exist) and \
FunctionContext::param_substs (does not exist)");
} }
}; };
name_to_append_suffix_to.push_char('<'); name_to_append_suffix_to.push_char('<');
let template_params: ~[DIDescriptor] = do generics let mut template_params: ~[DIDescriptor] =
.ty_params vec::with_capacity(actual_types.len() + 1);
.iter()
.enumerate()
.map |(index, &ast::TyParam{ ident: ident, _ })| {
let actual_type = actual_types[index]; if is_trait_default_impl {
let actual_type_metadata = type_metadata(cx, let actual_self_type_metadata = type_metadata(cx,
actual_type, actual_self_type.unwrap(),
codemap::dummy_sp()); codemap::dummy_sp());
// Add actual type name to <...> clause of function name // Add self type name to <...> clause of function name
let actual_type_name = ty_to_str(cx.tcx, actual_type); let actual_self_type_name = ty_to_str(cx.tcx, actual_self_type.unwrap());
name_to_append_suffix_to.push_str(actual_type_name); name_to_append_suffix_to.push_str(actual_self_type_name);
if index != generics.ty_params.len() - 1 { if actual_types.len() > 0 {
name_to_append_suffix_to.push_str(","); name_to_append_suffix_to.push_str(",");
}
let ident = special_idents::type_self;
let param_metadata = do cx.sess.str_of(ident).to_c_str().with_ref |name| {
unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
file_metadata,
name,
actual_self_type_metadata,
ptr::null(),
0,
0)
} }
};
do cx.sess.str_of(ident).to_c_str().with_ref |name| { template_params.push(param_metadata);
unsafe { }
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx), for (index, &ast::TyParam{ ident: ident, _ }) in generics
file_metadata, .ty_params
name, .iter()
actual_type_metadata, .enumerate() {
ptr::null(), let actual_type = actual_types[index];
0, let actual_type_metadata = type_metadata(cx,
0) actual_type,
} codemap::dummy_sp());
// Add actual type name to <...> clause of function name
let actual_type_name = ty_to_str(cx.tcx, actual_type);
name_to_append_suffix_to.push_str(actual_type_name);
if index != generics.ty_params.len() - 1 {
name_to_append_suffix_to.push_str(",");
}
let param_metadata = do cx.sess.str_of(ident).to_c_str().with_ref |name| {
unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
file_metadata,
name,
actual_type_metadata,
ptr::null(),
0,
0)
} }
}.collect(); };
template_params.push(param_metadata);
}
// let template_params: ~[DIDescriptor] = do generics
// .ty_params
// .iter()
// .enumerate()
// .map |(index, &ast::TyParam{ ident: ident, _ })| {
// let actual_type = actual_types[index];
// let actual_type_metadata = type_metadata(cx,
// actual_type,
// codemap::dummy_sp());
// // Add actual type name to <...> clause of function name
// let actual_type_name = ty_to_str(cx.tcx, actual_type);
// name_to_append_suffix_to.push_str(actual_type_name);
// if index != generics.ty_params.len() - 1 {
// name_to_append_suffix_to.push_str(",");
// }
// do cx.sess.str_of(ident).to_c_str().with_ref |name| {
// unsafe {
// llvm::LLVMDIBuilderCreateTemplateTypeParameter(
// DIB(cx),
// file_metadata,
// name,
// actual_type_metadata,
// ptr::null(),
// 0,
// 0)
// }
// }
// }.collect();
name_to_append_suffix_to.push_char('>'); name_to_append_suffix_to.push_char('>');
@ -795,7 +869,13 @@ fn struct_metadata(cx: &mut CrateContext,
let struct_llvm_type = type_of::type_of(cx, struct_type); let struct_llvm_type = type_of::type_of(cx, struct_type);
let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) }; let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) };
let field_names = do fields.map |field| { cx.sess.str_of(field.ident).to_owned() }; let field_names = do fields.map |field| {
if field.ident == special_idents::unnamed_field {
~""
} else {
cx.sess.str_of(field.ident).to_owned()
}
};
let field_types_metadata = do fields.map |field| { let field_types_metadata = do fields.map |field| {
type_metadata(cx, field.mt.ty, span) type_metadata(cx, field.mt.ty, span)
}; };

View File

@ -0,0 +1,141 @@
// 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
// STACK BY REF
// debugger:finish
// debugger:print *self
// check:$1 = {x = 100}
// debugger:print arg1
// check:$2 = -1
// debugger:print arg2
// check:$3 = -2
// debugger:continue
// STACK BY VAL
// debugger:finish
// d ebugger:print self -- ignored for now because of issue #8512
// c heck:$X = {x = 100}
// debugger:print arg1
// check:$4 = -3
// debugger:print arg2
// check:$5 = -4
// debugger:continue
// OWNED BY REF
// debugger:finish
// debugger:print *self
// check:$6 = {x = 200}
// debugger:print arg1
// check:$7 = -5
// debugger:print arg2
// check:$8 = -6
// debugger:continue
// OWNED BY VAL
// debugger:finish
// d ebugger:print self -- ignored for now because of issue #8512
// c heck:$X = {x = 200}
// debugger:print arg1
// check:$9 = -7
// debugger:print arg2
// check:$10 = -8
// debugger:continue
// OWNED MOVED
// debugger:finish
// debugger:print *self
// check:$11 = {x = 200}
// debugger:print arg1
// check:$12 = -9
// debugger:print arg2
// check:$13 = -10
// debugger:continue
// MANAGED BY REF
// debugger:finish
// debugger:print *self
// check:$14 = {x = 300}
// debugger:print arg1
// check:$15 = -11
// debugger:print arg2
// check:$16 = -12
// debugger:continue
// MANAGED BY VAL
// debugger:finish
// d ebugger:print self -- ignored for now because of issue #8512
// c heck:$X = {x = 300}
// debugger:print arg1
// check:$17 = -13
// debugger:print arg2
// check:$18 = -14
// debugger:continue
// MANAGED SELF
// debugger:finish
// debugger:print self->val
// check:$19 = {x = 300}
// debugger:print arg1
// check:$20 = -15
// debugger:print arg2
// check:$21 = -16
// debugger:continue
struct Struct {
x: int
}
trait Trait {
fn self_by_ref(&self, arg1: int, arg2: int) -> int {
zzz();
arg1 + arg2
}
fn self_by_val(self, arg1: int, arg2: int) -> int {
zzz();
arg1 + arg2
}
fn self_owned(~self, arg1: int, arg2: int) -> int {
zzz();
arg1 + arg2
}
fn self_managed(@self, arg1: int, arg2: int) -> int {
zzz();
arg1 + arg2
}
}
impl Trait for Struct;
fn main() {
let stack = Struct { x: 100 };
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
let owned = ~Struct { x: 200 };
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
let managed = @Struct { x: 300 };
let _ = managed.self_by_ref(-11, -12);
let _ = managed.self_by_val(-13, -14);
let _ = managed.self_managed(-15, -16);
}
fn zzz() {()}