@@ -70,7 +70,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
7070 ) -> & ' ll Value {
7171 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
7272
73- let args = self . check_call ( "call" , llty, llfn, args) ;
7473 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
7574 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
7675 if let Some ( funclet_bundle) = funclet_bundle {
@@ -414,7 +413,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
414413 ) -> & ' ll Value {
415414 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
416415
417- let args = self . check_call ( "invoke" , llty, llfn, args) ;
416+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
418417 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
419418 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
420419 if let Some ( funclet_bundle) = funclet_bundle {
@@ -446,8 +445,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
446445 } ;
447446 if let Some ( fn_abi) = fn_abi {
448447 fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
448+ self . cast_return ( fn_abi, llfn, invoke)
449+ } else {
450+ invoke
449451 }
450- invoke
451452 }
452453
453454 fn unreachable ( & mut self ) {
@@ -1395,7 +1396,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13951396 ) -> & ' ll Value {
13961397 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
13971398
1398- let args = self . check_call ( "call" , llty, llfn, args) ;
1399+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
13991400 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
14001401 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
14011402 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1448,8 +1449,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14481449
14491450 if let Some ( fn_abi) = fn_abi {
14501451 fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1452+ self . cast_return ( fn_abi, llfn, call)
1453+ } else {
1454+ call
14511455 }
1452- call
14531456 }
14541457
14551458 fn tail_call (
@@ -1630,47 +1633,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16301633 ret. expect ( "LLVM does not have support for catchret" )
16311634 }
16321635
1633- fn check_call < ' b > (
1634- & mut self ,
1635- typ : & str ,
1636- fn_ty : & ' ll Type ,
1637- llfn : & ' ll Value ,
1638- args : & ' b [ & ' ll Value ] ,
1639- ) -> Cow < ' b , [ & ' ll Value ] > {
1640- assert ! (
1641- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1642- "builder::{typ} not passed a function, but {fn_ty:?}"
1643- ) ;
1644-
1645- let param_tys = self . cx . func_params_types ( fn_ty) ;
1646-
1647- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1648- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1649-
1650- if all_args_match {
1651- return Cow :: Borrowed ( args) ;
1652- }
1653-
1654- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1655- . enumerate ( )
1656- . map ( |( i, ( expected_ty, & actual_val) ) | {
1657- let actual_ty = self . cx . val_ty ( actual_val) ;
1658- if expected_ty != actual_ty {
1659- debug ! (
1660- "type mismatch in function call of {:?}. \
1661- Expected {:?} for param {}, got {:?}; injecting bitcast",
1662- llfn, expected_ty, i, actual_ty
1663- ) ;
1664- self . bitcast ( actual_val, expected_ty)
1665- } else {
1666- actual_val
1667- }
1668- } )
1669- . collect ( ) ;
1670-
1671- Cow :: Owned ( casted_args)
1672- }
1673-
16741636 pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
16751637 unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
16761638 }
@@ -1726,6 +1688,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
17261688 }
17271689}
17281690impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1691+ fn autocast (
1692+ & mut self ,
1693+ llfn : & ' ll Value ,
1694+ val : & ' ll Value ,
1695+ src_ty : & ' ll Type ,
1696+ dest_ty : & ' ll Type ,
1697+ is_argument : bool ,
1698+ ) -> & ' ll Value {
1699+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1700+
1701+ if rust_ty == llvm_ty {
1702+ return val;
1703+ }
1704+
1705+ match self . type_kind ( llvm_ty) {
1706+ TypeKind :: Struct => {
1707+ let mut ret = self . const_poison ( dest_ty) ;
1708+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1709+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1710+ . enumerate ( )
1711+ {
1712+ let elt = self . extract_value ( val, idx as u64 ) ;
1713+ let casted_elt =
1714+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1715+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1716+ }
1717+ ret
1718+ }
1719+ _ => unreachable ! ( ) ,
1720+ }
1721+ }
1722+
1723+ fn cast_arguments < ' b > (
1724+ & mut self ,
1725+ typ : & str ,
1726+ fn_ty : & ' ll Type ,
1727+ llfn : & ' ll Value ,
1728+ args : & ' b [ & ' ll Value ] ,
1729+ has_fnabi : bool ,
1730+ ) -> Cow < ' b , [ & ' ll Value ] > {
1731+ assert_eq ! (
1732+ self . type_kind( fn_ty) ,
1733+ TypeKind :: Function ,
1734+ "{typ} not passed a function, but {fn_ty:?}"
1735+ ) ;
1736+
1737+ let param_tys = self . func_params_types ( fn_ty) ;
1738+
1739+ let mut casted_args = Cow :: Borrowed ( args) ;
1740+
1741+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1742+ let src_ty = self . val_ty ( arg) ;
1743+ assert ! (
1744+ self . equate_ty( src_ty, dest_ty) ,
1745+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1746+ ) ;
1747+
1748+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1749+ if arg != casted_arg {
1750+ assert ! (
1751+ has_fnabi,
1752+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1753+ ) ;
1754+
1755+ casted_args. to_mut ( ) [ idx] = casted_arg;
1756+ }
1757+ }
1758+
1759+ casted_args
1760+ }
1761+
1762+ fn cast_return (
1763+ & mut self ,
1764+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1765+ llfn : & ' ll Value ,
1766+ ret : & ' ll Value ,
1767+ ) -> & ' ll Value {
1768+ let src_ty = self . val_ty ( ret) ;
1769+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1770+ assert ! (
1771+ self . equate_ty( dest_ty, src_ty) ,
1772+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1773+ ) ;
1774+
1775+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1776+ }
1777+
17291778 pub ( crate ) fn landing_pad (
17301779 & mut self ,
17311780 ty : & ' ll Type ,
@@ -1755,7 +1804,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17551804 ) -> & ' ll Value {
17561805 debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
17571806
1758- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1807+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
17591808 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
17601809 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
17611810 if let Some ( funclet_bundle) = funclet_bundle {
@@ -1788,8 +1837,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17881837 } ;
17891838 if let Some ( fn_abi) = fn_abi {
17901839 fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1840+ self . cast_return ( fn_abi, llfn, callbr)
1841+ } else {
1842+ callbr
17911843 }
1792- callbr
17931844 }
17941845
17951846 // Emits CFI pointer type membership tests.
0 commit comments