@@ -68,7 +68,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
68
68
) -> & ' ll Value {
69
69
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
70
70
71
- let args = self . check_call ( "call" , llty, llfn, args) ;
72
71
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
73
72
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
74
73
if let Some ( funclet_bundle) = funclet_bundle {
@@ -415,7 +414,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
415
414
) -> & ' ll Value {
416
415
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
417
416
418
- let args = self . check_call ( "invoke" , llty, llfn, args) ;
417
+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
419
418
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
420
419
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
421
420
if let Some ( funclet_bundle) = funclet_bundle {
@@ -447,8 +446,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
447
446
} ;
448
447
if let Some ( fn_abi) = fn_abi {
449
448
fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
449
+ self . cast_return ( fn_abi, llfn, invoke)
450
+ } else {
451
+ invoke
450
452
}
451
- invoke
452
453
}
453
454
454
455
fn unreachable ( & mut self ) {
@@ -1401,7 +1402,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1401
1402
) -> & ' ll Value {
1402
1403
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
1403
1404
1404
- let args = self . check_call ( "call" , llty, llfn, args) ;
1405
+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1405
1406
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1406
1407
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1407
1408
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1454,8 +1455,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1454
1455
1455
1456
if let Some ( fn_abi) = fn_abi {
1456
1457
fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1458
+ self . cast_return ( fn_abi, llfn, call)
1459
+ } else {
1460
+ call
1457
1461
}
1458
- call
1459
1462
}
1460
1463
1461
1464
fn tail_call (
@@ -1645,47 +1648,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1645
1648
ret. expect ( "LLVM does not have support for catchret" )
1646
1649
}
1647
1650
1648
- fn check_call < ' b > (
1649
- & mut self ,
1650
- typ : & str ,
1651
- fn_ty : & ' ll Type ,
1652
- llfn : & ' ll Value ,
1653
- args : & ' b [ & ' ll Value ] ,
1654
- ) -> Cow < ' b , [ & ' ll Value ] > {
1655
- assert ! (
1656
- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1657
- "builder::{typ} not passed a function, but {fn_ty:?}"
1658
- ) ;
1659
-
1660
- let param_tys = self . cx . func_params_types ( fn_ty) ;
1661
-
1662
- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1663
- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1664
-
1665
- if all_args_match {
1666
- return Cow :: Borrowed ( args) ;
1667
- }
1668
-
1669
- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1670
- . enumerate ( )
1671
- . map ( |( i, ( expected_ty, & actual_val) ) | {
1672
- let actual_ty = self . cx . val_ty ( actual_val) ;
1673
- if expected_ty != actual_ty {
1674
- debug ! (
1675
- "type mismatch in function call of {:?}. \
1676
- Expected {:?} for param {}, got {:?}; injecting bitcast",
1677
- llfn, expected_ty, i, actual_ty
1678
- ) ;
1679
- self . bitcast ( actual_val, expected_ty)
1680
- } else {
1681
- actual_val
1682
- }
1683
- } )
1684
- . collect ( ) ;
1685
-
1686
- Cow :: Owned ( casted_args)
1687
- }
1688
-
1689
1651
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1690
1652
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1691
1653
}
@@ -1741,6 +1703,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1741
1703
}
1742
1704
}
1743
1705
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1706
+ fn autocast (
1707
+ & mut self ,
1708
+ llfn : & ' ll Value ,
1709
+ val : & ' ll Value ,
1710
+ src_ty : & ' ll Type ,
1711
+ dest_ty : & ' ll Type ,
1712
+ is_argument : bool ,
1713
+ ) -> & ' ll Value {
1714
+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1715
+
1716
+ if rust_ty == llvm_ty {
1717
+ return val;
1718
+ }
1719
+
1720
+ match self . type_kind ( llvm_ty) {
1721
+ TypeKind :: Struct => {
1722
+ let mut ret = self . const_poison ( dest_ty) ;
1723
+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1724
+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1725
+ . enumerate ( )
1726
+ {
1727
+ let elt = self . extract_value ( val, idx as u64 ) ;
1728
+ let casted_elt =
1729
+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1730
+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1731
+ }
1732
+ ret
1733
+ }
1734
+ _ => unreachable ! ( ) ,
1735
+ }
1736
+ }
1737
+
1738
+ fn cast_arguments < ' b > (
1739
+ & mut self ,
1740
+ typ : & str ,
1741
+ fn_ty : & ' ll Type ,
1742
+ llfn : & ' ll Value ,
1743
+ args : & ' b [ & ' ll Value ] ,
1744
+ has_fnabi : bool ,
1745
+ ) -> Cow < ' b , [ & ' ll Value ] > {
1746
+ assert_eq ! (
1747
+ self . type_kind( fn_ty) ,
1748
+ TypeKind :: Function ,
1749
+ "{typ} not passed a function, but {fn_ty:?}"
1750
+ ) ;
1751
+
1752
+ let param_tys = self . func_params_types ( fn_ty) ;
1753
+
1754
+ let mut casted_args = Cow :: Borrowed ( args) ;
1755
+
1756
+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1757
+ let src_ty = self . val_ty ( arg) ;
1758
+ assert ! (
1759
+ self . equate_ty( src_ty, dest_ty) ,
1760
+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1761
+ ) ;
1762
+
1763
+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1764
+ if arg != casted_arg {
1765
+ assert ! (
1766
+ has_fnabi,
1767
+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1768
+ ) ;
1769
+
1770
+ casted_args. to_mut ( ) [ idx] = casted_arg;
1771
+ }
1772
+ }
1773
+
1774
+ casted_args
1775
+ }
1776
+
1777
+ fn cast_return (
1778
+ & mut self ,
1779
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1780
+ llfn : & ' ll Value ,
1781
+ ret : & ' ll Value ,
1782
+ ) -> & ' ll Value {
1783
+ let src_ty = self . val_ty ( ret) ;
1784
+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1785
+ assert ! (
1786
+ self . equate_ty( dest_ty, src_ty) ,
1787
+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1788
+ ) ;
1789
+
1790
+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1791
+ }
1792
+
1744
1793
pub ( crate ) fn landing_pad (
1745
1794
& mut self ,
1746
1795
ty : & ' ll Type ,
@@ -1770,7 +1819,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1770
1819
) -> & ' ll Value {
1771
1820
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1772
1821
1773
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1822
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1774
1823
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1775
1824
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1776
1825
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1803,8 +1852,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1803
1852
} ;
1804
1853
if let Some ( fn_abi) = fn_abi {
1805
1854
fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1855
+ self . cast_return ( fn_abi, llfn, callbr)
1856
+ } else {
1857
+ callbr
1806
1858
}
1807
- callbr
1808
1859
}
1809
1860
1810
1861
// Emits CFI pointer type membership tests.
0 commit comments