@@ -796,6 +796,8 @@ where
796
796
}
797
797
}
798
798
799
+ /// Returns the corresponding function type for the `func` item located at
800
+ /// `function_index`.
799
801
fn type_of_function ( & self , function_index : u32 ) -> Result < & ' resources FuncType > {
800
802
match self . resources . type_of_function ( function_index) {
801
803
Some ( f) => Ok ( f) ,
@@ -808,18 +810,11 @@ where
808
810
}
809
811
}
810
812
811
- /// Validates a `call` instruction, ensuring that the function index is
812
- /// in-bounds and the right types are on the stack to call the function.
813
- fn check_call ( & mut self , function_index : u32 ) -> Result < ( ) > {
814
- let ty = self . type_of_function ( function_index) ?;
815
- self . check_call_ty ( ty)
816
- }
817
-
818
- fn check_call_type_index ( & mut self , type_index : u32 ) -> Result < ( ) > {
819
- let ty = self . func_type_at ( type_index) ?;
820
- self . check_call_ty ( ty)
821
- }
822
-
813
+ /// Checks a call-style instruction which will be invoking the function `ty`
814
+ /// specified.
815
+ ///
816
+ /// This will pop parameters from the operand stack for the function's
817
+ /// parameters and then push the results of the function on the stack.
823
818
fn check_call_ty ( & mut self , ty : & FuncType ) -> Result < ( ) > {
824
819
for & ty in ty. params ( ) . iter ( ) . rev ( ) {
825
820
debug_assert_type_indices_are_ids ( ty) ;
@@ -832,8 +827,53 @@ where
832
827
Ok ( ( ) )
833
828
}
834
829
835
- /// Validates a call to an indirect function, very similar to `check_call`.
836
- fn check_call_indirect ( & mut self , index : u32 , table_index : u32 ) -> Result < ( ) > {
830
+ /// Similar to `check_call_ty` except used for tail-call instructions.
831
+ fn check_return_call_ty ( & mut self , ty : & FuncType ) -> Result < ( ) > {
832
+ self . check_func_type_same_results ( ty) ?;
833
+ self . check_call_ty ( ty) ?;
834
+ self . check_return ( )
835
+ }
836
+
837
+ /// Checks the immediate `type_index` of a `call_ref`-style instruction
838
+ /// (also `return_call_ref`).
839
+ ///
840
+ /// This will validate that the value on the stack is a `(ref type_index)`
841
+ /// or a subtype. This will then return the corresponding function type used
842
+ /// for this call (to be used with `check_call_ty` or
843
+ /// `check_return_call_ty`).
844
+ fn check_call_ref_ty ( & mut self , type_index : u32 ) -> Result < & ' resources FuncType > {
845
+ let unpacked_index = UnpackedIndex :: Module ( type_index) ;
846
+ let mut hty = HeapType :: Concrete ( unpacked_index) ;
847
+ self . resources . check_heap_type ( & mut hty, self . offset ) ?;
848
+ // If `None` is popped then that means a "bottom" type was popped which
849
+ // is always considered equivalent to the `hty` tag.
850
+ if let Some ( rt) = self . pop_ref ( ) ? {
851
+ let expected = RefType :: new ( true , hty) . expect ( "hty should be previously validated" ) ;
852
+ let expected = ValType :: Ref ( expected) ;
853
+ if !self . resources . is_subtype ( ValType :: Ref ( rt) , expected) {
854
+ bail ! (
855
+ self . offset,
856
+ "type mismatch: funcref on stack does not match specified type" ,
857
+ ) ;
858
+ }
859
+ }
860
+ self . func_type_at ( type_index)
861
+ }
862
+
863
+ /// Validates the immediate operands of a `call_indirect` or
864
+ /// `return_call_indirect` instruction.
865
+ ///
866
+ /// This will validate that `table_index` is valid and a funcref table. It
867
+ /// will additionally pop the index argument which is used to index into the
868
+ /// table.
869
+ ///
870
+ /// The return value of this function is the function type behind
871
+ /// `type_index` which must then be passedt o `check_{call,return_call}_ty`.
872
+ fn check_call_indirect_ty (
873
+ & mut self ,
874
+ type_index : u32 ,
875
+ table_index : u32 ,
876
+ ) -> Result < & ' resources FuncType > {
837
877
let tab = self . check_table_index ( table_index) ?;
838
878
if !self
839
879
. resources
@@ -844,15 +884,8 @@ where
844
884
"indirect calls must go through a table with type <= funcref" ,
845
885
) ;
846
886
}
847
- let ty = self . func_type_at ( index) ?;
848
887
self . pop_operand ( Some ( tab. index_type ( ) ) ) ?;
849
- for ty in ty. clone ( ) . params ( ) . iter ( ) . rev ( ) {
850
- self . pop_operand ( Some ( * ty) ) ?;
851
- }
852
- for ty in ty. results ( ) {
853
- self . push_operand ( * ty) ?;
854
- }
855
- Ok ( ( ) )
888
+ self . func_type_at ( type_index)
856
889
}
857
890
858
891
/// Validates a `return` instruction, popping types from the operand
@@ -868,20 +901,6 @@ where
868
901
Ok ( ( ) )
869
902
}
870
903
871
- /// Check that the function at the given index has the same result types as
872
- /// the current function's results.
873
- fn check_func_same_results ( & self , function_index : u32 ) -> Result < ( ) > {
874
- let ty = self . type_of_function ( function_index) ?;
875
- self . check_func_type_same_results ( ty)
876
- }
877
-
878
- /// Check that the type at the given index has the same result types as the
879
- /// current function's results.
880
- fn check_func_type_index_same_results ( & self , type_index : u32 ) -> Result < ( ) > {
881
- let ty = self . func_type_at ( type_index) ?;
882
- self . check_func_type_same_results ( ty)
883
- }
884
-
885
904
/// Check that the given type has the same result types as the current
886
905
/// function's results.
887
906
fn check_func_type_same_results ( & self , callee_ty : & FuncType ) -> Result < ( ) > {
@@ -1551,47 +1570,33 @@ where
1551
1570
Ok ( ( ) )
1552
1571
}
1553
1572
fn visit_call ( & mut self , function_index : u32 ) -> Self :: Output {
1554
- self . check_call ( function_index) ?;
1573
+ let ty = self . type_of_function ( function_index) ?;
1574
+ self . check_call_ty ( ty) ?;
1555
1575
Ok ( ( ) )
1556
1576
}
1557
1577
fn visit_return_call ( & mut self , function_index : u32 ) -> Self :: Output {
1558
- self . check_call ( function_index) ?;
1559
- self . check_return ( ) ?;
1560
- self . check_func_same_results ( function_index) ?;
1578
+ let ty = self . type_of_function ( function_index) ?;
1579
+ self . check_return_call_ty ( ty) ?;
1561
1580
Ok ( ( ) )
1562
1581
}
1563
1582
fn visit_call_ref ( & mut self , type_index : u32 ) -> Self :: Output {
1564
- let unpacked_index = UnpackedIndex :: Module ( type_index) ;
1565
- let mut hty = HeapType :: Concrete ( unpacked_index) ;
1566
- self . resources . check_heap_type ( & mut hty, self . offset ) ?;
1567
- // If `None` is popped then that means a "bottom" type was popped which
1568
- // is always considered equivalent to the `hty` tag.
1569
- if let Some ( rt) = self . pop_ref ( ) ? {
1570
- let expected = RefType :: new ( true , hty) . expect ( "hty should be previously validated" ) ;
1571
- let expected = ValType :: Ref ( expected) ;
1572
- if !self . resources . is_subtype ( ValType :: Ref ( rt) , expected) {
1573
- bail ! (
1574
- self . offset,
1575
- "type mismatch: funcref on stack does not match specified type" ,
1576
- ) ;
1577
- }
1578
- }
1579
- self . check_call_type_index ( type_index)
1583
+ let ty = self . check_call_ref_ty ( type_index) ?;
1584
+ self . check_call_ty ( ty) ?;
1585
+ Ok ( ( ) )
1580
1586
}
1581
1587
fn visit_return_call_ref ( & mut self , type_index : u32 ) -> Self :: Output {
1582
- self . visit_call_ref ( type_index) ?;
1583
- self . check_return ( ) ?;
1584
- self . check_func_type_index_same_results ( type_index) ?;
1588
+ let ty = self . check_call_ref_ty ( type_index) ?;
1589
+ self . check_return_call_ty ( ty) ?;
1585
1590
Ok ( ( ) )
1586
1591
}
1587
- fn visit_call_indirect ( & mut self , index : u32 , table_index : u32 ) -> Self :: Output {
1588
- self . check_call_indirect ( index, table_index) ?;
1592
+ fn visit_call_indirect ( & mut self , type_index : u32 , table_index : u32 ) -> Self :: Output {
1593
+ let ty = self . check_call_indirect_ty ( type_index, table_index) ?;
1594
+ self . check_call_ty ( ty) ?;
1589
1595
Ok ( ( ) )
1590
1596
}
1591
1597
fn visit_return_call_indirect ( & mut self , type_index : u32 , table_index : u32 ) -> Self :: Output {
1592
- self . check_call_indirect ( type_index, table_index) ?;
1593
- self . check_return ( ) ?;
1594
- self . check_func_type_index_same_results ( type_index) ?;
1598
+ let ty = self . check_call_indirect_ty ( type_index, table_index) ?;
1599
+ self . check_return_call_ty ( ty) ?;
1595
1600
Ok ( ( ) )
1596
1601
}
1597
1602
fn visit_drop ( & mut self ) -> Self :: Output {
0 commit comments