      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228

    #![stable(feature = "", since = "1.30.0")]

    #![allow(non_camel_case_types)]

    //! Utilities related to FFI bindings.

    use ::fmt;

    /// Equivalent to C's `void` type when used as a [pointer].
    ///
    /// In essence, `*const c_void` is equivalent to C's `const void*`
    /// and `*mut c_void` is equivalent to C's `void*`. That said, this is
    /// *not* the same as C's `void` return type, which is Rust's `()` type.
    ///
    /// To model pointers to opaque types in FFI, until `extern type` is
    /// stabilized, it is recommended to use a newtype wrapper around an empty
    /// byte array. See the [Nomicon] for details.
    ///
    /// [pointer]: ../../std/primitive.pointer.html
    /// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
    // N.B., for LLVM to recognize the void pointer type and by extension
    //     functions like malloc(), we need to have it represented as i8* in
    //     LLVM bitcode. The enum used here ensures this and prevents misuse
    //     of the "raw" type by only having private variants. We need two
    //     variants, because the compiler complains about the repr attribute
    //     otherwise and we need at least one variant as otherwise the enum
    //     would be uninhabited and at least dereferencing such pointers would
    //     be UB.
    #[repr(u8)]
    #[stable(feature = "raw_os", since = "1.1.0")]
    pub enum c_void {
        #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
                   issue = "0")]
        #[doc(hidden)] __variant1,
        #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
                   issue = "0")]
        #[doc(hidden)] __variant2,
    }

    #[stable(feature = "std_debug", since = "1.16.0")]
    impl fmt::Debug for c_void {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            f.pad("c_void")
        }
    }

    /// Basic implementation of a `va_list`.
    #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                  not(target_arch = "x86_64")),
              all(target_arch = "aarch4", target_os = "ios"),
              windows))]
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    extern {
        type VaListImpl;
    }

    #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                  not(target_arch = "x86_64")),
              windows))]
    impl fmt::Debug for VaListImpl {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "va_list* {:p}", self)
        }
    }

    /// AArch64 ABI implementation of a `va_list`. See the
    /// [Aarch64 Procedure Call Standard] for more details.
    ///
    /// [AArch64 Procedure Call Standard]:
    /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
    #[cfg(all(target_arch = "aarch64", not(windows)))]
    #[repr(C)]
    #[derive(Debug)]
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    struct VaListImpl {
        stack: *mut (),
        gr_top: *mut (),
        vr_top: *mut (),
        gr_offs: i32,
        vr_offs: i32,
    }

    /// PowerPC ABI implementation of a `va_list`.
    #[cfg(all(target_arch = "powerpc", not(windows)))]
    #[repr(C)]
    #[derive(Debug)]
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    struct VaListImpl {
        gpr: u8,
        fpr: u8,
        reserved: u16,
        overflow_arg_area: *mut (),
        reg_save_area: *mut (),
    }

    /// x86_64 ABI implementation of a `va_list`.
    #[cfg(all(target_arch = "x86_64", not(windows)))]
    #[repr(C)]
    #[derive(Debug)]
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    struct VaListImpl {
        gp_offset: i32,
        fp_offset: i32,
        overflow_arg_area: *mut (),
        reg_save_area: *mut (),
    }

    /// A wrapper for a `va_list`
    #[lang = "va_list"]
    #[derive(Debug)]
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    #[repr(transparent)]
    pub struct VaList<'a>(&'a mut VaListImpl);

    // The VaArgSafe trait needs to be used in public interfaces, however, the trait
    // itself must not be allowed to be used outside this module. Allowing users to
    // implement the trait for a new type (thereby allowing the va_arg intrinsic to
    // be used on a new type) is likely to cause undefined behavior.
    //
    // FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
    // but also ensure it cannot be used elsewhere, the trait needs to be public
    // within a private module. Once RFC 2145 has been implemented look into
    // improving this.
    mod sealed_trait {
        /// Trait which whitelists the allowed types to be used with [VaList::arg]
        ///
        /// [VaList::va_arg]: struct.VaList.html#method.arg
        #[unstable(feature = "c_variadic",
                   reason = "the `c_variadic` feature has not been properly tested on \
                             all supported platforms",
                   issue = "44930")]
        pub trait VaArgSafe {}
    }

    macro_rules! impl_va_arg_safe {
        ($($t:ty),+) => {
            $(
                #[unstable(feature = "c_variadic",
                           reason = "the `c_variadic` feature has not been properly tested on \
                                     all supported platforms",
                           issue = "44930")]
                impl sealed_trait::VaArgSafe for $t {}
            )+
        }
    }

    impl_va_arg_safe!{i8, i16, i32, i64, usize}
    impl_va_arg_safe!{u8, u16, u32, u64, isize}
    impl_va_arg_safe!{f64}

    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    impl<T> sealed_trait::VaArgSafe for *mut T {}
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    impl<T> sealed_trait::VaArgSafe for *const T {}

    impl<'a> VaList<'a> {
        /// Advance to the next arg.
        #[unstable(feature = "c_variadic",
                   reason = "the `c_variadic` feature has not been properly tested on \
                             all supported platforms",
                   issue = "44930")]
        pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
            va_arg(self)
        }

        /// Copies the `va_list` at the current location.
        #[unstable(feature = "c_variadic",
                   reason = "the `c_variadic` feature has not been properly tested on \
                             all supported platforms",
                   issue = "44930")]
        pub unsafe fn copy<F, R>(&self, f: F) -> R
                where F: for<'copy> FnOnce(VaList<'copy>) -> R {
            #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                          not(target_arch = "x86_64")),
                      all(target_arch = "aarch4", target_os = "ios"),
                      windows))]
            let mut ap = va_copy(self);
            #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                      not(windows)))]
            let mut ap_inner = va_copy(self);
            #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                      not(windows)))]
            let mut ap = VaList(&mut ap_inner);
            let ret = f(VaList(ap.0));
            va_end(&mut ap);
            ret
        }
    }

    extern "rust-intrinsic" {
        /// Destroy the arglist `ap` after initialization with `va_start` or
        /// `va_copy`.
        fn va_end(ap: &mut VaList);

        /// Copies the current location of arglist `src` to the arglist `dst`.
        #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                      not(target_arch = "x86_64")),
                  windows))]
        fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>;
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        fn va_copy(src: &VaList) -> VaListImpl;

        /// Loads an argument of type `T` from the `va_list` `ap` and increment the
        /// argument `ap` points to.
        fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaList) -> T;
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)