@@ -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 . check_call ( "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 {
@@ -349,7 +348,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
349
348
) -> & ' ll Value {
350
349
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
351
350
352
- let args = self . check_call ( "invoke" , llty, llfn, args) ;
351
+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
353
352
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
354
353
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
355
354
if let Some ( funclet_bundle) = funclet_bundle {
@@ -381,8 +380,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
381
380
} ;
382
381
if let Some ( fn_abi) = fn_abi {
383
382
fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
383
+ self . cast_return ( fn_abi, llfn, invoke)
384
+ } else {
385
+ invoke
384
386
}
385
- invoke
386
387
}
387
388
388
389
fn unreachable ( & mut self ) {
@@ -1404,7 +1405,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1404
1405
) -> & ' ll Value {
1405
1406
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
1406
1407
1407
- let args = self . check_call ( "call" , llty, llfn, args) ;
1408
+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1408
1409
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1409
1410
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1410
1411
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1434,8 +1435,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1434
1435
} ;
1435
1436
if let Some ( fn_abi) = fn_abi {
1436
1437
fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1438
+ self . cast_return ( fn_abi, llfn, call)
1439
+ } else {
1440
+ call
1437
1441
}
1438
- call
1439
1442
}
1440
1443
1441
1444
fn zext ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
@@ -1596,47 +1599,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1596
1599
ret. expect ( "LLVM does not have support for catchret" )
1597
1600
}
1598
1601
1599
- fn check_call < ' b > (
1600
- & mut self ,
1601
- typ : & str ,
1602
- fn_ty : & ' ll Type ,
1603
- llfn : & ' ll Value ,
1604
- args : & ' b [ & ' ll Value ] ,
1605
- ) -> Cow < ' b , [ & ' ll Value ] > {
1606
- assert ! (
1607
- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1608
- "builder::{typ} not passed a function, but {fn_ty:?}"
1609
- ) ;
1610
-
1611
- let param_tys = self . cx . func_params_types ( fn_ty) ;
1612
-
1613
- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1614
- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1615
-
1616
- if all_args_match {
1617
- return Cow :: Borrowed ( args) ;
1618
- }
1619
-
1620
- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1621
- . enumerate ( )
1622
- . map ( |( i, ( expected_ty, & actual_val) ) | {
1623
- let actual_ty = self . cx . val_ty ( actual_val) ;
1624
- if expected_ty != actual_ty {
1625
- debug ! (
1626
- "type mismatch in function call of {:?}. \
1627
- Expected {:?} for param {}, got {:?}; injecting bitcast",
1628
- llfn, expected_ty, i, actual_ty
1629
- ) ;
1630
- self . bitcast ( actual_val, expected_ty)
1631
- } else {
1632
- actual_val
1633
- }
1634
- } )
1635
- . collect ( ) ;
1636
-
1637
- Cow :: Owned ( casted_args)
1638
- }
1639
-
1640
1602
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1641
1603
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1642
1604
}
@@ -1708,6 +1670,93 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1708
1670
self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
1709
1671
}
1710
1672
1673
+ fn autocast (
1674
+ & mut self ,
1675
+ llfn : & ' ll Value ,
1676
+ val : & ' ll Value ,
1677
+ src_ty : & ' ll Type ,
1678
+ dest_ty : & ' ll Type ,
1679
+ is_argument : bool ,
1680
+ ) -> & ' ll Value {
1681
+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1682
+
1683
+ if rust_ty == llvm_ty {
1684
+ return val;
1685
+ }
1686
+
1687
+ match self . type_kind ( llvm_ty) {
1688
+ TypeKind :: Struct => {
1689
+ let mut ret = self . const_poison ( dest_ty) ;
1690
+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1691
+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1692
+ . enumerate ( )
1693
+ {
1694
+ let elt = self . extract_value ( val, idx as u64 ) ;
1695
+ let casted_elt =
1696
+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1697
+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1698
+ }
1699
+ ret
1700
+ }
1701
+ _ => unreachable ! ( ) ,
1702
+ }
1703
+ }
1704
+
1705
+ fn cast_arguments < ' b > (
1706
+ & mut self ,
1707
+ typ : & str ,
1708
+ fn_ty : & ' ll Type ,
1709
+ llfn : & ' ll Value ,
1710
+ args : & ' b [ & ' ll Value ] ,
1711
+ has_fnabi : bool ,
1712
+ ) -> Cow < ' b , [ & ' ll Value ] > {
1713
+ assert_eq ! (
1714
+ self . type_kind( fn_ty) ,
1715
+ TypeKind :: Function ,
1716
+ "{typ} not passed a function, but {fn_ty:?}"
1717
+ ) ;
1718
+
1719
+ let param_tys = self . func_params_types ( fn_ty) ;
1720
+
1721
+ let mut casted_args = Cow :: Borrowed ( args) ;
1722
+
1723
+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1724
+ let src_ty = self . val_ty ( arg) ;
1725
+ assert ! (
1726
+ self . equate_ty( src_ty, dest_ty) ,
1727
+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1728
+ ) ;
1729
+
1730
+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1731
+ if arg != casted_arg {
1732
+ assert ! (
1733
+ has_fnabi,
1734
+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1735
+ ) ;
1736
+
1737
+ casted_args. to_mut ( ) [ idx] = casted_arg;
1738
+ }
1739
+ }
1740
+
1741
+ casted_args
1742
+ }
1743
+
1744
+ fn cast_return (
1745
+ & mut self ,
1746
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1747
+ llfn : & ' ll Value ,
1748
+ ret : & ' ll Value ,
1749
+ ) -> & ' ll Value {
1750
+ let src_ty = self . val_ty ( ret) ;
1751
+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1752
+ assert ! (
1753
+ self . equate_ty( dest_ty, src_ty) ,
1754
+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1755
+ ) ;
1756
+
1757
+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1758
+ }
1759
+
1711
1760
pub ( crate ) fn landing_pad (
1712
1761
& mut self ,
1713
1762
ty : & ' ll Type ,
@@ -1737,7 +1786,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1737
1786
) -> & ' ll Value {
1738
1787
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1739
1788
1740
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1789
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1741
1790
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1742
1791
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1743
1792
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1770,8 +1819,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1770
1819
} ;
1771
1820
if let Some ( fn_abi) = fn_abi {
1772
1821
fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1822
+ self . cast_return ( fn_abi, llfn, callbr)
1823
+ } else {
1824
+ callbr
1773
1825
}
1774
- callbr
1775
1826
}
1776
1827
1777
1828
// Emits CFI pointer type membership tests.
0 commit comments