Skip to content

Commit a55438b

Browse files
authored
Migrate more encoding to wasm-encoder (bytecodealliance#1823)
* Migrate more encoding to wasm-encoder Use `wasm_encoder::{CodeSection, Function}` and additionally replace some impls of the `Encode` trait in wast with the `Encode` trait in wasm-encoder. * Remove unnecessary clone
1 parent 0241ea3 commit a55438b

File tree

1 file changed

+28
-121
lines changed

1 file changed

+28
-121
lines changed

crates/wast/src/core/binary.rs

Lines changed: 28 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,8 @@ impl Encoder<'_> {
256256

257257
if !list.is_empty() {
258258
let mut branch_hints = wasm_encoder::BranchHints::new();
259-
let mut code_section = Vec::new();
259+
let mut code_section = wasm_encoder::CodeSection::new();
260260

261-
list.len().encode(&mut code_section);
262261
for func in list.iter() {
263262
let hints = func.encode(&mut code_section, dwarf.as_deref_mut());
264263
if !hints.is_empty() {
@@ -274,13 +273,10 @@ impl Encoder<'_> {
274273
}
275274

276275
// Finally, insert the Code section from the tmp buffer
277-
self.wasm.section(&wasm_encoder::RawSection {
278-
id: wasm_encoder::SectionId::Code as u8,
279-
data: &code_section,
280-
});
276+
self.wasm.section(&code_section);
281277

282278
if let Some(dwarf) = &mut dwarf {
283-
dwarf.set_code_section_size(code_section.len());
279+
dwarf.set_code_section_size(code_section.byte_len());
284280
}
285281
}
286282
self.custom_sections(CustomPlace::After(CustomPlaceAnchor::Code));
@@ -449,90 +445,13 @@ impl Encode for Option<Id<'_>> {
449445

450446
impl<'a> Encode for ValType<'a> {
451447
fn encode(&self, e: &mut Vec<u8>) {
452-
match self {
453-
ValType::I32 => e.push(0x7f),
454-
ValType::I64 => e.push(0x7e),
455-
ValType::F32 => e.push(0x7d),
456-
ValType::F64 => e.push(0x7c),
457-
ValType::V128 => e.push(0x7b),
458-
ValType::Ref(ty) => {
459-
ty.encode(e);
460-
}
461-
}
448+
wasm_encoder::Encode::encode(&wasm_encoder::ValType::from(*self), e)
462449
}
463450
}
464451

465452
impl<'a> Encode for HeapType<'a> {
466453
fn encode(&self, e: &mut Vec<u8>) {
467-
match self {
468-
HeapType::Abstract { shared, ty } => {
469-
if *shared {
470-
e.push(0x65);
471-
}
472-
ty.encode(e)
473-
}
474-
// Note that this is encoded as a signed leb128 so be sure to cast
475-
// to an i64 first
476-
HeapType::Concrete(Index::Num(n, _)) => i64::from(*n).encode(e),
477-
HeapType::Concrete(Index::Id(n)) => {
478-
panic!("unresolved index in emission: {:?}", n)
479-
}
480-
}
481-
}
482-
}
483-
484-
impl<'a> Encode for AbstractHeapType {
485-
fn encode(&self, e: &mut Vec<u8>) {
486-
use AbstractHeapType::*;
487-
match self {
488-
Func => e.push(0x70),
489-
Extern => e.push(0x6f),
490-
Cont => e.push(0x68),
491-
Exn => e.push(0x69),
492-
Any => e.push(0x6e),
493-
Eq => e.push(0x6d),
494-
Struct => e.push(0x6b),
495-
Array => e.push(0x6a),
496-
I31 => e.push(0x6c),
497-
NoFunc => e.push(0x73),
498-
NoExtern => e.push(0x72),
499-
NoExn => e.push(0x74),
500-
NoCont => e.push(0x75),
501-
None => e.push(0x71),
502-
}
503-
}
504-
}
505-
506-
impl<'a> Encode for RefType<'a> {
507-
fn encode(&self, e: &mut Vec<u8>) {
508-
match self {
509-
// Binary abbreviations (i.e., short form), for when the ref is
510-
// nullable.
511-
RefType {
512-
nullable: true,
513-
heap: heap @ HeapType::Abstract { .. },
514-
} => {
515-
heap.encode(e);
516-
}
517-
518-
// Generic 'ref null <heaptype>' encoding (i.e., long form).
519-
RefType {
520-
nullable: true,
521-
heap,
522-
} => {
523-
e.push(0x63);
524-
heap.encode(e);
525-
}
526-
527-
// Generic 'ref <heaptype>' encoding.
528-
RefType {
529-
nullable: false,
530-
heap,
531-
} => {
532-
e.push(0x64);
533-
heap.encode(e);
534-
}
535-
}
454+
wasm_encoder::Encode::encode(&wasm_encoder::HeapType::from(*self), e)
536455
}
537456
}
538457

@@ -672,7 +591,7 @@ impl SectionItem for Table<'_> {
672591
ty,
673592
init_expr: Some(init_expr),
674593
} => {
675-
section.table_with_init(ty.to_table_type(), &init_expr.to_const_expr(None));
594+
section.table_with_init(ty.to_table_type(), &init_expr.to_const_expr());
676595
}
677596
_ => panic!("TableKind should be normal during encoding"),
678597
}
@@ -701,7 +620,7 @@ impl SectionItem for Global<'_> {
701620
fn encode(&self, section: &mut wasm_encoder::GlobalSection) {
702621
assert!(self.exports.names.is_empty());
703622
let init = match &self.kind {
704-
GlobalKind::Inline(expr) => expr.to_const_expr(None),
623+
GlobalKind::Inline(expr) => expr.to_const_expr(),
705624
_ => panic!("GlobalKind should be inline during encoding"),
706625
};
707626
section.global(self.ty.to_global_type(), &init);
@@ -730,14 +649,14 @@ impl SectionItem for Elem<'_> {
730649
}
731650
ElemPayload::Exprs { exprs, ty } => Elements::Expressions(
732651
(*ty).into(),
733-
Cow::Owned(exprs.iter().map(|e| e.to_const_expr(None)).collect()),
652+
Cow::Owned(exprs.iter().map(|e| e.to_const_expr()).collect()),
734653
),
735654
};
736655
match &self.kind {
737656
ElemKind::Active { table, offset } => {
738657
section.active(
739658
table.map(|t| t.unwrap_u32()),
740-
&offset.to_const_expr(None),
659+
&offset.to_const_expr(),
741660
elements,
742661
);
743662
}
@@ -765,7 +684,7 @@ impl SectionItem for Data<'_> {
765684
section.passive(data);
766685
}
767686
DataKind::Active { memory, offset } => {
768-
section.active(memory.unwrap_u32(), &offset.to_const_expr(None), data);
687+
section.active(memory.unwrap_u32(), &offset.to_const_expr(), data);
769688
}
770689
}
771690
}
@@ -779,7 +698,7 @@ impl Func<'_> {
779698
/// for each instruction.
780699
fn encode(
781700
&self,
782-
e: &mut Vec<u8>,
701+
section: &mut wasm_encoder::CodeSection,
783702
mut dwarf: Option<&mut dwarf::Dwarf>,
784703
) -> Vec<wasm_encoder::BranchHint> {
785704
assert!(self.exports.names.is_empty());
@@ -799,55 +718,41 @@ impl Func<'_> {
799718
// Encode the function into a temporary vector because functions are
800719
// prefixed with their length. The temporary vector, when encoded,
801720
// encodes its length first then the body.
802-
let mut tmp = Vec::new();
803-
locals.encode(&mut tmp);
804-
let branch_hints = expr.encode(&mut tmp, dwarf.as_deref_mut());
805-
tmp.encode(e);
721+
let mut func =
722+
wasm_encoder::Function::new_with_locals_types(locals.iter().map(|t| t.ty.into()));
723+
let branch_hints = expr.encode(&mut func, dwarf.as_deref_mut());
724+
let func_size = func.byte_len();
725+
section.function(&func);
806726

807727
if let Some(dwarf) = &mut dwarf {
808-
dwarf.end_func(tmp.len(), e.len());
728+
dwarf.end_func(func_size, section.byte_len());
809729
}
810730

811731
branch_hints
812732
}
813733
}
814734

