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
main()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
exit_with_error(const char * message,wasmtime_error_t * error,wasm_trap_t * trap)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