Skip to content

Commit 302486e

Browse files
debuginfo: Make sure that all calls to drop glue are associated with debug locations.
This commit makes rustc emit debug locations for all call and invoke statements in LLVM IR, if they are contained within a function that debuginfo is enabled for. This is important because LLVM does not handle the case where a function body containing debuginfo is inlined into another function with debuginfo, but the inlined call statement does not have a debug location. In this case, LLVM will not know where (in terms of source code coordinates) the function was inlined to and we end up with some statements still linked to the source locations in there original, non-inlined function without any indication that they are indeed an inline-copy. Later, when generating DWARF from the IR, LLVM will interpret this as corrupt IR and abort. Unfortunately, the undesirable case described above can still occur when using LTO. If there is a crate compiled without debuginfo calling into a crate compiled with debuginfo, we again end up with the conditions triggering the error. This is why some LTO tests still fail with the dreaded assertion, if the standard library was built with debuginfo enabled. That is, `RUSTFLAGS_STAGE2=-g make rustc-stage2` will succeed but `RUSTFLAGS_STAGE2=-g make check` will still fail after this commit has been merged. This is a problem that has to be dealt with separately. Fixes #17201 Fixes #15816 Fixes #15156
1 parent d299baf commit 302486e

File tree

10 files changed

+284
-73
lines changed

10 files changed

+284
-73
lines changed

