| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <inttypes.h> |
| |
| #include "wasm.h" |
| |
| #define own |
| |
| wasm_global_t* get_export_global(const wasm_extern_vec_t* exports, size_t i) { |
| if (exports->size <= i || !wasm_extern_as_global(exports->data[i])) { |
| printf("> Error accessing global export %zu!\n", i); |
| exit(1); |
| } |
| return wasm_extern_as_global(exports->data[i]); |
| } |
| |
| wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) { |
| if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) { |
| printf("> Error accessing function export %zu!\n", i); |
| exit(1); |
| } |
| return wasm_extern_as_func(exports->data[i]); |
| } |
| |
| |
| #define check(val, type, expected) \ |
| if (val.of.type != expected) { \ |
| printf("> Error reading value\n"); \ |
| exit(1); \ |
| } |
| |
| #define check_global(global, type, expected) \ |
| { \ |
| wasm_val_t val; \ |
| wasm_global_get(global, &val); \ |
| check(val, type, expected); \ |
| } |
| |
| #define check_call(func, type, expected) \ |
| { \ |
| wasm_val_t results[1]; \ |
| wasm_func_call(func, NULL, results); \ |
| check(results[0], type, expected); \ |
| } |
| |
| |
| 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("global.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 globals. |
| printf("Creating globals...\n"); |
| own wasm_globaltype_t* const_f32_type = wasm_globaltype_new( |
| wasm_valtype_new(WASM_F32), WASM_CONST); |
| own wasm_globaltype_t* const_i64_type = wasm_globaltype_new( |
| wasm_valtype_new(WASM_I64), WASM_CONST); |
| own wasm_globaltype_t* var_f32_type = wasm_globaltype_new( |
| wasm_valtype_new(WASM_F32), WASM_VAR); |
| own wasm_globaltype_t* var_i64_type = wasm_globaltype_new( |
| wasm_valtype_new(WASM_I64), WASM_VAR); |
| |
| wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}}; |
| own wasm_global_t* const_f32_import = wasm_global_new(store, const_f32_type, &val_f32_1); |
| wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}}; |
| own wasm_global_t* const_i64_import = wasm_global_new(store, const_i64_type, &val_i64_2); |
| wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}}; |
| own wasm_global_t* var_f32_import = wasm_global_new(store, var_f32_type, &val_f32_3); |
| wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}}; |
| own wasm_global_t* var_i64_import = wasm_global_new(store, var_i64_type, &val_i64_4); |
| |
| wasm_globaltype_delete(const_f32_type); |
| wasm_globaltype_delete(const_i64_type); |
| wasm_globaltype_delete(var_f32_type); |
| wasm_globaltype_delete(var_i64_type); |
| |
| // Instantiate. |
| printf("Instantiating module...\n"); |
| const wasm_extern_t* imports[] = { |
| wasm_global_as_extern(const_f32_import), |
| wasm_global_as_extern(const_i64_import), |
| wasm_global_as_extern(var_f32_import), |
| wasm_global_as_extern(var_i64_import) |
| }; |
| own wasm_instance_t* instance = wasm_instance_new(store, module, imports); |
| if (!instance) { |
| printf("> Error instantiating module!\n"); |
| return 1; |
| } |
| |
| wasm_module_delete(module); |
| |
| // Extract export. |
| printf("Extracting exports...\n"); |
| own wasm_extern_vec_t exports; |
| wasm_instance_exports(instance, &exports); |
| size_t i = 0; |
| wasm_global_t* const_f32_export = get_export_global(&exports, i++); |
| wasm_global_t* const_i64_export = get_export_global(&exports, i++); |
| wasm_global_t* var_f32_export = get_export_global(&exports, i++); |
| wasm_global_t* var_i64_export = get_export_global(&exports, i++); |
| wasm_func_t* get_const_f32_import = get_export_func(&exports, i++); |
| wasm_func_t* get_const_i64_import = get_export_func(&exports, i++); |
| wasm_func_t* get_var_f32_import = get_export_func(&exports, i++); |
| wasm_func_t* get_var_i64_import = get_export_func(&exports, i++); |
| wasm_func_t* get_const_f32_export = get_export_func(&exports, i++); |
| wasm_func_t* get_const_i64_export = get_export_func(&exports, i++); |
| wasm_func_t* get_var_f32_export = get_export_func(&exports, i++); |
| wasm_func_t* get_var_i64_export = get_export_func(&exports, i++); |
| wasm_func_t* set_var_f32_import = get_export_func(&exports, i++); |
| wasm_func_t* set_var_i64_import = get_export_func(&exports, i++); |
| wasm_func_t* set_var_f32_export = get_export_func(&exports, i++); |
| wasm_func_t* set_var_i64_export = get_export_func(&exports, i++); |
| |
| // Interact. |
| printf("Accessing globals...\n"); |
| |
| // Check initial values. |
| check_global(const_f32_import, f32, 1); |
| check_global(const_i64_import, i64, 2); |
| check_global(var_f32_import, f32, 3); |
| check_global(var_i64_import, i64, 4); |
| check_global(const_f32_export, f32, 5); |
| check_global(const_i64_export, i64, 6); |
| check_global(var_f32_export, f32, 7); |
| check_global(var_i64_export, i64, 8); |
| |
| check_call(get_const_f32_import, f32, 1); |
| check_call(get_const_i64_import, i64, 2); |
| check_call(get_var_f32_import, f32, 3); |
| check_call(get_var_i64_import, i64, 4); |
| check_call(get_const_f32_export, f32, 5); |
| check_call(get_const_i64_export, i64, 6); |
| check_call(get_var_f32_export, f32, 7); |
| check_call(get_var_i64_export, i64, 8); |
| |
| // Modify variables through API and check again. |
| wasm_val_t val33 = {.kind = WASM_F32, .of = {.f32 = 33}}; |
| wasm_global_set(var_f32_import, &val33); |
| wasm_val_t val34 = {.kind = WASM_I64, .of = {.i64 = 34}}; |
| wasm_global_set(var_i64_import, &val34); |
| wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37}}; |
| wasm_global_set(var_f32_export, &val37); |
| wasm_val_t val38 = {.kind = WASM_I64, .of = {.i64 = 38}}; |
| wasm_global_set(var_i64_export, &val38); |
| |
| check_global(var_f32_import, f32, 33); |
| check_global(var_i64_import, i64, 34); |
| check_global(var_f32_export, f32, 37); |
| check_global(var_i64_export, i64, 38); |
| |
| check_call(get_var_f32_import, f32, 33); |
| check_call(get_var_i64_import, i64, 34); |
| check_call(get_var_f32_export, f32, 37); |
| check_call(get_var_i64_export, i64, 38); |
| |
| // Modify variables through calls and check again. |
| wasm_val_t args73[] = { {.kind = WASM_F32, .of = {.f32 = 73}} }; |
| wasm_func_call(set_var_f32_import, args73, NULL); |
| wasm_val_t args74[] = { {.kind = WASM_I64, .of = {.i64 = 74}} }; |
| wasm_func_call(set_var_i64_import, args74, NULL); |
| wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77}} }; |
| wasm_func_call(set_var_f32_export, args77, NULL); |
| wasm_val_t args78[] = { {.kind = WASM_I64, .of = {.i64 = 78}} }; |
| wasm_func_call(set_var_i64_export, args78, NULL); |
| |
| check_global(var_f32_import, f32, 73); |
| check_global(var_i64_import, i64, 74); |
| check_global(var_f32_export, f32, 77); |
| check_global(var_i64_export, i64, 78); |
| |
| check_call(get_var_f32_import, f32, 73); |
| check_call(get_var_i64_import, i64, 74); |
| check_call(get_var_f32_export, f32, 77); |
| check_call(get_var_i64_export, i64, 78); |
| |
| wasm_global_delete(const_f32_import); |
| wasm_global_delete(const_i64_import); |
| wasm_global_delete(var_f32_import); |
| wasm_global_delete(var_i64_import); |
| wasm_extern_vec_delete(&exports); |
| wasm_instance_delete(instance); |
| |
| // Shut down. |
| printf("Shutting down...\n"); |
| wasm_store_delete(store); |
| wasm_engine_delete(engine); |
| |
| // All done. |
| printf("Done.\n"); |
| return 0; |
| } |