@@ -9,7 +9,8 @@ use rustc_index::vec::IndexVec;
99use rustc_span:: symbol:: { kw, Symbol } ;
1010use rustc_span:: { BytePos , Span } ;
1111
12- use super :: OperandValue ;
12+ use super :: operand:: OperandValue ;
13+ use super :: place:: PlaceRef ;
1314use super :: { FunctionCx , LocalRef } ;
1415
1516pub struct FunctionDebugContext < D > {
@@ -111,8 +112,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
111112
112113 /// Apply debuginfo and/or name, after creating the `alloca` for a local,
113114 /// or initializing the local with an operand (whichever applies).
114- // FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
115- // not just `llvm.dbg.declare` (which requires `alloca`).
116115 pub fn debug_introduce_local ( & self , bx : & mut Bx , local : mir:: Local ) {
117116 let full_debug_info = bx. sess ( ) . opts . debuginfo == DebugInfo :: Full ;
118117
@@ -180,38 +179,60 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
180179
181180 let local_ref = & self . locals [ local] ;
182181
183- if !bx. sess ( ) . fewer_names ( ) {
184- let name = match whole_local_var. or ( fallback_var) {
182+ let name = if bx. sess ( ) . fewer_names ( ) {
183+ None
184+ } else {
185+ Some ( match whole_local_var. or ( fallback_var) {
185186 Some ( var) if var. name != kw:: Invalid => var. name . to_string ( ) ,
186187 _ => format ! ( "{:?}" , local) ,
187- } ;
188+ } )
189+ } ;
190+
191+ if let Some ( name) = & name {
188192 match local_ref {
189193 LocalRef :: Place ( place) | LocalRef :: UnsizedPlace ( place) => {
190- bx. set_var_name ( place. llval , & name) ;
194+ bx. set_var_name ( place. llval , name) ;
191195 }
192196 LocalRef :: Operand ( Some ( operand) ) => match operand. val {
193197 OperandValue :: Ref ( x, ..) | OperandValue :: Immediate ( x) => {
194- bx. set_var_name ( x, & name) ;
198+ bx. set_var_name ( x, name) ;
195199 }
196200 OperandValue :: Pair ( a, b) => {
197201 // FIXME(eddyb) these are scalar components,
198202 // maybe extract the high-level fields?
199203 bx. set_var_name ( a, & ( name. clone ( ) + ".0" ) ) ;
200- bx. set_var_name ( b, & ( name + ".1" ) ) ;
204+ bx. set_var_name ( b, & ( name. clone ( ) + ".1" ) ) ;
201205 }
202206 } ,
203207 LocalRef :: Operand ( None ) => { }
204208 }
205209 }
206210
207- if !full_debug_info {
211+ if !full_debug_info || vars . is_empty ( ) && fallback_var . is_none ( ) {
208212 return ;
209213 }
210214
211- // FIXME(eddyb) add debuginfo for unsized places too.
212215 let base = match local_ref {
213- LocalRef :: Place ( place) => place,
214- _ => return ,
216+ LocalRef :: Operand ( None ) => return ,
217+
218+ LocalRef :: Operand ( Some ( operand) ) => {
219+ // "Spill" the value onto the stack, for debuginfo,
220+ // without forcing non-debuginfo uses of the local
221+ // to also load from the stack every single time.
222+ // FIXME(#68817) use `llvm.dbg.value` instead,
223+ // at least for the cases which LLVM handles correctly.
224+ let spill_slot = PlaceRef :: alloca ( bx, operand. layout ) ;
225+ if let Some ( name) = name {
226+ bx. set_var_name ( spill_slot. llval , & ( name + ".dbg.spill" ) ) ;
227+ }
228+ operand. val . store ( bx, spill_slot) ;
229+ spill_slot
230+ }
231+
232+ LocalRef :: Place ( place) => * place,
233+
234+ // FIXME(eddyb) add debuginfo for unsized places too.
235+ LocalRef :: UnsizedPlace ( _) => return ,
215236 } ;
216237
217238 let vars = vars. iter ( ) . copied ( ) . chain ( fallback_var) ;
0 commit comments