@@ -3,12 +3,12 @@ use rustc_index::vec::IndexVec;
33use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
44use rustc_middle:: mir;
55use rustc_middle:: ty;
6+ use rustc_middle:: ty:: layout:: TyAndLayout ;
67use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
78use rustc_session:: config:: DebugInfo ;
89use rustc_span:: symbol:: { kw, Symbol } ;
910use rustc_span:: { BytePos , Span } ;
10- use rustc_target:: abi:: Abi ;
11- use rustc_target:: abi:: Size ;
11+ use rustc_target:: abi:: { Abi , Size , VariantIdx } ;
1212
1313use super :: operand:: { OperandRef , OperandValue } ;
1414use super :: place:: PlaceRef ;
@@ -76,6 +76,106 @@ impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
7676 }
7777}
7878
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+
79179impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
80180 pub fn set_debug_loc ( & self , bx : & mut Bx , source_info : mir:: SourceInfo ) {
81181 bx. set_span ( source_info. span ) ;
@@ -262,33 +362,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
262362 let Some ( dbg_var) = var. dbg_var else { continue } ;
263363 let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { continue } ;
264364
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 ) ;
292367
293368 // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
294369 // 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> {
306381 || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
307382
308383 if should_create_individual_allocas {
384+ let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
385+ calculate_debuginfo_offset ( bx, local, & var, base) ;
386+
309387 // Create a variable which will be a pointer to the actual value
310388 let ptr_ty = bx. tcx ( ) . mk_ty ( ty:: RawPtr ( ty:: TypeAndMut {
311389 mutbl : mir:: Mutability :: Mut ,
0 commit comments