815-
impl Encode for Box<[Local<'_>]> {
816-
fn encode(&self, e: &mut Vec<u8>) {
817-
let mut locals_compressed = Vec::<(u32, ValType)>::new();
818-
for local in self.iter() {
819-
if let Some((cnt, prev)) = locals_compressed.last_mut() {
820-
if *prev == local.ty {
821-
*cnt += 1;
822-
continue;
823-
}
824-
}
825-
locals_compressed.push((1, local.ty));
826-
}
827-
locals_compressed.encode(e);
828-
}
829-
}
830-
831735
impl Expression<'_> {
832736
/// Encodes this expression into `e` and optionally tracks debugging
833737
/// information for each instruction in `dwarf`.
834738
///
835739
/// Returns all branch hints, if any, found while parsing this function.
836740
fn encode(
837741
&self,
838-
e: &mut Vec<u8>,
742+
func: &mut wasm_encoder::Function,
839743
mut dwarf: Option<&mut dwarf::Dwarf>,
840744
) -> Vec<wasm_encoder::BranchHint> {
841745
let mut hints = Vec::with_capacity(self.branch_hints.len());
842746
let mut next_hint = self.branch_hints.iter().peekable();
747+
let mut tmp = Vec::new();
843748

844749
for (i, instr) in self.instrs.iter().enumerate() {
845750
// Branch hints are stored in order of increasing `instr_index` so
846751
// check to see if the next branch hint matches this instruction's
847752
// index.
848753
if let Some(hint) = next_hint.next_if(|h| h.instr_index == i) {
849754
hints.push(wasm_encoder::BranchHint {
850-
branch_func_offset: u32::try_from(e.len()).unwrap(),
755+
branch_func_offset: u32::try_from(func.byte_len() + tmp.len()).unwrap(),
851756
branch_hint_value: hint.value,
852757
});
853758
}
@@ -856,22 +761,24 @@ impl Expression<'_> {
856761
// and source location.
857762
if let Some(dwarf) = &mut dwarf {
858763
if let Some(span) = self.instr_spans.as_ref().map(|s| s[i]) {
859-
dwarf.instr(e.len(), span);
764+
dwarf.instr(func.byte_len() + tmp.len(), span);
860765
}
861766
}
862767

863768
// Finally emit the instruction and move to the next.
864-
instr.encode(e);
769+
instr.encode(&mut tmp);
865770
}
866-
e.push(0x0b);
771+
func.raw(tmp.iter().copied());
772+
func.instruction(&wasm_encoder::Instruction::End);
867773

868774
hints
869775
}
870776

871-
fn to_const_expr(&self, dwarf: Option<&mut dwarf::Dwarf>) -> wasm_encoder::ConstExpr {
777+
fn to_const_expr(&self) -> wasm_encoder::ConstExpr {
872778
let mut tmp = Vec::new();
873-
self.encode(&mut tmp, dwarf);
874-
tmp.pop(); // remove trailing 0x0b byte which wasm-encoder doesn't want
779+
for instr in self.instrs.iter() {
780+
instr.encode(&mut tmp);
781+
}
875782
wasm_encoder::ConstExpr::raw(tmp)
876783
}
877784
}

0 commit comments

Comments
 (0)