@@ -23,8 +23,8 @@ use super::{CachedLlbb, FunctionCx, LocalRef};
23
23
use crate :: base:: { self , is_call_from_compiler_builtins_to_upstream_monomorphization} ;
24
24
use crate :: common:: { self , IntPredicate } ;
25
25
use crate :: errors:: CompilerBuiltinsCannotCall ;
26
+ use crate :: meth;
26
27
use crate :: traits:: * ;
27
- use crate :: { meth, MemFlags } ;
28
28
29
29
// Indicates if we are in the middle of merging a BB's successor into it. This
30
30
// can happen when BB jumps directly to its successor and the successor has no
@@ -462,7 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
462
462
}
463
463
}
464
464
465
- PassMode :: Cast { cast : cast_ty , pad_i32 : _ } => {
465
+ PassMode :: Cast { cast, pad_i32 : _ } => {
466
466
let op = match self . locals [ mir:: RETURN_PLACE ] {
467
467
LocalRef :: Operand ( op) => op,
468
468
LocalRef :: PendingOperand => bug ! ( "use of return before def" ) ,
@@ -471,23 +471,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
471
471
}
472
472
LocalRef :: UnsizedPlace ( _) => bug ! ( "return type must be sized" ) ,
473
473
} ;
474
- let llslot = match op. val {
475
- Immediate ( _) | Pair ( ..) => {
476
- let scratch = PlaceRef :: alloca ( bx, self . fn_abi . ret . layout ) ;
477
- op. val . store ( bx, scratch) ;
478
- scratch. val . llval
479
- }
480
- Ref ( place_val) => {
481
- assert_eq ! (
482
- place_val. align, op. layout. align. abi,
483
- "return place is unaligned!"
484
- ) ;
485
- place_val. llval
486
- }
487
- ZeroSized => bug ! ( "ZST return value shouldn't be in PassMode::Cast" ) ,
488
- } ;
489
- let ty = bx. cast_backend_type ( cast_ty) ;
490
- bx. load ( ty, llslot, self . fn_abi . ret . layout . align . abi )
474
+ cast. cast_rust_abi_to_other ( bx, op)
491
475
}
492
476
} ;
493
477
bx. ret ( llval) ;
@@ -1460,10 +1444,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1460
1444
_ => { }
1461
1445
}
1462
1446
1463
- // Force by-ref if we have to load through a cast pointer.
1464
- let ( mut llval, align, by_ref) = match op. val {
1465
- Immediate ( _) | Pair ( ..) => match arg. mode {
1466
- PassMode :: Indirect { attrs, .. } => {
1447
+ let llval = match arg. mode {
1448
+ PassMode :: Indirect { attrs, on_stack, .. } => match op. val {
1449
+ Immediate ( _) | Pair ( ..) => {
1467
1450
// Indirect argument may have higher alignment requirements than the type's alignment.
1468
1451
// This can happen, e.g. when passing types with <4 byte alignment on the stack on x86.
1469
1452
let required_align = match attrs. pointee_align {
@@ -1472,17 +1455,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1472
1455
} ;
1473
1456
let scratch = PlaceValue :: alloca ( bx, arg. layout . size , required_align) ;
1474
1457
op. val . store ( bx, scratch. with_type ( arg. layout ) ) ;
1475
- ( scratch. llval , scratch. align , true )
1476
- }
1477
- PassMode :: Cast { .. } => {
1478
- let scratch = PlaceRef :: alloca ( bx, arg. layout ) ;
1479
- op. val . store ( bx, scratch) ;
1480
- ( scratch. val . llval , scratch. val . align , true )
1458
+ scratch. llval
1481
1459
}
1482
- _ => ( op. immediate_or_packed_pair ( bx) , arg. layout . align . abi , false ) ,
1483
- } ,
1484
- Ref ( op_place_val) => match arg. mode {
1485
- PassMode :: Indirect { attrs, .. } => {
1460
+ Ref ( op_place_val) => {
1486
1461
let required_align = match attrs. pointee_align {
1487
1462
Some ( pointee_align) => cmp:: max ( pointee_align, arg. layout . align . abi ) ,
1488
1463
None => arg. layout . align . abi ,
@@ -1493,15 +1468,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1493
1468
// to a higher-aligned alloca.
1494
1469
let scratch = PlaceValue :: alloca ( bx, arg. layout . size , required_align) ;
1495
1470
bx. typed_place_copy ( scratch, op_place_val, op. layout ) ;
1496
- ( scratch. llval , scratch . align , true )
1471
+ scratch. llval
1497
1472
} else {
1498
- ( op_place_val. llval , op_place_val . align , true )
1473
+ op_place_val. llval
1499
1474
}
1500
1475
}
1501
- _ => ( op_place_val. llval , op_place_val. align , true ) ,
1502
- } ,
1503
- ZeroSized => match arg. mode {
1504
- PassMode :: Indirect { on_stack, .. } => {
1476
+ ZeroSized => {
1505
1477
if on_stack {
1506
1478
// It doesn't seem like any target can have `byval` ZSTs, so this assert
1507
1479
// is here to replace a would-be untested codepath.
@@ -1511,59 +1483,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1511
1483
// a pointer for `repr(C)` structs even when empty, so get
1512
1484
// one from an `alloca` (which can be left uninitialized).
1513
1485
let scratch = PlaceRef :: alloca ( bx, arg. layout ) ;
1514
- ( scratch. val . llval , scratch . val . align , true )
1486
+ scratch. val . llval
1515
1487
}
1516
- _ => bug ! ( "ZST {op:?} wasn't ignored, but was passed with abi {arg:?}" ) ,
1517
1488
} ,
1518
- } ;
1519
-
1520
- if by_ref && !arg. is_indirect ( ) {
1521
- // Have to load the argument, maybe while casting it.
1522
- if let PassMode :: Cast { cast, pad_i32 : _ } = & arg. mode {
1523
- // The ABI mandates that the value is passed as a different struct representation.
1524
- // Spill and reload it from the stack to convert from the Rust representation to
1525
- // the ABI representation.
1526
- let scratch_size = cast. size ( bx) ;
1527
- let scratch_align = cast. align ( bx) ;
1528
- // Note that the ABI type may be either larger or smaller than the Rust type,
1529
- // due to the presence or absence of trailing padding. For example:
1530
- // - On some ABIs, the Rust layout { f64, f32, <f32 padding> } may omit padding
1531
- // when passed by value, making it smaller.
1532
- // - On some ABIs, the Rust layout { u16, u16, u16 } may be padded up to 8 bytes
1533
- // when passed by value, making it larger.
1534
- let copy_bytes = cmp:: min ( cast. unaligned_size ( bx) . bytes ( ) , arg. layout . size . bytes ( ) ) ;
1535
- // Allocate some scratch space...
1536
- let llscratch = bx. alloca ( scratch_size, scratch_align) ;
1537
- bx. lifetime_start ( llscratch, scratch_size) ;
1538
- // ...memcpy the value...
1539
- bx. memcpy (
1540
- llscratch,
1541
- scratch_align,
1542
- llval,
1543
- align,
1544
- bx. const_usize ( copy_bytes) ,
1545
- MemFlags :: empty ( ) ,
1546
- ) ;
1547
- // ...and then load it with the ABI type.
1548
- let cast_ty = bx. cast_backend_type ( cast) ;
1549
- llval = bx. load ( cast_ty, llscratch, scratch_align) ;
1550
- bx. lifetime_end ( llscratch, scratch_size) ;
1551
- } else {
1552
- // We can't use `PlaceRef::load` here because the argument
1553
- // may have a type we don't treat as immediate, but the ABI
1554
- // used for this call is passing it by-value. In that case,
1555
- // the load would just produce `OperandValue::Ref` instead
1556
- // of the `OperandValue::Immediate` we need for the call.
1557
- llval = bx. load ( bx. backend_type ( arg. layout ) , llval, align) ;
1558
- if let abi:: Abi :: Scalar ( scalar) = arg. layout . abi {
1559
- if scalar. is_bool ( ) {
1489
+ PassMode :: Cast { ref cast, .. } => cast. cast_rust_abi_to_other ( bx, op) ,
1490
+ _ => match op. val {
1491
+ Immediate ( _) | Pair ( ..) => op. immediate_or_packed_pair ( bx) ,
1492
+ Ref ( op_place_val) => {
1493
+ // We can't use `PlaceRef::load` here because the argument
1494
+ // may have a type we don't treat as immediate, but the ABI
1495
+ // used for this call is passing it by-value. In that case,
1496
+ // the load would just produce `OperandValue::Ref` instead
1497
+ // of the `OperandValue::Immediate` we need for the call.
1498
+ let mut llval = bx. load (
1499
+ bx. backend_type ( arg. layout ) ,
1500
+ op_place_val. llval ,
1501
+ op_place_val. align ,
1502
+ ) ;
1503
+ if let abi:: Abi :: Scalar ( scalar) = arg. layout . abi
1504
+ && scalar. is_bool ( )
1505
+ {
1560
1506
bx. range_metadata ( llval, WrappingRange { start : 0 , end : 1 } ) ;
1561
1507
}
1508
+ // We store bools as `i8` so we need to truncate to `i1`.
1509
+ llval = bx. to_immediate ( llval, arg. layout ) ;
1510
+ llval
1562
1511
}
1563
- // We store bools as `i8` so we need to truncate to `i1`.
1564
- llval = bx. to_immediate ( llval, arg. layout ) ;
1565
- }
1566
- }
1512
+ ZeroSized => bug ! ( "ZST {op:?} wasn't ignored, but was passed with abi {arg:?}" ) ,
1513
+ } ,
1514
+ } ;
1567
1515
1568
1516
llargs. push ( llval) ;
1569
1517
}
0 commit comments