@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Ty};
1414use rustc_target:: callconv:: { ArgAbi , ArgAttributes , FnAbi , PassMode } ;
1515use rustc_type_ir:: { Interner , TyKind } ;
1616
17- use crate :: builder:: { Builder , ToGccComp } ;
17+ use crate :: builder:: { Builder , ShiftKind , ToGccComp } ;
1818use crate :: common:: { SignType , TypeReflection } ;
1919use crate :: context:: CodegenCx ;
2020
@@ -68,36 +68,59 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
6868 self . cx . bitwise_operation ( BinaryOp :: BitwiseAnd , a, b, self . location )
6969 }
7070
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 > {
7277 let a_type = a. get_type ( ) ;
7378 let b_type = b. get_type ( ) ;
7479 let a_native = self . is_native_int_type ( a_type) ;
7580 let b_native = self . is_native_int_type ( b_type) ;
7681 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
95118 }
96119 }
97120 } else if a_type. is_vector ( ) && b_type. is_vector ( ) {
98121 a >> b
99122 } 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 )
101124 } else {
102125 // NOTE: we cannot use the lshr builtin because it's calling hi() (to get the most
103126 // significant half of the number) which uses lshr.
@@ -122,7 +145,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
122145
123146 let shift_value = self . gcc_sub ( b, sixty_four) ;
124147 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+ } ;
126152 let array_value = self . concat_low_high_rvalues ( a_type, high >> shift_value, sign) ;
127153 then_block. add_assignment ( self . location , result, array_value) ;
128154 then_block. end_with_jump ( self . location , after_block) ;
0 commit comments