Skip to content

Commit 3d2937a

Browse files
committed
Merge pull request #55 from WebAssembly/update-load-store
Update load/store to match design changes
2 parents 5ac7a32 + 6e50795 commit 3d2937a

File tree

9 files changed

+101
-134
lines changed

9 files changed

+101
-134
lines changed

ml-proto/README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ type expr =
127127
| SetLocal of var * expr (* write local variable
128128
| LoadGlobal of var (* read global variable
129129
| StoreGlobal of var * expr (* write global variable
130-
| Load of memop * expr (* read memory address
131-
| Store of memop * expr * expr (* write memory address
130+
| Load of loadop * expr (* read memory address
131+
| Store of storeop * expr * expr (* write memory address
132132
| Const of value (* constant
133133
| Unary of unop * expr (* unary arithmetic operator
134134
| Binary of binop * expr * expr (* binary arithmetic operator
@@ -147,7 +147,6 @@ The S-expression syntax is defined in `parser.mly`, the opcodes in `lexer.mll`.
147147

148148
```
149149
type: i32 | i64 | f32 | f64
150-
memtype: <type> | i8 | i16
151150
152151
value: <int> | <float>
153152
var: <int> | $<name>
@@ -157,7 +156,6 @@ binop: add | sub | mul | ...
157156
relop: eq | neq | lt | ...
158157
sign: s|u
159158
align: 1|2|4|8|...
160-
memop: (<sign>.)?(<align>.)?
161159
cvtop: trunc_s | trunc_u | extend_s | extend_u | ...
162160
163161
expr:
@@ -177,8 +175,8 @@ expr:
177175
( set_local <var> <expr> )
178176
( load_global <var> )
179177
( store_global <var> <expr> )
180-
( <type>.load<memop><memtype> <expr> )
181-
( <type>.store<memop><memtype> <expr> <expr> )
178+
( <type>.load((8|16)_<sign>)?(/<align>)? <expr> )
179+
( <type>.store(/<align>)? <expr> <expr> )
182180
( <type>.const <value> )
183181
( <type>.<unop> <expr> )
184182
( <type>.<binop> <expr> <expr> )

ml-proto/src/host/lexer.mll

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -60,27 +60,32 @@ let floatop t f32 f64 =
6060
| "f64" -> Values.Float64 f64
6161
| _ -> assert false
6262

63-
let mem_type t sign memty =
63+
let mem_type mty =
6464
let open Memory in
65-
match t, sign, memty with
66-
| ("i32" | "i64"), 's', "i8" -> SInt8Mem
67-
| ("i32" | "i64"), 's', "i16" -> SInt16Mem
68-
| ("i32" | "i64"), 's', "i32" -> SInt32Mem
69-
| "i64", 's', "i64" -> SInt64Mem
70-
| ("i32" | "i64"), 'u', "i8" -> UInt8Mem
71-
| ("i32" | "i64"), 'u', "i16" -> UInt16Mem
72-
| ("i32" | "i64"), 'u', "i32" -> UInt32Mem
73-
| "i64", 'u', "i64" -> UInt64Mem
74-
| "f32", ' ', "f32" -> Float32Mem
75-
| "f64", ' ', "f64" -> Float64Mem
65+
match mty with
66+
| "i8" -> Int8Mem
67+
| "i16" -> Int16Mem
68+
| "i32" -> Int32Mem
69+
| "i64" -> Int64Mem
70+
| "f32" -> Float32Mem
71+
| "f64" -> Float64Mem
7672
| _ -> assert false
7773

78-
let memop ty sign memsize a =
79-
let memty = mem_type ty sign memsize in
80-
let align = if a = "" then Memory.mem_size memty else int_of_string a in
81-
{ty = value_type ty; mem = memty; align}
82-
}
74+
let loadop t sign a =
75+
let mem = mem_type t in
76+
let ext = match sign with
77+
| ' ' -> Memory.NX
78+
| 's' -> Memory.SX
79+
| 'u' -> Memory.ZX
80+
| _ -> assert false in
81+
let align = if a = "" then Memory.mem_size mem else int_of_string a in
82+
{mem; ext; align}
8383

84+
let storeop t a =
85+
let mem = mem_type t in
86+
let align = if a = "" then Memory.mem_size mem else int_of_string a in
87+
{mem; align}
88+
}
8489

8590
let space = [' ''\t']
8691
let digit = ['0'-'9']
@@ -104,6 +109,7 @@ let mixx = "i" ("8" | "16" | "32" | "64")
104109
let mfxx = "f" ("32" | "64")
105110
let sign = "s" | "u"
106111
let align = digit+
112+
let width = digit+
107113

108114
rule token = parse
109115
| "(" { LPAR }
@@ -138,17 +144,14 @@ rule token = parse
138144
| "load_global" { LOADGLOBAL }
139145
| "store_global" { STOREGLOBAL }
140146

141-
| (ixx as t)".load_"(sign as s)"/"(mixx as m)"/"(align as a)
142-
{ LOAD (memop t s m a) }
143-
| (ixx as t)".load_"(sign as s)"/"(mixx as m) { LOAD (memop t s m "") }
144-
| (ixx as t)".load/"(mixx as m)"/"(align as a) { LOAD (memop t 's' m a) }
145-
| (ixx as t)".load/"(mixx as m) { LOAD (memop t 's' m "") }
146-
| (ixx as t)".store/"(mixx as m)"/"(align as a) { STORE (memop t 's' m a) }
147-
| (ixx as t)".store/"(mixx as m) { STORE (memop t 's' m "") }
148-
| (fxx as t)".load/"(mfxx as m)"/"(align as a) { LOAD (memop t ' ' m a) }
149-
| (fxx as t)".store/"(mfxx as m)"/"(align as a) { STORE (memop t ' ' m a) }
150-
| (fxx as t)".load/"(mfxx as m) { LOAD (memop t ' ' m "") }
151-
| (fxx as t)".store/"(mfxx as m) { STORE (memop t ' ' m "") }
147+
| (nxx as t)".load" { LOAD (loadop t ' ' "") }
148+
| (nxx as t)".load/"(align as a) { LOAD (loadop t ' ' a) }
149+
| (ixx)".load"(width as w)"_"(sign as s) { LOAD (loadop ("i" ^ w) s "") }
150+
| (ixx)".load"(width as w)"_"(sign as s)"/"(align as a) { LOAD (loadop ("i" ^ w) s a) }
151+
| (nxx as t)".store" { STORE (storeop t "") }
152+
| (nxx as t)".store/"(align as a) { STORE (storeop t a) }
153+
| (ixx)".store"(width as w) { STORE (storeop ("i" ^ w) "") }
154+
| (ixx)".store"(width as w)"/"(align as a) { STORE (storeop ("i" ^ w) a) }
152155

153156
| (nxx as t)".switch" { SWITCH (value_type t) }
154157
| (nxx as t)".const" { CONST (value_type t) }

ml-proto/src/host/parser.mly

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ let anon_label c = {c with labels = VarMap.map ((+) 1) c.labels}
113113
%token<Ast.binop> BINARY
114114
%token<Ast.relop> COMPARE
115115
%token<Ast.cvt> CONVERT
116-
%token<Ast.memop> LOAD
117-
%token<Ast.memop> STORE
116+
%token<Ast.loadop> LOAD
117+
%token<Ast.storeop> STORE
118118

119119
%start script
120120
%type<Script.script> script

ml-proto/src/spec/ast.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ type binop = (Int32Op.binop, Int64Op.binop, Float32Op.binop, Float64Op.binop) op
6363
type relop = (Int32Op.relop, Int64Op.relop, Float32Op.relop, Float64Op.relop) op
6464
type cvt = (Int32Op.cvt, Int64Op.cvt, Float32Op.cvt, Float64Op.cvt) op
6565

66-
type memop = {ty : Types.value_type; mem : Memory.mem_type; align : int}
66+
type loadop = {mem : Memory.mem_type; ext : Memory.extension; align : int}
67+
type storeop = {mem : Memory.mem_type; align : int}
6768

6869

6970
(* Expressions *)
@@ -87,8 +88,8 @@ and expr' =
8788
| SetLocal of var * expr
8889
| LoadGlobal of var
8990
| StoreGlobal of var * expr
90-
| Load of memop * expr
91-
| Store of memop * expr * expr
91+
| Load of loadop * expr
92+
| Store of storeop * expr * expr
9293
| Const of literal
9394
| Unary of unop * expr
9495
| Binary of binop * expr * expr

ml-proto/src/spec/check.ml

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,10 @@ let check_func_type actual expected at =
5454
(* Type Synthesis *)
5555

5656
let type_mem = function
57-
| Memory.SInt8Mem -> Int32Type
58-
| Memory.SInt16Mem -> Int32Type
59-
| Memory.SInt32Mem -> Int32Type
60-
| Memory.SInt64Mem -> Int64Type
61-
| Memory.UInt8Mem -> Int32Type
62-
| Memory.UInt16Mem -> Int32Type
63-
| Memory.UInt32Mem -> Int32Type
64-
| Memory.UInt64Mem -> Int64Type
57+
| Memory.Int8Mem -> Int32Type
58+
| Memory.Int16Mem -> Int32Type
59+
| Memory.Int32Mem -> Int32Type
60+
| Memory.Int64Mem -> Int64Type
6561
| Memory.Float32Mem -> Float32Type
6662
| Memory.Float64Mem -> Float64Type
6763

@@ -184,15 +180,15 @@ let rec check_expr c et e =
184180
check_expr c (Some (global c x)) e1;
185181
check_type None et e.at
186182

187-
| Load (memop, e1) ->
188-
check_memop memop e.at;
183+
| Load (loadop, e1) ->
184+
check_align loadop.align e.at;
189185
check_expr c (Some Int32Type) e1;
190-
check_type (Some (type_mem memop.mem)) et e.at
186+
check_type (Some (type_mem loadop.mem)) et e.at
191187

192-
| Store (memop, e1, e2) ->
193-
check_memop memop e.at;
188+
| Store (storeop, e1, e2) ->
189+
check_align storeop.align e.at;
194190
check_expr c (Some Int32Type) e1;
195-
check_expr c (Some memop.ty) e2;
191+
check_expr c (Some (type_mem storeop.mem)) e2;
196192
check_type None et e.at
197193

198194
| Const v ->
@@ -238,17 +234,8 @@ and check_arm c t et arm =
238234
check_literal c (Some t) l;
239235
check_expr c (if fallthru then None else et) e
240236

241-
and check_memop {ty; mem; align} at =
242-
require (Lib.Int.is_power_of_two align) at "non-power-of-two alignment";
243-
let open Memory in
244-
match mem, ty with
245-
| (SInt8Mem | SInt16Mem | SInt32Mem), Int32Type
246-
| (UInt8Mem | UInt16Mem | UInt32Mem), Int32Type
247-
| (SInt8Mem | SInt16Mem | SInt32Mem | SInt64Mem), Int64Type
248-
| (UInt8Mem | UInt16Mem | UInt32Mem | UInt64Mem), Int64Type
249-
| Float32Mem, Float32Type
250-
| Float64Mem, Float64Type -> ()
251-
| _ -> error at "type-inconsistent memory operator"
237+
and check_align align at =
238+
require (Lib.Int.is_power_of_two align) at "non-power-of-two alignment"
252239

253240

254241
(*

ml-proto/src/spec/eval.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,12 @@ let rec eval_expr (c : config) (e : expr) =
156156
global c x := v1;
157157
None
158158

159-
| Load ({mem; ty; _}, e1) ->
159+
| Load ({mem; ext; align = _}, e1) ->
160160
let v1 = some (eval_expr c e1) e1.at in
161-
(try Some (Memory.load c.modul.memory (Memory.address_of_value v1) mem ty)
161+
(try Some (Memory.load c.modul.memory (Memory.address_of_value v1) mem ext)
162162
with exn -> memory_error e.at exn)
163163

164-
| Store ({mem; _}, e1, e2) ->
164+
| Store ({mem; align = _}, e1, e2) ->
165165
let v1 = some (eval_expr c e1) e1.at in
166166
let v2 = some (eval_expr c e2) e2.at in
167167
(try Memory.store c.modul.memory (Memory.address_of_value v1) mem v2

ml-proto/src/spec/memory.ml

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ open Bigarray
1010
type address = int
1111
type size = address
1212
type mem_size = int
13+
type extension = SX | ZX | NX
1314
type mem_type =
14-
| SInt8Mem | SInt16Mem | SInt32Mem | SInt64Mem
15-
| UInt8Mem | UInt16Mem | UInt32Mem | UInt64Mem
16-
| Float32Mem | Float64Mem
15+
Int8Mem | Int16Mem | Int32Mem | Int64Mem | Float32Mem | Float64Mem
1716

1817
type segment =
1918
{
@@ -42,10 +41,10 @@ let view : memory -> ('c, 'd, c_layout) Array1.t = Obj.magic
4241
(* Queries *)
4342

4443
let mem_size = function
45-
| SInt8Mem | UInt8Mem -> 1
46-
| SInt16Mem | UInt16Mem -> 2
47-
| SInt32Mem | UInt32Mem | Float32Mem -> 4
48-
| SInt64Mem | UInt64Mem | Float64Mem -> 8
44+
| Int8Mem -> 1
45+
| Int16Mem -> 2
46+
| Int32Mem | Float32Mem -> 4
47+
| Int64Mem | Float64Mem -> 8
4948

5049

5150
(* Creation and initialization *)
@@ -83,51 +82,31 @@ let int64_of_int32_u i = Int64.logand (Int64.of_int32 i) int32_mask
8382

8483
let buf = create 8
8584

86-
let load mem a memty valty =
85+
let load mem a memty ext =
8786
let sz = mem_size memty in
8887
let open Types in
8988
try
9089
Array1.blit (Array1.sub mem a sz) (Array1.sub buf 0 sz);
91-
match memty, valty with
92-
| SInt8Mem, Int32Type -> Int32 (Int32.of_int (view buf : sint8_view).{0})
93-
| SInt8Mem, Int64Type -> Int64 (Int64.of_int (view buf : sint8_view).{0})
94-
| SInt16Mem, Int32Type -> Int32 (Int32.of_int (view buf : sint16_view).{0})
95-
| SInt16Mem, Int64Type -> Int64 (Int64.of_int (view buf : sint16_view).{0})
96-
| SInt32Mem, Int32Type -> Int32 (view buf : sint32_view).{0}
97-
| SInt32Mem, Int64Type ->
98-
Int64 (Int64.of_int32 (view buf : sint32_view).{0})
99-
| SInt64Mem, Int64Type -> Int64 (view buf : sint64_view).{0}
100-
| UInt8Mem, Int32Type -> Int32 (Int32.of_int (view buf : uint8_view).{0})
101-
| UInt8Mem, Int64Type -> Int64 (Int64.of_int (view buf : uint8_view).{0})
102-
| UInt16Mem, Int32Type -> Int32 (Int32.of_int (view buf : uint16_view).{0})
103-
| UInt16Mem, Int64Type -> Int64 (Int64.of_int (view buf : uint16_view).{0})
104-
| UInt32Mem, Int32Type -> Int32 (view buf : uint32_view).{0}
105-
| UInt32Mem, Int64Type ->
106-
Int64 (int64_of_int32_u (view buf : uint32_view).{0})
107-
| UInt64Mem, Int64Type -> Int64 (view buf : uint64_view).{0}
108-
| Float32Mem, Float32Type -> Float32 (view buf : float32_view).{0}
109-
| Float64Mem, Float64Type -> Float64 (view buf : float64_view).{0}
90+
match memty, ext with
91+
| Int8Mem, SX -> Int32 (Int32.of_int (view buf : sint8_view).{0})
92+
| Int8Mem, ZX -> Int32 (Int32.of_int (view buf : uint8_view).{0})
93+
| Int16Mem, SX -> Int32 (Int32.of_int (view buf : sint16_view).{0})
94+
| Int16Mem, ZX -> Int32 (Int32.of_int (view buf : uint16_view).{0})
95+
| Int32Mem, NX -> Int32 (view buf : sint32_view).{0}
96+
| Int64Mem, NX -> Int64 (view buf : sint64_view).{0}
97+
| Float32Mem, NX -> Float32 (view buf : float32_view).{0}
98+
| Float64Mem, NX -> Float64 (view buf : float64_view).{0}
11099
| _ -> raise Type
111100
with Invalid_argument _ -> raise Bounds
112101

113102
let store mem a memty v =
114103
let sz = mem_size memty in
115104
try
116105
(match memty, v with
117-
| SInt8Mem, Int32 x -> (view buf : sint8_view).{0} <- Int32.to_int x
118-
| SInt8Mem, Int64 x -> (view buf : sint8_view).{0} <- Int64.to_int x
119-
| SInt16Mem, Int32 x -> (view buf : sint16_view).{0} <- Int32.to_int x
120-
| SInt16Mem, Int64 x -> (view buf : sint16_view).{0} <- Int64.to_int x
121-
| SInt32Mem, Int32 x -> (view buf : sint32_view).{0} <- x
122-
| SInt32Mem, Int64 x -> (view buf : sint32_view).{0} <- Int64.to_int32 x
123-
| SInt64Mem, Int64 x -> (view buf : sint64_view).{0} <- x
124-
| UInt8Mem, Int32 x -> (view buf : uint8_view).{0} <- Int32.to_int x
125-
| UInt8Mem, Int64 x -> (view buf : uint8_view).{0} <- Int64.to_int x
126-
| UInt16Mem, Int32 x -> (view buf : uint16_view).{0} <- Int32.to_int x
127-
| UInt16Mem, Int64 x -> (view buf : uint16_view).{0} <- Int64.to_int x
128-
| UInt32Mem, Int32 x -> (view buf : uint32_view).{0} <- x
129-
| UInt32Mem, Int64 x -> (view buf : uint32_view).{0} <- Int64.to_int32 x
130-
| UInt64Mem, Int64 x -> (view buf : uint64_view).{0} <- x
106+
| Int8Mem, Int32 x -> (view buf : sint8_view).{0} <- Int32.to_int x
107+
| Int16Mem, Int32 x -> (view buf : sint16_view).{0} <- Int32.to_int x
108+
| Int32Mem, Int32 x -> (view buf : sint32_view).{0} <- x
109+
| Int64Mem, Int64 x -> (view buf : sint64_view).{0} <- x
131110
| Float32Mem, Float32 x -> (view buf : float32_view).{0} <- x
132111
| Float64Mem, Float64 x -> (view buf : float64_view).{0} <- x
133112
| _ -> raise Type);

ml-proto/src/spec/memory.mli

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ type t = memory
77
type address = int
88
type size = address
99
type mem_size = int
10+
type extension = SX | ZX | NX
1011
type mem_type =
11-
| SInt8Mem | SInt16Mem | SInt32Mem | SInt64Mem
12-
| UInt8Mem | UInt16Mem | UInt32Mem | UInt64Mem
13-
| Float32Mem | Float64Mem
12+
Int8Mem | Int16Mem | Int32Mem | Int64Mem | Float32Mem | Float64Mem
1413

1514
type segment = {addr : address; data : string}
1615

@@ -20,7 +19,7 @@ exception Address
2019

2120
val create : size -> memory
2221
val init : memory -> segment list -> unit
23-
val load : memory -> address -> mem_type -> Types.value_type -> Values.value
22+
val load : memory -> address -> mem_type -> extension -> Values.value
2423
val store : memory -> address -> mem_type -> Values.value -> unit
2524

2625
val mem_size : mem_type -> mem_size

0 commit comments

Comments
 (0)