Skip to content

Commit 2239b0c

Browse files
committed
Update Wasm linker to support stack switching instructions
1 parent 8115834 commit 2239b0c

File tree

2 files changed

+83
-14
lines changed

2 files changed

+83
-14
lines changed

compiler/lib-wasm/link.ml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,20 @@ module Wasm_binary = struct
173173

174174
let reftype' i ch =
175175
match i with
176-
| 0x6a | 0x6b | 0x6c | 0x6d | 0x6e | 0x6f | 0x70 | 0x71 | 0x72 | 0x73 -> ()
176+
| 0x68
177+
| 0x69
178+
| 0x6a
179+
| 0x6b
180+
| 0x6c
181+
| 0x6d
182+
| 0x6e
183+
| 0x6f
184+
| 0x70
185+
| 0x71
186+
| 0x72
187+
| 0x73
188+
| 0x74
189+
| 0x75 -> ()
177190
| 0x63 | 0x64 -> heaptype ch
178191
| _ ->
179192
Format.eprintf "Unknown reftype %x@." i;
@@ -206,6 +219,7 @@ module Wasm_binary = struct
206219
| Func of { arity : int }
207220
| Struct
208221
| Array
222+
| Cont
209223

210224
let supertype ch =
211225
match input_byte ch with
@@ -225,6 +239,9 @@ module Wasm_binary = struct
225239

226240
let comptype i ch =
227241
match i with
242+
| 0x5D ->
243+
ignore (read_sint ch);
244+
Cont
228245
| 0x5E ->
229246
fieldtype ch;
230247
Array

compiler/lib-wasm/wasm_link.ml

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ type heaptype =
2323
| Nofunc
2424
| Extern
2525
| Noextern
26+
| Exn
27+
| Noexn
28+
| Cont
29+
| Nocont
2630
| Any
2731
| Eq
2832
| I31
@@ -66,6 +70,7 @@ type comptype =
6670
}
6771
| Struct of fieldtype array
6872
| Array of fieldtype
73+
| Cont of int
6974

7075
type subtype =
7176
{ final : bool
@@ -164,6 +169,8 @@ module Write = struct
164169

165170
let heaptype st ch typ =
166171
match (typ : heaptype) with
172+
| Nocont -> byte ch 0x75
173+
| Noexn -> byte ch 0x74
167174
| Nofunc -> byte ch 0x73
168175
| Noextern -> byte ch 0x72
169176
| None_ -> byte ch 0x71
@@ -174,6 +181,8 @@ module Write = struct
174181
| I31 -> byte ch 0x6C
175182
| Struct -> byte ch 0x6B
176183
| Array -> byte ch 0x6A
184+
| Exn -> byte ch 0x69
185+
| Cont -> byte ch 0x68
177186
| Type idx -> sint ch (typeidx st idx)
178187

179188
let reftype st ch { nullable; typ } =
@@ -219,6 +228,9 @@ module Write = struct
219228
byte ch 1;
220229
uint ch (typeidx st supertype));
221230
match typ with
231+
| Cont idx ->
232+
byte ch 0x5D;
233+
sint ch (typeidx st idx)
222234
| Array field_type ->
223235
byte ch 0x5E;
224236
fieldtype st ch field_type
@@ -571,7 +583,9 @@ module Read = struct
571583
let heaptype st ch =
572584
let i = sint ch in
573585
match i + 128 with
574-
| 0X73 -> Nofunc
586+
| 0x75 -> Nocont
587+
| 0x74 -> Noexn
588+
| 0x73 -> Nofunc
575589
| 0x72 -> Noextern
576590
| 0x71 -> None_
577591
| 0x70 -> Func
@@ -581,6 +595,8 @@ module Read = struct
581595
| 0x6C -> I31
582596
| 0x6B -> Struct
583597
| 0x6A -> Array
598+
| 0x69 -> Exn
599+
| 0x68 -> Cont
584600
| _ ->
585601
if i < 0 then failwith (Printf.sprintf "Unknown heaptype %x@." i);
586602
let i =
@@ -598,7 +614,9 @@ module Read = struct
598614

599615
let reftype' st i ch =
600616
match i with
601-
| 0X73 -> nullable Nofunc
617+
| 0x75 -> nullable Nocont
618+
| 0x74 -> nullable Noexn
619+
| 0x73 -> nullable Nofunc
602620
| 0x72 -> nullable Noextern
603621
| 0x71 -> nullable None_
604622
| 0x70 -> nullable Func
@@ -608,6 +626,8 @@ module Read = struct
608626
| 0x6C -> nullable I31
609627
| 0x6B -> nullable Struct
610628
| 0x6A -> nullable Array
629+
| 0x69 -> nullable Exn
630+
| 0x68 -> nullable Cont
611631
| 0x63 -> nullable (heaptype st ch)
612632
| 0x64 -> { nullable = false; typ = heaptype st ch }
613633
| _ -> failwith (Printf.sprintf "Unknown reftype %x@." i)
@@ -654,6 +674,14 @@ module Read = struct
654674