src/librustc/middle/trans/base.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -1791,7 +1791,7 @@ pub fn trans_closure(ccx: &CrateContext,
17911791
body: &ast::Block,
17921792
llfndecl: ValueRef,
17931793
param_substs: &param_substs,
1794-
id: ast::NodeId,
1794+
fn_ast_id: ast::NodeId,
17951795
_attributes: &[ast::Attribute],
17961796
arg_types: Vec<ty::t>,
17971797
output_type: ty::t,
@@ -1811,7 +1811,7 @@ pub fn trans_closure(ccx: &CrateContext,
18111811
let arena = TypedArena::new();
18121812
let fcx = new_fn_ctxt(ccx,
18131813
llfndecl,
1814-
id,
1814+
fn_ast_id,
18151815
has_env,
18161816
output_type,
18171817
param_substs,
@@ -1820,7 +1820,9 @@ pub fn trans_closure(ccx: &CrateContext,
18201820
let mut bcx = init_function(&fcx, false, output_type);
18211821

18221822
// cleanup scope for the incoming arguments
1823-
let arg_scope = fcx.push_custom_cleanup_scope();
1823+
let fn_cleanup_debug_loc =
1824+
debuginfo::get_cleanup_debug_loc_for_ast_node(fn_ast_id, body.span, true);
1825+
let arg_scope = fcx.push_custom_cleanup_scope_with_debug_loc(fn_cleanup_debug_loc);
18241826

18251827
let block_ty = node_id_type(bcx, body.id);
18261828

@@ -1969,7 +1971,9 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
19691971
ctor_ty: ty::t,
19701972
disr: ty::Disr,
19711973
args: callee::CallArgs,
1972-
dest: expr::Dest) -> Result<'blk, 'tcx> {
1974+
dest: expr::Dest,
1975+
call_info: Option<NodeInfo>)
1976+
-> Result<'blk, 'tcx> {
19731977

19741978
let ccx = bcx.fcx.ccx;
19751979
let tcx = ccx.tcx();
@@ -1999,8 +2003,13 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
19992003
match args {
20002004
callee::ArgExprs(exprs) => {
20012005
let fields = exprs.iter().map(|x| &**x).enumerate().collect::<Vec<_>>();
2002-
bcx = expr::trans_adt(bcx, result_ty, disr, fields.as_slice(),
2003-
None, expr::SaveIn(llresult));
2006+
bcx = expr::trans_adt(bcx,
2007+
result_ty,
2008+
disr,
2009+
fields.as_slice(),
2010+
None,
2011+
expr::SaveIn(llresult),
2012+
call_info);
20042013
}
20052014
_ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
20062015
}
@@ -2010,7 +2019,9 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
20102019
// drop the temporary we made
20112020
let bcx = match dest {
20122021
expr::SaveIn(_) => bcx,
2013-
expr::Ignore => glue::drop_ty(bcx, llresult, result_ty)
2022+
expr::Ignore => {
2023+
glue::drop_ty(bcx, llresult, result_ty, call_info)
2024+
}
20142025
};
20152026

20162027
Result::new(bcx, llresult)

src/librustc/middle/trans/callee.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,12 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
714714
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
715715

716716
let ctor_ty = callee_ty.subst(bcx.tcx(), &substs);
717-
return base::trans_named_tuple_constructor(bcx, ctor_ty, disr,
718-
args, dest.unwrap());
717+
return base::trans_named_tuple_constructor(bcx,
718+
ctor_ty,
719+
disr,
720+
args,
721+
dest.unwrap(),
722+
call_info);
719723
}
720724
};
721725

@@ -835,7 +839,7 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
835839
match (dest, opt_llretslot) {
836840
(Some(expr::Ignore), Some(llretslot)) => {
837841
// drop the value if it is not being saved.
838-
bcx = glue::drop_ty(bcx, llretslot, ret_ty);
842+
bcx = glue::drop_ty(bcx, llretslot, ret_ty, call_info);
839843
call_lifetime_end(bcx, llretslot);
840844
}
841845
_ => {}

src/librustc/middle/trans/cleanup.rs

+96-24
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use middle::trans::base;
1818
use middle::trans::build;
1919
use middle::trans::callee;
2020
use middle::trans::common;
21-
use middle::trans::common::{Block, FunctionContext, ExprId};
21+
use middle::trans::common::{Block, FunctionContext, ExprId, NodeInfo};
22+
use middle::trans::debuginfo;
2223
use middle::trans::glue;
2324
use middle::trans::type_::Type;
2425
use middle::ty;
@@ -36,6 +37,10 @@ pub struct CleanupScope<'blk, 'tcx: 'blk> {
3637
// Cleanups to run upon scope exit.
3738
cleanups: Vec<CleanupObj>,
3839

40+
// The debug location any drop calls generated for this scope will be
41+
// associated with.
42+
debug_loc: Option<NodeInfo>,
43+
3944
cached_early_exits: Vec<CachedEarlyExit>,
4045
cached_landing_pad: Option<BasicBlockRef>,
4146
}
@@ -69,7 +74,10 @@ pub struct CachedEarlyExit {
6974
pub trait Cleanup {
7075
fn must_unwind(&self) -> bool;
7176
fn clean_on_unwind(&self) -> bool;
72-
fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>) -> Block<'blk, 'tcx>;
77+
fn trans<'blk, 'tcx>(&self,
78+
bcx: Block<'blk, 'tcx>,
79+
debug_loc: Option<NodeInfo>)
80+
-> Block<'blk, 'tcx>;
7381
}
7482

7583
pub type CleanupObj = Box<Cleanup+'static>;
@@ -80,14 +88,14 @@ pub enum ScopeId {
8088
}
8189

8290
impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
83-
fn push_ast_cleanup_scope(&self, id: ast::NodeId) {
91+
fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) {
8492
/*!
8593
* Invoked when we start to trans the code contained
8694
* within a new cleanup scope.
8795
*/
8896

8997
debug!("push_ast_cleanup_scope({})",
90-
self.ccx.tcx().map.node_to_string(id));
98+
self.ccx.tcx().map.node_to_string(debug_loc.id));
9199

92100
// FIXME(#2202) -- currently closure bodies have a parent
93101
// region, which messes up the assertion below, since there
@@ -101,10 +109,15 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
101109
// this new AST scope had better be its immediate child.
102110
let top_scope = self.top_ast_scope();
103111
if top_scope.is_some() {
104-
assert_eq!(self.ccx.tcx().region_maps.opt_encl_scope(id), top_scope);
112+
assert_eq!(self.ccx
113+
.tcx()
114+
.region_maps
115+
.opt_encl_scope(debug_loc.id),
116+
top_scope);
105117
}
106118

107-
self.push_scope(CleanupScope::new(AstScopeKind(id)));
119+
self.push_scope(CleanupScope::new(AstScopeKind(debug_loc.id),
120+
Some(debug_loc)));
108121
}
109122

110123
fn push_loop_cleanup_scope(&self,
@@ -114,13 +127,38 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
114127
self.ccx.tcx().map.node_to_string(id));
115128
assert_eq!(Some(id), self.top_ast_scope());
116129

117-
self.push_scope(CleanupScope::new(LoopScopeKind(id, exits)));
130+
// Just copy the debuginfo source location from the enclosing scope
131+
let debug_loc = self.scopes
132+
.borrow()
133+
.last()
134+
.unwrap()
135+
.debug_loc;
136+
137+
self.push_scope(CleanupScope::new(LoopScopeKind(id, exits), debug_loc));
118138
}
119139

