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

Allow to define functions using "untyped callbacks" #207

Merged
merged 10 commits into from
Jan 24, 2023

Conversation

kpreisser
Copy link
Contributor

@kpreisser kpreisser commented Jan 13, 2023

Currently, in order to define function callbacks in the Store or Linker, you have to use a Delegate type that specifies the signature of the function imported by WASM. This means that the function signature must be known at compile-time.
However, if you want to define callbacks at runtime without knowing the signature at compile-time, this will be difficult or even impossible.

With this PR, we allow to define functions using "untyped callbacks", which allows defining a function of any type without the need to use a specific delegate type, by using the following UntypedCallbackDelegate:

public delegate void UntypedCallbackDelegate(Caller caller, ReadOnlySpan<ValueBox> arguments, Span<ValueBox> results);

The untyped callback will receive arguments and can set results via a span of ValueBox. When defining the function, you will need to provide a IReadOnlyList<ValueKind> for the function parameters and results.

This can be thought of the callback equivalent to the Function.Invoke() method that allows to specify parameters as ReadOnlySpan<ValueBox>.

For this to work, I added new methods to ValueBox that allow to "unbox" the boxed value, as this was previously not possible. Note that I used the nomenclature of .NET, meaning I named the methods AsInt32, AsSingle, AsDouble etc., but we could also use AsFloat32, AsFloat64 etc.

For example, this allows to define trapping functions for a module's imports without having to know the function signature at compile-time, similar to Wasmtime's Linker::define_unknown_imports_as_traps (bytecodealliance/wasmtime#4312, bytecodealliance/wasmtime#5557), like this:

// Define all imported functions using a callback that traps.
Function.UntypedCallbackDelegate trappingCallback = (caller, args, results) =>
    throw new InvalidOperationException("This function is not implemented.");

foreach (var funcImport in module.Imports.OfType<FunctionImport>())
{
    linker.DefineFunction(
        funcImport.ModuleName,
        funcImport.Name,
        trappingCallback,
        funcImport.Parameters,
        funcImport.Results);
}

What do you think?
Thanks!

@peterhuene
Copy link
Member

It looks like the PR needs a small rebase with the other recent merges.

…pecify a callback of any type without the need to use a specific delegate type.

The untyped callback will receive arguments and can set results as a span of ValueBox.

For example, this allows to define trapping functions for a module's import without having to know the function time at compile-time, similar to Wasmtime's define_unknown_imports_as_traps.
…Kind but a default value, as otherwise they all would be initialized with ValueKind.Int32.
@kpreisser
Copy link
Contributor Author

Thanks! I rebased the PR.

Copy link
Member

@peterhuene peterhuene left a comment

Choose a reason for hiding this comment

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

Looks great 👍! Just two questions and a minor formatting fix.

src/Function.cs Show resolved Hide resolved
src/Linker.cs Outdated Show resolved Hide resolved
src/ValueBox.cs Outdated Show resolved Hide resolved
kpreisser and others added 3 commits January 24, 2023 21:37
Co-authored-by: Peter Huene <peter@huene.dev>
…g overloads of Linker.DefineFunction, to reduce allocations for the strings.
@peterhuene
Copy link
Member

Ok all pending PRs are merged, so should be able to fully rebase this now. Sorry for the churn!

@peterhuene peterhuene self-requested a review January 24, 2023 20:52
@peterhuene peterhuene enabled auto-merge (squash) January 24, 2023 20:52
@peterhuene
Copy link
Member

Many thanks @kpreisser and @martindevans for all this work. When we merge Martin's updated to remove the alloc for Caller, I'll cut new releases with all these changes.

@peterhuene peterhuene merged commit 43a5b51 into bytecodealliance:main Jan 24, 2023
@kpreisser kpreisser deleted the untyped-callbacks branch January 24, 2023 20:56
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.

2 participants