-
Notifications
You must be signed in to change notification settings - Fork 0
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
Imaginary cxx api #1
base: master
Are you sure you want to change the base?
Conversation
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.
Looks good to me overall! I didn't fully review changes in wasm.hh
and wasm-v8.cc
, but it generally seems like it makes the API much more natural in C++
example/callback.cc
Outdated
} break; | ||
} | ||
auto operator<<(std::ostream &out, const wasm::Val &val) -> std::ostream& { | ||
std::visit([](auto &&arg) { std::cout << arg; }); |
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.
Does this do the same thing? 🤔
Why is it going to std::cout
instead of out
?
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.
That's a bug, thanks.
example/callback.cc
Outdated
std::cout << "> Error accessing export!" << std::endl; | ||
auto run_func = instance.exported_func(0); | ||
if (auto error = run_func.error()) { | ||
std::cout << "> Error accessing export: " << error->what() << std::endl; | ||
exit(1); | ||
} | ||
auto run_func = exports[0]->func(); |
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.
redefinition of run_func
(previously defined on line 72), is this intentional?
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.
Nope! Bug, thanks.
example/finalize.c
Outdated
intptr_t i = (intptr_t)data; | ||
if (i % (iterations / 10) == 0) printf("Finalizing #%" PRIdPTR "...\n", i); |
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.
Unrelated change, maybe we want to split this off into a separate PR. I'll leave that up to you though!
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.
Yep, unrelated change. Removed!
exit(1); | ||
} | ||
instance->set_host_info(reinterpret_cast<void*>(i), &finalize); | ||
// ????? | ||
instance->set_host_info(&i, &finalize); |
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.
// ?????
Passes ownership of arbitrary data with a destructor to some thing, in this case the instance.
auto set_var_i64_import = get_export_func(exports, i++); | ||
auto set_var_f32_export = get_export_func(exports, i++); | ||
auto set_var_i64_export = get_export_func(exports, i++); | ||
auto const_f32_export = instance->exported_global(i++); |
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.
Is it ever possible to have an exports
without an Instance
?
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.
No, should it be? I don't think so, but if we should then what would create one?
}; | ||
struct EngineConfig { | ||
EngineConfig(); | ||
// Implementation provides extra c'tors 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.
How does this happen? By editing this file and shipping their own version of it?
Module compile(const std::vector<char> &); | ||
Instance instantiate(const std::vector<char> &); |
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.
You know better than I do, but is char
the normal way that vectors of bytes are expressed in C++? I know it's correct, just surprised there's not a fancier new type that is commonly used
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 is! There is also a newer fancier type named "std::byte" which is absolutely not the right thing to use here. It's safe to say that files in the C++ sense are contiguous chars (or unsigned chars).
Global &operator=(float); | ||
Global &operator=(double); | ||
Global &operator=(int32_t); | ||
Global &operator=(int64_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.
Fancy, but how will this handle 128bit numbers and other value types like references? Just make a new type for those things?
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.
Just declare another operator=
here, yes.
C++ doesn't have a native 128-bit integer type (well, rather, real compilers for C++ don't uniformly offer 128-bits, the spec specifies intX_t is X bits and lets the implementation pick which to provide). Probably we'll have to define a struct wasm::int128 { uint64_t data[2]; };
}; | ||
|
||
struct RefVal { | ||
void *ptr = nullptr; |
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.
Curious what your thoughts on this vs Optional<&>
or whatever it is in C++
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'm not sure what to do about RefVal
until we implement refs. This guarantees that every RefVal object will contain at least one pointer (worth of data) but says nothing about what the pointer is for or what it points to, leaving that up to the implementation choice of the implementer.
I'm not sure why I'd use std::optional
here? It could be std::optional<something&>
but what's the something?
|
||
// Grow memory. | ||
std::cout << "Growing memory..." << std::endl; | ||
check(memory->grow(1), true); | ||
check(memory->size(), 3u); | ||
check(memory->data_size(), 0x30000u); | ||
check(memory->contents()->size(), 0x30000u); |
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.
Hmm, what's the idea here? What is contents
, is it type that can be used on its own?
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.
Ideally it'd be a std::span<char>
but I realized that std::span didn't make it into c++17.
Thinking about this over the weekend, I now think we should provide a span-compatible type for C++17 users but under a macro that uses just makes our wasm::span = std::span when the user has std::span.
return nullptr; | ||
int32_t print_callback(int32_t v) { | ||
std::cout << "Calling back..." << std::endl << "> " << v << std::endl; | ||
return v; |
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.
This will prevent returning multi-values I think.
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 was thinking multi-value returns would look like this:
std::tuple<int32_t, float> my_callback() {
return {1, 2.0};
}
which when called from normal C++ would look like:
void foo() {
auto [x, y] = my_callback();
}
Ideally we want that same syntax when C++ code calls a multi-value return wasm function.
template<typename Fn> | ||
Func exported_func(const std::string &) const; | ||
size_t exported_func_size() const; | ||
bool exported_func_empty() const; |
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'm afraid this will lead to having many methods here:
export_func*
export_global*
export_table*
export_mem*
DO they really belong to Instance
or should we keep the exports
?
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.
Maybe? I'm not convinced that exports
makes sense as a standalone object? What does it mean to have an exports but not an instance? (BTW, take a look at https://llvm.org/doxygen/classllvm_1_1Module.html sections "global variable iteration", "function iteration", etc. I was thinking we would do the same thing.)
That said, ExportedFunc has to exist even though it's not really separate from an instance, but we know why we want it to be different, we want the ability to call it.
Starting with C++20 we could use ranges, and code like "for (auto func : instance.exports() | std::views::filter(wasm::Functions)) { " becomes possible. To me that's the most convincing argument for having an exports() function I've thought of.
} | ||
}; | ||
|
||
wasm::Instance instance = store.instantiate(file, imports); |
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 think we should keep the "standard" C++ API free from convenience method and ship them through a wrapper of our own or something like that.
No description provided.