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