Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debuginfo: Captured variables and large pass-by-value arguments #8855

Closed
25 changes: 25 additions & 0 deletions src/librustc/lib/llvm.rs
Expand Up @@ -2084,6 +2084,31 @@ pub mod llvm {
ColumnNo: c_uint)
-> ValueRef;

#[fast_ffi]
pub fn LLVMDIBuilderCreateOpDeref(IntType: TypeRef) -> ValueRef;

#[fast_ffi]
pub fn LLVMDIBuilderCreateOpPlus(IntType: TypeRef) -> ValueRef;

#[fast_ffi]
pub fn LLVMDIBuilderCreateComplexVariable(Builder: DIBuilderRef,
Tag: c_uint,
Scope: ValueRef,
Name: *c_char,
File: ValueRef,
LineNo: c_uint,
Ty: ValueRef,
AddrOps: *ValueRef,
AddrOpsCount: c_uint,
ArgNo: c_uint)
-> ValueRef;

#[fast_ffi]
pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;

#[fast_ffi]
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;

pub fn LLVMInitializeX86TargetInfo();
pub fn LLVMInitializeX86Target();
pub fn LLVMInitializeX86TargetMC();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/moves.rs
Expand Up @@ -143,7 +143,7 @@ use syntax::visit;
use syntax::visit::Visitor;
use syntax::codemap::Span;

#[deriving(Encodable, Decodable)]
#[deriving(Eq, Encodable, Decodable)]
pub enum CaptureMode {
CapCopy, // Copy the value into the closure.
CapMove, // Move the value into the closure.
Expand Down
27 changes: 14 additions & 13 deletions src/librustc/middle/trans/_match.rs
Expand Up @@ -2000,19 +2000,20 @@ pub fn store_arg(mut bcx: @mut Block,
let arg_ty = node_id_type(bcx, pat.id);
add_clean(bcx, llval, arg_ty);

match simple_identifier(pat) {
Some(_) => {
// Optimized path for `x: T` case. This just adopts
// `llval` wholesale as the pointer for `x`, avoiding the
// general logic which may copy out of `llval`.
bcx.fcx.llargs.insert(pat.id, llval);
}

None => {
// General path. Copy out the values that are used in the
// pattern.
bcx = bind_irrefutable_pat(bcx, pat, llval, BindArgument);
}
// Debug information (the llvm.dbg.declare intrinsic to be precise) always expects to get an
// alloca, which only is the case on the general path, so lets disable the optimized path when
// debug info is enabled.
let fast_path = !bcx.ccx().sess.opts.extra_debuginfo && simple_identifier(pat).is_some();

if fast_path {
// Optimized path for `x: T` case. This just adopts
// `llval` wholesale as the pointer for `x`, avoiding the
// general logic which may copy out of `llval`.
bcx.fcx.llargs.insert(pat.id, llval);
} else {
// General path. Copy out the values that are used in the
// pattern.
bcx = bind_irrefutable_pat(bcx, pat, llval, BindArgument);
}

return bcx;
Expand Down
28 changes: 4 additions & 24 deletions src/librustc/middle/trans/base.rs
Expand Up @@ -131,20 +131,6 @@ pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
_InsnCtxt { _x: () }
}

fn fcx_has_nonzero_span(fcx: &FunctionContext) -> bool {
match fcx.span {
None => false,
Some(span) => *span.lo != 0 || *span.hi != 0
}
}

fn span_is_empty(opt_span: &Option<Span>) -> bool {
match *opt_span {
None => true,
Some(span) => *span.lo == 0 && *span.hi == 0
}
}

struct StatRecorder<'self> {
ccx: @mut CrateContext,
name: &'self str,
Expand Down Expand Up @@ -1132,8 +1118,7 @@ pub fn trans_stmt(cx: @mut Block, s: &ast::Stmt) -> @mut Block {
match d.node {
ast::DeclLocal(ref local) => {
bcx = init_local(bcx, *local);
if cx.sess().opts.extra_debuginfo
&& fcx_has_nonzero_span(bcx.fcx) {
if cx.sess().opts.extra_debuginfo {
debuginfo::create_local_var_metadata(bcx, *local);
}
}
Expand Down Expand Up @@ -1633,12 +1618,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
}
};
let uses_outptr = type_of::return_uses_outptr(ccx.tcx, substd_output_type);

let debug_context = if id != -1 && ccx.sess.opts.debuginfo && !span_is_empty(&sp) {
Some(debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl))
} else {
None
};
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);

let fcx = @mut FunctionContext {
llfn: llfndecl,
Expand Down Expand Up @@ -1784,7 +1764,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
fcx.llself = Some(ValSelfData {v: self_val, ..slf});
add_clean(bcx, self_val, slf.t);

if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
if fcx.ccx.sess.opts.extra_debuginfo {
debuginfo::create_self_argument_metadata(bcx, slf.t, self_val);
}
}
Expand All @@ -1811,7 +1791,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
};
bcx = _match::store_arg(bcx, args[arg_n].pat, llarg);

