Skip to content

wasm2c: implement the reference-types proposal #1887

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

Merged
merged 6 commits into from
Oct 3, 2022

Conversation

keithw
Copy link
Member

@keithw keithw commented Apr 4, 2022

(This PR is sequenced behind #1875, #1814, #1877 and #1999.)

This PR adds support for the reference-types proposal (per #1853 (comment)). This makes it possible to run all of the non-SIMD spec tests in the current testsuite.

Closes #1737. Closes #1985.

@keithw keithw force-pushed the reference-types branch 2 times, most recently from 06a6ac5 to f939c50 Compare April 4, 2022 11:38
@keithw keithw changed the title wasm2c: implement reference types wasm2c: implement the reference-types proposal Apr 4, 2022
@keithw keithw requested a review from sbc100 April 4, 2022 11:40
@keithw keithw requested a review from kripken April 4, 2022 17:18
@keithw keithw force-pushed the reference-types branch from ef394d8 to 86c3ac4 Compare April 5, 2022 04:10
@keithw keithw force-pushed the reference-types branch 2 times, most recently from a5b4343 to bc1fa1a Compare April 6, 2022 11:34
@keithw keithw force-pushed the reference-types branch from b90ca98 to 1a16165 Compare May 15, 2022 06:05
@keithw keithw force-pushed the reference-types branch 4 times, most recently from 9e2d69b to ea15fd5 Compare July 15, 2022 06:40
@keithw keithw force-pushed the reference-types branch 5 times, most recently from 62aaba6 to 1e23777 Compare August 17, 2022 15:48
@keithw keithw force-pushed the reference-types branch 2 times, most recently from a6c6be3 to 99d3b78 Compare September 16, 2022 16:58
@keithw keithw force-pushed the reference-types branch 4 times, most recently from 81db43d to 703a9c7 Compare September 21, 2022 08:23
@keithw keithw force-pushed the reference-types branch 2 times, most recently from 6114337 to 2f352ab Compare October 1, 2022 05:25
Copy link
Member

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

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

Awesome! Just a few more nits and we good to land this I think.

wasm2c/wasm-rt.h Outdated
*/
void wasm_rt_free_funcref_table(wasm_rt_funcref_table_t*);

/** Initialize an externref Table object with an element count of `elements` and
Copy link
Member

Choose a reason for hiding this comment

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

Can you start these javadoc-style comments with a /** on a line by itself?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@@ -485,58 +485,96 @@ static inline void memory_init(wasm_rt_memory_t* dest,

typedef struct {
uint32_t func_type_index;
wasm_rt_funcref_t func;
wasm_rt_function_ptr_t func;
size_t module_offset;
} wasm_elem_segment_expr_t;
Copy link
Member

Choose a reason for hiding this comment

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

It seems like this type could/should be unified with wasm_rt_funcref_t... what happens if an elem segment contains funcrefs to imported functions? (or is that not possible?). It seems like this would only be able to represent module-local functions in elem segments?

Copy link
Member Author

@keithw keithw Oct 2, 2022

Choose a reason for hiding this comment

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

Re: what happens when an elem segment contains funcrefs to imported functions, I believe this is tested in the testsuite (e.g. in linking.wast) so we definitely have to handle it. The module_offset field is what makes this possible. (FWIW this code was added already in handling bulk memory ops.)

Re: unifying the types, the idea behind having these separate was that a wasm_rt_funcref_t includes a pointer to an instance of the originating module, which is what you want at runtime when calling a funcref. But when CWriter is representing the elem segment's initializing expr, we don't have the instance of the originating module because the module hasn't been instantiated yet. So instead the elem segment expr contains basically a pointer-to-member; the offset within the module instance where that function's originating module instance will be found, so that at runtime, funcref_table_init (previously table_init) can properly initialize the table.

Also, the wasm_elem_segment_expr_t stores the function's type index within the module, whereas a wasm_rt_funcref_t contains the global opaque type ID returned by wasm_rt_register_func_type (only known at runtime).

Write("table_init(", ExternalInstancePtr(dest_table->name), ", ");
if (dest_table->elem_type != src_segment->elem_type) {
WABT_UNREACHABLE;
}
Copy link
Member

Choose a reason for hiding this comment

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

Should this be an assert instead? (I guess it would be validation error if this were true.. so it should be impossible for that to happen here?)

Copy link
Member Author

@keithw keithw Oct 2, 2022

Choose a reason for hiding this comment

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

I agree this should be a validation error, but my understanding is that the validator doesn't currently catch this one. :-( Per #1612 . So it seems like this should abort (ideally with a helpful error message) even on a Release build.

Copy link
Member

Choose a reason for hiding this comment

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

Still, why not use assert here?

Copy link
Member Author

@keithw keithw Oct 3, 2022

Choose a reason for hiding this comment

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

My thinking was that an assert isn't strong enough here, because cmake disables asserts on Release builds. :-/ If we made this an assert, then a user could take an invalid module like this:

(module
 (table 1 externref)
 (func $f)
 (elem (i32.const 0) func $f)
)

and successfully pass it through wat2wasm and wasm2c (release build) and all they would get is a warning from the C compiler when compiling the generated code (warning: passing argument 1 of ‘funcref_table_init’ from incompatible pointer type; note: expected ‘wasm_rt_funcref_table_t *’ but argument is of type ‘wasm_rt_externref_table_t *’), and unless they compile everything with -Werror, the module would end up with the ability to create a garbage externref that the host never gave it. That felt kind of icky to have as a known bug that's only caught on non-Release builds.

Copy link
Member

Choose a reason for hiding this comment

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

True. but UNREACHABLE isn't much better as an end user experience is it? Wouldn't it manifest as a crash, which then would require debugger to figure out what happens? IIRC it doesn't even given a line number.

I guess the real fix is to update the validator. How we add a TODO that says something like "This should really be and assert since the validator should catch this, but currently it doesn't?"

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Write("table_copy(", ExternalInstancePtr(dest_table->name), ", ",
if (dest_table->elem_type != src_table->elem_type) {
WABT_UNREACHABLE;
}
Copy link
Member

Choose a reason for hiding this comment

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

assert instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

(same as previous)

src/c-writer.cc Outdated
const char* CWriter::GetReferenceNullValue(const Type& type) {
switch (type) {
case Type::FuncRef:
return "(wasm_rt_funcref_t){0, NULL, 0}";
Copy link
Member

Choose a reason for hiding this comment

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

Can we define wasm_rt_funcref_null_value too? Also, can we avoid having wasm_rt_externref_null_value in the wasm-rt.h header file if its only used here in the generated code?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, done (wasm_rt_funcref_null_value). We wanted wasm_rt_externref_null_value to be in the wasm-rt.h header so that if the embedder wants to choose a different type for wasm_rt_externref_t (something other than a void*), then the embedder can also specify the appropriate null value. (In Fix we're using externref = m256 instead of void*.)

wasm2c/wasm-rt.h Outdated
void wasm_rt_free_table(wasm_rt_table_t*);
void wasm_rt_free_externref_table(wasm_rt_externref_table_t*);

/** Grow a Table object by `delta` elements (giving the new elements the value
Copy link
Member

Choose a reason for hiding this comment

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

Can you put opening and closing comment marks on lines by themsevles.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Copy link
Member

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

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

lgtm with a final comments

@keithw keithw enabled auto-merge (squash) October 3, 2022 06:08
@keithw keithw merged commit cbc5684 into WebAssembly:main Oct 3, 2022
@keithw keithw deleted the reference-types branch October 4, 2022 00:42
matthias-blume pushed a commit to matthias-blume/wabt that referenced this pull request Dec 16, 2022
Restores current versions of all non-SIMD tests in the core testsuite
and multi-memory and exception-handling proposals.
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.

Aborted in CWriter::Write at wasm2c wasm2c no longer passes many spec tests
2 participants