@@ -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 {
@@ -1431,8 +1432,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1431
1432
} ;
1432
1433
if let Some ( fn_abi) = fn_abi {
1433
1434
fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1435
+ self . cast_return ( fn_abi, llfn, call)
1436
+ } else {
1437
+ call
1434
1438
}
1435
- call
1436
1439
}
1437
1440
1438
1441
fn tail_call (
@@ -1622,47 +1625,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1622
1625
ret. expect ( "LLVM does not have support for catchret" )
1623
1626
}
1624
1627
1625
- fn check_call < ' b > (
1626
- & mut self ,
1627
- typ : & str ,
1628
- fn_ty : & ' ll Type ,
1629
- llfn : & ' ll Value ,
1630
- args : & ' b [ & ' ll Value ] ,
1631
- ) -> Cow < ' b , [ & ' ll Value ] > {
1632
- assert ! (
1633
- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1634
- "builder::{typ} not passed a function, but {fn_ty:?}"
1635
- ) ;
1636
-
1637
- let param_tys = self . cx . func_params_types ( fn_ty) ;
1638
-
1639
- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1640
- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1641
-
1642
- if all_args_match {
1643
- return Cow :: Borrowed ( args) ;
1644
- }
1645
-
1646
- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1647
- . enumerate ( )
1648
- . map ( |( i, ( expected_ty, & actual_val) ) | {
1649
- let actual_ty = self . cx . val_ty ( actual_val) ;
1650
- if expected_ty != actual_ty {
1651
- debug ! (
1652
- "type mismatch in function call of {:?}. \
1653
- Expected {:?} for param {}, got {:?}; injecting bitcast",
1654
- llfn, expected_ty, i, actual_ty
1655
- ) ;
1656
- self . bitcast ( actual_val, expected_ty)
1657
- } else {
1658
- actual_val
1659
- }
1660
- } )
1661
- . collect ( ) ;
1662
-
1663
- Cow :: Owned ( casted_args)
1664
- }
1665
-
1666
1628
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1667
1629
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1668
1630
}
@@ -1718,6 +1680,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1718
1680
}
1719
1681
}
1720
1682
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1683
+ fn autocast (
1684
+ & mut self ,
1685
+ llfn : & ' ll Value ,
1686
+ val : & ' ll Value ,
1687
+ src_ty : & ' ll Type ,
1688
+ dest_ty : & ' ll Type ,
1689
+ is_argument : bool ,
1690
+ ) -> & ' ll Value {
1691
+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1692
+
1693
+ if rust_ty == llvm_ty {
1694
+ return val;
1695
+ }
1696
+
1697
+ match self . type_kind ( llvm_ty) {
1698
+ TypeKind :: Struct => {
1699
+ let mut ret = self . const_poison ( dest_ty) ;
1700
+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1701
+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1702
+ . enumerate ( )
1703
+ {
1704
+ let elt = self . extract_value ( val, idx as u64 ) ;
1705
+ let casted_elt =
1706
+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1707
+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1708
+ }
1709
+ ret
1710
+ }
1711
+ _ => unreachable ! ( ) ,
1712
+ }
1713
+ }
1714
+
1715
+ fn cast_arguments < ' b > (
1716
+ & mut self ,
1717
+ typ : & str ,
1718
+ fn_ty : & ' ll Type ,
1719
+ llfn : & ' ll Value ,
1720
+ args : & ' b [ & ' ll Value ] ,
1721
+ has_fnabi : bool ,
1722
+ ) -> Cow < ' b , [ & ' ll Value ] > {
1723
+ assert_eq ! (
1724
+ self . type_kind( fn_ty) ,
1725
+ TypeKind :: Function ,
1726
+ "{typ} not passed a function, but {fn_ty:?}"
1727
+ ) ;
1728
+
1729
+ let param_tys = self . func_params_types ( fn_ty) ;
1730
+
1731
+ let mut casted_args = Cow :: Borrowed ( args) ;
1732
+
1733
+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1734
+ let src_ty = self . val_ty ( arg) ;
1735
+ assert ! (
1736
+ self . equate_ty( src_ty, dest_ty) ,
1737
+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1738
+ ) ;
1739
+
1740
+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1741
+ if arg != casted_arg {
1742
+ assert ! (
1743
+ has_fnabi,
1744
+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1745
+ ) ;
1746
+
1747
+ casted_args. to_mut ( ) [ idx] = casted_arg;
1748
+ }
1749
+ }
1750
+
1751
+ casted_args
1752
+ }
1753
+
1754
+ fn cast_return (
1755
+ & mut self ,
1756
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1757
+ llfn : & ' ll Value ,
1758
+ ret : & ' ll Value ,
1759
+ ) -> & ' ll Value {
1760
+ let src_ty = self . val_ty ( ret) ;
1761
+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1762
+ assert ! (
1763
+ self . equate_ty( dest_ty, src_ty) ,
1764
+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1765
+ ) ;
1766
+
1767
+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1768
+ }
1769
+
1721
1770
pub ( crate ) fn landing_pad (
1722
1771
& mut self ,
1723
1772
ty : & ' ll Type ,
@@ -1747,7 +1796,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1747
1796
) -> & ' ll Value {
1748
1797
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1749
1798
1750
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1799
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1751
1800
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1752
1801
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1753
1802
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1780,8 +1829,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1780
1829
} ;
1781
1830
if let Some ( fn_abi) = fn_abi {
1782
1831
fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1832
+ self . cast_return ( fn_abi, llfn, callbr)
1833
+ } else {
1834
+ callbr
1783
1835
}
1784
- callbr
1785
1836
}
1786
1837
1787
1838
// Emits CFI pointer type membership tests.
0 commit comments