@@ -121,6 +121,24 @@ pub enum FrameKind {
121121 ///
122122 /// This belongs to the Wasm exception handling proposal.
123123 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 ,
124142}
125143
126144struct OperatorValidatorTemp < ' validator , ' resources , T > {
@@ -1322,6 +1340,7 @@ macro_rules! validate_proposal {
13221340 ( desc function_references) => ( "function references" ) ;
13231341 ( desc memory_control) => ( "memory control" ) ;
13241342 ( desc gc) => ( "gc" ) ;
1343+ ( desc legacy_exceptions) => ( "legacy exceptions" ) ;
13251344}
13261345
13271346impl < ' a , T > VisitOperator < ' a > for WasmProposalValidator < ' _ , ' _ , T >
@@ -1486,21 +1505,6 @@ where
14861505 self . unreachable ( ) ?;
14871506 Ok ( ( ) )
14881507 }
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- }
15041508 fn visit_end ( & mut self ) -> Self :: Output {
15051509 let mut frame = self . pop_ctrl ( ) ?;
15061510
@@ -4124,6 +4128,80 @@ where
41244128 self . pop_operand ( Some ( ValType :: Ref ( RefType :: I31REF ) ) ) ?;
41254129 self . push_operand ( ValType :: I32 )
41264130 }
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+ }
41274205}
41284206
41294207#[ derive( Clone , Debug ) ]
0 commit comments