120140
fn push_custom_cleanup_scope(&self) -> CustomScopeIndex {
121141
let index = self.scopes_len();
122142
debug!("push_custom_cleanup_scope(): {}", index);
123-
self.push_scope(CleanupScope::new(CustomScopeKind));
143+
144+
// Just copy the debuginfo source location from the enclosing scope
145+
let debug_loc = self.scopes
146+
.borrow()
147+
.last()
148+
.map(|opt_scope| opt_scope.debug_loc)
149+
.unwrap_or(None);
150+
151+
self.push_scope(CleanupScope::new(CustomScopeKind, debug_loc));
152+
CustomScopeIndex { index: index }
153+
}
154+
155+
fn push_custom_cleanup_scope_with_debug_loc(&self,
156+
debug_loc: NodeInfo)
157+
-> CustomScopeIndex {
158+
let index = self.scopes_len();
159+
debug!("push_custom_cleanup_scope(): {}", index);
160+
161+
self.push_scope(CleanupScope::new(CustomScopeKind, Some(debug_loc)));
124162
CustomScopeIndex { index: index }
125163
}
126164

@@ -141,7 +179,6 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
141179

142180
let scope = self.pop_scope();
143181
self.trans_scope_cleanups(bcx, &scope)
144-
145182
}
146183

147184
fn pop_loop_cleanup_scope(&self,
@@ -175,9 +212,9 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
175212
}
176213

