Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS target support #7506

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,10 @@ jobs:
- run: cargo install --root ${{ runner.tool_cache }}/cargo-ndk --version ${{ env.CARGO_NDK_VERSION }} cargo-ndk
- run: cargo ndk -t arm64-v8a check -p wasmtime

# Check whether `wasmtime` cross-compiles to aarch64-apple-ios
- run: rustup target add aarch64-apple-ios
- run: cargo check -p wasmtime --target aarch64-apple-ios

# common logic to cancel the entire run if this job fails
- run: gh run cancel ${{ github.run_id }}
if: failure() && github.event_name != 'pull_request'
Expand Down
7 changes: 5 additions & 2 deletions cranelift/native/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub fn infer_native_flags(isa_builder: &mut dyn Configurable) -> Result<(), &'st
isa_builder.enable("has_pauth").unwrap();
}

if cfg!(target_os = "macos") {
if cfg!(any(target_os = "macos", target_os = "ios")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something that I think may need to be confirmed. The comment below for example is incorrect since not all iOS devices will run on Apple Silicon, but I'm sure all recent ones do. That being said I don't know the story for return-address-signing on iOS and whether or not it's different than macOS.

// Pointer authentication is always available on Apple Silicon.
isa_builder.enable("sign_return_address").unwrap();
// macOS enforces the use of the B key for return addresses.
Expand Down Expand Up @@ -167,7 +167,10 @@ mod tests {
.finish(settings::Flags::new(flag_builder))
.unwrap();

if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
if cfg!(all(
any(target_os = "macos", target_os = "ios"),
target_arch = "aarch64"
)) {
Comment on lines +170 to +173
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also something to watch out for once you're at the point you can run some code. This block is true for macOS but iOS may very well be different in its calling convention. I'm not sure either way (or where to look it up), so it's mostly something to watch out for to see if apps crash when you load them.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can see from https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms, it doesn't look like macOS and iOS have different calling conventions on arm64.

assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64);
} else if cfg!(any(unix, target_os = "nebulet")) {
assert_eq!(isa.default_call_conv(), CallConv::SystemV);
Expand Down
2 changes: 1 addition & 1 deletion crates/asm-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! should be visible to Rust but not visible externally outside of a `*.so`.

cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
if #[cfg(any(target_os = "macos", target_os = "ios"))] {
#[macro_export]
macro_rules! asm_func {
($name:expr, $body:expr $(, $($args:tt)*)?) => {
Expand Down
2 changes: 1 addition & 1 deletion crates/fiber/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ mod tests {
// TODO: apparently windows unwind routines don't unwind through fibers, so this will always fail. Is there a way we can fix that?
|| cfg!(windows)
// TODO: the system libunwind is broken (#2808)
|| cfg!(all(target_os = "macos", target_arch = "aarch64"))
|| cfg!(all(any(target_os = "macos", target_os = "ios"), target_arch = "aarch64"))
);
}

Expand Down
2 changes: 1 addition & 1 deletion crates/fiber/src/unix/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use super::wasmtime_fiber_start;
use wasmtime_asm_macros::asm_func;

cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
if #[cfg(any(target_os = "macos", target_os = "ios"))] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This relates to my comment about pointer authentication above, because if iOS uses the A key instead of the B key then this block would need to change.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at https://support.apple.com/en-ng/guide/security/sec8b776536b/1/web/1#sec0167b469d, there does not seem to be any indication there are any differences across iOS and macOS regarding which key is used, it always seems to be IB for return addresses.

macro_rules! paci1716 { () => ("pacib1716\n"); }
macro_rules! pacisp { () => ("pacibsp\n"); }
macro_rules! autisp { () => ("autibsp\n"); }
Expand Down
2 changes: 1 addition & 1 deletion crates/jit-icache-coherence/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ features = [
"Win32_System_Diagnostics_Debug",
]

[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd", target_os = "android"))'.dependencies]
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "android"))'.dependencies]
libc = "0.2.42"

[features]
Expand Down
2 changes: 1 addition & 1 deletion crates/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ encoding_rs = { version = "0.8.31", optional = true }
sptr = "0.3.2"
wasm-encoder = { workspace = true }

[target.'cfg(target_os = "macos")'.dependencies]
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
mach = "0.3.2"

[target.'cfg(unix)'.dependencies]
Expand Down
12 changes: 6 additions & 6 deletions crates/runtime/src/traphandlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ cfg_if::cfg_if! {
}
}

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod macos;

pub use sys::SignalHandler;
Expand All @@ -93,7 +93,7 @@ pub use sys::SignalHandler;
static mut IS_WASM_PC: fn(usize) -> bool = |_| false;

/// Whether or not macOS is using mach ports.
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
static mut MACOS_USE_MACH_PORTS: bool = false;

/// This function is required to be called before any WebAssembly is entered.
Expand All @@ -118,15 +118,15 @@ pub fn init_traps(is_wasm_pc: fn(usize) -> bool, macos_use_mach_ports: bool) {

INIT.call_once(|| unsafe {
IS_WASM_PC = is_wasm_pc;
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
if macos_use_mach_ports {
MACOS_USE_MACH_PORTS = macos_use_mach_ports;
return macos::platform_init();
}
sys::platform_init();
});

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
unsafe {
assert_eq!(
MACOS_USE_MACH_PORTS, macos_use_mach_ports,
Expand All @@ -136,7 +136,7 @@ pub fn init_traps(is_wasm_pc: fn(usize) -> bool, macos_use_mach_ports: bool) {
}

fn lazy_per_thread_init() {
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
unsafe {
if MACOS_USE_MACH_PORTS {
return macos::lazy_per_thread_init();
Expand Down Expand Up @@ -489,7 +489,7 @@ impl CallThreadState {
/// instance, and the trap handler should quickly return.
/// * a different pointer - a jmp_buf buffer to longjmp to, meaning that
/// the wasm trap was succesfully handled.
#[cfg_attr(target_os = "macos", allow(dead_code))] // macOS is more raw and doesn't use this
#[cfg_attr(any(target_os = "macos", target_os = "ios"), allow(dead_code))] // macOS is more raw and doesn't use this
fn take_jmp_buf_if_trap(
&self,
pc: *const u8,
Expand Down
14 changes: 8 additions & 6 deletions crates/runtime/src/traphandlers/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub unsafe fn platform_init() {

// Sometimes we need to handle SIGBUS too:
// - On Darwin, guard page accesses are raised as SIGBUS.
if cfg!(target_os = "macos") || cfg!(target_os = "freebsd") {
if cfg!(any(target_os = "macos", target_os = "ios")) || cfg!(target_os = "freebsd") {
register(&mut PREV_SIGBUS, libc::SIGBUS);
}

Expand Down Expand Up @@ -138,7 +138,7 @@ unsafe extern "C" fn trap_handler(
// done running" which will clear the sigaltstack flag and allow
// reusing it for the next signal. Then upon resuming in our custom
// code we blow away the stack anyway with a longjmp.
if cfg!(target_os = "macos") {
if cfg!(any(target_os = "macos", target_os = "ios")) {
unsafe extern "C" fn wasmtime_longjmp_shim(jmp_buf: *const u8) {
wasmtime_longjmp(jmp_buf)
}
Expand Down Expand Up @@ -178,7 +178,7 @@ unsafe extern "C" fn trap_handler(
// more accurate definition. When that PR and/or issue is resolved then this
// should no longer be necessary.
#[repr(C)]
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
#[cfg(all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible you'll want to use libc::ucontext_t instead of this. This structure is one that has a high risk of being different between iOS and macOS. I posted #7507 to remove this structure definition entirely as it's not longer necessary (the PR referenced in the above comment has landed and has been published). I think you should be able to use libc::ucontext_t for iOS, but that depends on the libc crate which I can't say with certainty.

struct ucontext_t {
uc_onstack: libc::c_int,
uc_sigmask: libc::sigset_t,
Expand Down Expand Up @@ -222,13 +222,13 @@ unsafe fn get_pc_and_fp(cx: *mut libc::c_void, _signum: libc::c_int) -> (*const
(cx.uc_mcontext.psw.addr - trap_offset) as *const u8,
*(cx.uc_mcontext.gregs[15] as *const usize),
)
} else if #[cfg(all(target_os = "macos", target_arch = "x86_64"))] {
} else if #[cfg(all(any(target_os = "macos", target_os = "ios"), target_arch = "x86_64"))] {
let cx = &*(cx as *const libc::ucontext_t);
(
(*cx.uc_mcontext).__ss.__rip as *const u8,
(*cx.uc_mcontext).__ss.__rbp as usize,
)
} else if #[cfg(all(target_os = "macos", target_arch = "aarch64"))] {
} else if #[cfg(all(any(target_os = "macos", target_os = "ios"), target_arch = "aarch64"))] {
let cx = &*(cx as *const ucontext_t);
(
(*cx.uc_mcontext).__ss.__pc as *const u8,
Expand Down Expand Up @@ -265,7 +265,9 @@ unsafe fn get_pc_and_fp(cx: *mut libc::c_void, _signum: libc::c_int) -> (*const
// See more comments above where this is called for what it's doing.
unsafe fn set_pc(cx: *mut libc::c_void, pc: usize, arg1: usize) {
cfg_if::cfg_if! {
if #[cfg(not(target_os = "macos"))] {
if #[cfg(
all(not(target_os = "macos"), not(target_os = "ios"))
)] {
let _ = (cx, pc, arg1);
unreachable!(); // not used on these platforms
} else if #[cfg(target_arch = "x86_64")] {
Expand Down
4 changes: 2 additions & 2 deletions crates/test-programs/artifacts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ pub fn wasi_tests_environment() -> &'static [(&'static str, &'static str)] {
("NO_FDFLAGS_SYNC_SUPPORT", "1"),
]
}
#[cfg(all(unix, not(target_os = "macos")))]
#[cfg(all(unix, all(not(target_os = "macos"), not(target_os = "ios"))))]
{
&[
("ERRNO_MODE_UNIX", "1"),
// cap-std-sync does not support the sync family of fdflags
("NO_FDFLAGS_SYNC_SUPPORT", "1"),
]
}
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
&[
("ERRNO_MODE_MACOS", "1"),
Expand Down
2 changes: 1 addition & 1 deletion crates/wasi/src/preview2/host/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ pub(crate) mod util {
pub fn udp_disconnect<Fd: AsFd>(sockfd: Fd) -> rustix::io::Result<()> {
match rustix::net::connect_unspec(sockfd) {
// BSD platforms return an error even if the UDP socket was disconnected successfully.
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
Err(Errno::INVAL | Errno::AFNOSUPPORT) => Ok(()),
r => r,
}
Expand Down
8 changes: 4 additions & 4 deletions crates/wasi/src/preview2/host/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ impl<T: WasiView> crate::preview2::host::tcp::tcp::HostTcpSocket for T {
util::tcp_accept(listener, Blocking::No)
})?;

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
// Manually inherit socket options from listener. We only have to
// do this on platforms that don't already do this automatically
Expand Down Expand Up @@ -442,7 +442,7 @@ impl<T: WasiView> crate::preview2::host::tcp::tcp::HostTcpSocket for T {
}
}

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
socket.hop_limit = Some(value);
}
Expand All @@ -469,7 +469,7 @@ impl<T: WasiView> crate::preview2::host::tcp::tcp::HostTcpSocket for T {

util::set_socket_recv_buffer_size(socket.tcp_socket(), value)?;

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
socket.receive_buffer_size = Some(value);
}
Expand All @@ -496,7 +496,7 @@ impl<T: WasiView> crate::preview2::host::tcp::tcp::HostTcpSocket for T {

util::set_socket_send_buffer_size(socket.tcp_socket(), value)?;

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
socket.send_buffer_size = Some(value);
}
Expand Down
12 changes: 6 additions & 6 deletions crates/wasi/src/preview2/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ pub struct TcpSocket {
pub(crate) family: SocketAddressFamily,

/// The manually configured buffer size. `None` means: no preference, use system default.
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub(crate) receive_buffer_size: Option<usize>,
/// The manually configured buffer size. `None` means: no preference, use system default.
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub(crate) send_buffer_size: Option<usize>,
/// The manually configured TTL. `None` means: no preference, use system default.
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub(crate) hop_limit: Option<u8>,
}

Expand Down Expand Up @@ -295,11 +295,11 @@ impl TcpSocket {
tcp_state: TcpState::Default,
listen_backlog_size: None,
family,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
receive_buffer_size: None,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
send_buffer_size: None,
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
hop_limit: None,
})
}
Expand Down
5 changes: 4 additions & 1 deletion tests/all/custom_signal_handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#[cfg(any(
target_os = "linux",
all(target_os = "macos", feature = "posix-signals-on-macos")
all(
any(target_os = "macos", target_os = "ios"),
feature = "posix-signals-on-macos"
)
))]
#[cfg(not(miri))]
Comment on lines 1 to 8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a heads up I've posted #7509 which will conflict with this, although what you're doing here of "where macos is needed also allow ios" would also apply to that PR.

mod tests {
Expand Down
12 changes: 6 additions & 6 deletions tests/all/debug/lldb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn lldb_with_script(args: &[&str], script: &str) -> Result<String> {
let mut cmd = Command::new(&lldb_path);

cmd.arg("--batch");
if cfg!(target_os = "macos") {
if cfg!(any(target_os = "macos", target_os = "ios")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok to skip iOS in this file, it's unlikely these tests will ever complete successfully on iOS (and they're disabled by default too)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(ditto for all other tests/all/debug/*.rs files)

cmd.args(&["-o", "settings set plugin.jit-loader.gdb.enable on"]);
}
let mut script_file = NamedTempFile::new()?;
Expand Down Expand Up @@ -60,7 +60,7 @@ fn check_lldb_output(output: &str, directives: &str) -> Result<()> {
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
pub fn test_debug_dwarf_lldb() -> Result<()> {
Expand Down Expand Up @@ -101,7 +101,7 @@ check: exited with status
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
pub fn test_debug_dwarf5_lldb() -> Result<()> {
Expand Down Expand Up @@ -142,7 +142,7 @@ check: exited with status
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
pub fn test_debug_dwarf_ref() -> Result<()> {
Expand Down Expand Up @@ -176,7 +176,7 @@ check: resuming
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
pub fn test_debug_inst_offsets_are_correct_when_branches_are_removed() -> Result<()> {
Expand All @@ -203,7 +203,7 @@ check: exited with status
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
pub fn test_spilled_frame_base_is_accessible() -> Result<()> {
Expand Down
6 changes: 3 additions & 3 deletions tests/all/debug/simulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn check_wat(wat: &str) -> Result<()> {
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
fn test_debug_dwarf_simulate_simple_x86_64() -> Result<()> {
Expand Down Expand Up @@ -58,7 +58,7 @@ fn test_debug_dwarf_simulate_simple_x86_64() -> Result<()> {
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
fn test_debug_dwarf_simulate_with_imports_x86_64() -> Result<()> {
Expand All @@ -79,7 +79,7 @@ fn test_debug_dwarf_simulate_with_imports_x86_64() -> Result<()> {
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
fn test_debug_dwarf_simulate_with_invalid_name_x86_64() -> Result<()> {
Expand Down
6 changes: 3 additions & 3 deletions tests/all/debug/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn check_line_program(wasm_path: &str, directives: &str) -> Result<()> {
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
fn test_debug_dwarf_translate_dead_code() -> Result<()> {
Expand All @@ -70,7 +70,7 @@ check: DW_AT_name ("baz")
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
fn test_debug_dwarf_translate() -> Result<()> {
Expand Down Expand Up @@ -103,7 +103,7 @@ check: DW_AT_decl_line (10)
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
any(target_os = "linux", target_os = "macos", target_os = "ios"),
target_pointer_width = "64"
))]
fn test_debug_dwarf5_translate() -> Result<()> {
Expand Down