@@ -27,7 +27,7 @@ use rustc_span::Span;
27
27
use rustc_target:: callconv:: FnAbi ;
28
28
use rustc_target:: spec:: { HasTargetSpec , SanitizerSet , Target } ;
29
29
use smallvec:: SmallVec ;
30
- use tracing:: { debug, instrument} ;
30
+ use tracing:: { debug, instrument, warn } ;
31
31
32
32
use crate :: abi:: FnAbiLlvmExt ;
33
33
use crate :: attributes;
@@ -67,7 +67,7 @@ impl<'a, 'll> SBuilder<'a, 'll> {
67
67
) -> & ' ll Value {
68
68
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
69
69
70
- let args = self . check_call ( "call" , llty, llfn, args) ;
70
+ let args = self . cast_arguments ( "call" , llty, llfn, args, false ) ;
71
71
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
72
72
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
73
73
if let Some ( funclet_bundle) = funclet_bundle {
@@ -79,7 +79,7 @@ impl<'a, 'll> SBuilder<'a, 'll> {
79
79
self . llbuilder ,
80
80
llty,
81
81
llfn,
82
- args. as_ptr ( ) as * const & llvm :: Value ,
82
+ args. as_ptr ( ) ,
83
83
args. len ( ) as c_uint ,
84
84
bundles. as_ptr ( ) ,
85
85
bundles. len ( ) as c_uint ,
@@ -101,6 +101,22 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
101
101
unsafe { llvm:: LLVMBuildBitCast ( self . llbuilder , val, dest_ty, UNNAMED ) }
102
102
}
103
103
104
+ pub ( crate ) fn cast_vector_to_tile ( & mut self , val : & ' ll Value ) -> & ' ll Value {
105
+ let vector_type = self . cx . val_ty ( val) ;
106
+
107
+ assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
108
+ self . call_intrinsic ( "llvm.x86.cast.vector.to.tile" , & [ vector_type] , & [ val] )
109
+ }
110
+
111
+ pub ( crate ) fn cast_tile_to_vector (
112
+ & mut self ,
113
+ val : & ' ll Value ,
114
+ vector_type : & ' ll Type ,
115
+ ) -> & ' ll Value {
116
+ assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
117
+ self . call_intrinsic ( "llvm.x86.cast.tile.to.vector" , & [ vector_type] , & [ val] )
118
+ }
119
+
104
120
pub ( crate ) fn ret_void ( & mut self ) {
105
121
llvm:: LLVMBuildRetVoid ( self . llbuilder ) ;
106
122
}
@@ -349,7 +365,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
349
365
) -> & ' ll Value {
350
366
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
351
367
352
- let args = self . check_call ( "invoke" , llty, llfn, args) ;
368
+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
353
369
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
354
370
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
355
371
if let Some ( funclet_bundle) = funclet_bundle {
@@ -381,8 +397,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
381
397
} ;
382
398
if let Some ( fn_abi) = fn_abi {
383
399
fn_abi. apply_attrs_callsite ( self , invoke) ;
400
+ self . cast_return ( fn_abi, llfn, invoke)
401
+ } else {
402
+ invoke
384
403
}
385
- invoke
386
404
}
387
405
388
406
fn unreachable ( & mut self ) {
@@ -1348,7 +1366,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1348
1366
) -> & ' ll Value {
1349
1367
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
1350
1368
1351
- let args = self . check_call ( "call" , llty, llfn, args) ;
1369
+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1352
1370
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1353
1371
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1354
1372
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1378,8 +1396,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1378
1396
} ;
1379
1397
if let Some ( fn_abi) = fn_abi {
1380
1398
fn_abi. apply_attrs_callsite ( self , call) ;
1399
+ self . cast_return ( fn_abi, llfn, call)
1400
+ } else {
1401
+ call
1381
1402
}
1382
- call
1383
1403
}
1384
1404
1385
1405
fn zext ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
@@ -1540,45 +1560,47 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1540
1560
ret. expect ( "LLVM does not have support for catchret" )
1541
1561
}
1542
1562
1543
- fn check_call < ' b > (
1563
+ fn cast_arguments < ' b > (
1544
1564
& mut self ,
1545
1565
typ : & str ,
1546
1566
fn_ty : & ' ll Type ,
1547
1567
llfn : & ' ll Value ,
1548
1568
args : & ' b [ & ' ll Value ] ,
1569
+ has_fnabi : bool ,
1549
1570
) -> Cow < ' b , [ & ' ll Value ] > {
1550
- assert ! (
1551
- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1552
- "builder::{typ} not passed a function, but {fn_ty:?}"
1571
+ assert_eq ! (
1572
+ self . cx. type_kind( fn_ty) ,
1573
+ TypeKind :: Function ,
1574
+ "{typ} not passed a function, but {fn_ty:?}"
1553
1575
) ;
1554
1576
1555
1577
let param_tys = self . cx . func_params_types ( fn_ty) ;
1556
1578
1557
- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1558
- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1579
+ let mut casted_args = Cow :: Borrowed ( args) ;
1559
1580
1560
- if all_args_match {
1561
- return Cow :: Borrowed ( args) ;
1562
- }
1581
+ for ( i, ( expected_ty, & actual_val) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1582
+ let actual_ty = self . cx . val_ty ( actual_val) ;
1563
1583
1564
- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1565
- . enumerate ( )
1566
- . map ( |( i, ( expected_ty, & actual_val) ) | {
1567
- let actual_ty = self . cx . val_ty ( actual_val) ;
1568
- if expected_ty != actual_ty {
1569
- debug ! (
1570
- "type mismatch in function call of {:?}. \
1571
- Expected {:?} for param {}, got {:?}; injecting bitcast",
1572
- llfn, expected_ty, i, actual_ty
1584
+ if expected_ty != actual_ty {
1585
+ warn ! (
1586
+ "type mismatch in function call of {llfn:?}. \
1587
+ Expected {expected_ty:?} for param {i}, got {actual_ty:?}; injecting bitcast",
1588
+ ) ;
1589
+
1590
+ casted_args. to_mut ( ) [ i] = if self . cx . type_kind ( expected_ty) == TypeKind :: X86_AMX {
1591
+ // we can't do `cast_return` in without `FnAbi`
1592
+ assert ! (
1593
+ has_fnabi,
1594
+ "Found `x86amx` for parameter {i} in function call of {llfn:?}, but not able to get Rust return type"
1573
1595
) ;
1574
- self . bitcast ( actual_val, expected_ty )
1596
+ self . cast_vector_to_tile ( actual_val)
1575
1597
} else {
1576
- actual_val
1598
+ self . bitcast ( actual_val, expected_ty )
1577
1599
}
1578
- } )
1579
- . collect ( ) ;
1600
+ }
1601
+ }
1580
1602
1581
- Cow :: Owned ( casted_args)
1603
+ casted_args
1582
1604
}
1583
1605
1584
1606
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
@@ -1591,7 +1613,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1591
1613
llfn : & ' ll Value ,
1592
1614
args : & [ & ' ll Value ] ,
1593
1615
) -> & ' ll Value {
1594
- let args = self . check_call ( "simple call" , fn_ty, llfn, args) ;
1616
+ let args = self . cast_arguments ( "simple call" , fn_ty, llfn, args, false ) ;
1595
1617
1596
1618
unsafe {
1597
1619
llvm:: LLVMBuildCall2 (
@@ -1692,6 +1714,30 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1692
1714
self . simple_call ( fn_ty, llfn, & [ ptr1, ptr2, num] )
1693
1715
}
1694
1716
1717
+ fn cast_return (
1718
+ & mut self ,
1719
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1720
+ llfn : & ' ll Value ,
1721
+ ret : & ' ll Value ,
1722
+ ) -> & ' ll Value {
1723
+ let expected_ty = fn_abi. llvm_return_type ( self . cx ) ;
1724
+ let actual_ty = self . cx . val_ty ( ret) ;
1725
+
1726
+ if expected_ty != actual_ty {
1727
+ warn ! (
1728
+ "Type mismatch in function call of {llfn:?}. \
1729
+ Expected {expected_ty:?} for return type, got {actual_ty:?}"
1730
+ ) ;
1731
+ if self . cx . type_kind ( actual_ty) == TypeKind :: X86_AMX {
1732
+ self . cast_tile_to_vector ( ret, expected_ty)
1733
+ } else {
1734
+ self . bitcast ( ret, expected_ty)
1735
+ }
1736
+ } else {
1737
+ ret
1738
+ }
1739
+ }
1740
+
1695
1741
pub ( crate ) fn landing_pad (
1696
1742
& mut self ,
1697
1743
ty : & ' ll Type ,
@@ -1721,7 +1767,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1721
1767
) -> & ' ll Value {
1722
1768
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1723
1769
1724
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1770
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1725
1771
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1726
1772
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1727
1773
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1754,8 +1800,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1754
1800
} ;
1755
1801
if let Some ( fn_abi) = fn_abi {
1756
1802
fn_abi. apply_attrs_callsite ( self , callbr) ;
1803
+ self . cast_return ( fn_abi, llfn, callbr)
1804
+ } else {
1805
+ callbr
1757
1806
}
1758
- callbr
1759
1807
}
1760
1808
1761
1809
// Emits CFI pointer type membership tests.
0 commit comments