1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wasm.h>
#include <wasmtime.h>
#ifdef WASMTIME_TEST_ONLY
// These are the declarations provided from GDB documentation, used to validate
// that we actually added some DWARF info:
// https://sourceware.org/gdb/current/onlinedocs/gdb.html/Declarations.html#Declarations
//
// NOTE: These are not required in your code, rather they are used for wasmtime
// testing only.
typedef enum {
JIT_NOACTION = 0,
JIT_REGISTER_FN,
JIT_UNREGISTER_FN
} jit_actions_t;
struct jit_code_entry {
struct jit_code_entry *next_entry;
struct jit_code_entry *prev_entry;
const char *symfile_addr;
uint64_t symfile_size;
};
struct jit_descriptor {
uint32_t version;
/* This type should be jit_actions_t, but we use uint32_t
to be explicit about the bitwidth. */
uint32_t action_flag;
struct jit_code_entry *relevant_entry;
struct jit_code_entry *first_entry;
};
/*
* Import the descriptor, defined elsewhere in wasmtime
*/
extern struct jit_descriptor __jit_debug_descriptor;
#endif
#define own
static void exit_with_error(const char *message, wasmtime_error_t *error,
wasm_trap_t *trap);
int main(int argc, const char *argv[]) {
// Configuring engine to support generating of DWARF info.
// lldb can be used to attach to the program and observe
// original fib-wasm.c source code and variables.
wasm_config_t *config = wasm_config_new();
wasmtime_config_debug_info_set(config, true);
wasmtime_config_cranelift_opt_level_set(config, WASMTIME_OPT_LEVEL_NONE);
// Initialize.
printf("Initializing...\n");
wasm_engine_t *engine = wasm_engine_new_with_config(config);
wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL);
wasmtime_context_t *context = wasmtime_store_context(store);
#ifdef WASMTIME_TEST_ONLY
// NOTE: This validation is for wasmtime testing and should not be included in
// your code.
if (__jit_debug_descriptor.first_entry != NULL) {
fprintf(stderr, "FAIL: JIT descriptor is already initialized\n");
return 1;
}
#endif
// Load binary.
printf("Loading binary...\n");
FILE *file = fopen("target/wasm32-unknown-unknown/debug/fib.wasm", "rb");
if (!file) {
printf("> Error opening 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 reading module!\n");
return 1;
}
fclose(file);
// Compile.
printf("Compiling module...\n");
wasmtime_module_t *module = NULL;
wasmtime_error_t *error =
wasmtime_module_new(engine, (uint8_t *)binary.data, binary.size, &module);
if (!module)
exit_with_error("failed to compile module", error, NULL);
wasm_byte_vec_delete(&binary);
// Instantiate.
printf("Instantiating module...\n");
wasmtime_instance_t instance;
wasm_trap_t *trap = NULL;
error = wasmtime_instance_new(context, module, NULL, 0, &instance, &trap);
if (error != NULL || trap != NULL)
exit_with_error("failed to instantiate", error, trap);
wasmtime_module_delete(module);
#ifdef WASMTIME_TEST_ONLY
// NOTE: This validation is for wasmtime testing and should not be included in
// your code.
if (__jit_debug_descriptor.first_entry == NULL) {
fprintf(stderr, "FAIL: JIT descriptor is NOT initialized\n");
return 1;
}
#endif
// Extract export.
wasmtime_extern_t fib;
bool ok = wasmtime_instance_export_get(context, &instance, "fib", 3, &fib);
assert(ok);
// Call.
printf("Calling fib...\n");
wasmtime_val_t params[1];
params[0].kind = WASMTIME_I32;
params[0].of.i32 = 6;
wasmtime_val_t results[1];
error =
wasmtime_func_call(context, &fib.of.func, params, 1, results, 1, &trap);
if (error != NULL || trap != NULL)
exit_with_error("failed to call function", error, trap);
assert(results[0].kind == WASMTIME_I32);
printf("> fib(6) = %d\n", results[0].of.i32);
// Shut down.
printf("Shutting down...\n");
wasmtime_store_delete(store);
wasm_engine_delete(engine);
// All done.
printf("Done.\n");
return 0;
}
static void exit_with_error(const char *message, wasmtime_error_t *error,
wasm_trap_t *trap) {
fprintf(stderr, "error: %s\n", message);
wasm_byte_vec_t error_message;
if (error != NULL) {
wasmtime_error_message(error, &error_message);
} else {
wasm_trap_message(trap, &error_message);
}
fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data);
wasm_byte_vec_delete(&error_message);
exit(1);
}
|