@@ -55,7 +55,7 @@ use syntax::attr;
55
55
use syntax:: attr:: IntType ;
56
56
use _match;
57
57
use abi:: FAT_PTR_ADDR ;
58
- use base:: InitAlloca ;
58
+ use base:: { self , InitAlloca } ;
59
59
use build:: * ;
60
60
use cleanup;
61
61
use cleanup:: CleanupMethods ;
@@ -1023,16 +1023,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
1023
1023
Store ( bcx, C_null ( llptrty) , val) ;
1024
1024
}
1025
1025
}
1026
- StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
1026
+ StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull , .. } => {
1027
1027
if discr != nndiscr {
1028
- let llptrptr = GEPi ( bcx, val, & discrfield[ ..] ) ;
1029
- let llptrty = val_ty ( llptrptr) . element_type ( ) ;
1030
- Store ( bcx, C_null ( llptrty) , llptrptr) ;
1028
+ if target_sets_discr_via_memset ( bcx) {
1029
+ // Issue #34427: As workaround for LLVM bug on
1030
+ // ARM, use memset of 0 on whole struct rather
1031
+ // than storing null to single target field.
1032
+ let b = B ( bcx) ;
1033
+ let llptr = b. pointercast ( val, Type :: i8 ( b. ccx ) . ptr_to ( ) ) ;
1034
+ let fill_byte = C_u8 ( b. ccx , 0 ) ;
1035
+ let size = C_uint ( b. ccx , nonnull. size ) ;
1036
+ let align = C_i32 ( b. ccx , nonnull. align as i32 ) ;
1037
+ base:: call_memset ( & b, llptr, fill_byte, size, align, false ) ;
1038
+ } else {
1039
+ let llptrptr = GEPi ( bcx, val, & discrfield[ ..] ) ;
1040
+ let llptrty = val_ty ( llptrptr) . element_type ( ) ;
1041
+ Store ( bcx, C_null ( llptrty) , llptrptr) ;
1042
+ }
1031
1043
}
1032
1044
}
1033
1045
}
1034
1046
}
1035
1047
1048
+ fn target_sets_discr_via_memset < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ) -> bool {
1049
+ bcx. sess ( ) . target . target . arch == "arm" || bcx. sess ( ) . target . target . arch == "aarch64"
1050
+ }
1051
+
1036
1052
fn assert_discr_in_range ( ity : IntType , min : Disr , max : Disr , discr : Disr ) {
1037
1053
match ity {
1038
1054
attr:: UnsignedInt ( _) => {
0 commit comments