@@ -240,6 +240,7 @@ enum Value<'tcx> {
240
240
from : Ty < ' tcx > ,
241
241
to : Ty < ' tcx > ,
242
242
} ,
243
+ WrapUnsafeBinder ( VnIndex , Ty < ' tcx > ) ,
243
244
}
244
245
245
246
struct VnState < ' body , ' tcx > {
@@ -580,36 +581,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
580
581
let res = self . ecx . float_to_float_or_int ( & value, to) . discard_err ( ) ?;
581
582
res. into ( )
582
583
}
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) ?,
613
585
CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize , _) => {
614
586
let src = self . evaluated [ value] . as_ref ( ) ?;
615
587
let to = self . ecx . layout_of ( to) . ok ( ) ?;
@@ -635,10 +607,38 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
635
607
}
636
608
_ => return None ,
637
609
} ,
610
+ WrapUnsafeBinder ( value, ty) => self . transmute ( value, ty) ?,
638
611
} ;
639
612
Some ( op)
640
613
}
641
614
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
+
642
642
fn project (
643
643
& mut self ,
644
644
place : PlaceRef < ' tcx > ,
@@ -872,8 +872,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
872
872
self . simplify_place_projection ( place, location) ;
873
873
return self . new_pointer ( * place, AddressKind :: Address ( mutbl) ) ;
874
874
}
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)
877
878
}
878
879
879
880
// Operations.
0 commit comments