Skip to content

Commit 63b6007

Browse files
committed
Work around potential merging/duplication issues in sys/windows/compat.
1 parent 09cbaf4 commit 63b6007

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

library/std/src/sys/windows/compat.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,28 @@ macro_rules! compat_fn {
3838
use crate::sync::atomic::{AtomicUsize, Ordering};
3939
use crate::mem;
4040

41+
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
42+
4143
static PTR: AtomicUsize = AtomicUsize::new(0);
4244

4345
#[allow(unused_variables)]
4446
unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body
4547

48+
/// This address is stored in `PTR` to incidate an unavailable API.
49+
///
50+
/// This way, call() will end up calling fallback() if it is unavailable.
51+
///
52+
/// This is a `static` to avoid rustc duplicating `fn fallback()`
53+
/// into both load() and is_available(), which would break
54+
/// is_available()'s comparison. By using the same static variable
55+
/// in both places, they'll refer to the same (copy of the)
56+
/// function.
57+
///
58+
/// LLVM merging the address of fallback with other functions
59+
/// (because of unnamed_addr) is fine, since it's only compared to
60+
/// an address from GetProcAddress from an external dll.
61+
static FALLBACK: F = fallback;
62+
4663
#[cold]
4764
fn load() -> usize {
4865
// There is no locking here. It's okay if this is executed by multiple threads in
@@ -51,7 +68,7 @@ macro_rules! compat_fn {
5168
// about memory ordering, as this involves just a single atomic variable which is
5269
// not used to protect or order anything else.
5370
let addr = crate::sys::compat::lookup($module, stringify!($symbol))
54-
.unwrap_or(fallback as usize);
71+
.unwrap_or(FALLBACK as usize);
5572
PTR.store(addr, Ordering::Relaxed);
5673
addr
5774
}
@@ -65,11 +82,10 @@ macro_rules! compat_fn {
6582

6683
#[allow(dead_code)]
6784
pub fn is_available() -> bool {
68-
addr() != fallback as usize
85+
addr() != FALLBACK as usize
6986
}
7087

7188
pub unsafe fn call($($argname: $argtype),*) -> $rettype {
72-
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
7389
mem::transmute::<usize, F>(addr())($($argname),*)
7490
}
7591
}

0 commit comments

Comments
 (0)