@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Ty};
14
14
use rustc_target:: callconv:: { ArgAbi , ArgAttributes , FnAbi , PassMode } ;
15
15
use rustc_type_ir:: { Interner , TyKind } ;
16
16
17
- use crate :: builder:: { Builder , ToGccComp } ;
17
+ use crate :: builder:: { Builder , ShiftKind , ToGccComp } ;
18
18
use crate :: common:: { SignType , TypeReflection } ;
19
19
use crate :: context:: CodegenCx ;
20
20
@@ -68,36 +68,59 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
68
68
self . cx . bitwise_operation ( BinaryOp :: BitwiseAnd , a, b, self . location )
69
69
}
70
70
71
- pub fn gcc_lshr ( & mut self , a : RValue < ' gcc > , b : RValue < ' gcc > ) -> RValue < ' gcc > {
71
+ pub fn gcc_shr (
72
+ & mut self ,
73
+ a : RValue < ' gcc > ,
74
+ b : RValue < ' gcc > ,
75
+ shift_kind : ShiftKind ,
76
+ ) -> RValue < ' gcc > {
72
77
let a_type = a. get_type ( ) ;
73
78
let b_type = b. get_type ( ) ;
74
79
let a_native = self . is_native_int_type ( a_type) ;
75
80
let b_native = self . is_native_int_type ( b_type) ;
76
81
if a_native && b_native {
77
- // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by a signed number.
78
- // TODO(antoyo): cast to unsigned to do a logical shift if that does not work.
79
- if a_type. is_signed ( self ) != b_type. is_signed ( self ) {
80
- let b = self . context . new_cast ( self . location , b, a_type) ;
81
- a >> b
82
- } else {
83
- let a_size = a_type. get_size ( ) ;
84
- let b_size = b_type. get_size ( ) ;
85
- match a_size. cmp ( & b_size) {
86
- std:: cmp:: Ordering :: Less => {
87
- let a = self . context . new_cast ( self . location , a, b_type) ;
88
- a >> b
89
- }
90
- std:: cmp:: Ordering :: Equal => a >> b,
91
- std:: cmp:: Ordering :: Greater => {
92
- let b = self . context . new_cast ( self . location , b, a_type) ;
93
- a >> b
94
- }
82
+ let ( a, a_type) = match ( shift_kind, a_type. is_signed ( self . cx ) ) {
83
+ ( ShiftKind :: Logical , true ) => {
84
+ let a_type = a_type. to_unsigned ( self . cx ) ;
85
+ ( self . gcc_int_cast ( a, a_type) , a_type)
86
+ }
87
+ ( ShiftKind :: Logical , false ) => ( a, a_type) ,
88
+ ( ShiftKind :: Arithmetic , true ) => ( a, a_type) ,
89
+ ( ShiftKind :: Arithmetic , false ) => {
90
+ let a_type = a_type. to_signed ( self . cx ) ;
91
+ ( self . gcc_int_cast ( a, a_type) , a_type)
92
+ }
93
+ } ;
94
+ let ( b, b_type) = match ( shift_kind, b_type. is_signed ( self . cx ) ) {
95
+ ( ShiftKind :: Logical , true ) => {
96
+ let b_type = b_type. to_unsigned ( self . cx ) ;
97
+ ( self . gcc_int_cast ( b, b_type) , b_type)
98
+ }
99
+ ( ShiftKind :: Logical , false ) => ( b, b_type) ,
100
+ ( ShiftKind :: Arithmetic , true ) => ( b, b_type) ,
101
+ ( ShiftKind :: Arithmetic , false ) => {
102
+ let b_type = b_type. to_signed ( self . cx ) ;
103
+ ( self . gcc_int_cast ( b, b_type) , b_type)
104
+ }
105
+ } ;
106
+
107
+ let a_size = a_type. get_size ( ) ;
108
+ let b_size = b_type. get_size ( ) ;
109
+ match a_size. cmp ( & b_size) {
110
+ std:: cmp:: Ordering :: Less => {
111
+ let a = self . context . new_cast ( self . location , a, b_type) ;
112
+ a >> b
113
+ }
114
+ std:: cmp:: Ordering :: Equal => a >> b,
115
+ std:: cmp:: Ordering :: Greater => {
116
+ let b = self . context . new_cast ( self . location , b, a_type) ;
117
+ a >> b
95
118
}
96
119
}
97
120
} else if a_type. is_vector ( ) && b_type. is_vector ( ) {
98
121
a >> b
99
122
} else if a_native && !b_native {
100
- self . gcc_lshr ( a, self . gcc_int_cast ( b, a_type) )
123
+ self . gcc_shr ( a, self . gcc_int_cast ( b, a_type) , shift_kind )
101
124
} else {
102
125
// NOTE: we cannot use the lshr builtin because it's calling hi() (to get the most
103
126
// significant half of the number) which uses lshr.
@@ -122,7 +145,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
122
145
123
146
let shift_value = self . gcc_sub ( b, sixty_four) ;
124
147
let high = self . high ( a) ;
125
- let sign = if a_type. is_signed ( self ) { high >> sixty_three } else { zero } ;
148
+ let sign = match shift_kind{
149
+ ShiftKind :: Logical => zero,
150
+ ShiftKind :: Arithmetic => high >> sixty_three,
151
+ } ;
126
152
let array_value = self . concat_low_high_rvalues ( a_type, high >> shift_value, sign) ;
127
153
then_block. add_assignment ( self . location , result, array_value) ;
128
154
then_block. end_with_jump ( self . location , after_block) ;
0 commit comments