-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwasi.gr
431 lines (408 loc) · 11 KB
/
wasi.gr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
/* grainc-flags --no-gc */
// WASI Polyfill file
import WasmI32 from "runtime/unsafe/wasmi32"
import WasmI64 from "runtime/unsafe/wasmi64"
import foreign wasm log_utf8: (WasmI64, WasmI64) -> Void as log from "env"
import foreign wasm random_seed: WasmI64 -> Void as randomSeed from "env"
import foreign wasm read_register: (
WasmI64,
WasmI64,
) -> Void as readRegister from "env"
import foreign wasm register_len: WasmI64 -> WasmI64 as registerLen from "env"
// clocks
export let _CLOCK_REALTIME = 0n
export let _CLOCK_MONOTONIC = 1n
export let _CLOCK_PROCESS_CPUTIME = 2n
export let _CLOCK_THREAD_CPUTIME = 3n
// time
export let _TIME_SET_ATIM = 1n
export let _TIME_SET_ATIM_NOW = 2n
export let _TIME_SET_MTIM = 4n
export let _TIME_SET_MTIM_NOW = 8n
// lookup flags
export let _LOOKUP_FLAG_SYMLINK_FOLLOW = 1n
// open flags
export let _OPEN_FLAG_CREAT = 1n
export let _OPEN_FLAG_DIRECTORY = 2n
export let _OPEN_FLAG_EXCL = 4n
export let _OPEN_FLAG_TRUNC = 8n
// fdflags
export let _FDFLAG_APPEND = 1n
export let _FDFLAG_DSYNC = 2n
export let _FDFLAG_NONBLOCK = 4n
export let _FDFLAG_RSYNC = 8n
export let _FDFLAG_SYNC = 16n
// whence
export let _WHENCE_SET = 0n
export let _WHENCE_CUR = 1n
export let _WHENCE_END = 2n
// error codes
export let _ESUCCESS = 0n
export let _ETOOBIG = 1n
export let _EACCES = 2n
export let _EADDRINUSE = 3n
export let _EADDRNOTAVAIL = 4n
export let _EAFNOSUPPORT = 5n
export let _EAGAIN = 6n
export let _EALREADY = 7n
export let _EBADF = 8n
export let _EBADMSG = 9n
export let _EBUSY = 10n
export let _ECANCELED = 11n
export let _ECHILD = 12n
export let _ECONNABORTED = 13n
export let _ECONNREFUSED = 14n
export let _ECONNRESET = 15n
export let _EDEADLK = 16n
export let _EDESTADDRREQ = 17n
export let _EDOM = 18n
export let _EDQUOT = 19n
export let _EEXIST = 20n
export let _EFAULT = 21n
export let _EFBIG = 22n
export let _EHOSTUNREACH = 23n
export let _EIDRM = 24n
export let _EILSEQ = 25n
export let _EINPROGRESS = 26n
export let _EINTR = 27n
export let _EINVAL = 28n
export let _EIO = 29n
export let _EISCONN = 30n
export let _EISDIR = 31n
export let _ELOOP = 32n
export let _EMFILE = 33n
export let _EMLINK = 34n
export let _EMSGSIZE = 35n
export let _EMULTIHOP = 36n
export let _ENAMETOOLONG = 37n
export let _ENETDOWN = 38n
export let _ENETRESET = 39n
export let _ENETUNREACH = 40n
export let _ENFILE = 41n
export let _ENOBUFS = 42n
export let _ENODEV = 43n
export let _ENOENT = 44n
export let _ENOEXEC = 45n
export let _ENOLCK = 46n
export let _ENOLINK = 47n
export let _ENOMEM = 48n
export let _ENOMSG = 49n
export let _ENOPROTOOPT = 50n
export let _ENOSPC = 51n
export let _ENOSYS = 52n
export let _ENOTCONN = 53n
export let _ENOTDIR = 54n
export let _ENOTEMPTY = 55n
export let _ENOTRECOVERABLE = 56n
export let _ENOTSOCK = 57n
export let _ENOTSUP = 58n
export let _ENOTTY = 59n
export let _ENXIO = 60n
export let _EOVERFLOW = 61n
export let _EOWNERDEAD = 62n
export let _EPERM = 63n
export let _EPIPE = 64n
export let _EPROTO = 65n
export let _EPROTONOSUPPORT = 66n
export let _EPROTOTYPE = 67n
export let _ERANGE = 68n
export let _EROFS = 69n
export let _ESPIPE = 70n
export let _ESRCH = 71n
export let _ESTALE = 72n
export let _ETIMEDOUT = 73n
export let _ETXTBSY = 74n
export let _EXDEV = 75n
export let _ENOTCAPABLE = 76n
export let fd_write: (WasmI32, WasmI32, WasmI32, WasmI32) -> WasmI32 =
(
fd,
iovs,
iovs_len,
nwritten,
) => {
if (WasmI32.eqz(fd)) {
let mut written = 0n
let mut iovs_offset = 0n
for (let mut i = 0n; WasmI32.ltU(i, iovs_len); i = WasmI32.add(i, 1n)) {
let iovs = WasmI32.add(iovs, iovs_offset)
let ptr = WasmI32.load(iovs, 0n)
let size = WasmI32.load(iovs, 4n)
log(WasmI64.extendI32U(size), WasmI64.extendI32U(ptr))
written = WasmI32.add(written, size)
iovs_offset = WasmI32.add(iovs_offset, 8n)
}
WasmI32.store(nwritten, written, 0n)
0n
} else {
_ENOTCAPABLE
}
}
let mut seedSet = false
// scratch buffer; overwritten by below operations
let buf = "fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
// ^~~~~~~~^~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// counter result buffer for random seed
// https://arxiv.org/pdf/2004.06278v3.pdf
let squares = (ctr: WasmI64, key: WasmI64) => {
let mut x = WasmI64.mul(ctr, key)
let mut y = x
let mut z = WasmI64.add(y, key)
// round 1
x = WasmI64.add(WasmI64.mul(x, x), y)
x = WasmI64.or(WasmI64.shrU(x, 32N), WasmI64.shl(x, 32N))
// round 2
x = WasmI64.add(WasmI64.mul(x, x), z)
x = WasmI64.or(WasmI64.shrU(x, 32N), WasmI64.shl(x, 32N))
// round 3
x = WasmI64.add(WasmI64.mul(x, x), y)
x = WasmI64.or(WasmI64.shrU(x, 32N), WasmI64.shl(x, 32N))
WasmI32.wrapI64(WasmI64.shrU(WasmI64.add(WasmI64.mul(x, x), z), 32N))
}
let initSeed = () => {
if (seedSet) {
0n
} else {
randomSeed(0N)
let len = registerLen(0N)
if (WasmI64.gtU(len, 64N)) {
// we can't partially read in the register, so choke if the seed is > 4 bytes
_EOVERFLOW
} else {
// read 0-4 bytes into buf
readRegister(
0N,
WasmI64.extendI32U(WasmI32.add(WasmI32.fromGrain(buf), 24n))
)
// Our PRNG uses an 8-byte seed, so if the seed is greater than 8 bytes
// we XOR successive windows to make it so that all bytes of the seed
// impact the PRNG.
if (WasmI64.gtU(len, 8N)) {
// nWindows := ceil(len / 8)
let nWindows = WasmI32.wrapI64(WasmI64.divU(WasmI64.add(len, 7N), 8N))
let mut idx = 1n
let bufPtr = WasmI32.fromGrain(buf)
for (
let mut idx = 1n;
WasmI32.leU(idx, nWindows);
idx = WasmI32.add(idx, 1n)
) {
WasmI64.store(
bufPtr,
WasmI64.xor(
WasmI64.load(bufPtr, 8n),
WasmI64.load(WasmI32.add(bufPtr, WasmI32.mul(idx, 8n)), 8n)
),
24n
)
}
}
// store counter
WasmI64.store(WasmI32.fromGrain(buf), 0N, 8n)
// sometimes, we can end up with a seed which will produce zeros for the first
// few iterations. to prevent this, we churn until we generate a MSB of 1
while (
WasmI32.gtU(
WasmI32.clz(
squares(
WasmI64.load(WasmI32.fromGrain(buf), 8n),
WasmI64.load(WasmI32.fromGrain(buf), 24n)
)
),
0n
)
) {
// MSB is zero. Increment counter
WasmI64.store(
WasmI32.fromGrain(buf),
WasmI64.add(WasmI64.load(WasmI32.fromGrain(buf), 8n), 1N),
8n
)
}
seedSet = true
0n
}
}
}
let nextRand = () => {
// PRECONDITION: Seed is set
let ctrVal = WasmI64.load(WasmI32.fromGrain(buf), 8n)
let seedVal = WasmI64.load(WasmI32.fromGrain(buf), 24n)
let squares = squares(ctrVal, seedVal)
WasmI32.store(WasmI32.fromGrain(buf), squares, 16n)
WasmI64.store(WasmI32.fromGrain(buf), WasmI64.add(ctrVal, 1N), 8n)
void
}
primitive (&&): (Bool, Bool) -> Bool = "@and"
export let random_get = (inbuf: WasmI32, bufLen: WasmI32) => {
let res = initSeed()
if (WasmI32.eqz(res)) {
// seed is valid. generate the random data
let mut remaining = bufLen
let mut i = 0n
while (WasmI32.gtU(remaining, 0n)) {
nextRand()
let mut nextRemaining = 2n
let nextI = 0n
while (WasmI32.gtU(remaining, 0n) && WasmI32.gtU(nextRemaining, 0n)) {
WasmI32.store8(
WasmI32.add(inbuf, i),
WasmI32.load8U(WasmI32.add(WasmI32.fromGrain(buf), nextI), 16n),
0n
)
i = WasmI32.add(i, 1n)
nextRemaining = WasmI32.sub(nextRemaining, 1n)
remaining = WasmI32.sub(remaining, 1n)
}
}
_ESUCCESS
} else {
res
}
}
// stubs
// env
export let args_get = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let args_sizes_get = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let environ_get = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let environ_sizes_get = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
// proc
export let proc_exit = (_: WasmI32) => void
export let proc_raise = (_: WasmI32) => _ENOTCAPABLE
export let sched_yield = () => _ENOTCAPABLE
// random
// random_get above
// time
export let clock_time_get = (_: WasmI32, _: WasmI64, _: WasmI32) => _ENOTCAPABLE
// file
export let path_open =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI64,
_: WasmI64,
_: WasmI32,
_: WasmI32,
) =>
_ENOTCAPABLE
export let fd_read = (_: WasmI32, _: WasmI32, _: WasmI32, _: WasmI32) =>
_ENOTCAPABLE
export let fd_pread =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI64,
_: WasmI32,
) =>
_ENOTCAPABLE
// fd_write above
export let fd_pwrite =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI64,
_: WasmI32,
) =>
_ENOTCAPABLE
export let fd_allocate = (_: WasmI32, _: WasmI64, _: WasmI64) => _ENOTCAPABLE
export let fd_close = (_: WasmI32) => _ENOTCAPABLE
export let fd_datasync = (_: WasmI32) => _ENOTCAPABLE
export let fd_sync = (_: WasmI32) => _ENOTCAPABLE
export let fd_fdstat_get = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let fd_fdstat_set_flags = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let fd_fdstat_set_rights = (_: WasmI32, _: WasmI64, _: WasmI64) =>
_ENOTCAPABLE
export let fd_filestat_get = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let fd_filestat_set_size = (_: WasmI32, _: WasmI64) => _ENOTCAPABLE
export let fd_filestat_set_times =
(
_: WasmI32,
_: WasmI64,
_: WasmI64,
_: WasmI32,
) =>
_ENOTCAPABLE
export let fd_readdir =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI64,
_: WasmI32,
) =>
_ENOTCAPABLE
export let fd_renumber = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let fd_seek = (_: WasmI32, _: WasmI64, _: WasmI32, _: WasmI32) =>
_ENOTCAPABLE
export let fd_tell = (_: WasmI32, _: WasmI32) => _ENOTCAPABLE
export let path_create_directory = (_: WasmI32, _: WasmI32, _: WasmI32) =>
_ENOTCAPABLE
export let path_filestat_get =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
) =>
_ENOTCAPABLE
export let path_filestat_set_times =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI64,
_: WasmI64,
_: WasmI32,
) =>
_ENOTCAPABLE
export let path_link =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
) =>
_ENOTCAPABLE
export let path_symlink =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
) =>
_ENOTCAPABLE
export let path_unlink_file = (_: WasmI32, _: WasmI32, _: WasmI32) =>
_ENOTCAPABLE
export let path_readlink =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
) =>
_ENOTCAPABLE
export let path_remove_directory = (_: WasmI32, _: WasmI32, _: WasmI32) =>
_ENOTCAPABLE
export let path_rename =
(
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
_: WasmI32,
) =>
_ENOTCAPABLE