@@ -9,7 +9,8 @@ use rustc_index::vec::IndexVec;
9
9
use rustc_span:: symbol:: { kw, Symbol } ;
10
10
use rustc_span:: { BytePos , Span } ;
11
11
12
- use super :: OperandValue ;
12
+ use super :: operand:: OperandValue ;
13
+ use super :: place:: PlaceRef ;
13
14
use super :: { FunctionCx , LocalRef } ;
14
15
15
16
pub struct FunctionDebugContext < D > {
@@ -111,8 +112,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
111
112
112
113
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
113
114
/// 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`).
116
115
pub fn debug_introduce_local ( & self , bx : & mut Bx , local : mir:: Local ) {
117
116
let full_debug_info = bx. sess ( ) . opts . debuginfo == DebugInfo :: Full ;
118
117
@@ -180,38 +179,60 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
180
179
181
180
let local_ref = & self . locals [ local] ;
182
181
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) {
185
186
Some ( var) if var. name != kw:: Invalid => var. name . to_string ( ) ,
186
187
_ => format ! ( "{:?}" , local) ,
187
- } ;
188
+ } )
189
+ } ;
190
+
191
+ if let Some ( name) = & name {
188
192
match local_ref {
189
193
LocalRef :: Place ( place) | LocalRef :: UnsizedPlace ( place) => {
190
- bx. set_var_name ( place. llval , & name) ;
194
+ bx. set_var_name ( place. llval , name) ;
191
195
}
192
196
LocalRef :: Operand ( Some ( operand) ) => match operand. val {
193
197
OperandValue :: Ref ( x, ..) | OperandValue :: Immediate ( x) => {
194
- bx. set_var_name ( x, & name) ;
198
+ bx. set_var_name ( x, name) ;
195
199
}
196
200
OperandValue :: Pair ( a, b) => {
197
201
// FIXME(eddyb) these are scalar components,
198
202
// maybe extract the high-level fields?
199
203
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" ) ) ;
201
205
}
202
206
} ,
203
207
LocalRef :: Operand ( None ) => { }
204
208
}
205
209
}
206
210
207
- if !full_debug_info {
211
+ if !full_debug_info || vars . is_empty ( ) && fallback_var . is_none ( ) {
208
212
return ;
209
213
}
210
214
211
- // FIXME(eddyb) add debuginfo for unsized places too.
212
215
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 ,
215
236
} ;
216
237
217
238
let vars = vars. iter ( ) . copied ( ) . chain ( fallback_var) ;
0 commit comments