Skip to content

Commit 0bacf91

Browse files
committed
Update Wasm linker to support stack switching instructions
1 parent 815f4c8 commit 0bacf91

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
@@ -569,7 +581,9 @@ module Read = struct
569581
let heaptype st ch =
570582
let i = sint ch in
571583
match i + 128 with
572-
| 0X73 -> Nofunc
584+
| 0x75 -> Nocont
585+
| 0x74 -> Noexn
586+
| 0x73 -> Nofunc
573587
| 0x72 -> Noextern
574588
| 0x71 -> None_
575589
| 0x70 -> Func
@@ -579,6 +593,8 @@ module Read = struct
579593
| 0x6C -> I31
580594
| 0x6B -> Struct
581595
| 0x6A -> Array
596+
| 0x69 -> Exn
597+
| 0x68 -> Cont
582598
| _ ->
583599
if i < 0 then failwith (Printf.sprintf "Unknown heaptype %x@." i);
584600
let i =
@@ -596,7 +612,9 @@ module Read = struct
596612

597613
let reftype' st i ch =
598614
match i with
599-
| 0X73 -> nullable Nofunc
615+
| 0x75 -> nullable Nocont
616+
| 0x74 -> nullable Noexn
617+
| 0x73 -> nullable Nofunc
600618
| 0x72 -> nullable Noextern
601619
| 0x71 -> nullable None_
602620
| 0x70 -> nullable Func
@@ -606,6 +624,8 @@ module Read = struct
606624
| 0x6C -> nullable I31
607625
| 0x6B -> nullable Struct
608626
| 0x6A -> nullable Array
627+
| 0x69 -> nullable Exn
628+
| 0x68 -> nullable Cont
609629
| 0x63 -> nullable (heaptype st ch)
610630
| 0x64 -> { nullable = false; typ = heaptype st ch }
611631
| _ -> failwith (Printf.sprintf "Unknown reftype %x@." i)
@@ -652,6 +672,14 @@ module Read = struct
652672

653673
let comptype st i ch =
654674
match i with
675+
| 0x5D ->
676+
let i = sint ch in
677+
let i =
678+
if i >= st.type_index_count
679+
then lnot (i - st.type_index_count)
680+
else st.type_mapping.(i)
681+
in
682+
Cont i
655683
| 0x5E -> Array (fieldtype st ch)
656684
| 0x5F -> Struct (vec (fieldtype st) ch)
657685
| 0x60 ->
@@ -1258,6 +1286,13 @@ module Scan = struct
12581286
| 0xD1 (* ref.is_null *) | 0xD3 (* ref.eq *) | 0xD4 (* ref.as_non_null *) ->
12591287
pos + 1 |> instructions
12601288
| 0xD2 (* ref.func *) -> pos + 1 |> funcidx |> instructions
1289+
| 0xE0 (* cont.new *) -> pos + 1 |> typeidx |> instructions
1290+
| 0xE1 (* cont.bind *) -> pos + 1 |> typeidx |> typeidx |> instructions
1291+
| 0xE2 (* suspend *) -> pos + 1 |> tagidx |> instructions
1292+
| 0xE3 (* resume *) -> pos + 1 |> typeidx |> vector on_clause |> instructions
1293+
| 0xE4 (* resume_throw *) ->
1294+
pos + 1 |> typeidx |> tagidx |> vector on_clause |> instructions
1295+
| 0xE5 (* switch *) -> pos + 1 |> typeidx |> tagidx |> instructions
12611296
| 0xFB -> pos + 1 |> gc_instruction
12621297
| 0xFC -> (
12631298
if debug then Format.eprintf " %d@." (get (pos + 1));
@@ -1392,6 +1427,11 @@ module Scan = struct
13921427
| 0 (* catch *) | 1 (* catch_ref *) -> pos + 1 |> tagidx |> labelidx
13931428
| 2 (* catch_all *) | 3 (* catch_all_ref *) -> pos + 1 |> labelidx
13941429
| c -> failwith (Printf.sprintf "bad catch 0x02%d@." c)
1430+
and on_clause pos =
1431+
match get pos with
1432+
| 0 (* on *) -> pos + 1 |> tagidx |> labelidx
1433+
| 1 (* on .. switch *) -> pos + 1 |> tagidx
1434+
| c -> failwith (Printf.sprintf "bad on clause 0x02%d@." c)
13951435
and block_end pos =
13961436
if debug then Format.eprintf "0x%02X (@%d) block end@." (get pos) pos;
13971437
match get pos with
@@ -1544,30 +1584,43 @@ let rec subtype subtyping_info (i : int) i' =
15441584
| None -> false
15451585
| Some s -> subtype subtyping_info s i'
15461586

1547-
let heap_subtype (subtyping_info : subtype array) (ty : heaptype) (ty' : heaptype) =
1587+
let rec heap_subtype (subtyping_info : subtype array) (ty : heaptype) (ty' : heaptype) =
15481588
match ty, ty' with
1549-
| (Func | Nofunc), Func
1550-
| Nofunc, Nofunc
1551-
| (Extern | Noextern), Extern
1589+
| Func, Func
1590+
| Extern, Extern
1591+
| Noextern, Noextern
1592+
| Exn, Exn
1593+
| Noexn, Noexn
1594+
| Cont, Cont
1595+
| Nocont, Nocont
15521596
| (Any | Eq | I31 | Struct | Array | None_ | Type _), Any
15531597
| (Eq | I31 | Struct | Array | None_ | Type _), Eq
1554-
| (I31 | None_), I31
1555-
| (Struct | None_), Struct
1556-
| (Array | None_), Array
1598+
| I31, I31
1599+
| Struct, Struct
1600+
| Array, Array
15571601
| None_, None_ -> true
15581602
| Type i, Struct -> (
15591603
match subtyping_info.(i).typ with
15601604
| Struct _ -> true
1561-
| Array _ | Func _ -> false)
1605+
| Array _ | Func _ | Cont _ -> false)
15621606
| Type i, Array -> (
15631607
match subtyping_info.(i).typ with
15641608
| Array _ -> true
1565-
| Struct _ | Func _ -> false)
1609+
| Struct _ | Func _ | Cont _ -> false)
15661610
| Type i, Func -> (
15671611
match subtyping_info.(i).typ with
15681612
| Func _ -> true
1569-
| Struct _ | Array _ -> false)
1613+
| Struct _ | Array _ | Cont _ -> false)
1614+
| Type i, Cont -> (
1615+
match subtyping_info.(i).typ with
1616+
| Cont _ -> true
1617+
| Struct _ | Array _ | Func _ -> false)
15701618
| Type i, Type i' -> subtype subtyping_info i i'
1619+
| Nofunc, _ -> heap_subtype subtyping_info ty' Func
1620+
| Noextern, _ -> heap_subtype subtyping_info ty' Extern
1621+
| Noexn, _ -> heap_subtype subtyping_info ty' Exn
1622+
| Nocont, _ -> heap_subtype subtyping_info ty' Cont
1623+
| None_, _ -> heap_subtype subtyping_info ty' Any
15711624
| _ -> false
15721625

15731626
let ref_subtype subtyping_info { nullable; typ } { nullable = nullable'; typ = typ' } =
@@ -2455,7 +2508,6 @@ let f ?(filter_export = fun _ -> true) files ~output_file =
24552508
(*
24562509
LATER
24572510
- testsuite : import/export matching, source maps, multiple start functions, ...
2458-
- missing instructions ==> typed continuations (?)
24592511
- check features?
24602512
24612513
MAYBE

0 commit comments

Comments
 (0)