@@ -3,12 +3,12 @@ use rustc_index::vec::IndexVec;
3
3
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
4
4
use rustc_middle:: mir;
5
5
use rustc_middle:: ty;
6
+ use rustc_middle:: ty:: layout:: TyAndLayout ;
6
7
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
7
8
use rustc_session:: config:: DebugInfo ;
8
9
use rustc_span:: symbol:: { kw, Symbol } ;
9
10
use rustc_span:: { BytePos , Span } ;
10
- use rustc_target:: abi:: Abi ;
11
- use rustc_target:: abi:: Size ;
11
+ use rustc_target:: abi:: { Abi , Size , VariantIdx } ;
12
12
13
13
use super :: operand:: { OperandRef , OperandValue } ;
14
14
use super :: place:: PlaceRef ;
@@ -76,6 +76,106 @@ impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
76
76
}
77
77
}
78
78
79
+ trait DebugInfoOffsetLocation < ' tcx , Bx > {
80
+ fn deref ( & self , bx : & mut Bx ) -> Self ;
81
+ fn layout ( & self ) -> TyAndLayout < ' tcx > ;
82
+ fn project_field ( & self , bx : & mut Bx , field : mir:: Field ) -> Self ;
83
+ fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self ;
84
+ }
85
+
86
+ impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > DebugInfoOffsetLocation < ' tcx , Bx >
87
+ for PlaceRef < ' tcx , Bx :: Value >
88
+ {
89
+ fn deref ( & self , bx : & mut Bx ) -> Self {
90
+ bx. load_operand ( * self ) . deref ( bx. cx ( ) )
91
+ }
92
+
93
+ fn layout ( & self ) -> TyAndLayout < ' tcx > {
94
+ self . layout
95
+ }
96
+
97
+ fn project_field ( & self , bx : & mut Bx , field : mir:: Field ) -> Self {
98
+ PlaceRef :: project_field ( * self , bx, field. index ( ) )
99
+ }
100
+
101
+ fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self {
102
+ self . project_downcast ( bx, variant)
103
+ }
104
+ }
105
+
106
+ impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > DebugInfoOffsetLocation < ' tcx , Bx >
107
+ for TyAndLayout < ' tcx >
108
+ {
109
+ fn deref ( & self , bx : & mut Bx ) -> Self {
110
+ bx. cx ( ) . layout_of (
111
+ self . ty . builtin_deref ( true ) . unwrap_or_else ( || bug ! ( "cannot deref `{}`" , self . ty) ) . ty ,
112
+ )
113
+ }
114
+
115
+ fn layout ( & self ) -> TyAndLayout < ' tcx > {
116
+ * self
117
+ }
118
+
119
+ fn project_field ( & self , bx : & mut Bx , field : mir:: Field ) -> Self {
120
+ self . field ( bx. cx ( ) , field. index ( ) )
121
+ }
122
+
123
+ fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self {
124
+ self . for_variant ( bx. cx ( ) , variant)
125
+ }
126
+ }
127
+
128
+ struct DebugInfoOffset < T > {
129
+ /// Offset from the `base` used to calculate the debuginfo offset.
130
+ direct_offset : Size ,
131
+ /// Each offset in this vector indicates one level of indirection from the base or previous
132
+ /// indirect offset plus a dereference.
133
+ indirect_offsets : Vec < Size > ,
134
+ /// The final location debuginfo should point to.
135
+ result : T ,
136
+ }
137
+
138
+ fn calculate_debuginfo_offset <
139
+ ' a ,
140
+ ' tcx ,
141
+ Bx : BuilderMethods < ' a , ' tcx > ,
142
+ L : DebugInfoOffsetLocation < ' tcx , Bx > ,
143
+ > (
144
+ bx : & mut Bx ,
145
+ local : mir:: Local ,
146
+ var : & PerLocalVarDebugInfo < ' tcx , Bx :: DIVariable > ,
147
+ base : L ,
148
+ ) -> DebugInfoOffset < L > {
149
+ let mut direct_offset = Size :: ZERO ;
150
+ // FIXME(eddyb) use smallvec here.
151
+ let mut indirect_offsets = vec ! [ ] ;
152
+ let mut place = base;
153
+
154
+ for elem in & var. projection [ ..] {
155
+ match * elem {
156
+ mir:: ProjectionElem :: Deref => {
157
+ indirect_offsets. push ( Size :: ZERO ) ;
158
+ place = place. deref ( bx) ;
159
+ }
160
+ mir:: ProjectionElem :: Field ( field, _) => {
161
+ let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
162
+ * offset += place. layout ( ) . fields . offset ( field. index ( ) ) ;
163
+ place = place. project_field ( bx, field) ;
164
+ }
165
+ mir:: ProjectionElem :: Downcast ( _, variant) => {
166
+ place = place. downcast ( bx, variant) ;
167
+ }
168
+ _ => span_bug ! (
169
+ var. source_info. span,
170
+ "unsupported var debuginfo place `{:?}`" ,
171
+ mir:: Place { local, projection: var. projection } ,
172
+ ) ,
173
+ }
174
+ }
175
+
176
+ DebugInfoOffset { direct_offset, indirect_offsets, result : place }
177
+ }
178
+
79
179
impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
80
180
pub fn set_debug_loc ( & self , bx : & mut Bx , source_info : mir:: SourceInfo ) {
81
181
bx. set_span ( source_info. span ) ;
@@ -262,33 +362,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
262
362
let Some ( dbg_var) = var. dbg_var else { continue } ;
263
363
let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { continue } ;
264
364
265
- let mut direct_offset = Size :: ZERO ;
266
- // FIXME(eddyb) use smallvec here.
267
- let mut indirect_offsets = vec ! [ ] ;
268
- let mut place = base;
269
-
270
- for elem in & var. projection [ ..] {
271
- match * elem {
272
- mir:: ProjectionElem :: Deref => {
273
- indirect_offsets. push ( Size :: ZERO ) ;
274
- place = bx. load_operand ( place) . deref ( bx. cx ( ) ) ;
275
- }
276
- mir:: ProjectionElem :: Field ( field, _) => {
277
- let i = field. index ( ) ;
278
- let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
279
- * offset += place. layout . fields . offset ( i) ;
280
- place = place. project_field ( bx, i) ;
281
- }
282
- mir:: ProjectionElem :: Downcast ( _, variant) => {
283
- place = place. project_downcast ( bx, variant) ;
284
- }
285
- _ => span_bug ! (
286
- var. source_info. span,
287
- "unsupported var debuginfo place `{:?}`" ,
288
- mir:: Place { local, projection: var. projection } ,
289
- ) ,
290
- }
291
- }
365
+ let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
366
+ calculate_debuginfo_offset ( bx, local, & var, base. layout ) ;
292
367
293
368
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
294
369
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -306,6 +381,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
306
381
|| !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
307
382
308
383
if should_create_individual_allocas {
384
+ let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
385
+ calculate_debuginfo_offset ( bx, local, & var, base) ;
386
+
309
387
// Create a variable which will be a pointer to the actual value
310
388
let ptr_ty = bx. tcx ( ) . mk_ty ( ty:: RawPtr ( ty:: TypeAndMut {
311
389
mutbl : mir:: Mutability :: Mut ,
0 commit comments