-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wasm-c-api] Add upstream examples as tests
Plus a script to compile/link/run them. Change-Id: Iac8ffcda3a73902261c07a7b4e5d967a19414c75 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1564058 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Cr-Commit-Position: refs/heads/master@{#60911}
- Loading branch information
1 parent
f80bfea
commit 912b391
Showing
42 changed files
with
3,131 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <inttypes.h> | ||
|
||
#include "wasm.h" | ||
|
||
#define own | ||
|
||
// Print a Wasm value | ||
void wasm_val_print(wasm_val_t val) { | ||
switch (val.kind) { | ||
case WASM_I32: { | ||
printf("%" PRIu32, val.of.i32); | ||
} break; | ||
case WASM_I64: { | ||
printf("%" PRIu64, val.of.i64); | ||
} break; | ||
case WASM_F32: { | ||
printf("%f", val.of.f32); | ||
} break; | ||
case WASM_F64: { | ||
printf("%g", val.of.f64); | ||
} break; | ||
case WASM_ANYREF: | ||
case WASM_FUNCREF: { | ||
if (val.of.ref == NULL) { | ||
printf("null"); | ||
} else { | ||
printf("ref(%p)", val.of.ref); | ||
} | ||
} break; | ||
} | ||
} | ||
|
||
// A function to be called from Wasm code. | ||
own wasm_trap_t* print_callback( | ||
const wasm_val_t args[], wasm_val_t results[] | ||
) { | ||
printf("Calling back...\n> "); | ||
wasm_val_print(args[0]); | ||
printf("\n"); | ||
|
||
wasm_val_copy(&results[0], &args[0]); | ||
return NULL; | ||
} | ||
|
||
|
||
// A function closure. | ||
own wasm_trap_t* closure_callback( | ||
void* env, const wasm_val_t args[], wasm_val_t results[] | ||
) { | ||
int i = *(int*)env; | ||
printf("Calling back closure...\n"); | ||
printf("> %d\n", i); | ||
|
||
results[0].kind = WASM_I32; | ||
results[0].of.i32 = (int32_t)i; | ||
return NULL; | ||
} | ||
|
||
|
||
int main(int argc, const char* argv[]) { | ||
// Initialize. | ||
printf("Initializing...\n"); | ||
wasm_engine_t* engine = wasm_engine_new(); | ||
wasm_store_t* store = wasm_store_new(engine); | ||
|
||
// Load binary. | ||
printf("Loading binary...\n"); | ||
FILE* file = fopen("callback.wasm", "r"); | ||
if (!file) { | ||
printf("> Error loading module!\n"); | ||
return 1; | ||
} | ||
fseek(file, 0L, SEEK_END); | ||
size_t file_size = ftell(file); | ||
fseek(file, 0L, SEEK_SET); | ||
wasm_byte_vec_t binary; | ||
wasm_byte_vec_new_uninitialized(&binary, file_size); | ||
if (fread(binary.data, file_size, 1, file) != 1) { | ||
printf("> Error loading module!\n"); | ||
return 1; | ||
} | ||
fclose(file); | ||
|
||
// Compile. | ||
printf("Compiling module...\n"); | ||
own wasm_module_t* module = wasm_module_new(store, &binary); | ||
if (!module) { | ||
printf("> Error compiling module!\n"); | ||
return 1; | ||
} | ||
|
||
wasm_byte_vec_delete(&binary); | ||
|
||
// Create external print functions. | ||
printf("Creating callback...\n"); | ||
own wasm_functype_t* print_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()); | ||
own wasm_func_t* print_func = wasm_func_new(store, print_type, print_callback); | ||
|
||
int i = 42; | ||
own wasm_functype_t* closure_type = wasm_functype_new_0_1(wasm_valtype_new_i32()); | ||
own wasm_func_t* closure_func = wasm_func_new_with_env(store, closure_type, closure_callback, &i, NULL); | ||
|
||
wasm_functype_delete(print_type); | ||
wasm_functype_delete(closure_type); | ||
|
||
// Instantiate. | ||
printf("Instantiating module...\n"); | ||
const wasm_extern_t* imports[] = { | ||
wasm_func_as_extern(print_func), wasm_func_as_extern(closure_func) | ||
}; | ||
own wasm_instance_t* instance = wasm_instance_new(store, module, imports); | ||
if (!instance) { | ||
printf("> Error instantiating module!\n"); | ||
return 1; | ||
} | ||
|
||
wasm_func_delete(print_func); | ||
wasm_func_delete(closure_func); | ||
|
||
// Extract export. | ||
printf("Extracting export...\n"); | ||
own wasm_extern_vec_t exports; | ||
wasm_instance_exports(instance, &exports); | ||
if (exports.size == 0) { | ||
printf("> Error accessing exports!\n"); | ||
return 1; | ||
} | ||
const wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]); | ||
if (run_func == NULL) { | ||
printf("> Error accessing export!\n"); | ||
return 1; | ||
} | ||
|
||
wasm_module_delete(module); | ||
wasm_instance_delete(instance); | ||
|
||
// Call. | ||
printf("Calling export...\n"); | ||
wasm_val_t args[2]; | ||
args[0].kind = WASM_I32; | ||
args[0].of.i32 = 3; | ||
args[1].kind = WASM_I32; | ||
args[1].of.i32 = 4; | ||
wasm_val_t results[1]; | ||
if (wasm_func_call(run_func, args, results)) { | ||
printf("> Error calling function!\n"); | ||
return 1; | ||
} | ||
|
||
wasm_extern_vec_delete(&exports); | ||
|
||
// Print result. | ||
printf("Printing result...\n"); | ||
printf("> %u\n", results[0].of.i32); | ||
|
||
// Shut down. | ||
printf("Shutting down...\n"); | ||
wasm_store_delete(store); | ||
wasm_engine_delete(engine); | ||
|
||
// All done. | ||
printf("Done.\n"); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#include <iostream> | ||
#include <fstream> | ||
#include <cstdlib> | ||
#include <string> | ||
#include <cinttypes> | ||
|
||
#include "wasm.hh" | ||
|
||
// Print a Wasm value | ||
auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& { | ||
switch (val.kind()) { | ||
case wasm::I32: { | ||
out << val.i32(); | ||
} break; | ||
case wasm::I64: { | ||
out << val.i64(); | ||
} break; | ||
case wasm::F32: { | ||
out << val.f32(); | ||
} break; | ||
case wasm::F64: { | ||
out << val.f64(); | ||
} break; | ||
case wasm::ANYREF: | ||
case wasm::FUNCREF: { | ||
if (val.ref() == nullptr) { | ||
out << "null"; | ||
} else { | ||
out << "ref(" << val.ref() << ")"; | ||
} | ||
} break; | ||
} | ||
return out; | ||
} | ||
|
||
// A function to be called from Wasm code. | ||
auto print_callback( | ||
const wasm::Val args[], wasm::Val results[] | ||
) -> wasm::own<wasm::Trap*> { | ||
std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl; | ||
results[0] = args[0].copy(); | ||
return nullptr; | ||
} | ||
|
||
|
||
// A function closure. | ||
auto closure_callback( | ||
void* env, const wasm::Val args[], wasm::Val results[] | ||
) -> wasm::own<wasm::Trap*> { | ||
auto i = *reinterpret_cast<int*>(env); | ||
std::cout << "Calling back closure..." << std::endl; | ||
std::cout << "> " << i << std::endl; | ||
results[0] = wasm::Val::i32(static_cast<int32_t>(i)); | ||
return nullptr; | ||
} | ||
|
||
|
||
void run() { | ||
// Initialize. | ||
std::cout << "Initializing..." << std::endl; | ||
auto engine = wasm::Engine::make(); | ||
auto store_ = wasm::Store::make(engine.get()); | ||
auto store = store_.get(); | ||
|
||
// Load binary. | ||
std::cout << "Loading binary..." << std::endl; | ||
std::ifstream file("callback.wasm"); | ||
file.seekg(0, std::ios_base::end); | ||
auto file_size = file.tellg(); | ||
file.seekg(0); | ||
auto binary = wasm::vec<byte_t>::make_uninitialized(file_size); | ||
file.read(binary.get(), file_size); | ||
file.close(); | ||
if (file.fail()) { | ||
std::cout << "> Error loading module!" << std::endl; | ||
return; | ||
} | ||
|
||
// Compile. | ||
std::cout << "Compiling module..." << std::endl; | ||
auto module = wasm::Module::make(store, binary); | ||
if (!module) { | ||
std::cout << "> Error compiling module!" << std::endl; | ||
return; | ||
} | ||
|
||
// Create external print functions. | ||
std::cout << "Creating callback..." << std::endl; | ||
auto print_type = wasm::FuncType::make( | ||
wasm::vec<wasm::ValType*>::make(wasm::ValType::make(wasm::I32)), | ||
wasm::vec<wasm::ValType*>::make(wasm::ValType::make(wasm::I32)) | ||
); | ||
auto print_func = wasm::Func::make(store, print_type.get(), print_callback); | ||
|
||
// Creating closure. | ||
std::cout << "Creating closure..." << std::endl; | ||
int i = 42; | ||
auto closure_type = wasm::FuncType::make( | ||
wasm::vec<wasm::ValType*>::make(), | ||
wasm::vec<wasm::ValType*>::make(wasm::ValType::make(wasm::I32)) | ||
); | ||
auto closure_func = wasm::Func::make(store, closure_type.get(), closure_callback, &i); | ||
|
||
// Instantiate. | ||
std::cout << "Instantiating module..." << std::endl; | ||
wasm::Extern* imports[] = {print_func.get(), closure_func.get()}; | ||
auto instance = wasm::Instance::make(store, module.get(), imports); | ||
if (!instance) { | ||
std::cout << "> Error instantiating module!" << std::endl; | ||
return; | ||
} | ||
|
||
// Extract export. | ||
std::cout << "Extracting export..." << std::endl; | ||
auto exports = instance->exports(); | ||
if (exports.size() == 0 || exports[0]->kind() != wasm::EXTERN_FUNC || !exports[0]->func()) { | ||
std::cout << "> Error accessing export!" << std::endl; | ||
return; | ||
} | ||
auto run_func = exports[0]->func(); | ||
|
||
// Call. | ||
std::cout << "Calling export..." << std::endl; | ||
wasm::Val args[] = {wasm::Val::i32(3), wasm::Val::i32(4)}; | ||
wasm::Val results[1]; | ||
if (run_func->call(args, results)) { | ||
std::cout << "> Error calling function!" << std::endl; | ||
return; | ||
} | ||
|
||
// Print result. | ||
std::cout << "Printing result..." << std::endl; | ||
std::cout << "> " << results[0].i32() << std::endl; | ||
|
||
// Shut down. | ||
std::cout << "Shutting down..." << std::endl; | ||
} | ||
|
||
|
||
int main(int argc, const char* argv[]) { | ||
run(); | ||
std::cout << "Done." << std::endl; | ||
return 0; | ||
} | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
(module | ||
(func $print (import "" "print") (param i32) (result i32)) | ||
(func $closure (import "" "closure") (result i32)) | ||
(func (export "run") (param $x i32) (param $y i32) (result i32) | ||
(i32.add | ||
(call $print (i32.add (local.get $x) (local.get $y))) | ||
(call $closure) | ||
) | ||
) | ||
) |
Oops, something went wrong.