@@ -54,6 +54,7 @@ use syntax::ast;
5454use syntax:: attr;
5555use syntax:: attr:: IntType ;
5656use abi:: FAT_PTR_ADDR ;
57+ use base;
5758use build:: * ;
5859use common:: * ;
5960use debuginfo:: DebugLoc ;
@@ -963,16 +964,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
963964 Store ( bcx, C_null ( llptrty) , val) ;
964965 }
965966 }
966- StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
967+ StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull , .. } => {
967968 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+ }
971984 }
972985 }
973986 }
974987}
975988
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+
976993fn assert_discr_in_range ( ity : IntType , min : Disr , max : Disr , discr : Disr ) {
977994 match ity {
978995 attr:: UnsignedInt ( _) => {
0 commit comments