@@ -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 {
@@ -415,7 +414,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
415414 ) -> & ' ll Value {
416415 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
417416
418- let args = self . check_call ( "invoke" , llty, llfn, args) ;
417+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
419418 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
420419 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
421420 if let Some ( funclet_bundle) = funclet_bundle {
@@ -447,8 +446,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
447446 } ;
448447 if let Some ( fn_abi) = fn_abi {
449448 fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
449+ self . cast_return ( fn_abi, llfn, invoke)
450+ } else {
451+ invoke
450452 }
451- invoke
452453 }
453454
454455 fn unreachable ( & mut self ) {
@@ -1401,7 +1402,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14011402 ) -> & ' ll Value {
14021403 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
14031404
1404- let args = self . check_call ( "call" , llty, llfn, args) ;
1405+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
14051406 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
14061407 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
14071408 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1454,8 +1455,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14541455
14551456 if let Some ( fn_abi) = fn_abi {
14561457 fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1458+ self . cast_return ( fn_abi, llfn, call)
1459+ } else {
1460+ call
14571461 }
1458- call
14591462 }
14601463
14611464 fn tail_call (
@@ -1645,47 +1648,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16451648 ret. expect ( "LLVM does not have support for catchret" )
16461649 }
16471650
1648- fn check_call < ' b > (
1649- & mut self ,
1650- typ : & str ,
1651- fn_ty : & ' ll Type ,
1652- llfn : & ' ll Value ,
1653- args : & ' b [ & ' ll Value ] ,
1654- ) -> Cow < ' b , [ & ' ll Value ] > {
1655- assert ! (
1656- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1657- "builder::{typ} not passed a function, but {fn_ty:?}"
1658- ) ;
1659-
1660- let param_tys = self . cx . func_params_types ( fn_ty) ;
1661-
1662- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1663- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1664-
1665- if all_args_match {
1666- return Cow :: Borrowed ( args) ;
1667- }
1668-
1669- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1670- . enumerate ( )
1671- . map ( |( i, ( expected_ty, & actual_val) ) | {
1672- let actual_ty = self . cx . val_ty ( actual_val) ;
1673- if expected_ty != actual_ty {
1674- debug ! (
1675- "type mismatch in function call of {:?}. \
1676- Expected {:?} for param {}, got {:?}; injecting bitcast",
1677- llfn, expected_ty, i, actual_ty
1678- ) ;
1679- self . bitcast ( actual_val, expected_ty)
1680- } else {
1681- actual_val
1682- }
1683- } )
1684- . collect ( ) ;
1685-
1686- Cow :: Owned ( casted_args)
1687- }
1688-
16891651 pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
16901652 unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
16911653 }
@@ -1741,6 +1703,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
17411703 }
17421704}
17431705impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1706+ fn autocast (
1707+ & mut self ,
1708+ llfn : & ' ll Value ,
1709+ val : & ' ll Value ,
1710+ src_ty : & ' ll Type ,
1711+ dest_ty : & ' ll Type ,
1712+ is_argument : bool ,
1713+ ) -> & ' ll Value {
1714+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1715+
1716+ if rust_ty == llvm_ty {
1717+ return val;
1718+ }
1719+
1720+ match self . type_kind ( llvm_ty) {
1721+ TypeKind :: Struct => {
1722+ let mut ret = self . const_poison ( dest_ty) ;
1723+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1724+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1725+ . enumerate ( )
1726+ {
1727+ let elt = self . extract_value ( val, idx as u64 ) ;
1728+ let casted_elt =
1729+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1730+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1731+ }
1732+ ret
1733+ }
1734+ _ => unreachable ! ( ) ,
1735+ }
1736+ }
1737+
1738+ fn cast_arguments < ' b > (
1739+ & mut self ,
1740+ typ : & str ,
1741+ fn_ty : & ' ll Type ,
1742+ llfn : & ' ll Value ,
1743+ args : & ' b [ & ' ll Value ] ,
1744+ has_fnabi : bool ,
1745+ ) -> Cow < ' b , [ & ' ll Value ] > {
1746+ assert_eq ! (
1747+ self . type_kind( fn_ty) ,
1748+ TypeKind :: Function ,
1749+ "{typ} not passed a function, but {fn_ty:?}"
1750+ ) ;
1751+
1752+ let param_tys = self . func_params_types ( fn_ty) ;
1753+
1754+ let mut casted_args = Cow :: Borrowed ( args) ;
1755+
1756+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1757+ let src_ty = self . val_ty ( arg) ;
1758+ assert ! (
1759+ self . equate_ty( src_ty, dest_ty) ,
1760+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1761+ ) ;
1762+
1763+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1764+ if arg != casted_arg {
1765+ assert ! (
1766+ has_fnabi,
1767+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1768+ ) ;
1769+
1770+ casted_args. to_mut ( ) [ idx] = casted_arg;
1771+ }
1772+ }
1773+
1774+ casted_args
1775+ }
1776+
1777+ fn cast_return (
1778+ & mut self ,
1779+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1780+ llfn : & ' ll Value ,
1781+ ret : & ' ll Value ,
1782+ ) -> & ' ll Value {
1783+ let src_ty = self . val_ty ( ret) ;
1784+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1785+ assert ! (
1786+ self . equate_ty( dest_ty, src_ty) ,
1787+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1788+ ) ;
1789+
1790+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1791+ }
1792+
17441793 pub ( crate ) fn landing_pad (
17451794 & mut self ,
17461795 ty : & ' ll Type ,
@@ -1770,7 +1819,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17701819 ) -> & ' ll Value {
17711820 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
17721821
1773- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1822+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
17741823 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
17751824 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
17761825 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1803,8 +1852,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
18031852 } ;
18041853 if let Some ( fn_abi) = fn_abi {
18051854 fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1855+ self . cast_return ( fn_abi, llfn, callbr)
1856+ } else {
1857+ callbr
18061858 }
1807- callbr
18081859 }
18091860
18101861 // Emits CFI pointer type membership tests.
0 commit comments