@@ -484,73 +484,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
484
484
fn checked_binop (
485
485
& mut self ,
486
486
oop : OverflowOp ,
487
- ty : Ty < ' _ > ,
487
+ ty : Ty < ' tcx > ,
488
488
lhs : Self :: Value ,
489
489
rhs : Self :: Value ,
490
490
) -> ( Self :: Value , Self :: Value ) {
491
- use rustc_middle:: ty:: IntTy :: * ;
492
- use rustc_middle:: ty:: UintTy :: * ;
493
- use rustc_middle:: ty:: { Int , Uint } ;
494
-
495
- let new_kind = match ty. kind ( ) {
496
- Int ( t @ Isize ) => Int ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
497
- Uint ( t @ Usize ) => Uint ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
498
- t @ ( Uint ( _) | Int ( _) ) => * t,
499
- _ => panic ! ( "tried to get overflow intrinsic for op applied to non-int type" ) ,
500
- } ;
491
+ let ( width, signed) = ty. int_size_and_signed ( self . tcx ) ;
501
492
502
- let name = match oop {
503
- OverflowOp :: Add => match new_kind {
504
- Int ( I8 ) => "llvm.sadd.with.overflow.i8" ,
505
- Int ( I16 ) => "llvm.sadd.with.overflow.i16" ,
506
- Int ( I32 ) => "llvm.sadd.with.overflow.i32" ,
507
- Int ( I64 ) => "llvm.sadd.with.overflow.i64" ,
508
- Int ( I128 ) => "llvm.sadd.with.overflow.i128" ,
509
-
510
- Uint ( U8 ) => "llvm.uadd.with.overflow.i8" ,
511
- Uint ( U16 ) => "llvm.uadd.with.overflow.i16" ,
512
- Uint ( U32 ) => "llvm.uadd.with.overflow.i32" ,
513
- Uint ( U64 ) => "llvm.uadd.with.overflow.i64" ,
514
- Uint ( U128 ) => "llvm.uadd.with.overflow.i128" ,
515
-
516
- _ => unreachable ! ( ) ,
517
- } ,
518
- OverflowOp :: Sub => match new_kind {
519
- Int ( I8 ) => "llvm.ssub.with.overflow.i8" ,
520
- Int ( I16 ) => "llvm.ssub.with.overflow.i16" ,
521
- Int ( I32 ) => "llvm.ssub.with.overflow.i32" ,
522
- Int ( I64 ) => "llvm.ssub.with.overflow.i64" ,
523
- Int ( I128 ) => "llvm.ssub.with.overflow.i128" ,
524
-
525
- Uint ( _) => {
526
- // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
527
- // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
528
- // in the backend if profitable.
529
- let sub = self . sub ( lhs, rhs) ;
530
- let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
531
- return ( sub, cmp) ;
532
- }
493
+ if oop == OverflowOp :: Sub && !signed {
494
+ // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
495
+ // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
496
+ // in the backend if profitable.
497
+ let sub = self . sub ( lhs, rhs) ;
498
+ let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
499
+ return ( sub, cmp) ;
500
+ }
533
501
534
- _ => unreachable ! ( ) ,
535
- } ,
536
- OverflowOp :: Mul => match new_kind {
537
- Int ( I8 ) => "llvm.smul.with.overflow.i8" ,
538
- Int ( I16 ) => "llvm.smul.with.overflow.i16" ,
539
- Int ( I32 ) => "llvm.smul.with.overflow.i32" ,
540
- Int ( I64 ) => "llvm.smul.with.overflow.i64" ,
541
- Int ( I128 ) => "llvm.smul.with.overflow.i128" ,
542
-
543
- Uint ( U8 ) => "llvm.umul.with.overflow.i8" ,
544
- Uint ( U16 ) => "llvm.umul.with.overflow.i16" ,
545
- Uint ( U32 ) => "llvm.umul.with.overflow.i32" ,
546
- Uint ( U64 ) => "llvm.umul.with.overflow.i64" ,
547
- Uint ( U128 ) => "llvm.umul.with.overflow.i128" ,
548
-
549
- _ => unreachable ! ( ) ,
550
- } ,
502
+ let op = match oop {
503
+ OverflowOp :: Add => "add" ,
504
+ OverflowOp :: Sub => "sub" ,
505
+ OverflowOp :: Mul => "mul" ,
551
506
} ;
552
507
553
- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
508
+ let llvm_intrinsic = format ! ( "llvm.{}{op}.with.overflow" , if signed { 's' } else { 'u' } ) ;
509
+
510
+ let res = self . call_intrinsic ( & llvm_intrinsic, & [ self . type_ix ( width. bits ( ) ) ] , & [ lhs, rhs] ) ;
554
511
( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
555
512
}
556
513
@@ -954,11 +911,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
954
911
}
955
912
956
913
fn fptoui_sat ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
957
- self . fptoint_sat ( false , val, dest_ty )
914
+ self . call_intrinsic ( "llvm.fptoui.sat" , & [ dest_ty , self . val_ty ( val) ] , & [ val ] )
958
915
}
959
916
960
917
fn fptosi_sat ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
961
- self . fptoint_sat ( true , val, dest_ty )
918
+ self . call_intrinsic ( "llvm.fptosi.sat" , & [ dest_ty , self . val_ty ( val) ] , & [ val ] )
962
919
}
963
920
964
921
fn fptoui ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
@@ -981,15 +938,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
981
938
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
982
939
let float_width = self . cx . float_width ( src_ty) ;
983
940
let int_width = self . cx . int_width ( dest_ty) ;
984
- let name = match ( int_width, float_width) {
985
- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f32" ) ,
986
- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f64" ) ,
987
- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f32" ) ,
988
- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f64" ) ,
989
- _ => None ,
990
- } ;
991
- if let Some ( name) = name {
992
- return self . call_intrinsic ( name, & [ val] ) ;
941
+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
942
+ return self . call_intrinsic (
943
+ "llvm.wasm.trunc.unsigned" ,
944
+ & [ dest_ty, src_ty] ,
945
+ & [ val] ,
946
+ ) ;
993
947
}
994
948
}
995
949
}
@@ -1003,15 +957,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1003
957
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1004
958
let float_width = self . cx . float_width ( src_ty) ;
1005
959
let int_width = self . cx . int_width ( dest_ty) ;
1006
- let name = match ( int_width, float_width) {
1007
- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.signed.i32.f32" ) ,
1008
- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.signed.i32.f64" ) ,
1009
- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.signed.i64.f32" ) ,
1010
- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.signed.i64.f64" ) ,
1011
- _ => None ,
1012
- } ;
1013
- if let Some ( name) = name {
1014
- return self . call_intrinsic ( name, & [ val] ) ;
960
+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
961
+ return self . call_intrinsic (
962
+ "llvm.wasm.trunc.signed" ,
963
+ & [ dest_ty, src_ty] ,
964
+ & [ val] ,
965
+ ) ;
1015
966
}
1016
967
}
1017
968
}
@@ -1084,22 +1035,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1084
1035
return None ;
1085
1036
}
1086
1037
1087
- let name = match ( ty. is_signed ( ) , ty. primitive_size ( self . tcx ) . bits ( ) ) {
1088
- ( true , 8 ) => "llvm.scmp.i8.i8" ,
1089
- ( true , 16 ) => "llvm.scmp.i8.i16" ,
1090
- ( true , 32 ) => "llvm.scmp.i8.i32" ,
1091
- ( true , 64 ) => "llvm.scmp.i8.i64" ,
1092
- ( true , 128 ) => "llvm.scmp.i8.i128" ,
1093
-
1094
- ( false , 8 ) => "llvm.ucmp.i8.i8" ,
1095
- ( false , 16 ) => "llvm.ucmp.i8.i16" ,
1096
- ( false , 32 ) => "llvm.ucmp.i8.i32" ,
1097
- ( false , 64 ) => "llvm.ucmp.i8.i64" ,
1098
- ( false , 128 ) => "llvm.ucmp.i8.i128" ,
1099
-
1038
+ let ( signed, llty) = match ty. kind ( ) {
1039
+ ty:: Int ( t) => ( true , self . type_int_from_ty ( * t) ) ,
1040
+ ty:: Uint ( t) => ( true , self . type_uint_from_ty ( * t) ) ,
1041
+ ty:: Char => ( true , self . type_i32 ( ) ) ,
1100
1042
_ => bug ! ( "three-way compare unsupported for type {ty:?}" ) ,
1101
1043
} ;
1102
- Some ( self . call_intrinsic ( name, & [ lhs, rhs] ) )
1044
+
1045
+ let llvm_intrinsic = format ! ( "llvm.{}cmp" , if signed { 's' } else { 'u' } ) ;
1046
+ Some ( self . call_intrinsic ( & llvm_intrinsic, & [ self . type_i8 ( ) , llty] , & [ lhs, rhs] ) )
1103
1047
}
1104
1048
1105
1049
/* Miscellaneous instructions */
@@ -1385,11 +1329,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1385
1329
}
1386
1330
1387
1331
fn lifetime_start ( & mut self , ptr : & ' ll Value , size : Size ) {
1388
- self . call_lifetime_intrinsic ( "llvm.lifetime.start.p0i8 " , ptr, size) ;
1332
+ self . call_lifetime_intrinsic ( "llvm.lifetime.start" , ptr, size) ;
1389
1333
}
1390
1334
1391
1335
fn lifetime_end ( & mut self , ptr : & ' ll Value , size : Size ) {
1392
- self . call_lifetime_intrinsic ( "llvm.lifetime.end.p0i8 " , ptr, size) ;
1336
+ self . call_lifetime_intrinsic ( "llvm.lifetime.end" , ptr, size) ;
1393
1337
}
1394
1338
1395
1339
fn call (
@@ -1640,14 +1584,41 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1640
1584
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1641
1585
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1642
1586
}
1643
- }
1644
1587
1645
- impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1646
- pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1647
- let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1648
- self . call ( ty, None , None , f, args, None , None )
1588
+ pub ( crate ) fn simple_call (
1589
+ & mut self ,
1590
+ fn_ty : & ' ll Type ,
1591
+ llfn : & ' ll Value ,
1592
+ args : & [ & ' ll Value ] ,
1593
+ ) -> & ' ll Value {
1594
+ let args = self . check_call ( "simple call" , fn_ty, llfn, args) ;
1595
+
1596
+ unsafe {
1597
+ llvm:: LLVMBuildCall2 (
1598
+ self . llbuilder ,
1599
+ fn_ty,
1600
+ llfn,
1601
+ args. as_ptr ( ) ,
1602
+ args. len ( ) as _ ,
1603
+ c"" . as_ptr ( ) ,
1604
+ )
1605
+ }
1606
+ }
1607
+
1608
+ pub ( crate ) fn call_intrinsic (
1609
+ & mut self ,
1610
+ base_name : & str ,
1611
+ type_params : & [ & ' ll Type ] ,
1612
+ args : & [ & ' ll Value ] ,
1613
+ ) -> & ' ll Value {
1614
+ let intrinsic = llvm:: Intrinsic :: lookup ( base_name. as_bytes ( ) )
1615
+ . unwrap_or_else ( || bug ! ( "Intrinsic `{base_name}` not found" ) ) ;
1616
+ let ( fn_ty, llfn) = self . cx . get_intrinsic ( intrinsic, type_params) ;
1617
+ self . simple_call ( fn_ty, llfn, args)
1649
1618
}
1619
+ }
1650
1620
1621
+ impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1651
1622
fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
1652
1623
let size = size. bytes ( ) ;
1653
1624
if size == 0 {
@@ -1658,7 +1629,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1658
1629
return ;
1659
1630
}
1660
1631
1661
- self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1632
+ self . call_intrinsic ( intrinsic, & [ self . type_ptr ( ) ] , & [ self . cx . const_u64 ( size) , ptr] ) ;
1662
1633
}
1663
1634
}
1664
1635
impl < ' a , ' ll , CX : Borrow < SCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
@@ -1683,29 +1654,24 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1683
1654
}
1684
1655
}
1685
1656
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1686
- fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
1687
- let src_ty = self . cx . val_ty ( val) ;
1688
- let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
1689
- assert_eq ! ( self . cx. vector_length( src_ty) , self . cx. vector_length( dest_ty) ) ;
1690
- (
1691
- self . cx . element_type ( src_ty) ,
1692
- self . cx . element_type ( dest_ty) ,
1693
- Some ( self . cx . vector_length ( src_ty) ) ,
1694
- )
1695
- } else {
1696
- ( src_ty, dest_ty, None )
1657
+ pub ( crate ) fn memcmp (
1658
+ & mut self ,
1659
+ ptr1 : & ' ll Value ,
1660
+ ptr2 : & ' ll Value ,
1661
+ num : & ' ll Value ,
1662
+ ) -> & ' ll Value {
1663
+ let llreturn_ty = match self . sess ( ) . target . arch . as_ref ( ) {
1664
+ "avr" | "msp430" => self . type_i16 ( ) ,
1665
+ _ => self . type_i32 ( ) ,
1697
1666
} ;
1698
- let float_width = self . cx . float_width ( float_ty ) ;
1699
- let int_width = self . cx . int_width ( int_ty ) ;
1667
+ let fn_ty =
1668
+ self . type_func ( & [ self . type_ptr ( ) , self . type_ptr ( ) , self . type_isize ( ) ] , llreturn_ty ) ;
1700
1669
1701
- let instr = if signed { "fptosi" } else { "fptoui" } ;
1702
- let name = if let Some ( vector_length) = vector_length {
1703
- format ! ( "llvm.{instr}.sat.v{vector_length}i{int_width}.v{vector_length}f{float_width}" )
1704
- } else {
1705
- format ! ( "llvm.{instr}.sat.i{int_width}.f{float_width}" )
1706
- } ;
1707
- let f = self . declare_cfn ( & name, llvm:: UnnamedAddr :: No , self . type_func ( & [ src_ty] , dest_ty) ) ;
1708
- self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
1670
+ let llfn = self
1671
+ . get_function ( "memcmp" )
1672
+ . unwrap_or_else ( || self . declare_cfn ( "memcmp" , llvm:: UnnamedAddr :: No , fn_ty) ) ;
1673
+
1674
+ self . simple_call ( fn_ty, llfn, & [ ptr1, ptr2, num] )
1709
1675
}
1710
1676
1711
1677
pub ( crate ) fn landing_pad (
@@ -1878,7 +1844,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1878
1844
num_counters : & ' ll Value ,
1879
1845
index : & ' ll Value ,
1880
1846
) {
1881
- self . call_intrinsic ( "llvm.instrprof.increment" , & [ fn_name, hash, num_counters, index] ) ;
1847
+ self . call_intrinsic ( "llvm.instrprof.increment" , & [ ] , & [ fn_name, hash, num_counters, index] ) ;
1882
1848
}
1883
1849
1884
1850
/// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1897,7 +1863,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1897
1863
hash : & ' ll Value ,
1898
1864
bitmap_bits : & ' ll Value ,
1899
1865
) {
1900
- self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ fn_name, hash, bitmap_bits] ) ;
1866
+ self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ ] , & [ fn_name, hash, bitmap_bits] ) ;
1901
1867
}
1902
1868
1903
1869
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -1909,7 +1875,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1909
1875
mcdc_temp : & ' ll Value ,
1910
1876
) {
1911
1877
let args = & [ fn_name, hash, bitmap_index, mcdc_temp] ;
1912
- self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , args) ;
1878
+ self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , & [ ] , args) ;
1913
1879
}
1914
1880
1915
1881
#[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments