1f8fee938STyler Rockwood #include <inttypes.h>
23c51d3adSAlex Crichton #include <stdio.h>
33c51d3adSAlex Crichton #include <stdlib.h>
43c51d3adSAlex Crichton #include <string.h>
53c51d3adSAlex Crichton #include <wasm.h>
67a1b7cdfSAlex Crichton #include <wasmtime.h>
73c51d3adSAlex Crichton
86a95189cSBen Jackson #ifdef WASMTIME_TEST_ONLY
96a95189cSBen Jackson // These are the declarations provided from GDB documentation, used to validate
106a95189cSBen Jackson // that we actually added some DWARF info:
116a95189cSBen Jackson // https://sourceware.org/gdb/current/onlinedocs/gdb.html/Declarations.html#Declarations
126a95189cSBen Jackson //
136a95189cSBen Jackson // NOTE: These are not required in your code, rather they are used for wasmtime
146a95189cSBen Jackson // testing only.
156a95189cSBen Jackson typedef enum {
166a95189cSBen Jackson JIT_NOACTION = 0,
176a95189cSBen Jackson JIT_REGISTER_FN,
186a95189cSBen Jackson JIT_UNREGISTER_FN
196a95189cSBen Jackson } jit_actions_t;
206a95189cSBen Jackson
216a95189cSBen Jackson struct jit_code_entry {
226a95189cSBen Jackson struct jit_code_entry *next_entry;
236a95189cSBen Jackson struct jit_code_entry *prev_entry;
246a95189cSBen Jackson const char *symfile_addr;
256a95189cSBen Jackson uint64_t symfile_size;
266a95189cSBen Jackson };
276a95189cSBen Jackson
286a95189cSBen Jackson struct jit_descriptor {
296a95189cSBen Jackson uint32_t version;
306a95189cSBen Jackson /* This type should be jit_actions_t, but we use uint32_t
316a95189cSBen Jackson to be explicit about the bitwidth. */
326a95189cSBen Jackson uint32_t action_flag;
336a95189cSBen Jackson struct jit_code_entry *relevant_entry;
346a95189cSBen Jackson struct jit_code_entry *first_entry;
356a95189cSBen Jackson };
366a95189cSBen Jackson
376a95189cSBen Jackson /*
386a95189cSBen Jackson * Import the descriptor, defined elsewhere in wasmtime
396a95189cSBen Jackson */
406a95189cSBen Jackson extern struct jit_descriptor __jit_debug_descriptor;
416a95189cSBen Jackson #endif
426a95189cSBen Jackson
433c51d3adSAlex Crichton #define own
443c51d3adSAlex Crichton
45f8fee938STyler Rockwood static void exit_with_error(const char *message, wasmtime_error_t *error,
46f8fee938STyler Rockwood wasm_trap_t *trap);
47bd374fd6SAlex Crichton
main()48*adff9d9dSAlex Crichton int main() {
493c51d3adSAlex Crichton // Configuring engine to support generating of DWARF info.
503c51d3adSAlex Crichton // lldb can be used to attach to the program and observe
513c51d3adSAlex Crichton // original fib-wasm.c source code and variables.
523c51d3adSAlex Crichton wasm_config_t *config = wasm_config_new();
533c51d3adSAlex Crichton wasmtime_config_debug_info_set(config, true);
5496c905a6SAlex Crichton wasmtime_config_cranelift_opt_level_set(config, WASMTIME_OPT_LEVEL_NONE);
553c51d3adSAlex Crichton
563c51d3adSAlex Crichton // Initialize.
573c51d3adSAlex Crichton printf("Initializing...\n");
583c51d3adSAlex Crichton wasm_engine_t *engine = wasm_engine_new_with_config(config);
597a1b7cdfSAlex Crichton wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL);
607a1b7cdfSAlex Crichton wasmtime_context_t *context = wasmtime_store_context(store);
613c51d3adSAlex Crichton
626a95189cSBen Jackson #ifdef WASMTIME_TEST_ONLY
636a95189cSBen Jackson // NOTE: This validation is for wasmtime testing and should not be included in
646a95189cSBen Jackson // your code.
656a95189cSBen Jackson if (__jit_debug_descriptor.first_entry != NULL) {
666a95189cSBen Jackson fprintf(stderr, "FAIL: JIT descriptor is already initialized\n");
676a95189cSBen Jackson return 1;
686a95189cSBen Jackson }
696a95189cSBen Jackson #endif
706a95189cSBen Jackson
713c51d3adSAlex Crichton // Load binary.
723c51d3adSAlex Crichton printf("Loading binary...\n");
733c51d3adSAlex Crichton FILE *file = fopen("target/wasm32-unknown-unknown/debug/fib.wasm", "rb");
743c51d3adSAlex Crichton if (!file) {
753c51d3adSAlex Crichton printf("> Error opening module!\n");
763c51d3adSAlex Crichton return 1;
773c51d3adSAlex Crichton }
783c51d3adSAlex Crichton fseek(file, 0L, SEEK_END);
793c51d3adSAlex Crichton size_t file_size = ftell(file);
803c51d3adSAlex Crichton fseek(file, 0L, SEEK_SET);
813c51d3adSAlex Crichton wasm_byte_vec_t binary;
823c51d3adSAlex Crichton wasm_byte_vec_new_uninitialized(&binary, file_size);
833c51d3adSAlex Crichton if (fread(binary.data, file_size, 1, file) != 1) {
843c51d3adSAlex Crichton printf("> Error reading module!\n");
853c51d3adSAlex Crichton return 1;
863c51d3adSAlex Crichton }
873c51d3adSAlex Crichton fclose(file);
883c51d3adSAlex Crichton
893c51d3adSAlex Crichton // Compile.
903c51d3adSAlex Crichton printf("Compiling module...\n");
917a1b7cdfSAlex Crichton wasmtime_module_t *module = NULL;
92f8fee938STyler Rockwood wasmtime_error_t *error =
93f8fee938STyler Rockwood wasmtime_module_new(engine, (uint8_t *)binary.data, binary.size, &module);
94bd374fd6SAlex Crichton if (!module)
95bd374fd6SAlex Crichton exit_with_error("failed to compile module", error, NULL);
963c51d3adSAlex Crichton wasm_byte_vec_delete(&binary);
973c51d3adSAlex Crichton
983c51d3adSAlex Crichton // Instantiate.
993c51d3adSAlex Crichton printf("Instantiating module...\n");
1007a1b7cdfSAlex Crichton wasmtime_instance_t instance;
101bd374fd6SAlex Crichton wasm_trap_t *trap = NULL;
1027a1b7cdfSAlex Crichton error = wasmtime_instance_new(context, module, NULL, 0, &instance, &trap);
103bd374fd6SAlex Crichton if (error != NULL || trap != NULL)
104bd374fd6SAlex Crichton exit_with_error("failed to instantiate", error, trap);
1057a1b7cdfSAlex Crichton wasmtime_module_delete(module);
1063c51d3adSAlex Crichton
1076a95189cSBen Jackson #ifdef WASMTIME_TEST_ONLY
1086a95189cSBen Jackson // NOTE: This validation is for wasmtime testing and should not be included in
1096a95189cSBen Jackson // your code.
1106a95189cSBen Jackson if (__jit_debug_descriptor.first_entry == NULL) {
1116a95189cSBen Jackson fprintf(stderr, "FAIL: JIT descriptor is NOT initialized\n");
1126a95189cSBen Jackson return 1;
1136a95189cSBen Jackson }
1146a95189cSBen Jackson #endif
1156a95189cSBen Jackson
1163c51d3adSAlex Crichton // Extract export.
1177a1b7cdfSAlex Crichton wasmtime_extern_t fib;
1187a1b7cdfSAlex Crichton bool ok = wasmtime_instance_export_get(context, &instance, "fib", 3, &fib);
1197a1b7cdfSAlex Crichton assert(ok);
1203c51d3adSAlex Crichton
1213c51d3adSAlex Crichton // Call.
1223c51d3adSAlex Crichton printf("Calling fib...\n");
1237a1b7cdfSAlex Crichton wasmtime_val_t params[1];
1247a1b7cdfSAlex Crichton params[0].kind = WASMTIME_I32;
1257a1b7cdfSAlex Crichton params[0].of.i32 = 6;
1267a1b7cdfSAlex Crichton wasmtime_val_t results[1];
127f8fee938STyler Rockwood error =
128f8fee938STyler Rockwood wasmtime_func_call(context, &fib.of.func, params, 1, results, 1, &trap);
129bd374fd6SAlex Crichton if (error != NULL || trap != NULL)
130bd374fd6SAlex Crichton exit_with_error("failed to call function", error, trap);
1313c51d3adSAlex Crichton
1327a1b7cdfSAlex Crichton assert(results[0].kind == WASMTIME_I32);
1333c51d3adSAlex Crichton printf("> fib(6) = %d\n", results[0].of.i32);
1343c51d3adSAlex Crichton
1353c51d3adSAlex Crichton // Shut down.
1363c51d3adSAlex Crichton printf("Shutting down...\n");
1377a1b7cdfSAlex Crichton wasmtime_store_delete(store);
1383c51d3adSAlex Crichton wasm_engine_delete(engine);
1393c51d3adSAlex Crichton
1403c51d3adSAlex Crichton // All done.
1413c51d3adSAlex Crichton printf("Done.\n");
1423c51d3adSAlex Crichton return 0;
1433c51d3adSAlex Crichton }
1443c51d3adSAlex Crichton
exit_with_error(const char * message,wasmtime_error_t * error,wasm_trap_t * trap)145f8fee938STyler Rockwood static void exit_with_error(const char *message, wasmtime_error_t *error,
146f8fee938STyler Rockwood wasm_trap_t *trap) {
147bd374fd6SAlex Crichton fprintf(stderr, "error: %s\n", message);
148bd374fd6SAlex Crichton wasm_byte_vec_t error_message;
149bd374fd6SAlex Crichton if (error != NULL) {
150bd374fd6SAlex Crichton wasmtime_error_message(error, &error_message);
151bd374fd6SAlex Crichton } else {
152bd374fd6SAlex Crichton wasm_trap_message(trap, &error_message);
153bd374fd6SAlex Crichton }
154bd374fd6SAlex Crichton fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data);
155bd374fd6SAlex Crichton wasm_byte_vec_delete(&error_message);
156bd374fd6SAlex Crichton exit(1);
157bd374fd6SAlex Crichton }
158