I'm experimenting with embedding V8 in a test app in order to load, compile, and run wasm bytecode that has been generated by LLVM (using V8 7.4.x and recent trunk versions of LLVM)
Loading and running seems simple enough (via WasmModuleObject::DeserializeOrCompile), but calling the resulting functions from C++ seems tricky, because, well, it's not clear that there's a public V8 API for actually looking at what's in the resulting WasmModuleObject; in JavaScript, you can apparently do something like
let module = new WebAssembly.Module(buffer)
let imports = { ... map of funcs that are declared as 'import' by the module, if any ... }
let instance = new WebAssembly.Instance(module, imports);
let myfunc = instance.exports["myfunc"];
myfunc(...);
but a similar API doesn't seem to be surfaced for C++, at least not in the public API.
I've tried replicating the JavaScript calls from C++, but there's a big problem: it appears that the 'imports' argument is required to be v8::internal::Handle<v8::internal::JSReceiver>, which (AFAICT) there isn't a clean way to create and manipulate directly from the C++ API, at least certainly not from the public API:
Local<WasmModuleObject> module = WasmModuleObject::DeserializeOrCompile(
isolate, {nullptr, 0}, {source, source_len}).ToLocalChecked();
v8::internal::Handle<v8::internal::JSReceiver> imports = ???; // Oh well
Local<Value> args[2] = { module, imports };
Local<Object> module_instance_exports = context->Global()
->Get(context, String::NewFromUtf8(isolate, "WebAssembly")).ToLocalChecked().As<Object>()
->Get(context, String::NewFromUtf8(isolate, "Instance")).ToLocalChecked().As<Object>()
->CallAsConstructor(context, 2, args).ToLocalChecked().As<Object>()
->Get(context, String::NewFromUtf8(isolate, "exports")).ToLocalChecked().As<Object>()
;
I suppose I could accomplish this by adding some extra JS-only wrapper code that does the necessary magic, but that's going to add another layer of indirection that surely shouldn't be necessary here (since the code in question here is otherwise free of JavaScript).
The thing that makes this extra-fun is that apparently LLVM injects a couple of symbols into the import table of every bit of wasm it generates ("__linear_memory" and "__indirect_function_table")... which don't appear to be referenced in any code in V8 that I can find, so their purpose is a bit of a mystery to me. (Perhaps holdovers from older implementations of wasm?) In any event, I'm almost certainly going to have other imports I need to fill in here (for glue functions), so figuring out how to to accomplish this is probably essential to my task.
So...
(1) Is there an explicit API to access/call wasm-compiled functions from C++? Is so, where may I find it? If not, um, shouldn't we have one?
(2) If there isn't a C++ API for this (and/or isn't going to be one anytime in the very near future), is the above approach the most reasonable workaround for now?
(3) If the above mimic-JS-from-C++ approach is reasonable, is there a clean way to specify the imports table?
(4) Finally, just out of curiosity, anyone know what the story is with "__linear_memory" and "__indirect_function_table"?