Add Wishbone datasheets
[AGH_computer_science_engineering_thesis.git] / tools / parse_module.c
blob8c519abeb73d945bc6f4f04f9757bbc8f9c58daf
1 // TODO: count read bytes ourselves instead of relying on ftell()
2 #include "wasm_compile.h"
3 #include "wasm.h"
5 int leb_32(FILE *handle, uint32_t *result, bool with_sign)
7 int i, j;
8 int encoded[5];
9 int64_t decoded;
11 for (i = 0; i < 5; i++) {
12 encoded[i] = fgetc(handle);
14 if (encoded[i] == EOF) {
15 PRERR(MSG_EOF);
16 return -1;
19 if (encoded[i] < 128)
20 break;
22 if (i == 4) {
23 PRERR(MSG_BAD_NUM_ENC);
24 return -1;
28 if (with_sign && encoded[i] & (1 << 6))
29 decoded = -1;
30 else
31 decoded = 0;
33 for (j = i; j >= 0; j--)
34 decoded = (decoded << 7) | (encoded[j] & 0x7F);
36 if ((with_sign && decoded > INT32_MAX) ||
37 (with_sign && decoded < INT32_MIN) ||
38 (!with_sign && decoded > UINT32_MAX)) {
39 PRERR(MSG_BAD_NUM_ENC);
40 return -1;
43 *result = decoded;
45 return 0;
48 void deinitialize_resulttype(struct resulttype *type)
50 type->count = 0;
51 free(type->types);
52 type->types = NULL;
55 void deinitialize_functype(struct functype *type)
57 deinitialize_resulttype(&type->args);
58 deinitialize_resulttype(&type->results);
61 void free_module(struct module *module)
63 size_t i;
65 if (!module)
66 return;
68 for (i = 0; i < module->functypes_count; i++)
69 deinitialize_functype(module->functypes + i);
71 free(module->functypes);
73 for (i = 0; i < module->functions_count; i++) {
74 free(module->functions[i].locals);
75 free_expr(module->functions[i].translated_body);
78 free(module->functions);
80 for (i = 0; i < module->exports_count; i++)
81 free(module->exports[i].name);
83 free(module->exports);
85 free_targets(module->targets);
87 free_expr(module->startup);
89 free(module);
92 /* Guard against overflows on 32-bit systems */
93 static inline int safe_mul(size_t *factor1, uint32_t factor2)
95 uint64_t product;
97 product = *factor1;
98 product *= factor2;
100 if (product > SIZE_MAX) {
101 PRERR(MSG_SIZE_OVERFLOW);
102 return -1;
105 *factor1 = product;
107 return 0;
110 int parse_resulttype(FILE *handle, struct resulttype *type)
112 int readval;
113 uint32_t i;
115 if (leb_u32(handle, &type->count)) {
116 PRERR(MSG_BAD_NUM);
117 goto fail;
120 if (type->count) {
121 type->types = malloc(type->count);
123 if (!type->types) {
124 PRERR(MSG_ALLOC_FAIL(type->count));
125 goto fail;
127 } else {
128 type->types = NULL;
131 i = type->count;
133 while (i--) {
134 readval = fgetc(handle);
136 if (readval == EOF) {
137 PRERR(MSG_EOF);
138 goto fail;
141 if (!is_valid_valtype(readval)) {
142 PRERR(MSG_BAD("value type encoding", readval));
143 goto fail;
146 type->types[i] = readval;
149 return 0;
151 fail:
152 deinitialize_resulttype(type);
154 return -1;
157 int parse_functype(FILE *handle, struct functype *type)
159 int readval;
161 readval = fgetc(handle);
163 if (readval == EOF) {
164 PRERR(MSG_EOF);
165 return -1;
168 if (readval != 0x60) {
169 PRERR(MSG_BAD("functype starting byte (0x60)", readval));
170 return -1;
173 if (parse_resulttype(handle, &type->args) ||
174 parse_resulttype(handle, &type->results)) {
175 deinitialize_functype(type);
176 return -1;
179 return 0;
182 int parse_type_section(FILE *handle, struct module *module)
184 uint32_t types_count;
185 size_t malloc_size;
186 struct functype *types = NULL;
187 uint32_t types_parsed = 0;
189 if (leb_u32(handle, &types_count)) {
190 PRERR(MSG_BAD_NUM);
191 goto fail;
194 malloc_size = sizeof(struct functype);
196 if (safe_mul(&malloc_size, types_count)) {
197 PRERR(MSG_BAD_SIZE);
198 goto fail;
201 types = malloc(malloc_size);
203 if (!types) {
204 PRERR(MSG_ALLOC_FAIL(malloc_size));
205 goto fail;
208 while (types_parsed < types_count) {
209 if (parse_functype(handle, types + types_parsed))
210 goto fail;
212 types_parsed++;
215 module->functypes_count = types_count;
216 module->functypes = types;
218 return 0;
220 fail:
221 PRERR("Couldn't parse function types section\n");
223 if (types) {
224 while (types_parsed--)
225 deinitialize_functype(types + types_parsed);
227 free(types);
230 return -1;
233 int parse_function_section(FILE *handle, struct module *module)
235 uint32_t funcs_count;
236 size_t malloc_size;
237 struct function *funcs = NULL;
238 uint32_t i;
239 uint32_t type_idx;
241 if (leb_u32(handle, &funcs_count)) {
242 PRERR(MSG_BAD_NUM);
243 goto fail;
246 malloc_size = sizeof(struct function);
248 if (safe_mul(&malloc_size, funcs_count)) {
249 PRERR(MSG_BAD_SIZE);
250 goto fail;
253 funcs = malloc(malloc_size);
255 if (!funcs) {
256 PRERR(MSG_ALLOC_FAIL(malloc_size));
257 goto fail;
260 for (i = 0; i < funcs_count; i++) {
261 if (leb_u32(handle, &type_idx)) {
262 PRERR(MSG_BAD_NUM);
263 goto fail;
266 if (type_idx >= module->functypes_count) {
267 PRERR("Nonexistent function type index used");
268 goto fail;
271 if (module->functypes[type_idx].results.count > 1) {
272 PRERR("Function returning more than one value\n");
273 goto fail;
276 funcs[i].type = module->functypes + type_idx;
277 funcs[i].translated_body = NULL;
280 module->functions_count = funcs_count;
281 module->functions = funcs;
283 return 0;
285 fail:
286 PRERR("Couldn't parse functions section");
288 free(funcs);
290 return -1;
293 static int parse_memory_section(FILE *handle, struct module *module)
295 // TODO: move limits parsing to separate function?
296 uint32_t memories_count;
297 int limits_type;
299 if (leb_u32(handle, &memories_count)) {
300 PRERR(MSG_BAD_NUM);
301 goto fail;
304 if (memories_count > 1) {
305 PRERR("More than one Wasm memory\n");
306 goto fail;
309 limits_type = fgetc(handle);
311 if (limits_type == EOF) {
312 PRERR(MSG_EOF);
313 return -1;
316 if (leb_u32(handle, &module->mem_min)) {
317 PRERR(MSG_BAD_NUM);
318 goto fail;
321 if (limits_type == 0x00) {
322 module->memory_type = MEM_MIN;
323 } else if (limits_type == 0x01) {
324 if (leb_u32(handle, &module->mem_max)) {
325 PRERR(MSG_BAD_NUM);
326 goto fail;
329 module->memory_type = MEM_MIN_MAX;
330 } else {
331 PRERR(MSG_BAD("limit type", limits_type));
332 goto fail;
335 return 0;
337 fail:
338 module->mem_min = 0;
340 return -1;
343 static int parse_export_section(FILE *handle, struct module *module)
345 int readval;
346 uint32_t exports_count;
347 size_t malloc_size;
348 struct export *exports = NULL;
349 uint32_t exports_parsed = 0;
350 uint32_t name_len;
351 char *name;
353 if (leb_u32(handle, &exports_count)) {
354 PRERR(MSG_BAD_NUM);
355 goto fail;
358 malloc_size = sizeof(struct export);
360 if (safe_mul(&malloc_size, exports_count)) {
361 PRERR(MSG_BAD_SIZE);
362 goto fail;
365 exports = malloc(malloc_size);
367 if (!exports) {
368 PRERR(MSG_ALLOC_FAIL(malloc_size));
369 goto fail;
372 while (exports_parsed < exports_count) {
373 if (leb_u32(handle, &name_len)) {
374 PRERR(MSG_BAD_NUM);
375 goto fail;
378 name = malloc(name_len + 1);
380 if (!name) {
381 PRERR(MSG_ALLOC_FAIL(name_len + 1));
382 goto fail;
385 exports[exports_parsed].name = name;
386 /* Increment here, so that jump to fail: frees the name */
387 exports_parsed++;
389 if (fread(name, name_len, 1, handle) != 1) {
390 PRERR(MSG_EOF);
391 goto fail;
394 name[name_len] = '\0';
396 readval = fgetc(handle);
398 if (!is_valid_exportdesc(readval)) {
399 PRERR(MSG_BAD("exportdesc", readval));
400 goto fail;
403 exports[exports_parsed - 1].desc = readval;
405 if (leb_u32(handle, &exports[exports_parsed - 1].idx)) {
406 PRERR(MSG_BAD_NUM);
407 goto fail;
411 module->exports_count = exports_count;
412 module->exports = exports;
414 return 0;
416 fail:
417 PRERR("Couldn't parse exports section\n");
419 if (exports) {
420 while (exports_parsed) {
421 free(exports[exports_parsed - 1].name);
422 exports_parsed--;
425 free(exports);
428 return -1;
431 static int parse_function_code(FILE *handle, struct function *function,
432 struct module *module)
434 int readval;
435 uint32_t locals_blocks;
436 uint32_t locals_count = 0;
437 char *locals = NULL, *tmp;
438 uint32_t i;
439 uint32_t locals_in_block;
441 if (leb_u32(handle, &locals_blocks)) {
442 PRERR(MSG_BAD_NUM);
443 goto fail;
446 for (i = 0; i < locals_blocks; i++) {
447 if (leb_u32(handle, &locals_in_block)) {
448 PRERR(MSG_BAD_NUM);
449 goto fail;
452 if (locals_count + (uint64_t) locals_in_block +
453 (uint64_t) function->type->args.count > UINT32_MAX) {
454 PRERR("Too many locals\n");
455 goto fail;
458 locals_count += locals_in_block;
460 if (locals_in_block) {
461 tmp = realloc(locals, locals_count);
463 if (!tmp) {
464 PRERR(MSG_ALLOC_FAIL(locals_count));
465 goto fail;
468 locals = tmp;
471 readval = fgetc(handle);
473 if (readval == EOF) {
474 PRERR(MSG_EOF);
475 goto fail;
478 if (!is_valid_valtype(readval)) {
479 PRERR(MSG_BAD("value type encoding", readval));
480 goto fail;
483 while (locals_in_block)
484 locals[locals_count - locals_in_block--] = readval;
487 function->translated_body = NULL;
489 function->locals_count = locals_count;
490 function->locals = locals;
492 if (translate(handle, function, module))
493 goto fail;
495 return 0;
497 fail:
498 free(locals);
500 return -1;
503 int parse_code_section(FILE *handle, struct module *module)
505 uint32_t functions_count;
506 uint32_t functions_parsed = 0;
507 uint32_t function_size;
508 long function_start, function_end;
510 if (leb_u32(handle, &functions_count)) {
511 PRERR(MSG_BAD_NUM);
512 goto fail;
515 if (functions_count != module->functions_count) {
516 PRERR("Number of function bodies doesn't match number of functions\n");
517 goto fail;
520 while (functions_parsed < functions_count) {
521 if (leb_u32(handle, &function_size)) {
522 PRERR(MSG_BAD_NUM);
523 goto fail;
526 function_start = ftell(handle);
528 if (parse_function_code(handle,
529 module->functions + functions_parsed,
530 module)) {
531 PRERR("Couldn't parse code of function %lu\n",
532 (unsigned long) functions_parsed);
533 goto fail;
536 function_end = ftell(handle);
538 if (function_end - function_size != function_start) {
539 PRERR("Function %lu started at offset %ld and should end at %ld, but ended at %ld\n",
540 (unsigned long) functions_parsed,
541 function_start, function_end,
542 (long) (function_start + function_size));
543 goto fail;
546 functions_parsed++;
549 return 0;
551 fail:
552 PRERR("Couldn't parse code section\n");
554 while (functions_parsed) {
555 free(module->functions[functions_parsed - 1].locals);
556 free_expr(module->functions[functions_parsed - 1]
557 .translated_body);
558 module->functions[functions_parsed - 1].translated_body = NULL;
560 functions_parsed--;
563 return -1;
566 static const char magic[] = {0x00, 0x61, 0x73, 0x6D};
567 static const char version[] = {0x01, 0x00, 0x00, 0x00};
569 struct module *parse_module(FILE *handle)
571 char initial[8];
572 struct module *module = NULL;
573 int section_id;
574 char highest_section_id = 0;
575 uint32_t section_size;
576 long section_start, section_end;
577 int (*section_parser) (FILE*, struct module*);
579 if (fread(initial, 8, 1, handle) != 1) {
580 PRERR(MSG_EOF);
581 goto fail;
584 /* check magic number */
585 if (memcmp(initial, magic, 4)) {
586 PRERR("Bad magic number\n");
587 goto fail;
590 /* check version */
591 if (memcmp(initial + 4, version, 4)) {
592 PRERR("Unsupported Wasm version: 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx\n",
593 initial[4], initial[5], initial[6], initial[7]);
594 goto fail;
597 module = calloc(1, sizeof(struct module));
599 if (!module) {
600 PRERR(MSG_ALLOC_FAIL(sizeof(struct module)));
601 goto fail;
604 while (1) {
605 section_id = fgetc(handle);
607 if (section_id == EOF)
608 break;
610 if (leb_u32(handle, &section_size)) {
611 PRERR(MSG_BAD_NUM);
612 goto fail;
615 section_start = ftell(handle);
617 if (section_id == SECTION_CUSTOM)
618 continue;
620 /* Sections are only allowed to appear in order */
621 if (section_id <= highest_section_id) {
622 PRERR("Sections out of order\n");
623 goto fail;
626 highest_section_id = section_id;
628 if (section_id == SECTION_TYPE) {
629 section_parser = parse_type_section;
630 } else if (section_id == SECTION_FUNCTION) {
631 section_parser = parse_function_section;
632 } else if (section_id == SECTION_MEMORY) {
633 section_parser = parse_memory_section;
634 } else if (section_id == SECTION_EXPORT) {
635 section_parser = parse_export_section;
636 } else if (section_id == SECTION_CODE) {
637 section_parser = parse_code_section;
638 } else {
639 PRERR("Unknown section id: %d\n", section_id);
640 goto fail;
643 if (section_parser(handle, module))
644 goto fail;
646 section_end = ftell(handle);
648 if (section_end - section_size != section_start) {
649 PRERR("Section %d started at offset %ld and should end at %ld, but ended at %ld\n",
650 section_id, section_start, section_end,
651 (long) (section_start + section_size));
652 goto fail;
656 return module;
658 fail:
659 PRERR("Parsing failed\n");
661 free_module(module);
663 return NULL;