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

Rust bindings (unsafe execution) #566

Merged
merged 5 commits into from
Nov 19, 2020
Merged

Rust bindings (unsafe execution) #566

merged 5 commits into from
Nov 19, 2020

Conversation

axic
Copy link
Member

@axic axic commented Oct 1, 2020

TODO:

  • Cleanup the commits
  • Rustdoc
  • Fizzy error enum (will do this in a new PR)

@axic axic marked this pull request as draft October 1, 2020 13:30
@axic axic force-pushed the rust branch 10 times, most recently from dc15f97 to 49ef6bb Compare October 1, 2020 19:50
@codecov
Copy link

codecov bot commented Oct 1, 2020

Codecov Report

Merging #566 (9d05550) into master (c290d0d) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##           master     #566   +/-   ##
=======================================
  Coverage   98.38%   98.38%           
=======================================
  Files          69       69           
  Lines        9712     9712           
=======================================
  Hits         9555     9555           
  Misses        157      157           
Flag Coverage Δ
spectests 91.47% <ø> (ø)
unittests 98.38% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


impl Module {
// TODO: support imported functions{
pub fn instantiate(self) -> Option<Instance> {
Copy link

Choose a reason for hiding this comment

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

This should probably return a Result, as failure to instantiate is more of an error condition. Also, question mark operator.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I was wondering if I could avoid defining error types (given nothing is returned), but the question mark operator is a good point.

Copy link
Member Author

Choose a reason for hiding this comment

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

Need to have custom error type otherwise question mark operator won't work 😞

bindings/rust/src/lib.rs Show resolved Hide resolved
bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
@@ -4,8 +4,123 @@

Copy link

Choose a reason for hiding this comment

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

The conventional file layout is:

<use statements>
<module declarations>
<trait declarations>
<struct declarations>
<struct methods>
<trait impls>

bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
pub type ExecutionResult = sys::FizzyExecutionResult;

impl Instance {
pub fn execute(&mut self, func_idx: u32, args: &[Value]) -> ExecutionResult {
Copy link

Choose a reason for hiding this comment

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

Ergonomics could be better if func_idx was replaced with the name. Users will probably be looking to call an export by name anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

The C API does not yet offer anything like that and this is a direct translation as of now.

Copy link
Member Author

@axic axic Nov 6, 2020

Choose a reason for hiding this comment

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

Added function to look it up (now that the underlying API has it). Since this function is called unsafe_execute, I think it is fine to keep func_idx as it already has unsafe inputs.

Will eventually have a properly wrapped safe execute function, similar to what it is in wasmi and others.

bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
@axic axic changed the base branch from capi_execute to capi-execute-dynamic-module October 12, 2020 13:10
@gumb0 gumb0 force-pushed the capi-execute-dynamic-module branch 2 times, most recently from f38f7e5 to 59419bd Compare October 12, 2020 16:34
Base automatically changed from capi-execute-dynamic-module to master October 12, 2020 17:16
@axic axic force-pushed the rust branch 2 times, most recently from 54e4c4e to d2e6a1f Compare October 12, 2020 17:21
@axic axic marked this pull request as ready for review October 12, 2020 17:23
bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
bindings/rust/src/lib.rs Outdated Show resolved Hide resolved
@axic axic changed the title Rust bindings (execution) Rust bindings (unsafe execution) Nov 18, 2020
@axic axic changed the base branch from master to capi-find-exports November 18, 2020 12:59
Base automatically changed from capi-find-exports to master November 18, 2020 13:04
bindings/rust/src/lib.rs Show resolved Hide resolved
bindings/rust/src/lib.rs Show resolved Hide resolved
bindings/rust/src/lib.rs Show resolved Hide resolved

/// The optional return value. Only a single return value is allowed in WebAssembly 1.0.
pub fn value(&self) -> Option<Value> {
if !self.0.trapped && self.0.has_value {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Documentation says otherwise, but this is too defensive. It is guaranteed that has_value if false if trapped is true.

Copy link
Member Author

Choose a reason for hiding this comment

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

@gumb0 suggested this. Where is it guaranteed?

Copy link
Collaborator

@gumb0 gumb0 Nov 18, 2020

Choose a reason for hiding this comment

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

Documentation says otherwise, but this is too defensive. It is guaranteed that has_value if false if trapped is true.

Here it's the opposite - when trapped is false, we have to check has_value.

What I suggested was changing if has_value -> if !trapped && has_value

Yeah I see what you mean, perhaps could be changed back, with a change to C API documentation and some new asserts in tests.

Copy link
Member Author

Choose a reason for hiding this comment

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

What I suggested was changing if has_value -> if !trapped && has_value

This is what the code has now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The ExecuteResult constructor guarantees it. If you want to keep it, swap the checks: has_value && !trapped.

Copy link
Member Author

@axic axic Nov 18, 2020

Choose a reason for hiding this comment

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

I can also add the trapped as an assertion, which is only present in debug builds:

    pub fn value(&self) -> Option<Value> {
        if self.0.has_value {
            assert!(!self.0.trapped);
            Some(self.0.value)
        } else {
            None
        }
    }

Copy link
Member Author

Choose a reason for hiding this comment

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

The ExecuteResult constructor guarantees it.

The C API has no constructor guarantee for it though?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The ExecuteResult constructor guarantees it.

The C API has no constructor guarantee for it though?

No constructor guarantees but FizzyExecutionResult wrap(const fizzy::ExecutionResult&) just copies all three fields always.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can also add the trapped as an assertion, which is only present in debug builds:

This variant looks good.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm ok with changing trapped check to assertion.

bindings/rust/src/lib.rs Show resolved Hide resolved
bindings/rust/src/lib.rs Show resolved Hide resolved
@axic axic force-pushed the rust branch 4 times, most recently from e45448f to 4eb205c Compare November 18, 2020 19:11

/// The optional return value. Only a single return value is allowed in WebAssembly 1.0.
pub fn value(&self) -> Option<Value> {
if !self.0.trapped && self.0.has_value {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm ok with changing trapped check to assertion.

@axic
Copy link
Member Author

axic commented Nov 19, 2020

@chfast @gumb0 made the assertion change

@axic axic requested review from chfast and gumb0 November 19, 2020 16:30
@axic axic merged commit bc60be5 into master Nov 19, 2020
@axic axic deleted the rust branch November 19, 2020 19:20
@axic axic mentioned this pull request Feb 4, 2021
16 tasks
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.

4 participants