@@ -240,6 +240,7 @@ enum Value<'tcx> {
240240 from : Ty < ' tcx > ,
241241 to : Ty < ' tcx > ,
242242 } ,
243+ WrapUnsafeBinder ( VnIndex , Ty < ' tcx > ) ,
243244}
244245
245246struct VnState < ' body , ' tcx > {
@@ -580,36 +581,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
580581 let res = self . ecx . float_to_float_or_int ( & value, to) . discard_err ( ) ?;
581582 res. into ( )
582583 }
583- CastKind :: Transmute => {
584- let value = self . evaluated [ value] . as_ref ( ) ?;
585- let to = self . ecx . layout_of ( to) . ok ( ) ?;
586- // `offset` for immediates generally only supports projections that match the
587- // type of the immediate. However, as a HACK, we exploit that it can also do
588- // limited transmutes: it only works between types with the same layout, and
589- // cannot transmute pointers to integers.
590- if value. as_mplace_or_imm ( ) . is_right ( ) {
591- let can_transmute = match ( value. layout . backend_repr , to. backend_repr ) {
592- ( BackendRepr :: Scalar ( s1) , BackendRepr :: Scalar ( s2) ) => {
593- s1. size ( & self . ecx ) == s2. size ( & self . ecx )
594- && !matches ! ( s1. primitive( ) , Primitive :: Pointer ( ..) )
595- }
596- ( BackendRepr :: ScalarPair ( a1, b1) , BackendRepr :: ScalarPair ( a2, b2) ) => {
597- a1. size ( & self . ecx ) == a2. size ( & self . ecx ) &&
598- b1. size ( & self . ecx ) == b2. size ( & self . ecx ) &&
599- // The alignment of the second component determines its offset, so that also needs to match.
600- b1. align ( & self . ecx ) == b2. align ( & self . ecx ) &&
601- // None of the inputs may be a pointer.
602- !matches ! ( a1. primitive( ) , Primitive :: Pointer ( ..) )
603- && !matches ! ( b1. primitive( ) , Primitive :: Pointer ( ..) )
604- }
605- _ => false ,
606- } ;
607- if !can_transmute {
608- return None ;
609- }
610- }
611- value. offset ( Size :: ZERO , to, & self . ecx ) . discard_err ( ) ?
612- }
584+ CastKind :: Transmute => self . transmute ( value, to) ?,
613585 CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize , _) => {
614586 let src = self . evaluated [ value] . as_ref ( ) ?;
615587 let to = self . ecx . layout_of ( to) . ok ( ) ?;
@@ -635,10 +607,38 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
635607 }
636608 _ => return None ,
637609 } ,
610+ WrapUnsafeBinder ( value, ty) => self . transmute ( value, ty) ?,
638611 } ;
639612 Some ( op)
640613 }
641614
615+ fn transmute ( & mut self , value : VnIndex , to : Ty < ' tcx > ) -> Option < OpTy < ' tcx > > {
616+ let value = self . evaluated [ value] . as_ref ( ) ?;
617+ let to = self . ecx . layout_of ( to) . ok ( ) ?;
618+ if value. as_mplace_or_imm ( ) . is_right ( ) {
619+ let can_transmute = match ( value. layout . backend_repr , to. backend_repr ) {
620+ ( BackendRepr :: Scalar ( s1) , BackendRepr :: Scalar ( s2) ) => {
621+ s1. size ( & self . ecx ) == s2. size ( & self . ecx )
622+ && !matches ! ( s1. primitive( ) , Primitive :: Pointer ( ..) )
623+ }
624+ ( BackendRepr :: ScalarPair ( a1, b1) , BackendRepr :: ScalarPair ( a2, b2) ) => {
625+ a1. size ( & self . ecx ) == a2. size ( & self . ecx ) &&
626+ b1. size ( & self . ecx ) == b2. size ( & self . ecx ) &&
627+ // The alignment of the second component determines its offset, so that also needs to match.
628+ b1. align ( & self . ecx ) == b2. align ( & self . ecx ) &&
629+ // None of the inputs may be a pointer.
630+ !matches ! ( a1. primitive( ) , Primitive :: Pointer ( ..) )
631+ && !matches ! ( b1. primitive( ) , Primitive :: Pointer ( ..) )
632+ }
633+ _ => false ,
634+ } ;
635+ if !can_transmute {
636+ return None ;
637+ }
638+ }
639+ Some ( value. offset ( Size :: ZERO , to, & self . ecx ) . discard_err ( ) ?)
640+ }
641+
642642 fn project (
643643 & mut self ,
644644 place : PlaceRef < ' tcx > ,
@@ -872,8 +872,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
872872 self . simplify_place_projection ( place, location) ;
873873 return self . new_pointer ( * place, AddressKind :: Address ( mutbl) ) ;
874874 }
875- Rvalue :: WrapUnsafeBinder ( ref mut op, _) => {
876- return self . simplify_operand ( op, location) ;
875+ Rvalue :: WrapUnsafeBinder ( ref mut op, ty) => {
876+ let value = self . simplify_operand ( op, location) ?;
877+ Value :: WrapUnsafeBinder ( value, ty)
877878 }
878879
879880 // Operations.
0 commit comments