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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
#![stable(feature = "", since = "1.30.0")]
#![allow(non_camel_case_types)]

//! 与外部函数接口 (FFI) 绑定有关的实用工具。

use crate::fmt;
use crate::marker::PhantomData;
use crate::ops::{Deref, DerefMut};

/// 当用作 [指针][pointer] 时,等效于 C 的 `void` 类型。
///
/// 本质上,`*const c_void` 等效于 C 的 `const void*`,而 `*mut c_void` 等效于 C 的 `void*`。
/// 也就是说,这与 C 的 `void` 返回类型 (即 Rust 的 `()` 类型) 不同。
///
/// 要在 FFI 中对指向不透明类型的指针进行建模,直到 `extern type` 稳定为止,建议在空字节数组周围使用 newtype 包装器。
///
/// 有关详细信息,请参见 [Nomicon]。
///
/// 如果他们想支持低至 1.1.0 的旧 Rust 编译器,则可以使用 `std::os::raw::c_void`。
/// Rust 1.30.0 之后,此定义将其重导出。
/// 有关更多信息,请阅读 [RFC 2521]。
///
/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
/// [RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
///
// 注意,为使 LLVM 能够识别空指针类型,并通过扩展函数 (如 malloc()) 来识别它,我们需要在 LLVM 位码中将其表示为 i8 *。
// 此处使用的枚举可确保这一点,并通过仅拥有私有成员来防止 "raw" 类型的滥用。
// 我们需要两个成员,因为编译器否则会抱怨 repr 属性,并且我们至少需要一个成员,否则枚举将无人居住,并且至少解引用此类指针将是 UB。
//
//
//
//
//
#[repr(u8)]
#[stable(feature = "core_c_void", since = "1.30.0")]
pub enum c_void {
    #[unstable(
        feature = "c_void_variant",
        reason = "temporary implementation detail",
        issue = "none"
    )]
    #[doc(hidden)]
    __variant1,
    #[unstable(
        feature = "c_void_variant",
        reason = "temporary implementation detail",
        issue = "none"
    )]
    #[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.debug_struct("c_void").finish()
    }
}

/// `va_list` 的基本实现。
// 名称为 WIP,现在使用 `VaListImpl`。
#[cfg(any(
    all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
    target_arch = "wasm32",
    target_arch = "asmjs",
    windows
))]
#[repr(transparent)]
#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
    ptr: *mut c_void,

    // 在 `'f` 上不变,因此每个 `VaListImpl<'f>` 对象都绑定到它在以下位置定义的函数的区域
    //
    _marker: PhantomData<&'f mut &'f c_void>,
}

#[cfg(any(
    all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
    target_arch = "wasm32",
    target_arch = "asmjs",
    windows
))]
#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'f> fmt::Debug for VaListImpl<'f> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "va_list* {:p}", self.ptr)
    }
}

/// AArch64 `va_list` 的 ABI 实现。
/// 有关更多详细信息,请参见 [AArch64 Procedure Call Standard]。
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(
    target_arch = "aarch64",
    not(any(target_os = "macos", target_os = "ios")),
    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"
)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
    stack: *mut c_void,
    gr_top: *mut c_void,
    vr_top: *mut c_void,
    gr_offs: i32,
    vr_offs: i32,
    _marker: PhantomData<&'f mut &'f c_void>,
}

/// PowerPC `va_list` 的 ABI 实现。
#[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"
)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
    gpr: u8,
    fpr: u8,
    reserved: u16,
    overflow_arg_area: *mut c_void,
    reg_save_area: *mut c_void,
    _marker: PhantomData<&'f mut &'f c_void>,
}

/// x86_64 `va_list` 的 ABI 实现。
#[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"
)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
    gp_offset: i32,
    fp_offset: i32,
    overflow_arg_area: *mut c_void,
    reg_save_area: *mut c_void,
    _marker: PhantomData<&'f mut &'f c_void>,
}

/// `va_list` 的包装
#[repr(transparent)]
#[derive(Debug)]
#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
pub struct VaList<'a, 'f: 'a> {
    #[cfg(any(
        all(
            not(target_arch = "aarch64"),
            not(target_arch = "powerpc"),
            not(target_arch = "x86_64")
        ),
        all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
        target_arch = "wasm32",
        target_arch = "asmjs",
        windows
    ))]
    inner: VaListImpl<'f>,

    #[cfg(all(
        any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
        any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
        not(target_arch = "wasm32"),
        not(target_arch = "asmjs"),
        not(windows)
    ))]
    inner: &'a mut VaListImpl<'f>,

    _marker: PhantomData<&'a mut VaListImpl<'f>>,
}

