1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <inttypes.h>
5 
6 #include "wasm.h"
7 
8 #define own
9 
get_export_global(const wasm_extern_vec_t * exports,size_t i)10 wasm_global_t* get_export_global(const wasm_extern_vec_t* exports, size_t i) {
11   if (exports->size <= i || !wasm_extern_as_global(exports->data[i])) {
12     printf("> Error accessing global export %zu!\n", i);
13     exit(1);
14   }
15   return wasm_extern_as_global(exports->data[i]);
16 }
17 
get_export_func(const wasm_extern_vec_t * exports,size_t i)18 wasm_func_t* get_export_func(const wasm_extern_vec_t* exports, size_t i) {
19   if (exports->size <= i || !wasm_extern_as_func(exports->data[i])) {
20     printf("> Error accessing function export %zu!\n", i);
21     exit(1);
22   }
23   return wasm_extern_as_func(exports->data[i]);
24 }
25 
26 
27 #define check(val, type, expected) \
28   if (val.of.type != expected) { \
29     printf("> Error reading value\n"); \
30     exit(1); \
31   }
32 
33 #define check_global(global, type, expected) \
34   { \
35     wasm_val_t val; \
36     wasm_global_get(global, &val); \
37     check(val, type, expected); \
38   }
39 
40 #define check_call(func, type, expected) \
41   { \
42     wasm_val_t results[1]; \
43     wasm_func_call(func, NULL, results); \
44     check(results[0], type, expected); \
45   }
46 
47 
main(int argc,const char * argv[])48 int main(int argc, const char* argv[]) {
49   // Initialize.
50   printf("Initializing...\n");
51   wasm_engine_t* engine = wasm_engine_new();
52   wasm_store_t* store = wasm_store_new(engine);
53 
54   // Load binary.
55   printf("Loading binary...\n");
56   FILE* file = fopen("global.wasm", "r");
57   if (!file) {
58     printf("> Error loading module!\n");
59     return 1;
60   }
61   fseek(file, 0L, SEEK_END);
62   size_t file_size = ftell(file);
63   fseek(file, 0L, SEEK_SET);
64   wasm_byte_vec_t binary;
65   wasm_byte_vec_new_uninitialized(&binary, file_size);
66   if (fread(binary.data, file_size, 1, file) != 1) {
67     printf("> Error loading module!\n");
68     return 1;
69   }
70   fclose(file);
71 
72   // Compile.
73   printf("Compiling module...\n");
74   own wasm_module_t* module = wasm_module_new(store, &binary);
75   if (!module) {
76     printf("> Error compiling module!\n");
77     return 1;
78   }
79 
80   wasm_byte_vec_delete(&binary);
81 
82   // Create external globals.
83   printf("Creating globals...\n");
84   own wasm_globaltype_t* const_f32_type = wasm_globaltype_new(
85     wasm_valtype_new(WASM_F32), WASM_CONST);
86   own wasm_globaltype_t* const_i64_type = wasm_globaltype_new(
87     wasm_valtype_new(WASM_I64), WASM_CONST);
88   own wasm_globaltype_t* var_f32_type = wasm_globaltype_new(
89     wasm_valtype_new(WASM_F32), WASM_VAR);
90   own wasm_globaltype_t* var_i64_type = wasm_globaltype_new(
91     wasm_valtype_new(WASM_I64), WASM_VAR);
92 
93   wasm_val_t val_f32_1 = {.kind = WASM_F32, .of = {.f32 = 1}};
94   own wasm_global_t* const_f32_import =
95     wasm_global_new(store, const_f32_type, &val_f32_1);
96   wasm_val_t val_i64_2 = {.kind = WASM_I64, .of = {.i64 = 2}};
97   own wasm_global_t* const_i64_import =
98     wasm_global_new(store, const_i64_type, &val_i64_2);
99   wasm_val_t val_f32_3 = {.kind = WASM_F32, .of = {.f32 = 3}};
100   own wasm_global_t* var_f32_import =
101     wasm_global_new(store, var_f32_type, &val_f32_3);
102   wasm_val_t val_i64_4 = {.kind = WASM_I64, .of = {.i64 = 4}};
103   own wasm_global_t* var_i64_import =
104     wasm_global_new(store, var_i64_type, &val_i64_4);
105 
106   wasm_globaltype_delete(const_f32_type);
107   wasm_globaltype_delete(const_i64_type);
108   wasm_globaltype_delete(var_f32_type);
109   wasm_globaltype_delete(var_i64_type);
110 
111   // Instantiate.
112   printf("Instantiating module...\n");
113   const wasm_extern_t* imports[] = {
114     wasm_global_as_extern(const_f32_import),
115     wasm_global_as_extern(const_i64_import),
116     wasm_global_as_extern(var_f32_import),
117     wasm_global_as_extern(var_i64_import)
118   };
119   own wasm_instance_t* instance =
120     wasm_instance_new(store, module, imports, NULL);
121   if (!instance) {
122     printf("> Error instantiating module!\n");
123     return 1;
124   }
125 
126   wasm_module_delete(module);
127 
128   // Extract export.
129   printf("Extracting exports...\n");
130   own wasm_extern_vec_t exports;
131   wasm_instance_exports(instance, &exports);
132   size_t i = 0;
133   wasm_global_t* const_f32_export = get_export_global(&exports, i++);
134   wasm_global_t* const_i64_export = get_export_global(&exports, i++);
135   wasm_global_t* var_f32_export = get_export_global(&exports, i++);
136   wasm_global_t* var_i64_export = get_export_global(&exports, i++);
137   wasm_func_t* get_const_f32_import = get_export_func(&exports, i++);
138   wasm_func_t* get_const_i64_import = get_export_func(&exports, i++);
139   wasm_func_t* get_var_f32_import = get_export_func(&exports, i++);
140   wasm_func_t* get_var_i64_import = get_export_func(&exports, i++);
141   wasm_func_t* get_const_f32_export = get_export_func(&exports, i++);
142   wasm_func_t* get_const_i64_export = get_export_func(&exports, i++);
143   wasm_func_t* get_var_f32_export = get_export_func(&exports, i++);
144   wasm_func_t* get_var_i64_export = get_export_func(&exports, i++);
145   wasm_func_t* set_var_f32_import = get_export_func(&exports, i++);
146   wasm_func_t* set_var_i64_import = get_export_func(&exports, i++);
147   wasm_func_t* set_var_f32_export = get_export_func(&exports, i++);
148   wasm_func_t* set_var_i64_export = get_export_func(&exports, i++);
149 
150   // Try cloning.
151   own wasm_global_t* copy = wasm_global_copy(var_f32_import);
152   assert(wasm_global_same(var_f32_import, copy));
153   wasm_global_delete(copy);
154 
155   // Interact.
156   printf("Accessing globals...\n");
157 
158   // Check initial values.
159   check_global(const_f32_import, f32, 1);
160   check_global(const_i64_import, i64, 2);
161   check_global(var_f32_import, f32, 3);
162   check_global(var_i64_import, i64, 4);
163   check_global(const_f32_export, f32, 5);
164   check_global(const_i64_export, i64, 6);
165   check_global(var_f32_export, f32, 7);
166   check_global(var_i64_export, i64, 8);
167 
168   check_call(get_const_f32_import, f32, 1);
169   check_call(get_const_i64_import, i64, 2);
170   check_call(get_var_f32_import, f32, 3);
171   check_call(get_var_i64_import, i64, 4);
172   check_call(get_const_f32_export, f32, 5);
173   check_call(get_const_i64_export, i64, 6);
174   check_call(get_var_f32_export, f32, 7);
175   check_call(get_var_i64_export, i64, 8);
176 
177   // Modify variables through API and check again.
178   wasm_val_t val33 = {.kind = WASM_F32, .of = {.f32 = 33}};
179   wasm_global_set(var_f32_import, &val33);
180   wasm_val_t val34 = {.kind = WASM_I64, .of = {.i64 = 34}};
181   wasm_global_set(var_i64_import, &val34);
182   wasm_val_t val37 = {.kind = WASM_F32, .of = {.f32 = 37}};
183   wasm_global_set(var_f32_export, &val37);
184   wasm_val_t val38 = {.kind = WASM_I64, .of = {.i64 = 38}};
185   wasm_global_set(var_i64_export, &val38);
186 
187   check_global(var_f32_import, f32, 33);
188   check_global(var_i64_import, i64, 34);
189   check_global(var_f32_export, f32, 37);
190   check_global(var_i64_export, i64, 38);
191 
192   check_call(get_var_f32_import, f32, 33);
193   check_call(get_var_i64_import, i64, 34);
194   check_call(get_var_f32_export, f32, 37);
195   check_call(get_var_i64_export, i64, 38);
196 
197   // Modify variables through calls and check again.
198   wasm_val_t args73[] = { {.kind = WASM_F32, .of = {.f32 = 73}} };
199   wasm_func_call(set_var_f32_import, args73, NULL);
200   wasm_val_t args74[] = { {.kind = WASM_I64, .of = {.i64 = 74}} };
201   wasm_func_call(set_var_i64_import, args74, NULL);
202   wasm_val_t args77[] = { {.kind = WASM_F32, .of = {.f32 = 77}} };
203   wasm_func_call(set_var_f32_export, args77, NULL);
204   wasm_val_t args78[] = { {.kind = WASM_I64, .of = {.i64 = 78}} };
205   wasm_func_call(set_var_i64_export, args78, NULL);
206 
207   check_global(var_f32_import, f32, 73);
208   check_global(var_i64_import, i64, 74);
209   check_global(var_f32_export, f32, 77);
210   check_global(var_i64_export, i64, 78);
211 
212   check_call(get_var_f32_import, f32, 73);
213   check_call(get_var_i64_import, i64, 74);
214   check_call(get_var_f32_export, f32, 77);
215   check_call(get_var_i64_export, i64, 78);
216 
217   wasm_global_delete(const_f32_import);
218   wasm_global_delete(const_i64_import);
219   wasm_global_delete(var_f32_import);
220   wasm_global_delete(var_i64_import);
221   wasm_extern_vec_delete(&exports);
222   wasm_instance_delete(instance);
223 
224   // Shut down.
225   printf("Shutting down...\n");
226   wasm_store_delete(store);
227   wasm_engine_delete(engine);
228 
229   // All done.
230   printf("Done.\n");
231   return 0;
232 }
233