10
10
11
11
use libc:: c_uint;
12
12
use llvm:: { self , ValueRef } ;
13
- use llvm:: debuginfo:: DIScope ;
14
13
use rustc:: ty;
15
14
use rustc:: mir:: repr as mir;
16
15
use rustc:: mir:: tcx:: LvalueTy ;
17
16
use session:: config:: FullDebugInfo ;
18
17
use base;
19
18
use common:: { self , Block , BlockAndBuilder , CrateContext , FunctionContext , C_null } ;
20
- use debuginfo:: { self , declare_local, DebugLoc , VariableAccess , VariableKind } ;
19
+ use debuginfo:: { self , declare_local, DebugLoc , VariableAccess , VariableKind , FunctionDebugContext } ;
21
20
use machine;
22
21
use type_of;
23
22
24
- use syntax_pos:: DUMMY_SP ;
23
+ use syntax_pos:: { DUMMY_SP , NO_EXPANSION , COMMAND_LINE_EXPN , BytePos } ;
25
24
use syntax:: parse:: token:: keywords;
26
25
27
26
use std:: ops:: Deref ;
@@ -103,12 +102,67 @@ pub struct MirContext<'bcx, 'tcx:'bcx> {
103
102
locals : IndexVec < mir:: Local , LocalRef < ' tcx > > ,
104
103
105
104
/// Debug information for MIR scopes.
106
- scopes : IndexVec < mir:: VisibilityScope , DIScope >
105
+ scopes : IndexVec < mir:: VisibilityScope , debuginfo :: MirDebugScope > ,
107
106
}
108
107
109
108
impl < ' blk , ' tcx > MirContext < ' blk , ' tcx > {
110
- pub fn debug_loc ( & self , source_info : mir:: SourceInfo ) -> DebugLoc {
111
- DebugLoc :: ScopeAt ( self . scopes [ source_info. scope ] , source_info. span )
109
+ pub fn debug_loc ( & mut self , source_info : mir:: SourceInfo ) -> DebugLoc {
110
+ // Bail out if debug info emission is not enabled.
111
+ match self . fcx . debug_context {
112
+ FunctionDebugContext :: DebugInfoDisabled |
113
+ FunctionDebugContext :: FunctionWithoutDebugInfo => {
114
+ // Can't return DebugLoc::None here because intrinsic::trans_intrinsic_call()
115
+ // relies on debug location to obtain span of the call site.
116
+ return DebugLoc :: ScopeAt ( self . scopes [ source_info. scope ] . scope_metadata ,
117
+ source_info. span ) ;
118
+ }
119
+ FunctionDebugContext :: RegularContext ( _) =>{ }
120
+ }
121
+
122
+ // In order to have a good line stepping behavior in debugger, we overwrite debug
123
+ // locations of macro expansions with that of the outermost expansion site
124
+ // (unless the crate is being compiled with `-Z debug-macros`).
125
+ if source_info. span . expn_id == NO_EXPANSION ||
126
+ source_info. span . expn_id == COMMAND_LINE_EXPN ||
127
+ self . fcx . ccx . sess ( ) . opts . debugging_opts . debug_macros {
128
+
129
+ let scope_metadata = self . scope_metadata_for_loc ( source_info. scope ,
130
+ source_info. span . lo ) ;
131
+ DebugLoc :: ScopeAt ( scope_metadata, source_info. span )
132
+ } else {
133
+ let cm = self . fcx . ccx . sess ( ) . codemap ( ) ;
134
+ // Walk up the macro expansion chain until we reach a non-expanded span.
135
+ let mut span = source_info. span ;
136
+ while span. expn_id != NO_EXPANSION && span. expn_id != COMMAND_LINE_EXPN {
137
+ if let Some ( callsite_span) = cm. with_expn_info ( span. expn_id ,
138
+ |ei| ei. map ( |ei| ei. call_site . clone ( ) ) ) {
139
+ span = callsite_span;
140
+ } else {
141
+ break ;
142
+ }
143
+ }
144
+ let scope_metadata = self . scope_metadata_for_loc ( source_info. scope , span. lo ) ;
145
+ // Use span of the outermost call site, while keeping the original lexical scope
146
+ DebugLoc :: ScopeAt ( scope_metadata, span)
147
+ }
148
+ }
149
+
150
+ // DILocations inherit source file name from the parent DIScope. Due to macro expansions
151
+ // it may so happen that the current span belongs to a different file than the DIScope
152
+ // corresponding to span's containing visibility scope. If so, we need to create a DIScope
153
+ // "extension" into that file.
154
+ fn scope_metadata_for_loc ( & self , scope_id : mir:: VisibilityScope , pos : BytePos )
155
+ -> llvm:: debuginfo:: DIScope {
156
+ let scope_metadata = self . scopes [ scope_id] . scope_metadata ;
157
+ if pos < self . scopes [ scope_id] . file_start_pos ||
158
+ pos >= self . scopes [ scope_id] . file_end_pos {
159
+ let cm = self . fcx . ccx . sess ( ) . codemap ( ) ;
160
+ debuginfo:: extend_scope_to_file ( self . fcx . ccx ,
161
+ scope_metadata,
162
+ & cm. lookup_char_pos ( pos) . file )
163
+ } else {
164
+ scope_metadata
165
+ }
112
166
}
113
167
}
114
168
@@ -155,16 +209,38 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
155
209
analyze:: cleanup_kinds ( bcx, & mir) )
156
210
} ) ;
157
211
212
+ // Allocate a `Block` for every basic block
213
+ let block_bcxs: IndexVec < mir:: BasicBlock , Block < ' blk , ' tcx > > =
214
+ mir. basic_blocks ( ) . indices ( ) . map ( |bb| {
215
+ if bb == mir:: START_BLOCK {
216
+ fcx. new_block ( "start" , None )
217
+ } else {
218
+ fcx. new_block ( & format ! ( "{:?}" , bb) , None )
219
+ }
220
+ } ) . collect ( ) ;
221
+
158
222
// Compute debuginfo scopes from MIR scopes.
159
223
let scopes = debuginfo:: create_mir_scopes ( fcx) ;
160
224
225
+ let mut mircx = MirContext {
226
+ mir : mir. clone ( ) ,
227
+ fcx : fcx,
228
+ llpersonalityslot : None ,
229
+ blocks : block_bcxs,
230
+ unreachable_block : None ,
231
+ cleanup_kinds : cleanup_kinds,
232
+ landing_pads : IndexVec :: from_elem ( None , mir. basic_blocks ( ) ) ,
233
+ scopes : scopes,
234
+ locals : IndexVec :: new ( ) ,
235
+ } ;
236
+
161
237
// Allocate variable and temp allocas
162
- let locals = {
163
- let args = arg_local_refs ( & bcx, & mir, & scopes, & lvalue_locals) ;
238
+ mircx . locals = {
239
+ let args = arg_local_refs ( & bcx, & mir, & mircx . scopes , & lvalue_locals) ;
164
240
let vars = mir. var_decls . iter ( ) . enumerate ( ) . map ( |( i, decl) | {
165
241
let ty = bcx. monomorphize ( & decl. ty ) ;
166
- let scope = scopes[ decl. source_info . scope ] ;
167
- let dbg = !scope . is_null ( ) && bcx. sess ( ) . opts . debuginfo == FullDebugInfo ;
242
+ let debug_scope = mircx . scopes [ decl. source_info . scope ] ;
243
+ let dbg = debug_scope . is_valid ( ) && bcx. sess ( ) . opts . debuginfo == FullDebugInfo ;
168
244
169
245
let local = mir. local_index ( & mir:: Lvalue :: Var ( mir:: Var :: new ( i) ) ) . unwrap ( ) ;
170
246
if !lvalue_locals. contains ( local. index ( ) ) && !dbg {
@@ -173,11 +249,16 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
173
249
174
250
let lvalue = LvalueRef :: alloca ( & bcx, ty, & decl. name . as_str ( ) ) ;
175
251
if dbg {
176
- bcx. with_block ( |bcx| {
177
- declare_local ( bcx, decl. name , ty, scope,
178
- VariableAccess :: DirectVariable { alloca : lvalue. llval } ,
179
- VariableKind :: LocalVariable , decl. source_info . span ) ;
180
- } ) ;
252
+ let dbg_loc = mircx. debug_loc ( decl. source_info ) ;
253
+ if let DebugLoc :: ScopeAt ( scope, span) = dbg_loc {
254
+ bcx. with_block ( |bcx| {
255
+ declare_local ( bcx, decl. name , ty, scope,
256
+ VariableAccess :: DirectVariable { alloca : lvalue. llval } ,
257
+ VariableKind :: LocalVariable , span) ;
258
+ } ) ;
259
+ } else {
260
+ panic ! ( "Unexpected" ) ;
261
+ }
181
262
}
182
263
LocalRef :: Lvalue ( lvalue)
183
264
} ) ;
@@ -203,37 +284,15 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
203
284
} ) ) . collect ( )
204
285
} ;
205
286
206
- // Allocate a `Block` for every basic block
207
- let block_bcxs: IndexVec < mir:: BasicBlock , Block < ' blk , ' tcx > > =
208
- mir. basic_blocks ( ) . indices ( ) . map ( |bb| {
209
- if bb == mir:: START_BLOCK {
210
- fcx. new_block ( "start" , None )
211
- } else {
212
- fcx. new_block ( & format ! ( "{:?}" , bb) , None )
213
- }
214
- } ) . collect ( ) ;
215
-
216
287
// Branch to the START block
217
- let start_bcx = block_bcxs [ mir:: START_BLOCK ] ;
288
+ let start_bcx = mircx . blocks [ mir:: START_BLOCK ] ;
218
289
bcx. br ( start_bcx. llbb ) ;
219
290
220
291
// Up until here, IR instructions for this function have explicitly not been annotated with
221
292
// source code location, so we don't step into call setup code. From here on, source location
222
293
// emitting should be enabled.
223
294
debuginfo:: start_emitting_source_locations ( fcx) ;
224
295
225
- let mut mircx = MirContext {
226
- mir : mir. clone ( ) ,
227
- fcx : fcx,
228
- llpersonalityslot : None ,
229
- blocks : block_bcxs,
230
- unreachable_block : None ,
231
- cleanup_kinds : cleanup_kinds,
232
- landing_pads : IndexVec :: from_elem ( None , mir. basic_blocks ( ) ) ,
233
- locals : locals,
234
- scopes : scopes
235
- } ;
236
-
237
296
let mut visited = BitVector :: new ( mir. basic_blocks ( ) . len ( ) ) ;
238
297
239
298
let mut rpo = traversal:: reverse_postorder ( & mir) ;
@@ -271,7 +330,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
271
330
/// indirect.
272
331
fn arg_local_refs < ' bcx , ' tcx > ( bcx : & BlockAndBuilder < ' bcx , ' tcx > ,
273
332
mir : & mir:: Mir < ' tcx > ,
274
- scopes : & IndexVec < mir:: VisibilityScope , DIScope > ,
333
+ scopes : & IndexVec < mir:: VisibilityScope , debuginfo :: MirDebugScope > ,
275
334
lvalue_locals : & BitVector )
276
335
-> Vec < LocalRef < ' tcx > > {
277
336
let fcx = bcx. fcx ( ) ;
@@ -281,8 +340,8 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
281
340
282
341
// Get the argument scope, if it exists and if we need it.
283
342
let arg_scope = scopes[ mir:: ARGUMENT_VISIBILITY_SCOPE ] ;
284
- let arg_scope = if ! arg_scope. is_null ( ) && bcx. sess ( ) . opts . debuginfo == FullDebugInfo {
285
- Some ( arg_scope)
343
+ let arg_scope = if arg_scope. is_valid ( ) && bcx. sess ( ) . opts . debuginfo == FullDebugInfo {
344
+ Some ( arg_scope. scope_metadata )
286
345
} else {
287
346
None
288
347
} ;
0 commit comments