177214
fn pop_and_trans_custom_cleanup_scope(&self,
178-
bcx: Block<'blk, 'tcx>,
179-
custom_scope: CustomScopeIndex)
180-
-> Block<'blk, 'tcx> {
215+
bcx: Block<'blk, 'tcx>,
216+
custom_scope: CustomScopeIndex)
217+
-> Block<'blk, 'tcx> {
181218
/*!
182219
* Removes the top cleanup scope from the stack, which must be
183220
* a temporary scope, and generates the code to do its
@@ -503,7 +540,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
503540
let mut bcx = bcx;
504541
if !bcx.unreachable.get() {
505542
for cleanup in scope.cleanups.iter().rev() {
506-
bcx = cleanup.trans(bcx);
543+
bcx = cleanup.trans(bcx, scope.debug_loc);
507544
}
508545
}
509546
bcx
@@ -671,7 +708,8 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
671708
let mut bcx_out = bcx_in;
672709
for cleanup in scope.cleanups.iter().rev() {
673710
if cleanup_is_suitable_for(&**cleanup, label) {
674-
bcx_out = cleanup.trans(bcx_out);
711+
bcx_out = cleanup.trans(bcx_out,
712+
scope.debug_loc);
675713
}
676714
}
677715
build::Br(bcx_out, prev_llbb);
@@ -785,9 +823,12 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
785823
}
786824

787825
impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> {
788-
fn new(kind: CleanupScopeKind<'blk, 'tcx>) -> CleanupScope<'blk, 'tcx> {
826+
fn new(kind: CleanupScopeKind<'blk, 'tcx>,
827+
debug_loc: Option<NodeInfo>)
828+
-> CleanupScope<'blk, 'tcx> {
789829
CleanupScope {
790830
kind: kind,
831+
debug_loc: debug_loc,
791832
cleanups: vec!(),
792833
cached_early_exits: vec!(),
793834
cached_landing_pad: None,
@@ -902,11 +943,14 @@ impl Cleanup for DropValue {
902943
self.must_unwind
903944
}
904945

905-
fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>) -> Block<'blk, 'tcx> {
946+
fn trans<'blk, 'tcx>(&self,
947+
bcx: Block<'blk, 'tcx>,
948+
debug_loc: Option<NodeInfo>)
949+
-> Block<'blk, 'tcx> {
906950
let bcx = if self.is_immediate {
907-
glue::drop_ty_immediate(bcx, self.val, self.ty)
951+
glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc)
908952
} else {
909-
glue::drop_ty(bcx, self.val, self.ty)
953+
glue::drop_ty(bcx, self.val, self.ty, debug_loc)
910954
};
911955
if self.zero {
912956
base::zero_mem(bcx, self.val, self.ty);
@@ -935,7 +979,12 @@ impl Cleanup for FreeValue {
935979
true
936980
}
937981

938-
fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>) -> Block<'blk, 'tcx> {
982+
fn trans<'blk, 'tcx>(&self,
983+
bcx: Block<'blk, 'tcx>,
984+
debug_loc: Option<NodeInfo>)
985+
-> Block<'blk, 'tcx> {
986+
apply_debug_loc(bcx.fcx, debug_loc);
987+
939988
match self.heap {
940989
HeapManaged => {
941990
glue::trans_free(bcx, self.ptr)
@@ -963,7 +1012,12 @@ impl Cleanup for FreeSlice {
9631012
true
9641013
}
9651014

966-
fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>) -> Block<'blk, 'tcx> {
1015+
fn trans<'blk, 'tcx>(&self,
1016+
bcx: Block<'blk, 'tcx>,
1017+
debug_loc: Option<NodeInfo>)
1018+
-> Block<'blk, 'tcx> {
1019+
apply_debug_loc(bcx.fcx, debug_loc);
1020+
9671021
match self.heap {
9681022
HeapManaged => {
9691023
glue::trans_free(bcx, self.ptr)
@@ -988,7 +1042,11 @@ impl Cleanup for LifetimeEnd {
9881042
true
9891043
}
9901044

991-
fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>) -> Block<'blk, 'tcx> {
1045+
fn trans<'blk, 'tcx>(&self,
1046+
bcx: Block<'blk, 'tcx>,
1047+
debug_loc: Option<NodeInfo>)
1048+
-> Block<'blk, 'tcx> {
1049+
apply_debug_loc(bcx.fcx, debug_loc);
9921050
base::call_lifetime_end(bcx, self.ptr);
9931051
bcx
9941052
}
@@ -1023,15 +1081,29 @@ fn cleanup_is_suitable_for(c: &Cleanup,
10231081
!label.is_unwind() || c.clean_on_unwind()
10241082
}
10251083

1084+
fn apply_debug_loc(fcx: &FunctionContext, debug_loc: Option<NodeInfo>) {
1085+
match debug_loc {
1086+
Some(ref src_loc) => {
1087+
debuginfo::set_source_location(fcx, src_loc.id, src_loc.span);
1088+
}
1089+
None => {
1090+
debuginfo::clear_source_location(fcx);
1091+
}
1092+
}
1093+
}
1094+
10261095
///////////////////////////////////////////////////////////////////////////
10271096
// These traits just exist to put the methods into this file.
10281097

10291098
pub trait CleanupMethods<'blk, 'tcx> {
1030-
fn push_ast_cleanup_scope(&self, id: ast::NodeId);
1099+
fn push_ast_cleanup_scope(&self, id: NodeInfo);
10311100
fn push_loop_cleanup_scope(&self,
1032-
id: ast::NodeId,
1033-
exits: [Block<'blk, 'tcx>, ..EXIT_MAX]);
1101+
id: ast::NodeId,
1102+
exits: [Block<'blk, 'tcx>, ..EXIT_MAX]);
10341103
fn push_custom_cleanup_scope(&self) -> CustomScopeIndex;
1104+
fn push_custom_cleanup_scope_with_debug_loc(&self,
1105+
debug_loc: NodeInfo)
1106+
-> CustomScopeIndex;
10351107
fn pop_and_trans_ast_cleanup_scope(&self,
10361108
bcx: Block<'blk, 'tcx>,
10371109
cleanup_scope: ast::NodeId)

src/librustc/middle/trans/controlflow.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use middle::trans::cleanup;
2222
use middle::trans::common::*;
2323
use middle::trans::consts;
2424
use middle::trans::datum;
25+
use middle::trans::debuginfo;
2526
use middle::trans::expr;
2627
use middle::trans::meth;
2728
use middle::trans::type_::Type;
@@ -53,7 +54,9 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
5354
let mut bcx = cx;
5455

5556
let id = ast_util::stmt_id(s);
56-
fcx.push_ast_cleanup_scope(id);
57+
let cleanup_debug_loc =
58+
debuginfo::get_cleanup_debug_loc_for_ast_node(id, s.span, false);
59+
fcx.push_ast_cleanup_scope(cleanup_debug_loc);
5760

5861
match s.node {
5962
ast::StmtExpr(ref e, _) | ast::StmtSemi(ref e, _) => {
@@ -75,8 +78,7 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
7578
ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
7679
}
7780

78-
bcx = fcx.pop_and_trans_ast_cleanup_scope(
79-
bcx, ast_util::stmt_id(s));
81+
bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, ast_util::stmt_id(s));
8082

8183
return bcx;
8284
}
@@ -100,7 +102,9 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
100102
let fcx = bcx.fcx;
101103
let mut bcx = bcx;
102104

103-
fcx.push_ast_cleanup_scope(b.id);
105+
let cleanup_debug_loc =
106+
debuginfo::get_cleanup_debug_loc_for_ast_node(b.id, b.span, true);
107+
fcx.push_ast_cleanup_scope(cleanup_debug_loc);
104108

105109
for s in b.stmts.iter() {
106110
bcx = trans_stmt(bcx, &**s);

0 commit comments

Comments
 (0)