@@ -229,27 +229,80 @@ impl TargetTriple {
229
229
#[ cfg( windows) ]
230
230
fn inner ( ) -> Option < TargetTriple > {
231
231
use std:: mem;
232
- use winapi:: um:: sysinfoapi:: GetNativeSystemInfo ;
233
232
234
- // First detect architecture
235
- const PROCESSOR_ARCHITECTURE_AMD64 : u16 = 9 ;
236
- const PROCESSOR_ARCHITECTURE_INTEL : u16 = 0 ;
237
- const PROCESSOR_ARCHITECTURE_ARM64 : u16 = 12 ;
233
+ /// Get the host architecture using `IsWow64Process2`. This function
234
+ /// produces the most accurate results (supports detecting aarch64), but
235
+ /// it is only available on Windows 10 1511+, so we use `GetProcAddress`
236
+ /// to maintain backward compatibility with older Windows versions.
237
+ fn arch_primary ( ) -> Option < & ' static str > {
238
+ use winapi:: shared:: minwindef:: BOOL ;
239
+ use winapi:: um:: libloaderapi:: { GetModuleHandleA , GetProcAddress } ;
240
+ use winapi:: um:: processthreadsapi:: GetCurrentProcess ;
241
+ use winapi:: um:: winnt:: HANDLE ;
242
+
243
+ const IMAGE_FILE_MACHINE_ARM64 : u16 = 0xAA64 ;
244
+ const IMAGE_FILE_MACHINE_AMD64 : u16 = 0x8664 ;
245
+ const IMAGE_FILE_MACHINE_I386 : u16 = 0x014c ;
246
+
247
+ #[ allow( non_snake_case) ]
248
+ let IsWow64Process2 : unsafe extern "system" fn (
249
+ HANDLE ,
250
+ * mut u16 ,
251
+ * mut u16 ,
252
+ )
253
+ -> BOOL = unsafe {
254
+ let module = GetModuleHandleA ( b"kernel32.dll\0 " as * const u8 as * const i8 ) ;
255
+ if module. is_null ( ) {
256
+ return None ;
257
+ }
258
+ let process =
259
+ GetProcAddress ( module, b"IsWow64Process2\0 " as * const u8 as * const i8 ) ;
260
+ if process. is_null ( ) {
261
+ return None ;
262
+ }
263
+ mem:: transmute ( process)
264
+ } ;
238
265
239
- let mut sys_info;
240
- unsafe {
241
- sys_info = mem:: zeroed ( ) ;
242
- GetNativeSystemInfo ( & mut sys_info) ;
266
+ let mut _machine = 0 ;
267
+ let mut native_machine = 0 ;
268
+ unsafe {
269
+ // cannot fail; handle does not need to be closed.
270
+ let process = GetCurrentProcess ( ) ;
271
+ if IsWow64Process2 ( process, & mut _machine, & mut native_machine) == 0 {
272
+ return None ;
273
+ }
274
+ } ;
275
+ match native_machine {
276
+ IMAGE_FILE_MACHINE_AMD64 => Some ( "x86_64" ) ,
277
+ IMAGE_FILE_MACHINE_I386 => Some ( "i686" ) ,
278
+ IMAGE_FILE_MACHINE_ARM64 => Some ( "aarch64" ) ,
279
+ _ => None ,
280
+ }
243
281
}
244
282
245
- let arch = match unsafe { sys_info. u . s ( ) } . wProcessorArchitecture {
246
- PROCESSOR_ARCHITECTURE_AMD64 => "x86_64" ,
247
- PROCESSOR_ARCHITECTURE_INTEL => "i686" ,
248
- PROCESSOR_ARCHITECTURE_ARM64 => "aarch64" ,
249
- _ => return None ,
250
- } ;
283
+ /// Get the host architecture using `GetNativeSystemInfo`.
284
+ /// Does not support detecting aarch64.
285
+ fn arch_fallback ( ) -> Option < & ' static str > {
286
+ use winapi:: um:: sysinfoapi:: GetNativeSystemInfo ;
287
+
288
+ const PROCESSOR_ARCHITECTURE_AMD64 : u16 = 9 ;
289
+ const PROCESSOR_ARCHITECTURE_INTEL : u16 = 0 ;
290
+
291
+ let mut sys_info;
292
+ unsafe {
293
+ sys_info = mem:: zeroed ( ) ;
294
+ GetNativeSystemInfo ( & mut sys_info) ;
295
+ }
296
+
297
+ match unsafe { sys_info. u . s ( ) } . wProcessorArchitecture {
298
+ PROCESSOR_ARCHITECTURE_AMD64 => Some ( "x86_64" ) ,
299
+ PROCESSOR_ARCHITECTURE_INTEL => Some ( "i686" ) ,
300
+ _ => None ,
301
+ }
302
+ }
251
303
252
304
// Default to msvc
305
+ let arch = arch_primary ( ) . or_else ( arch_fallback) ?;
253
306
let msvc_triple = format ! ( "{}-pc-windows-msvc" , arch) ;
254
307
Some ( TargetTriple ( msvc_triple) )
255
308
}
@@ -328,12 +381,13 @@ impl TargetTriple {
328
381
let ret = if partial_self. os != partial_other. os {
329
382
false
330
383
} else if partial_self. os . as_deref ( ) == Some ( "pc-windows" ) {
331
- // Windows is a special case here, we know we can run 32bit on 64bit
332
- // and we know we can run gnu and msvc on the same system
333
- // We don't immediately assume we can cross between x86 and aarch64 though
384
+ // Windows is a special case here: we can run gnu and msvc on the same system,
385
+ // x86_64 can run i686, and aarch64 can run i686 through emulation
334
386
( partial_self. arch == partial_other. arch )
335
387
|| ( partial_self. arch . as_deref ( ) == Some ( "x86_64" )
336
388
&& partial_other. arch . as_deref ( ) == Some ( "i686" ) )
389
+ || ( partial_self. arch . as_deref ( ) == Some ( "aarch64" )
390
+ && partial_other. arch . as_deref ( ) == Some ( "i686" ) )
337
391
} else {
338
392
// For other OSes, for now, we assume other toolchains won't run
339
393
false
0 commit comments