655675
let comptype st i ch =
656676
match i with
677+
| 0x5D ->
678+
let i = sint ch in
679+
let i =
680+
if i >= st.type_index_count
681+
then lnot (i - st.type_index_count)
682+
else st.type_mapping.(i)
683+
in
684+
Cont i
657685
| 0x5E -> Array (fieldtype st ch)
658686
| 0x5F -> Struct (vec (fieldtype st) ch)
659687
| 0x60 ->
@@ -1260,6 +1288,13 @@ module Scan = struct
12601288
| 0xD1 (* ref.is_null *) | 0xD3 (* ref.eq *) | 0xD4 (* ref.as_non_null *) ->
12611289
pos + 1 |> instructions
12621290
| 0xD2 (* ref.func *) -> pos + 1 |> funcidx |> instructions
1291+
| 0xE0 (* cont.new *) -> pos + 1 |> typeidx |> instructions
1292+
| 0xE1 (* cont.bind *) -> pos + 1 |> typeidx |> typeidx |> instructions
1293+
| 0xE2 (* suspend *) -> pos + 1 |> tagidx |> instructions
1294+
| 0xE3 (* resume *) -> pos + 1 |> typeidx |> vector on_clause |> instructions
1295+
| 0xE4 (* resume_throw *) ->
1296+
pos + 1 |> typeidx |> tagidx |> vector on_clause |> instructions
1297+
| 0xE5 (* switch *) -> pos + 1 |> typeidx |> tagidx |> instructions
12631298
| 0xFB -> pos + 1 |> gc_instruction
12641299
| 0xFC -> (
12651300
if debug then Format.eprintf " %d@." (get (pos + 1));
@@ -1394,6 +1429,11 @@ module Scan = struct
13941429
| 0 (* catch *) | 1 (* catch_ref *) -> pos + 1 |> tagidx |> labelidx
13951430
| 2 (* catch_all *) | 3 (* catch_all_ref *) -> pos + 1 |> labelidx
13961431
| c -> failwith (Printf.sprintf "bad catch 0x02%d@." c)
1432+
and on_clause pos =
1433+
match get pos with
1434+
| 0 (* on *) -> pos + 1 |> tagidx |> labelidx
1435+
| 1 (* on .. switch *) -> pos + 1 |> tagidx
1436+
| c -> failwith (Printf.sprintf "bad on clause 0x02%d@." c)
13971437
and block_end pos =
13981438
if debug then Format.eprintf "0x%02X (@%d) block end@." (get pos) pos;
13991439
match get pos with
@@ -1546,30 +1586,43 @@ let rec subtype subtyping_info (i : int) i' =
15461586
| None -> false
15471587
| Some s -> subtype subtyping_info s i'
15481588

1549-
let heap_subtype (subtyping_info : subtype array) (ty : heaptype) (ty' : heaptype) =
1589+
let rec heap_subtype (subtyping_info : subtype array) (ty : heaptype) (ty' : heaptype) =
15501590
match ty, ty' with
1551-
| (Func | Nofunc), Func
1552-
| Nofunc, Nofunc
1553-
| (Extern | Noextern), Extern
1591+
| Func, Func
1592+
| Extern, Extern
1593+
| Noextern, Noextern
1594+
| Exn, Exn
1595+
| Noexn, Noexn
1596+
| Cont, Cont
1597+
| Nocont, Nocont
15541598
| (Any | Eq | I31 | Struct | Array | None_ | Type _), Any
15551599
| (Eq | I31 | Struct | Array | None_ | Type _), Eq
1556-
| (I31 | None_), I31
1557-
| (Struct | None_), Struct
1558-
| (Array | None_), Array
1600+
| I31, I31
1601+
| Struct, Struct
1602+
| Array, Array
15591603
| None_, None_ -> true
15601604
| Type i, Struct -> (
15611605
match subtyping_info.(i).typ with
15621606
| Struct _ -> true
1563-
| Array _ | Func _ -> false)
1607+
| Array _ | Func _ | Cont _ -> false)
15641608
| Type i, Array -> (
15651609
match subtyping_info.(i).typ with
15661610
| Array _ -> true
1567-
| Struct _ | Func _ -> false)
1611+
| Struct _ | Func _ | Cont _ -> false)
15681612
| Type i, Func -> (
15691613
match subtyping_info.(i).typ with
15701614
| Func _ -> true
1571-
| Struct _ | Array _ -> false)
1615+
| Struct _ | Array _ | Cont _ -> false)
1616+
| Type i, Cont -> (
1617+
match subtyping_info.(i).typ with
1618+
| Cont _ -> true
1619+
| Struct _ | Array _ | Func _ -> false)
15721620
| Type i, Type i' -> subtype subtyping_info i i'
1621+
| Nofunc, _ -> heap_subtype subtyping_info ty' Func
1622+
| Noextern, _ -> heap_subtype subtyping_info ty' Extern
1623+
| Noexn, _ -> heap_subtype subtyping_info ty' Exn
1624+
| Nocont, _ -> heap_subtype subtyping_info ty' Cont
1625+
| None_, _ -> heap_subtype subtyping_info ty' Any
15731626
| _ -> false
15741627

15751628
let ref_subtype subtyping_info { nullable; typ } { nullable = nullable'; typ = typ' } =
@@ -2457,7 +2510,6 @@ let f ?(filter_export = fun _ -> true) files ~output_file =
24572510
(*
24582511
LATER
24592512
- testsuite : import/export matching, source maps, multiple start functions, ...
2460-
- missing instructions ==> typed continuations (?)
24612513
- check features?
24622514
24632515
MAYBE

0 commit comments

Comments
 (0)