diff --git a/src/comp/middle/debuginfo.rs b/src/comp/middle/debuginfo.rs index 1b83353119d9..be70c1b3f3da 100644 --- a/src/comp/middle/debuginfo.rs +++ b/src/comp/middle/debuginfo.rs @@ -4,10 +4,10 @@ import lib::llvm::llvm; import lib::llvm::llvm::ValueRef; import middle::trans_common::*; import middle::ty; -import ast::ty; import syntax::{ast, codemap}; +import ast::ty; -const LLVMDebugVersion: int = (9 << 16); //& 0xffff0000; // 0x80000 ? +const LLVMDebugVersion: int = (9 << 16); const DW_LANG_RUST: int = 0x9000; const DW_VIRTUALITY_none: int = 0; @@ -78,6 +78,8 @@ type subprogram_md = {name: str, file: str}; type local_var_md = {id: ast::node_id}; type tydesc_md = {hash: uint}; type block_md = {start: codemap::loc, end: codemap::loc}; +type argument_md = {id: ast::node_id}; +type retval_md = {id: ast::node_id}; type metadata_cache = hashmap; @@ -88,9 +90,11 @@ tag debug_metadata { local_var_metadata(@metadata); tydesc_metadata(@metadata); block_metadata(@metadata); + argument_metadata(@metadata); + retval_metadata(@metadata); } -fn cast_safely(val: T) -> U unsafe { +fn cast_safely(val: T) -> U unsafe { let val2 = val; let val3 = unsafe::reinterpret_cast(val2); unsafe::leak(val2); @@ -105,11 +109,13 @@ fn md_from_metadata(val: debug_metadata) -> T unsafe { local_var_metadata(md) { cast_safely(md) } tydesc_metadata(md) { cast_safely(md) } block_metadata(md) { cast_safely(md) } + argument_metadata(md) { cast_safely(md) } + retval_metadata(md) { cast_safely(md) } } } -fn cached_metadata(cache: metadata_cache, mdtag: int, - eq: block(md: T) -> bool) -> option::t unsafe { +fn cached_metadata(cache: metadata_cache, mdtag: int, + eq: block(md: T) -> bool) -> option::t unsafe { if cache.contains_key(mdtag) { let items = cache.get(mdtag); for item in items { @@ -270,7 +276,7 @@ fn function_metadata_from_block(bcx: @block_ctxt) -> @metadata { let fcx = bcx_fcx(bcx); let fn_node = cx.ast_map.get(fcx.id); let fn_item = alt fn_node { ast_map::node_item(item) { item } }; - get_function_metadata(cx, fn_item, fcx.llfn) + get_function_metadata(fcx, fn_item, fcx.llfn) } fn filename_from_span(cx: @crate_ctxt, sp: codemap::span) -> str { @@ -323,6 +329,98 @@ fn get_local_var_metadata(bcx: @block_ctxt, local: @ast::local) ret mdval; } +//FIXME: consolidate with get_local_var_metadata +/*fn get_retval_metadata(bcx: @block_ctxt) + -> @metadata unsafe { + let fcx = bcx_fcx(bcx); + let cx = fcx_ccx(fcx); + let cache = cx.llmetadata; + alt cached_metadata::<@metadata>( + cache, ReturnVariableTag, {|md| md.data.id == fcx.id}) { + option::some(md) { ret md; } + option::none. {} + } + let item = alt option::get(cx.ast_map.find(fcx.id)) { + ast_map::node_item(item) { item } + }; + let loc = codemap::lookup_char_pos(cx.sess.get_codemap(), + fcx.sp.lo); + let ret_ty = alt item.node { + ast::item_fn(f, _) { f.decl.output } + }; + let ty_node = alt ret_ty.node { + ast::ty_nil. { llnull() } + _ { get_ty_metadata(cx, ty::node_id_to_type(ccx_tcx(cx), item.id), + ret_ty).node } + }; + /*let ty_node = get_ty_metadata(cx, ty::node_id_to_type(ccx_tcx(cx), fcx.id), + ty).node;*/ + //let ty = trans::node_id_type(cx, arg.id); + //let tymd = get_ty_metadata(cx, ty, arg.ty); + let filemd = get_file_metadata(cx, loc.filename); + let fn_node = cx.ast_map.get(fcx.id); + let fn_item = alt fn_node { ast_map::node_item(item) { item } }; + let context = get_function_metadata(fcx, fn_item, fcx.llfn); + let lldata = [lltag(ReturnVariableTag), + context.node, // context + llstr("%0"), // name + filemd.node, + lli32(loc.line as int), // line + ty_node, + lli32(0) //XXX flags + ]; + let mdnode = llmdnode(lldata); + let mdval = @{node: mdnode, data: {id: fcx.id}}; + update_cache(cache, ReturnVariableTag, retval_metadata(mdval)); + let llptr = fcx.llretptr; + let declargs = [llmdnode([llptr]), mdnode]; + trans_build::Call(bcx, cx.intrinsics.get("llvm.dbg.declare"), + declargs); + ret mdval; +}*/ + +//FIXME: consolidate with get_local_var_metadata +fn get_arg_metadata(bcx: @block_ctxt, arg: ast::arg) + -> @metadata unsafe { + let fcx = bcx_fcx(bcx); + let cx = fcx_ccx(fcx); + let cache = cx.llmetadata; + alt cached_metadata::<@metadata>( + cache, ArgVariableTag, {|md| md.data.id == arg.id}) { + option::some(md) { ret md; } + option::none. {} + } + let arg_n = alt cx.ast_map.get(arg.id) { + ast_map::node_arg(_, n) { n - 2u } + }; + let loc = codemap::lookup_char_pos(cx.sess.get_codemap(), + fcx.sp.lo); + let ty = trans::node_id_type(cx, arg.id); + let tymd = get_ty_metadata(cx, ty, arg.ty); + let filemd = get_file_metadata(cx, loc.filename); + let fn_node = cx.ast_map.get(fcx.id); + let fn_item = alt fn_node { ast_map::node_item(item) { item } }; + let context = get_function_metadata(fcx, fn_item, fcx.llfn); + let lldata = [lltag(ArgVariableTag), + context.node, // context + llstr(arg.ident), // name + filemd.node, + lli32(loc.line as int), // line + tymd.node, + lli32(0) //XXX flags + ]; + let mdnode = llmdnode(lldata); + let mdval = @{node: mdnode, data: {id: arg.id}}; + update_cache(cache, ArgVariableTag, argument_metadata(mdval)); + let llptr = alt fcx.llargs.get(arg.id) { + local_mem(v) | local_imm(v) { v } + }; + let declargs = [llmdnode([llptr]), mdnode]; + trans_build::Call(bcx, cx.intrinsics.get("llvm.dbg.declare"), + declargs); + ret mdval; +} + fn update_source_pos(cx: @block_ctxt, s: codemap::span) -> @debug_source_pos { let dsp = @debug_source_pos(cx); if !bcx_ccx(cx).sess.get_opts().debuginfo { @@ -384,8 +482,9 @@ fn add_line_info(cx: @block_ctxt, llinstr: ValueRef) { llvm::LLVMSetMetadata(llinstr, kind_id, dbgscope); } -fn get_function_metadata(cx: @crate_ctxt, item: @ast::item, +fn get_function_metadata(fcx: @fn_ctxt, item: @ast::item, llfndecl: ValueRef) -> @metadata { + let cx = fcx_ccx(fcx); let cache = cx.llmetadata; alt cached_metadata::<@metadata>( cache, SubprogramTag, {|md| md.data.name == item.ident && @@ -448,5 +547,9 @@ fn get_function_metadata(cx: @crate_ctxt, item: @ast::item, let mdval = @{node: val, data: {name: item.ident, file: loc.filename}}; update_cache(cache, SubprogramTag, subprogram_metadata(mdval)); + /*alt ret_ty.node { + ast::ty_nil. {} + _ { let _ = get_retval_metadata(fcx, ret_ty); } + }*/ ret mdval; } \ No newline at end of file diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4c58cc5e26d9..81f15d6b4de1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4422,6 +4422,12 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg, fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], arg_tys: [ty::arg]) -> @block_ctxt { + if fcx_ccx(fcx).sess.get_opts().debuginfo { + llvm::LLVMAddAttribute(llvm::LLVMGetFirstParam(fcx.llfn), + lib::llvm::LLVMStructRetAttribute as + lib::llvm::llvm::Attribute); + //let _ = debuginfo::get_retval_metadata(bcx); + } let arg_n: uint = 0u, bcx = bcx; for arg in arg_tys { let id = args[arg_n].id; @@ -4441,6 +4447,9 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg], } ast::by_ref. {} } + if fcx_ccx(fcx).sess.get_opts().debuginfo { + let _ = debuginfo::get_arg_metadata(bcx, args[arg_n]); + } arg_n += 1u; } ret bcx; @@ -4574,12 +4583,13 @@ fn trans_fn(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef, id: ast::node_id) { let do_time = cx.ccx.sess.get_opts().stats; let start = do_time ? time::get_time() : {sec: 0u32, usec: 0u32}; - trans_closure(cx, sp, f, llfndecl, ty_self, ty_params, id, {|_fcx|}); + let fcx = option::none; + trans_closure(cx, sp, f, llfndecl, ty_self, ty_params, id, {|new_fcx| fcx = option::some(new_fcx);}); if cx.ccx.sess.get_opts().debuginfo { let item = alt option::get(cx.ccx.ast_map.find(id)) { ast_map::node_item(item) { item } }; - debuginfo::get_function_metadata(cx.ccx, item, llfndecl); + debuginfo::get_function_metadata(option::get(fcx), item, llfndecl); } if do_time { let end = time::get_time(); diff --git a/src/comp/middle/trans_build.rs b/src/comp/middle/trans_build.rs index 600c1e27c73d..2b45285a4ef0 100644 --- a/src/comp/middle/trans_build.rs +++ b/src/comp/middle/trans_build.rs @@ -104,6 +104,14 @@ fn Invoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef], let instr = llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args), vec::len(Args), Then, Catch, noname()); + if bcx_ccx(cx).sess.get_opts().debuginfo { + /*llvm::LLVMAddAttribute(option::get(vec::last(llargs)), + lib::llvm::LLVMStructRetAttribute as + lib::llvm::llvm::Attribute);*/ + llvm::LLVMAddInstrAttribute(instr, 1u, + lib::llvm::LLVMStructRetAttribute as + lib::llvm::llvm::Attribute); + } debuginfo::add_line_info(cx, instr); } }