@@ -7,10 +7,12 @@ use rustc::ty::layout::HasTyCtxt;
77use rustc_target:: abi:: { Variants , VariantIdx } ;
88use crate :: traits:: * ;
99
10+ use std:: fmt;
1011use syntax_pos:: { DUMMY_SP , BytePos , Span } ;
1112use syntax:: symbol:: kw;
1213
1314use super :: { FunctionCx , LocalRef } ;
15+ use super :: OperandValue ;
1416
1517pub enum FunctionDebugContext < D > {
1618 RegularContext ( FunctionDebugContextData < D > ) ,
@@ -90,6 +92,29 @@ impl<D> DebugScope<D> {
9092 }
9193}
9294
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+
93118impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
94119 pub fn set_debug_loc (
95120 & mut self ,
@@ -149,54 +174,107 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
149174 }
150175 }
151176
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 ) {
154182 let upvar_debuginfo = & self . mir . __upvar_debuginfo_codegen_only_do_not_use ;
155183
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 {
157186 return ;
158187 }
159188
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 ;
163239 }
164240
165241 // FIXME(eddyb) add debuginfo for unsized places too.
166242 let place = match local_ref {
167243 LocalRef :: Place ( place) => place,
168- _ => continue ,
244+ _ => return ,
169245 } ;
170246
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) ;
198270 }
199271 }
272+
273+ return ;
274+ }
275+
276+ for local in self . locals . indices ( ) {
277+ self . debug_introduce_local ( bx, local) ;
200278 }
201279
202280 // Declare closure captures as if they were local variables.
0 commit comments