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`
This commit is contained in:
commit
b837f5be70
8 changed files with 201 additions and 33 deletions
|
@ -55,36 +55,33 @@ use core::mem;
|
|||
use core::raw;
|
||||
use core::panic::BoxMeUp;
|
||||
|
||||
// Rust runtime's startup objects depend on these symbols, so make them public.
|
||||
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
||||
pub use imp::eh_frame_registry::*;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// *-pc-windows-msvc
|
||||
#[cfg(target_env = "msvc")]
|
||||
#[path = "seh.rs"]
|
||||
mod imp;
|
||||
|
||||
// x86_64-pc-windows-gnu
|
||||
#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))]
|
||||
#[path = "seh64_gnu.rs"]
|
||||
mod imp;
|
||||
|
||||
// i686-pc-windows-gnu and all others
|
||||
#[cfg(any(all(unix, not(target_os = "emscripten")),
|
||||
target_os = "cloudabi",
|
||||
target_os = "redox",
|
||||
all(windows, target_arch = "x86", target_env = "gnu")))]
|
||||
#[path = "gcc.rs"]
|
||||
mod imp;
|
||||
|
||||
// emscripten
|
||||
#[cfg(target_os = "emscripten")]
|
||||
#[path = "emcc.rs"]
|
||||
mod imp;
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
||||
#[path = "wasm32.rs"]
|
||||
mod imp;
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "emscripten")] {
|
||||
#[path = "emcc.rs"]
|
||||
mod imp;
|
||||
} else if #[cfg(target_arch = "wasm32")] {
|
||||
#[path = "dummy.rs"]
|
||||
mod imp;
|
||||
} else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
|
||||
#[path = "dummy.rs"]
|
||||
mod imp;
|
||||
} else if #[cfg(target_env = "msvc")] {
|
||||
#[path = "seh.rs"]
|
||||
mod imp;
|
||||
} else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
|
||||
#[path = "seh64_gnu.rs"]
|
||||
mod imp;
|
||||
} else {
|
||||
// Rust runtime's startup objects depend on these symbols, so make them public.
|
||||
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
||||
pub use imp::eh_frame_registry::*;
|
||||
#[path = "gcc.rs"]
|
||||
mod imp;
|
||||
}
|
||||
}
|
||||
|
||||
mod dwarf;
|
||||
mod windows;
|
||||
|
|
45
src/libpanic_unwind/macros.rs
Normal file
45
src/libpanic_unwind/macros.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// A macro for defining `#[cfg]` if-else statements.
|
||||
///
|
||||
/// This is similar to the `if/elif` C preprocessor macro by allowing definition
|
||||
/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
|
||||
/// first.
|
||||
///
|
||||
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
|
||||
/// without having to rewrite each clause multiple times.
|
||||
macro_rules! cfg_if {
|
||||
($(
|
||||
if #[cfg($($meta:meta),*)] { $($it:item)* }
|
||||
) else * else {
|
||||
$($it2:item)*
|
||||
}) => {
|
||||
__cfg_if_items! {
|
||||
() ;
|
||||
$( ( ($($meta),*) ($($it)*) ), )*
|
||||
( () ($($it2)*) ),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! __cfg_if_items {
|
||||
(($($not:meta,)*) ; ) => {};
|
||||
(($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
|
||||
__cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* }
|
||||
__cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! __cfg_if_apply {
|
||||
($m:meta, $($it:item)*) => {
|
||||
$(#[$m] $it)*
|
||||
}
|
||||
}
|
35
src/librustc_target/spec/aarch64_pc_windows_msvc.rs
Normal file
35
src/librustc_target/spec/aarch64_pc_windows_msvc.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::windows_msvc_base::opts();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.has_elf_tls = true;
|
||||
|
||||
// FIXME: this shouldn't be panic=abort, it should be panic=unwind
|
||||
base.panic_strategy = PanicStrategy::Abort;
|
||||
base.linker = Some("rust-lld".to_owned());
|
||||
|
||||
Ok(Target {
|
||||
llvm_target: "aarch64-pc-windows-msvc".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "64".to_string(),
|
||||
target_c_int_width: "32".to_string(),
|
||||
data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
|
||||
arch: "aarch64".to_string(),
|
||||
target_os: "windows".to_string(),
|
||||
target_env: "msvc".to_string(),
|
||||
target_vendor: "pc".to_string(),
|
||||
linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
|
||||
options: base,
|
||||
})
|
||||
}
|
|
@ -355,6 +355,7 @@ supported_targets! {
|
|||
("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
|
||||
("i686-pc-windows-gnu", i686_pc_windows_gnu),
|
||||
|
||||
("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
|
||||
("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
|
||||
("i686-pc-windows-msvc", i686_pc_windows_msvc),
|
||||
("i586-pc-windows-msvc", i586_pc_windows_msvc),
|
||||
|
|
|
@ -229,6 +229,7 @@ impl StackFrame for c::STACKFRAME_EX {
|
|||
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
c::IMAGE_FILE_MACHINE_I386
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
|
||||
self.AddrPC.Offset = ctx.Rip as u64;
|
||||
|
@ -240,6 +241,17 @@ impl StackFrame for c::STACKFRAME_EX {
|
|||
c::IMAGE_FILE_MACHINE_AMD64
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
|
||||
self.AddrPC.Offset = ctx.Pc as u64;
|
||||
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
self.AddrStack.Offset = ctx.Sp as u64;
|
||||
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
self.AddrFrame.Offset = ctx.Fp as u64;
|
||||
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
c::IMAGE_FILE_MACHINE_ARM64
|
||||
}
|
||||
|
||||
fn get_addr(&self) -> *const u8 {
|
||||
(self.AddrPC.Offset - 1) as *const u8
|
||||
}
|
||||
|
@ -260,6 +272,7 @@ impl StackFrame for c::STACKFRAME64 {
|
|||
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
c::IMAGE_FILE_MACHINE_I386
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
|
||||
self.AddrPC.Offset = ctx.Rip as u64;
|
||||
|
@ -271,6 +284,17 @@ impl StackFrame for c::STACKFRAME64 {
|
|||
c::IMAGE_FILE_MACHINE_AMD64
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
|
||||
self.AddrPC.Offset = ctx.Pc as u64;
|
||||
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
self.AddrStack.Offset = ctx.Sp as u64;
|
||||
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
self.AddrFrame.Offset = ctx.Fp as u64;
|
||||
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
|
||||
c::IMAGE_FILE_MACHINE_ARM64
|
||||
}
|
||||
|
||||
fn get_addr(&self) -> *const u8 {
|
||||
(self.AddrPC.Offset - 1) as *const u8
|
||||
}
|
||||
|
|
|
@ -280,6 +280,9 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(feature = "backtrace")]
|
||||
pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[cfg(feature = "backtrace")]
|
||||
pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
|
||||
|
||||
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
|
||||
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
|
||||
|
@ -791,9 +794,68 @@ pub struct FLOATING_SAVE_AREA {
|
|||
// will not appear in the final documentation. This should be also defined for
|
||||
// other architectures supported by Windows such as ARM, and for historical
|
||||
// interest, maybe MIPS and PowerPC as well.
|
||||
#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
|
||||
#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
|
||||
pub enum CONTEXT {}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const ARM64_MAX_BREAKPOINTS: usize = 8;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub const ARM64_MAX_WATCHPOINTS: usize = 2;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[repr(C)]
|
||||
pub struct ARM64_NT_NEON128 {
|
||||
pub D: [f64; 2],
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[repr(C, align(16))]
|
||||
pub struct CONTEXT {
|
||||
pub ContextFlags: DWORD,
|
||||
pub Cpsr: DWORD,
|
||||
pub X0: u64,
|
||||
pub X1: u64,
|
||||
pub X2: u64,
|
||||
pub X3: u64,
|
||||
pub X4: u64,
|
||||
pub X5: u64,
|
||||
pub X6: u64,
|
||||
pub X7: u64,
|
||||
pub X8: u64,
|
||||
pub X9: u64,
|
||||
pub X10: u64,
|
||||
pub X11: u64,
|
||||
pub X12: u64,
|
||||
pub X13: u64,
|
||||
pub X14: u64,
|
||||
pub X15: u64,
|
||||
pub X16: u64,
|
||||
pub X17: u64,
|
||||
pub X18: u64,
|
||||
pub X19: u64,
|
||||
pub X20: u64,
|
||||
pub X21: u64,
|
||||
pub X22: u64,
|
||||
pub X23: u64,
|
||||
pub X24: u64,
|
||||
pub X25: u64,
|
||||
pub X26: u64,
|
||||
pub X27: u64,
|
||||
pub X28: u64,
|
||||
pub Fp: u64,
|
||||
pub Lr: u64,
|
||||
pub Sp: u64,
|
||||
pub Pc: u64,
|
||||
pub V: [ARM64_NT_NEON128; 32],
|
||||
pub Fpcr: DWORD,
|
||||
pub Fpsr: DWORD,
|
||||
pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
|
||||
pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
|
||||
pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
|
||||
pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SOCKADDR_STORAGE_LH {
|
||||
pub ss_family: ADDRESS_FAMILY,
|
||||
|
|
|
@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
|
|||
// handlers.
|
||||
//
|
||||
// https://msdn.microsoft.com/en-us/library/dn774154.aspx
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
#[allow(unreachable_code)]
|
||||
pub unsafe fn abort_internal() -> ! {
|
||||
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
|
||||
::intrinsics::unreachable();
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
{
|
||||
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
|
||||
::intrinsics::unreachable();
|
||||
}
|
||||
::intrinsics::abort();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue