@@ -54,6 +54,7 @@ use syntax::ast;
54
54
use syntax:: attr;
55
55
use syntax:: attr:: IntType ;
56
56
use abi:: FAT_PTR_ADDR ;
57
+ use base;
57
58
use build:: * ;
58
59
use common:: * ;
59
60
use debuginfo:: DebugLoc ;
@@ -963,16 +964,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
963
964
Store ( bcx, C_null ( llptrty) , val) ;
964
965
}
965
966
}
966
- StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
967
+ StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull , .. } => {
967
968
if discr != nndiscr {
968
- let llptrptr = GEPi ( bcx, val, & discrfield[ ..] ) ;
969
- let llptrty = val_ty ( llptrptr) . element_type ( ) ;
970
- Store ( bcx, C_null ( llptrty) , llptrptr) ;
969
+ if target_sets_discr_via_memset ( bcx) {
970
+ // Issue #34427: As workaround for LLVM bug on
971
+ // ARM, use memset of 0 on whole struct rather
972
+ // than storing null to single target field.
973
+ let b = B ( bcx) ;
974
+ let llptr = b. pointercast ( val, Type :: i8 ( b. ccx ) . ptr_to ( ) ) ;
975
+ let fill_byte = C_u8 ( b. ccx , 0 ) ;
976
+ let size = C_uint ( b. ccx , nonnull. size ) ;
977
+ let align = C_i32 ( b. ccx , nonnull. align as i32 ) ;
978
+ base:: call_memset ( & b, llptr, fill_byte, size, align, false ) ;
979
+ } else {
980
+ let llptrptr = GEPi ( bcx, val, & discrfield[ ..] ) ;
981
+ let llptrty = val_ty ( llptrptr) . element_type ( ) ;
982
+ Store ( bcx, C_null ( llptrty) , llptrptr) ;
983
+ }
971
984
}
972
985
}
973
986
}
974
987
}
975
988
989
+ fn target_sets_discr_via_memset < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ) -> bool {
990
+ bcx. sess ( ) . target . target . arch == "arm" || bcx. sess ( ) . target . target . arch == "aarch64"
991
+ }
992
+
976
993
fn assert_discr_in_range ( ity : IntType , min : Disr , max : Disr , discr : Disr ) {
977
994
match ity {
978
995
attr:: UnsignedInt ( _) => {
0 commit comments