@@ -3,18 +3,54 @@ use crate::prelude::*;
3
3
fn codegen_field < ' tcx > (
4
4
fx : & mut FunctionCx < ' _ , ' tcx , impl Backend > ,
5
5
base : Value ,
6
+ extra : Option < Value > ,
6
7
layout : TyLayout < ' tcx > ,
7
8
field : mir:: Field ,
8
9
) -> ( Value , TyLayout < ' tcx > ) {
9
10
let field_offset = layout. fields . offset ( field. index ( ) ) ;
10
- let field_ty = layout. field ( & * fx, field. index ( ) ) ;
11
- if field_offset. bytes ( ) > 0 {
12
- (
13
- fx. bcx . ins ( ) . iadd_imm ( base, field_offset. bytes ( ) as i64 ) ,
14
- field_ty,
15
- )
11
+ let field_layout = layout. field ( & * fx, field. index ( ) ) ;
12
+
13
+ let simple = |fx : & mut FunctionCx < _ > | {
14
+ if field_offset. bytes ( ) > 0 {
15
+ (
16
+ fx. bcx . ins ( ) . iadd_imm ( base, field_offset. bytes ( ) as i64 ) ,
17
+ field_layout,
18
+ )
19
+ } else {
20
+ ( base, field_layout)
21
+ }
22
+ } ;
23
+
24
+ if let Some ( extra) = extra {
25
+ if !field_layout. is_unsized ( ) {
26
+ return simple ( fx) ;
27
+ }
28
+ match field_layout. ty . sty {
29
+ ty:: Slice ( ..) | ty:: Str | ty:: Foreign ( ..) => return simple ( fx) ,
30
+ ty:: Adt ( def, _) if def. repr . packed ( ) => {
31
+ assert_eq ! ( layout. align. abi. bytes( ) , 1 ) ;
32
+ return simple ( fx) ;
33
+ }
34
+ _ => {
35
+ // We have to align the offset for DST's
36
+ let unaligned_offset = field_offset. bytes ( ) ;
37
+ let ( _, unsized_align) = crate :: unsize:: size_and_align_of_dst ( fx, field_layout. ty , extra) ;
38
+
39
+ let one = fx. bcx . ins ( ) . iconst ( pointer_ty ( fx. tcx ) , 1 ) ;
40
+ let align_sub_1 = fx. bcx . ins ( ) . isub ( unsized_align, one) ;
41
+ let and_lhs = fx. bcx . ins ( ) . iadd_imm ( align_sub_1, unaligned_offset as i64 ) ;
42
+ let zero = fx. bcx . ins ( ) . iconst ( pointer_ty ( fx. tcx ) , 0 ) ;
43
+ let and_rhs = fx. bcx . ins ( ) . isub ( zero, unsized_align) ;
44
+ let offset = fx. bcx . ins ( ) . band ( and_lhs, and_rhs) ;
45
+
46
+ (
47
+ fx. bcx . ins ( ) . iadd ( base, offset) ,
48
+ field_layout,
49
+ )
50
+ }
51
+ }
16
52
} else {
17
- ( base , field_ty )
53
+ simple ( fx )
18
54
}
19
55
}
20
56
@@ -125,7 +161,7 @@ impl<'tcx> CValue<'tcx> {
125
161
_ => bug ! ( "place_field for {:?}" , self ) ,
126
162
} ;
127
163
128
- let ( field_ptr, field_layout) = codegen_field ( fx, base, layout, field) ;
164
+ let ( field_ptr, field_layout) = codegen_field ( fx, base, None , layout, field) ;
129
165
CValue :: by_ref ( field_ptr, field_layout)
130
166
}
131
167
@@ -431,7 +467,7 @@ impl<'tcx> CPlace<'tcx> {
431
467
let layout = self . layout ( ) ;
432
468
let ( base, extra) = self . to_addr_maybe_unsized ( fx) ;
433
469
434
- let ( field_ptr, field_layout) = codegen_field ( fx, base, layout, field) ;
470
+ let ( field_ptr, field_layout) = codegen_field ( fx, base, extra , layout, field) ;
435
471
if field_layout. is_unsized ( ) {
436
472
CPlace :: for_addr_with_extra ( field_ptr, extra. unwrap ( ) , field_layout)
437
473
} else {
0 commit comments