@@ -38,11 +38,28 @@ macro_rules! compat_fn {
38
38
use crate :: sync:: atomic:: { AtomicUsize , Ordering } ;
39
39
use crate :: mem;
40
40
41
+ type F = unsafe extern "system" fn ( $( $argtype) ,* ) -> $rettype;
42
+
41
43
static PTR : AtomicUsize = AtomicUsize :: new( 0 ) ;
42
44
43
45
#[ allow( unused_variables) ]
44
46
unsafe extern "system" fn fallback( $( $argname: $argtype) ,* ) -> $rettype $body
45
47
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
+
46
63
#[ cold]
47
64
fn load( ) -> usize {
48
65
// There is no locking here. It's okay if this is executed by multiple threads in
@@ -51,7 +68,7 @@ macro_rules! compat_fn {
51
68
// about memory ordering, as this involves just a single atomic variable which is
52
69
// not used to protect or order anything else.
53
70
let addr = crate :: sys:: compat:: lookup( $module, stringify!( $symbol) )
54
- . unwrap_or( fallback as usize ) ;
71
+ . unwrap_or( FALLBACK as usize ) ;
55
72
PTR . store( addr, Ordering :: Relaxed ) ;
56
73
addr
57
74
}
@@ -65,11 +82,10 @@ macro_rules! compat_fn {
65
82
66
83
#[ allow( dead_code) ]
67
84
pub fn is_available( ) -> bool {
68
- addr( ) != fallback as usize
85
+ addr( ) != FALLBACK as usize
69
86
}
70
87
71
88
pub unsafe fn call( $( $argname: $argtype) ,* ) -> $rettype {
72
- type F = unsafe extern "system" fn ( $( $argtype) ,* ) -> $rettype;
73
89
mem:: transmute:: <usize , F >( addr( ) ) ( $( $argname) ,* )
74
90
}
75
91
}
0 commit comments