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