Skip to content

Commit 4034e63

Browse files
authored
Implement atomic instructions in the interpreter (WebAssembly#67)
Added support for all atomic loads, stores, rmw, and cmpxchg instructions. They currently operate on non-shared memory, since I haven't implemented the `shared` flag yet.
1 parent ca698f9 commit 4034e63

File tree

14 files changed

+943
-0
lines changed

14 files changed

+943
-0
lines changed

interpreter/binary/decode.ml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
(* Decoding stream *)
22

3+
open Values
4+
35
type stream =
46
{
57
name : string;
@@ -200,6 +202,82 @@ let memop s =
200202
let offset = vu32 s in
201203
Int32.to_int align, offset
202204

205+
let atomic_instr s =
206+
let pos = pos s in
207+
match op s with
208+
| 0x10 -> let a, o = memop s in i32_atomic_load a o
209+
| 0x11 -> let a, o = memop s in i64_atomic_load a o
210+
| 0x12 -> let a, o = memop s in i32_atomic_load8_u a o
211+
| 0x13 -> let a, o = memop s in i32_atomic_load16_u a o
212+
| 0x14 -> let a, o = memop s in i64_atomic_load8_u a o
213+
| 0x15 -> let a, o = memop s in i64_atomic_load16_u a o
214+
| 0x16 -> let a, o = memop s in i64_atomic_load32_u a o
215+
| 0x17 -> let a, o = memop s in i32_atomic_store a o
216+
| 0x18 -> let a, o = memop s in i64_atomic_store a o
217+
| 0x19 -> let a, o = memop s in i32_atomic_store8 a o
218+
| 0x1a -> let a, o = memop s in i32_atomic_store16 a o
219+
| 0x1b -> let a, o = memop s in i64_atomic_store8 a o
220+
| 0x1c -> let a, o = memop s in i64_atomic_store16 a o
221+
| 0x1d -> let a, o = memop s in i64_atomic_store32 a o
222+
223+
| 0x1e -> let a, o = memop s in i32_atomic_rmw (I32 I32Op.RmwAdd) a o
224+
| 0x1f -> let a, o = memop s in i64_atomic_rmw (I64 I64Op.RmwAdd) a o
225+
| 0x20 -> let a, o = memop s in i32_atomic_rmw8_u (I32 I32Op.RmwAdd) a o
226+
| 0x21 -> let a, o = memop s in i32_atomic_rmw16_u (I32 I32Op.RmwAdd) a o
227+
| 0x22 -> let a, o = memop s in i64_atomic_rmw8_u (I64 I64Op.RmwAdd) a o
228+
| 0x23 -> let a, o = memop s in i64_atomic_rmw16_u (I64 I64Op.RmwAdd) a o
229+
| 0x24 -> let a, o = memop s in i64_atomic_rmw32_u (I64 I64Op.RmwAdd) a o
230+
231+
| 0x25 -> let a, o = memop s in i32_atomic_rmw (I32 I32Op.RmwSub) a o
232+
| 0x26 -> let a, o = memop s in i64_atomic_rmw (I64 I64Op.RmwSub) a o
233+
| 0x27 -> let a, o = memop s in i32_atomic_rmw8_u (I32 I32Op.RmwSub) a o
234+
| 0x28 -> let a, o = memop s in i32_atomic_rmw16_u (I32 I32Op.RmwSub) a o
235+
| 0x29 -> let a, o = memop s in i64_atomic_rmw8_u (I64 I64Op.RmwSub) a o
236+
| 0x2a -> let a, o = memop s in i64_atomic_rmw16_u (I64 I64Op.RmwSub) a o
237+
| 0x2b -> let a, o = memop s in i64_atomic_rmw32_u (I64 I64Op.RmwSub) a o
238+
239+
| 0x2c -> let a, o = memop s in i32_atomic_rmw (I32 I32Op.RmwAnd) a o
240+
| 0x2d -> let a, o = memop s in i64_atomic_rmw (I64 I64Op.RmwAnd) a o
241+
| 0x2e -> let a, o = memop s in i32_atomic_rmw8_u (I32 I32Op.RmwAnd) a o
242+
| 0x2f -> let a, o = memop s in i32_atomic_rmw16_u (I32 I32Op.RmwAnd) a o
243+
| 0x30 -> let a, o = memop s in i64_atomic_rmw8_u (I64 I64Op.RmwAnd) a o
244+
| 0x31 -> let a, o = memop s in i64_atomic_rmw16_u (I64 I64Op.RmwAnd) a o
245+
| 0x32 -> let a, o = memop s in i64_atomic_rmw32_u (I64 I64Op.RmwAnd) a o
246+
247+
| 0x33 -> let a, o = memop s in i32_atomic_rmw (I32 I32Op.RmwOr) a o
248+
| 0x34 -> let a, o = memop s in i64_atomic_rmw (I64 I64Op.RmwOr) a o
249+
| 0x35 -> let a, o = memop s in i32_atomic_rmw8_u (I32 I32Op.RmwOr) a o
250+
| 0x36 -> let a, o = memop s in i32_atomic_rmw16_u (I32 I32Op.RmwOr) a o
251+
| 0x37 -> let a, o = memop s in i64_atomic_rmw8_u (I64 I64Op.RmwOr) a o
252+
| 0x38 -> let a, o = memop s in i64_atomic_rmw16_u (I64 I64Op.RmwOr) a o
253+
| 0x39 -> let a, o = memop s in i64_atomic_rmw32_u (I64 I64Op.RmwOr) a o
254+
255+
| 0x3a -> let a, o = memop s in i32_atomic_rmw (I32 I32Op.RmwXor) a o
256+
| 0x3b -> let a, o = memop s in i64_atomic_rmw (I64 I64Op.RmwXor) a o
257+
| 0x3c -> let a, o = memop s in i32_atomic_rmw8_u (I32 I32Op.RmwXor) a o
258+
| 0x3d -> let a, o = memop s in i32_atomic_rmw16_u (I32 I32Op.RmwXor) a o
259+
| 0x3e -> let a, o = memop s in i64_atomic_rmw8_u (I64 I64Op.RmwXor) a o
260+
| 0x3f -> let a, o = memop s in i64_atomic_rmw16_u (I64 I64Op.RmwXor) a o
261+
| 0x40 -> let a, o = memop s in i64_atomic_rmw32_u (I64 I64Op.RmwXor) a o
262+
263+
| 0x41 -> let a, o = memop s in i32_atomic_rmw (I32 I32Op.RmwXchg) a o
264+
| 0x42 -> let a, o = memop s in i64_atomic_rmw (I64 I64Op.RmwXchg) a o
265+
| 0x43 -> let a, o = memop s in i32_atomic_rmw8_u (I32 I32Op.RmwXchg) a o
266+
| 0x44 -> let a, o = memop s in i32_atomic_rmw16_u (I32 I32Op.RmwXchg) a o
267+
| 0x45 -> let a, o = memop s in i64_atomic_rmw8_u (I64 I64Op.RmwXchg) a o
268+
| 0x46 -> let a, o = memop s in i64_atomic_rmw16_u (I64 I64Op.RmwXchg) a o
269+
| 0x47 -> let a, o = memop s in i64_atomic_rmw32_u (I64 I64Op.RmwXchg) a o
270+
271+
| 0x48 -> let a, o = memop s in i32_atomic_rmw_cmpxchg a o
272+
| 0x49 -> let a, o = memop s in i64_atomic_rmw_cmpxchg a o
273+
| 0x4a -> let a, o = memop s in i32_atomic_rmw8_u_cmpxchg a o
274+
| 0x4b -> let a, o = memop s in i32_atomic_rmw16_u_cmpxchg a o
275+
| 0x4c -> let a, o = memop s in i64_atomic_rmw8_u_cmpxchg a o
276+
| 0x4d -> let a, o = memop s in i64_atomic_rmw16_u_cmpxchg a o
277+
| 0x4e -> let a, o = memop s in i64_atomic_rmw32_u_cmpxchg a o
278+
279+
| b -> illegal s pos b
280+
203281
let rec instr s =
204282
let pos = pos s in
205283
match op s with
@@ -438,6 +516,8 @@ let rec instr s =
438516
| 0xc3 -> i64_extend16_s
439517
| 0xc4 -> i64_extend32_s
440518

519+
| 0xfe -> atomic_instr s
520+
441521
| b -> illegal s pos b
442522

443523
and instr_block s = List.rev (instr_block' s [])

interpreter/binary/encode.ml

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,154 @@ let encode m =
208208
| Store ({ty = I64Type; sz = Some Mem32; _} as mo) -> op 0x3e; memop mo
209209
| Store {ty = F32Type | F64Type; sz = Some _; _} -> assert false
210210

211+
| AtomicLoad ({ty = I32Type; sz = None; _} as mo) ->
212+
op 0xfe; op 0x10; memop mo
213+
| AtomicLoad ({ty = I64Type; sz = None; _} as mo) ->
214+
op 0xfe; op 0x11; memop mo
215+
| AtomicLoad ({ty = I32Type; sz = Some Mem8; _} as mo) ->
216+
op 0xfe; op 0x12; memop mo
217+
| AtomicLoad ({ty = I32Type; sz = Some Mem16; _} as mo) ->
218+
op 0xfe; op 0x13; memop mo
219+
| AtomicLoad {ty = I32Type; sz = Some Mem32; _} -> assert false
220+
| AtomicLoad ({ty = I64Type; sz = Some Mem8; _} as mo) ->
221+
op 0xfe; op 0x14; memop mo
222+
| AtomicLoad ({ty = I64Type; sz = Some Mem16; _} as mo) ->
223+
op 0xfe; op 0x15; memop mo
224+
| AtomicLoad ({ty = I64Type; sz = Some Mem32; _} as mo) ->
225+
op 0xfe; op 0x16; memop mo
226+
| AtomicLoad {ty = F32Type | F64Type; _} -> assert false
227+
228+
| AtomicStore ({ty = I32Type; sz = None; _} as mo) ->
229+
op 0xfe; op 0x17; memop mo
230+
| AtomicStore ({ty = I64Type; sz = None; _} as mo) ->
231+
op 0xfe; op 0x18; memop mo
232+
| AtomicStore ({ty = I32Type; sz = Some Mem8; _} as mo) ->
233+
op 0xfe; op 0x19; memop mo
234+
| AtomicStore ({ty = I32Type; sz = Some Mem16; _} as mo) ->
235+
op 0xfe; op 0x1a; memop mo
236+
| AtomicStore {ty = I32Type; sz = Some Mem32; _} -> assert false
237+
| AtomicStore ({ty = I64Type; sz = Some Mem8; _} as mo) ->
238+
op 0xfe; op 0x1b; memop mo
239+
| AtomicStore ({ty = I64Type; sz = Some Mem16; _} as mo) ->
240+
op 0xfe; op 0x1c; memop mo
241+
| AtomicStore ({ty = I64Type; sz = Some Mem32; _} as mo) ->
242+
op 0xfe; op 0x1d; memop mo
243+
| AtomicStore {ty = F32Type | F64Type; _} -> assert false
244+
245+
| AtomicRmw (I32 I32Op.RmwAdd, ({ty = I32Type; sz = None; _} as mo)) ->
246+
op 0xfe; op 0x1e; memop mo
247+
| AtomicRmw (I64 I64Op.RmwAdd, ({ty = I64Type; sz = None; _} as mo)) ->
248+
op 0xfe; op 0x1f; memop mo
249+
| AtomicRmw (I32 I32Op.RmwAdd, ({ty = I32Type; sz = Some Mem8; _} as mo)) ->
250+
op 0xfe; op 0x20; memop mo
251+
| AtomicRmw (I32 I32Op.RmwAdd, ({ty = I32Type; sz = Some Mem16; _} as mo)) ->
252+
op 0xfe; op 0x21; memop mo
253+
| AtomicRmw (I64 I64Op.RmwAdd, ({ty = I64Type; sz = Some Mem8; _} as mo)) ->
254+
op 0xfe; op 0x22; memop mo
255+
| AtomicRmw (I64 I64Op.RmwAdd, ({ty = I64Type; sz = Some Mem16; _} as mo)) ->
256+
op 0xfe; op 0x23; memop mo
257+
| AtomicRmw (I64 I64Op.RmwAdd, ({ty = I64Type; sz = Some Mem32; _} as mo)) ->
258+
op 0xfe; op 0x24; memop mo
259+
260+
| AtomicRmw (I32 I32Op.RmwSub, ({ty = I32Type; sz = None; _} as mo)) ->
261+
op 0xfe; op 0x25; memop mo
262+
| AtomicRmw (I64 I64Op.RmwSub, ({ty = I64Type; sz = None; _} as mo)) ->
263+
op 0xfe; op 0x26; memop mo
264+
| AtomicRmw (I32 I32Op.RmwSub, ({ty = I32Type; sz = Some Mem8; _} as mo)) ->
265+
op 0xfe; op 0x27; memop mo
266+
| AtomicRmw (I32 I32Op.RmwSub, ({ty = I32Type; sz = Some Mem16; _} as mo)) ->
267+
op 0xfe; op 0x28; memop mo
268+
| AtomicRmw (I64 I64Op.RmwSub, ({ty = I64Type; sz = Some Mem8; _} as mo)) ->
269+
op 0xfe; op 0x29; memop mo
270+
| AtomicRmw (I64 I64Op.RmwSub, ({ty = I64Type; sz = Some Mem16; _} as mo)) ->
271+
op 0xfe; op 0x2a; memop mo
272+
| AtomicRmw (I64 I64Op.RmwSub, ({ty = I64Type; sz = Some Mem32; _} as mo)) ->
273+
op 0xfe; op 0x2b; memop mo
274+
275+
| AtomicRmw (I32 I32Op.RmwAnd, ({ty = I32Type; sz = None; _} as mo)) ->
276+
op 0xfe; op 0x2c; memop mo
277+
| AtomicRmw (I64 I64Op.RmwAnd, ({ty = I64Type; sz = None; _} as mo)) ->
278+
op 0xfe; op 0x2d; memop mo
279+
| AtomicRmw (I32 I32Op.RmwAnd, ({ty = I32Type; sz = Some Mem8; _} as mo)) ->
280+
op 0xfe; op 0x2e; memop mo
281+
| AtomicRmw (I32 I32Op.RmwAnd, ({ty = I32Type; sz = Some Mem16; _} as mo)) ->
282+
op 0xfe; op 0x2f; memop mo
283+
| AtomicRmw (I64 I64Op.RmwAnd, ({ty = I64Type; sz = Some Mem8; _} as mo)) ->
284+
op 0xfe; op 0x30; memop mo
285+
| AtomicRmw (I64 I64Op.RmwAnd, ({ty = I64Type; sz = Some Mem16; _} as mo)) ->
286+
op 0xfe; op 0x31; memop mo
287+
| AtomicRmw (I64 I64Op.RmwAnd, ({ty = I64Type; sz = Some Mem32; _} as mo)) ->
288+
op 0xfe; op 0x32; memop mo
289+
290+
| AtomicRmw (I32 I32Op.RmwOr, ({ty = I32Type; sz = None; _} as mo)) ->
291+
op 0xfe; op 0x33; memop mo
292+
| AtomicRmw (I64 I64Op.RmwOr, ({ty = I64Type; sz = None; _} as mo)) ->
293+
op 0xfe; op 0x34; memop mo
294+
| AtomicRmw (I32 I32Op.RmwOr, ({ty = I32Type; sz = Some Mem8; _} as mo)) ->
295+
op 0xfe; op 0x35; memop mo
296+
| AtomicRmw (I32 I32Op.RmwOr, ({ty = I32Type; sz = Some Mem16; _} as mo)) ->
297+
op 0xfe; op 0x36; memop mo
298+
| AtomicRmw (I64 I64Op.RmwOr, ({ty = I64Type; sz = Some Mem8; _} as mo)) ->
299+
op 0xfe; op 0x37; memop mo
300+
| AtomicRmw (I64 I64Op.RmwOr, ({ty = I64Type; sz = Some Mem16; _} as mo)) ->
301+
op 0xfe; op 0x38; memop mo
302+
| AtomicRmw (I64 I64Op.RmwOr, ({ty = I64Type; sz = Some Mem32; _} as mo)) ->
303+
op 0xfe; op 0x39; memop mo
304+
305+
| AtomicRmw (I32 I32Op.RmwXor, ({ty = I32Type; sz = None; _} as mo)) ->
306+
op 0xfe; op 0x3a; memop mo
307+
| AtomicRmw (I64 I64Op.RmwXor, ({ty = I64Type; sz = None; _} as mo)) ->
308+
op 0xfe; op 0x3b; memop mo
309+
| AtomicRmw (I32 I32Op.RmwXor, ({ty = I32Type; sz = Some Mem8; _} as mo)) ->
310+
op 0xfe; op 0x3c; memop mo
311+
| AtomicRmw (I32 I32Op.RmwXor, ({ty = I32Type; sz = Some Mem16; _} as mo)) ->
312+
op 0xfe; op 0x3d; memop mo
313+
| AtomicRmw (I64 I64Op.RmwXor, ({ty = I64Type; sz = Some Mem8; _} as mo)) ->
314+
op 0xfe; op 0x3e; memop mo
315+
| AtomicRmw (I64 I64Op.RmwXor, ({ty = I64Type; sz = Some Mem16; _} as mo)) ->
316+
op 0xfe; op 0x3f; memop mo
317+
| AtomicRmw (I64 I64Op.RmwXor, ({ty = I64Type; sz = Some Mem32; _} as mo)) ->
318+
op 0xfe; op 0x40; memop mo
319+
320+
| AtomicRmw (I32 I32Op.RmwXchg, ({ty = I32Type; sz = None; _} as mo)) ->
321+
op 0xfe; op 0x41; memop mo
322+
| AtomicRmw (I64 I64Op.RmwXchg, ({ty = I64Type; sz = None; _} as mo)) ->
323+
op 0xfe; op 0x42; memop mo
324+
| AtomicRmw (I32 I32Op.RmwXchg, ({ty = I32Type; sz = Some Mem8; _} as mo)) ->
325+
op 0xfe; op 0x43; memop mo
326+
| AtomicRmw (I32 I32Op.RmwXchg, ({ty = I32Type; sz = Some Mem16; _} as mo)) ->
327+
op 0xfe; op 0x44; memop mo
328+
| AtomicRmw (I64 I64Op.RmwXchg, ({ty = I64Type; sz = Some Mem8; _} as mo)) ->
329+
op 0xfe; op 0x45; memop mo
330+
| AtomicRmw (I64 I64Op.RmwXchg, ({ty = I64Type; sz = Some Mem16; _} as mo)) ->
331+
op 0xfe; op 0x46; memop mo
332+
| AtomicRmw (I64 I64Op.RmwXchg, ({ty = I64Type; sz = Some Mem32; _} as mo)) ->
333+
op 0xfe; op 0x47; memop mo
334+
335+
| AtomicRmw (I32 _, {ty = I64Type; _}) -> assert false
336+
| AtomicRmw (I64 _, {ty = I32Type; _}) -> assert false
337+
| AtomicRmw ((F32 _ | F64 _), _) -> assert false
338+
| AtomicRmw (_, {ty = I32Type; sz = Some Mem32; _}) -> assert false
339+
| AtomicRmw (_, {ty = F32Type | F64Type; _}) -> assert false
340+
341+
| AtomicRmwCmpXchg ({ty = I32Type; sz = None; _} as mo) ->
342+
op 0xfe; op 0x48; memop mo
343+
| AtomicRmwCmpXchg ({ty = I64Type; sz = None; _} as mo) ->
344+
op 0xfe; op 0x49; memop mo
345+
| AtomicRmwCmpXchg ({ty = I32Type; sz = Some Mem8; _} as mo) ->
346+
op 0xfe; op 0x4a; memop mo
347+
| AtomicRmwCmpXchg ({ty = I32Type; sz = Some Mem16; _} as mo) ->
348+
op 0xfe; op 0x4b; memop mo
349+
| AtomicRmwCmpXchg {ty = I32Type; sz = Some Mem32; _} -> assert false
350+
| AtomicRmwCmpXchg ({ty = I64Type; sz = Some Mem8; _} as mo) ->
351+
op 0xfe; op 0x4c; memop mo
352+
| AtomicRmwCmpXchg ({ty = I64Type; sz = Some Mem16; _} as mo) ->
353+
op 0xfe; op 0x4d; memop mo
354+
| AtomicRmwCmpXchg ({ty = I64Type; sz = Some Mem32; _} as mo) ->
355+
op 0xfe; op 0x4e; memop mo
356+
| AtomicRmwCmpXchg {ty = F32Type | F64Type; _} -> assert false
357+
358+
211359
| CurrentMemory -> op 0x3f; u8 0x00
212360
| GrowMemory -> op 0x40; u8 0x00
213361

interpreter/exec/eval.ml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ let take n (vs : 'a stack) at =
100100
let drop n (vs : 'a stack) at =
101101
try Lib.List.drop n vs with Failure _ -> Crash.error at "stack underflow"
102102

103+
let check_align addr ty sz at =
104+
if not (Memory.is_aligned addr ty sz) then
105+
Trap.error at "unaligned atomic memory access"
106+
103107

104108
(* Evaluation *)
105109

@@ -214,6 +218,64 @@ let rec step (c : config) : config =
214218
vs', []
215219
with exn -> vs', [Trapped (memory_error e.at exn) @@ e.at]);
216220

221+
| AtomicLoad {offset; ty; sz; _}, I32 i :: vs' ->
222+
let mem = memory frame.inst (0l @@ e.at) in
223+
let addr = I64_convert.extend_u_i32 i in
224+
(try
225+
check_align addr ty sz e.at;
226+
let v =
227+
match sz with
228+
| None -> Memory.load_value mem addr offset ty
229+
| Some sz -> Memory.load_packed sz Memory.ZX mem addr offset ty
230+
in v :: vs', []
231+
with exn -> vs', [Trapped (memory_error e.at exn) @@ e.at])
232+
233+
| AtomicStore {offset; ty; sz; _}, v :: I32 i :: vs' ->
234+
let mem = memory frame.inst (0l @@ e.at) in
235+
let addr = I64_convert.extend_u_i32 i in
236+
(try
237+
check_align addr ty sz e.at;
238+
(match sz with
239+
| None -> Memory.store_value mem addr offset v
240+
| Some sz -> Memory.store_packed sz mem addr offset v
241+
);
242+
vs', []
243+
with exn -> vs', [Trapped (memory_error e.at exn) @@ e.at]);
244+
245+
| AtomicRmw (rmwop, {offset; ty; sz; _}), v :: I32 i :: vs' ->
246+
let mem = memory frame.inst (0l @@ e.at) in
247+
let addr = I64_convert.extend_u_i32 i in
248+
(try
249+
check_align addr ty sz e.at;
250+
let v1 =
251+
match sz with
252+
| None -> Memory.load_value mem addr offset ty
253+
| Some sz -> Memory.load_packed sz Memory.ZX mem addr offset ty
254+
in let v2 = Eval_numeric.eval_rmwop rmwop v1 v
255+
in (match sz with
256+
| None -> Memory.store_value mem addr offset v2
257+
| Some sz -> Memory.store_packed sz mem addr offset v2
258+
);
259+
v1 :: vs', []
260+
with exn -> vs', [Trapped (memory_error e.at exn) @@ e.at])
261+
262+
| AtomicRmwCmpXchg {offset; ty; sz; _}, vn :: ve :: I32 i :: vs' ->
263+
let mem = memory frame.inst (0l @@ e.at) in
264+
let addr = I64_convert.extend_u_i32 i in
265+
(try
266+
check_align addr ty sz e.at;
267+
let v1 =
268+
match sz with
269+
| None -> Memory.load_value mem addr offset ty
270+
| Some sz -> Memory.load_packed sz Memory.ZX mem addr offset ty
271+
in (if v1 = ve then
272+
match sz with
273+
| None -> Memory.store_value mem addr offset vn
274+
| Some sz -> Memory.store_packed sz mem addr offset vn
275+
);
276+
v1 :: vs', []
277+
with exn -> vs', [Trapped (memory_error e.at exn) @@ e.at]);
278+
217279
| CurrentMemory, vs ->
218280
let mem = memory frame.inst (0l @@ e.at) in
219281
I32 (Memory.size mem) :: vs, []

interpreter/exec/eval_numeric.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ struct
6666
| GeS -> IXX.ge_s
6767
| GeU -> IXX.ge_u
6868
in fun v1 v2 -> f (of_value 1 v1) (of_value 2 v2)
69+
70+
let rmwop op =
71+
let f = match op with
72+
| RmwAdd -> IXX.add
73+
| RmwSub -> IXX.sub
74+
| RmwAnd -> IXX.and_
75+
| RmwOr -> IXX.or_
76+
| RmwXor -> IXX.xor
77+
| RmwXchg -> fun x y -> y (* Return the "new" value, y *)
78+
in fun v1 v2 -> to_value (f (of_value 1 v1) (of_value 2 v2))
6979
end
7080

7181
module I32Op = IntOp (I32) (Values.I32Value)
@@ -114,6 +124,8 @@ struct
114124
| Gt -> FXX.gt
115125
| Ge -> FXX.ge
116126
in fun v1 v2 -> f (of_value 1 v1) (of_value 2 v2)
127+
128+
let rmwop op = assert false
117129
end
118130

119131
module F32Op = FloatOp (F32) (Values.F32Value)
@@ -198,3 +210,4 @@ let eval_binop = op I32Op.binop I64Op.binop F32Op.binop F64Op.binop
198210
let eval_testop = op I32Op.testop I64Op.testop F32Op.testop F64Op.testop
199211
let eval_relop = op I32Op.relop I64Op.relop F32Op.relop F64Op.relop
200212
let eval_cvtop = op I32CvtOp.cvtop I64CvtOp.cvtop F32CvtOp.cvtop F64CvtOp.cvtop
213+
let eval_rmwop = op I32Op.rmwop I64Op.rmwop F32Op.rmwop F64Op.rmwop

interpreter/exec/eval_numeric.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ val eval_binop : Ast.binop -> value -> value -> value
77
val eval_testop : Ast.testop -> value -> bool
88
val eval_relop : Ast.relop -> value -> value -> bool
99
val eval_cvtop : Ast.cvtop -> value -> value
10+
val eval_rmwop : Ast.rmwop -> value -> value -> value

interpreter/runtime/memory.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ let mem_size = function
2727
| Mem16 -> 2
2828
| Mem32 -> 4
2929

30+
let mem_size_opt t sz =
31+
match sz with
32+
| None -> Types.size t
33+
| Some s -> mem_size s
34+
35+
let is_aligned a t sz =
36+
let align = mem_size_opt t sz in
37+
let mask = align - 1 in
38+
Int64.(logand a (of_int mask)) = 0L
39+
3040
let within_limits n = function
3141
| None -> true
3242
| Some max -> I32.le_u n max

interpreter/runtime/memory.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ exception OutOfMemory
1919

2020
val page_size : int64
2121
val mem_size : mem_size -> int
22+
val is_aligned : address -> value_type -> mem_size option -> bool
2223

2324
val alloc : memory_type -> memory (* raises SizeOverflow, OutOfMemory *)
2425
val type_of : memory -> memory_type

0 commit comments

Comments
 (0)