Skip to content

Commit b837f5b

Browse files
committed
Auto merge of #53173 - alexcrichton:win-arm64, r=sfackler
Start adding an `aarch64-pc-windows-msvc` target This commit adds the necessary definitions for target specs and such as well as the necessary support in libstd to compile basic `aarch64-pc-windows-msvc` binaries. The target is not currently built on CI, but it can be built locally with: ./configure --target=aarch64-pc-windows-msvc --set rust.lld ./x.py build src/libstd --target aarch64-pc-windows-msvc Currently this fails to build `libtest` due to a linker bug (seemingly in LLD?) which hasn't been investigate yet. Otherwise though with libstd you can build a hello world program (linked with LLD). I've not tried to execute it yet, but it at least links! Full support for this target is still a long road ahead, but this is hopefully a good stepping stone to get started. Points of note about this target are: * Currently defaults to `panic=abort` as support is still landing in LLVM for SEH on AArch64. * Currently defaults to LLD as a linker as I was able to get farther with it than I was with `link.exe`
2 parents 142bb27 + fccc04d commit b837f5b

File tree

8 files changed

+201
-33
lines changed

8 files changed

+201
-33
lines changed
File renamed without changes.

src/libpanic_unwind/lib.rs

+26-29
Original file line numberDiff line numberDiff line change
@@ -55,36 +55,33 @@ use core::mem;
5555
use core::raw;
5656
use core::panic::BoxMeUp;
5757

58-
// Rust runtime's startup objects depend on these symbols, so make them public.
59-
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
60-
pub use imp::eh_frame_registry::*;
58+
#[macro_use]
59+
mod macros;
6160

62-
// *-pc-windows-msvc
63-
#[cfg(target_env = "msvc")]
64-
#[path = "seh.rs"]
65-
mod imp;
66-
67-
// x86_64-pc-windows-gnu
68-
#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))]
69-
#[path = "seh64_gnu.rs"]
70-
mod imp;
71-
72-
// i686-pc-windows-gnu and all others
73-
#[cfg(any(all(unix, not(target_os = "emscripten")),
74-
target_os = "cloudabi",
75-
target_os = "redox",
76-
all(windows, target_arch = "x86", target_env = "gnu")))]
77-
#[path = "gcc.rs"]
78-
mod imp;
79-
80-
// emscripten
81-
#[cfg(target_os = "emscripten")]
82-
#[path = "emcc.rs"]
83-
mod imp;
84-
85-
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
86-
#[path = "wasm32.rs"]
87-
mod imp;
61+
cfg_if! {
62+
if #[cfg(target_os = "emscripten")] {
63+
#[path = "emcc.rs"]
64+
mod imp;
65+
} else if #[cfg(target_arch = "wasm32")] {
66+
#[path = "dummy.rs"]
67+
mod imp;
68+
} else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
69+
#[path = "dummy.rs"]
70+
mod imp;
71+
} else if #[cfg(target_env = "msvc")] {
72+
#[path = "seh.rs"]
73+
mod imp;
74+
} else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
75+
#[path = "seh64_gnu.rs"]
76+
mod imp;
77+
} else {
78+
// Rust runtime's startup objects depend on these symbols, so make them public.
79+
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
80+
pub use imp::eh_frame_registry::*;
81+
#[path = "gcc.rs"]
82+
mod imp;
83+
}
84+
}
8885

8986
mod dwarf;
9087
mod windows;

