authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-28 17:52:10+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-10-28 17:52:10+01:00
logd22049a987493d1cb64d54829dc042726d6cc2de
tree5b22c7099441e1e8f5e274c6916e28788a52b853
parentcdd8e82f0ac7ace0a03653960fbf9ba3daa69dc4
parentc2e6be97ffc23f2fa6c28175766b8bb565e9c970
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21693 from alexrp/wasm2c-endian

`wasm2c`: Add big endian support.

2 files changed, 102 insertions(+), 62 deletions(-)

stage1/wasi.c+65-41
......@@ -184,6 +184,26 @@ enum wasi_whence {
184184 wasi_whence_end = 2,
185185};
186186
187extern uint16_t load16_align0(const uint8_t *ptr);
188extern uint16_t load16_align1(const uint16_t *ptr);
189extern uint32_t load32_align0(const uint8_t *ptr);
190extern uint32_t load32_align1(const uint16_t *ptr);
191extern uint32_t load32_align2(const uint32_t *ptr);
192extern uint64_t load64_align0(const uint8_t *ptr);
193extern uint64_t load64_align1(const uint16_t *ptr);
194extern uint64_t load64_align2(const uint32_t *ptr);
195extern uint64_t load64_align3(const uint64_t *ptr);
196
197extern void store16_align0(uint8_t *ptr, uint16_t val);
198extern void store16_align1(uint16_t *ptr, uint16_t val);
199extern void store32_align0(uint8_t *ptr, uint32_t val);
200extern void store32_align1(uint16_t *ptr, uint32_t val);
201extern void store32_align2(uint32_t *ptr, uint32_t val);
202extern void store64_align0(uint8_t *ptr, uint64_t val);
203extern void store64_align1(uint16_t *ptr, uint64_t val);
204extern void store64_align2(uint32_t *ptr, uint64_t val);
205extern void store64_align3(uint64_t *ptr, uint64_t val);
206
187207extern uint8_t **const wasm_memory;
188208extern void wasm__start(void);
189209
......@@ -362,14 +382,14 @@ static enum wasi_errno DirEntry_lookup(uint32_t dir_fd, uint32_t flags, const ch
362382}
363383
364384static void DirEntry_filestat(uint32_t de, struct wasi_filestat *res_filestat) {
365 res_filestat->dev = 0;
366 res_filestat->ino = de;
367 res_filestat->filetype = des[de].filetype;
368 res_filestat->nlink = 1;
369 res_filestat->size = 0;
370 res_filestat->atim = des[de].atim * UINT64_C(1000000000);
371 res_filestat->mtim = des[de].mtim * UINT64_C(1000000000);
372 res_filestat->ctim = des[de].ctim * UINT64_C(1000000000);
385 store64_align3(&res_filestat->dev, 0);
386 store64_align3(&res_filestat->ino, de);
387 store64_align3(&res_filestat->filetype, des[de].filetype);
388 store64_align3(&res_filestat->nlink, 1);
389 store64_align3(&res_filestat->size, 0);
390 store64_align3(&res_filestat->atim, des[de].atim * UINT64_C(1000000000));
391 store64_align3(&res_filestat->mtim, des[de].mtim * UINT64_C(1000000000));
392 store64_align3(&res_filestat->ctim, des[de].ctim * UINT64_C(1000000000));
373393}
374394
375395static void DirEntry_unlink(uint32_t de) {
......@@ -394,8 +414,8 @@ uint32_t wasi_snapshot_preview1_args_sizes_get(uint32_t argv_size, uint32_t argv
394414 if (i == 1) continue;
395415 size += strlen(c_argv[i]) + 1;
396416 }
397 *argv_size_ptr = c_argc - 1;
398 *argv_buf_size_ptr = size;
417 store32_align2(argv_size_ptr, c_argc - 1);
418 store32_align2(argv_buf_size_ptr, size);
399419 return wasi_errno_success;
400420}
401421
......@@ -413,7 +433,7 @@ uint32_t wasi_snapshot_preview1_args_get(uint32_t argv, uint32_t argv_buf) {
413433 uint32_t argv_buf_i = 0;
414434 for (int src_i = 0; src_i < c_argc; src_i += 1) {
415435 if (src_i == 1) continue;
416 argv_ptr[dst_i] = argv_buf + argv_buf_i;
436 store32_align2(&argv_ptr[dst_i], argv_buf + argv_buf_i);
417437 dst_i += 1;
418438 strcpy(&argv_buf_ptr[argv_buf_i], c_argv[src_i]);
419439 argv_buf_i += strlen(c_argv[src_i]) + 1;
......@@ -430,8 +450,8 @@ uint32_t wasi_snapshot_preview1_fd_prestat_get(uint32_t fd, uint32_t res_prestat
430450
431451 if (fd >= fd_len || fds[fd].de >= de_len) return wasi_errno_badf;
432452
433 res_prestat_ptr[0] = 0;
434 res_prestat_ptr[1] = strlen(des[fds[fd].de].guest_path);
453 store32_align2(&res_prestat_ptr[0], 0);
454 store32_align2(&res_prestat_ptr[1], strlen(des[fds[fd].de].guest_path));
435455 return wasi_errno_success;
436456}
437457
......@@ -443,7 +463,7 @@ uint32_t wasi_snapshot_preview1_fd_prestat_dir_name(uint32_t fd, uint32_t path,
443463#endif
444464
445465 if (fd >= fd_len || fds[fd].de >= de_len) return wasi_errno_badf;
446 strncpy(path_ptr, des[fds[fd].de].guest_path, path_len);
466 strncpy(path_ptr, des[fds[fd].de].guest_path, path_len);
447467 return wasi_errno_success;
448468}
449469
......@@ -502,15 +522,16 @@ uint32_t wasi_snapshot_preview1_fd_read(uint32_t fd, uint32_t iovs, uint32_t iov
502522
503523 size_t size = 0;
504524 for (uint32_t i = 0; i < iovs_len; i += 1) {
525 uint32_t len = load32_align2(&iovs_ptr[i].len);
505526 size_t read_size = 0;
506527 if (fds[fd].stream != NULL)
507 read_size = fread(&m[iovs_ptr[i].ptr], 1, iovs_ptr[i].len, fds[fd].stream);
528 read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
508529 size += read_size;
509 if (read_size < iovs_ptr[i].len) break;
530 if (read_size < len) break;
510531 }
511532
512533 if (size > 0) des[fds[fd].de].atim = time(NULL);
513 *res_size_ptr = size;
534 store32_align2(res_size_ptr, size);
514535 return wasi_errno_success;
515536}
516537
......@@ -530,7 +551,7 @@ uint32_t wasi_snapshot_preview1_fd_filestat_get(uint32_t fd, uint32_t res_filest
530551 if (fseek(fds[fd].stream, 0, SEEK_END) < 0) return wasi_errno_io;
531552 long size = ftell(fds[fd].stream);
532553 if (size < 0) return wasi_errno_io;
533 res_filestat_ptr->size = size;
554 store64_align3(&res_filestat_ptr->size, size);
534555 if (fsetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;
535556 return wasi_errno_success;
536557}
......@@ -617,13 +638,14 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i
617638
618639 size_t size = 0;
619640 for (uint32_t i = 0; i < iovs_len; i += 1) {
641 uint32_t len = load32_align2(&iovs_ptr[i].len);
620642 size_t written_size = 0;
621643 if (fds[fd].stream != NULL)
622 written_size = fwrite(&m[iovs_ptr[i].ptr], 1, iovs_ptr[i].len, fds[fd].stream);
644 written_size = fwrite(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
623645 else
624 written_size = iovs_ptr[i].len;
646 written_size = len;
625647 size += written_size;
626 if (written_size < iovs_ptr[i].len) break;
648 if (written_size < len) break;
627649 }
628650
629651 if (fsetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;
......@@ -633,7 +655,7 @@ uint32_t wasi_snapshot_preview1_fd_pwrite(uint32_t fd, uint32_t iovs, uint32_t i
633655 des[fds[fd].de].atim = now;
634656 des[fds[fd].de].mtim = now;
635657 }
636 *res_size_ptr = size;
658 store32_align2(res_size_ptr, size);
637659 return wasi_errno_success;
638660}
639661
......@@ -669,8 +691,8 @@ uint32_t wasi_snapshot_preview1_environ_sizes_get(uint32_t environ_size, uint32_
669691 fprintf(stderr, "wasi_snapshot_preview1_environ_sizes_get()\n");
670692#endif
671693
672 *environ_size_ptr = 0;
673 *environ_buf_size_ptr = 0;
694 store32_align2(environ_size_ptr, 0);
695 store32_align2(environ_buf_size_ptr, 0);
674696 return wasi_errno_success;
675697}
676698
......@@ -702,7 +724,7 @@ uint32_t wasi_snapshot_preview1_path_filestat_get(uint32_t fd, uint32_t flags, u
702724 if (stream != NULL) {
703725 if (fseek(stream, 0, SEEK_END) >= 0) {
704726 long size = ftell(stream);
705 if (size >= 0) res_filestat_ptr->size = size;
727 if (size >= 0) store64_align3(&res_filestat_ptr->size, size);
706728 }
707729 fclose(stream);
708730 }
......@@ -718,10 +740,10 @@ uint32_t wasi_snapshot_preview1_fd_fdstat_get(uint32_t fd, uint32_t res_fdstat)
718740#endif
719741
720742 if (fd >= fd_len || fds[fd].de >= de_len) return wasi_errno_badf;
721 res_fdstat_ptr->fs_filetype = des[fds[fd].de].filetype;
722 res_fdstat_ptr->fs_flags = fds[fd].fdflags;
723 res_fdstat_ptr->padding = 0;
724 res_fdstat_ptr->fs_rights_inheriting = fds[fd].fs_rights_inheriting;
743 store16_align1(&res_fdstat_ptr->fs_filetype, des[fds[fd].de].filetype);
744 store16_align1(&res_fdstat_ptr->fs_flags, fds[fd].fdflags);
745 store32_align2(&res_fdstat_ptr->padding, 0);
746 store64_align3(&res_fdstat_ptr->fs_rights_inheriting, fds[fd].fs_rights_inheriting);
725747 return wasi_errno_success;
726748}
727749
......@@ -757,13 +779,14 @@ uint32_t wasi_snapshot_preview1_fd_write(uint32_t fd, uint32_t iovs, uint32_t io
757779
758780 size_t size = 0;
759781 for (uint32_t i = 0; i < iovs_len; i += 1) {
782 uint32_t len = load32_align2(&iovs_ptr[i].len);
760783 size_t written_size = 0;
761784 if (fds[fd].stream != NULL)
762 written_size = fwrite(&m[iovs_ptr[i].ptr], 1, iovs_ptr[i].len, fds[fd].stream);
785 written_size = fwrite(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
763786 else
764 written_size = iovs_ptr[i].len;
787 written_size = len;
765788 size += written_size;
766 if (written_size < iovs_ptr[i].len) break;
789 if (written_size < len) break;
767790 }
768791
769792 if (size > 0) {
......@@ -771,7 +794,7 @@ uint32_t wasi_snapshot_preview1_fd_write(uint32_t fd, uint32_t iovs, uint32_t io
771794 des[fds[fd].de].atim = now;
772795 des[fds[fd].de].mtim = now;
773796 }
774 *res_size_ptr = size;
797 store32_align2(res_size_ptr, size);
775798 return wasi_errno_success;
776799}
777800
......@@ -809,7 +832,7 @@ uint32_t wasi_snapshot_preview1_path_open(uint32_t fd, uint32_t dirflags, uint32
809832#if LOG_TRACE
810833 fprintf(stderr, "fd = %u\n", fd_len);
811834#endif
812 *res_fd_ptr = fd_len;
835 store32_align2(res_fd_ptr, fd_len);
813836 fd_len += 1;
814837 }
815838 if (lookup_errno != wasi_errno_noent) return lookup_errno;
......@@ -867,7 +890,7 @@ uint32_t wasi_snapshot_preview1_path_open(uint32_t fd, uint32_t dirflags, uint32
867890 fds[fd_len].fdflags = fdflags;
868891 fds[fd_len].stream = stream;
869892 fds[fd_len].fs_rights_inheriting = fs_rights_inheriting;
870 *res_fd_ptr = fd_len;
893 store32_align2(res_fd_ptr, fd_len);
871894 fd_len += 1;
872895 return wasi_errno_success;
873896}
......@@ -882,12 +905,12 @@ uint32_t wasi_snapshot_preview1_clock_time_get(uint32_t id, uint64_t precision,
882905
883906 switch (id) {
884907 case wasi_clockid_realtime:
885 *res_timestamp_ptr = time(NULL) * UINT64_C(1000000000);
908 store64_align3(res_timestamp_ptr, time(NULL) * UINT64_C(1000000000));
886909 break;
887910 case wasi_clockid_monotonic:
888911 case wasi_clockid_process_cputime_id:
889912 case wasi_clockid_thread_cputime_id:
890 *res_timestamp_ptr = clock() * (UINT64_C(1000000000) / CLOCKS_PER_SEC);
913 store64_align3(res_timestamp_ptr, clock() * (UINT64_C(1000000000) / CLOCKS_PER_SEC));
891914 break;
892915 default: return wasi_errno_inval;
893916 }
......@@ -947,19 +970,20 @@ uint32_t wasi_snapshot_preview1_fd_pread(uint32_t fd, uint32_t iovs, uint32_t io
947970
948971 size_t size = 0;
949972 for (uint32_t i = 0; i < iovs_len; i += 1) {
973 uint32_t len = load32_align2(&iovs_ptr[i].len);
950974 size_t read_size = 0;
951975 if (fds[fd].stream != NULL)
952 read_size = fread(&m[iovs_ptr[i].ptr], 1, iovs_ptr[i].len, fds[fd].stream);
976 read_size = fread(&m[load32_align2(&iovs_ptr[i].ptr)], 1, len, fds[fd].stream);
953977 else
954978 panic("unimplemented");
955979 size += read_size;
956 if (read_size < iovs_ptr[i].len) break;
980 if (read_size < len) break;
957981 }
958982
959983 if (fsetpos(fds[fd].stream, &pos) < 0) return wasi_errno_io;
960984
961985 if (size > 0) des[fds[fd].de].atim = time(NULL);
962 *res_size_ptr = size;
986 store32_align2(res_size_ptr, size);
963987 return wasi_errno_success;
964988}
965989
......@@ -996,7 +1020,7 @@ uint32_t wasi_snapshot_preview1_fd_seek(uint32_t fd, uint64_t in_offset, uint32_
9961020 if (fseek(fds[fd].stream, offset, seek_whence) < 0) return wasi_errno_io;
9971021 long res_offset = ftell(fds[fd].stream);
9981022 if (res_offset < 0) return wasi_errno_io;
999 *res_filesize_ptr = (uint64_t)res_offset;
1023 store64_align3(res_filesize_ptr, res_offset);
10001024 return wasi_errno_success;
10011025}
10021026
stage1/wasm2c.c+37-21
......@@ -73,14 +73,30 @@ static void renderExpr(FILE *out, struct InputStream *in) {
7373 }
7474}
7575
76static const uint32_t big_endian = 0xff000000;
77
7678int main(int argc, char **argv) {
77 if (argc != 3) {
78 fprintf(stderr, "usage: %s in.wasm.zst out.c\n", argv[0]);
79 if (argc != 3 && argc != 4) {
80 fprintf(stderr, "usage: %s <in.wasm.zst> <out.c> [endian]\n", argv[0]);
7981 return 1;
8082 }
8183
84 bool is_big_endian;
85
86 if (argc >= 4) {
87 if (!strcmp(argv[3], "big")) {
88 is_big_endian = true;
89 } else if (!strcmp(argv[3], "little")) {
90 is_big_endian = false;
91 } else {
92 fprintf(stderr, "endianness must be 'big' or 'little'\n");
93 return 1;
94 }
95 } else {
96 is_big_endian = *(uint8_t *)&big_endian; // Infer from host endianness.
97 }
98
8299 const char *mod = "wasm";
83 bool is_big_endian = false; // TODO
84100
85101 struct InputStream in;
86102 InputStream_open(&in, argv[1]);
......@@ -111,55 +127,55 @@ int main(int argc, char **argv) {
111127 " (uint64_t)i32_byteswap(src >> 32) << 0;\n"
112128 "}\n"
113129 "\n", out);
114 fputs("static uint16_t load16_align0(const uint8_t *ptr) {\n"
130 fputs("uint16_t load16_align0(const uint8_t *ptr) {\n"
115131 " uint16_t val;\n"
116132 " memcpy(&val, ptr, sizeof(val));\n", out);
117133 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
118134 fputs(" return val;\n"
119135 "}\n"
120 "static uint16_t load16_align1(const uint16_t *ptr) {\n"
136 "uint16_t load16_align1(const uint16_t *ptr) {\n"
121137 " uint16_t val;\n"
122138 " memcpy(&val, ptr, sizeof(val));\n", out);
123139 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
124140 fputs(" return val;\n"
125141 "}\n"
126 "static uint32_t load32_align0(const uint8_t *ptr) {\n"
142 "uint32_t load32_align0(const uint8_t *ptr) {\n"
127143 " uint32_t val;\n"
128144 " memcpy(&val, ptr, sizeof(val));\n", out);
129145 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
130146 fputs(" return val;\n"
131147 "}\n"
132 "static uint32_t load32_align1(const uint16_t *ptr) {\n"
148 "uint32_t load32_align1(const uint16_t *ptr) {\n"
133149 " uint32_t val;\n"
134150 " memcpy(&val, ptr, sizeof(val));\n", out);
135151 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
136152 fputs(" return val;\n"
137153 "}\n"
138 "static uint32_t load32_align2(const uint32_t *ptr) {\n"
154 "uint32_t load32_align2(const uint32_t *ptr) {\n"
139155 " uint32_t val;\n"
140156 " memcpy(&val, ptr, sizeof(val));\n", out);
141157 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
142158 fputs(" return val;\n"
143159 "}\n"
144 "static uint64_t load64_align0(const uint8_t *ptr) {\n"
160 "uint64_t load64_align0(const uint8_t *ptr) {\n"
145161 " uint64_t val;\n"
146162 " memcpy(&val, ptr, sizeof(val));\n", out);
147163 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
148164 fputs(" return val;\n"
149165 "}\n"
150 "static uint64_t load64_align1(const uint16_t *ptr) {\n"
166 "uint64_t load64_align1(const uint16_t *ptr) {\n"
151167 " uint64_t val;\n"
152168 " memcpy(&val, ptr, sizeof(val));\n", out);
153169 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
154170 fputs(" return val;\n"
155171 "}\n"
156 "static uint64_t load64_align2(const uint32_t *ptr) {\n"
172 "uint64_t load64_align2(const uint32_t *ptr) {\n"
157173 " uint64_t val;\n"
158174 " memcpy(&val, ptr, sizeof(val));\n", out);
159175 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
160176 fputs(" return val;\n"
161177 "}\n"
162 "static uint64_t load64_align3(const uint64_t *ptr) {\n"
178 "uint64_t load64_align3(const uint64_t *ptr) {\n"
163179 " uint64_t val;\n"
164180 " memcpy(&val, ptr, sizeof(val));\n", out);
165181 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
......@@ -199,39 +215,39 @@ int main(int argc, char **argv) {
199215 " return i64_ctz(lhs);\n"
200216 "}\n"
201217 "\n"
202 "static void store16_align0(uint8_t *ptr, uint16_t val) {\n", out);
218 "void store16_align0(uint8_t *ptr, uint16_t val) {\n", out);
203219 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
204220 fputs(" memcpy(ptr, &val, sizeof(val));\n"
205221 "}\n"
206 "static void store16_align1(uint16_t *ptr, uint16_t val) {\n", out);
222 "void store16_align1(uint16_t *ptr, uint16_t val) {\n", out);
207223 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
208224 fputs(" memcpy(ptr, &val, sizeof(val));\n"
209225 "}\n"
210 "static void store32_align0(uint8_t *ptr, uint32_t val) {\n", out);
226 "void store32_align0(uint8_t *ptr, uint32_t val) {\n", out);
211227 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
212228 fputs(" memcpy(ptr, &val, sizeof(val));\n"
213229 "}\n"
214 "static void store32_align1(uint16_t *ptr, uint32_t val) {\n", out);
230 "void store32_align1(uint16_t *ptr, uint32_t val) {\n", out);
215231 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
216232 fputs(" memcpy(ptr, &val, sizeof(val));\n"
217233 "}\n"
218 "static void store32_align2(uint32_t *ptr, uint32_t val) {\n", out);
234 "void store32_align2(uint32_t *ptr, uint32_t val) {\n", out);
219235 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
220236 fputs(" memcpy(ptr, &val, sizeof(val));\n"
221237 "}\n"
222 "static void store64_align0(uint8_t *ptr, uint64_t val) {\n", out);
238 "void store64_align0(uint8_t *ptr, uint64_t val) {\n", out);
223239 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
224240 fputs(" memcpy(ptr, &val, sizeof(val));\n"
225241 "}\n"
226 "static void store64_align1(uint16_t *ptr, uint64_t val) {\n", out);
242 "void store64_align1(uint16_t *ptr, uint64_t val) {\n", out);
227243 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
228244 fputs(" memcpy(ptr, &val, sizeof(val));\n"
229245 "}\n"
230 "static void store64_align2(uint32_t *ptr, uint64_t val) {\n", out);
246 "void store64_align2(uint32_t *ptr, uint64_t val) {\n", out);
231247 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
232248 fputs(" memcpy(ptr, &val, sizeof(val));\n"
233249 "}\n"
234 "static void store64_align3(uint64_t *ptr, uint64_t val) {\n", out);
250 "void store64_align3(uint64_t *ptr, uint64_t val) {\n", out);
235251 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
236252 fputs(" memcpy(ptr, &val, sizeof(val));\n"
237253 "}\n"