authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-15 18:33:31+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-26 22:00:09+02:00
log5cb45b68557e32724cb6a10ead8123a588c5000f
tree749741a1630707297c86a128e14f63e571f18b09
parent6a364b4a5e71b971b753d2b62c7708ae1e76d707
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

wasm2c: Add big endian support.

I took a slightly unconventional approach to detecting endianness here. We have no compiler/platform-specific preprocessor checks in the stage1 C code today, and I think that's a property worth maintaining.

2 files changed, 86 insertions(+), 60 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+21-19
......@@ -73,6 +73,8 @@ 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) {
7779 if (argc != 3) {
7880 fprintf(stderr, "usage: %s in.wasm.zst out.c\n", argv[0]);
......@@ -80,7 +82,7 @@ int main(int argc, char **argv) {
8082 }
8183
8284 const char *mod = "wasm";
83 bool is_big_endian = false; // TODO
85 bool is_big_endian = *(uint8_t *)&big_endian;
8486
8587 struct InputStream in;
8688 InputStream_open(&in, argv[1]);
......@@ -111,55 +113,55 @@ int main(int argc, char **argv) {
111113 " (uint64_t)i32_byteswap(src >> 32) << 0;\n"
112114 "}\n"
113115 "\n", out);
114 fputs("static uint16_t load16_align0(const uint8_t *ptr) {\n"
116 fputs("uint16_t load16_align0(const uint8_t *ptr) {\n"
115117 " uint16_t val;\n"
116118 " memcpy(&val, ptr, sizeof(val));\n", out);
117119 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
118120 fputs(" return val;\n"
119121 "}\n"
120 "static uint16_t load16_align1(const uint16_t *ptr) {\n"
122 "uint16_t load16_align1(const uint16_t *ptr) {\n"
121123 " uint16_t val;\n"
122124 " memcpy(&val, ptr, sizeof(val));\n", out);
123125 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
124126 fputs(" return val;\n"
125127 "}\n"
126 "static uint32_t load32_align0(const uint8_t *ptr) {\n"
128 "uint32_t load32_align0(const uint8_t *ptr) {\n"
127129 " uint32_t val;\n"
128130 " memcpy(&val, ptr, sizeof(val));\n", out);
129131 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
130132 fputs(" return val;\n"
131133 "}\n"
132 "static uint32_t load32_align1(const uint16_t *ptr) {\n"
134 "uint32_t load32_align1(const uint16_t *ptr) {\n"
133135 " uint32_t val;\n"
134136 " memcpy(&val, ptr, sizeof(val));\n", out);
135137 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
136138 fputs(" return val;\n"
137139 "}\n"
138 "static uint32_t load32_align2(const uint32_t *ptr) {\n"
140 "uint32_t load32_align2(const uint32_t *ptr) {\n"
139141 " uint32_t val;\n"
140142 " memcpy(&val, ptr, sizeof(val));\n", out);
141143 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
142144 fputs(" return val;\n"
143145 "}\n"
144 "static uint64_t load64_align0(const uint8_t *ptr) {\n"
146 "uint64_t load64_align0(const uint8_t *ptr) {\n"
145147 " uint64_t val;\n"
146148 " memcpy(&val, ptr, sizeof(val));\n", out);
147149 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
148150 fputs(" return val;\n"
149151 "}\n"
150 "static uint64_t load64_align1(const uint16_t *ptr) {\n"
152 "uint64_t load64_align1(const uint16_t *ptr) {\n"
151153 " uint64_t val;\n"
152154 " memcpy(&val, ptr, sizeof(val));\n", out);
153155 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
154156 fputs(" return val;\n"
155157 "}\n"
156 "static uint64_t load64_align2(const uint32_t *ptr) {\n"
158 "uint64_t load64_align2(const uint32_t *ptr) {\n"
157159 " uint64_t val;\n"
158160 " memcpy(&val, ptr, sizeof(val));\n", out);
159161 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
160162 fputs(" return val;\n"
161163 "}\n"
162 "static uint64_t load64_align3(const uint64_t *ptr) {\n"
164 "uint64_t load64_align3(const uint64_t *ptr) {\n"
163165 " uint64_t val;\n"
164166 " memcpy(&val, ptr, sizeof(val));\n", out);
165167 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
......@@ -199,39 +201,39 @@ int main(int argc, char **argv) {
199201 " return i64_ctz(lhs);\n"
200202 "}\n"
201203 "\n"
202 "static void store16_align0(uint8_t *ptr, uint16_t val) {\n", out);
204 "void store16_align0(uint8_t *ptr, uint16_t val) {\n", out);
203205 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
204206 fputs(" memcpy(ptr, &val, sizeof(val));\n"
205207 "}\n"
206 "static void store16_align1(uint16_t *ptr, uint16_t val) {\n", out);
208 "void store16_align1(uint16_t *ptr, uint16_t val) {\n", out);
207209 if (is_big_endian) fputs(" val = i16_byteswap(val);", out);
208210 fputs(" memcpy(ptr, &val, sizeof(val));\n"
209211 "}\n"
210 "static void store32_align0(uint8_t *ptr, uint32_t val) {\n", out);
212 "void store32_align0(uint8_t *ptr, uint32_t val) {\n", out);
211213 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
212214 fputs(" memcpy(ptr, &val, sizeof(val));\n"
213215 "}\n"
214 "static void store32_align1(uint16_t *ptr, uint32_t val) {\n", out);
216 "void store32_align1(uint16_t *ptr, uint32_t val) {\n", out);
215217 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
216218 fputs(" memcpy(ptr, &val, sizeof(val));\n"
217219 "}\n"
218 "static void store32_align2(uint32_t *ptr, uint32_t val) {\n", out);
220 "void store32_align2(uint32_t *ptr, uint32_t val) {\n", out);
219221 if (is_big_endian) fputs(" val = i32_byteswap(val);", out);
220222 fputs(" memcpy(ptr, &val, sizeof(val));\n"
221223 "}\n"
222 "static void store64_align0(uint8_t *ptr, uint64_t val) {\n", out);
224 "void store64_align0(uint8_t *ptr, uint64_t val) {\n", out);
223225 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
224226 fputs(" memcpy(ptr, &val, sizeof(val));\n"
225227 "}\n"
226 "static void store64_align1(uint16_t *ptr, uint64_t val) {\n", out);
228 "void store64_align1(uint16_t *ptr, uint64_t val) {\n", out);
227229 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
228230 fputs(" memcpy(ptr, &val, sizeof(val));\n"
229231 "}\n"
230 "static void store64_align2(uint32_t *ptr, uint64_t val) {\n", out);
232 "void store64_align2(uint32_t *ptr, uint64_t val) {\n", out);
231233 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
232234 fputs(" memcpy(ptr, &val, sizeof(val));\n"
233235 "}\n"
234 "static void store64_align3(uint64_t *ptr, uint64_t val) {\n", out);
236 "void store64_align3(uint64_t *ptr, uint64_t val) {\n", out);
235237 if (is_big_endian) fputs(" val = i64_byteswap(val);", out);
236238 fputs(" memcpy(ptr, &val, sizeof(val));\n"
237239 "}\n"