src/libpanic_unwind/macros.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
/// A macro for defining `#[cfg]` if-else statements.
12+
///
13+
/// This is similar to the `if/elif` C preprocessor macro by allowing definition
14+
/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
15+
/// first.
16+
///
17+
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
18+
/// without having to rewrite each clause multiple times.
19+
macro_rules! cfg_if {
20+
($(
21+
if #[cfg($($meta:meta),*)] { $($it:item)* }
22+
) else * else {
23+
$($it2:item)*
24+
}) => {
25+
__cfg_if_items! {
26+
() ;
27+
$( ( ($($meta),*) ($($it)*) ), )*
28+
( () ($($it2)*) ),
29+
}
30+
}
31+
}
32+
33+
macro_rules! __cfg_if_items {
34+
(($($not:meta,)*) ; ) => {};
35+
(($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
36+
__cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* }
37+
__cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
38+
}
39+
}
40+
41+
macro_rules! __cfg_if_apply {
42+
($m:meta, $($it:item)*) => {
43+
$(#[$m] $it)*
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};
12+
13+
pub fn target() -> TargetResult {
14+
let mut base = super::windows_msvc_base::opts();
15+
base.max_atomic_width = Some(64);
16+
base.has_elf_tls = true;
17+
18+
// FIXME: this shouldn't be panic=abort, it should be panic=unwind
19+
base.panic_strategy = PanicStrategy::Abort;
20+
base.linker = Some("rust-lld".to_owned());
21+
22+
Ok(Target {
23+
llvm_target: "aarch64-pc-windows-msvc".to_string(),
24+
target_endian: "little".to_string(),
25+
target_pointer_width: "64".to_string(),
26+
target_c_int_width: "32".to_string(),
27+
data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
28+
arch: "aarch64".to_string(),
29+
target_os: "windows".to_string(),
30+
target_env: "msvc".to_string(),
31+
target_vendor: "pc".to_string(),
32+
linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
33+
options: base,
34+
})
35+
}

src/librustc_target/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ supported_targets! {
355355
("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
356356
("i686-pc-windows-gnu", i686_pc_windows_gnu),
357357

358+
("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
358359
("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
359360
("i686-pc-windows-msvc", i686_pc_windows_msvc),
360361
("i586-pc-windows-msvc", i586_pc_windows_msvc),

src/libstd/sys/windows/backtrace/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ impl StackFrame for c::STACKFRAME_EX {
229229
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
230230
c::IMAGE_FILE_MACHINE_I386
231231
}
232+
232233
#[cfg(target_arch = "x86_64")]
233234
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
234235
self.AddrPC.Offset = ctx.Rip as u64;
@@ -240,6 +241,17 @@ impl StackFrame for c::STACKFRAME_EX {
240241
c::IMAGE_FILE_MACHINE_AMD64
241242
}
242243

244+
#[cfg(target_arch = "aarch64")]
245+
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
246+
self.AddrPC.Offset = ctx.Pc as u64;
247+
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
248+
self.AddrStack.Offset = ctx.Sp as u64;
249+
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
250+
self.AddrFrame.Offset = ctx.Fp as u64;
251+
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
252+
c::IMAGE_FILE_MACHINE_ARM64
253+
}
254+
243255
fn get_addr(&self) -> *const u8 {
244256
(self.AddrPC.Offset - 1) as *const u8
245257
}
@@ -260,6 +272,7 @@ impl StackFrame for c::STACKFRAME64 {
260272
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
261273
c::IMAGE_FILE_MACHINE_I386
262274
}
275+
263276
#[cfg(target_arch = "x86_64")]
264277
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
265278
self.AddrPC.Offset = ctx.Rip as u64;
@@ -271,6 +284,17 @@ impl StackFrame for c::STACKFRAME64 {
271284
c::IMAGE_FILE_MACHINE_AMD64
272285
}
273286

287+
#[cfg(target_arch = "aarch64")]
288+
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
289+
self.AddrPC.Offset = ctx.Pc as u64;
290+
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
291+
self.AddrStack.Offset = ctx.Sp as u64;
292+
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
293+
self.AddrFrame.Offset = ctx.Fp as u64;
294+
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
295+
c::IMAGE_FILE_MACHINE_ARM64
296+
}
297+
274298
fn get_addr(&self) -> *const u8 {
275299
(self.AddrPC.Offset - 1) as *const u8
276300
}

src/libstd/sys/windows/c.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,9 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
280280
#[cfg(target_arch = "x86_64")]
281281
#[cfg(feature = "backtrace")]
282282
pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
283+
#[cfg(target_arch = "aarch64")]
284+
#[cfg(feature = "backtrace")]
285+
pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
283286

284287
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
285288
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
@@ -791,9 +794,68 @@ pub struct FLOATING_SAVE_AREA {
791794
// will not appear in the final documentation. This should be also defined for
792795
// other architectures supported by Windows such as ARM, and for historical
793796
// interest, maybe MIPS and PowerPC as well.
794-
#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
797+
#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
795798
pub enum CONTEXT {}
796799

800+
#[cfg(target_arch = "aarch64")]
801+
pub const ARM64_MAX_BREAKPOINTS: usize = 8;
802+
803+
#[cfg(target_arch = "aarch64")]
804+
pub const ARM64_MAX_WATCHPOINTS: usize = 2;
805+
806+
#[cfg(target_arch = "aarch64")]
807+
#[repr(C)]
808+
pub struct ARM64_NT_NEON128 {
809+
pub D: [f64; 2],
810+
}
811+
812+
#[cfg(target_arch = "aarch64")]
813+
#[repr(C, align(16))]
814+
pub struct CONTEXT {
815+
pub ContextFlags: DWORD,
816+
pub Cpsr: DWORD,
817+
pub X0: u64,
818+
pub X1: u64,
819+
pub X2: u64,
820+
pub X3: u64,
821+
pub X4: u64,
822+
pub X5: u64,
823+
pub X6: u64,
824+
pub X7: u64,
825+
pub X8: u64,
826+
pub X9: u64,
827+
pub X10: u64,
828+
pub X11: u64,
829+
pub X12: u64,
830+
pub X13: u64,
831+
pub X14: u64,
832+
pub X15: u64,
833+
pub X16: u64,
834+
pub X17: u64,
835+
pub X18: u64,
836+
pub X19: u64,
837+
pub X20: u64,
838+
pub X21: u64,
839+
pub X22: u64,
840+
pub X23: u64,
841+
pub X24: u64,
842+
pub X25: u64,
843+
pub X26: u64,
844+
pub X27: u64,
845+
pub X28: u64,
846+
pub Fp: u64,
847+
pub Lr: u64,
848+
pub Sp: u64,
849+
pub Pc: u64,
850+
pub V: [ARM64_NT_NEON128; 32],
851+
pub Fpcr: DWORD,
852+
pub Fpsr: DWORD,
853+
pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
854+
pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
855+
pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
856+
pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
857+
}
858+
797859
#[repr(C)]
798860
pub struct SOCKADDR_STORAGE_LH {
799861
pub ss_family: ADDRESS_FAMILY,

src/libstd/sys/windows/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
266266
// handlers.
267267
//
268268
// https://msdn.microsoft.com/en-us/library/dn774154.aspx
269-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
269+
#[allow(unreachable_code)]
270270
pub unsafe fn abort_internal() -> ! {
271-
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
272-
::intrinsics::unreachable();
271+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
272+
{
273+
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
274+
::intrinsics::unreachable();
275+
}
276+
::intrinsics::abort();
273277
}

0 commit comments

Comments
 (0)