#[cfg(any(
    all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
    all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
    target_arch = "wasm32",
    target_arch = "asmjs",
    windows
))]
#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'f> VaListImpl<'f> {
    /// 将 `VaListImpl` 转换为与 C 的 `va_list` 二进制兼容的 `VaList`。
    #[inline]
    pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
        VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
    }
}

#[cfg(all(
    any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
    any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
    not(target_arch = "wasm32"),
    not(target_arch = "asmjs"),
    not(windows)
))]
#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'f> VaListImpl<'f> {
    /// 将 `VaListImpl` 转换为与 C 的 `va_list` 二进制兼容的 `VaList`。
    #[inline]
    pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
        VaList { inner: self, _marker: PhantomData }
    }
}

#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'a, 'f: 'a> Deref for VaList<'a, 'f> {
    type Target = VaListImpl<'f>;

    #[inline]
    fn deref(&self) -> &VaListImpl<'f> {
        &self.inner
    }
}

#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
    #[inline]
    fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
        &mut self.inner
    }
}

// 必须在公共接口中使用 VaArgSafe trait,但是,不允许在该模块之外使用 trait 本身。
// 允许用户为新类型实现 trait (从而允许在新类型上使用 va_arg 内联函数) 可能会导致未定义的行为。
//
// FIXME(dlrobertson): 为了在公共接口中使用 VaArgSafe trait 并确保不能在其他地方使用它,trait 需要在私有模块中是公共的。
// RFC 2145 实现后,可以考虑对此进行改进。
//
//
//
//
mod sealed_trait {
    /// Trait,允许将允许的类型与 [super::VaListImpl::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 {}

#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'f> VaListImpl<'f> {
    /// 前进到下一个 arg。
    #[inline]
    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
        // SAFETY: 调用者必须坚持 `va_arg` 的安全保证。
        unsafe { va_arg(self) }
    }

    /// 在当前位置复制 `va_list`。
    pub unsafe fn with_copy<F, R>(&self, f: F) -> R
    where
        F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R,
    {
        let mut ap = self.clone();
        let ret = f(ap.as_va_list());
        // SAFETY: 调用者必须坚持 `va_end` 的安全保证。
        unsafe {
            va_end(&mut ap);
        }
        ret
    }
}

#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'f> Clone for VaListImpl<'f> {
    #[inline]
    fn clone(&self) -> Self {
        let mut dest = crate::mem::MaybeUninit::uninit();
        // SAFETY: 我们写入 `MaybeUninit`,因此它被初始化并且 `assume_init` 是合法的
        unsafe {
            va_copy(dest.as_mut_ptr(), self);
            dest.assume_init()
        }
    }
}

#[unstable(
    feature = "c_variadic",
    reason = "the `c_variadic` feature has not been properly tested on \
              all supported platforms",
    issue = "44930"
)]
impl<'f> Drop for VaListImpl<'f> {
    fn drop(&mut self) {
        // FIXME: 这应该调用 `va_end`,但是没有干净的方法来保证 `drop` 总是内联到其调用程序中,因此 `va_end` 将直接从与相应 `va_copy` 相同的函数中调用。
        //
        // `man va_end` 声明 C 要求这样做,并且 LLVM 基本遵循 C 语义,因此我们需要确保始终从与 `va_copy` 相同的函数调用 `va_end`。
        // 更多细节, see https://github.com/rust-lang/rust/pull/59625andhttps://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic.
        //
        // 由于 `va_end` 是当前所有 LLVM 目标上的无操作项,因此,该操作现在有效。
        //
        //
        //
        //
    }
}

extern "rust-intrinsic" {
    /// 用 `va_start` 或 `va_copy` 初始化后,销毁参数列表 `ap`。
    ///
    fn va_end(ap: &mut VaListImpl<'_>);

    /// 将 arglist `src` 的当前位置复制到 arglist `dst`。
    fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);

    /// 从 `va_list` `ap` 加载 `T` 类型的参数,并将 `ap` 指向的参数递增。
    ///
    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
}