Skip to content

Commit 6a65794

Browse files
committed
Update Wasm linker to support stack switching instructions
1 parent 0b4e60b commit 6a65794

File tree

2 files changed

+83
-14
lines changed

2 files changed

+83
-14
lines changed

compiler/lib-wasm/link.ml

+18-1
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

+65-13
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
@@ -147,6 +152,8 @@ module Write = struct
147152

148153
let heaptype st ch typ =
149154
match (typ : heaptype) with
155+
| Nocont -> byte ch 0x75
156+
| Noexn -> byte ch 0x74
150157
| Nofunc -> byte ch 0x73
151158
| Noextern -> byte ch 0x72
152159
| None_ -> byte ch 0x71
@@ -157,6 +164,8 @@ module Write = struct
157164
| I31 -> byte ch 0x6C
158165
| Struct -> byte ch 0x6B
159166
| Array -> byte ch 0x6A
167+
| Exn -> byte ch 0x69
168+
| Cont -> byte ch 0x68
160169
| Type idx -> sint ch (typeidx st idx)
161170

162171
let reftype st ch { nullable; typ } =
@@ -202,6 +211,9 @@ module Write = struct
202211
byte ch 1;
203212
uint ch (typeidx st supertype));
204213
match typ with
214+
| Cont idx ->
215+
byte ch 0x5D;
216+
sint ch (typeidx st idx)
205217
| Array field_type ->
206218
byte ch 0x5E;
207219
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 ->
@@ -1252,6 +1280,13 @@ module Scan = struct
12521280
| 0xD1 (* ref.is_null *) | 0xD3 (* ref.eq *) | 0xD4 (* ref.as_non_null *) ->
12531281
pos + 1 |> instructions
12541282
| 0xD2 (* ref.func *) -> pos + 1 |> funcidx |> instructions
1283+
| 0xE0 (* cont.new *) -> pos + 1 |> typeidx |> instructions
1284+
| 0xE1 (* cont.bind *) -> pos + 1 |> typeidx |> typeidx |> instructions
1285+
| 0xE2 (* suspend *) -> pos + 1 |> tagidx |> instructions
1286+
| 0xE3 (* resume *) -> pos + 1 |> typeidx |> vector on_clause |> instructions
1287+
| 0xE4 (* resume_throw *) ->
1288+
pos + 1 |> typeidx |> tagidx |> vector on_clause |> instructions
1289+
| 0xE5 (* switch *) -> pos + 1 |> typeidx |> tagidx |> instructions
12551290
| 0xFB -> pos + 1 |> gc_instruction
12561291
| 0xFC -> (
12571292
if debug then Format.eprintf " %d@." (get (pos + 1));
@@ -1386,6 +1421,11 @@ module Scan = struct
13861421
| 0 (* catch *) | 1 (* catch_ref *) -> pos + 1 |> tagidx |> labelidx
13871422
| 2 (* catch_all *) | 3 (* catch_all_ref *) -> pos + 1 |> labelidx
13881423
| c -> failwith (Printf.sprintf "bad catch 0x02%d@." c)
1424+
and on_clause pos =
1425+
match get pos with
1426+
| 0 (* on *) -> pos + 1 |> tagidx |> labelidx
1427+
| 1 (* on .. switch *) -> pos + 1 |> tagidx
1428+
| c -> failwith (Printf.sprintf "bad on clause 0x02%d@." c)
13891429
and block_end pos =
13901430
if debug then Format.eprintf "0x%02X (@%d) block end@." (get pos) pos;
13911431
match get pos with
@@ -1538,30 +1578,43 @@ let rec subtype subtyping_info (i : int) i' =
15381578
| None -> false
15391579
| Some s -> subtype subtyping_info s i'
15401580

1541-
let heap_subtype (subtyping_info : subtype array) (ty : heaptype) (ty' : heaptype) =
1581+
let rec heap_subtype (subtyping_info : subtype array) (ty : heaptype) (ty' : heaptype) =
15421582
match ty, ty' with
1543-
| (Func | Nofunc), Func
1544-
| Nofunc, Nofunc
1545-
| (Extern | Noextern), Extern
1583+
| Func, Func
1584+
| Extern, Extern
1585+
| Noextern, Noextern
1586+
| Exn, Exn
1587+
| Noexn, Noexn
1588+
| Cont, Cont
1589+
| Nocont, Nocont
15461590
| (Any | Eq | I31 | Struct | Array | None_ | Type _), Any
15471591
| (Eq | I31 | Struct | Array | None_ | Type _), Eq
1548-
| (I31 | None_), I31
1549-
| (Struct | None_), Struct
1550-
| (Array | None_), Array
1592+
| I31, I31
1593+
| Struct, Struct
1594+
| Array, Array
15511595
| None_, None_ -> true
15521596
| Type i, Struct -> (
15531597
match subtyping_info.(i).typ with
15541598
| Struct _ -> true
1555-
| Array _ | Func _ -> false)
1599+
| Array _ | Func _ | Cont _ -> false)
15561600
| Type i, Array -> (
15571601
match subtyping_info.(i).typ with
15581602
| Array _ -> true
1559-
| Struct _ | Func _ -> false)
1603+
| Struct _ | Func _ | Cont _ -> false)
15601604
| Type i, Func -> (
15611605
match subtyping_info.(i).typ with
15621606
| Func _ -> true
1563-
| Struct _ | Array _ -> false)
1607+
| Struct _ | Array _ | Cont _ -> false)
1608+
| Type i, Cont -> (
1609+
match subtyping_info.(i).typ with
1610+
| Cont _ -> true
1611+
| Struct _ | Array _ | Func _ -> false)
15641612
| Type i, Type i' -> subtype subtyping_info i i'
1613+
| Nofunc, _ -> heap_subtype subtyping_info ty' Func
1614+
| Noextern, _ -> heap_subtype subtyping_info ty' Extern
1615+
| Noexn, _ -> heap_subtype subtyping_info ty' Exn
1616+
| Nocont, _ -> heap_subtype subtyping_info ty' Cont
1617+
| None_, _ -> heap_subtype subtyping_info ty' Any
15651618
| _ -> false
15661619

15671620
let ref_subtype subtyping_info { nullable; typ } { nullable = nullable'; typ = typ' } =
@@ -2449,7 +2502,6 @@ let f ?(filter_export = fun _ -> true) files ~output_file =
24492502
(*
24502503
LATER
24512504
- testsuite : import/export matching, source maps, multiple start functions, ...
2452-
- missing instructions ==> typed continuations (?)
24532505
- check features?
24542506
24552507
MAYBE

0 commit comments

Comments
 (0)