@@ -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