@@ -91,6 +91,72 @@ class Try extends Label {
9191 List <ir.ValueType > get targetTypes => outputs;
9292}
9393
94+ class TryTable extends Label {
95+ final List <TryTableCatch > catches;
96+
97+ TryTable (super .inputs, super .outputs, this .catches) : super ._();
98+
99+ @override
100+ List <ir.ValueType > get targetTypes => outputs;
101+ }
102+
103+ abstract class TryTableCatch {
104+ final Label label;
105+
106+ TryTableCatch (this .label);
107+
108+ ir.TryTableCatch toIr (int labelIndex);
109+
110+ /// Values that the catch block catches, i.e. pushes as outputs.
111+ List <ir.ValueType > caughtValues ();
112+ }
113+
114+ class Catch extends TryTableCatch {
115+ final ir.Tag tag;
116+
117+ Catch (this .tag, super .label);
118+
119+ @override
120+ ir.TryTableCatch toIr (int labelIndex) => ir.Catch (tag, labelIndex);
121+
122+ @override
123+ List <ir.ValueType > caughtValues () => tag.type.inputs;
124+ }
125+
126+ class CatchRef extends TryTableCatch {
127+ final ir.Tag tag;
128+
129+ CatchRef (this .tag, super .label);
130+
131+ @override
132+ ir.TryTableCatch toIr (int labelIndex) => ir.CatchRef (tag, labelIndex);
133+
134+ @override
135+ List <ir.ValueType > caughtValues () =>
136+ < ir.ValueType > [...tag.type.inputs, ir.RefType .exn (nullable: false )];
137+ }
138+
139+ class CatchAll extends TryTableCatch {
140+ CatchAll (super .label);
141+
142+ @override
143+ ir.TryTableCatch toIr (int labelIndex) => ir.CatchAll (labelIndex);
144+
145+ @override
146+ List <ir.ValueType > caughtValues () => < ir.ValueType > [];
147+ }
148+
149+ class CatchAllRef extends TryTableCatch {
150+ CatchAllRef (super .label);
151+
152+ @override
153+ ir.TryTableCatch toIr (int labelIndex) => ir.CatchAllRef (labelIndex);
154+
155+ @override
156+ List <ir.ValueType > caughtValues () =>
157+ < ir.ValueType > [ir.RefType .exn (nullable: false )];
158+ }
159+
94160/// A sequence of Wasm instructions.
95161///
96162/// Instructions can be added to the sequence by calling the corresponding
@@ -545,8 +611,8 @@ class InstructionsBuilder with Builder<ir.Instructions> {
545611 ir.BeginOneOutputTry .new ,
546612 ir.BeginFunctionTry .new );
547613
548- /// Emit a `catch` instruction.
549- void catch_ (ir.Tag tag) {
614+ /// Emit a legacy `catch` instruction.
615+ void catch_legacy (ir.Tag tag) {
550616 assert (_topOfLabelStack is Try ||
551617 _reportError ("Unexpected 'catch' (not in 'try' block)" ));
552618 final Try try_ = _topOfLabelStack as Try ;
@@ -555,18 +621,18 @@ class InstructionsBuilder with Builder<ir.Instructions> {
555621 assert (tag.enclosingModule == module);
556622 try_.hasCatch = true ;
557623 _reachable = try_.reachable;
558- _add (ir.Catch (tag));
624+ _add (ir.CatchLegacy (tag));
559625 }
560626
561- void catch_all () {
627+ void catch_all_legacy () {
562628 assert (_topOfLabelStack is Try ||
563629 _reportError ("Unexpected 'catch_all' (not in 'try' block)" ));
564630 final Try try_ = _topOfLabelStack as Try ;
565631 assert (_verifyEndOfBlock ([],
566632 trace: ['catch_all' ], reachableAfter: try_.reachable, reindent: true ));
567633 try_.hasCatch = true ;
568634 _reachable = try_.reachable;
569- _add (const ir.CatchAll ());
635+ _add (const ir.CatchAllLegacy ());
570636 }
571637
572638 /// Emit a `throw` instruction.
@@ -585,6 +651,12 @@ class InstructionsBuilder with Builder<ir.Instructions> {
585651 _reachable = false ;
586652 }
587653
654+ /// Emit a `throw_ref` instruction.
655+ void throw_ref () {
656+ _add (ir.ThrowRef ());
657+ _reachable = false ;
658+ }
659+
588660 /// Emit an `end` instruction.
589661 void end () {
590662 assert (_verifyEndOfBlock (_topOfLabelStack.outputs,
@@ -632,6 +704,26 @@ class InstructionsBuilder with Builder<ir.Instructions> {
632704 _reachable = false ;
633705 }
634706
707+ /// Emit a `try_table` instruction.
708+ Label try_table (List <TryTableCatch > catches,
709+ [List <ir.ValueType > inputs = const [],
710+ List <ir.ValueType > outputs = const []]) {
711+ // Validation: blocks in the table should have the outputs based on the
712+ // types of exceptions they catch.
713+ for (TryTableCatch catch_ in catches) {
714+ assert (_verifyBranchTypes (catch_.label, 0 , catch_.caughtValues ()));
715+ }
716+ final List <ir.TryTableCatch > irCatches =
717+ catches.map ((c) => c.toIr (_labelIndex (c.label))).toList ();
718+ final label = _pushLabel (TryTable (inputs, outputs, catches),
719+ trace: const ['try_table' ]);
720+ return _beginBlock (
721+ label,
722+ () => ir.BeginNoEffectTryTable (irCatches),
723+ (ty) => ir.BeginOneOutputTryTable (ty, irCatches),
724+ (ty) => ir.BeginFunctionTryTable (ty, irCatches));
725+ }
726+
635727 /// Emit a `return` instruction.
636728 void return_ () {
637729 assert (_verifyTypes (_labelStack[0 ].outputs, const [],
0 commit comments