mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #32803 - eddyb:mir-debuginfo, r=nikomatsakis
Initial implementation of debuginfo in MIR trans. Progress is made towards #31005, but several issues remain, such as #32790.
This commit is contained in:
commit
7c27cce9e5
@ -868,27 +868,11 @@ fn cleanup_debug_info_options(options: &Option<String>) -> Option<String> {
|
|||||||
"-g".to_owned(),
|
"-g".to_owned(),
|
||||||
"--debuginfo".to_owned()
|
"--debuginfo".to_owned()
|
||||||
];
|
];
|
||||||
let mut new_options =
|
let new_options =
|
||||||
split_maybe_args(options).into_iter()
|
split_maybe_args(options).into_iter()
|
||||||
.filter(|x| !options_to_remove.contains(x))
|
.filter(|x| !options_to_remove.contains(x))
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
let mut i = 0;
|
|
||||||
while i + 1 < new_options.len() {
|
|
||||||
if new_options[i] == "-Z" {
|
|
||||||
// FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
if new_options[i + 1] == "orbit" {
|
|
||||||
// Remove "-Z" and "orbit".
|
|
||||||
new_options.remove(i);
|
|
||||||
new_options.remove(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Always skip over -Z's argument.
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(new_options.join(" "))
|
Some(new_options.join(" "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,6 +698,7 @@ impl ScopeId {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub struct ScopeData {
|
pub struct ScopeData {
|
||||||
|
pub span: Span,
|
||||||
pub parent_scope: Option<ScopeId>,
|
pub parent_scope: Option<ScopeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,9 +298,11 @@ macro_rules! make_mir_visitor {
|
|||||||
fn super_scope_data(&mut self,
|
fn super_scope_data(&mut self,
|
||||||
scope_data: & $($mutability)* ScopeData) {
|
scope_data: & $($mutability)* ScopeData) {
|
||||||
let ScopeData {
|
let ScopeData {
|
||||||
|
ref $($mutability)* span,
|
||||||
ref $($mutability)* parent_scope,
|
ref $($mutability)* parent_scope,
|
||||||
} = *scope_data;
|
} = *scope_data;
|
||||||
|
|
||||||
|
self.visit_span(span);
|
||||||
if let Some(ref $($mutability)* parent_scope) = *parent_scope {
|
if let Some(ref $($mutability)* parent_scope) = *parent_scope {
|
||||||
self.visit_scope_id(parent_scope);
|
self.visit_scope_id(parent_scope);
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||||||
debug!("push_scope({:?})", extent);
|
debug!("push_scope({:?})", extent);
|
||||||
let parent_id = self.scopes.last().map(|s| s.id);
|
let parent_id = self.scopes.last().map(|s| s.id);
|
||||||
let id = ScopeId::new(self.scope_datas.len());
|
let id = ScopeId::new(self.scope_datas.len());
|
||||||
|
let tcx = self.hir.tcx();
|
||||||
self.scope_datas.push(ScopeData {
|
self.scope_datas.push(ScopeData {
|
||||||
|
span: extent.span(&tcx.region_maps, &tcx.map).unwrap_or(DUMMY_SP),
|
||||||
parent_scope: parent_id,
|
parent_scope: parent_id,
|
||||||
});
|
});
|
||||||
self.scopes.push(Scope {
|
self.scopes.push(Scope {
|
||||||
|
@ -242,7 +242,11 @@ fn write_mir_intro(tcx: &TyCtxt, nid: NodeId, mir: &Mir, w: &mut Write)
|
|||||||
if var.mutability == Mutability::Mut {
|
if var.mutability == Mutability::Mut {
|
||||||
write!(w, "mut ")?;
|
write!(w, "mut ")?;
|
||||||
}
|
}
|
||||||
writeln!(w, "{:?}: {}; // {}", Lvalue::Var(i as u32), var.ty, var.name)?;
|
writeln!(w, "{:?}: {}; // {} in {}",
|
||||||
|
Lvalue::Var(i as u32),
|
||||||
|
var.ty,
|
||||||
|
var.name,
|
||||||
|
comment(tcx, var.scope, var.span))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compiler-introduced temporary types.
|
// Compiler-introduced temporary types.
|
||||||
|
@ -1276,7 +1276,7 @@ pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef {
|
|||||||
return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
|
return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debuginfo::clear_source_location(cx.fcx);
|
DebugLoc::None.apply(cx.fcx);
|
||||||
Alloca(cx, ty, name)
|
Alloca(cx, ty, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1400,23 +1400,23 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
|||||||
pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
|
pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
|
||||||
llfndecl: ValueRef,
|
llfndecl: ValueRef,
|
||||||
fn_ty: FnType,
|
fn_ty: FnType,
|
||||||
def_id: Option<DefId>,
|
definition: Option<(Instance<'tcx>, &ty::FnSig<'tcx>, Abi)>,
|
||||||
param_substs: &'tcx Substs<'tcx>,
|
|
||||||
block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
|
block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
|
||||||
-> FunctionContext<'blk, 'tcx> {
|
-> FunctionContext<'blk, 'tcx> {
|
||||||
common::validate_substs(param_substs);
|
let (param_substs, def_id) = match definition {
|
||||||
|
Some((instance, _, _)) => {
|
||||||
|
common::validate_substs(instance.substs);
|
||||||
|
(instance.substs, Some(instance.def))
|
||||||
|
}
|
||||||
|
None => (ccx.tcx().mk_substs(Substs::empty()), None)
|
||||||
|
};
|
||||||
|
|
||||||
let inlined_did = def_id.and_then(|def_id| inline::get_local_instance(ccx, def_id));
|
let inlined_did = def_id.and_then(|def_id| inline::get_local_instance(ccx, def_id));
|
||||||
let inlined_id = inlined_did.and_then(|id| ccx.tcx().map.as_local_node_id(id));
|
let inlined_id = inlined_did.and_then(|id| ccx.tcx().map.as_local_node_id(id));
|
||||||
let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
|
let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
|
||||||
|
|
||||||
debug!("FunctionContext::new(path={}, def_id={:?}, param_substs={:?})",
|
debug!("FunctionContext::new({})",
|
||||||
inlined_id.map_or(String::new(), |id| ccx.tcx().node_path_str(id)),
|
definition.map_or(String::new(), |d| d.0.to_string()));
|
||||||
def_id,
|
|
||||||
param_substs);
|
|
||||||
|
|
||||||
let debug_context = debuginfo::create_function_debug_context(ccx,
|
|
||||||
inlined_id.unwrap_or(ast::DUMMY_NODE_ID), param_substs, llfndecl);
|
|
||||||
|
|
||||||
let cfg = inlined_id.map(|id| build_cfg(ccx.tcx(), id));
|
let cfg = inlined_id.map(|id| build_cfg(ccx.tcx(), id));
|
||||||
let nested_returns = if let Some((blk_id, Some(ref cfg))) = cfg {
|
let nested_returns = if let Some((blk_id, Some(ref cfg))) = cfg {
|
||||||
@ -1428,10 +1428,11 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
|||||||
let check_attrs = |attrs: &[ast::Attribute]| {
|
let check_attrs = |attrs: &[ast::Attribute]| {
|
||||||
let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
|
let default_to_mir = ccx.sess().opts.debugging_opts.orbit;
|
||||||
let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
|
let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" };
|
||||||
default_to_mir ^ attrs.iter().any(|item| item.check_name(invert))
|
(default_to_mir ^ attrs.iter().any(|item| item.check_name(invert)),
|
||||||
|
attrs.iter().any(|item| item.check_name("no_debug")))
|
||||||
};
|
};
|
||||||
|
|
||||||
let use_mir = if let Some(id) = local_id {
|
let (use_mir, no_debug) = if let Some(id) = local_id {
|
||||||
check_attrs(ccx.tcx().map.attrs(id))
|
check_attrs(ccx.tcx().map.attrs(id))
|
||||||
} else if let Some(def_id) = def_id {
|
} else if let Some(def_id) = def_id {
|
||||||
check_attrs(&ccx.sess().cstore.item_attrs(def_id))
|
check_attrs(&ccx.sess().cstore.item_attrs(def_id))
|
||||||
@ -1445,6 +1446,13 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let debug_context = if let (false, Some(definition)) = (no_debug, definition) {
|
||||||
|
let (instance, sig, abi) = definition;
|
||||||
|
debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl)
|
||||||
|
} else {
|
||||||
|
debuginfo::empty_function_debug_context(ccx)
|
||||||
|
};
|
||||||
|
|
||||||
FunctionContext {
|
FunctionContext {
|
||||||
needs_ret_allocas: nested_returns && mir.is_none(),
|
needs_ret_allocas: nested_returns && mir.is_none(),
|
||||||
mir: mir,
|
mir: mir,
|
||||||
@ -1731,7 +1739,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
|||||||
|
|
||||||
self.build_return_block(ret_cx, ret_debug_loc);
|
self.build_return_block(ret_cx, ret_debug_loc);
|
||||||
|
|
||||||
debuginfo::clear_source_location(self);
|
DebugLoc::None.apply(self);
|
||||||
self.cleanup();
|
self.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1810,32 +1818,34 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
decl: &hir::FnDecl,
|
decl: &hir::FnDecl,
|
||||||
body: &hir::Block,
|
body: &hir::Block,
|
||||||
llfndecl: ValueRef,
|
llfndecl: ValueRef,
|
||||||
param_substs: &'tcx Substs<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
def_id: DefId,
|
|
||||||
inlined_id: ast::NodeId,
|
inlined_id: ast::NodeId,
|
||||||
fn_ty: FnType,
|
sig: &ty::FnSig<'tcx>,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
closure_env: closure::ClosureEnv) {
|
closure_env: closure::ClosureEnv) {
|
||||||
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
|
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
|
||||||
|
|
||||||
if collector::collecting_debug_information(ccx) {
|
if collector::collecting_debug_information(ccx) {
|
||||||
ccx.record_translation_item_as_generated(
|
ccx.record_translation_item_as_generated(TransItem::Fn(instance));
|
||||||
TransItem::Fn(Instance::new(def_id, param_substs)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _icx = push_ctxt("trans_closure");
|
let _icx = push_ctxt("trans_closure");
|
||||||
attributes::emit_uwtable(llfndecl, true);
|
attributes::emit_uwtable(llfndecl, true);
|
||||||
|
|
||||||
debug!("trans_closure(..., param_substs={:?})", param_substs);
|
debug!("trans_closure(..., {})", instance);
|
||||||
|
|
||||||
|
let fn_ty = FnType::new(ccx, abi, sig, &[]);
|
||||||
|
|
||||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
arena = TypedArena::new();
|
arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some(def_id), param_substs, &arena);
|
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some((instance, sig, abi)), &arena);
|
||||||
|
|
||||||
if fcx.mir.is_some() {
|
if fcx.mir.is_some() {
|
||||||
return mir::trans_mir(&fcx);
|
return mir::trans_mir(&fcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debuginfo::fill_scope_map_for_function(&fcx, decl, body, inlined_id);
|
||||||
|
|
||||||
// cleanup scope for the incoming arguments
|
// cleanup scope for the incoming arguments
|
||||||
let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(
|
let fn_cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(
|
||||||
ccx, inlined_id, body.span, true);
|
ccx, inlined_id, body.span, true);
|
||||||
@ -1890,10 +1900,8 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret_debug_loc = DebugLoc::At(fn_cleanup_debug_loc.id, fn_cleanup_debug_loc.span);
|
|
||||||
|
|
||||||
// Insert the mandatory first few basic blocks before lltop.
|
// Insert the mandatory first few basic blocks before lltop.
|
||||||
fcx.finish(bcx, ret_debug_loc);
|
fcx.finish(bcx, fn_cleanup_debug_loc.debug_loc());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an LLVM function corresponding to a source language function.
|
/// Creates an LLVM function corresponding to a source language function.
|
||||||
@ -1906,25 +1914,23 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(id));
|
let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(id));
|
||||||
debug!("trans_fn(param_substs={:?})", param_substs);
|
debug!("trans_fn(param_substs={:?})", param_substs);
|
||||||
let _icx = push_ctxt("trans_fn");
|
let _icx = push_ctxt("trans_fn");
|
||||||
let fn_ty = ccx.tcx().node_id_to_type(id);
|
|
||||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty);
|
|
||||||
let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
|
|
||||||
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
|
||||||
let abi = fn_ty.fn_abi();
|
|
||||||
let fn_ty = FnType::new(ccx, abi, &sig, &[]);
|
|
||||||
let def_id = if let Some(&def_id) = ccx.external_srcs().borrow().get(&id) {
|
let def_id = if let Some(&def_id) = ccx.external_srcs().borrow().get(&id) {
|
||||||
def_id
|
def_id
|
||||||
} else {
|
} else {
|
||||||
ccx.tcx().map.local_def_id(id)
|
ccx.tcx().map.local_def_id(id)
|
||||||
};
|
};
|
||||||
|
let fn_ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||||
|
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty);
|
||||||
|
let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
|
||||||
|
let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
|
||||||
|
let abi = fn_ty.fn_abi();
|
||||||
trans_closure(ccx,
|
trans_closure(ccx,
|
||||||
decl,
|
decl,
|
||||||
body,
|
body,
|
||||||
llfndecl,
|
llfndecl,
|
||||||
param_substs,
|
Instance::new(def_id, param_substs),
|
||||||
def_id,
|
|
||||||
id,
|
id,
|
||||||
fn_ty,
|
&sig,
|
||||||
abi,
|
abi,
|
||||||
closure::ClosureEnv::NotClosure);
|
closure::ClosureEnv::NotClosure);
|
||||||
}
|
}
|
||||||
@ -2015,9 +2021,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
|
|
||||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
arena = TypedArena::new();
|
arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfndecl, fn_ty,
|
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, None, &arena);
|
||||||
Some(ccx.tcx().map.local_def_id(ctor_id)),
|
|
||||||
param_substs, &arena);
|
|
||||||
let bcx = fcx.init(false, None);
|
let bcx = fcx.init(false, None);
|
||||||
|
|
||||||
assert!(!fcx.needs_ret_allocas);
|
assert!(!fcx.needs_ret_allocas);
|
||||||
|
@ -24,7 +24,6 @@ use middle::cstore::LOCAL_CRATE;
|
|||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer;
|
use rustc::infer;
|
||||||
use rustc::ty::subst;
|
use rustc::ty::subst;
|
||||||
use rustc::ty::subst::{Substs};
|
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::hir::map as hir_map;
|
use rustc::hir::map as hir_map;
|
||||||
use abi::{Abi, FnType};
|
use abi::{Abi, FnType};
|
||||||
@ -385,10 +384,9 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
|
|||||||
let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
|
let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
|
||||||
|
|
||||||
//
|
//
|
||||||
let empty_substs = tcx.mk_substs(Substs::empty());
|
|
||||||
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
block_arena = TypedArena::new();
|
block_arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
|
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena);
|
||||||
let mut bcx = fcx.init(false, None);
|
let mut bcx = fcx.init(false, None);
|
||||||
|
|
||||||
let llargs = get_params(fcx.llfn);
|
let llargs = get_params(fcx.llfn);
|
||||||
|
@ -234,16 +234,14 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||||||
output: sig.output,
|
output: sig.output,
|
||||||
variadic: false
|
variadic: false
|
||||||
};
|
};
|
||||||
let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
|
|
||||||
|
|
||||||
trans_closure(ccx,
|
trans_closure(ccx,
|
||||||
decl,
|
decl,
|
||||||
body,
|
body,
|
||||||
llfn,
|
llfn,
|
||||||
param_substs,
|
Instance::new(closure_def_id, param_substs),
|
||||||
closure_def_id,
|
|
||||||
id,
|
id,
|
||||||
fn_ty,
|
&sig,
|
||||||
Abi::RustCall,
|
Abi::RustCall,
|
||||||
ClosureEnv::Closure(closure_def_id, id));
|
ClosureEnv::Closure(closure_def_id, id));
|
||||||
|
|
||||||
@ -387,7 +385,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||||||
|
|
||||||
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
block_arena = TypedArena::new();
|
block_arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, substs.func_substs, &block_arena);
|
fcx = FunctionContext::new(ccx, lloncefn, fn_ty, None, &block_arena);
|
||||||
let mut bcx = fcx.init(false, None);
|
let mut bcx = fcx.init(false, None);
|
||||||
|
|
||||||
|
|
||||||
|
@ -167,11 +167,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
if cv == 1 {
|
if cv == 1 {
|
||||||
// if true { .. } [else { .. }]
|
// if true { .. } [else { .. }]
|
||||||
bcx = trans_block(bcx, &thn, dest);
|
bcx = trans_block(bcx, &thn, dest);
|
||||||
debuginfo::clear_source_location(bcx.fcx);
|
DebugLoc::None.apply(bcx.fcx);
|
||||||
} else {
|
} else {
|
||||||
if let Some(elexpr) = els {
|
if let Some(elexpr) = els {
|
||||||
bcx = expr::trans_into(bcx, &elexpr, dest);
|
bcx = expr::trans_into(bcx, &elexpr, dest);
|
||||||
debuginfo::clear_source_location(bcx.fcx);
|
DebugLoc::None.apply(bcx.fcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
let name = format!("then-block-{}-", thn.id);
|
let name = format!("then-block-{}-", thn.id);
|
||||||
let then_bcx_in = bcx.fcx.new_id_block(&name[..], thn.id);
|
let then_bcx_in = bcx.fcx.new_id_block(&name[..], thn.id);
|
||||||
let then_bcx_out = trans_block(then_bcx_in, &thn, dest);
|
let then_bcx_out = trans_block(then_bcx_in, &thn, dest);
|
||||||
debuginfo::clear_source_location(bcx.fcx);
|
DebugLoc::None.apply(bcx.fcx);
|
||||||
|
|
||||||
let cond_source_loc = cond.debug_loc();
|
let cond_source_loc = cond.debug_loc();
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
|
|
||||||
// Clear the source location because it is still set to whatever has been translated
|
// Clear the source location because it is still set to whatever has been translated
|
||||||
// right before.
|
// right before.
|
||||||
debuginfo::clear_source_location(next_bcx.fcx);
|
DebugLoc::None.apply(next_bcx.fcx);
|
||||||
|
|
||||||
next_bcx
|
next_bcx
|
||||||
}
|
}
|
||||||
|
@ -8,19 +8,24 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use super::FunctionDebugContext;
|
||||||
use super::metadata::file_metadata;
|
use super::metadata::file_metadata;
|
||||||
use super::utils::DIB;
|
use super::utils::{DIB, span_start};
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::debuginfo::{DIScope, DISubprogram};
|
use llvm::debuginfo::{DIScope, DISubprogram};
|
||||||
use common::CrateContext;
|
use common::{CrateContext, FunctionContext};
|
||||||
use rustc::hir::pat_util;
|
use rustc::hir::pat_util;
|
||||||
|
use rustc::mir::repr::{Mir, ScopeId};
|
||||||
use rustc::util::nodemap::NodeMap;
|
use rustc::util::nodemap::NodeMap;
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
use syntax::codemap::{Span, Pos};
|
use syntax::codemap::{Span, Pos};
|
||||||
use syntax::{ast, codemap};
|
use syntax::{ast, codemap};
|
||||||
|
|
||||||
|
use rustc_data_structures::bitvec::BitVector;
|
||||||
use rustc::hir::{self, PatKind};
|
use rustc::hir::{self, PatKind};
|
||||||
|
|
||||||
// This procedure builds the *scope map* for a given function, which maps any
|
// This procedure builds the *scope map* for a given function, which maps any
|
||||||
@ -65,6 +70,74 @@ pub fn create_scope_map(cx: &CrateContext,
|
|||||||
return scope_map;
|
return scope_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
|
||||||
|
/// If debuginfo is disabled, the returned vector is empty.
|
||||||
|
pub fn create_mir_scopes(fcx: &FunctionContext) -> Vec<DIScope> {
|
||||||
|
let mir = fcx.mir.clone().expect("create_mir_scopes: missing MIR for fn");
|
||||||
|
let mut scopes = vec![ptr::null_mut(); mir.scopes.len()];
|
||||||
|
|
||||||
|
let fn_metadata = match fcx.debug_context {
|
||||||
|
FunctionDebugContext::RegularContext(box ref data) => data.fn_metadata,
|
||||||
|
FunctionDebugContext::DebugInfoDisabled |
|
||||||
|
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find all the scopes with variables defined in them.
|
||||||
|
let mut has_variables = BitVector::new(mir.scopes.len());
|
||||||
|
for var in &mir.var_decls {
|
||||||
|
has_variables.insert(var.scope.index());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate all scopes.
|
||||||
|
for idx in 0..mir.scopes.len() {
|
||||||
|
let scope = ScopeId::new(idx);
|
||||||
|
make_mir_scope(fcx.ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
scopes
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_mir_scope(ccx: &CrateContext,
|
||||||
|
mir: &Mir,
|
||||||
|
has_variables: &BitVector,
|
||||||
|
fn_metadata: DISubprogram,
|
||||||
|
scope: ScopeId,
|
||||||
|
scopes: &mut [DIScope]) {
|
||||||
|
let idx = scope.index();
|
||||||
|
if !scopes[idx].is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scope_data = &mir.scopes[scope];
|
||||||
|
let parent_scope = if let Some(parent) = scope_data.parent_scope {
|
||||||
|
make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes);
|
||||||
|
scopes[parent.index()]
|
||||||
|
} else {
|
||||||
|
// The root is the function itself.
|
||||||
|
scopes[idx] = fn_metadata;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
scopes[idx] = if !has_variables.contains(idx) {
|
||||||
|
// Do not create a DIScope if there are no variables
|
||||||
|
// defined in this MIR Scope, to avoid debuginfo bloat.
|
||||||
|
parent_scope
|
||||||
|
} else {
|
||||||
|
let loc = span_start(ccx, scope_data.span);
|
||||||
|
let file_metadata = file_metadata(ccx, &loc.file.name);
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMDIBuilderCreateLexicalBlock(
|
||||||
|
DIB(ccx),
|
||||||
|
parent_scope,
|
||||||
|
file_metadata,
|
||||||
|
loc.line as c_uint,
|
||||||
|
loc.col.to_usize() as c_uint)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// local helper functions for walking the AST.
|
// local helper functions for walking the AST.
|
||||||
fn with_new_scope<F>(cx: &CrateContext,
|
fn with_new_scope<F>(cx: &CrateContext,
|
||||||
scope_span: Span,
|
scope_span: Span,
|
||||||
@ -74,7 +147,7 @@ fn with_new_scope<F>(cx: &CrateContext,
|
|||||||
F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
|
F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
|
||||||
{
|
{
|
||||||
// Create a new lexical scope and push it onto the stack
|
// Create a new lexical scope and push it onto the stack
|
||||||
let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
|
let loc = span_start(cx, scope_span);
|
||||||
let file_metadata = file_metadata(cx, &loc.file.name);
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
||||||
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
||||||
|
|
||||||
@ -199,7 +272,7 @@ fn walk_pattern(cx: &CrateContext,
|
|||||||
|
|
||||||
if need_new_scope {
|
if need_new_scope {
|
||||||
// Create a new lexical scope and push it onto the stack
|
// Create a new lexical scope and push it onto the stack
|
||||||
let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
|
let loc = span_start(cx, pat.span);
|
||||||
let file_metadata = file_metadata(cx, &loc.file.name);
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
||||||
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use self::EnumDiscriminantInfo::*;
|
|||||||
use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
|
use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
|
||||||
get_namespace_and_span_for_item, create_DIArray,
|
get_namespace_and_span_for_item, create_DIArray,
|
||||||
fn_should_be_ignored, is_node_local_to_unit};
|
fn_should_be_ignored, is_node_local_to_unit};
|
||||||
use super::namespace::namespace_for_item;
|
use super::namespace::mangled_name_of_item;
|
||||||
use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
|
use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
|
||||||
use super::{declare_local, VariableKind, VariableAccess};
|
use super::{declare_local, VariableKind, VariableAccess};
|
||||||
|
|
||||||
@ -68,8 +68,8 @@ pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
|||||||
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
||||||
|
|
||||||
// ptr::null() doesn't work :(
|
// ptr::null() doesn't work :(
|
||||||
const NO_FILE_METADATA: DIFile = (0 as DIFile);
|
pub const NO_FILE_METADATA: DIFile = (0 as DIFile);
|
||||||
const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
|
pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
|
||||||
|
|
||||||
const FLAGS_NONE: c_uint = 0;
|
const FLAGS_NONE: c_uint = 0;
|
||||||
|
|
||||||
@ -1846,28 +1846,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let var_item = cx.tcx().map.get(node_id);
|
let node_def_id = cx.tcx().map.local_def_id(node_id);
|
||||||
|
let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id);
|
||||||
let (name, span) = match var_item {
|
|
||||||
hir_map::NodeItem(item) => {
|
|
||||||
match item.node {
|
|
||||||
hir::ItemStatic(..) => (item.name, item.span),
|
|
||||||
hir::ItemConst(..) => (item.name, item.span),
|
|
||||||
_ => {
|
|
||||||
span_bug!(item.span,
|
|
||||||
"debuginfo::\
|
|
||||||
create_global_var_metadata() -
|
|
||||||
Captured var-id refers to \
|
|
||||||
unexpected ast_item variant: {:?}",
|
|
||||||
var_item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => bug!("debuginfo::create_global_var_metadata() \
|
|
||||||
- Captured var-id refers to unexpected \
|
|
||||||
hir_map variant: {:?}",
|
|
||||||
var_item)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
|
let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
|
||||||
let loc = span_start(cx, span);
|
let loc = span_start(cx, span);
|
||||||
@ -1879,12 +1859,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
|||||||
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
|
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
|
||||||
let variable_type = cx.tcx().node_id_to_type(node_id);
|
let variable_type = cx.tcx().node_id_to_type(node_id);
|
||||||
let type_metadata = type_metadata(cx, variable_type, span);
|
let type_metadata = type_metadata(cx, variable_type, span);
|
||||||
let node_def_id = cx.tcx().map.local_def_id(node_id);
|
let var_name = cx.tcx().item_name(node_def_id).to_string();
|
||||||
let namespace_node = namespace_for_item(cx, node_def_id);
|
let linkage_name = mangled_name_of_item(cx, node_def_id, "");
|
||||||
let var_name = name.to_string();
|
|
||||||
let linkage_name =
|
|
||||||
namespace_node.mangled_name_of_contained_item(&var_name[..]);
|
|
||||||
let var_scope = namespace_node.scope;
|
|
||||||
|
|
||||||
let var_name = CString::new(var_name).unwrap();
|
let var_name = CString::new(var_name).unwrap();
|
||||||
let linkage_name = CString::new(linkage_name).unwrap();
|
let linkage_name = CString::new(linkage_name).unwrap();
|
||||||
|
@ -14,42 +14,38 @@ mod doc;
|
|||||||
use self::VariableAccess::*;
|
use self::VariableAccess::*;
|
||||||
use self::VariableKind::*;
|
use self::VariableKind::*;
|
||||||
|
|
||||||
use self::utils::{DIB, span_start, assert_type_for_node_id, contains_nodebug_attribute,
|
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit,
|
||||||
create_DIArray, is_node_local_to_unit};
|
get_namespace_and_span_for_item};
|
||||||
use self::namespace::{namespace_for_item, NamespaceTreeNode};
|
use self::namespace::mangled_name_of_item;
|
||||||
use self::type_names::compute_debuginfo_type_name;
|
use self::type_names::compute_debuginfo_type_name;
|
||||||
use self::metadata::{type_metadata, diverging_type_metadata};
|
use self::metadata::{type_metadata, diverging_type_metadata};
|
||||||
use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
|
use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
|
||||||
use self::source_loc::InternalDebugLocation;
|
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{ModuleRef, ContextRef, ValueRef};
|
use llvm::{ModuleRef, ContextRef, ValueRef};
|
||||||
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
|
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
|
||||||
DIDescriptor, FlagPrototyped};
|
FlagPrototyped};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::normalize_associated_type;
|
use rustc::hir::map::DefPathData;
|
||||||
use rustc::ty::subst::{self, Substs};
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
use abi::Abi;
|
use abi::Abi;
|
||||||
use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
|
use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder};
|
||||||
use monomorphize;
|
use monomorphize::Instance;
|
||||||
use rustc::infer;
|
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
||||||
use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
|
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
|
||||||
use rustc::hir::map as hir_map;
|
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use syntax::codemap::{Span, Pos};
|
use syntax::codemap::{Span, Pos};
|
||||||
use syntax::{ast, codemap};
|
use syntax::{ast, codemap};
|
||||||
use syntax::attr::IntType;
|
use syntax::attr::IntType;
|
||||||
use syntax::parse::token::{self, special_idents};
|
|
||||||
|
|
||||||
pub mod gdb;
|
pub mod gdb;
|
||||||
mod utils;
|
mod utils;
|
||||||
@ -59,8 +55,7 @@ mod metadata;
|
|||||||
mod create_scope_map;
|
mod create_scope_map;
|
||||||
mod source_loc;
|
mod source_loc;
|
||||||
|
|
||||||
pub use self::source_loc::set_source_location;
|
pub use self::create_scope_map::create_mir_scopes;
|
||||||
pub use self::source_loc::clear_source_location;
|
|
||||||
pub use self::source_loc::start_emitting_source_locations;
|
pub use self::source_loc::start_emitting_source_locations;
|
||||||
pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
|
pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
|
||||||
pub use self::source_loc::with_source_location_override;
|
pub use self::source_loc::with_source_location_override;
|
||||||
@ -84,7 +79,7 @@ pub struct CrateDebugContext<'tcx> {
|
|||||||
created_enum_disr_types: RefCell<FnvHashMap<(DefId, IntType), DIType>>,
|
created_enum_disr_types: RefCell<FnvHashMap<(DefId, IntType), DIType>>,
|
||||||
|
|
||||||
type_map: RefCell<TypeMap<'tcx>>,
|
type_map: RefCell<TypeMap<'tcx>>,
|
||||||
namespace_map: RefCell<FnvHashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
|
namespace_map: RefCell<DefIdMap<DIScope>>,
|
||||||
|
|
||||||
// This collection is used to assert that composite types (structs, enums,
|
// This collection is used to assert that composite types (structs, enums,
|
||||||
// ...) have their members only set once:
|
// ...) have their members only set once:
|
||||||
@ -104,7 +99,7 @@ impl<'tcx> CrateDebugContext<'tcx> {
|
|||||||
created_files: RefCell::new(FnvHashMap()),
|
created_files: RefCell::new(FnvHashMap()),
|
||||||
created_enum_disr_types: RefCell::new(FnvHashMap()),
|
created_enum_disr_types: RefCell::new(FnvHashMap()),
|
||||||
type_map: RefCell::new(TypeMap::new()),
|
type_map: RefCell::new(TypeMap::new()),
|
||||||
namespace_map: RefCell::new(FnvHashMap()),
|
namespace_map: RefCell::new(DefIdMap()),
|
||||||
composite_types_completed: RefCell::new(FnvHashSet()),
|
composite_types_completed: RefCell::new(FnvHashSet()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -214,6 +209,18 @@ pub fn finalize(cx: &CrateContext) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a function-specific debug context for a function w/o debuginfo.
|
||||||
|
pub fn empty_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>)
|
||||||
|
-> FunctionDebugContext {
|
||||||
|
if cx.sess().opts.debuginfo == NoDebugInfo {
|
||||||
|
return FunctionDebugContext::DebugInfoDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the debug location so we don't assign them in the function prelude.
|
||||||
|
source_loc::set_debug_location(cx, None, UnknownLocation);
|
||||||
|
FunctionDebugContext::FunctionWithoutDebugInfo
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates the function-specific debug context.
|
/// Creates the function-specific debug context.
|
||||||
///
|
///
|
||||||
/// Returns the FunctionDebugContext for the function which holds state needed
|
/// Returns the FunctionDebugContext for the function which holds state needed
|
||||||
@ -221,8 +228,9 @@ pub fn finalize(cx: &CrateContext) {
|
|||||||
/// FunctionDebugContext enum which indicates why no debuginfo should be created
|
/// FunctionDebugContext enum which indicates why no debuginfo should be created
|
||||||
/// for the function.
|
/// for the function.
|
||||||
pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
fn_ast_id: ast::NodeId,
|
instance: Instance<'tcx>,
|
||||||
param_substs: &Substs<'tcx>,
|
sig: &ty::FnSig<'tcx>,
|
||||||
|
abi: Abi,
|
||||||
llfn: ValueRef) -> FunctionDebugContext {
|
llfn: ValueRef) -> FunctionDebugContext {
|
||||||
if cx.sess().opts.debuginfo == NoDebugInfo {
|
if cx.sess().opts.debuginfo == NoDebugInfo {
|
||||||
return FunctionDebugContext::DebugInfoDisabled;
|
return FunctionDebugContext::DebugInfoDisabled;
|
||||||
@ -230,105 +238,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
|
|
||||||
// Clear the debug location so we don't assign them in the function prelude.
|
// Clear the debug location so we don't assign them in the function prelude.
|
||||||
// Do this here already, in case we do an early exit from this function.
|
// Do this here already, in case we do an early exit from this function.
|
||||||
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
|
source_loc::set_debug_location(cx, None, UnknownLocation);
|
||||||
|
|
||||||
if fn_ast_id == ast::DUMMY_NODE_ID {
|
|
||||||
// This is a function not linked to any source location, so don't
|
|
||||||
// generate debuginfo for it.
|
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
let empty_generics = hir::Generics::empty();
|
|
||||||
|
|
||||||
let fnitem = cx.tcx().map.get(fn_ast_id);
|
|
||||||
|
|
||||||
let (name, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
|
|
||||||
hir_map::NodeItem(ref item) => {
|
|
||||||
if contains_nodebug_attribute(&item.attrs) {
|
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
match item.node {
|
|
||||||
hir::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
|
|
||||||
(item.name, fn_decl, generics, top_level_block, item.span, true)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
span_bug!(item.span,
|
|
||||||
"create_function_debug_context: item bound to non-function");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hir_map::NodeImplItem(impl_item) => {
|
|
||||||
match impl_item.node {
|
|
||||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
|
||||||
if contains_nodebug_attribute(&impl_item.attrs) {
|
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
(impl_item.name,
|
|
||||||
&sig.decl,
|
|
||||||
&sig.generics,
|
|
||||||
body,
|
|
||||||
impl_item.span,
|
|
||||||
true)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
span_bug!(impl_item.span,
|
|
||||||
"create_function_debug_context() \
|
|
||||||
called on non-method impl item?!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hir_map::NodeExpr(ref expr) => {
|
|
||||||
match expr.node {
|
|
||||||
hir::ExprClosure(_, ref fn_decl, ref top_level_block) => {
|
|
||||||
let name = format!("fn{}", token::gensym("fn"));
|
|
||||||
let name = token::intern(&name[..]);
|
|
||||||
(name, fn_decl,
|
|
||||||
// This is not quite right. It should actually inherit
|
|
||||||
// the generics of the enclosing function.
|
|
||||||
&empty_generics,
|
|
||||||
top_level_block,
|
|
||||||
expr.span,
|
|
||||||
// Don't try to lookup the item path:
|
|
||||||
false)
|
|
||||||
}
|
|
||||||
_ => span_bug!(expr.span,
|
|
||||||
"create_function_debug_context: expected an expr_fn_block here")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hir_map::NodeTraitItem(trait_item) => {
|
|
||||||
match trait_item.node {
|
|
||||||
hir::MethodTraitItem(ref sig, Some(ref body)) => {
|
|
||||||
if contains_nodebug_attribute(&trait_item.attrs) {
|
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
(trait_item.name,
|
|
||||||
&sig.decl,
|
|
||||||
&sig.generics,
|
|
||||||
body,
|
|
||||||
trait_item.span,
|
|
||||||
true)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
bug!("create_function_debug_context: \
|
|
||||||
unexpected sort of node: {:?}",
|
|
||||||
fnitem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hir_map::NodeForeignItem(..) |
|
|
||||||
hir_map::NodeVariant(..) |
|
|
||||||
hir_map::NodeStructCtor(..) => {
|
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
||||||
}
|
|
||||||
_ => bug!("create_function_debug_context: \
|
|
||||||
unexpected sort of node: {:?}",
|
|
||||||
fnitem)
|
|
||||||
};
|
|
||||||
|
|
||||||
// This can be the case for functions inlined from another crate
|
// This can be the case for functions inlined from another crate
|
||||||
|
let (containing_scope, span) = get_namespace_and_span_for_item(cx, instance.def);
|
||||||
if span == codemap::DUMMY_SP {
|
if span == codemap::DUMMY_SP {
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
||||||
}
|
}
|
||||||
@ -337,44 +250,38 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
let file_metadata = file_metadata(cx, &loc.file.name);
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
||||||
|
|
||||||
let function_type_metadata = unsafe {
|
let function_type_metadata = unsafe {
|
||||||
let fn_signature = get_function_signature(cx,
|
let fn_signature = get_function_signature(cx, sig, abi);
|
||||||
fn_ast_id,
|
|
||||||
param_substs,
|
|
||||||
span);
|
|
||||||
llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
|
llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Find the enclosing function, in case this is a closure.
|
||||||
|
let mut fn_def_id = instance.def;
|
||||||
|
let mut def_key = cx.tcx().def_key(fn_def_id);
|
||||||
|
let mut name = def_key.disambiguated_data.data.to_string();
|
||||||
|
let name_len = name.len();
|
||||||
|
while def_key.disambiguated_data.data == DefPathData::ClosureExpr {
|
||||||
|
fn_def_id.index = def_key.parent.expect("closure without a parent?");
|
||||||
|
def_key = cx.tcx().def_key(fn_def_id);
|
||||||
|
}
|
||||||
|
|
||||||
// Get_template_parameters() will append a `<...>` clause to the function
|
// Get_template_parameters() will append a `<...>` clause to the function
|
||||||
// name if necessary.
|
// name if necessary.
|
||||||
let mut function_name = name.to_string();
|
let generics = cx.tcx().lookup_item_type(fn_def_id).generics;
|
||||||
let template_parameters = get_template_parameters(cx,
|
let template_parameters = get_template_parameters(cx,
|
||||||
generics,
|
&generics,
|
||||||
param_substs,
|
instance.substs,
|
||||||
file_metadata,
|
file_metadata,
|
||||||
&mut function_name);
|
&mut name);
|
||||||
|
|
||||||
// There is no hir_map::Path for hir::ExprClosure-type functions. For now,
|
// Build the linkage_name out of the item path and "template" parameters.
|
||||||
// just don't put them into a namespace. In the future this could be improved
|
let linkage_name = mangled_name_of_item(cx, instance.def, &name[name_len..]);
|
||||||
// somehow (storing a path in the hir_map, or construct a path using the
|
|
||||||
// enclosing function).
|
|
||||||
let (linkage_name, containing_scope) = if has_path {
|
|
||||||
let fn_ast_def_id = cx.tcx().map.local_def_id(fn_ast_id);
|
|
||||||
let namespace_node = namespace_for_item(cx, fn_ast_def_id);
|
|
||||||
let linkage_name = namespace_node.mangled_name_of_contained_item(
|
|
||||||
&function_name[..]);
|
|
||||||
let containing_scope = namespace_node.scope;
|
|
||||||
(linkage_name, containing_scope)
|
|
||||||
} else {
|
|
||||||
(function_name.clone(), file_metadata)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Clang sets this parameter to the opening brace of the function's block,
|
let scope_line = span_start(cx, span).line;
|
||||||
// so let's do this too.
|
|
||||||
let scope_line = span_start(cx, top_level_block.span).line;
|
|
||||||
|
|
||||||
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
|
let local_id = cx.tcx().map.as_local_node_id(instance.def);
|
||||||
|
let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id));
|
||||||
|
|
||||||
let function_name = CString::new(function_name).unwrap();
|
let function_name = CString::new(name).unwrap();
|
||||||
let linkage_name = CString::new(linkage_name).unwrap();
|
let linkage_name = CString::new(linkage_name).unwrap();
|
||||||
let fn_metadata = unsafe {
|
let fn_metadata = unsafe {
|
||||||
llvm::LLVMDIBuilderCreateFunction(
|
llvm::LLVMDIBuilderCreateFunction(
|
||||||
@ -395,54 +302,24 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
ptr::null_mut())
|
ptr::null_mut())
|
||||||
};
|
};
|
||||||
|
|
||||||
let scope_map = create_scope_map::create_scope_map(cx,
|
|
||||||
&fn_decl.inputs,
|
|
||||||
&top_level_block,
|
|
||||||
fn_metadata,
|
|
||||||
fn_ast_id);
|
|
||||||
|
|
||||||
// Initialize fn debug context (including scope map and namespace map)
|
// Initialize fn debug context (including scope map and namespace map)
|
||||||
let fn_debug_context = box FunctionDebugContextData {
|
let fn_debug_context = box FunctionDebugContextData {
|
||||||
scope_map: RefCell::new(scope_map),
|
scope_map: RefCell::new(NodeMap()),
|
||||||
fn_metadata: fn_metadata,
|
fn_metadata: fn_metadata,
|
||||||
argument_counter: Cell::new(1),
|
argument_counter: Cell::new(1),
|
||||||
source_locations_enabled: Cell::new(false),
|
source_locations_enabled: Cell::new(false),
|
||||||
source_location_override: Cell::new(false),
|
source_location_override: Cell::new(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return FunctionDebugContext::RegularContext(fn_debug_context);
|
return FunctionDebugContext::RegularContext(fn_debug_context);
|
||||||
|
|
||||||
fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
fn_ast_id: ast::NodeId,
|
sig: &ty::FnSig<'tcx>,
|
||||||
param_substs: &Substs<'tcx>,
|
abi: Abi) -> DIArray {
|
||||||
error_reporting_span: Span) -> DIArray {
|
|
||||||
if cx.sess().opts.debuginfo == LimitedDebugInfo {
|
if cx.sess().opts.debuginfo == LimitedDebugInfo {
|
||||||
return create_DIArray(DIB(cx), &[]);
|
return create_DIArray(DIB(cx), &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return type -- llvm::DIBuilder wants this at index 0
|
|
||||||
assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
|
|
||||||
let fn_type = cx.tcx().node_id_to_type(fn_ast_id);
|
|
||||||
let fn_type = monomorphize::apply_param_substs(cx.tcx(), param_substs, &fn_type);
|
|
||||||
|
|
||||||
let (sig, abi) = match fn_type.sty {
|
|
||||||
ty::TyFnDef(_, _, ref barefnty) | ty::TyFnPtr(ref barefnty) => {
|
|
||||||
let sig = cx.tcx().erase_late_bound_regions(&barefnty.sig);
|
|
||||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
|
||||||
(sig, barefnty.abi)
|
|
||||||
}
|
|
||||||
ty::TyClosure(def_id, ref substs) => {
|
|
||||||
let closure_type = cx.tcx().closure_type(def_id, substs);
|
|
||||||
let sig = cx.tcx().erase_late_bound_regions(&closure_type.sig);
|
|
||||||
let sig = infer::normalize_associated_type(cx.tcx(), &sig);
|
|
||||||
(sig, closure_type.abi)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => bug!("get_function_metdata: Expected a function type!")
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut signature = Vec::with_capacity(sig.inputs.len() + 1);
|
let mut signature = Vec::with_capacity(sig.inputs.len() + 1);
|
||||||
|
|
||||||
// Return type -- llvm::DIBuilder wants this at index 0
|
// Return type -- llvm::DIBuilder wants this at index 0
|
||||||
@ -477,86 +354,39 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
generics: &hir::Generics,
|
generics: &ty::Generics<'tcx>,
|
||||||
param_substs: &Substs<'tcx>,
|
param_substs: &Substs<'tcx>,
|
||||||
file_metadata: DIFile,
|
file_metadata: DIFile,
|
||||||
name_to_append_suffix_to: &mut String)
|
name_to_append_suffix_to: &mut String)
|
||||||
-> DIArray
|
-> DIArray
|
||||||
{
|
{
|
||||||
let self_type = param_substs.self_ty();
|
let actual_types = param_substs.types.as_slice();
|
||||||
let self_type = normalize_associated_type(cx.tcx(), &self_type);
|
|
||||||
|
|
||||||
// Only true for static default methods:
|
if actual_types.is_empty() {
|
||||||
let has_self_type = self_type.is_some();
|
|
||||||
|
|
||||||
if !generics.is_type_parameterized() && !has_self_type {
|
|
||||||
return create_DIArray(DIB(cx), &[]);
|
return create_DIArray(DIB(cx), &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
name_to_append_suffix_to.push('<');
|
name_to_append_suffix_to.push('<');
|
||||||
|
for (i, &actual_type) in actual_types.iter().enumerate() {
|
||||||
// The list to be filled with template parameters:
|
|
||||||
let mut template_params: Vec<DIDescriptor> =
|
|
||||||
Vec::with_capacity(generics.ty_params.len() + 1);
|
|
||||||
|
|
||||||
// Handle self type
|
|
||||||
if has_self_type {
|
|
||||||
let actual_self_type = self_type.unwrap();
|
|
||||||
// Add self type name to <...> clause of function name
|
|
||||||
let actual_self_type_name = compute_debuginfo_type_name(
|
|
||||||
cx,
|
|
||||||
actual_self_type,
|
|
||||||
true);
|
|
||||||
|
|
||||||
name_to_append_suffix_to.push_str(&actual_self_type_name[..]);
|
|
||||||
|
|
||||||
if generics.is_type_parameterized() {
|
|
||||||
name_to_append_suffix_to.push_str(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only create type information if full debuginfo is enabled
|
|
||||||
if cx.sess().opts.debuginfo == FullDebugInfo {
|
|
||||||
let actual_self_type_metadata = type_metadata(cx,
|
|
||||||
actual_self_type,
|
|
||||||
codemap::DUMMY_SP);
|
|
||||||
|
|
||||||
let name = special_idents::type_self.name.as_str();
|
|
||||||
|
|
||||||
let name = CString::new(name.as_bytes()).unwrap();
|
|
||||||
let param_metadata = unsafe {
|
|
||||||
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
|
||||||
DIB(cx),
|
|
||||||
ptr::null_mut(),
|
|
||||||
name.as_ptr(),
|
|
||||||
actual_self_type_metadata,
|
|
||||||
file_metadata,
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
};
|
|
||||||
|
|
||||||
template_params.push(param_metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle other generic parameters
|
|
||||||
let actual_types = param_substs.types.get_slice(subst::FnSpace);
|
|
||||||
for (index, &hir::TyParam{ name, .. }) in generics.ty_params.iter().enumerate() {
|
|
||||||
let actual_type = actual_types[index];
|
|
||||||
// Add actual type name to <...> clause of function name
|
// Add actual type name to <...> clause of function name
|
||||||
let actual_type_name = compute_debuginfo_type_name(cx,
|
let actual_type_name = compute_debuginfo_type_name(cx,
|
||||||
actual_type,
|
actual_type,
|
||||||
true);
|
true);
|
||||||
name_to_append_suffix_to.push_str(&actual_type_name[..]);
|
name_to_append_suffix_to.push_str(&actual_type_name[..]);
|
||||||
|
|
||||||
if index != generics.ty_params.len() - 1 {
|
if i != actual_types.len() - 1 {
|
||||||
name_to_append_suffix_to.push_str(",");
|
name_to_append_suffix_to.push_str(",");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
name_to_append_suffix_to.push('>');
|
||||||
|
|
||||||
// Again, only create type information if full debuginfo is enabled
|
// Again, only create type information if full debuginfo is enabled
|
||||||
if cx.sess().opts.debuginfo == FullDebugInfo {
|
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
|
||||||
|
generics.types.as_slice().iter().enumerate().map(|(i, param)| {
|
||||||
|
let actual_type = actual_types[i];
|
||||||
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
|
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
|
||||||
let name = CString::new(name.as_str().as_bytes()).unwrap();
|
let name = CString::new(param.name.as_str().as_bytes()).unwrap();
|
||||||
let param_metadata = unsafe {
|
unsafe {
|
||||||
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
@ -565,24 +395,42 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
file_metadata,
|
file_metadata,
|
||||||
0,
|
0,
|
||||||
0)
|
0)
|
||||||
};
|
}
|
||||||
template_params.push(param_metadata);
|
}).collect()
|
||||||
}
|
} else {
|
||||||
}
|
vec![]
|
||||||
|
};
|
||||||
name_to_append_suffix_to.push('>');
|
|
||||||
|
|
||||||
return create_DIArray(DIB(cx), &template_params[..]);
|
return create_DIArray(DIB(cx), &template_params[..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
/// Computes the scope map for a function given its declaration and body.
|
||||||
variable_name: ast::Name,
|
pub fn fill_scope_map_for_function<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
|
||||||
variable_type: Ty<'tcx>,
|
fn_decl: &hir::FnDecl,
|
||||||
scope_metadata: DIScope,
|
top_level_block: &hir::Block,
|
||||||
variable_access: VariableAccess,
|
fn_ast_id: ast::NodeId) {
|
||||||
variable_kind: VariableKind,
|
match fcx.debug_context {
|
||||||
span: Span) {
|
FunctionDebugContext::RegularContext(box ref data) => {
|
||||||
|
let scope_map = create_scope_map::create_scope_map(fcx.ccx,
|
||||||
|
&fn_decl.inputs,
|
||||||
|
top_level_block,
|
||||||
|
data.fn_metadata,
|
||||||
|
fn_ast_id);
|
||||||
|
*data.scope_map.borrow_mut() = scope_map;
|
||||||
|
}
|
||||||
|
FunctionDebugContext::DebugInfoDisabled |
|
||||||
|
FunctionDebugContext::FunctionWithoutDebugInfo => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
|
variable_name: ast::Name,
|
||||||
|
variable_type: Ty<'tcx>,
|
||||||
|
scope_metadata: DIScope,
|
||||||
|
variable_access: VariableAccess,
|
||||||
|
variable_kind: VariableKind,
|
||||||
|
span: Span) {
|
||||||
let cx: &CrateContext = bcx.ccx();
|
let cx: &CrateContext = bcx.ccx();
|
||||||
|
|
||||||
let filename = span_start(cx, span).file.name.clone();
|
let filename = span_start(cx, span).file.name.clone();
|
||||||
@ -616,9 +464,8 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
address_operations.len() as c_uint,
|
address_operations.len() as c_uint,
|
||||||
argument_index)
|
argument_index)
|
||||||
};
|
};
|
||||||
source_loc::set_debug_location(cx, InternalDebugLocation::new(scope_metadata,
|
source_loc::set_debug_location(cx, None,
|
||||||
loc.line,
|
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
|
||||||
loc.col.to_usize()));
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
|
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
|
||||||
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
||||||
@ -642,7 +489,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
.get_ref(span)
|
.get_ref(span)
|
||||||
.source_locations_enabled
|
.source_locations_enabled
|
||||||
.get());
|
.get());
|
||||||
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
|
source_loc::set_debug_location(cx, None, UnknownLocation);
|
||||||
}
|
}
|
||||||
_ => { /* nothing to do */ }
|
_ => { /* nothing to do */ }
|
||||||
}
|
}
|
||||||
@ -651,19 +498,17 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum DebugLoc {
|
pub enum DebugLoc {
|
||||||
At(ast::NodeId, Span),
|
At(ast::NodeId, Span),
|
||||||
|
ScopeAt(DIScope, Span),
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugLoc {
|
impl DebugLoc {
|
||||||
pub fn apply(&self, fcx: &FunctionContext) {
|
pub fn apply(self, fcx: &FunctionContext) {
|
||||||
match *self {
|
source_loc::set_source_location(fcx, None, self);
|
||||||
DebugLoc::At(node_id, span) => {
|
}
|
||||||
source_loc::set_source_location(fcx, node_id, span);
|
|
||||||
}
|
pub fn apply_to_bcx(self, bcx: &BlockAndBuilder) {
|
||||||
DebugLoc::None => {
|
source_loc::set_source_location(bcx.fcx(), Some(bcx), self);
|
||||||
source_loc::clear_source_location(fcx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,118 +10,82 @@
|
|||||||
|
|
||||||
// Namespace Handling.
|
// Namespace Handling.
|
||||||
|
|
||||||
use super::utils::{DIB, debug_context};
|
use super::metadata::{file_metadata, NO_FILE_METADATA, UNKNOWN_LINE_NUMBER};
|
||||||
|
use super::utils::{DIB, debug_context, span_start};
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::debuginfo::DIScope;
|
use llvm::debuginfo::DIScope;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map as hir_map;
|
use rustc::hir::map::DefPathData;
|
||||||
use common::CrateContext;
|
use common::CrateContext;
|
||||||
|
|
||||||
|
use libc::c_uint;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::iter::once;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::{Rc, Weak};
|
use syntax::codemap::DUMMY_SP;
|
||||||
use syntax::ast;
|
|
||||||
use syntax::parse::token;
|
|
||||||
|
|
||||||
pub struct NamespaceTreeNode {
|
pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String {
|
||||||
pub name: ast::Name,
|
fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) {
|
||||||
pub scope: DIScope,
|
let def_key = ccx.tcx().def_key(def_id);
|
||||||
pub parent: Option<Weak<NamespaceTreeNode>>,
|
if let Some(parent) = def_key.parent {
|
||||||
}
|
fill_nested(ccx, DefId {
|
||||||
|
krate: def_id.krate,
|
||||||
impl NamespaceTreeNode {
|
index: parent
|
||||||
pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
|
}, "", output);
|
||||||
fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
|
|
||||||
match node.parent {
|
|
||||||
Some(ref parent) => fill_nested(&parent.upgrade().unwrap(), output),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
let string = node.name.as_str();
|
|
||||||
output.push_str(&string.len().to_string());
|
|
||||||
output.push_str(&string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut name = String::from("_ZN");
|
let name = match def_key.disambiguated_data.data {
|
||||||
fill_nested(self, &mut name);
|
DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate),
|
||||||
name.push_str(&item_name.len().to_string());
|
data => data.as_interned_str()
|
||||||
name.push_str(item_name);
|
|
||||||
name.push('E');
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc<NamespaceTreeNode> {
|
|
||||||
// prepend crate name.
|
|
||||||
// This shouldn't need a roundtrip through InternedString.
|
|
||||||
let krate = token::intern(&cx.tcx().crate_name(def_id.krate));
|
|
||||||
let krate = hir_map::DefPathData::TypeNs(krate);
|
|
||||||
let path = cx.tcx().def_path(def_id).data;
|
|
||||||
let mut path = once(krate).chain(path.into_iter().map(|e| e.data)).peekable();
|
|
||||||
|
|
||||||
let mut current_key = Vec::new();
|
|
||||||
let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
|
|
||||||
|
|
||||||
// Create/Lookup namespace for each element of the path.
|
|
||||||
loop {
|
|
||||||
// Emulate a for loop so we can use peek below.
|
|
||||||
let path_element = match path.next() {
|
|
||||||
Some(e) => e,
|
|
||||||
None => break
|
|
||||||
};
|
|
||||||
// Ignore the name of the item (the last path element).
|
|
||||||
if path.peek().is_none() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This shouldn't need a roundtrip through InternedString.
|
|
||||||
let namespace_name = path_element.as_interned_str();
|
|
||||||
let name = token::intern(&namespace_name);
|
|
||||||
current_key.push(name);
|
|
||||||
|
|
||||||
let existing_node = debug_context(cx).namespace_map.borrow()
|
|
||||||
.get(¤t_key).cloned();
|
|
||||||
let current_node = match existing_node {
|
|
||||||
Some(existing_node) => existing_node,
|
|
||||||
None => {
|
|
||||||
// create and insert
|
|
||||||
let parent_scope = match parent_node {
|
|
||||||
Some(ref node) => node.scope,
|
|
||||||
None => ptr::null_mut()
|
|
||||||
};
|
|
||||||
let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
|
|
||||||
let scope = unsafe {
|
|
||||||
llvm::LLVMDIBuilderCreateNameSpace(
|
|
||||||
DIB(cx),
|
|
||||||
parent_scope,
|
|
||||||
namespace_name.as_ptr(),
|
|
||||||
// cannot reconstruct file ...
|
|
||||||
ptr::null_mut(),
|
|
||||||
// ... or line information, but that's not so important.
|
|
||||||
0)
|
|
||||||
};
|
|
||||||
|
|
||||||
let node = Rc::new(NamespaceTreeNode {
|
|
||||||
name: name,
|
|
||||||
scope: scope,
|
|
||||||
parent: parent_node.map(|parent| Rc::downgrade(&parent)),
|
|
||||||
});
|
|
||||||
|
|
||||||
debug_context(cx).namespace_map.borrow_mut()
|
|
||||||
.insert(current_key.clone(), node.clone());
|
|
||||||
|
|
||||||
node
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
parent_node = Some(current_node);
|
output.push_str(&(name.len() + extra.len()).to_string());
|
||||||
|
output.push_str(&name);
|
||||||
|
output.push_str(extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
match parent_node {
|
let mut name = String::from("_ZN");
|
||||||
Some(node) => node,
|
fill_nested(ccx, def_id, extra, &mut name);
|
||||||
None => {
|
name.push('E');
|
||||||
bug!("debuginfo::namespace_for_item: path too short for {:?}", def_id);
|
name
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
|
||||||
|
if let Some(&scope) = debug_context(ccx).namespace_map.borrow().get(&def_id) {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
let def_key = ccx.tcx().def_key(def_id);
|
||||||
|
let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| {
|
||||||
|
item_namespace(ccx, DefId {
|
||||||
|
krate: def_id.krate,
|
||||||
|
index: parent
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let namespace_name = match def_key.disambiguated_data.data {
|
||||||
|
DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate),
|
||||||
|
data => data.as_interned_str()
|
||||||
|
};
|
||||||
|
|
||||||
|
let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
|
||||||
|
let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP);
|
||||||
|
let (file, line) = if span != DUMMY_SP {
|
||||||
|
let loc = span_start(ccx, span);
|
||||||
|
(file_metadata(ccx, &loc.file.name), loc.line as c_uint)
|
||||||
|
} else {
|
||||||
|
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
|
||||||
|
};
|
||||||
|
|
||||||
|
let scope = unsafe {
|
||||||
|
llvm::LLVMDIBuilderCreateNameSpace(
|
||||||
|
DIB(ccx),
|
||||||
|
parent_scope,
|
||||||
|
namespace_name.as_ptr(),
|
||||||
|
file,
|
||||||
|
line as c_uint)
|
||||||
|
};
|
||||||
|
|
||||||
|
debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope);
|
||||||
|
scope
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
|
|
||||||
use self::InternalDebugLocation::*;
|
use self::InternalDebugLocation::*;
|
||||||
|
|
||||||
use super::utils::{debug_context, span_start, fn_should_be_ignored};
|
use super::utils::{debug_context, span_start};
|
||||||
use super::metadata::{scope_metadata,UNKNOWN_COLUMN_NUMBER};
|
use super::metadata::{scope_metadata,UNKNOWN_COLUMN_NUMBER};
|
||||||
use super::{FunctionDebugContext, DebugLoc};
|
use super::{FunctionDebugContext, DebugLoc};
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::debuginfo::DIScope;
|
use llvm::debuginfo::DIScope;
|
||||||
|
use builder::Builder;
|
||||||
use common::{NodeIdAndSpan, CrateContext, FunctionContext};
|
use common::{NodeIdAndSpan, CrateContext, FunctionContext};
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
@ -86,41 +87,46 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||||||
|
|
||||||
/// Sets the current debug location at the beginning of the span.
|
/// Sets the current debug location at the beginning of the span.
|
||||||
///
|
///
|
||||||
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id
|
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
|
||||||
/// parameter is used to reliably find the correct visibility scope for the code
|
|
||||||
/// position.
|
|
||||||
pub fn set_source_location(fcx: &FunctionContext,
|
pub fn set_source_location(fcx: &FunctionContext,
|
||||||
node_id: ast::NodeId,
|
builder: Option<&Builder>,
|
||||||
span: Span) {
|
debug_loc: DebugLoc) {
|
||||||
match fcx.debug_context {
|
let builder = builder.map(|b| b.llbuilder);
|
||||||
|
let function_debug_context = match fcx.debug_context {
|
||||||
FunctionDebugContext::DebugInfoDisabled => return,
|
FunctionDebugContext::DebugInfoDisabled => return,
|
||||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||||
set_debug_location(fcx.ccx, UnknownLocation);
|
set_debug_location(fcx.ccx, builder, UnknownLocation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FunctionDebugContext::RegularContext(box ref function_debug_context) => {
|
FunctionDebugContext::RegularContext(box ref data) => data
|
||||||
if function_debug_context.source_location_override.get() {
|
};
|
||||||
// Just ignore any attempts to set a new debug location while
|
|
||||||
// the override is active.
|
if function_debug_context.source_location_override.get() {
|
||||||
|
// Just ignore any attempts to set a new debug location while
|
||||||
|
// the override is active.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dbg_loc = if function_debug_context.source_locations_enabled.get() {
|
||||||
|
let (scope, span) = match debug_loc {
|
||||||
|
DebugLoc::At(node_id, span) => {
|
||||||
|
(scope_metadata(fcx, node_id, span), span)
|
||||||
|
}
|
||||||
|
DebugLoc::ScopeAt(scope, span) => (scope, span),
|
||||||
|
DebugLoc::None => {
|
||||||
|
set_debug_location(fcx.ccx, builder, UnknownLocation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let cx = fcx.ccx;
|
debug!("set_source_location: {}",
|
||||||
|
fcx.ccx.sess().codemap().span_to_string(span));
|
||||||
debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
|
let loc = span_start(fcx.ccx, span);
|
||||||
|
InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
|
||||||
if function_debug_context.source_locations_enabled.get() {
|
} else {
|
||||||
let loc = span_start(cx, span);
|
UnknownLocation
|
||||||
let scope = scope_metadata(fcx, node_id, span);
|
};
|
||||||
|
set_debug_location(fcx.ccx, builder, dbg_loc);
|
||||||
set_debug_location(cx, InternalDebugLocation::new(scope,
|
|
||||||
loc.line,
|
|
||||||
loc.col.to_usize()));
|
|
||||||
} else {
|
|
||||||
set_debug_location(cx, UnknownLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function makes sure that all debug locations emitted while executing
|
/// This function makes sure that all debug locations emitted while executing
|
||||||
@ -135,7 +141,7 @@ pub fn with_source_location_override<F, R>(fcx: &FunctionContext,
|
|||||||
wrapped_function()
|
wrapped_function()
|
||||||
}
|
}
|
||||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||||
set_debug_location(fcx.ccx, UnknownLocation);
|
set_debug_location(fcx.ccx, None, UnknownLocation);
|
||||||
wrapped_function()
|
wrapped_function()
|
||||||
}
|
}
|
||||||
FunctionDebugContext::RegularContext(box ref function_debug_context) => {
|
FunctionDebugContext::RegularContext(box ref function_debug_context) => {
|
||||||
@ -152,17 +158,6 @@ pub fn with_source_location_override<F, R>(fcx: &FunctionContext,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the current debug location.
|
|
||||||
///
|
|
||||||
/// Instructions generated hereafter won't be assigned a source location.
|
|
||||||
pub fn clear_source_location(fcx: &FunctionContext) {
|
|
||||||
if fn_should_be_ignored(fcx) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_debug_location(fcx.ccx, UnknownLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enables emitting source locations for the given functions.
|
/// Enables emitting source locations for the given functions.
|
||||||
///
|
///
|
||||||
/// Since we don't want source locations to be emitted for the function prelude,
|
/// Since we don't want source locations to be emitted for the function prelude,
|
||||||
@ -195,37 +190,42 @@ impl InternalDebugLocation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) {
|
pub fn set_debug_location(cx: &CrateContext,
|
||||||
if debug_location == debug_context(cx).current_debug_location.get() {
|
builder: Option<llvm::BuilderRef>,
|
||||||
return;
|
debug_location: InternalDebugLocation) {
|
||||||
|
if builder.is_none() {
|
||||||
|
if debug_location == debug_context(cx).current_debug_location.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let metadata_node;
|
let metadata_node = match debug_location {
|
||||||
|
|
||||||
match debug_location {
|
|
||||||
KnownLocation { scope, line, .. } => {
|
KnownLocation { scope, line, .. } => {
|
||||||
// Always set the column to zero like Clang and GCC
|
// Always set the column to zero like Clang and GCC
|
||||||
let col = UNKNOWN_COLUMN_NUMBER;
|
let col = UNKNOWN_COLUMN_NUMBER;
|
||||||
debug!("setting debug location to {} {}", line, col);
|
debug!("setting debug location to {} {}", line, col);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
metadata_node = llvm::LLVMDIBuilderCreateDebugLocation(
|
llvm::LLVMDIBuilderCreateDebugLocation(
|
||||||
debug_context(cx).llcontext,
|
debug_context(cx).llcontext,
|
||||||
line as c_uint,
|
line as c_uint,
|
||||||
col as c_uint,
|
col as c_uint,
|
||||||
scope,
|
scope,
|
||||||
ptr::null_mut());
|
ptr::null_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnknownLocation => {
|
UnknownLocation => {
|
||||||
debug!("clearing debug location ");
|
debug!("clearing debug location ");
|
||||||
metadata_node = ptr::null_mut();
|
ptr::null_mut()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
if builder.is_none() {
|
||||||
llvm::LLVMSetCurrentDebugLocation(cx.raw_builder(), metadata_node);
|
debug_context(cx).current_debug_location.set(debug_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_context(cx).current_debug_location.set(debug_location);
|
let builder = builder.unwrap_or_else(|| cx.raw_builder());
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMSetCurrentDebugLocation(builder, metadata_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// Utility Functions.
|
// Utility Functions.
|
||||||
|
|
||||||
use super::{FunctionDebugContext, CrateDebugContext};
|
use super::{FunctionDebugContext, CrateDebugContext};
|
||||||
use super::namespace::namespace_for_item;
|
use super::namespace::item_namespace;
|
||||||
|
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
|
||||||
@ -44,16 +44,6 @@ pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
|
|
||||||
attributes.iter().any(|attr| {
|
|
||||||
let meta_item: &ast::MetaItem = &attr.node.value;
|
|
||||||
match meta_item.node {
|
|
||||||
ast::MetaItemKind::Word(ref value) => &value[..] == "no_debug",
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return codemap::Loc corresponding to the beginning of the span
|
/// Return codemap::Loc corresponding to the beginning of the span
|
||||||
pub fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
|
pub fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
|
||||||
cx.sess().codemap().lookup_char_pos(span.lo)
|
cx.sess().codemap().lookup_char_pos(span.lo)
|
||||||
@ -87,21 +77,19 @@ pub fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_type_for_node_id(cx: &CrateContext,
|
|
||||||
node_id: ast::NodeId,
|
|
||||||
error_reporting_span: Span) {
|
|
||||||
if !cx.tcx().node_types().contains_key(&node_id) {
|
|
||||||
span_bug!(error_reporting_span,
|
|
||||||
"debuginfo: Could not find type for node id!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
|
pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
|
||||||
-> (DIScope, Span) {
|
-> (DIScope, Span) {
|
||||||
let containing_scope = namespace_for_item(cx, def_id).scope;
|
let containing_scope = item_namespace(cx, DefId {
|
||||||
let definition_span = cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP /* (1) */ );
|
krate: def_id.krate,
|
||||||
|
index: cx.tcx().def_key(def_id).parent
|
||||||
|
.expect("get_namespace_and_span_for_item: missing parent?")
|
||||||
|
});
|
||||||
|
|
||||||
// (1) For external items there is no span information
|
// Try to get some span information, if we have an inlined item.
|
||||||
|
let definition_span = match cx.external().borrow().get(&def_id) {
|
||||||
|
Some(&Some(node_id)) => cx.tcx().map.span(node_id),
|
||||||
|
_ => cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP)
|
||||||
|
};
|
||||||
|
|
||||||
(containing_scope, definition_span)
|
(containing_scope, definition_span)
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
-> Block<'blk, 'tcx> {
|
-> Block<'blk, 'tcx> {
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
|
|
||||||
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
|
expr.debug_loc().apply(bcx.fcx);
|
||||||
|
|
||||||
if adjustment_required(bcx, expr) {
|
if adjustment_required(bcx, expr) {
|
||||||
// use trans, which may be less efficient but
|
// use trans, which may be less efficient but
|
||||||
@ -587,7 +587,7 @@ fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
debug!("trans_unadjusted(expr={:?})", expr);
|
debug!("trans_unadjusted(expr={:?})", expr);
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
|
expr.debug_loc().apply(bcx.fcx);
|
||||||
|
|
||||||
return match expr_kind(bcx.tcx(), expr) {
|
return match expr_kind(bcx.tcx(), expr) {
|
||||||
ExprKind::Lvalue | ExprKind::RvalueDatum => {
|
ExprKind::Lvalue | ExprKind::RvalueDatum => {
|
||||||
@ -923,7 +923,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
|
expr.debug_loc().apply(bcx.fcx);
|
||||||
|
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprBreak(label_opt) => {
|
hir::ExprBreak(label_opt) => {
|
||||||
@ -987,7 +987,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
//
|
//
|
||||||
// We could avoid this intermediary with some analysis
|
// We could avoid this intermediary with some analysis
|
||||||
// to determine whether `dst` may possibly own `src`.
|
// to determine whether `dst` may possibly own `src`.
|
||||||
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
|
expr.debug_loc().apply(bcx.fcx);
|
||||||
let src_datum = unpack_datum!(
|
let src_datum = unpack_datum!(
|
||||||
bcx, src_datum.to_rvalue_datum(bcx, "ExprAssign"));
|
bcx, src_datum.to_rvalue_datum(bcx, "ExprAssign"));
|
||||||
let opt_hint_datum = dst_datum.kind.drop_flag_info.hint_datum(bcx);
|
let opt_hint_datum = dst_datum.kind.drop_flag_info.hint_datum(bcx);
|
||||||
@ -1062,7 +1062,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
|
let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
|
|
||||||
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
|
expr.debug_loc().apply(bcx.fcx);
|
||||||
|
|
||||||
// Entry into the method table if this is an overloaded call/op.
|
// Entry into the method table if this is an overloaded call/op.
|
||||||
let method_call = MethodCall::expr(expr.id);
|
let method_call = MethodCall::expr(expr.id);
|
||||||
|
@ -272,10 +272,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
|
|
||||||
let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
|
let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
|
||||||
|
|
||||||
let empty_substs = ccx.tcx().mk_substs(Substs::empty());
|
|
||||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
arena = TypedArena::new();
|
arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &arena);
|
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &arena);
|
||||||
|
|
||||||
let bcx = fcx.init(false, None);
|
let bcx = fcx.init(false, None);
|
||||||
|
|
||||||
|
@ -195,8 +195,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||||||
let name = tcx.item_name(def_id).as_str();
|
let name = tcx.item_name(def_id).as_str();
|
||||||
|
|
||||||
let span = match call_debug_location {
|
let span = match call_debug_location {
|
||||||
DebugLoc::At(_, span) => span,
|
DebugLoc::At(_, span) | DebugLoc::ScopeAt(_, span) => span,
|
||||||
DebugLoc::None => fcx.span.unwrap_or(DUMMY_SP)
|
DebugLoc::None => {
|
||||||
|
span_bug!(fcx.span.unwrap_or(DUMMY_SP),
|
||||||
|
"intrinsic `{}` called with missing span", name);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let cleanup_scope = fcx.push_custom_cleanup_scope();
|
let cleanup_scope = fcx.push_custom_cleanup_scope();
|
||||||
@ -1319,10 +1322,9 @@ fn gen_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
|
|||||||
sig: ty::Binder(sig)
|
sig: ty::Binder(sig)
|
||||||
});
|
});
|
||||||
let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty);
|
let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty);
|
||||||
let empty_substs = ccx.tcx().mk_substs(Substs::empty());
|
|
||||||
let (fcx, block_arena);
|
let (fcx, block_arena);
|
||||||
block_arena = TypedArena::new();
|
block_arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
|
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena);
|
||||||
let bcx = fcx.init(true, None);
|
let bcx = fcx.init(true, None);
|
||||||
trans(bcx);
|
trans(bcx);
|
||||||
fcx.cleanup();
|
fcx.cleanup();
|
||||||
|
@ -93,10 +93,9 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
|
|||||||
symbol_names::internal_name_from_type_and_suffix(ccx, method_ty, "object_shim");
|
symbol_names::internal_name_from_type_and_suffix(ccx, method_ty, "object_shim");
|
||||||
let llfn = declare::define_internal_fn(ccx, &function_name, method_ty);
|
let llfn = declare::define_internal_fn(ccx, &function_name, method_ty);
|
||||||
|
|
||||||
let empty_substs = tcx.mk_substs(Substs::empty());
|
|
||||||
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
block_arena = TypedArena::new();
|
block_arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
|
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, &block_arena);
|
||||||
let mut bcx = fcx.init(false, None);
|
let mut bcx = fcx.init(false, None);
|
||||||
assert!(!fcx.needs_ret_allocas);
|
assert!(!fcx.needs_ret_allocas);
|
||||||
|
|
||||||
|
@ -54,9 +54,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
bcx = self.trans_statement(bcx, statement);
|
bcx = self.trans_statement(bcx, statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("trans_block: terminator: {:?}", data.terminator());
|
let terminator = data.terminator();
|
||||||
|
debug!("trans_block: terminator: {:?}", terminator);
|
||||||
|
|
||||||
match data.terminator().kind {
|
let debug_loc = DebugLoc::ScopeAt(self.scopes[terminator.scope.index()],
|
||||||
|
terminator.span);
|
||||||
|
debug_loc.apply_to_bcx(&bcx);
|
||||||
|
debug_loc.apply(bcx.fcx());
|
||||||
|
match terminator.kind {
|
||||||
mir::TerminatorKind::Resume => {
|
mir::TerminatorKind::Resume => {
|
||||||
if let Some(cleanup_pad) = cleanup_pad {
|
if let Some(cleanup_pad) = cleanup_pad {
|
||||||
bcx.cleanup_ret(cleanup_pad, None);
|
bcx.cleanup_ret(cleanup_pad, None);
|
||||||
@ -117,7 +122,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
|
|
||||||
mir::TerminatorKind::Return => {
|
mir::TerminatorKind::Return => {
|
||||||
bcx.with_block(|bcx| {
|
bcx.with_block(|bcx| {
|
||||||
self.fcx.build_return_block(bcx, DebugLoc::None);
|
self.fcx.build_return_block(bcx, debug_loc);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +149,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
self.llblock(target),
|
self.llblock(target),
|
||||||
unwind.llbb(),
|
unwind.llbb(),
|
||||||
cleanup_bundle.as_ref());
|
cleanup_bundle.as_ref());
|
||||||
self.bcx(target).at_start(|bcx| drop::drop_fill(bcx, lvalue.llval, ty));
|
self.bcx(target).at_start(|bcx| {
|
||||||
|
debug_loc.apply_to_bcx(bcx);
|
||||||
|
drop::drop_fill(bcx, lvalue.llval, ty)
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
bcx.call(drop_fn, &[llvalue], cleanup_bundle.as_ref());
|
bcx.call(drop_fn, &[llvalue], cleanup_bundle.as_ref());
|
||||||
drop::drop_fill(&bcx, lvalue.llval, ty);
|
drop::drop_fill(&bcx, lvalue.llval, ty);
|
||||||
@ -267,7 +275,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
bcx.with_block(|bcx| {
|
bcx.with_block(|bcx| {
|
||||||
trans_intrinsic_call(bcx, callee.ty, &fn_ty,
|
trans_intrinsic_call(bcx, callee.ty, &fn_ty,
|
||||||
ArgVals(llargs), dest,
|
ArgVals(llargs), dest,
|
||||||
DebugLoc::None);
|
debug_loc);
|
||||||
});
|
});
|
||||||
|
|
||||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||||
@ -311,13 +319,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
cleanup_bundle.as_ref());
|
cleanup_bundle.as_ref());
|
||||||
fn_ty.apply_attrs_callsite(invokeret);
|
fn_ty.apply_attrs_callsite(invokeret);
|
||||||
|
|
||||||
landingpad.at_start(|bcx| for op in args {
|
landingpad.at_start(|bcx| {
|
||||||
self.set_operand_dropped(bcx, op);
|
debug_loc.apply_to_bcx(bcx);
|
||||||
|
for op in args {
|
||||||
|
self.set_operand_dropped(bcx, op);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if destination.is_some() {
|
if destination.is_some() {
|
||||||
let ret_bcx = ret_bcx.build();
|
let ret_bcx = ret_bcx.build();
|
||||||
ret_bcx.at_start(|ret_bcx| {
|
ret_bcx.at_start(|ret_bcx| {
|
||||||
|
debug_loc.apply_to_bcx(ret_bcx);
|
||||||
let op = OperandRef {
|
let op = OperandRef {
|
||||||
val: OperandValue::Immediate(invokeret),
|
val: OperandValue::Immediate(invokeret),
|
||||||
ty: sig.output.unwrap()
|
ty: sig.output.unwrap()
|
||||||
@ -514,7 +526,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
let use_funclets = base::wants_msvc_seh(bcx.sess()) && data.is_cleanup;
|
let use_funclets = base::wants_msvc_seh(bcx.sess()) && data.is_cleanup;
|
||||||
let cleanup_pad = if use_funclets {
|
let cleanup_pad = if use_funclets {
|
||||||
bcx.set_personality_fn(self.fcx.eh_personality());
|
bcx.set_personality_fn(self.fcx.eh_personality());
|
||||||
bcx.at_start(|bcx| Some(bcx.cleanup_pad(None, &[])))
|
bcx.at_start(|bcx| {
|
||||||
|
DebugLoc::None.apply_to_bcx(bcx);
|
||||||
|
Some(bcx.cleanup_pad(None, &[]))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -10,11 +10,19 @@
|
|||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use llvm::{self, ValueRef};
|
use llvm::{self, ValueRef};
|
||||||
|
use llvm::debuginfo::DIScope;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::mir::repr as mir;
|
use rustc::mir::repr as mir;
|
||||||
use rustc::mir::tcx::LvalueTy;
|
use rustc::mir::tcx::LvalueTy;
|
||||||
|
use session::config::FullDebugInfo;
|
||||||
use base;
|
use base;
|
||||||
use common::{self, Block, BlockAndBuilder, FunctionContext};
|
use common::{self, Block, BlockAndBuilder, FunctionContext};
|
||||||
|
use debuginfo::{self, declare_local, DebugLoc, VariableAccess, VariableKind};
|
||||||
|
use machine;
|
||||||
|
use type_of;
|
||||||
|
|
||||||
|
use syntax::codemap::DUMMY_SP;
|
||||||
|
use syntax::parse::token;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -44,8 +52,6 @@ impl<'mir, 'tcx: 'mir> Deref for CachedMir<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME DebugLoc is always None right now
|
|
||||||
|
|
||||||
/// Master context for translating MIR.
|
/// Master context for translating MIR.
|
||||||
pub struct MirContext<'bcx, 'tcx:'bcx> {
|
pub struct MirContext<'bcx, 'tcx:'bcx> {
|
||||||
mir: CachedMir<'bcx, 'tcx>,
|
mir: CachedMir<'bcx, 'tcx>,
|
||||||
@ -92,6 +98,9 @@ pub struct MirContext<'bcx, 'tcx:'bcx> {
|
|||||||
/// always indirect, though we try to avoid creating an alloca
|
/// always indirect, though we try to avoid creating an alloca
|
||||||
/// when we can (and just reuse the pointer the caller provided).
|
/// when we can (and just reuse the pointer the caller provided).
|
||||||
args: Vec<LvalueRef<'tcx>>,
|
args: Vec<LvalueRef<'tcx>>,
|
||||||
|
|
||||||
|
/// Debug information for MIR scopes.
|
||||||
|
scopes: Vec<DIScope>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TempRef<'tcx> {
|
enum TempRef<'tcx> {
|
||||||
@ -113,11 +122,26 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
|
|||||||
analyze::lvalue_temps(bcx, &mir)
|
analyze::lvalue_temps(bcx, &mir)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Compute debuginfo scopes from MIR scopes.
|
||||||
|
let scopes = debuginfo::create_mir_scopes(fcx);
|
||||||
|
|
||||||
// Allocate variable and temp allocas
|
// Allocate variable and temp allocas
|
||||||
let vars = mir.var_decls.iter()
|
let vars = mir.var_decls.iter()
|
||||||
.map(|decl| (bcx.monomorphize(&decl.ty), decl.name))
|
.map(|decl| (bcx.monomorphize(&decl.ty), decl))
|
||||||
.map(|(mty, name)| LvalueRef::alloca(&bcx, mty, &name.as_str()))
|
.map(|(mty, decl)| {
|
||||||
.collect();
|
let lvalue = LvalueRef::alloca(&bcx, mty, &decl.name.as_str());
|
||||||
|
|
||||||
|
let scope = scopes[decl.scope.index()];
|
||||||
|
if !scope.is_null() && bcx.sess().opts.debuginfo == FullDebugInfo {
|
||||||
|
bcx.with_block(|bcx| {
|
||||||
|
declare_local(bcx, decl.name, mty, scope,
|
||||||
|
VariableAccess::DirectVariable { alloca: lvalue.llval },
|
||||||
|
VariableKind::LocalVariable, decl.span);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
lvalue
|
||||||
|
}).collect();
|
||||||
let temps = mir.temp_decls.iter()
|
let temps = mir.temp_decls.iter()
|
||||||
.map(|decl| bcx.monomorphize(&decl.ty))
|
.map(|decl| bcx.monomorphize(&decl.ty))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -132,7 +156,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
|
|||||||
TempRef::Operand(None)
|
TempRef::Operand(None)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let args = arg_value_refs(&bcx, &mir);
|
let args = arg_value_refs(&bcx, &mir, &scopes);
|
||||||
|
|
||||||
// Allocate a `Block` for every basic block
|
// Allocate a `Block` for every basic block
|
||||||
let block_bcxs: Vec<Block<'blk,'tcx>> =
|
let block_bcxs: Vec<Block<'blk,'tcx>> =
|
||||||
@ -152,6 +176,11 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
|
|||||||
let start_bcx = block_bcxs[mir::START_BLOCK.index()];
|
let start_bcx = block_bcxs[mir::START_BLOCK.index()];
|
||||||
bcx.br(start_bcx.llbb);
|
bcx.br(start_bcx.llbb);
|
||||||
|
|
||||||
|
// Up until here, IR instructions for this function have explicitly not been annotated with
|
||||||
|
// source code location, so we don't step into call setup code. From here on, source location
|
||||||
|
// emitting should be enabled.
|
||||||
|
debuginfo::start_emitting_source_locations(fcx);
|
||||||
|
|
||||||
let mut mircx = MirContext {
|
let mut mircx = MirContext {
|
||||||
mir: mir.clone(),
|
mir: mir.clone(),
|
||||||
fcx: fcx,
|
fcx: fcx,
|
||||||
@ -161,6 +190,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
|
|||||||
vars: vars,
|
vars: vars,
|
||||||
temps: temps,
|
temps: temps,
|
||||||
args: args,
|
args: args,
|
||||||
|
scopes: scopes
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut visited = BitVector::new(mir_blocks.len());
|
let mut visited = BitVector::new(mir_blocks.len());
|
||||||
@ -185,6 +215,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DebugLoc::None.apply(fcx);
|
||||||
fcx.cleanup();
|
fcx.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,12 +223,25 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
|
|||||||
/// argument's value. As arguments are lvalues, these are always
|
/// argument's value. As arguments are lvalues, these are always
|
||||||
/// indirect.
|
/// indirect.
|
||||||
fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
||||||
mir: &mir::Mir<'tcx>)
|
mir: &mir::Mir<'tcx>,
|
||||||
|
scopes: &[DIScope])
|
||||||
-> Vec<LvalueRef<'tcx>> {
|
-> Vec<LvalueRef<'tcx>> {
|
||||||
let fcx = bcx.fcx();
|
let fcx = bcx.fcx();
|
||||||
let tcx = bcx.tcx();
|
let tcx = bcx.tcx();
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
|
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
|
||||||
|
|
||||||
|
// Get the argument scope assuming ScopeId(0) has no parent.
|
||||||
|
let arg_scope = mir.scopes.get(0).and_then(|data| {
|
||||||
|
let scope = scopes[0];
|
||||||
|
if data.parent_scope.is_none() && !scope.is_null() &&
|
||||||
|
bcx.sess().opts.debuginfo == FullDebugInfo {
|
||||||
|
Some(scope)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| {
|
mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| {
|
||||||
let arg_ty = bcx.monomorphize(&arg_decl.ty);
|
let arg_ty = bcx.monomorphize(&arg_decl.ty);
|
||||||
if arg_decl.spread {
|
if arg_decl.spread {
|
||||||
@ -211,13 +255,14 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
|||||||
_ => bug!("spread argument isn't a tuple?!")
|
_ => bug!("spread argument isn't a tuple?!")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
|
||||||
let lltemp = bcx.with_block(|bcx| {
|
let lltemp = bcx.with_block(|bcx| {
|
||||||
base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
|
base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
|
||||||
});
|
});
|
||||||
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
|
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() {
|
||||||
let dst = bcx.struct_gep(lltemp, i);
|
let dst = bcx.struct_gep(lltemp, i);
|
||||||
let arg = &fcx.fn_ty.args[idx];
|
let arg = &fcx.fn_ty.args[idx];
|
||||||
idx += 1;
|
idx += 1;
|
||||||
if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
|
if common::type_is_fat_ptr(tcx, tupled_arg_ty) {
|
||||||
// We pass fat pointers as two words, but inside the tuple
|
// We pass fat pointers as two words, but inside the tuple
|
||||||
// they are the two sub-fields of a single aggregate field.
|
// they are the two sub-fields of a single aggregate field.
|
||||||
@ -228,17 +273,37 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
|||||||
} else {
|
} else {
|
||||||
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
|
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bcx.with_block(|bcx| arg_scope.map(|scope| {
|
||||||
|
let byte_offset_of_var_in_tuple =
|
||||||
|
machine::llelement_offset(bcx.ccx(), lltuplety, i);
|
||||||
|
|
||||||
|
let address_operations = unsafe {
|
||||||
|
[llvm::LLVMDIBuilderCreateOpDeref(),
|
||||||
|
llvm::LLVMDIBuilderCreateOpPlus(),
|
||||||
|
byte_offset_of_var_in_tuple as i64]
|
||||||
|
};
|
||||||
|
|
||||||
|
let variable_access = VariableAccess::IndirectVariable {
|
||||||
|
alloca: lltemp,
|
||||||
|
address_operations: &address_operations
|
||||||
|
};
|
||||||
|
declare_local(bcx, token::special_idents::invalid.name,
|
||||||
|
tupled_arg_ty, scope, variable_access,
|
||||||
|
VariableKind::ArgumentVariable(arg_index + i + 1),
|
||||||
|
bcx.fcx().span.unwrap_or(DUMMY_SP));
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty));
|
return LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg = &fcx.fn_ty.args[idx];
|
let arg = &fcx.fn_ty.args[idx];
|
||||||
idx += 1;
|
idx += 1;
|
||||||
let llval = if arg.is_indirect() {
|
let llval = if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo {
|
||||||
// Don't copy an indirect argument to an alloca, the caller
|
// Don't copy an indirect argument to an alloca, the caller
|
||||||
// already put it in a temporary alloca and gave it up, unless
|
// already put it in a temporary alloca and gave it up, unless
|
||||||
// we emit extra-debug-info, which requires local allocas :(.
|
// we emit extra-debug-info, which requires local allocas :(.
|
||||||
// FIXME: lifetimes, debug info
|
// FIXME: lifetimes
|
||||||
let llarg = llvm::get_param(fcx.llfn, llarg_idx as c_uint);
|
let llarg = llvm::get_param(fcx.llfn, llarg_idx as c_uint);
|
||||||
llarg_idx += 1;
|
llarg_idx += 1;
|
||||||
llarg
|
llarg
|
||||||
@ -261,6 +326,12 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
lltemp
|
lltemp
|
||||||
};
|
};
|
||||||
|
bcx.with_block(|bcx| arg_scope.map(|scope| {
|
||||||
|
declare_local(bcx, token::special_idents::invalid.name, arg_ty, scope,
|
||||||
|
VariableAccess::DirectVariable { alloca: llval },
|
||||||
|
VariableKind::ArgumentVariable(arg_index + 1),
|
||||||
|
bcx.fcx().span.unwrap_or(DUMMY_SP));
|
||||||
|
}));
|
||||||
LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty))
|
LvalueRef::new_sized(llval, LvalueTy::from_ty(arg_ty))
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
pub fn trans_rvalue(&mut self,
|
pub fn trans_rvalue(&mut self,
|
||||||
bcx: BlockAndBuilder<'bcx, 'tcx>,
|
bcx: BlockAndBuilder<'bcx, 'tcx>,
|
||||||
dest: LvalueRef<'tcx>,
|
dest: LvalueRef<'tcx>,
|
||||||
rvalue: &mir::Rvalue<'tcx>)
|
rvalue: &mir::Rvalue<'tcx>,
|
||||||
|
debug_loc: DebugLoc)
|
||||||
-> BlockAndBuilder<'bcx, 'tcx>
|
-> BlockAndBuilder<'bcx, 'tcx>
|
||||||
{
|
{
|
||||||
debug!("trans_rvalue(dest.llval={:?}, rvalue={:?})",
|
debug!("trans_rvalue(dest.llval={:?}, rvalue={:?})",
|
||||||
@ -58,7 +59,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
|
if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
|
||||||
// into-coerce of a thin pointer to a fat pointer - just
|
// into-coerce of a thin pointer to a fat pointer - just
|
||||||
// use the operand path.
|
// use the operand path.
|
||||||
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
|
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue, debug_loc);
|
||||||
self.store_operand(&bcx, dest.llval, temp);
|
self.store_operand(&bcx, dest.llval, temp);
|
||||||
return bcx;
|
return bcx;
|
||||||
}
|
}
|
||||||
@ -217,7 +218,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
assert!(rvalue_creates_operand(rvalue));
|
assert!(rvalue_creates_operand(rvalue));
|
||||||
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
|
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue, debug_loc);
|
||||||
self.store_operand(&bcx, dest.llval, temp);
|
self.store_operand(&bcx, dest.llval, temp);
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
@ -226,7 +227,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
|
|
||||||
pub fn trans_rvalue_operand(&mut self,
|
pub fn trans_rvalue_operand(&mut self,
|
||||||
bcx: BlockAndBuilder<'bcx, 'tcx>,
|
bcx: BlockAndBuilder<'bcx, 'tcx>,
|
||||||
rvalue: &mir::Rvalue<'tcx>)
|
rvalue: &mir::Rvalue<'tcx>,
|
||||||
|
debug_loc: DebugLoc)
|
||||||
-> (BlockAndBuilder<'bcx, 'tcx>, OperandRef<'tcx>)
|
-> (BlockAndBuilder<'bcx, 'tcx>, OperandRef<'tcx>)
|
||||||
{
|
{
|
||||||
assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
|
assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
|
||||||
@ -419,7 +421,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
lhs_addr, lhs_extra,
|
lhs_addr, lhs_extra,
|
||||||
rhs_addr, rhs_extra,
|
rhs_addr, rhs_extra,
|
||||||
lhs.ty, op.to_hir_binop(),
|
lhs.ty, op.to_hir_binop(),
|
||||||
DebugLoc::None)
|
debug_loc)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => bug!()
|
_ => bug!()
|
||||||
@ -470,7 +472,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
box_ty,
|
box_ty,
|
||||||
llsize,
|
llsize,
|
||||||
llalign,
|
llalign,
|
||||||
DebugLoc::None);
|
debug_loc);
|
||||||
llval = Some(val);
|
llval = Some(val);
|
||||||
bcx
|
bcx
|
||||||
});
|
});
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
use rustc::mir::repr as mir;
|
use rustc::mir::repr as mir;
|
||||||
use common::BlockAndBuilder;
|
use common::BlockAndBuilder;
|
||||||
|
use debuginfo::DebugLoc;
|
||||||
|
|
||||||
use super::MirContext;
|
use super::MirContext;
|
||||||
use super::TempRef;
|
use super::TempRef;
|
||||||
@ -21,6 +22,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
-> BlockAndBuilder<'bcx, 'tcx> {
|
-> BlockAndBuilder<'bcx, 'tcx> {
|
||||||
debug!("trans_statement(statement={:?})", statement);
|
debug!("trans_statement(statement={:?})", statement);
|
||||||
|
|
||||||
|
let debug_loc = DebugLoc::ScopeAt(self.scopes[statement.scope.index()],
|
||||||
|
statement.span);
|
||||||
|
debug_loc.apply_to_bcx(&bcx);
|
||||||
|
debug_loc.apply(bcx.fcx());
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
||||||
match *lvalue {
|
match *lvalue {
|
||||||
@ -28,10 +33,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
match self.temps[index as usize] {
|
match self.temps[index as usize] {
|
||||||
TempRef::Lvalue(tr_dest) => {
|
TempRef::Lvalue(tr_dest) => {
|
||||||
self.trans_rvalue(bcx, tr_dest, rvalue)
|
self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc)
|
||||||
}
|
}
|
||||||
TempRef::Operand(None) => {
|
TempRef::Operand(None) => {
|
||||||
let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
|
let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue,
|
||||||
|
debug_loc);
|
||||||
self.temps[index] = TempRef::Operand(Some(operand));
|
self.temps[index] = TempRef::Operand(Some(operand));
|
||||||
bcx
|
bcx
|
||||||
}
|
}
|
||||||
@ -44,7 +50,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let tr_dest = self.trans_lvalue(&bcx, lvalue);
|
let tr_dest = self.trans_lvalue(&bcx, lvalue);
|
||||||
self.trans_rvalue(bcx, tr_dest, rvalue)
|
self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(repr_simd, platform_intrinsics, rustc_attrs, core_intrinsics)]
|
#![feature(repr_simd, platform_intrinsics, core_intrinsics)]
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
// Bad monomorphizations could previously cause LLVM asserts even though the
|
// Bad monomorphizations could previously cause LLVM asserts even though the
|
||||||
@ -23,19 +23,16 @@ use std::intrinsics;
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Foo(i64);
|
struct Foo(i64);
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_cttz(v: Foo) -> Foo {
|
unsafe fn test_cttz(v: Foo) -> Foo {
|
||||||
intrinsics::cttz(v)
|
intrinsics::cttz(v)
|
||||||
//~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
|
//~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
|
unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
|
||||||
intrinsics::fadd_fast(a, b)
|
intrinsics::fadd_fast(a, b)
|
||||||
//~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo`
|
//~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
|
unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
|
||||||
simd_add(a, b)
|
simd_add(a, b)
|
||||||
//~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
|
//~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(core_intrinsics, rustc_attrs)]
|
#![feature(core_intrinsics)]
|
||||||
#![allow(warnings)]
|
#![allow(warnings)]
|
||||||
|
|
||||||
use std::intrinsics;
|
use std::intrinsics;
|
||||||
@ -18,97 +18,81 @@ struct Foo(i64);
|
|||||||
type Bar = &'static Fn();
|
type Bar = &'static Fn();
|
||||||
type Quux = [u8; 100];
|
type Quux = [u8; 100];
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_bool_load(p: &mut bool, v: bool) {
|
unsafe fn test_bool_load(p: &mut bool, v: bool) {
|
||||||
intrinsics::atomic_load(p);
|
intrinsics::atomic_load(p);
|
||||||
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
|
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_bool_store(p: &mut bool, v: bool) {
|
unsafe fn test_bool_store(p: &mut bool, v: bool) {
|
||||||
intrinsics::atomic_store(p, v);
|
intrinsics::atomic_store(p, v);
|
||||||
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
|
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
|
unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
|
||||||
intrinsics::atomic_xchg(p, v);
|
intrinsics::atomic_xchg(p, v);
|
||||||
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
|
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
|
unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
|
||||||
intrinsics::atomic_cxchg(p, v, v);
|
intrinsics::atomic_cxchg(p, v, v);
|
||||||
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
|
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
|
unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
|
||||||
intrinsics::atomic_load(p);
|
intrinsics::atomic_load(p);
|
||||||
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
|
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
|
unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
|
||||||
intrinsics::atomic_store(p, v);
|
intrinsics::atomic_store(p, v);
|
||||||
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
|
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
|
unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
|
||||||
intrinsics::atomic_xchg(p, v);
|
intrinsics::atomic_xchg(p, v);
|
||||||
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
|
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
|
unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
|
||||||
intrinsics::atomic_cxchg(p, v, v);
|
intrinsics::atomic_cxchg(p, v, v);
|
||||||
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
|
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
|
unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
|
||||||
intrinsics::atomic_load(p);
|
intrinsics::atomic_load(p);
|
||||||
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
|
unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
|
||||||
intrinsics::atomic_store(p, v);
|
intrinsics::atomic_store(p, v);
|
||||||
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
|
unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
|
||||||
intrinsics::atomic_xchg(p, v);
|
intrinsics::atomic_xchg(p, v);
|
||||||
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
|
unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
|
||||||
intrinsics::atomic_cxchg(p, v, v);
|
intrinsics::atomic_cxchg(p, v, v);
|
||||||
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
|
unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
|
||||||
intrinsics::atomic_load(p);
|
intrinsics::atomic_load(p);
|
||||||
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
|
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
|
unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
|
||||||
intrinsics::atomic_store(p, v);
|
intrinsics::atomic_store(p, v);
|
||||||
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
|
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
|
unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
|
||||||
intrinsics::atomic_xchg(p, v);
|
intrinsics::atomic_xchg(p, v);
|
||||||
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
|
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
|
unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
|
||||||
intrinsics::atomic_cxchg(p, v, v);
|
intrinsics::atomic_cxchg(p, v, v);
|
||||||
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
|
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(repr_simd, platform_intrinsics, rustc_attrs)]
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -34,7 +34,6 @@ extern "platform-intrinsic" {
|
|||||||
fn simd_xor<T>(x: T, y: T) -> T;
|
fn simd_xor<T>(x: T, y: T) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = i32x4(0, 0, 0, 0);
|
let x = i32x4(0, 0, 0, 0);
|
||||||
let y = u32x4(0, 0, 0, 0);
|
let y = u32x4(0, 0, 0, 0);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(repr_simd, platform_intrinsics, rustc_attrs)]
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -35,7 +35,6 @@ extern "platform-intrinsic" {
|
|||||||
fn simd_cast<T, U>(x: T) -> U;
|
fn simd_cast<T, U>(x: T) -> U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = i32x4(0, 0, 0, 0);
|
let x = i32x4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(repr_simd, platform_intrinsics, rustc_attrs)]
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -29,7 +29,6 @@ extern "platform-intrinsic" {
|
|||||||
fn simd_ge<T, U>(x: T, y: T) -> U;
|
fn simd_ge<T, U>(x: T, y: T) -> U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = i32x4(0, 0, 0, 0);
|
let x = i32x4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ extern "platform-intrinsic" {
|
|||||||
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
|
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = i32x4(0, 0, 0, 0);
|
let x = i32x4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![feature(omit_gdb_pretty_printer_section)]
|
#![feature(omit_gdb_pretty_printer_section, rustc_attrs)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
trait TraitWithAssocType {
|
trait TraitWithAssocType {
|
||||||
@ -127,6 +127,7 @@ fn assoc_tuple<T: TraitWithAssocType>(arg: (T, T::Type)) {
|
|||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_no_mir] // FIXME(#32790) MIR reuses scopes for match arms.
|
||||||
fn assoc_enum<T: TraitWithAssocType>(arg: Enum<T>) {
|
fn assoc_enum<T: TraitWithAssocType>(arg: Enum<T>) {
|
||||||
|
|
||||||
match arg {
|
match arg {
|
||||||
|
@ -157,7 +157,8 @@ fn main() {
|
|||||||
|
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
|
|
||||||
let a = SINGLE_VARIANT;
|
// Borrow to avoid an eager load of the constant value in the static.
|
||||||
|
let a = &SINGLE_VARIANT;
|
||||||
let a = unsafe { AUTO_ONE };
|
let a = unsafe { AUTO_ONE };
|
||||||
let a = unsafe { MANUAL_ONE };
|
let a = unsafe { MANUAL_ONE };
|
||||||
}
|
}
|
||||||
|
@ -247,10 +247,11 @@
|
|||||||
// lldb-command:continue
|
// lldb-command:continue
|
||||||
|
|
||||||
#![allow(dead_code, unused_assignments, unused_variables)]
|
#![allow(dead_code, unused_assignments, unused_variables)]
|
||||||
#![feature(omit_gdb_pretty_printer_section)]
|
#![feature(omit_gdb_pretty_printer_section, rustc_attrs)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn immediate_args(a: isize, b: bool, c: f64) {
|
fn immediate_args(a: isize, b: bool, c: f64) {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
@ -267,43 +268,51 @@ struct BigStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn non_immediate_args(a: BigStruct, b: BigStruct) {
|
fn non_immediate_args(a: BigStruct, b: BigStruct) {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn binding(a: i64, b: u64, c: f64) {
|
fn binding(a: i64, b: u64, c: f64) {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn assignment(mut a: u64, b: u64, c: f64) {
|
fn assignment(mut a: u64, b: u64, c: f64) {
|
||||||
a = b;
|
a = b;
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn function_call(x: u64, y: u64, z: f64) {
|
fn function_call(x: u64, y: u64, z: f64) {
|
||||||
println!("Hi!")
|
println!("Hi!")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn identifier(x: u64, y: u64, z: f64) -> u64 {
|
fn identifier(x: u64, y: u64, z: f64) -> u64 {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn return_expr(x: u64, y: u64, z: f64) -> u64 {
|
fn return_expr(x: u64, y: u64, z: f64) -> u64 {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
|
fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
|
||||||
x + y
|
x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn if_expr(x: u64, y: u64, z: f64) -> u64 {
|
fn if_expr(x: u64, y: u64, z: f64) -> u64 {
|
||||||
if x + y < 1000 {
|
if x + y < 1000 {
|
||||||
x
|
x
|
||||||
@ -313,6 +322,7 @@ fn if_expr(x: u64, y: u64, z: f64) -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
|
fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
|
||||||
while x + y < 1000 {
|
while x + y < 1000 {
|
||||||
x += z
|
x += z
|
||||||
@ -321,6 +331,7 @@ fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_stack_check]
|
#[no_stack_check]
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing argument names.
|
||||||
fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
|
fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
|
||||||
loop {
|
loop {
|
||||||
x += z;
|
x += z;
|
||||||
|
@ -23,10 +23,11 @@
|
|||||||
// gdb-command:continue
|
// gdb-command:continue
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![feature(no_debug)]
|
#![feature(no_debug, rustc_attrs)]
|
||||||
#![feature(omit_gdb_pretty_printer_section)]
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is inaccurate for returns.
|
||||||
fn function_with_debuginfo() {
|
fn function_with_debuginfo() {
|
||||||
let abc = 10_usize;
|
let abc = 10_usize;
|
||||||
return (); // #break
|
return (); // #break
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
// lldb-command:continue
|
// lldb-command:continue
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax, rustc_attrs, stmt_expr_attributes)]
|
||||||
#![feature(omit_gdb_pretty_printer_section)]
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
@ -88,6 +88,7 @@ struct Struct {
|
|||||||
c: usize
|
c: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut variable = 1;
|
let mut variable = 1;
|
||||||
let constant = 2;
|
let constant = 2;
|
||||||
@ -101,10 +102,14 @@ fn main() {
|
|||||||
let struct_ref = &a_struct;
|
let struct_ref = &a_struct;
|
||||||
let owned: Box<_> = box 6;
|
let owned: Box<_> = box 6;
|
||||||
|
|
||||||
let mut closure = || {
|
let mut closure =
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
|
|| {
|
||||||
let closure_local = 8;
|
let closure_local = 8;
|
||||||
|
|
||||||
let mut nested_closure = || {
|
let mut nested_closure =
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
|
|| {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
variable = constant + a_struct.a + struct_ref.a + *owned + closure_local;
|
variable = constant + a_struct.a + struct_ref.a + *owned + closure_local;
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
// lldb-check:[...]$2 = 5
|
// lldb-check:[...]$2 = 5
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![feature(unboxed_closures, box_syntax)]
|
#![feature(unboxed_closures, box_syntax, rustc_attrs, stmt_expr_attributes)]
|
||||||
#![feature(omit_gdb_pretty_printer_section)]
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ struct Struct {
|
|||||||
c: usize
|
c: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
fn main() {
|
fn main() {
|
||||||
let constant = 1;
|
let constant = 1;
|
||||||
|
|
||||||
@ -61,7 +62,9 @@ fn main() {
|
|||||||
|
|
||||||
let owned: Box<_> = box 5;
|
let owned: Box<_> = box 5;
|
||||||
|
|
||||||
let closure = move || {
|
let closure =
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
|
move || {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
do_something(&constant, &a_struct.a, &*owned);
|
do_something(&constant, &a_struct.a, &*owned);
|
||||||
};
|
};
|
||||||
@ -73,7 +76,9 @@ fn main() {
|
|||||||
// The `self` argument of the following closure should be passed by value
|
// The `self` argument of the following closure should be passed by value
|
||||||
// to FnOnce::call_once(self, args), which gets translated a bit differently
|
// to FnOnce::call_once(self, args), which gets translated a bit differently
|
||||||
// than the regular case. Let's make sure this is supported too.
|
// than the regular case. Let's make sure this is supported too.
|
||||||
let immedate_env = move || {
|
let immedate_env =
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
|
move || {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
return constant2;
|
return constant2;
|
||||||
};
|
};
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
// lldb-command:print *owned
|
// lldb-command:print *owned
|
||||||
// lldb-check:[...]$9 = 6
|
// lldb-check:[...]$9 = 6
|
||||||
|
|
||||||
#![feature(unboxed_closures, box_syntax)]
|
#![feature(unboxed_closures, box_syntax, rustc_attrs, stmt_expr_attributes)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![feature(omit_gdb_pretty_printer_section)]
|
#![feature(omit_gdb_pretty_printer_section)]
|
||||||
#![omit_gdb_pretty_printer_section]
|
#![omit_gdb_pretty_printer_section]
|
||||||
@ -80,6 +80,7 @@ struct Struct {
|
|||||||
c: usize
|
c: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut variable = 1;
|
let mut variable = 1;
|
||||||
let constant = 2;
|
let constant = 2;
|
||||||
@ -94,7 +95,9 @@ fn main() {
|
|||||||
let owned: Box<_> = box 6;
|
let owned: Box<_> = box 6;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut first_closure = || {
|
let mut first_closure =
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
|
|| {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
variable = constant + a_struct.a + struct_ref.a + *owned;
|
variable = constant + a_struct.a + struct_ref.a + *owned;
|
||||||
};
|
};
|
||||||
@ -103,7 +106,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut second_closure = || {
|
let mut second_closure =
|
||||||
|
#[rustc_no_mir] // FIXME(#31005) MIR debuginfo is missing captures.
|
||||||
|
|| {
|
||||||
zzz(); // #break
|
zzz(); // #break
|
||||||
variable = constant + a_struct.a + struct_ref.a + *owned;
|
variable = constant + a_struct.a + struct_ref.a + *owned;
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
// ignore-test: not a test, used by backtrace-debuginfo.rs to test file!()
|
// ignore-test: not a test, used by backtrace-debuginfo.rs to test file!()
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
pub fn callback<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
pub fn callback<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
||||||
f((file!(), line!()))
|
f((file!(), line!()))
|
||||||
}
|
}
|
||||||
@ -21,7 +20,6 @@ pub fn callback<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
|||||||
// this case.
|
// this case.
|
||||||
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
||||||
#[cfg_attr(target_env = "msvc", inline(never))]
|
#[cfg_attr(target_env = "msvc", inline(never))]
|
||||||
#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
pub fn callback_inlined<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
pub fn callback_inlined<F>(f: F) where F: FnOnce((&'static str, u32)) {
|
||||||
f((file!(), line!()))
|
f((file!(), line!()))
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
|
||||||
|
|
||||||
// We disable tail merging here because it can't preserve debuginfo and thus
|
// We disable tail merging here because it can't preserve debuginfo and thus
|
||||||
// potentially breaks the backtraces. Also, subtle changes can decide whether
|
// potentially breaks the backtraces. Also, subtle changes can decide whether
|
||||||
// tail merging suceeds, so the test might work today but fail tomorrow due to a
|
// tail merging suceeds, so the test might work today but fail tomorrow due to a
|
||||||
@ -74,7 +72,6 @@ fn dump_filelines(filelines: &[Pos]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
||||||
check!(counter; main_pos, outer_pos);
|
check!(counter; main_pos, outer_pos);
|
||||||
check!(counter; main_pos, outer_pos);
|
check!(counter; main_pos, outer_pos);
|
||||||
@ -91,7 +88,6 @@ fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
|||||||
// this case.
|
// this case.
|
||||||
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
#[cfg_attr(not(target_env = "msvc"), inline(always))]
|
||||||
#[cfg_attr(target_env = "msvc", inline(never))]
|
#[cfg_attr(target_env = "msvc", inline(never))]
|
||||||
#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
||||||
check!(counter; main_pos, outer_pos);
|
check!(counter; main_pos, outer_pos);
|
||||||
check!(counter; main_pos, outer_pos);
|
check!(counter; main_pos, outer_pos);
|
||||||
@ -117,7 +113,6 @@ fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
fn outer(mut counter: i32, main_pos: Pos) {
|
fn outer(mut counter: i32, main_pos: Pos) {
|
||||||
inner(&mut counter, main_pos, pos!());
|
inner(&mut counter, main_pos, pos!());
|
||||||
inner_inlined(&mut counter, main_pos, pos!());
|
inner_inlined(&mut counter, main_pos, pos!());
|
||||||
@ -162,7 +157,6 @@ fn run_test(me: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[rustc_no_mir] // FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() >= 2 {
|
if args.len() >= 2 {
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
|
||||||
|
|
||||||
// no-pretty-expanded FIXME #15189
|
// no-pretty-expanded FIXME #15189
|
||||||
// ignore-android FIXME #17520
|
// ignore-android FIXME #17520
|
||||||
// compile-flags:-g
|
// compile-flags:-g
|
||||||
@ -18,8 +16,6 @@ use std::env;
|
|||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
// FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
#[cfg_attr(target_env = "msvc", rustc_no_mir)]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn foo() {
|
fn foo() {
|
||||||
let _v = vec![1, 2, 3];
|
let _v = vec![1, 2, 3];
|
||||||
@ -28,8 +24,6 @@ fn foo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME #31005 MIR missing debuginfo currently.
|
|
||||||
#[cfg_attr(target_env = "msvc", rustc_no_mir)]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn double() {
|
fn double() {
|
||||||
struct Double;
|
struct Double;
|
||||||
|
Loading…
Reference in New Issue
Block a user