-
Notifications
You must be signed in to change notification settings - Fork 749
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
Conversation
06a6ac5
to
f939c50
Compare
a5b4343
to
bc1fa1a
Compare
9e2d69b
to
ea15fd5
Compare
62aaba6
to
1e23777
Compare
1e23777
to
acb6ed0
Compare
a6c6be3
to
99d3b78
Compare
81db43d
to
703a9c7
Compare
6114337
to
2f352ab
Compare
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; | ||
} |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?"
There was a problem hiding this comment.
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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert instead?
There was a problem hiding this comment.
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}"; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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*.)
a9a0a7b
to
028c068
Compare
Restores current versions of all non-SIMD tests in the core testsuite and multi-memory and exception-handling proposals.
028c068
to
87f8cd7
Compare
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this 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
Restores current versions of all non-SIMD tests in the core testsuite and multi-memory and exception-handling proposals.
(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.