4
4
5
5
// cSpell:words cmpti divti modti mulodi muloti udivti umodti
6
6
7
- use gccjit:: { BinaryOp , ComparisonOp , FunctionType , Location , RValue , ToRValue , Type , UnaryOp } ;
7
+ use gccjit:: {
8
+ BinaryOp , CType , ComparisonOp , FunctionType , Location , RValue , ToRValue , Type , UnaryOp ,
9
+ } ;
8
10
use rustc_abi:: { CanonAbi , Endian , ExternAbi } ;
9
11
use rustc_codegen_ssa:: common:: { IntPredicate , TypeKind } ;
10
12
use rustc_codegen_ssa:: traits:: { BackendTypes , BaseTypeCodegenMethods , BuilderMethods , OverflowOp } ;
11
13
use rustc_middle:: ty:: { self , Ty } ;
12
14
use rustc_target:: callconv:: { ArgAbi , ArgAttributes , FnAbi , PassMode } ;
15
+ use rustc_type_ir:: { Interner , TyKind } ;
13
16
14
17
use crate :: builder:: { Builder , ToGccComp } ;
15
18
use crate :: common:: { SignType , TypeReflection } ;
@@ -167,9 +170,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
167
170
if a_type. is_vector ( ) {
168
171
// Vector types need to be bitcast.
169
172
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
170
- b = self . context . new_bitcast ( self . ___location , b, a . get_type ( ) ) ;
173
+ b = self . context . new_bitcast ( self . ___location , b, a_type ) ;
171
174
} else {
172
- b = self . context . new_cast ( self . ___location , b, a . get_type ( ) ) ;
175
+ b = self . context . new_cast ( self . ___location , b, a_type ) ;
173
176
}
174
177
}
175
178
self . context . new_binary_op ( self . ___location , operation, a_type, a, b)
@@ -216,13 +219,22 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
216
219
operation_name : & str ,
217
220
signed : bool ,
218
221
a : RValue < ' gcc > ,
219
- b : RValue < ' gcc > ,
222
+ mut b : RValue < ' gcc > ,
220
223
) -> RValue < ' gcc > {
221
224
let a_type = a. get_type ( ) ;
222
225
let b_type = b. get_type ( ) ;
223
226
if ( self . is_native_int_type_or_bool ( a_type) && self . is_native_int_type_or_bool ( b_type) )
224
227
|| ( a_type. is_vector ( ) && b_type. is_vector ( ) )
225
228
{
229
+ if !a_type. is_compatible_with ( b_type) {
230
+ if a_type. is_vector ( ) {
231
+ // Vector types need to be bitcast.
232
+ // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
233
+ b = self . context . new_bitcast ( self . ___location , b, a_type) ;
234
+ } else {
235
+ b = self . context . new_cast ( self . ___location , b, a_type) ;
236
+ }
237
+ }
226
238
self . context . new_binary_op ( self . ___location , operation, a_type, a, b)
227
239
} else {
228
240
debug_assert ! ( a_type. dyncast_array( ) . is_some( ) ) ;
@@ -351,6 +363,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
351
363
// TODO(antoyo): is it correct to use rhs type instead of the parameter typ?
352
364
. new_local ( self . ___location , rhs. get_type ( ) , "binopResult" )
353
365
. get_address ( self . ___location ) ;
366
+ let new_type = type_kind_to_gcc_type ( new_kind) ;
367
+ let new_type = self . context . new_c_type ( new_type) ;
368
+ let lhs = self . context . new_cast ( self . ___location , lhs, new_type) ;
369
+ let rhs = self . context . new_cast ( self . ___location , rhs, new_type) ;
370
+ let res = self . context . new_cast ( self . ___location , res, new_type. make_pointer ( ) ) ;
354
371
let overflow = self . overflow_call ( intrinsic, & [ lhs, rhs, res] , None ) ;
355
372
( res. dereference ( self . ___location ) . to_rvalue ( ) , overflow)
356
373
}
@@ -477,11 +494,27 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
477
494
let lhs_low = self . context . new_cast ( self . ___location , self . low ( lhs) , unsigned_type) ;
478
495
let rhs_low = self . context . new_cast ( self . ___location , self . low ( rhs) , unsigned_type) ;
479
496
497
+ let mut lhs_high = self . high ( lhs) ;
498
+ let mut rhs_high = self . high ( rhs) ;
499
+
500
+ match op {
501
+ IntPredicate :: IntUGT
502
+ | IntPredicate :: IntUGE
503
+ | IntPredicate :: IntULT
504
+ | IntPredicate :: IntULE => {
505
+ lhs_high = self . context . new_cast ( self . ___location , lhs_high, unsigned_type) ;
506
+ rhs_high = self . context . new_cast ( self . ___location , rhs_high, unsigned_type) ;
507
+ }
508
+ // TODO(antoyo): we probably need to handle signed comparison for unsigned
509
+ // integers.
510
+ _ => ( ) ,
511
+ }
512
+
480
513
let condition = self . context . new_comparison (
481
514
self . ___location ,
482
515
ComparisonOp :: LessThan ,
483
- self . high ( lhs ) ,
484
- self . high ( rhs ) ,
516
+ lhs_high ,
517
+ rhs_high ,
485
518
) ;
486
519
self . llbb ( ) . end_with_conditional ( self . ___location , condition, block1, block2) ;
487
520
@@ -495,8 +528,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
495
528
let condition = self . context . new_comparison (
496
529
self . ___location ,
497
530
ComparisonOp :: GreaterThan ,
498
- self . high ( lhs ) ,
499
- self . high ( rhs ) ,
531
+ lhs_high ,
532
+ rhs_high ,
500
533
) ;
501
534
block2. end_with_conditional ( self . ___location , condition, block3, block4) ;
502
535
@@ -620,14 +653,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
620
653
}
621
654
}
622
655
623
- pub fn gcc_xor ( & self , a : RValue < ' gcc > , b : RValue < ' gcc > ) -> RValue < ' gcc > {
656
+ pub fn gcc_xor ( & self , a : RValue < ' gcc > , mut b : RValue < ' gcc > ) -> RValue < ' gcc > {
624
657
let a_type = a. get_type ( ) ;
625
658
let b_type = b. get_type ( ) ;
626
659
if a_type. is_vector ( ) && b_type. is_vector ( ) {
627
660
let b = self . bitcast_if_needed ( b, a_type) ;
628
661
a ^ b
629
662
} else if self . is_native_int_type_or_bool ( a_type) && self . is_native_int_type_or_bool ( b_type)
630
663
{
664
+ if !a_type. is_compatible_with ( b_type) {
665
+ b = self . context . new_cast ( self . ___location , b, a_type) ;
666
+ }
631
667
a ^ b
632
668
} else {
633
669
self . concat_low_high_rvalues (
@@ -1042,3 +1078,25 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
1042
1078
self . context . new_array_constructor ( None , typ, & values)
1043
1079
}
1044
1080
}
1081
+
1082
+ fn type_kind_to_gcc_type < I : Interner > ( kind : TyKind < I > ) -> CType {
1083
+ use rustc_middle:: ty:: IntTy :: * ;
1084
+ use rustc_middle:: ty:: UintTy :: * ;
1085
+ use rustc_middle:: ty:: { Int , Uint } ;
1086
+
1087
+ match kind {
1088
+ Int ( I8 ) => CType :: Int8t ,
1089
+ Int ( I16 ) => CType :: Int16t ,
1090
+ Int ( I32 ) => CType :: Int32t ,
1091
+ Int ( I64 ) => CType :: Int64t ,
1092
+ Int ( I128 ) => CType :: Int128t ,
1093
+
1094
+ Uint ( U8 ) => CType :: UInt8t ,
1095
+ Uint ( U16 ) => CType :: UInt16t ,
1096
+ Uint ( U32 ) => CType :: UInt32t ,
1097
+ Uint ( U64 ) => CType :: UInt64t ,
1098
+ Uint ( U128 ) => CType :: UInt128t ,
1099
+
1100
+ _ => unimplemented ! ( "Kind: {:?}" , kind) ,
1101
+ }
1102
+ }
0 commit comments