if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
if fcx.ccx.sess.opts.extra_debuginfo {
debuginfo::create_argument_metadata(bcx, &args[arg_n]);
}
}
Expand Down
25 changes: 24 additions & 1 deletion src/librustc/middle/trans/closure.rs
Expand Up @@ -17,6 +17,7 @@ use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::datum::{Datum, INIT};
use middle::trans::debuginfo;
use middle::trans::expr;
use middle::trans::glue;
use middle::trans::type_of::*;
Expand Down Expand Up @@ -307,7 +308,17 @@ pub fn load_environment(fcx: @mut FunctionContext,
// Load a pointer to the closure data, skipping over the box header:
let llcdata = opaque_box_body(bcx, cdata_ty, fcx.llenv);

// Populate the upvars from the environment.
// Store the pointer to closure data in an alloca for debug info because that's what the
// llvm.dbg.declare intrinsic expects
let env_pointer_alloca = if fcx.ccx.sess.opts.extra_debuginfo {
let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr");
Store(bcx, llcdata, alloc);
Some(alloc)
} else {
None
};

// Populate the upvars from the environment
let mut i = 0u;
for cap_var in cap_vars.iter() {
let mut upvarptr = GEPi(bcx, llcdata, [0u, i]);
Expand All @@ -317,6 +328,18 @@ pub fn load_environment(fcx: @mut FunctionContext,
}
let def_id = ast_util::def_id_of_def(cap_var.def);
fcx.llupvars.insert(def_id.node, upvarptr);

for &env_pointer_alloca in env_pointer_alloca.iter() {
debuginfo::create_captured_var_metadata(
bcx,
def_id.node,
cdata_ty,
env_pointer_alloca,
i,
sigil,
cap_var.span);
}

i += 1u;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/common.rs
Expand Up @@ -228,7 +228,7 @@ pub struct FunctionContext {
ccx: @mut CrateContext,

// Used and maintained by the debuginfo module.
debug_context: Option<~debuginfo::FunctionDebugContext>
debug_context: debuginfo::FunctionDebugContext,
}

impl FunctionContext {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/context.rs
Expand Up @@ -111,7 +111,7 @@ pub struct CrateContext {
// decl_gc_metadata knows whether to link to the module metadata, which
// is not emitted by LLVM's GC pass when no functions use GC.
uses_gc: bool,
dbg_cx: Option<debuginfo::DebugContext>,
dbg_cx: Option<debuginfo::CrateDebugContext>,
do_not_commit_warning_issued: bool
}

Expand Down Expand Up @@ -161,7 +161,7 @@ impl CrateContext {

let crate_map = decl_crate_map(sess, link_meta, llmod);
let dbg_cx = if sess.opts.debuginfo {
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned()))
} else {
None
};
Expand Down