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

Implement unwind support for ARM64 Windows #9266

Merged
merged 1 commit into from
Sep 19, 2024

Conversation

dpaoliello
Copy link
Contributor

@dpaoliello dpaoliello commented Sep 17, 2024

Implements unwind support for ARM64 Windows.

This also fixes an issue with the current AArch64 ABI code where it wasn't emitting unwind instructions when adjusting the stack pointer (i.e., doing a stack alloc).

With this change, cargo test passes all tests on my Windows ARM64 device.

Fixes #4992

@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator cranelift:area:aarch64 Issues related to AArch64 backend. wasmtime:api Related to the API of the `wasmtime` crate itself labels Sep 17, 2024
@alexcrichton
Copy link
Member

At a high level this looks great, thanks for working on this! We'll probably be trusting you on the particulars of the table format here, and we unfortunately also probably won't be able to run this on CI (unless you know of way to run this and/or emulation on CI). That being said once you're able to run tests locally that's probably a good enough sign for now and should be good to land afterwards.

It may also be worth noting that the test failures may not be related to unwinding necessarily, I believe Wasmtime has seen very little testing on Windows ARM64 meaning that there could be little other things here and there to overcome as well.

@dpaoliello dpaoliello force-pushed the arm64unwind branch 3 times, most recently from 24d6330 to 9804955 Compare September 18, 2024 18:01
@dpaoliello dpaoliello marked this pull request as ready for review September 18, 2024 18:10
@dpaoliello dpaoliello requested review from a team as code owners September 18, 2024 18:10
@dpaoliello dpaoliello requested review from abrown and fitzgen and removed request for a team September 18, 2024 18:10
Copy link
Member

@cfallin cfallin left a comment

Choose a reason for hiding this comment

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

I made a pass over this code as well and it's generally very high-quality, thanks!

To confirm specifically: does the whole Wasmtime suite (cargo test in the root) pass now on Windows/aarch64?

Echoing Alex's thoughts -- if we can test this somehow (WINE on qemu-aarch64? or does Windows/x64 support running aarch64 binaries with emulation somehow? or ...?) then we can add release binaries.

