@@ -67,7 +67,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
6767 ) -> & ' ll Value {
6868 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
6969
70- let args = self . check_call ( "call" , llty, llfn, args) ;
7170 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
7271 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
7372 if let Some ( funclet_bundle) = funclet_bundle {
@@ -349,7 +348,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
349348 ) -> & ' ll Value {
350349 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
351350
352- let args = self . check_call ( "invoke" , llty, llfn, args) ;
351+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
353352 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
354353 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
355354 if let Some ( funclet_bundle) = funclet_bundle {
@@ -381,8 +380,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
381380 } ;
382381 if let Some ( fn_abi) = fn_abi {
383382 fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
383+ self . cast_return ( fn_abi, llfn, invoke)
384+ } else {
385+ invoke
384386 }
385- invoke
386387 }
387388
388389 fn unreachable ( & mut self ) {
@@ -1404,7 +1405,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14041405 ) -> & ' ll Value {
14051406 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
14061407
1407- let args = self . check_call ( "call" , llty, llfn, args) ;
1408+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
14081409 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
14091410 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
14101411 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1434,8 +1435,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14341435 } ;
14351436 if let Some ( fn_abi) = fn_abi {
14361437 fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1438+ self . cast_return ( fn_abi, llfn, call)
1439+ } else {
1440+ call
14371441 }
1438- call
14391442 }
14401443
14411444 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> {
15961599 ret. expect ( "LLVM does not have support for catchret" )
15971600 }
15981601
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-
16401602 pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
16411603 unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
16421604 }
@@ -1708,6 +1670,93 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17081670 self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
17091671 }
17101672
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+
17111760 pub ( crate ) fn landing_pad (
17121761 & mut self ,
17131762 ty : & ' ll Type ,
@@ -1737,7 +1786,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17371786 ) -> & ' ll Value {
17381787 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
17391788
1740- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1789+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
17411790 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
17421791 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
17431792 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1770,8 +1819,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17701819 } ;
17711820 if let Some ( fn_abi) = fn_abi {
17721821 fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1822+ self . cast_return ( fn_abi, llfn, callbr)
1823+ } else {
1824+ callbr
17731825 }
1774- callbr
17751826 }
17761827
17771828 // Emits CFI pointer type membership tests.
0 commit comments