@@ -68,7 +68,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
6868 ) -> & ' ll Value {
6969 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
7070
71- let args = self . check_call ( "call" , llty, llfn, args) ;
7271 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
7372 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
7473 if let Some ( funclet_bundle) = funclet_bundle {
@@ -412,7 +411,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
412411 ) -> & ' ll Value {
413412 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
414413
415- let args = self . check_call ( "invoke" , llty, llfn, args) ;
414+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
416415 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
417416 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
418417 if let Some ( funclet_bundle) = funclet_bundle {
@@ -444,8 +443,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
444443 } ;
445444 if let Some ( fn_abi) = fn_abi {
446445 fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
446+ self . cast_return ( fn_abi, llfn, invoke)
447+ } else {
448+ invoke
447449 }
448- invoke
449450 }
450451
451452 fn unreachable ( & mut self ) {
@@ -1393,7 +1394,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13931394 ) -> & ' ll Value {
13941395 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
13951396
1396- let args = self . check_call ( "call" , llty, llfn, args) ;
1397+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
13971398 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
13981399 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
13991400 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1446,8 +1447,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14461447
14471448 if let Some ( fn_abi) = fn_abi {
14481449 fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1450+ self . cast_return ( fn_abi, llfn, call)
1451+ } else {
1452+ call
14491453 }
1450- call
14511454 }
14521455
14531456 fn tail_call (
@@ -1628,47 +1631,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16281631 ret. expect ( "LLVM does not have support for catchret" )
16291632 }
16301633
1631- fn check_call < ' b > (
1632- & mut self ,
1633- typ : & str ,
1634- fn_ty : & ' ll Type ,
1635- llfn : & ' ll Value ,
1636- args : & ' b [ & ' ll Value ] ,
1637- ) -> Cow < ' b , [ & ' ll Value ] > {
1638- assert ! (
1639- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1640- "builder::{typ} not passed a function, but {fn_ty:?}"
1641- ) ;
1642-
1643- let param_tys = self . cx . func_params_types ( fn_ty) ;
1644-
1645- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1646- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1647-
1648- if all_args_match {
1649- return Cow :: Borrowed ( args) ;
1650- }
1651-
1652- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1653- . enumerate ( )
1654- . map ( |( i, ( expected_ty, & actual_val) ) | {
1655- let actual_ty = self . cx . val_ty ( actual_val) ;
1656- if expected_ty != actual_ty {
1657- debug ! (
1658- "type mismatch in function call of {:?}. \
1659- Expected {:?} for param {}, got {:?}; injecting bitcast",
1660- llfn, expected_ty, i, actual_ty
1661- ) ;
1662- self . bitcast ( actual_val, expected_ty)
1663- } else {
1664- actual_val
1665- }
1666- } )
1667- . collect ( ) ;
1668-
1669- Cow :: Owned ( casted_args)
1670- }
1671-
16721634 pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
16731635 unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
16741636 }
@@ -1724,6 +1686,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
17241686 }
17251687}
17261688impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1689+ fn autocast (
1690+ & mut self ,
1691+ llfn : & ' ll Value ,
1692+ val : & ' ll Value ,
1693+ src_ty : & ' ll Type ,
1694+ dest_ty : & ' ll Type ,
1695+ is_argument : bool ,
1696+ ) -> & ' ll Value {
1697+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1698+
1699+ if rust_ty == llvm_ty {
1700+ return val;
1701+ }
1702+
1703+ match self . type_kind ( llvm_ty) {
1704+ TypeKind :: Struct => {
1705+ let mut ret = self . const_poison ( dest_ty) ;
1706+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1707+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1708+ . enumerate ( )
1709+ {
1710+ let elt = self . extract_value ( val, idx as u64 ) ;
1711+ let casted_elt =
1712+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1713+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1714+ }
1715+ ret
1716+ }
1717+ _ => unreachable ! ( ) ,
1718+ }
1719+ }
1720+
1721+ fn cast_arguments < ' b > (
1722+ & mut self ,
1723+ typ : & str ,
1724+ fn_ty : & ' ll Type ,
1725+ llfn : & ' ll Value ,
1726+ args : & ' b [ & ' ll Value ] ,
1727+ has_fnabi : bool ,
1728+ ) -> Cow < ' b , [ & ' ll Value ] > {
1729+ assert_eq ! (
1730+ self . type_kind( fn_ty) ,
1731+ TypeKind :: Function ,
1732+ "{typ} not passed a function, but {fn_ty:?}"
1733+ ) ;
1734+
1735+ let param_tys = self . func_params_types ( fn_ty) ;
1736+
1737+ let mut casted_args = Cow :: Borrowed ( args) ;
1738+
1739+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1740+ let src_ty = self . val_ty ( arg) ;
1741+ assert ! (
1742+ self . equate_ty( src_ty, dest_ty) ,
1743+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1744+ ) ;
1745+
1746+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1747+ if arg != casted_arg {
1748+ assert ! (
1749+ has_fnabi,
1750+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1751+ ) ;
1752+
1753+ casted_args. to_mut ( ) [ idx] = casted_arg;
1754+ }
1755+ }
1756+
1757+ casted_args
1758+ }
1759+
1760+ fn cast_return (
1761+ & mut self ,
1762+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1763+ llfn : & ' ll Value ,
1764+ ret : & ' ll Value ,
1765+ ) -> & ' ll Value {
1766+ let src_ty = self . val_ty ( ret) ;
1767+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1768+ assert ! (
1769+ self . equate_ty( dest_ty, src_ty) ,
1770+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1771+ ) ;
1772+
1773+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1774+ }
1775+
17271776 pub ( crate ) fn landing_pad (
17281777 & mut self ,
17291778 ty : & ' ll Type ,
@@ -1753,7 +1802,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17531802 ) -> & ' ll Value {
17541803 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
17551804
1756- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1805+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
17571806 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
17581807 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
17591808 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1786,8 +1835,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17861835 } ;
17871836 if let Some ( fn_abi) = fn_abi {
17881837 fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1838+ self . cast_return ( fn_abi, llfn, callbr)
1839+ } else {
1840+ callbr
17891841 }
1790- callbr
17911842 }
17921843
17931844 // Emits CFI pointer type membership tests.
0 commit comments