@@ -69,32 +69,30 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
69
69
match bin_op {
70
70
// can have rhs with a different numeric type
71
71
Shl | Shr => {
72
- // these numbers are the maximum number of bits a bitshift rhs could possibly have
73
- // e.g. u16 can be bitshifted by 0..16, so 2^4 - 1 is the largest possible bitshift
74
- let mask_bits = match left {
75
- I8 ( _) => 3 ,
76
- I16 ( _) => 4 ,
77
- I32 ( _) => 5 ,
78
- I64 ( _) => 6 ,
79
- U8 ( _) => 3 ,
80
- U16 ( _) => 4 ,
81
- U32 ( _) => 5 ,
82
- U64 ( _) => 6 ,
72
+ // these numbers are the maximum number a bitshift rhs could possibly have
73
+ // e.g. u16 can be bitshifted by 0..16, so masking with 0b1111 (16 - 1) will ensure we are in that range
74
+ let type_bits: u32 = match left {
75
+ I8 ( _) | U8 ( _) => 8 ,
76
+ I16 ( _) | U16 ( _) => 16 ,
77
+ I32 ( _) | U32 ( _) => 32 ,
78
+ I64 ( _) | U64 ( _) => 64 ,
83
79
_ => unreachable ! ( ) ,
84
80
} ;
85
- let mask = ( 1 << mask_bits) - 1 ;
81
+ assert ! ( type_bits. is_power_of_two( ) ) ;
82
+ // turn into `u32` because `overflowing_sh{l,r}` only take `u32`
86
83
let r = match right {
87
- I8 ( i) => i as u8 & mask ,
88
- I16 ( i) => i as u8 & mask ,
89
- I32 ( i) => i as u8 & mask ,
90
- I64 ( i) => i as u8 & mask ,
91
- U8 ( i) => i as u8 & mask ,
92
- U16 ( i) => i as u8 & mask ,
93
- U32 ( i) => i as u8 & mask ,
94
- U64 ( i) => i as u8 & mask ,
84
+ I8 ( i) => i as u32 ,
85
+ I16 ( i) => i as u32 ,
86
+ I32 ( i) => i as u32 ,
87
+ I64 ( i) => i as u32 ,
88
+ U8 ( i) => i as u32 ,
89
+ U16 ( i) => i as u32 ,
90
+ U32 ( i) => i as u32 ,
91
+ U64 ( i) => i as u32 ,
95
92
_ => panic ! ( "bad MIR: bitshift rhs is not integral" ) ,
96
93
} ;
97
- let r = r as u32 ;
94
+ // apply mask
95
+ let r = r & ( type_bits - 1 ) ;
98
96
macro_rules! shift {
99
97
( $v: ident, $l: ident, $r: ident) => ( {
100
98
match bin_op {
0 commit comments