@@ -70,7 +70,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
70
70
) -> & ' ll Value {
71
71
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
72
72
73
- let args = self . check_call ( "call" , llty, llfn, args) ;
74
73
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
75
74
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
76
75
if let Some ( funclet_bundle) = funclet_bundle {
@@ -414,7 +413,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
414
413
) -> & ' ll Value {
415
414
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
416
415
417
- let args = self . check_call ( "invoke" , llty, llfn, args) ;
416
+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
418
417
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
419
418
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
420
419
if let Some ( funclet_bundle) = funclet_bundle {
@@ -446,8 +445,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
446
445
} ;
447
446
if let Some ( fn_abi) = fn_abi {
448
447
fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
448
+ self . cast_return ( fn_abi, llfn, invoke)
449
+ } else {
450
+ invoke
449
451
}
450
- invoke
451
452
}
452
453
453
454
fn unreachable ( & mut self ) {
@@ -1395,7 +1396,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1395
1396
) -> & ' ll Value {
1396
1397
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
1397
1398
1398
- let args = self . check_call ( "call" , llty, llfn, args) ;
1399
+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1399
1400
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1400
1401
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1401
1402
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1448,8 +1449,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1448
1449
1449
1450
if let Some ( fn_abi) = fn_abi {
1450
1451
fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1452
+ self . cast_return ( fn_abi, llfn, call)
1453
+ } else {
1454
+ call
1451
1455
}
1452
- call
1453
1456
}
1454
1457
1455
1458
fn tail_call (
@@ -1630,47 +1633,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1630
1633
ret. expect ( "LLVM does not have support for catchret" )
1631
1634
}
1632
1635
1633
- fn check_call < ' b > (
1634
- & mut self ,
1635
- typ : & str ,
1636
- fn_ty : & ' ll Type ,
1637
- llfn : & ' ll Value ,
1638
- args : & ' b [ & ' ll Value ] ,
1639
- ) -> Cow < ' b , [ & ' ll Value ] > {
1640
- assert ! (
1641
- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1642
- "builder::{typ} not passed a function, but {fn_ty:?}"
1643
- ) ;
1644
-
1645
- let param_tys = self . cx . func_params_types ( fn_ty) ;
1646
-
1647
- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1648
- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1649
-
1650
- if all_args_match {
1651
- return Cow :: Borrowed ( args) ;
1652
- }
1653
-
1654
- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1655
- . enumerate ( )
1656
- . map ( |( i, ( expected_ty, & actual_val) ) | {
1657
- let actual_ty = self . cx . val_ty ( actual_val) ;
1658
- if expected_ty != actual_ty {
1659
- debug ! (
1660
- "type mismatch in function call of {:?}. \
1661
- Expected {:?} for param {}, got {:?}; injecting bitcast",
1662
- llfn, expected_ty, i, actual_ty
1663
- ) ;
1664
- self . bitcast ( actual_val, expected_ty)
1665
- } else {
1666
- actual_val
1667
- }
1668
- } )
1669
- . collect ( ) ;
1670
-
1671
- Cow :: Owned ( casted_args)
1672
- }
1673
-
1674
1636
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1675
1637
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1676
1638
}
@@ -1726,6 +1688,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1726
1688
}
1727
1689
}
1728
1690
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1691
+ fn autocast (
1692
+ & mut self ,
1693
+ llfn : & ' ll Value ,
1694
+ val : & ' ll Value ,
1695
+ src_ty : & ' ll Type ,
1696
+ dest_ty : & ' ll Type ,
1697
+ is_argument : bool ,
1698
+ ) -> & ' ll Value {
1699
+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1700
+
1701
+ if rust_ty == llvm_ty {
1702
+ return val;
1703
+ }
1704
+
1705
+ match self . type_kind ( llvm_ty) {
1706
+ TypeKind :: Struct => {
1707
+ let mut ret = self . const_poison ( dest_ty) ;
1708
+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1709
+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1710
+ . enumerate ( )
1711
+ {
1712
+ let elt = self . extract_value ( val, idx as u64 ) ;
1713
+ let casted_elt =
1714
+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1715
+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1716
+ }
1717
+ ret
1718
+ }
1719
+ _ => unreachable ! ( ) ,
1720
+ }
1721
+ }
1722
+
1723
+ fn cast_arguments < ' b > (
1724
+ & mut self ,
1725
+ typ : & str ,
1726
+ fn_ty : & ' ll Type ,
1727
+ llfn : & ' ll Value ,
1728
+ args : & ' b [ & ' ll Value ] ,
1729
+ has_fnabi : bool ,
1730
+ ) -> Cow < ' b , [ & ' ll Value ] > {
1731
+ assert_eq ! (
1732
+ self . type_kind( fn_ty) ,
1733
+ TypeKind :: Function ,
1734
+ "{typ} not passed a function, but {fn_ty:?}"
1735
+ ) ;
1736
+
1737
+ let param_tys = self . func_params_types ( fn_ty) ;
1738
+
1739
+ let mut casted_args = Cow :: Borrowed ( args) ;
1740
+
1741
+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1742
+ let src_ty = self . val_ty ( arg) ;
1743
+ assert ! (
1744
+ self . equate_ty( src_ty, dest_ty) ,
1745
+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1746
+ ) ;
1747
+
1748
+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1749
+ if arg != casted_arg {
1750
+ assert ! (
1751
+ has_fnabi,
1752
+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1753
+ ) ;
1754
+
1755
+ casted_args. to_mut ( ) [ idx] = casted_arg;
1756
+ }
1757
+ }
1758
+
1759
+ casted_args
1760
+ }
1761
+
1762
+ fn cast_return (
1763
+ & mut self ,
1764
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1765
+ llfn : & ' ll Value ,
1766
+ ret : & ' ll Value ,
1767
+ ) -> & ' ll Value {
1768
+ let src_ty = self . val_ty ( ret) ;
1769
+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1770
+ assert ! (
1771
+ self . equate_ty( dest_ty, src_ty) ,
1772
+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1773
+ ) ;
1774
+
1775
+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1776
+ }
1777
+
1729
1778
pub ( crate ) fn landing_pad (
1730
1779
& mut self ,
1731
1780
ty : & ' ll Type ,
@@ -1755,7 +1804,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1755
1804
) -> & ' ll Value {
1756
1805
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1757
1806
1758
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1807
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1759
1808
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1760
1809
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1761
1810
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1788,8 +1837,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1788
1837
} ;
1789
1838
if let Some ( fn_abi) = fn_abi {
1790
1839
fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1840
+ self . cast_return ( fn_abi, llfn, callbr)
1841
+ } else {
1842
+ callbr
1791
1843
}
1792
- callbr
1793
1844
}
1794
1845
1795
1846
// Emits CFI pointer type membership tests.
0 commit comments