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

Add support for exceptions in LLVM #5347

Open
wants to merge 9 commits into
base: wasmer-5.1.0
Choose a base branch
from

Conversation

xdoardo
Copy link
Contributor

@xdoardo xdoardo commented Jan 15, 2025

This PR adds support for exceptions in LLVM for linux-64 targets.
This is of course still experimental. Missing bits:

  • Figure out EH in macOS (compact_unwind sections)
  • Figure out EH in windows
  • Add a bit of documentation

…n, throw, rethrow..)

This commit adds (half of) the important functionalities for exception
handling: the personality function - in part adapted from Rust's stdlib,
which however does not do any "typechecking" in the sense that every
"catch" block is akin to a "catch_all" (while we need to catch the
correct `Tag`); the `throw` and `rethrow` mechanisms, and functions to
allocate, delete and "read" an exception.
This commit adds the code to generate `landingpads` and `catch`es in
LLVM.
…t_unwind` tables for Mach-O

(Work in progress) macOS uses a different scheme for exception handling
in Mach-O; in contrast with the "usual" .eh_frame mechanism, Mach-O has
a `compact_unwind` section in which EH-related metadata are embedded.
This commit begins the effort to support it in its entirety. On the path
to that end, it also adds GOT-based relocations, which are necessary for
Mach-O object files.
@xdoardo xdoardo requested a review from syrusakbary as a code owner January 15, 2025 14:17
@xdoardo xdoardo linked an issue Jan 15, 2025 that may be closed by this pull request
@xdoardo xdoardo force-pushed the 5201-experimental-add-support-for-exceptions branch from 128a476 to 19d21ff Compare January 15, 2025 14:22
@@ -183,6 +204,13 @@ impl LibCall {
Self::ImportedMemory32AtomicWait64 => "wasmer_vm_imported_memory32_atomic_wait64",
Self::Memory32AtomicNotify => "wasmer_vm_memory32_atomic_notify",
Self::ImportedMemory32AtomicNotify => "wasmer_vm_imported_memory32_atomic_notify",
Self::Throw => "wasmer_vm_throw",
Self::Rethrow => "wasmer_vm_rethrow",
Self::EHPersonality => "__gxx_personality_v0",
Copy link
Member

Choose a reason for hiding this comment

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

This function can't be named other way, right?

Copy link
Contributor Author

@xdoardo xdoardo Jan 15, 2025

Choose a reason for hiding this comment

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

It can on Linux, apparently can't on macOS. Not sure about windows.

edit: It can't on macOS because, as far as I can tell, changing the name of the personality function makes LLVM generate different (wrong?) EH info in the object file.

Payload::TagSection(_) => {
unimplemented!("exception handling not implemented yet")
}
Payload::TagSection(t) => parse_tag_section(t, environ)?,
Copy link
Member

Choose a reason for hiding this comment

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

Since we are enabling this in the parser now, we'll need to make sure that the cranelift compiler fails with an exception/Error instead of panicking

@@ -54,7 +54,7 @@ pub fn type_to_irtype(ty: Type, target_config: TargetFrontendConfig) -> WasmResu
Type::F32 => Ok(ir::types::F32),
Type::F64 => Ok(ir::types::F64),
Type::V128 => Ok(ir::types::I8X16),
Type::ExternRef | Type::FuncRef => reference_type(target_config),
Copy link
Member

Choose a reason for hiding this comment

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

If ExceptionRef is passed, should we return an error? (since cranelift doesn't support it)

@@ -253,6 +303,7 @@ impl std::fmt::Display for Value {
Self::I64(v) => v.to_string(),
Self::F32(v) => v.to_string(),
Self::F64(v) => v.to_string(),
Self::ExceptionRef(_) => "exceptionref".to_string(),
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 this is commonly known as exnref

#[derive(Debug, Clone)]
#[repr(transparent)]
/// A WebAssembly `exnref` in `js`.
pub struct ExceptionRef;
Copy link
Member

@syrusakbary syrusakbary Jan 15, 2025

Choose a reason for hiding this comment

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

This should be opaque (pub only for the crate)


#[derive(Debug, Clone, derive_more::From)]
/// An opaque reference to some data. This reference can be passed through Wasm.
pub struct ExceptionRef(pub(crate) RuntimeExceptionRef);
Copy link
Member

Choose a reason for hiding this comment

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

This should be opaque (pub only for the crate)

#[derive(Debug, Clone)]
#[repr(transparent)]
/// A WebAssembly `exnref` in `jsc`.
pub struct ExceptionRef;
Copy link
Member

Choose a reason for hiding this comment

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

This should be opaque (pub only for the crate)

#[derive(Debug, Clone)]
#[repr(transparent)]
/// A WebAssembly `extern ref` in `v8`.
pub struct ExceptionRef;
Copy link
Member

Choose a reason for hiding this comment

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

This should be opaque (pub only for the crate)

#[derive(Debug, Clone)]
#[repr(transparent)]
/// A WebAssembly `extern ref` in `wamr`.
pub struct ExceptionRef;
Copy link
Member

Choose a reason for hiding this comment

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

This should be opaque (pub only for the crate)

#[derive(Debug, Clone)]
#[repr(transparent)]
/// A WebAssembly `extern ref` in `wasmi`.
pub struct ExceptionRef;
Copy link
Member

Choose a reason for hiding this comment

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

This should be opaque (pub only for the crate)

_ => {
panic!("wamr currently does not support V128 values")
}
_ => unreachable!("wamr kind has no matching wasmer_types::Type"),
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 not the right type. We should format well


impl WasmTagType {
pub(crate) fn new(_tag_type: TagType) -> Self {
panic!()
Copy link
Member

Choose a reason for hiding this comment

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

Fixme?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Experimental: add support for exceptions in LLVM
2 participants