(There's precedent for adding release binaries before that, from the macOS/aarch64 case -- we just got GitHub runners for that a few months ago -- though in that case there was external CI run by a third party and those of us with new Macs also manually checked when able.)

const LARGE_STACK_ALLOC_MAX: u32 = (1 << 24) * 16;
match size {
0..SMALL_STACK_ALLOC_MAX => {
unwind_codes.push(UnwindCode::SmallStackAlloc { size: size as u16 })
Copy link
Member

Choose a reason for hiding this comment

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

At least in new code, we're trying to avoid as-casts; even though here it's infallibly correct, could we write u16::try_from(size).unwrap() (or .expect("constant max size for this case exceeds u16") or somesuch so that auditing for overflows is a little easier?

Copy link
Contributor Author

@dpaoliello dpaoliello Sep 18, 2024

Choose a reason for hiding this comment

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

Done: removed the as casts.

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

LGTM modulo one nitpick below

Comment on lines 13 to 58
/// The supported unwind codes for the Arm64 Windows ABI.
///
/// See: <https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling>
/// Only what is needed to describe the prologues generated by the Cranelift AArch64 ISA are represented here.
#[allow(dead_code)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub(crate) enum UnwindCode {
/// Save int register, or register pair.
SaveReg {
reg: u8,
stack_offset: u16,
is_pair: bool,
},
/// Save floating point register, or register pair.
SaveFReg {
reg: u8,
stack_offset: u16,
is_pair: bool,
},
/// Save frame-pointer register (X29) and LR register pair.
SaveFpLrPair {
stack_offset: u16,
},
SmallStackAlloc {
size: u16,
},
MediumStackAlloc {
size: u16,
},
LargeStackAlloc {
size: u32,
},
/// PAC sign the LR register.
PacSignLr,
/// Set the frame-pointer register to the stack-pointer register.
SetFp,
/// Set the frame-pointer register to the stack-pointer register with an
/// offset.
AddFp {
offset: u16,
},
}
Copy link
Member

Choose a reason for hiding this comment

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

Can the names of each of these individual codes match the name in the link above? Specifically SmallStackAlloc is called alloc_s there so I'd expect it to be AllocS here.

Also, it would be nice to have doc comments for the variants that are missing them. For example, the difference between small vs medium stack alloc isn't immediately clear to the reader because they have the same u16 data representation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done: Renamed the alloc items and added a comment to explain the max size of each one.

@dpaoliello
Copy link
Contributor Author

To confirm specifically: does the whole Wasmtime suite (cargo test in the root) pass now on Windows/aarch64?

Correct: cargo test in the root passes on an ARM64 Windows device.

Echoing Alex's thoughts -- if we can test this somehow (WINE on qemu-aarch64? or does Windows/x64 support running aarch64 binaries with emulation somehow? or ...?) then we can add release binaries.

That's a tough one.

I've never tried WINE on AArch64 (emulated or physical), so I can't comment on that.

Windows x64 can't run AArch64 binaries.

GitHub does offer Windows ARM64 runners however the only image available is a clean Windows 11 install (No Visual Studio, no Git, etc.). The lack of an image with pre-installed tools is also blocking making aarch64-pc-windows-msvc a tier 1 Rust target, so it's high on my priority list to get the correct team at GitHub/Microsoft to make and support those images.

@alexcrichton
Copy link
Member

If you're interested @dpaoliello the "fully exhaustive test suite" can be run with ./ci/run-tests.sh locally (and/or copying out the cargo invocation since you probably don't have bash on windows) which basically is cargo test --workspace with a few --exclude for things that aren't supposed to be tested. That will run all wasmtime-wasi tests for example which exercise some "larger modules" than the cargo test does at the root of the repo. (but for development most of us I think do just cargo test and let CI figure everything else out). I mention this if you want to perform an extra double-check that all the various bits are working, but I suspect that if cargo test works this won't turn up much else.

I'm also happy to leave this untested on CI until it's easier to set up CI with tools and such. The likelihood of this regressing is relatively low and we can always ping you @dpaoliello (if you're ok with that) if something looks like it's changing. Otherwise I'm also happy to investigate adding ARM64 binaries for Windows to our CI to get release artifacts as well.

@dpaoliello
Copy link
Contributor Author

If you're interested @dpaoliello the "fully exhaustive test suite" can be run with ./ci/run-tests.sh locally (and/or copying out the cargo invocation since you probably don't have bash on windows) which basically is cargo test --workspace with a few --exclude for things that aren't supposed to be tested. That will run all wasmtime-wasi tests for example which exercise some "larger modules" than the cargo test does at the root of the repo. (but for development most of us I think do just cargo test and let CI figure everything else out). I mention this if you want to perform an extra double-check that all the various bits are working, but I suspect that if cargo test works this won't turn up much else.

Sure, I'll give it a go. Otherwise, I was starting to look into getting rustc_codegen_cranelift working.

I'm also happy to leave this untested on CI until it's easier to set up CI with tools and such.

I'll add it to my list of repos to setup CIs once the Windows ARM64 images are available...

we can always ping you @dpaoliello (if you're ok with that) if something looks like it's changing.

Yes, please!
Feel free to summon me for any Rust -msvc target or Windows on ARM issue.

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

Thanks so much!

@fitzgen fitzgen added this pull request to the merge queue Sep 19, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 19, 2024
@fitzgen
Copy link
Member

fitzgen commented Sep 19, 2024

Looks like this is failing on our MSRV of Rust 1.78:

https://github.com/bytecodealliance/wasmtime/actions/runs/10944294333/job/30385843729#step:18:102

error[E0658]: exclusive range pattern syntax is experimental
   --> cranelift/codegen/src/isa/unwind/winarm64.rs:231:21
    |
231 |                     0..SMALL_STACK_ALLOC_MAX => unwind_codes.push(UnwindCode::AllocS {
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: use an inclusive range pattern, like N..=M

error[E0658]: exclusive range pattern syntax is experimental
   --> cranelift/codegen/src/isa/unwind/winarm64.rs:234:21
    |
234 |                     SMALL_STACK_ALLOC_MAX..MEDIUM_STACK_ALLOC_MAX => {
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: use an inclusive range pattern, like N..=M

error[E0658]: exclusive range pattern syntax is experimental
   --> cranelift/codegen/src/isa/unwind/winarm64.rs:239:21
    |
239 |                     MEDIUM_STACK_ALLOC_MAX..LARGE_STACK_ALLOC_MAX => {
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
    = help: use an inclusive range pattern, like N..=M

@dpaoliello
Copy link
Contributor Author

Looks like this is failing on our MSRV of Rust 1.78

Fixed

@cfallin cfallin enabled auto-merge September 19, 2024 16:31
@cfallin cfallin added this pull request to the merge queue Sep 19, 2024
Merged via the queue into bytecodealliance:main with commit 4e50ecc Sep 19, 2024
39 checks passed
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Sep 19, 2024
With bytecodealliance#9266 Wasmtime should have full support for this platform. While
not tested in CI it can still be useful to build artifacts nonetheless
in case users are interested.
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Sep 19, 2024
With bytecodealliance#9266 Wasmtime should have full support for this platform. While
not tested in CI it can still be useful to build artifacts nonetheless
in case users are interested.

prtest:full
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Sep 19, 2024
With bytecodealliance#9266 Wasmtime should have full support for this platform. While
not tested in CI it can still be useful to build artifacts nonetheless
in case users are interested.

prtest:full
github-merge-queue bot pushed a commit that referenced this pull request Sep 19, 2024
With #9266 Wasmtime should have full support for this platform. While
not tested in CI it can still be useful to build artifacts nonetheless
in case users are interested.

prtest:full
kpreisser added a commit to kpreisser/wasmtime-dotnet that referenced this pull request Sep 23, 2024
Wasmtime recently completed Windows ARM64 support with bytecodealliance/wasmtime#9266 and added release artifacts with bytecodealliance/wasmtime#9283.

Fixes bytecodealliance#298
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:area:aarch64 Issues related to AArch64 backend. cranelift Issues related to the Cranelift code generator wasmtime:api Related to the API of the `wasmtime` crate itself
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Trap handling for Windows ARM64
4 participants