@@ -33,129 +33,93 @@ pub fn prepare(binary: &[u8]) -> Result<Vec<MetadataEntry>, Error> {
33
33
34
34
#[ allow( dead_code) ]
35
35
#[ allow( unused_variables) ]
36
- // Checks whether a WASM module with the side table in binary format is valid.
36
+ /// Checks whether a WASM module with the side table in binary format is valid.
37
37
pub fn verify ( binary : & [ u8 ] ) -> Result < ( ) , Error > {
38
38
todo ! ( )
39
39
}
40
40
41
41
trait ValidMode : Default {
42
- type LabelBranches < ' m > : Default ;
43
-
44
- fn end_label ( expr : & mut Expr < Self > ) -> CheckResult ;
45
-
46
- fn br_label < ' m > ( expr : & mut Expr < ' _ , ' m , Self > , l : LabelIdx ) -> Result < ResultType < ' m > , Error > ;
42
+ /// List of source branches, when preparing.
43
+ ///
44
+ /// When verifying, contains at most one _target_ branch. Source branches are eagerly patched to
45
+ /// their target branch using the branch table.
46
+ type Branches < ' m > : Default + IntoIterator < Item = SideTableBranch < ' m > > ;
47
+
48
+ /// Branch table to prepare or verify.
49
+ type BranchTable < ' m > ;
50
+
51
+ /// Updates the branch table for source according to target, when preparing.
52
+ ///
53
+ /// When verifying, makes sure source is target branch.
54
+ fn stitch_branch < ' m > (
55
+ expr : & mut Expr < ' _ , ' m , Self > , source : SideTableBranch < ' m > , target : SideTableBranch < ' m > ,
56
+ ) -> CheckResult ;
57
+
58
+ /// Pushes a source branch, when preparing.
59
+ ///
60
+ /// When verifying, only push if there are no branches already. If there is one, verify that
61
+ /// it's the same.
62
+ fn push_branch < ' m > (
63
+ branches : & mut Self :: Branches < ' m > , branch : SideTableBranch < ' m > ,
64
+ ) -> CheckResult ;
65
+
66
+ /// Does nothing, when preparing.
67
+ ///
68
+ /// When verifying, patches a source branch to its target branch using the branch table.
69
+ fn patch_branch < ' m > (
70
+ table : & Self :: BranchTable < ' m > , source : SideTableBranch < ' m > ,
71
+ ) -> Result < SideTableBranch < ' m > , Error > ;
47
72
}
48
73
49
74
#[ derive( Default ) ]
50
75
struct Prepare ;
51
76
impl ValidMode for Prepare {
52
- type LabelBranches < ' m > = Vec < SideTableBranch < ' m > > ;
77
+ type Branches < ' m > = Vec < SideTableBranch < ' m > > ;
78
+ type BranchTable < ' m > = BranchTable ;
53
79
54
- fn end_label ( expr : & mut Expr < Self > ) -> CheckResult {
55
- let results_len = expr. label ( ) . type_ . results . len ( ) ;
56
- let mut target = expr. branch_target ( results_len) ;
57
- for source in core:: mem:: take ( & mut expr. label ( ) . branches ) {
58
- expr. branch_table . stitch ( source, target) ?;
59
- }
60
- let label = expr. label ( ) ;
61
- if let LabelKind :: If ( source) = label. kind {
62
- check ( label. type_ . params == label. type_ . results ) ?;
63
- // SAFETY: This function is only called after parsing an End instruction.
64
- target. parser = offset_front ( target. parser , -1 ) ;
65
- expr. branch_table . stitch ( source, target) ?;
66
- }
67
- let results = expr. label ( ) . type_ . results ;
68
- expr. pops ( results) ?;
69
- check ( expr. labels . pop ( ) . unwrap ( ) . stack . is_empty ( ) ) ?;
70
- if !expr. labels . is_empty ( ) {
71
- expr. pushs ( results) ;
72
- }
73
- Ok ( ( ) )
80
+ fn stitch_branch < ' m > (
81
+ expr : & mut Expr < ' _ , ' m , Self > , source : SideTableBranch < ' m > , target : SideTableBranch < ' m > ,
82
+ ) -> CheckResult {
83
+ expr. branch_table . stitch ( source, target)
74
84
}
75
85
76
- fn br_label < ' m > ( expr : & mut Expr < ' _ , ' m , Self > , l : LabelIdx ) -> Result < ResultType < ' m > , Error > {
77
- let l = l as usize ;
78
- let n = expr. labels . len ( ) ;
79
- check ( l < n) ?;
80
- let source = expr. branch_source ( ) ;
81
- let label = & mut expr. labels [ n - l - 1 ] ;
82
- Ok ( match label. kind {
83
- LabelKind :: Block | LabelKind :: If ( _) => {
84
- label. branches . push ( source) ;
85
- label. type_ . results
86
- }
87
- LabelKind :: Loop ( target) => {
88
- expr. branch_table . stitch ( source, target) ?;
89
- label. type_ . params
90
- }
91
- } )
86
+ fn push_branch < ' m > (
87
+ branches : & mut Self :: Branches < ' m > , branch : SideTableBranch < ' m > ,
88
+ ) -> CheckResult {
89
+ Ok ( branches. push ( branch) )
90
+ }
91
+
92
+ fn patch_branch < ' m > (
93
+ _: & Self :: BranchTable < ' m > , source : SideTableBranch < ' m > ,
94
+ ) -> Result < SideTableBranch < ' m > , Error > {
95
+ Ok ( source)
92
96
}
93
97
}
94
98
95
99
#[ derive( Default ) ]
96
100
struct Verify ;
97
101
impl ValidMode for Verify {
98
- type LabelBranches < ' m > = Option < SideTableBranch < ' m > > ;
99
-
100
- #[ allow( dead_code) ]
101
- fn end_label ( expr : & mut Expr < Self > ) -> CheckResult {
102
- let results_len = expr. label ( ) . type_ . results . len ( ) ;
103
- let mut target = expr. branch_target ( results_len) ;
104
- let label = expr. label ( ) ;
105
- if let LabelKind :: If ( _) = label. kind {
106
- check ( label. type_ . params == label. type_ . results ) ?;
107
- // SAFETY: This function is only called after parsing an End instruction.
108
- target. parser = offset_front ( target. parser , -1 ) ;
109
- }
110
- if expr. label ( ) . branches . is_none_or ( |x| x != target) {
111
- #[ cfg( feature = "debug" ) ]
112
- eprintln ! ( "The side table in the custom section is wrong." ) ;
113
- Err ( unsupported ( if_debug ! ( Unsupported :: SideTable ) ) ) ?
114
- }
115
- let results = expr. label ( ) . type_ . results ;
116
- expr. pops ( results) ?;
117
- check ( expr. labels . pop ( ) . unwrap ( ) . stack . is_empty ( ) ) ?;
118
- if !expr. labels . is_empty ( ) {
119
- expr. pushs ( results) ;
120
- }
121
- Ok ( ( ) )
102
+ type Branches < ' m > = Option < SideTableBranch < ' m > > ;
103
+ type BranchTable < ' m > = BranchTableView < ' m > ;
104
+
105
+ fn stitch_branch < ' m > (
106
+ _: & mut Expr < ' _ , ' m , Self > , source : SideTableBranch < ' m > , target : SideTableBranch < ' m > ,
107
+ ) -> CheckResult {
108
+ check ( source == target)
122
109
}
123
110
124
- #[ allow( dead_code) ]
125
- fn br_label < ' m > ( expr : & mut Expr < ' _ , ' m , Self > , l : LabelIdx ) -> Result < ResultType < ' m > , Error > {
126
- let l = l as usize ;
127
- let n = expr. labels . len ( ) ;
128
- check ( l < n) ?;
129
- let source = expr. branch_source ( ) ;
130
- // Should be `mut`.
131
- let expected_target = source;
132
- // expected_target.parser += delta_ip;
133
- // expected_target.branch_table += delta_stp;
134
- let label = & mut expr. labels [ n - l - 1 ] ;
135
- Ok ( match label. kind {
136
- LabelKind :: Block | LabelKind :: If ( _) => {
137
- if !label. branches . replace ( expected_target) . is_none_or ( |x| x == expected_target) {
138
- #[ cfg( feature = "debug" ) ]
139
- eprintln ! (
140
- "The branch table entries in the custom section are consistent with each \
141
- other."
142
- ) ;
143
- Err ( unsupported ( if_debug ! ( Unsupported :: SideTable ) ) ) ?
144
- }
145
- label. branches = Some ( expected_target) ;
146
- label. type_ . results
147
- }
148
- LabelKind :: Loop ( target) => {
149
- if expected_target != target {
150
- #[ cfg( feature = "debug" ) ]
151
- eprintln ! ( "The branch table entries for loop in the custom section are wrong." ) ;
152
- Err ( unsupported ( if_debug ! ( Unsupported :: SideTable ) ) ) ?
153
- }
154
- // expr.branch_table[source.branch_table] = the branch table entry from the custom
155
- // section;
156
- label. type_ . params
157
- }
158
- } )
111
+ fn push_branch < ' m > (
112
+ branches : & mut Self :: Branches < ' m > , branch : SideTableBranch < ' m > ,
113
+ ) -> CheckResult {
114
+ check ( branches. replace ( branch) . is_none_or ( |x| x == branch) )
115
+ }
116
+
117
+ fn patch_branch < ' m > (
118
+ table : & Self :: BranchTable < ' m > , source : SideTableBranch < ' m > ,
119
+ ) -> Result < SideTableBranch < ' m > , Error > {
120
+ // source.parser += delta_ip;
121
+ // source.branch_table += delta_stp;
122
+ todo ! ( )
159
123
}
160
124
}
161
125
@@ -549,7 +513,7 @@ struct Expr<'a, 'm, M: ValidMode> {
549
513
is_body : bool ,
550
514
locals : Vec < ValType > ,
551
515
labels : Vec < Label < ' m , M > > ,
552
- branch_table : BranchTable ,
516
+ branch_table : M :: BranchTable < ' m > ,
553
517
}
554
518
555
519
#[ derive( Default ) ]
@@ -620,7 +584,7 @@ impl BranchTable {
620
584
}
621
585
}
622
586
623
- #[ derive( Debug , Copy , Clone , PartialEq ) ]
587
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
624
588
struct SideTableBranch < ' m > {
625
589
parser : & ' m [ u8 ] ,
626
590
branch_table : usize ,
@@ -636,7 +600,7 @@ struct Label<'m, M: ValidMode> {
636
600
/// Whether the bottom of the stack is polymorphic.
637
601
polymorphic : bool ,
638
602
stack : Vec < OpdType > ,
639
- branches : M :: LabelBranches < ' m > ,
603
+ branches : M :: Branches < ' m > ,
640
604
/// Total stack length of the labels in this function up to this label.
641
605
prev_stack : usize ,
642
606
}
@@ -741,7 +705,7 @@ impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> {
741
705
let result = self . label ( ) . type_ . results . len ( ) ;
742
706
let mut target = self . branch_target ( result) ;
743
707
target. branch_table += 1 ;
744
- self . branch_table . stitch ( source, target) ?
708
+ M :: stitch_branch ( self , source, target) ?;
745
709
}
746
710
_ => Err ( invalid ( ) ) ?,
747
711
}
@@ -1000,11 +964,45 @@ impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> {
1000
964
}
1001
965
1002
966
fn end_label ( & mut self ) -> CheckResult {
1003
- M :: end_label ( self )
967
+ let results_len = self . label ( ) . type_ . results . len ( ) ;
968
+ let mut target = self . branch_target ( results_len) ;
969
+ for source in core:: mem:: take ( & mut self . label ( ) . branches ) {
970
+ M :: stitch_branch ( self , source, target) ?;
971
+ }
972
+ let label = self . label ( ) ;
973
+ if let LabelKind :: If ( source) = label. kind {
974
+ check ( label. type_ . params == label. type_ . results ) ?;
975
+ // SAFETY: This function is only called after parsing an End instruction.
976
+ target. parser = offset_front ( target. parser , -1 ) ;
977
+ M :: stitch_branch ( self , source, target) ?;
978
+ }
979
+ let results = self . label ( ) . type_ . results ;
980
+ self . pops ( results) ?;
981
+ check ( self . labels . pop ( ) . unwrap ( ) . stack . is_empty ( ) ) ?;
982
+ if !self . labels . is_empty ( ) {
983
+ self . pushs ( results) ;
984
+ }
985
+ Ok ( ( ) )
1004
986
}
1005
987
1006
988
fn br_label ( & mut self , l : LabelIdx ) -> Result < ResultType < ' m > , Error > {
1007
- M :: br_label ( self , l)
989
+ let l = l as usize ;
990
+ let n = self . labels . len ( ) ;
991
+ check ( l < n) ?;
992
+ let source = self . branch_source ( ) ;
993
+ let source = M :: patch_branch ( & self . branch_table , source) ?;
994
+ let label = & mut self . labels [ n - l - 1 ] ;
995
+ Ok ( match label. kind {
996
+ LabelKind :: Block | LabelKind :: If ( _) => {
997
+ M :: push_branch ( & mut label. branches , source) ?;
998
+ label. type_ . results
999
+ }
1000
+ LabelKind :: Loop ( target) => {
1001
+ let params = label. type_ . params ;
1002
+ M :: stitch_branch ( self , source, target) ?;
1003
+ params
1004
+ }
1005
+ } )
1008
1006
}
1009
1007
1010
1008
fn branch_source ( & mut self ) -> SideTableBranch < ' m > {
0 commit comments