@@ -7,10 +7,12 @@ use rustc::ty::layout::HasTyCtxt;
7
7
use rustc_target:: abi:: { Variants , VariantIdx } ;
8
8
use crate :: traits:: * ;
9
9
10
+ use std:: fmt;
10
11
use syntax_pos:: { DUMMY_SP , BytePos , Span } ;
11
12
use syntax:: symbol:: kw;
12
13
13
14
use super :: { FunctionCx , LocalRef } ;
15
+ use super :: OperandValue ;
14
16
15
17
pub enum FunctionDebugContext < D > {
16
18
RegularContext ( FunctionDebugContextData < D > ) ,
@@ -90,6 +92,29 @@ impl<D> DebugScope<D> {
90
92
}
91
93
}
92
94
95
+ // HACK(eddyb) helpers for `set_var_name` calls, move elsewhere?
96
+ enum Either < T , U > {
97
+ Left ( T ) ,
98
+ Right ( U ) ,
99
+ }
100
+
101
+ impl < T : fmt:: Display , U : fmt:: Display > fmt:: Display for Either < T , U > {
102
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
103
+ match self {
104
+ Either :: Left ( x) => x. fmt ( f) ,
105
+ Either :: Right ( x) => x. fmt ( f) ,
106
+ }
107
+ }
108
+ }
109
+
110
+ struct DisplayViaDebug < T > ( T ) ;
111
+
112
+ impl < T : fmt:: Debug > fmt:: Display for DisplayViaDebug < T > {
113
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
114
+ self . 0 . fmt ( f)
115
+ }
116
+ }
117
+
93
118
impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
94
119
pub fn set_debug_loc (
95
120
& mut self ,
@@ -149,54 +174,107 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
149
174
}
150
175
}
151
176
152
- pub fn debug_declare_locals ( & self , bx : & mut Bx ) {
153
- let tcx = self . cx . tcx ( ) ;
177
+ /// Apply debuginfo and/or name, after creating the `alloca` for a local,
178
+ /// or initializing the local with an operand (whichever applies).
179
+ // FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
180
+ // not just `llvm.dbg.declare` (which requires `alloca`).
181
+ pub fn debug_introduce_local ( & self , bx : & mut Bx , local : mir:: Local ) {
154
182
let upvar_debuginfo = & self . mir . __upvar_debuginfo_codegen_only_do_not_use ;
155
183
156
- if bx. sess ( ) . opts . debuginfo != DebugInfo :: Full {
184
+ // FIXME(eddyb) maybe name the return place as `_0` or `return`?
185
+ if local == mir:: RETURN_PLACE {
157
186
return ;
158
187
}
159
188
160
- for ( local, local_ref) in self . locals . iter_enumerated ( ) {
161
- if local == mir:: RETURN_PLACE {
162
- continue ;
189
+ let decl = & self . mir . local_decls [ local] ;
190
+ let ( name, kind) = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
191
+ let arg_index = local. index ( ) - 1 ;
192
+
193
+ // Add debuginfo even to unnamed arguments.
194
+ // FIXME(eddyb) is this really needed?
195
+ let name = if arg_index == 0 && !upvar_debuginfo. is_empty ( ) {
196
+ // Hide closure environments from debuginfo.
197
+ // FIXME(eddyb) shouldn't `ArgumentVariable` indices
198
+ // be offset to account for the hidden environment?
199
+ None
200
+ } else {
201
+ Some ( decl. name . unwrap_or ( kw:: Invalid ) )
202
+ } ;
203
+ ( name, VariableKind :: ArgumentVariable ( arg_index + 1 ) )
204
+ } else {
205
+ ( decl. name , VariableKind :: LocalVariable )
206
+ } ;
207
+
208
+ let local_ref = & self . locals [ local] ;
209
+
210
+ {
211
+ let name = match name {
212
+ Some ( name) if name != kw:: Invalid => Either :: Left ( name) ,
213
+ _ => Either :: Right ( DisplayViaDebug ( local) ) ,
214
+ } ;
215
+ match local_ref {
216
+ LocalRef :: Place ( place) |
217
+ LocalRef :: UnsizedPlace ( place) => {
218
+ bx. set_var_name ( place. llval , name) ;
219
+ }
220
+ LocalRef :: Operand ( Some ( operand) ) => match operand. val {
221
+ OperandValue :: Ref ( x, ..) |
222
+ OperandValue :: Immediate ( x) => {
223
+ bx. set_var_name ( x, name) ;
224
+ }
225
+ OperandValue :: Pair ( a, b) => {
226
+ // FIXME(eddyb) these are scalar components,
227
+ // maybe extract the high-level fields?
228
+ bx. set_var_name ( a, format_args ! ( "{}.0" , name) ) ;
229
+ bx. set_var_name ( b, format_args ! ( "{}.1" , name) ) ;
230
+ }
231
+ }
232
+ LocalRef :: Operand ( None ) => { }
233
+ }
234
+ }
235
+
236
+ if let Some ( name) = name {
237
+ if bx. sess ( ) . opts . debuginfo != DebugInfo :: Full {
238
+ return ;
163
239
}
164
240
165
241
// FIXME(eddyb) add debuginfo for unsized places too.
166
242
let place = match local_ref {
167
243
LocalRef :: Place ( place) => place,
168
- _ => continue ,
244
+ _ => return ,
169
245
} ;
170
246
171
- let decl = & self . mir . local_decls [ local] ;
172
- let ( name, kind) = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
173
- let arg_index = local. index ( ) - 1 ;
174
-
175
- // Add debuginfo even to unnamed arguments.
176
- // FIXME(eddyb) is this really needed?
177
- let name = if arg_index == 0 && !upvar_debuginfo. is_empty ( ) {
178
- // Hide closure environments from debuginfo.
179
- // FIXME(eddyb) shouldn't `ArgumentVariable` indices
180
- // be offset to account for the hidden environment?
181
- None
182
- } else {
183
- Some ( decl. name . unwrap_or ( kw:: Invalid ) )
184
- } ;
185
- ( name, VariableKind :: ArgumentVariable ( arg_index + 1 ) )
186
- } else {
187
- ( decl. name , VariableKind :: LocalVariable )
188
- } ;
189
- if let Some ( name) = name {
190
- let ( scope, span) = self . debug_loc ( mir:: SourceInfo {
191
- span : decl. source_info . span ,
192
- scope : decl. visibility_scope ,
193
- } ) ;
194
- if let Some ( scope) = scope {
195
- bx. declare_local ( & self . debug_context , name, place. layout . ty , scope,
196
- VariableAccess :: DirectVariable { alloca : place. llval } ,
197
- kind, span) ;
247
+ let ( scope, span) = self . debug_loc ( mir:: SourceInfo {
248
+ span : decl. source_info . span ,
249
+ scope : decl. visibility_scope ,
250
+ } ) ;
251
+ if let Some ( scope) = scope {
252
+ bx. declare_local ( & self . debug_context , name, place. layout . ty , scope,
253
+ VariableAccess :: DirectVariable { alloca : place. llval } ,
254
+ kind, span) ;
255
+ }
256
+ }
257
+ }
258
+
259
+ pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
260
+ let tcx = self . cx . tcx ( ) ;
261
+ let upvar_debuginfo = & self . mir . __upvar_debuginfo_codegen_only_do_not_use ;
262
+
263
+ if bx. sess ( ) . opts . debuginfo != DebugInfo :: Full {
264
+ // HACK(eddyb) figure out a way to perhaps disentangle
265
+ // the use of `declare_local` and `set_var_name`.
266
+ // Or maybe just running this loop always is not that expensive?
267
+ if !bx. sess ( ) . fewer_names ( ) {
268
+ for local in self . locals . indices ( ) {
269
+ self . debug_introduce_local ( bx, local) ;
198
270
}
199
271
}
272
+
273
+ return ;
274
+ }
275
+
276
+ for local in self . locals . indices ( ) {
277
+ self . debug_introduce_local ( bx, local) ;
200
278
}
201
279
202
280
// Declare closure captures as if they were local variables.
0 commit comments