@@ -103,6 +103,30 @@ impl CodeSection {
103103 self . num_added += 1 ;
104104 self
105105 }
106+
107+ /// Parses the input `section` given from the `wasmparser` crate and adds
108+ /// all the code to this section.
109+ #[ cfg( feature = "wasmparser" ) ]
110+ pub fn parse_section (
111+ & mut self ,
112+ section : wasmparser:: CodeSectionReader < ' _ > ,
113+ ) -> wasmparser:: Result < & mut Self > {
114+ for code in section {
115+ self . parse ( code?) ?;
116+ }
117+ Ok ( self )
118+ }
119+
120+ /// Parses a single [`wasmparser::Code`] and adds it to this section.
121+ #[ cfg( feature = "wasmparser" ) ]
122+ pub fn parse ( & mut self , func : wasmparser:: FunctionBody < ' _ > ) -> wasmparser:: Result < & mut Self > {
123+ let mut f = Function :: new_parsed_locals ( & func) ?;
124+ let mut reader = func. get_operators_reader ( ) ?;
125+ while !reader. eof ( ) {
126+ f. parse ( & mut reader) ?;
127+ }
128+ Ok ( self . function ( & f) )
129+ }
106130}
107131
108132impl Encode for CodeSection {
@@ -214,6 +238,18 @@ impl Function {
214238 Function :: new ( locals_collected)
215239 }
216240
241+ /// Create a new [`Function`] by parsing the locals declarations from the
242+ /// provided [`wasmparser::FunctionBody`].
243+ #[ cfg( feature = "wasmparser" ) ]
244+ pub fn new_parsed_locals ( func : & wasmparser:: FunctionBody < ' _ > ) -> wasmparser:: Result < Self > {
245+ let mut locals = Vec :: new ( ) ;
246+ for pair in func. get_locals_reader ( ) ? {
247+ let ( cnt, ty) = pair?;
248+ locals. push ( ( cnt, ty. try_into ( ) . unwrap ( ) ) ) ;
249+ }
250+ Ok ( Function :: new ( locals) )
251+ }
252+
217253 /// Write an instruction into this function body.
218254 pub fn instruction ( & mut self , instruction : & Instruction ) -> & mut Self {
219255 instruction. encode ( & mut self . bytes ) ;
@@ -237,6 +273,15 @@ impl Function {
237273 pub fn byte_len ( & self ) -> usize {
238274 self . bytes . len ( )
239275 }
276+
277+ /// Parses a single instruction from `reader` and adds it to `self`.
278+ #[ cfg( feature = "wasmparser" ) ]
279+ pub fn parse (
280+ & mut self ,
281+ reader : & mut wasmparser:: OperatorsReader < ' _ > ,
282+ ) -> wasmparser:: Result < & mut Self > {
283+ Ok ( self . instruction ( & reader. read ( ) ?. try_into ( ) . unwrap ( ) ) )
284+ }
240285}
241286
242287impl Encode for Function {
@@ -276,6 +321,17 @@ impl Encode for MemArg {
276321 }
277322}
278323
324+ #[ cfg( feature = "wasmparser" ) ]
325+ impl From < wasmparser:: MemArg > for MemArg {
326+ fn from ( arg : wasmparser:: MemArg ) -> MemArg {
327+ MemArg {
328+ offset : arg. offset ,
329+ align : arg. align . into ( ) ,
330+ memory_index : arg. memory ,
331+ }
332+ }
333+ }
334+
279335/// The memory ordering for atomic instructions.
280336///
281337/// For an in-depth explanation of memory orderings, see the C++ documentation
@@ -304,6 +360,16 @@ impl Encode for Ordering {
304360 }
305361}
306362
363+ #[ cfg( feature = "wasmparser" ) ]
364+ impl From < wasmparser:: Ordering > for Ordering {
365+ fn from ( arg : wasmparser:: Ordering ) -> Ordering {
366+ match arg {
367+ wasmparser:: Ordering :: SeqCst => Ordering :: SeqCst ,
368+ wasmparser:: Ordering :: AcqRel => Ordering :: AcqRel ,
369+ }
370+ }
371+ }
372+
307373/// Describe an unchecked SIMD lane index.
308374pub type Lane = u8 ;
309375
@@ -328,6 +394,18 @@ impl Encode for BlockType {
328394 }
329395}
330396
397+ #[ cfg( feature = "wasmparser" ) ]
398+ impl TryFrom < wasmparser:: BlockType > for BlockType {
399+ type Error = ( ) ;
400+ fn try_from ( arg : wasmparser:: BlockType ) -> Result < BlockType , ( ) > {
401+ match arg {
402+ wasmparser:: BlockType :: Empty => Ok ( BlockType :: Empty ) ,
403+ wasmparser:: BlockType :: FuncType ( n) => Ok ( BlockType :: FunctionType ( n) ) ,
404+ wasmparser:: BlockType :: Type ( t) => Ok ( BlockType :: Result ( t. try_into ( ) ?) ) ,
405+ }
406+ }
407+ }
408+
331409/// WebAssembly instructions.
332410#[ derive( Clone , Debug ) ]
333411#[ non_exhaustive]
@@ -350,14 +428,14 @@ pub enum Instruction<'a> {
350428 Call ( u32 ) ,
351429 CallRef ( u32 ) ,
352430 CallIndirect {
353- ty : u32 ,
354- table : u32 ,
431+ type_index : u32 ,
432+ table_index : u32 ,
355433 } ,
356434 ReturnCallRef ( u32 ) ,
357435 ReturnCall ( u32 ) ,
358436 ReturnCallIndirect {
359- ty : u32 ,
360- table : u32 ,
437+ type_index : u32 ,
438+ table_index : u32 ,
361439 } ,
362440 TryTable ( BlockType , Cow < ' a , [ Catch ] > ) ,
363441 Throw ( u32 ) ,
@@ -1119,10 +1197,13 @@ impl Encode for Instruction<'_> {
11191197 sink. push ( 0x14 ) ;
11201198 ty. encode ( sink) ;
11211199 }
1122- Instruction :: CallIndirect { ty, table } => {
1200+ Instruction :: CallIndirect {
1201+ type_index,
1202+ table_index,
1203+ } => {
11231204 sink. push ( 0x11 ) ;
1124- ty . encode ( sink) ;
1125- table . encode ( sink) ;
1205+ type_index . encode ( sink) ;
1206+ table_index . encode ( sink) ;
11261207 }
11271208 Instruction :: ReturnCallRef ( ty) => {
11281209 sink. push ( 0x15 ) ;
@@ -1133,10 +1214,13 @@ impl Encode for Instruction<'_> {
11331214 sink. push ( 0x12 ) ;
11341215 f. encode ( sink) ;
11351216 }
1136- Instruction :: ReturnCallIndirect { ty, table } => {
1217+ Instruction :: ReturnCallIndirect {
1218+ type_index,
1219+ table_index,
1220+ } => {
11371221 sink. push ( 0x13 ) ;
1138- ty . encode ( sink) ;
1139- table . encode ( sink) ;
1222+ type_index . encode ( sink) ;
1223+ table_index . encode ( sink) ;
11401224 }
11411225 Instruction :: Delegate ( l) => {
11421226 sink. push ( 0x18 ) ;
@@ -3278,6 +3362,64 @@ impl Encode for Instruction<'_> {
32783362 }
32793363}
32803364
3365+ #[ cfg( feature = "wasmparser" ) ]
3366+ impl TryFrom < wasmparser:: Operator < ' _ > > for Instruction < ' _ > {
3367+ type Error = ( ) ;
3368+
3369+ fn try_from ( arg : wasmparser:: Operator < ' _ > ) -> Result < Self , ( ) > {
3370+ use Instruction :: * ;
3371+
3372+ macro_rules! define_match {
3373+ ( $( @$p: ident $op: ident $( { $( $arg: ident: $argty: ty) ,* } ) ? => $visit: ident) * ) => {
3374+ match arg {
3375+ $(
3376+ wasmparser:: Operator :: $op $( { $( $arg) ,* } ) ? => {
3377+ $(
3378+ $( let $arg = define_match!( map $arg $arg) ; ) *
3379+ ) ?
3380+ Ok ( define_match!( mk $op $( $( $arg) * ) ?) )
3381+ }
3382+ ) *
3383+ }
3384+ } ;
3385+
3386+ // No-payload instructions are named the same in wasmparser as they are in
3387+ // wasm-encoder
3388+ ( mk $op: ident) => ( $op) ;
3389+
3390+ // Instructions which need "special care" to map from wasmparser to
3391+ // wasm-encoder
3392+ ( mk BrTable $arg: ident) => ( { BrTable ( $arg. 0 , $arg. 1 ) } ) ;
3393+ ( mk TryTable $arg: ident) => ( { TryTable ( $arg. 0 , $arg. 1 ) } ) ;
3394+
3395+ // Catch-all for the translation of one payload argument which is typically
3396+ // represented as a tuple-enum in wasm-encoder.
3397+ ( mk $op: ident $arg: ident) => ( $op( $arg) ) ;
3398+
3399+ // Catch-all of everything else where the wasmparser fields are simply
3400+ // translated to wasm-encoder fields.
3401+ ( mk $op: ident $( $arg: ident) * ) => ( $op { $( $arg) ,* } ) ;
3402+
3403+ // Special-case BrTable/TryTable conversion of arguments.
3404+ ( map $arg: ident targets) => ( (
3405+ $arg. targets( ) . map( |i| i. unwrap( ) ) . collect:: <Vec <_>>( ) . into( ) ,
3406+ $arg. default ( ) ,
3407+ ) ) ;
3408+ ( map $arg: ident try_table) => ( (
3409+ $arg. ty. try_into( ) . unwrap( ) ,
3410+ $arg. catches. into_iter( ) . map( |i| i. into( ) ) . collect:: <Vec <_>>( ) . into( ) ,
3411+ ) ) ;
3412+
3413+ // Everything else is converted with `TryFrom`/`From`. Note that the
3414+ // fallibility here has to do with how indexes are represented in
3415+ // `wasmparser` which we know when reading directly we'll never hit the
3416+ // erroneous cases here, hence the unwrap.
3417+ ( map $arg: ident $other: ident) => { $other. try_into( ) . unwrap( ) } ;
3418+ }
3419+ wasmparser:: for_each_operator!( define_match)
3420+ }
3421+ }
3422+
32813423#[ derive( Clone , Debug ) ]
32823424#[ allow( missing_docs) ]
32833425pub enum Catch {
@@ -3312,6 +3454,18 @@ impl Encode for Catch {
33123454 }
33133455}
33143456
3457+ #[ cfg( feature = "wasmparser" ) ]
3458+ impl From < wasmparser:: Catch > for Catch {
3459+ fn from ( arg : wasmparser:: Catch ) -> Catch {
3460+ match arg {
3461+ wasmparser:: Catch :: One { tag, label } => Catch :: One { tag, label } ,
3462+ wasmparser:: Catch :: OneRef { tag, label } => Catch :: OneRef { tag, label } ,
3463+ wasmparser:: Catch :: All { label } => Catch :: All { label } ,
3464+ wasmparser:: Catch :: AllRef { label } => Catch :: AllRef { label } ,
3465+ }
3466+ }
3467+ }
3468+
33153469/// A constant expression.
33163470///
33173471/// Usable in contexts such as offsets or initializers.
@@ -3494,6 +3648,13 @@ pub enum ConstExprConversionError {
34943648 CanonicalizedTypeReference ,
34953649}
34963650
3651+ #[ cfg( feature = "wasmparser" ) ]
3652+ impl From < wasmparser:: BinaryReaderError > for ConstExprConversionError {
3653+ fn from ( err : wasmparser:: BinaryReaderError ) -> ConstExprConversionError {
3654+ ConstExprConversionError :: ParseError ( err)
3655+ }
3656+ }
3657+
34973658#[ cfg( feature = "wasmparser" ) ]
34983659impl std:: fmt:: Display for ConstExprConversionError {
34993660 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
0 commit comments