@@ -67,7 +67,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
67
67
) -> & ' ll Value {
68
68
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
69
69
70
- let args = self . cast_arguments ( "call" , llty, llfn, args) ;
71
70
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
72
71
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
73
72
if let Some ( funclet_bundle) = funclet_bundle {
@@ -105,21 +104,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
105
104
let vector_type = self . cx . val_ty ( val) ;
106
105
107
106
assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
108
-
109
- let intrinsic = llvm:: Intrinsic :: lookup ( b"llvm.x86.cast.vector.to.tile" . as_ref ( ) ) . unwrap ( ) ;
110
- let ( fn_ty, f) = self . cx . get_or_declare_intrinsic ( intrinsic, & [ vector_type] ) ;
111
- unsafe {
112
- llvm:: LLVMBuildCallWithOperandBundles (
113
- self . llbuilder ,
114
- fn_ty,
115
- f,
116
- [ val] . as_ptr ( ) . cast ( ) ,
117
- 1 ,
118
- [ ] . as_ptr ( ) ,
119
- 0 ,
120
- c"" . as_ptr ( ) ,
121
- )
122
- }
107
+ self . call_intrinsic ( "llvm.x86.cast.vector.to.tile" , & [ vector_type] , & [ val] )
123
108
}
124
109
125
110
pub ( crate ) fn cast_tile_to_vector (
@@ -130,20 +115,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
130
115
assert ! ( self . cx. val_ty( val) == self . cx. type_x86amx( ) ) ;
131
116
assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
132
117
133
- let intrinsic = llvm:: Intrinsic :: lookup ( b"llvm.x86.cast.tile.to.vector" ) . unwrap ( ) ;
134
- let ( fn_ty, f) = self . cx . get_or_declare_intrinsic ( intrinsic, & [ vector_type] ) ;
135
- unsafe {
136
- llvm:: LLVMBuildCallWithOperandBundles (
137
- self . llbuilder ,
138
- fn_ty,
139
- f,
140
- [ val] . as_ptr ( ) . cast ( ) ,
141
- 1 ,
142
- [ ] . as_ptr ( ) ,
143
- 0 ,
144
- c"" . as_ptr ( ) ,
145
- )
146
- }
118
+ self . call_intrinsic ( "llvm.x86.cast.tile.to.vector" , & [ vector_type] , & [ val] )
147
119
}
148
120
149
121
pub ( crate ) fn ret_void ( & mut self ) {
@@ -531,73 +503,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
531
503
fn checked_binop (
532
504
& mut self ,
533
505
oop : OverflowOp ,
534
- ty : Ty < ' _ > ,
506
+ ty : Ty < ' tcx > ,
535
507
lhs : Self :: Value ,
536
508
rhs : Self :: Value ,
537
509
) -> ( Self :: Value , Self :: Value ) {
538
- use rustc_middle:: ty:: IntTy :: * ;
539
- use rustc_middle:: ty:: UintTy :: * ;
540
- use rustc_middle:: ty:: { Int , Uint } ;
541
-
542
- let new_kind = match ty. kind ( ) {
543
- Int ( t @ Isize ) => Int ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
544
- Uint ( t @ Usize ) => Uint ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
545
- t @ ( Uint ( _) | Int ( _) ) => * t,
546
- _ => panic ! ( "tried to get overflow intrinsic for op applied to non-int type" ) ,
547
- } ;
510
+ let ( width, signed) = ty. int_size_and_signed ( self . tcx ) ;
548
511
549
- let name = match oop {
550
- OverflowOp :: Add => match new_kind {
551
- Int ( I8 ) => "llvm.sadd.with.overflow.i8" ,
552
- Int ( I16 ) => "llvm.sadd.with.overflow.i16" ,
553
- Int ( I32 ) => "llvm.sadd.with.overflow.i32" ,
554
- Int ( I64 ) => "llvm.sadd.with.overflow.i64" ,
555
- Int ( I128 ) => "llvm.sadd.with.overflow.i128" ,
556
-
557
- Uint ( U8 ) => "llvm.uadd.with.overflow.i8" ,
558
- Uint ( U16 ) => "llvm.uadd.with.overflow.i16" ,
559
- Uint ( U32 ) => "llvm.uadd.with.overflow.i32" ,
560
- Uint ( U64 ) => "llvm.uadd.with.overflow.i64" ,
561
- Uint ( U128 ) => "llvm.uadd.with.overflow.i128" ,
562
-
563
- _ => unreachable ! ( ) ,
564
- } ,
565
- OverflowOp :: Sub => match new_kind {
566
- Int ( I8 ) => "llvm.ssub.with.overflow.i8" ,
567
- Int ( I16 ) => "llvm.ssub.with.overflow.i16" ,
568
- Int ( I32 ) => "llvm.ssub.with.overflow.i32" ,
569
- Int ( I64 ) => "llvm.ssub.with.overflow.i64" ,
570
- Int ( I128 ) => "llvm.ssub.with.overflow.i128" ,
571
-
572
- Uint ( _) => {
573
- // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
574
- // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
575
- // in the backend if profitable.
576
- let sub = self . sub ( lhs, rhs) ;
577
- let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
578
- return ( sub, cmp) ;
579
- }
512
+ if oop == OverflowOp :: Sub && !signed {
513
+ // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
514
+ // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
515
+ // in the backend if profitable.
516
+ let sub = self . sub ( lhs, rhs) ;
517
+ let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
518
+ return ( sub, cmp) ;
519
+ }
580
520
581
- _ => unreachable ! ( ) ,
582
- } ,
583
- OverflowOp :: Mul => match new_kind {
584
- Int ( I8 ) => "llvm.smul.with.overflow.i8" ,
585
- Int ( I16 ) => "llvm.smul.with.overflow.i16" ,
586
- Int ( I32 ) => "llvm.smul.with.overflow.i32" ,
587
- Int ( I64 ) => "llvm.smul.with.overflow.i64" ,
588
- Int ( I128 ) => "llvm.smul.with.overflow.i128" ,
589
-
590
- Uint ( U8 ) => "llvm.umul.with.overflow.i8" ,
591
- Uint ( U16 ) => "llvm.umul.with.overflow.i16" ,
592
- Uint ( U32 ) => "llvm.umul.with.overflow.i32" ,
593
- Uint ( U64 ) => "llvm.umul.with.overflow.i64" ,
594
- Uint ( U128 ) => "llvm.umul.with.overflow.i128" ,
595
-
596
- _ => unreachable ! ( ) ,
597
- } ,
521
+ let op = match oop {
522
+ OverflowOp :: Add => "add" ,
523
+ OverflowOp :: Sub => "sub" ,
524
+ OverflowOp :: Mul => "mul" ,
598
525
} ;
599
526
600
- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
527
+ let llvm_intrinsic = format ! ( "llvm.{}{op}.with.overflow" , if signed { 's' } else { 'u' } ) ;
528
+
529
+ let res = self . call_intrinsic ( & llvm_intrinsic, & [ self . type_ix ( width. bits ( ) ) ] , & [ lhs, rhs] ) ;
601
530
( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
602
531
}
603
532
@@ -1028,15 +957,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1028
957
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1029
958
let float_width = self . cx . float_width ( src_ty) ;
1030
959
let int_width = self . cx . int_width ( dest_ty) ;
1031
- let name = match ( int_width, float_width) {
1032
- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f32" ) ,
1033
- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f64" ) ,
1034
- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f32" ) ,
1035
- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f64" ) ,
1036
- _ => None ,
1037
- } ;
1038
- if let Some ( name) = name {
1039
- 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.unsigned" ,
963
+ & [ dest_ty, src_ty] ,
964
+ & [ val] ,
965
+ ) ;
1040
966
}
1041
967
}
1042
968
}
@@ -1050,15 +976,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1050
976
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1051
977
let float_width = self . cx . float_width ( src_ty) ;
1052
978
let int_width = self . cx . int_width ( dest_ty) ;
1053
- let name = match ( int_width, float_width) {
1054
- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.signed.i32.f32" ) ,
1055
- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.signed.i32.f64" ) ,
1056
- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.signed.i64.f32" ) ,
1057
- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.signed.i64.f64" ) ,
1058
- _ => None ,
1059
- } ;
1060
- if let Some ( name) = name {
1061
- return self . call_intrinsic ( name, & [ val] ) ;
979
+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
980
+ return self . call_intrinsic (
981
+ "llvm.wasm.trunc.signed" ,
982
+ & [ dest_ty, src_ty] ,
983
+ & [ val] ,
984
+ ) ;
1062
985
}
1063
986
}
1064
987
}
@@ -1131,22 +1054,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1131
1054
return None ;
1132
1055
}
1133
1056
1134
- let name = match ( ty. is_signed ( ) , ty. primitive_size ( self . tcx ) . bits ( ) ) {
1135
- ( true , 8 ) => "llvm.scmp.i8.i8" ,
1136
- ( true , 16 ) => "llvm.scmp.i8.i16" ,
1137
- ( true , 32 ) => "llvm.scmp.i8.i32" ,
1138
- ( true , 64 ) => "llvm.scmp.i8.i64" ,
1139
- ( true , 128 ) => "llvm.scmp.i8.i128" ,
1140
-
1141
- ( false , 8 ) => "llvm.ucmp.i8.i8" ,
1142
- ( false , 16 ) => "llvm.ucmp.i8.i16" ,
1143
- ( false , 32 ) => "llvm.ucmp.i8.i32" ,
1144
- ( false , 64 ) => "llvm.ucmp.i8.i64" ,
1145
- ( false , 128 ) => "llvm.ucmp.i8.i128" ,
1146
-
1057
+ let ( signed, llty) = match ty. kind ( ) {
1058
+ ty:: Int ( t) => ( true , self . type_int_from_ty ( * t) ) ,
1059
+ ty:: Uint ( t) => ( true , self . type_uint_from_ty ( * t) ) ,
1060
+ ty:: Char => ( true , self . type_i32 ( ) ) ,
1147
1061
_ => bug ! ( "three-way compare unsupported for type {ty:?}" ) ,
1148
1062
} ;
1149
- Some ( self . call_intrinsic ( name, & [ lhs, rhs] ) )
1063
+
1064
+ let llvm_intrinsic = format ! ( "llvm.{}cmp" , if signed { 's' } else { 'u' } ) ;
1065
+ Some ( self . call_intrinsic ( & llvm_intrinsic, & [ self . type_i8 ( ) , llty] , & [ lhs, rhs] ) )
1150
1066
}
1151
1067
1152
1068
/* Miscellaneous instructions */
@@ -1432,11 +1348,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1432
1348
}
1433
1349
1434
1350
fn lifetime_start ( & mut self , ptr : & ' ll Value , size : Size ) {
1435
- self . call_lifetime_intrinsic ( "llvm.lifetime.start.p0i8 " , ptr, size) ;
1351
+ self . call_lifetime_intrinsic ( "llvm.lifetime.start" , ptr, size) ;
1436
1352
}
1437
1353
1438
1354
fn lifetime_end ( & mut self , ptr : & ' ll Value , size : Size ) {
1439
- self . call_lifetime_intrinsic ( "llvm.lifetime.end.p0i8 " , ptr, size) ;
1355
+ self . call_lifetime_intrinsic ( "llvm.lifetime.end" , ptr, size) ;
1440
1356
}
1441
1357
1442
1358
fn call (
@@ -1645,6 +1561,29 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1645
1561
ret. expect ( "LLVM does not have support for catchret" )
1646
1562
}
1647
1563
1564
+ pub ( crate ) fn call_intrinsic (
1565
+ & mut self ,
1566
+ base_name : & str ,
1567
+ type_params : & [ & ' ll Type ] ,
1568
+ args : & [ & ' ll Value ] ,
1569
+ ) -> & ' ll Value {
1570
+ let intrinsic = llvm:: Intrinsic :: lookup ( base_name. as_bytes ( ) )
1571
+ . unwrap_or_else ( || bug ! ( "Intrinsic `{base_name}` not found" ) ) ;
1572
+ let ( fn_ty, llfn) = self . cx . get_intrinsic ( intrinsic, type_params) ;
1573
+ unsafe {
1574
+ llvm:: LLVMBuildCallWithOperandBundles (
1575
+ self . llbuilder ,
1576
+ fn_ty,
1577
+ llfn,
1578
+ args. as_ptr ( ) ,
1579
+ args. len ( ) . try_into ( ) . unwrap ( ) ,
1580
+ [ ] . as_ptr ( ) ,
1581
+ 0 ,
1582
+ c"" . as_ptr ( ) ,
1583
+ )
1584
+ }
1585
+ }
1586
+
1648
1587
fn cast_arguments < ' b > (
1649
1588
& mut self ,
1650
1589
typ : & str ,
@@ -1696,11 +1635,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1696
1635
}
1697
1636
1698
1637
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1699
- pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1700
- let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1701
- self . call ( ty, None , None , f, args, None , None )
1702
- }
1703
-
1704
1638
fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
1705
1639
let size = size. bytes ( ) ;
1706
1640
if size == 0 {
@@ -1711,7 +1645,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1711
1645
return ;
1712
1646
}
1713
1647
1714
- self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1648
+ self . call_intrinsic ( intrinsic, & [ self . type_ptr ( ) ] , & [ self . cx . const_u64 ( size) , ptr] ) ;
1715
1649
}
1716
1650
}
1717
1651
impl < ' a , ' ll , CX : Borrow < SCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
@@ -1736,6 +1670,37 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1736
1670
}
1737
1671
}
1738
1672
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1673
+ pub ( crate ) fn memcmp (
1674
+ & mut self ,
1675
+ ptr1 : & ' ll Value ,
1676
+ ptr2 : & ' ll Value ,
1677
+ num : & ' ll Value ,
1678
+ ) -> & ' ll Value {
1679
+ let llreturn_ty = match self . sess ( ) . target . arch . as_ref ( ) {
1680
+ "avr" | "msp430" => self . type_i16 ( ) ,
1681
+ _ => self . type_i32 ( ) ,
1682
+ } ;
1683
+ let fn_ty =
1684
+ self . type_func ( & [ self . type_ptr ( ) , self . type_ptr ( ) , self . type_isize ( ) ] , llreturn_ty) ;
1685
+
1686
+ let llfn = self
1687
+ . get_function ( "memcmp" )
1688
+ . unwrap_or_else ( || self . declare_cfn ( "memcmp" , llvm:: UnnamedAddr :: No , fn_ty) ) ;
1689
+
1690
+ unsafe {
1691
+ llvm:: LLVMBuildCallWithOperandBundles (
1692
+ self . llbuilder ,
1693
+ fn_ty,
1694
+ llfn,
1695
+ [ ptr1, ptr2, num] . as_ptr ( ) ,
1696
+ 3 ,
1697
+ [ ] . as_ptr ( ) ,
1698
+ 0 ,
1699
+ c"" . as_ptr ( ) ,
1700
+ )
1701
+ }
1702
+ }
1703
+
1739
1704
fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
1740
1705
let src_ty = self . cx . val_ty ( val) ;
1741
1706
let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
@@ -1958,7 +1923,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1958
1923
num_counters : & ' ll Value ,
1959
1924
index : & ' ll Value ,
1960
1925
) {
1961
- self . call_intrinsic ( "llvm.instrprof.increment" , & [ fn_name, hash, num_counters, index] ) ;
1926
+ self . call_intrinsic ( "llvm.instrprof.increment" , & [ ] , & [ fn_name, hash, num_counters, index] ) ;
1962
1927
}
1963
1928
1964
1929
/// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1977,7 +1942,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1977
1942
hash : & ' ll Value ,
1978
1943
bitmap_bits : & ' ll Value ,
1979
1944
) {
1980
- self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ fn_name, hash, bitmap_bits] ) ;
1945
+ self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ ] , & [ fn_name, hash, bitmap_bits] ) ;
1981
1946
}
1982
1947
1983
1948
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -1989,7 +1954,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1989
1954
mcdc_temp : & ' ll Value ,
1990
1955
) {
1991
1956
let args = & [ fn_name, hash, bitmap_index, mcdc_temp] ;
1992
- self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , args) ;
1957
+ self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , & [ ] , args) ;
1993
1958
}
1994
1959
1995
1960
#[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments