1
1
use crate :: traits:: * ;
2
2
use rustc:: mir;
3
3
use rustc:: session:: config:: DebugInfo ;
4
+ use rustc:: ty;
4
5
use rustc:: ty:: layout:: { LayoutOf , Size } ;
5
- use rustc:: ty:: TyCtxt ;
6
6
use rustc_hir:: def_id:: CrateNum ;
7
7
use rustc_index:: vec:: IndexVec ;
8
8
9
- use rustc_span:: symbol:: kw ;
9
+ use rustc_span:: symbol:: { kw , Symbol } ;
10
10
use rustc_span:: { BytePos , Span } ;
11
11
12
12
use super :: OperandValue ;
@@ -24,6 +24,19 @@ pub enum VariableKind {
24
24
LocalVariable ,
25
25
}
26
26
27
+ /// Like `mir::VarDebugInfo`, but within a `mir::Local`.
28
+ #[ derive( Copy , Clone ) ]
29
+ pub struct PerLocalVarDebugInfo < ' tcx , D > {
30
+ pub name : Symbol ,
31
+ pub source_info : mir:: SourceInfo ,
32
+
33
+ /// `DIVariable` returned by `create_dbg_var`.
34
+ pub dbg_var : Option < D > ,
35
+
36
+ /// `.place.projection` from `mir::VarDebugInfo`.
37
+ pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
38
+ }
39
+
27
40
#[ derive( Clone , Copy , Debug ) ]
28
41
pub struct DebugScope < D > {
29
42
pub scope_metadata : Option < D > ,
@@ -103,6 +116,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
103
116
// FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
104
117
// not just `llvm.dbg.declare` (which requires `alloca`).
105
118
pub fn debug_introduce_local ( & self , bx : & mut Bx , local : mir:: Local ) {
119
+ let full_debug_info = bx. sess ( ) . opts . debuginfo == DebugInfo :: Full ;
120
+
106
121
// FIXME(eddyb) maybe name the return place as `_0` or `return`?
107
122
if local == mir:: RETURN_PLACE {
108
123
return ;
@@ -112,35 +127,63 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
112
127
Some ( per_local) => & per_local[ local] ,
113
128
None => return ,
114
129
} ;
115
- let whole_local_var = vars. iter ( ) . copied ( ) . find ( |var| var. place . projection . is_empty ( ) ) ;
116
- let has_proj = || vars. iter ( ) . any ( |var| !var. place . projection . is_empty ( ) ) ;
130
+ let whole_local_var = vars. iter ( ) . find ( |var| var. projection . is_empty ( ) ) . copied ( ) ;
131
+ let has_proj = || vars. iter ( ) . any ( |var| !var. projection . is_empty ( ) ) ;
117
132
118
- let ( fallback_var, kind ) = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
133
+ let fallback_var = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
119
134
let arg_index = local. index ( ) - 1 ;
120
135
121
136
// Add debuginfo even to unnamed arguments.
122
137
// FIXME(eddyb) is this really needed?
123
- let var = if arg_index == 0 && has_proj ( ) {
138
+ if arg_index == 0 && has_proj ( ) {
124
139
// Hide closure environments from debuginfo.
125
140
// FIXME(eddyb) shouldn't `ArgumentVariable` indices
126
141
// be offset to account for the hidden environment?
127
142
None
143
+ } else if whole_local_var. is_some ( ) {
144
+ // No need to make up anything, there is a `mir::VarDebugInfo`
145
+ // covering the whole local.
146
+ // FIXME(eddyb) take `whole_local_var.source_info.scope` into
147
+ // account, just in case it doesn't use `ArgumentVariable`
148
+ // (after #67586 gets fixed).
149
+ None
128
150
} else {
129
- Some ( mir:: VarDebugInfo {
130
- name : kw:: Invalid ,
131
- source_info : self . mir . local_decls [ local] . source_info ,
132
- place : local. into ( ) ,
151
+ let name = kw:: Invalid ;
152
+ let decl = & self . mir . local_decls [ local] ;
153
+ let ( scope, span) = if full_debug_info {
154
+ self . debug_loc ( decl. source_info )
155
+ } else {
156
+ ( None , decl. source_info . span )
157
+ } ;
158
+ let dbg_var = scope. map ( |scope| {
159
+ // FIXME(eddyb) is this `+ 1` needed at all?
160
+ let kind = VariableKind :: ArgumentVariable ( arg_index + 1 ) ;
161
+
162
+ self . cx . create_dbg_var (
163
+ self . debug_context . as_ref ( ) . unwrap ( ) ,
164
+ name,
165
+ self . monomorphize ( & decl. ty ) ,
166
+ scope,
167
+ kind,
168
+ span,
169
+ )
170
+ } ) ;
171
+
172
+ Some ( PerLocalVarDebugInfo {
173
+ name,
174
+ source_info : decl. source_info ,
175
+ dbg_var,
176
+ projection : ty:: List :: empty ( ) ,
133
177
} )
134
- } ;
135
- ( var, VariableKind :: ArgumentVariable ( arg_index + 1 ) )
178
+ }
136
179
} else {
137
- ( None , VariableKind :: LocalVariable )
180
+ None
138
181
} ;
139
182
140
183
let local_ref = & self . locals [ local] ;
141
184
142
185
if !bx. sess ( ) . fewer_names ( ) {
143
- let name = match whole_local_var. or ( fallback_var. as_ref ( ) ) {
186
+ let name = match whole_local_var. or ( fallback_var) {
144
187
Some ( var) if var. name != kw:: Invalid => var. name . to_string ( ) ,
145
188
_ => format ! ( "{:?}" , local) ,
146
189
} ;
@@ -163,7 +206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
163
206
}
164
207
}
165
208
166
- if bx . sess ( ) . opts . debuginfo != DebugInfo :: Full {
209
+ if !full_debug_info {
167
210
return ;
168
211
}
169
212
@@ -178,22 +221,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
178
221
_ => return ,
179
222
} ;
180
223
181
- let vars = vars. iter ( ) . copied ( ) . chain ( if whole_local_var. is_none ( ) {
182
- fallback_var. as_ref ( )
183
- } else {
184
- None
185
- } ) ;
224
+ let vars = vars. iter ( ) . copied ( ) . chain ( fallback_var) ;
186
225
187
226
for var in vars {
188
227
let mut layout = base. layout ;
189
228
let mut direct_offset = Size :: ZERO ;
190
229
// FIXME(eddyb) use smallvec here.
191
230
let mut indirect_offsets = vec ! [ ] ;
192
231
193
- let kind =
194
- if var. place . projection . is_empty ( ) { kind } else { VariableKind :: LocalVariable } ;
195
-
196
- for elem in & var. place . projection [ ..] {
232
+ for elem in & var. projection [ ..] {
197
233
match * elem {
198
234
mir:: ProjectionElem :: Deref => {
199
235
indirect_offsets. push ( Size :: ZERO ) ;
@@ -202,7 +238,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
202
238
. ty
203
239
. builtin_deref ( true )
204
240
. unwrap_or_else ( || {
205
- span_bug ! ( var. source_info. span, "cannot deref `{}`" , layout. ty, )
241
+ span_bug ! ( var. source_info. span, "cannot deref `{}`" , layout. ty)
206
242
} )
207
243
. ty ,
208
244
) ;
@@ -219,24 +255,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
219
255
_ => span_bug ! (
220
256
var. source_info. span,
221
257
"unsupported var debuginfo place `{:?}`" ,
222
- var. place ,
258
+ mir :: Place { local , projection : var. projection } ,
223
259
) ,
224
260
}
225
261
}
226
262
227
263
let ( scope, span) = self . debug_loc ( var. source_info ) ;
228
264
if let Some ( scope) = scope {
229
- let dbg_var =
230
- bx. create_dbg_var ( debug_context , var . name , layout . ty , scope , kind , span ) ;
231
- bx . dbg_var_addr (
232
- debug_context ,
233
- dbg_var ,
234
- scope ,
235
- base . llval ,
236
- direct_offset ,
237
- & indirect_offsets ,
238
- span ,
239
- ) ;
265
+ if let Some ( dbg_var) = var . dbg_var {
266
+ bx. dbg_var_addr (
267
+ debug_context ,
268
+ dbg_var ,
269
+ scope ,
270
+ base . llval ,
271
+ direct_offset ,
272
+ & indirect_offsets ,
273
+ span ,
274
+ ) ;
275
+ }
240
276
}
241
277
}
242
278
}
@@ -248,20 +284,60 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
248
284
}
249
285
}
250
286
}
251
- }
252
287
253
- /// Partition all `VarDebuginfo` in `body`, by their base `Local`.
254
- pub fn per_local_var_debug_info (
255
- tcx : TyCtxt < ' tcx > ,
256
- body : & ' a mir:: Body < ' tcx > ,
257
- ) -> Option < IndexVec < mir:: Local , Vec < & ' a mir:: VarDebugInfo < ' tcx > > > > {
258
- if tcx. sess . opts . debuginfo == DebugInfo :: Full || !tcx. sess . fewer_names ( ) {
259
- let mut per_local = IndexVec :: from_elem ( vec ! [ ] , & body. local_decls ) ;
260
- for var in & body. var_debug_info {
261
- per_local[ var. place . local ] . push ( var) ;
288
+ /// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
289
+ pub fn compute_per_local_var_debug_info (
290
+ & self ,
291
+ ) -> Option < IndexVec < mir:: Local , Vec < PerLocalVarDebugInfo < ' tcx , Bx :: DIVariable > > > > {
292
+ let full_debug_info = self . cx . sess ( ) . opts . debuginfo == DebugInfo :: Full ;
293
+
294
+ if !( full_debug_info || !self . cx . sess ( ) . fewer_names ( ) ) {
295
+ return None ;
296
+ }
297
+
298
+ let mut per_local = IndexVec :: from_elem ( vec ! [ ] , & self . mir . local_decls ) ;
299
+ for var in & self . mir . var_debug_info {
300
+ let ( scope, span) = if full_debug_info {
301
+ self . debug_loc ( var. source_info )
302
+ } else {
303
+ ( None , var. source_info . span )
304
+ } ;
305
+ let dbg_var = scope. map ( |scope| {
306
+ let place = var. place ;
307
+ let var_ty = self . monomorphized_place_ty ( place. as_ref ( ) ) ;
308
+ let var_kind = if self . mir . local_kind ( place. local ) == mir:: LocalKind :: Arg
309
+ && place. projection . is_empty ( )
310
+ {
311
+ // FIXME(eddyb, #67586) take `var.source_info.scope` into
312
+ // account to avoid using `ArgumentVariable` more than once
313
+ // per argument local.
314
+
315
+ let arg_index = place. local . index ( ) - 1 ;
316
+
317
+ // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
318
+ // offset in closures to account for the hidden environment?
319
+ // Also, is this `+ 1` needed at all?
320
+ VariableKind :: ArgumentVariable ( arg_index + 1 )
321
+ } else {
322
+ VariableKind :: LocalVariable
323
+ } ;
324
+ self . cx . create_dbg_var (
325
+ self . debug_context . as_ref ( ) . unwrap ( ) ,
326
+ var. name ,
327
+ var_ty,
328
+ scope,
329
+ var_kind,
330
+ span,
331
+ )
332
+ } ) ;
333
+
334
+ per_local[ var. place . local ] . push ( PerLocalVarDebugInfo {
335
+ name : var. name ,
336
+ source_info : var. source_info ,
337
+ dbg_var,
338
+ projection : var. place . projection ,
339
+ } ) ;
262
340
}
263
341
Some ( per_local)
264
- } else {
265
- None
266
342
}
267
343
}
0 commit comments