@@ -46,17 +46,23 @@ pub enum PassMode {
46
46
///
47
47
/// The argument has a layout abi of `ScalarPair`.
48
48
Pair ( ArgAttributes , ArgAttributes ) ,
49
- /// Pass the argument after casting it. See the `CastTarget` docs for details. The bool
50
- /// indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
49
+ /// Pass the argument after casting it. See the `CastTarget` docs for details.
50
+ ///
51
+ /// `pad_i32` indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
51
52
Cast { pad_i32 : bool , cast : Box < CastTarget > } ,
52
53
/// Pass the argument indirectly via a hidden pointer.
54
+ ///
53
55
/// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
54
56
/// argument. (This is the only mode that supports unsized arguments.)
57
+ ///
55
58
/// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
56
59
/// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
57
- /// attribute (using a byte array type with the same size as the Rust type [which ensures that
58
- /// padding is preserved and that we do not rely on LLVM's struct layout], and with alignment
59
- /// determined in a complex, target-specific manner [see callers of `make_indirect_byval`]).
60
+ /// attribute. The `byval` argument will use a byte array with the same size as the Rust type
61
+ /// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout),
62
+ /// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's
63
+ /// alignment, depending on the target's ABI. This means that the alignment will not always
64
+ /// match the Rust type's alignment; see documentation of `make_indirect_byval` for more info.
65
+ ///
60
66
/// `on_stack` cannot be true for unsized arguments, i.e., when `meta_attrs` is `Some`.
61
67
Indirect { attrs : ArgAttributes , meta_attrs : Option < ArgAttributes > , on_stack : bool } ,
62
68
}
@@ -598,6 +604,8 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
598
604
}
599
605
}
600
606
607
+ /// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead.
608
+ /// This is valid for both sized and unsized arguments.
601
609
pub fn make_indirect ( & mut self ) {
602
610
match self . mode {
603
611
PassMode :: Direct ( _) | PassMode :: Pair ( _, _) => {
@@ -611,7 +619,26 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
611
619
}
612
620
}
613
621
622
+ /// Pass this argument indirectly, by placing it at a fixed stack offset.
623
+ /// This corresponds to the `byval` LLVM argument attribute.
624
+ /// This is only valid for sized arguments.
625
+ ///
626
+ /// `byval_align` specifies the alignment of the `byval` stack slot, which does not need to
627
+ /// correspond to the type's alignment. This will be `Some` if the target's ABI specifies that
628
+ /// stack slots used for arguments passed by-value have specific alignment requirements which
629
+ /// differ from the alignment used in other situations.
630
+ ///
631
+ /// If `None`, the type's alignment is used.
632
+ ///
633
+ /// If the resulting alignment differs from the type's alignment,
634
+ /// the argument will be copied to an alloca with sufficient alignment,
635
+ /// either in the caller (if the type's alignment is lower than the byval alignment)
636
+ /// or in the callee† (if the type's alignment is higher than the byval alignment),
637
+ /// to ensure that Rust code never sees an underaligned pointer.
638
+ ///
639
+ /// † This is currently broken, see <https://github.com/rust-lang/rust/pull/122212>.
614
640
pub fn make_indirect_byval ( & mut self , byval_align : Option < Align > ) {
641
+ assert ! ( !self . layout. is_unsized( ) , "used byval ABI for unsized layout" ) ;
615
642
self . make_indirect ( ) ;
616
643
match self . mode {
617
644
PassMode :: Indirect { ref mut attrs, meta_attrs : _, ref mut on_stack } => {
0 commit comments