@@ -66,7 +66,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
66
66
) -> & ' ll Value {
67
67
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
68
68
69
- let args = self . check_call ( "call" , llty, llfn, args) ;
70
69
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
71
70
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
72
71
if let Some ( funclet_bundle) = funclet_bundle {
@@ -348,7 +347,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
348
347
) -> & ' ll Value {
349
348
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
350
349
351
- let args = self . check_call ( "invoke" , llty, llfn, args) ;
350
+ let args = self . cast_arguments ( "invoke" , llty, llfn, args, fn_abi . is_some ( ) ) ;
352
351
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
353
352
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
354
353
if let Some ( funclet_bundle) = funclet_bundle {
@@ -380,8 +379,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
380
379
} ;
381
380
if let Some ( fn_abi) = fn_abi {
382
381
fn_abi. apply_attrs_callsite ( self , invoke, llfn) ;
382
+ self . cast_return ( fn_abi, llfn, invoke)
383
+ } else {
384
+ invoke
383
385
}
384
- invoke
385
386
}
386
387
387
388
fn unreachable ( & mut self ) {
@@ -1343,7 +1344,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1343
1344
) -> & ' ll Value {
1344
1345
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
1345
1346
1346
- let args = self . check_call ( "call" , llty, llfn, args) ;
1347
+ let args = self . cast_arguments ( "call" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1347
1348
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1348
1349
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1349
1350
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1373,8 +1374,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1373
1374
} ;
1374
1375
if let Some ( fn_abi) = fn_abi {
1375
1376
fn_abi. apply_attrs_callsite ( self , call, llfn) ;
1377
+ self . cast_return ( fn_abi, llfn, call)
1378
+ } else {
1379
+ call
1376
1380
}
1377
- call
1378
1381
}
1379
1382
1380
1383
fn zext ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
@@ -1541,47 +1544,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1541
1544
ret. expect ( "LLVM does not have support for catchret" )
1542
1545
}
1543
1546
1544
- fn check_call < ' b > (
1545
- & mut self ,
1546
- typ : & str ,
1547
- fn_ty : & ' ll Type ,
1548
- llfn : & ' ll Value ,
1549
- args : & ' b [ & ' ll Value ] ,
1550
- ) -> Cow < ' b , [ & ' ll Value ] > {
1551
- assert ! (
1552
- self . cx. type_kind( fn_ty) == TypeKind :: Function ,
1553
- "builder::{typ} not passed a function, but {fn_ty:?}"
1554
- ) ;
1555
-
1556
- let param_tys = self . cx . func_params_types ( fn_ty) ;
1557
-
1558
- let all_args_match = iter:: zip ( & param_tys, args. iter ( ) . map ( |& v| self . cx . val_ty ( v) ) )
1559
- . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1560
-
1561
- if all_args_match {
1562
- return Cow :: Borrowed ( args) ;
1563
- }
1564
-
1565
- let casted_args: Vec < _ > = iter:: zip ( param_tys, args)
1566
- . enumerate ( )
1567
- . map ( |( i, ( expected_ty, & actual_val) ) | {
1568
- let actual_ty = self . cx . val_ty ( actual_val) ;
1569
- if expected_ty != actual_ty {
1570
- debug ! (
1571
- "type mismatch in function call of {:?}. \
1572
- Expected {:?} for param {}, got {:?}; injecting bitcast",
1573
- llfn, expected_ty, i, actual_ty
1574
- ) ;
1575
- self . bitcast ( actual_val, expected_ty)
1576
- } else {
1577
- actual_val
1578
- }
1579
- } )
1580
- . collect ( ) ;
1581
-
1582
- Cow :: Owned ( casted_args)
1583
- }
1584
-
1585
1547
pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
1586
1548
unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
1587
1549
}
@@ -1633,6 +1595,93 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1633
1595
}
1634
1596
}
1635
1597
impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1598
+ fn autocast (
1599
+ & mut self ,
1600
+ llfn : & ' ll Value ,
1601
+ val : & ' ll Value ,
1602
+ src_ty : & ' ll Type ,
1603
+ dest_ty : & ' ll Type ,
1604
+ is_argument : bool ,
1605
+ ) -> & ' ll Value {
1606
+ let ( rust_ty, llvm_ty) = if is_argument { ( src_ty, dest_ty) } else { ( dest_ty, src_ty) } ;
1607
+
1608
+ if rust_ty == llvm_ty {
1609
+ return val;
1610
+ }
1611
+
1612
+ match self . type_kind ( llvm_ty) {
1613
+ TypeKind :: Struct => {
1614
+ let mut ret = self . const_poison ( dest_ty) ;
1615
+ for ( idx, ( src_element_ty, dest_element_ty) ) in
1616
+ iter:: zip ( self . struct_element_types ( src_ty) , self . struct_element_types ( dest_ty) )
1617
+ . enumerate ( )
1618
+ {
1619
+ let elt = self . extract_value ( val, idx as u64 ) ;
1620
+ let casted_elt =
1621
+ self . autocast ( llfn, elt, src_element_ty, dest_element_ty, is_argument) ;
1622
+ ret = self . insert_value ( ret, casted_elt, idx as u64 ) ;
1623
+ }
1624
+ ret
1625
+ }
1626
+ _ => unreachable ! ( ) ,
1627
+ }
1628
+ }
1629
+
1630
+ fn cast_arguments < ' b > (
1631
+ & mut self ,
1632
+ typ : & str ,
1633
+ fn_ty : & ' ll Type ,
1634
+ llfn : & ' ll Value ,
1635
+ args : & ' b [ & ' ll Value ] ,
1636
+ has_fnabi : bool ,
1637
+ ) -> Cow < ' b , [ & ' ll Value ] > {
1638
+ assert_eq ! (
1639
+ self . type_kind( fn_ty) ,
1640
+ TypeKind :: Function ,
1641
+ "{typ} not passed a function, but {fn_ty:?}"
1642
+ ) ;
1643
+
1644
+ let param_tys = self . func_params_types ( fn_ty) ;
1645
+
1646
+ let mut casted_args = Cow :: Borrowed ( args) ;
1647
+
1648
+ for ( idx, ( dest_ty, & arg) ) in iter:: zip ( param_tys, args) . enumerate ( ) {
1649
+ let src_ty = self . val_ty ( arg) ;
1650
+ assert ! (
1651
+ self . equate_ty( src_ty, dest_ty) ,
1652
+ "Cannot match `{dest_ty:?}` (expected) with `{src_ty:?}` (found) in `{llfn:?}`"
1653
+ ) ;
1654
+
1655
+ let casted_arg = self . autocast ( llfn, arg, src_ty, dest_ty, true ) ;
1656
+ if arg != casted_arg {
1657
+ assert ! (
1658
+ has_fnabi,
1659
+ "Should inject autocasts in function call of {llfn:?}, but not able to get Rust signature"
1660
+ ) ;
1661
+
1662
+ casted_args. to_mut ( ) [ idx] = casted_arg;
1663
+ }
1664
+ }
1665
+
1666
+ casted_args
1667
+ }
1668
+
1669
+ fn cast_return (
1670
+ & mut self ,
1671
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1672
+ llfn : & ' ll Value ,
1673
+ ret : & ' ll Value ,
1674
+ ) -> & ' ll Value {
1675
+ let src_ty = self . val_ty ( ret) ;
1676
+ let dest_ty = fn_abi. llvm_return_type ( self ) ;
1677
+ assert ! (
1678
+ self . equate_ty( dest_ty, src_ty) ,
1679
+ "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{llfn:?}`"
1680
+ ) ;
1681
+
1682
+ self . autocast ( llfn, ret, src_ty, dest_ty, false )
1683
+ }
1684
+
1636
1685
pub ( crate ) fn landing_pad (
1637
1686
& mut self ,
1638
1687
ty : & ' ll Type ,
@@ -1662,7 +1711,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1662
1711
) -> & ' ll Value {
1663
1712
debug ! ( "invoke {:?} with args ({:?})" , llfn, args) ;
1664
1713
1665
- let args = self . check_call ( "callbr" , llty, llfn, args) ;
1714
+ let args = self . cast_arguments ( "callbr" , llty, llfn, args, fn_abi . is_some ( ) ) ;
1666
1715
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
1667
1716
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
1668
1717
if let Some ( funclet_bundle) = funclet_bundle {
@@ -1695,8 +1744,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1695
1744
} ;
1696
1745
if let Some ( fn_abi) = fn_abi {
1697
1746
fn_abi. apply_attrs_callsite ( self , callbr, llfn) ;
1747
+ self . cast_return ( fn_abi, llfn, callbr)
1748
+ } else {
1749
+ callbr
1698
1750
}
1699
- callbr
1700
1751
}
1701
1752
1702
1753
// Emits CFI pointer type membership tests.
0 commit comments