@@ -121,6 +121,24 @@ pub enum FrameKind {
121
121
///
122
122
/// This belongs to the Wasm exception handling proposal.
123
123
TryTable ,
124
+ /// A Wasm legacy `try` control block.
125
+ ///
126
+ /// # Note
127
+ ///
128
+ /// See: `WasmFeatures::legacy_exceptions` Note in `crates/wasmparser/src/features.rs`
129
+ LegacyTry ,
130
+ /// A Wasm legacy `catch` control block.
131
+ ///
132
+ /// # Note
133
+ ///
134
+ /// See: `WasmFeatures::legacy_exceptions` Note in `crates/wasmparser/src/features.rs`
135
+ LegacyCatch ,
136
+ /// A Wasm legacy `catch_all` control block.
137
+ ///
138
+ /// # Note
139
+ ///
140
+ /// See: `WasmFeatures::legacy_exceptions` Note in `crates/wasmparser/src/features.rs`
141
+ LegacyCatchAll ,
124
142
}
125
143
126
144
struct OperatorValidatorTemp < ' validator , ' resources , T > {
@@ -1322,6 +1340,7 @@ macro_rules! validate_proposal {
1322
1340
( desc function_references) => ( "function references" ) ;
1323
1341
( desc memory_control) => ( "memory control" ) ;
1324
1342
( desc gc) => ( "gc" ) ;
1343
+ ( desc legacy_exceptions) => ( "legacy exceptions" ) ;
1325
1344
}
1326
1345
1327
1346
impl < ' a , T > VisitOperator < ' a > for WasmProposalValidator < ' _ , ' _ , T >
@@ -1486,21 +1505,6 @@ where
1486
1505
self . unreachable ( ) ?;
1487
1506
Ok ( ( ) )
1488
1507
}
1489
- fn visit_try ( & mut self , _: BlockType ) -> Self :: Output {
1490
- bail ! ( self . offset, "unimplemented validation of deprecated opcode" )
1491
- }
1492
- fn visit_catch ( & mut self , _: u32 ) -> Self :: Output {
1493
- bail ! ( self . offset, "unimplemented validation of deprecated opcode" )
1494
- }
1495
- fn visit_rethrow ( & mut self , _: u32 ) -> Self :: Output {
1496
- bail ! ( self . offset, "unimplemented validation of deprecated opcode" )
1497
- }
1498
- fn visit_delegate ( & mut self , _: u32 ) -> Self :: Output {
1499
- bail ! ( self . offset, "unimplemented validation of deprecated opcode" )
1500
- }
1501
- fn visit_catch_all ( & mut self ) -> Self :: Output {
1502
- bail ! ( self . offset, "unimplemented validation of deprecated opcode" )
1503
- }
1504
1508
fn visit_end ( & mut self ) -> Self :: Output {
1505
1509
let mut frame = self . pop_ctrl ( ) ?;
1506
1510
@@ -4124,6 +4128,80 @@ where
4124
4128
self . pop_operand ( Some ( ValType :: Ref ( RefType :: I31REF ) ) ) ?;
4125
4129
self . push_operand ( ValType :: I32 )
4126
4130
}
4131
+ fn visit_try ( & mut self , mut ty : BlockType ) -> Self :: Output {
4132
+ self . check_block_type ( & mut ty) ?;
4133
+ for ty in self . params ( ty) ?. rev ( ) {
4134
+ self . pop_operand ( Some ( ty) ) ?;
4135
+ }
4136
+ self . push_ctrl ( FrameKind :: LegacyTry , ty) ?;
4137
+ Ok ( ( ) )
4138
+ }
4139
+ fn visit_catch ( & mut self , index : u32 ) -> Self :: Output {
4140
+ let frame = self . pop_ctrl ( ) ?;
4141
+ if frame. kind != FrameKind :: LegacyTry && frame. kind != FrameKind :: LegacyCatch {
4142
+ bail ! ( self . offset, "catch found outside of an `try` block" ) ;
4143
+ }
4144
+ // Start a new frame and push `exnref` value.
4145
+ let height = self . operands . len ( ) ;
4146
+ let init_height = self . inits . len ( ) ;
4147
+ self . control . push ( Frame {
4148
+ kind : FrameKind :: LegacyCatch ,
4149
+ block_type : frame. block_type ,
4150
+ height,
4151
+ unreachable : false ,
4152
+ init_height,
4153
+ } ) ;
4154
+ // Push exception argument types.
4155
+ let ty = self . tag_at ( index) ?;
4156
+ for ty in ty. params ( ) {
4157
+ self . push_operand ( * ty) ?;
4158
+ }
4159
+ Ok ( ( ) )
4160
+ }
4161
+ fn visit_rethrow ( & mut self , relative_depth : u32 ) -> Self :: Output {
4162
+ // This is not a jump, but we need to check that the `rethrow`
4163
+ // targets an actual `catch` to get the exception.
4164
+ let ( _, kind) = self . jump ( relative_depth) ?;
4165
+ if kind != FrameKind :: LegacyCatch && kind != FrameKind :: LegacyCatchAll {
4166
+ bail ! (
4167
+ self . offset,
4168
+ "invalid rethrow label: target was not a `catch` block"
4169
+ ) ;
4170
+ }
4171
+ self . unreachable ( ) ?;
4172
+ Ok ( ( ) )
4173
+ }
4174
+ fn visit_delegate ( & mut self , relative_depth : u32 ) -> Self :: Output {
4175
+ let frame = self . pop_ctrl ( ) ?;
4176
+ if frame. kind != FrameKind :: LegacyTry {
4177
+ bail ! ( self . offset, "delegate found outside of an `try` block" ) ;
4178
+ }
4179
+ // This operation is not a jump, but we need to check the
4180
+ // depth for validity
4181
+ let _ = self . jump ( relative_depth) ?;
4182
+ for ty in self . results ( frame. block_type ) ? {
4183
+ self . push_operand ( ty) ?;
4184
+ }
4185
+ Ok ( ( ) )
4186
+ }
4187
+ fn visit_catch_all ( & mut self ) -> Self :: Output {
4188
+ let frame = self . pop_ctrl ( ) ?;
4189
+ if frame. kind == FrameKind :: LegacyCatchAll {
4190
+ bail ! ( self . offset, "only one catch_all allowed per `try` block" ) ;
4191
+ } else if frame. kind != FrameKind :: LegacyTry && frame. kind != FrameKind :: LegacyCatch {
4192
+ bail ! ( self . offset, "catch_all found outside of a `try` block" ) ;
4193
+ }
4194
+ let height = self . operands . len ( ) ;
4195
+ let init_height = self . inits . len ( ) ;
4196
+ self . control . push ( Frame {
4197
+ kind : FrameKind :: LegacyCatchAll ,
4198
+ block_type : frame. block_type ,
4199
+ height,
4200
+ unreachable : false ,
4201
+ init_height,
4202
+ } ) ;
4203
+ Ok ( ( ) )
4204
+ }
4127
4205
}
4128
4206
4129
4207
#[ derive( Clone , Debug ) ]
0 commit comments