Skip to content

Allow to define functions using "untyped callbacks" #207

New issue

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

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

Already on GitHub? # to your account

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 peterhuene self-requested a review January 23, 2023 19:43
@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.

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
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants