@@ -55,7 +55,7 @@ use syntax::attr;
5555use syntax:: attr:: IntType ;
5656use _match;
5757use abi:: FAT_PTR_ADDR ;
58- use base:: InitAlloca ;
58+ use base:: { self , InitAlloca } ;
5959use build:: * ;
6060use cleanup;
6161use cleanup:: CleanupMethods ;
@@ -1023,16 +1023,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
10231023 Store ( bcx, C_null ( llptrty) , val) ;
10241024 }
10251025 }
1026- StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
1026+ StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull , .. } => {
10271027 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+ }
10311043 }
10321044 }
10331045 }
10341046}
10351047
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+
10361052fn assert_discr_in_range ( ity : IntType , min : Disr , max : Disr , discr : Disr ) {
10371053 match ity {
10381054 attr:: UnsignedInt ( _) => {
0 commit comments