summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasm-encoder/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/wasm-encoder/src
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wasm-encoder/src')
-rw-r--r--third_party/rust/wasm-encoder/src/component.rs160
-rw-r--r--third_party/rust/wasm-encoder/src/component/aliases.rs160
-rw-r--r--third_party/rust/wasm-encoder/src/component/canonicals.rs133
-rw-r--r--third_party/rust/wasm-encoder/src/component/components.rs29
-rw-r--r--third_party/rust/wasm-encoder/src/component/exports.rs125
-rw-r--r--third_party/rust/wasm-encoder/src/component/imports.rs151
-rw-r--r--third_party/rust/wasm-encoder/src/component/instances.rs199
-rw-r--r--third_party/rust/wasm-encoder/src/component/modules.rs29
-rw-r--r--third_party/rust/wasm-encoder/src/component/names.rs147
-rw-r--r--third_party/rust/wasm-encoder/src/component/start.rs52
-rw-r--r--third_party/rust/wasm-encoder/src/component/types.rs736
-rw-r--r--third_party/rust/wasm-encoder/src/core.rs166
-rw-r--r--third_party/rust/wasm-encoder/src/core/code.rs2894
-rw-r--r--third_party/rust/wasm-encoder/src/core/custom.rs53
-rw-r--r--third_party/rust/wasm-encoder/src/core/data.rs185
-rw-r--r--third_party/rust/wasm-encoder/src/core/elements.rs227
-rw-r--r--third_party/rust/wasm-encoder/src/core/exports.rs85
-rw-r--r--third_party/rust/wasm-encoder/src/core/functions.rs63
-rw-r--r--third_party/rust/wasm-encoder/src/core/globals.rs90
-rw-r--r--third_party/rust/wasm-encoder/src/core/imports.rs142
-rw-r--r--third_party/rust/wasm-encoder/src/core/linking.rs261
-rw-r--r--third_party/rust/wasm-encoder/src/core/memories.rs99
-rw-r--r--third_party/rust/wasm-encoder/src/core/names.rs263
-rw-r--r--third_party/rust/wasm-encoder/src/core/producers.rs178
-rw-r--r--third_party/rust/wasm-encoder/src/core/start.rs39
-rw-r--r--third_party/rust/wasm-encoder/src/core/tables.rs104
-rw-r--r--third_party/rust/wasm-encoder/src/core/tags.rs85
-rw-r--r--third_party/rust/wasm-encoder/src/core/types.rs191
-rw-r--r--third_party/rust/wasm-encoder/src/lib.rs188
-rw-r--r--third_party/rust/wasm-encoder/src/raw.rs30
30 files changed, 7264 insertions, 0 deletions
diff --git a/third_party/rust/wasm-encoder/src/component.rs b/third_party/rust/wasm-encoder/src/component.rs
new file mode 100644
index 0000000000..5f92a91f77
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component.rs
@@ -0,0 +1,160 @@
+mod aliases;
+mod canonicals;
+mod components;
+mod exports;
+mod imports;
+mod instances;
+mod modules;
+mod names;
+mod start;
+mod types;
+
+pub use self::aliases::*;
+pub use self::canonicals::*;
+pub use self::components::*;
+pub use self::exports::*;
+pub use self::imports::*;
+pub use self::instances::*;
+pub use self::modules::*;
+pub use self::names::*;
+pub use self::start::*;
+pub use self::types::*;
+
+use crate::{CustomSection, Encode, ProducersSection};
+
+// Core sorts extended by the component model
+const CORE_TYPE_SORT: u8 = 0x10;
+const CORE_MODULE_SORT: u8 = 0x11;
+const CORE_INSTANCE_SORT: u8 = 0x12;
+
+const CORE_SORT: u8 = 0x00;
+const FUNCTION_SORT: u8 = 0x01;
+const VALUE_SORT: u8 = 0x02;
+const TYPE_SORT: u8 = 0x03;
+const COMPONENT_SORT: u8 = 0x04;
+const INSTANCE_SORT: u8 = 0x05;
+
+/// A WebAssembly component section.
+///
+/// Various builders defined in this crate already implement this trait, but you
+/// can also implement it yourself for your own custom section builders, or use
+/// `RawSection` to use a bunch of raw bytes as a section.
+pub trait ComponentSection: Encode {
+ /// Gets the section identifier for this section.
+ fn id(&self) -> u8;
+
+ /// Appends this section to the specified destination list of bytes.
+ fn append_to_component(&self, dst: &mut Vec<u8>) {
+ dst.push(self.id());
+ self.encode(dst);
+ }
+}
+
+/// Known section identifiers of WebAssembly components.
+///
+/// These sections are supported by the component model proposal.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+#[repr(u8)]
+pub enum ComponentSectionId {
+ /// The section is a core custom section.
+ CoreCustom = 0,
+ /// The section is a core module section.
+ CoreModule = 1,
+ /// The section is a core instance section.
+ CoreInstance = 2,
+ /// The section is a core type section.
+ CoreType = 3,
+ /// The section is a component section.
+ Component = 4,
+ /// The section is an instance section.
+ Instance = 5,
+ /// The section is an alias section.
+ Alias = 6,
+ /// The section is a type section.
+ Type = 7,
+ /// The section is a canonical function section.
+ CanonicalFunction = 8,
+ /// The section is a start section.
+ Start = 9,
+ /// The section is an import section.
+ Import = 10,
+ /// The section is an export section.
+ Export = 11,
+}
+
+impl From<ComponentSectionId> for u8 {
+ #[inline]
+ fn from(id: ComponentSectionId) -> u8 {
+ id as u8
+ }
+}
+
+impl Encode for ComponentSectionId {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(*self as u8);
+ }
+}
+
+/// Represents a WebAssembly component that is being encoded.
+///
+/// Unlike core WebAssembly modules, the sections of a component
+/// may appear in any order and may be repeated.
+///
+/// Components may also added as a section to other components.
+#[derive(Clone, Debug)]
+pub struct Component {
+ bytes: Vec<u8>,
+}
+
+impl Component {
+ /// The 8-byte header at the beginning of all components.
+ #[rustfmt::skip]
+ pub const HEADER: [u8; 8] = [
+ // Magic
+ 0x00, 0x61, 0x73, 0x6D,
+ // Version
+ 0x0c, 0x00, 0x01, 0x00,
+ ];
+
+ /// Begin writing a new `Component`.
+ pub fn new() -> Self {
+ Self {
+ bytes: Self::HEADER.to_vec(),
+ }
+ }
+
+ /// Finish writing this component and extract ownership of the encoded bytes.
+ pub fn finish(self) -> Vec<u8> {
+ self.bytes
+ }
+
+ /// Write a section to this component.
+ pub fn section(&mut self, section: &impl ComponentSection) -> &mut Self {
+ self.bytes.push(section.id());
+ section.encode(&mut self.bytes);
+ self
+ }
+
+ /// View the encoded bytes.
+ pub fn as_slice(&self) -> &[u8] {
+ &self.bytes
+ }
+}
+
+impl Default for Component {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl ComponentSection for CustomSection<'_> {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreCustom.into()
+ }
+}
+
+impl ComponentSection for ProducersSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreCustom.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/aliases.rs b/third_party/rust/wasm-encoder/src/component/aliases.rs
new file mode 100644
index 0000000000..1e317fb0e2
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/aliases.rs
@@ -0,0 +1,160 @@
+use super::{COMPONENT_SORT, CORE_MODULE_SORT, CORE_SORT, CORE_TYPE_SORT, TYPE_SORT};
+use crate::{
+ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind,
+};
+
+/// Represents the kinds of outer aliasable items in a component.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ComponentOuterAliasKind {
+ /// The alias is to a core module.
+ CoreModule,
+ /// The alias is to a core type.
+ CoreType,
+ /// The alias is to a type.
+ Type,
+ /// The alias is to a component.
+ Component,
+}
+
+impl Encode for ComponentOuterAliasKind {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::CoreModule => {
+ sink.push(CORE_SORT);
+ sink.push(CORE_MODULE_SORT);
+ }
+ Self::CoreType => {
+ sink.push(CORE_SORT);
+ sink.push(CORE_TYPE_SORT);
+ }
+ Self::Type => sink.push(TYPE_SORT),
+ Self::Component => sink.push(COMPONENT_SORT),
+ }
+ }
+}
+
+/// An encoder for the alias section of WebAssembly component.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, Alias, ComponentAliasSection, ComponentExportKind, ComponentOuterAliasKind};
+///
+/// let mut aliases = ComponentAliasSection::new();
+/// aliases.alias(Alias::InstanceExport { instance: 0, kind: ComponentExportKind::Func, name: "f" });
+/// aliases.alias(Alias::Outer { count: 0, kind: ComponentOuterAliasKind::Type, index: 1 });
+///
+/// let mut component = Component::new();
+/// component.section(&aliases);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentAliasSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+/// Different forms of aliases that can be inserted into a
+/// [`ComponentAliasSection`].
+#[derive(Copy, Clone, Debug)]
+pub enum Alias<'a> {
+ /// An alias of a component instance export.
+ InstanceExport {
+ /// The index of the component instance that's being aliased from.
+ instance: u32,
+ /// The kind of item that's being extracted from the component
+ /// instance.
+ kind: ComponentExportKind,
+ /// The name of the export that's being aliased.
+ name: &'a str,
+ },
+ /// Same as `InstanceExport`, but for core instances.
+ #[allow(missing_docs)]
+ CoreInstanceExport {
+ instance: u32,
+ kind: ExportKind,
+ name: &'a str,
+ },
+ /// Aliasing an item from an outer component.
+ Outer {
+ /// The kind of item being aliased, either a type or a component.
+ kind: ComponentOuterAliasKind,
+ /// Number of levels "up" to go to lookup the index within. Level 0 is
+ /// the current scope and level 1 is the enclosing scope, and so on.
+ count: u32,
+ /// The index of the item to alias within the scope referenced by
+ /// `count`.
+ index: u32,
+ },
+}
+
+impl ComponentAliasSection {
+ /// Create a new alias section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of aliases in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an alias to a component instance's export.
+ pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
+ alias.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentAliasSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentAliasSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Alias.into()
+ }
+}
+
+impl Encode for Alias<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Alias::InstanceExport {
+ instance,
+ kind,
+ name,
+ } => {
+ kind.encode(sink);
+ sink.push(0x00);
+ instance.encode(sink);
+ name.encode(sink);
+ }
+ Alias::CoreInstanceExport {
+ instance,
+ kind,
+ name,
+ } => {
+ sink.push(CORE_SORT);
+ kind.encode(sink);
+ sink.push(0x01);
+ instance.encode(sink);
+ name.encode(sink);
+ }
+ Alias::Outer { kind, count, index } => {
+ kind.encode(sink);
+ sink.push(0x02);
+ count.encode(sink);
+ index.encode(sink);
+ }
+ }
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/canonicals.rs b/third_party/rust/wasm-encoder/src/component/canonicals.rs
new file mode 100644
index 0000000000..e81819c44e
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/canonicals.rs
@@ -0,0 +1,133 @@
+use crate::{encode_section, ComponentSection, ComponentSectionId, Encode};
+
+/// Represents options for canonical function definitions.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum CanonicalOption {
+ /// The string types in the function signature are UTF-8 encoded.
+ UTF8,
+ /// The string types in the function signature are UTF-16 encoded.
+ UTF16,
+ /// The string types in the function signature are compact UTF-16 encoded.
+ CompactUTF16,
+ /// The memory to use if the lifting or lowering of a function requires memory access.
+ ///
+ /// The value is an index to a core memory.
+ Memory(u32),
+ /// The realloc function to use if the lifting or lowering of a function requires memory
+ /// allocation.
+ ///
+ /// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`.
+ Realloc(u32),
+ /// The post-return function to use if the lifting of a function requires
+ /// cleanup after the function returns.
+ PostReturn(u32),
+}
+
+impl Encode for CanonicalOption {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::UTF8 => sink.push(0x00),
+ Self::UTF16 => sink.push(0x01),
+ Self::CompactUTF16 => sink.push(0x02),
+ Self::Memory(idx) => {
+ sink.push(0x03);
+ idx.encode(sink);
+ }
+ Self::Realloc(idx) => {
+ sink.push(0x04);
+ idx.encode(sink);
+ }
+ Self::PostReturn(idx) => {
+ sink.push(0x05);
+ idx.encode(sink);
+ }
+ }
+ }
+}
+
+/// An encoder for the canonical function section of WebAssembly components.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Component, CanonicalFunctionSection, CanonicalOption};
+///
+/// let mut functions = CanonicalFunctionSection::new();
+/// functions.lift(0, 0, [CanonicalOption::UTF8]);
+///
+/// let mut component = Component::new();
+/// component.section(&functions);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct CanonicalFunctionSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl CanonicalFunctionSection {
+ /// Construct a new component function section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of functions in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a function that will lift a core WebAssembly function to the canonical ABI.
+ pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
+ where
+ O: IntoIterator<Item = CanonicalOption>,
+ O::IntoIter: ExactSizeIterator,
+ {
+ let options = options.into_iter();
+ self.bytes.push(0x00);
+ self.bytes.push(0x00);
+ core_func_index.encode(&mut self.bytes);
+ options.len().encode(&mut self.bytes);
+ for option in options {
+ option.encode(&mut self.bytes);
+ }
+ type_index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Define a function that will lower a canonical ABI function to a core WebAssembly function.
+ pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
+ where
+ O: IntoIterator<Item = CanonicalOption>,
+ O::IntoIter: ExactSizeIterator,
+ {
+ let options = options.into_iter();
+ self.bytes.push(0x01);
+ self.bytes.push(0x00);
+ func_index.encode(&mut self.bytes);
+ options.len().encode(&mut self.bytes);
+ for option in options {
+ option.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for CanonicalFunctionSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for CanonicalFunctionSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CanonicalFunction.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/components.rs b/third_party/rust/wasm-encoder/src/component/components.rs
new file mode 100644
index 0000000000..c08645e3b9
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/components.rs
@@ -0,0 +1,29 @@
+use crate::{Component, ComponentSection, ComponentSectionId, Encode};
+
+/// An encoder for the component section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, NestedComponentSection};
+///
+/// let mut nested = Component::new();
+/// let mut component = Component::new();
+/// component.section(&NestedComponentSection(&nested));
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct NestedComponentSection<'a>(pub &'a Component);
+
+impl Encode for NestedComponentSection<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.0.bytes.encode(sink);
+ }
+}
+
+impl ComponentSection for NestedComponentSection<'_> {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Component.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/exports.rs b/third_party/rust/wasm-encoder/src/component/exports.rs
new file mode 100644
index 0000000000..9720d51b02
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/exports.rs
@@ -0,0 +1,125 @@
+use super::{
+ COMPONENT_SORT, CORE_MODULE_SORT, CORE_SORT, FUNCTION_SORT, INSTANCE_SORT, TYPE_SORT,
+ VALUE_SORT,
+};
+use crate::{encode_section, ComponentSection, ComponentSectionId, ComponentTypeRef, Encode};
+
+/// Represents the kind of an export from a WebAssembly component.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ComponentExportKind {
+ /// The export is a core module.
+ Module,
+ /// The export is a function.
+ Func,
+ /// The export is a value.
+ Value,
+ /// The export is a type.
+ Type,
+ /// The export is an instance.
+ Instance,
+ /// The export is a component.
+ Component,
+}
+
+impl Encode for ComponentExportKind {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Module => {
+ sink.push(CORE_SORT);
+ sink.push(CORE_MODULE_SORT);
+ }
+ Self::Func => {
+ sink.push(FUNCTION_SORT);
+ }
+ Self::Value => {
+ sink.push(VALUE_SORT);
+ }
+ Self::Type => {
+ sink.push(TYPE_SORT);
+ }
+ Self::Instance => {
+ sink.push(INSTANCE_SORT);
+ }
+ Self::Component => {
+ sink.push(COMPONENT_SORT);
+ }
+ }
+ }
+}
+
+/// An encoder for the export section of WebAssembly component.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentExportSection, ComponentExportKind};
+///
+/// // This exports a function named "foo"
+/// let mut exports = ComponentExportSection::new();
+/// exports.export("foo", "", ComponentExportKind::Func, 0, None);
+///
+/// let mut component = Component::new();
+/// component.section(&exports);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentExportSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentExportSection {
+ /// Create a new component export section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of exports in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an export in the export section.
+ pub fn export(
+ &mut self,
+ name: &str,
+ url: &str,
+ kind: ComponentExportKind,
+ index: u32,
+ ty: Option<ComponentTypeRef>,
+ ) -> &mut Self {
+ name.encode(&mut self.bytes);
+ url.encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ match ty {
+ Some(ty) => {
+ self.bytes.push(0x01);
+ ty.encode(&mut self.bytes);
+ }
+ None => {
+ self.bytes.push(0x00);
+ }
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentExportSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentExportSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Export.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/imports.rs b/third_party/rust/wasm-encoder/src/component/imports.rs
new file mode 100644
index 0000000000..8d843407f3
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/imports.rs
@@ -0,0 +1,151 @@
+use crate::{
+ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, ComponentValType,
+ Encode,
+};
+
+/// Represents the possible type bounds for type references.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub enum TypeBounds {
+ /// The type is bounded by equality.
+ Eq,
+}
+
+impl Encode for TypeBounds {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Eq => sink.push(0x00),
+ }
+ }
+}
+
+/// Represents a reference to a type.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub enum ComponentTypeRef {
+ /// The reference is to a core module type.
+ ///
+ /// The index is expected to be core type index to a core module type.
+ Module(u32),
+ /// The reference is to a function type.
+ ///
+ /// The index is expected to be a type index to a function type.
+ Func(u32),
+ /// The reference is to a value type.
+ Value(ComponentValType),
+ /// The reference is to a bounded type.
+ ///
+ /// The index is expected to be a type index.
+ Type(TypeBounds, u32),
+ /// The reference is to an instance type.
+ ///
+ /// The index is expected to be a type index to an instance type.
+ Instance(u32),
+ /// The reference is to a component type.
+ ///
+ /// The index is expected to be a type index to a component type.
+ Component(u32),
+}
+
+impl ComponentTypeRef {
+ /// Gets the export kind of the reference.
+ pub fn kind(&self) -> ComponentExportKind {
+ match self {
+ Self::Module(_) => ComponentExportKind::Module,
+ Self::Func(_) => ComponentExportKind::Func,
+ Self::Value(_) => ComponentExportKind::Value,
+ Self::Type(..) => ComponentExportKind::Type,
+ Self::Instance(_) => ComponentExportKind::Instance,
+ Self::Component(_) => ComponentExportKind::Component,
+ }
+ }
+}
+
+impl Encode for ComponentTypeRef {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.kind().encode(sink);
+
+ match self {
+ Self::Module(idx) | Self::Func(idx) | Self::Instance(idx) | Self::Component(idx) => {
+ idx.encode(sink);
+ }
+ Self::Value(ty) => ty.encode(sink),
+ Self::Type(bounds, idx) => {
+ bounds.encode(sink);
+ idx.encode(sink);
+ }
+ }
+ }
+}
+
+/// An encoder for the import section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType, ComponentImportSection, ComponentTypeRef};
+///
+/// let mut types = ComponentTypeSection::new();
+///
+/// // Define a function type of `[string, string] -> string`.
+/// types
+/// .function()
+/// .params(
+/// [
+/// ("a", PrimitiveValType::String),
+/// ("b", PrimitiveValType::String)
+/// ]
+/// )
+/// .result(PrimitiveValType::String);
+///
+/// // This imports a function named `f` with the type defined above
+/// let mut imports = ComponentImportSection::new();
+/// imports.import("f", "", ComponentTypeRef::Func(0));
+///
+/// let mut component = Component::new();
+/// component.section(&types);
+/// component.section(&imports);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentImportSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentImportSection {
+ /// Create a new component import section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of imports in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an import in the component import section.
+ pub fn import(&mut self, name: &str, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ name.encode(&mut self.bytes);
+ url.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentImportSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentImportSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Import.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/instances.rs b/third_party/rust/wasm-encoder/src/component/instances.rs
new file mode 100644
index 0000000000..5f2c97dec3
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/instances.rs
@@ -0,0 +1,199 @@
+use super::CORE_INSTANCE_SORT;
+use crate::{
+ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind,
+};
+
+/// Represents an argument to a module instantiation.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ModuleArg {
+ /// The argument is an instance.
+ Instance(u32),
+}
+
+impl Encode for ModuleArg {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let (sort, idx) = match self {
+ Self::Instance(idx) => (CORE_INSTANCE_SORT, *idx),
+ };
+ sink.push(sort);
+ idx.encode(sink);
+ }
+}
+
+/// An encoder for the core instance section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, InstanceSection, ExportKind, ModuleArg};
+///
+/// let mut instances = InstanceSection::new();
+/// instances.export_items([("foo", ExportKind::Func, 0)]);
+/// instances.instantiate(1, [("foo", ModuleArg::Instance(0))]);
+///
+/// let mut component = Component::new();
+/// component.section(&instances);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct InstanceSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl InstanceSection {
+ /// Create a new core instance section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of instances in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an instance by instantiating a core module.
+ pub fn instantiate<A, S>(&mut self, module_index: u32, args: A) -> &mut Self
+ where
+ A: IntoIterator<Item = (S, ModuleArg)>,
+ A::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ let args = args.into_iter();
+ self.bytes.push(0x00);
+ module_index.encode(&mut self.bytes);
+ args.len().encode(&mut self.bytes);
+ for (name, arg) in args {
+ name.as_ref().encode(&mut self.bytes);
+ arg.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Define an instance by exporting core WebAssembly items.
+ pub fn export_items<E, S>(&mut self, exports: E) -> &mut Self
+ where
+ E: IntoIterator<Item = (S, ExportKind, u32)>,
+ E::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ let exports = exports.into_iter();
+ self.bytes.push(0x01);
+ exports.len().encode(&mut self.bytes);
+ for (name, kind, index) in exports {
+ name.as_ref().encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for InstanceSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for InstanceSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreInstance.into()
+ }
+}
+
+/// An encoder for the instance section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentInstanceSection, ComponentExportKind};
+///
+/// let mut instances = ComponentInstanceSection::new();
+/// instances.export_items([("foo", ComponentExportKind::Func, 0)]);
+/// instances.instantiate(1, [("foo", ComponentExportKind::Instance, 0)]);
+///
+/// let mut component = Component::new();
+/// component.section(&instances);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentInstanceSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentInstanceSection {
+ /// Create a new instance section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of instances in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an instance by instantiating a component.
+ pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> &mut Self
+ where
+ A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
+ A::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ let args = args.into_iter();
+ self.bytes.push(0x00);
+ component_index.encode(&mut self.bytes);
+ args.len().encode(&mut self.bytes);
+ for (name, kind, index) in args {
+ name.as_ref().encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Define an instance by exporting items.
+ pub fn export_items<'a, E>(&mut self, exports: E) -> &mut Self
+ where
+ E: IntoIterator<Item = (&'a str, ComponentExportKind, u32)>,
+ E::IntoIter: ExactSizeIterator,
+ {
+ let exports = exports.into_iter();
+ self.bytes.push(0x01);
+ exports.len().encode(&mut self.bytes);
+ for (name, kind, index) in exports {
+ name.encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentInstanceSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentInstanceSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Instance.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/modules.rs b/third_party/rust/wasm-encoder/src/component/modules.rs
new file mode 100644
index 0000000000..437cd353af
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/modules.rs
@@ -0,0 +1,29 @@
+use crate::{ComponentSection, ComponentSectionId, Encode, Module};
+
+/// An encoder for the module section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Module, Component, ModuleSection};
+///
+/// let mut module = Module::new();
+/// let mut component = Component::new();
+/// component.section(&ModuleSection(&module));
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct ModuleSection<'a>(pub &'a Module);
+
+impl Encode for ModuleSection<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.0.bytes.encode(sink);
+ }
+}
+
+impl ComponentSection for ModuleSection<'_> {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreModule.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/names.rs b/third_party/rust/wasm-encoder/src/component/names.rs
new file mode 100644
index 0000000000..0e3b02dc2e
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/names.rs
@@ -0,0 +1,147 @@
+use super::*;
+use crate::{encoding_size, CustomSection, Encode, ExportKind, NameMap, SectionId};
+
+/// Encoding for the `component-name` custom section which assigns
+/// human-readable names to items within a component.
+#[derive(Clone, Debug, Default)]
+pub struct ComponentNameSection {
+ bytes: Vec<u8>,
+}
+
+enum Subsection {
+ Component,
+ Decls,
+}
+
+impl ComponentNameSection {
+ /// Creates a new blank `name` custom section.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Appends a component name subsection to this section.
+ ///
+ /// This will indicate that the name of the entire component should be the
+ /// `name` specified. Note that this should be encoded first before other
+ /// subsections.
+ pub fn component(&mut self, name: &str) {
+ let len = encoding_size(u32::try_from(name.len()).unwrap());
+ self.subsection_header(Subsection::Component, len + name.len());
+ name.encode(&mut self.bytes);
+ }
+
+ /// Appends a decls name subsection to name core functions within the
+ /// component.
+ pub fn core_funcs(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Func as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core tables within the
+ /// component.
+ pub fn core_tables(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Table as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core memories within the
+ /// component.
+ pub fn core_memories(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Memory as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core globals within the
+ /// component.
+ pub fn core_globals(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Global as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core types within the
+ /// component.
+ pub fn core_types(&mut self, names: &NameMap) {
+ self.core_decls(CORE_TYPE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name core modules within the
+ /// component.
+ pub fn core_modules(&mut self, names: &NameMap) {
+ self.core_decls(CORE_MODULE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name core instances within the
+ /// component.
+ pub fn core_instances(&mut self, names: &NameMap) {
+ self.core_decls(CORE_INSTANCE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component functions within the
+ /// component.
+ pub fn funcs(&mut self, names: &NameMap) {
+ self.component_decls(FUNCTION_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component values within the
+ /// component.
+ pub fn values(&mut self, names: &NameMap) {
+ self.component_decls(VALUE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component type within the
+ /// component.
+ pub fn types(&mut self, names: &NameMap) {
+ self.component_decls(TYPE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name components within the
+ /// component.
+ pub fn components(&mut self, names: &NameMap) {
+ self.component_decls(COMPONENT_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component instances within the
+ /// component.
+ pub fn instances(&mut self, names: &NameMap) {
+ self.component_decls(INSTANCE_SORT, names)
+ }
+
+ fn component_decls(&mut self, kind: u8, names: &NameMap) {
+ self.subsection_header(Subsection::Decls, 1 + names.size());
+ self.bytes.push(kind);
+ names.encode(&mut self.bytes);
+ }
+
+ fn core_decls(&mut self, kind: u8, names: &NameMap) {
+ self.subsection_header(Subsection::Decls, 2 + names.size());
+ self.bytes.push(CORE_SORT);
+ self.bytes.push(kind);
+ names.encode(&mut self.bytes);
+ }
+
+ fn subsection_header(&mut self, id: Subsection, len: usize) {
+ self.bytes.push(id as u8);
+ len.encode(&mut self.bytes);
+ }
+
+ /// Returns whether this section is empty, or nothing has been encoded.
+ pub fn is_empty(&self) -> bool {
+ self.bytes.is_empty()
+ }
+
+ /// View the encoded section as a CustomSection.
+ pub fn as_custom<'a>(&'a self) -> CustomSection<'a> {
+ CustomSection {
+ name: "component-name",
+ data: &self.bytes,
+ }
+ }
+}
+
+impl Encode for ComponentNameSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.as_custom().encode(sink);
+ }
+}
+
+impl ComponentSection for ComponentNameSection {
+ fn id(&self) -> u8 {
+ SectionId::Custom.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/start.rs b/third_party/rust/wasm-encoder/src/component/start.rs
new file mode 100644
index 0000000000..d4b60e1dfc
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/start.rs
@@ -0,0 +1,52 @@
+use crate::{ComponentSection, ComponentSectionId, Encode};
+
+/// An encoder for the start section of WebAssembly components.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Component, ComponentStartSection};
+///
+/// let start = ComponentStartSection { function_index: 0, args: [0, 1], results: 1 };
+///
+/// let mut component = Component::new();
+/// component.section(&start);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct ComponentStartSection<A> {
+ /// The index to the start function.
+ pub function_index: u32,
+ /// The arguments to pass to the start function.
+ ///
+ /// An argument is an index to a value.
+ pub args: A,
+ /// The number of expected results for the start function.
+ ///
+ /// This should match the number of results for the type of
+ /// the function referenced by `function_index`.
+ pub results: u32,
+}
+
+impl<A> Encode for ComponentStartSection<A>
+where
+ A: AsRef<[u32]>,
+{
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let mut bytes = Vec::new();
+ self.function_index.encode(&mut bytes);
+ self.args.as_ref().encode(&mut bytes);
+ self.results.encode(&mut bytes);
+ bytes.encode(sink);
+ }
+}
+
+impl<A> ComponentSection for ComponentStartSection<A>
+where
+ A: AsRef<[u32]>,
+{
+ fn id(&self) -> u8 {
+ ComponentSectionId::Start.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/types.rs b/third_party/rust/wasm-encoder/src/component/types.rs
new file mode 100644
index 0000000000..930467d57a
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/types.rs
@@ -0,0 +1,736 @@
+use super::CORE_TYPE_SORT;
+use crate::{
+ encode_section, Alias, ComponentExportKind, ComponentOuterAliasKind, ComponentSection,
+ ComponentSectionId, ComponentTypeRef, Encode, EntityType, ValType,
+};
+
+/// Represents the type of a core module.
+#[derive(Debug, Clone, Default)]
+pub struct ModuleType {
+ bytes: Vec<u8>,
+ num_added: u32,
+ types_added: u32,
+}
+
+impl ModuleType {
+ /// Creates a new core module type.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Defines an import in this module type.
+ pub fn import(&mut self, module: &str, name: &str, ty: EntityType) -> &mut Self {
+ self.bytes.push(0x00);
+ module.encode(&mut self.bytes);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Define a type in this module type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> CoreTypeEncoder {
+ self.bytes.push(0x01);
+ self.num_added += 1;
+ self.types_added += 1;
+ CoreTypeEncoder(&mut self.bytes)
+ }
+
+ /// Defines an outer core type alias in this module type.
+ pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self {
+ self.bytes.push(0x02);
+ self.bytes.push(CORE_TYPE_SORT);
+ self.bytes.push(0x01); // outer
+ count.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self.types_added += 1;
+ self
+ }
+
+ /// Defines an export in this module type.
+ pub fn export(&mut self, name: &str, ty: EntityType) -> &mut Self {
+ self.bytes.push(0x03);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Gets the number of types that have been added to this module type.
+ pub fn type_count(&self) -> u32 {
+ self.types_added
+ }
+}
+
+impl Encode for ModuleType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(0x50);
+ self.num_added.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
+
+/// Used to encode core types.
+#[derive(Debug)]
+pub struct CoreTypeEncoder<'a>(pub(crate) &'a mut Vec<u8>);
+
+impl<'a> CoreTypeEncoder<'a> {
+ /// Define a function type.
+ pub fn function<P, R>(self, params: P, results: R)
+ where
+ P: IntoIterator<Item = ValType>,
+ P::IntoIter: ExactSizeIterator,
+ R: IntoIterator<Item = ValType>,
+ R::IntoIter: ExactSizeIterator,
+ {
+ let params = params.into_iter();
+ let results = results.into_iter();
+
+ self.0.push(0x60);
+ params.len().encode(self.0);
+ params.for_each(|p| p.encode(self.0));
+ results.len().encode(self.0);
+ results.for_each(|p| p.encode(self.0));
+ }
+
+ /// Define a module type.
+ pub fn module(self, ty: &ModuleType) {
+ ty.encode(self.0);
+ }
+}
+
+/// An encoder for the core type section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, CoreTypeSection, ModuleType};
+///
+/// let mut types = CoreTypeSection::new();
+///
+/// types.module(&ModuleType::new());
+///
+/// let mut component = Component::new();
+/// component.section(&types);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct CoreTypeSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl CoreTypeSection {
+ /// Create a new core type section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of types in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Encode a type into this section.
+ ///
+ /// The returned encoder must be finished before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> CoreTypeEncoder<'_> {
+ self.num_added += 1;
+ CoreTypeEncoder(&mut self.bytes)
+ }
+
+ /// Define a function type in this type section.
+ pub fn function<P, R>(&mut self, params: P, results: R) -> &mut Self
+ where
+ P: IntoIterator<Item = ValType>,
+ P::IntoIter: ExactSizeIterator,
+ R: IntoIterator<Item = ValType>,
+ R::IntoIter: ExactSizeIterator,
+ {
+ self.ty().function(params, results);
+ self
+ }
+
+ /// Define a module type in this type section.
+ ///
+ /// Currently this is only used for core type sections in components.
+ pub fn module(&mut self, ty: &ModuleType) -> &mut Self {
+ self.ty().module(ty);
+ self
+ }
+}
+
+impl Encode for CoreTypeSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for CoreTypeSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreType.into()
+ }
+}
+
+/// Represents a component type.
+#[derive(Debug, Clone, Default)]
+pub struct ComponentType {
+ bytes: Vec<u8>,
+ num_added: u32,
+ core_types_added: u32,
+ types_added: u32,
+}
+
+impl ComponentType {
+ /// Creates a new component type.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Define a core type in this component type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn core_type(&mut self) -> CoreTypeEncoder {
+ self.bytes.push(0x00);
+ self.num_added += 1;
+ self.core_types_added += 1;
+ CoreTypeEncoder(&mut self.bytes)
+ }
+
+ /// Define a type in this component type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> ComponentTypeEncoder {
+ self.bytes.push(0x01);
+ self.num_added += 1;
+ self.types_added += 1;
+ ComponentTypeEncoder(&mut self.bytes)
+ }
+
+ /// Defines an alias for an exported item of a prior instance or an
+ /// outer type.
+ pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
+ self.bytes.push(0x02);
+ alias.encode(&mut self.bytes);
+ self.num_added += 1;
+ match &alias {
+ Alias::InstanceExport {
+ kind: ComponentExportKind::Type,
+ ..
+ }
+ | Alias::Outer {
+ kind: ComponentOuterAliasKind::Type,
+ ..
+ } => self.types_added += 1,
+ Alias::Outer {
+ kind: ComponentOuterAliasKind::CoreType,
+ ..
+ } => self.core_types_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Defines an import in this component type.
+ pub fn import(&mut self, name: &str, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.bytes.push(0x03);
+ name.encode(&mut self.bytes);
+ url.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ match ty {
+ ComponentTypeRef::Type(..) => self.types_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Defines an export in this component type.
+ pub fn export(&mut self, name: &str, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.bytes.push(0x04);
+ name.encode(&mut self.bytes);
+ url.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ match ty {
+ ComponentTypeRef::Type(..) => self.types_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Gets the number of core types that have been added to this component type.
+ pub fn core_type_count(&self) -> u32 {
+ self.core_types_added
+ }
+
+ /// Gets the number of types that have been added or aliased in this component type.
+ pub fn type_count(&self) -> u32 {
+ self.types_added
+ }
+}
+
+impl Encode for ComponentType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(0x41);
+ self.num_added.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
+
+/// Represents an instance type.
+#[derive(Debug, Clone, Default)]
+pub struct InstanceType(ComponentType);
+
+impl InstanceType {
+ /// Creates a new instance type.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Define a core type in this instance type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn core_type(&mut self) -> CoreTypeEncoder {
+ self.0.core_type()
+ }
+
+ /// Define a type in this instance type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> ComponentTypeEncoder {
+ self.0.ty()
+ }
+
+ /// Defines an outer core type alias in this component type.
+ pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
+ self.0.alias(alias);
+ self
+ }
+
+ /// Defines an export in this instance type.
+ pub fn export(&mut self, name: &str, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.0.export(name, url, ty);
+ self
+ }
+
+ /// Gets the number of core types that have been added to this instance type.
+ pub fn core_type_count(&self) -> u32 {
+ self.0.core_types_added
+ }
+
+ /// Gets the number of types that have been added or aliased in this instance type.
+ pub fn type_count(&self) -> u32 {
+ self.0.types_added
+ }
+
+ /// Returns whether or not this instance type is empty.
+ pub fn is_empty(&self) -> bool {
+ self.0.num_added == 0
+ }
+
+ /// Returns the number of entries added to this instance types.
+ pub fn len(&self) -> u32 {
+ self.0.num_added
+ }
+}
+
+impl Encode for InstanceType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(0x42);
+ self.0.num_added.encode(sink);
+ sink.extend(&self.0.bytes);
+ }
+}
+
+/// Used to encode component function types.
+#[derive(Debug)]
+pub struct ComponentFuncTypeEncoder<'a>(&'a mut Vec<u8>);
+
+impl<'a> ComponentFuncTypeEncoder<'a> {
+ fn new(sink: &'a mut Vec<u8>) -> Self {
+ sink.push(0x40);
+ Self(sink)
+ }
+
+ /// Defines named parameters.
+ ///
+ /// Parameters must be defined before defining results.
+ pub fn params<'b, P, T>(&mut self, params: P) -> &mut Self
+ where
+ P: IntoIterator<Item = (&'b str, T)>,
+ P::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let params = params.into_iter();
+ params.len().encode(self.0);
+ for (name, ty) in params {
+ name.encode(self.0);
+ ty.into().encode(self.0);
+ }
+ self
+ }
+
+ /// Defines a single unnamed result.
+ ///
+ /// This method cannot be used with `results`.
+ pub fn result(&mut self, ty: impl Into<ComponentValType>) -> &mut Self {
+ self.0.push(0x00);
+ ty.into().encode(self.0);
+ self
+ }
+
+ /// Defines named results.
+ ///
+ /// This method cannot be used with `result`.
+ pub fn results<'b, R, T>(&mut self, results: R) -> &mut Self
+ where
+ R: IntoIterator<Item = (&'b str, T)>,
+ R::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ self.0.push(0x01);
+ let results = results.into_iter();
+ results.len().encode(self.0);
+ for (name, ty) in results {
+ name.encode(self.0);
+ ty.into().encode(self.0);
+ }
+ self
+ }
+}
+
+/// Used to encode component and instance types.
+#[derive(Debug)]
+pub struct ComponentTypeEncoder<'a>(&'a mut Vec<u8>);
+
+impl<'a> ComponentTypeEncoder<'a> {
+ /// Define a component type.
+ pub fn component(self, ty: &ComponentType) {
+ ty.encode(self.0);
+ }
+
+ /// Define an instance type.
+ pub fn instance(self, ty: &InstanceType) {
+ ty.encode(self.0);
+ }
+
+ /// Define a function type.
+ pub fn function(self) -> ComponentFuncTypeEncoder<'a> {
+ ComponentFuncTypeEncoder::new(self.0)
+ }
+
+ /// Define a defined component type.
+ ///
+ /// The returned encoder must be used before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn defined_type(self) -> ComponentDefinedTypeEncoder<'a> {
+ ComponentDefinedTypeEncoder(self.0)
+ }
+}
+
+/// Represents a primitive component value type.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum PrimitiveValType {
+ /// The type is a boolean.
+ Bool,
+ /// The type is a signed 8-bit integer.
+ S8,
+ /// The type is an unsigned 8-bit integer.
+ U8,
+ /// The type is a signed 16-bit integer.
+ S16,
+ /// The type is an unsigned 16-bit integer.
+ U16,
+ /// The type is a signed 32-bit integer.
+ S32,
+ /// The type is an unsigned 32-bit integer.
+ U32,
+ /// The type is a signed 64-bit integer.
+ S64,
+ /// The type is an unsigned 64-bit integer.
+ U64,
+ /// The type is a 32-bit floating point number.
+ Float32,
+ /// The type is a 64-bit floating point number.
+ Float64,
+ /// The type is a Unicode character.
+ Char,
+ /// The type is a string.
+ String,
+}
+
+impl Encode for PrimitiveValType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(match self {
+ Self::Bool => 0x7f,
+ Self::S8 => 0x7e,
+ Self::U8 => 0x7d,
+ Self::S16 => 0x7c,
+ Self::U16 => 0x7b,
+ Self::S32 => 0x7a,
+ Self::U32 => 0x79,
+ Self::S64 => 0x78,
+ Self::U64 => 0x77,
+ Self::Float32 => 0x76,
+ Self::Float64 => 0x75,
+ Self::Char => 0x74,
+ Self::String => 0x73,
+ });
+ }
+}
+
+/// Represents a component value type.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ComponentValType {
+ /// The value is a primitive type.
+ Primitive(PrimitiveValType),
+ /// The value is to a defined value type.
+ ///
+ /// The type index must be to a value type.
+ Type(u32),
+}
+
+impl Encode for ComponentValType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Primitive(ty) => ty.encode(sink),
+ Self::Type(index) => (*index as i64).encode(sink),
+ }
+ }
+}
+
+impl From<PrimitiveValType> for ComponentValType {
+ fn from(ty: PrimitiveValType) -> Self {
+ Self::Primitive(ty)
+ }
+}
+
+/// Used for encoding component defined types.
+#[derive(Debug)]
+pub struct ComponentDefinedTypeEncoder<'a>(&'a mut Vec<u8>);
+
+impl ComponentDefinedTypeEncoder<'_> {
+ /// Define a primitive value type.
+ pub fn primitive(self, ty: PrimitiveValType) {
+ ty.encode(self.0);
+ }
+
+ /// Define a record type.
+ pub fn record<'a, F, T>(self, fields: F)
+ where
+ F: IntoIterator<Item = (&'a str, T)>,
+ F::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let fields = fields.into_iter();
+ self.0.push(0x72);
+ fields.len().encode(self.0);
+ for (name, ty) in fields {
+ name.encode(self.0);
+ ty.into().encode(self.0);
+ }
+ }
+
+ /// Define a variant type.
+ pub fn variant<'a, C>(self, cases: C)
+ where
+ C: IntoIterator<Item = (&'a str, Option<ComponentValType>, Option<u32>)>,
+ C::IntoIter: ExactSizeIterator,
+ {
+ let cases = cases.into_iter();
+ self.0.push(0x71);
+ cases.len().encode(self.0);
+ for (name, ty, refines) in cases {
+ name.encode(self.0);
+ ty.encode(self.0);
+ refines.encode(self.0);
+ }
+ }
+
+ /// Define a list type.
+ pub fn list(self, ty: impl Into<ComponentValType>) {
+ self.0.push(0x70);
+ ty.into().encode(self.0);
+ }
+
+ /// Define a tuple type.
+ pub fn tuple<I, T>(self, types: I)
+ where
+ I: IntoIterator<Item = T>,
+ I::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let types = types.into_iter();
+ self.0.push(0x6F);
+ types.len().encode(self.0);
+ for ty in types {
+ ty.into().encode(self.0);
+ }
+ }
+
+ /// Define a flags type.
+ pub fn flags<'a, I>(self, names: I)
+ where
+ I: IntoIterator<Item = &'a str>,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let names = names.into_iter();
+ self.0.push(0x6E);
+ names.len().encode(self.0);
+ for name in names {
+ name.encode(self.0);
+ }
+ }
+
+ /// Define an enum type.
+ pub fn enum_type<'a, I>(self, tags: I)
+ where
+ I: IntoIterator<Item = &'a str>,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let tags = tags.into_iter();
+ self.0.push(0x6D);
+ tags.len().encode(self.0);
+ for tag in tags {
+ tag.encode(self.0);
+ }
+ }
+
+ /// Define a union type.
+ pub fn union<I, T>(self, types: I)
+ where
+ I: IntoIterator<Item = T>,
+ I::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let types = types.into_iter();
+ self.0.push(0x6C);
+ types.len().encode(self.0);
+ for ty in types {
+ ty.into().encode(self.0);
+ }
+ }
+
+ /// Define an option type.
+ pub fn option(self, ty: impl Into<ComponentValType>) {
+ self.0.push(0x6B);
+ ty.into().encode(self.0);
+ }
+
+ /// Define a result type.
+ pub fn result(self, ok: Option<ComponentValType>, err: Option<ComponentValType>) {
+ self.0.push(0x6A);
+ ok.encode(self.0);
+ err.encode(self.0);
+ }
+}
+
+/// An encoder for the type section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType};
+///
+/// let mut types = ComponentTypeSection::new();
+///
+/// // Define a function type of `[string, string] -> string`.
+/// types
+/// .function()
+/// .params(
+/// [
+/// ("a", PrimitiveValType::String),
+/// ("b", PrimitiveValType::String)
+/// ]
+/// )
+/// .result(PrimitiveValType::String);
+///
+/// let mut component = Component::new();
+/// component.section(&types);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentTypeSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentTypeSection {
+ /// Create a new component type section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of types in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Encode a type into this section.
+ ///
+ /// The returned encoder must be finished before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> ComponentTypeEncoder<'_> {
+ self.num_added += 1;
+ ComponentTypeEncoder(&mut self.bytes)
+ }
+
+ /// Define a component type in this type section.
+ pub fn component(&mut self, ty: &ComponentType) -> &mut Self {
+ self.ty().component(ty);
+ self
+ }
+
+ /// Define an instance type in this type section.
+ pub fn instance(&mut self, ty: &InstanceType) -> &mut Self {
+ self.ty().instance(ty);
+ self
+ }
+
+ /// Define a function type in this type section.
+ pub fn function(&mut self) -> ComponentFuncTypeEncoder<'_> {
+ self.ty().function()
+ }
+
+ /// Add a component defined type to this type section.
+ ///
+ /// The returned encoder must be used before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn defined_type(&mut self) -> ComponentDefinedTypeEncoder<'_> {
+ self.ty().defined_type()
+ }
+}
+
+impl Encode for ComponentTypeSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentTypeSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Type.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core.rs b/third_party/rust/wasm-encoder/src/core.rs
new file mode 100644
index 0000000000..dcf4d6fb74
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core.rs
@@ -0,0 +1,166 @@
+mod code;
+mod custom;
+mod data;
+mod elements;
+mod exports;
+mod functions;
+mod globals;
+mod imports;
+mod linking;
+mod memories;
+mod names;
+mod producers;
+mod start;
+mod tables;
+mod tags;
+mod types;
+
+pub use code::*;
+pub use custom::*;
+pub use data::*;
+pub use elements::*;
+pub use exports::*;
+pub use functions::*;
+pub use globals::*;
+pub use imports::*;
+pub use linking::*;
+pub use memories::*;
+pub use names::*;
+pub use producers::*;
+pub use start::*;
+pub use tables::*;
+pub use tags::*;
+pub use types::*;
+
+use crate::Encode;
+
+pub(crate) const CORE_FUNCTION_SORT: u8 = 0x00;
+pub(crate) const CORE_TABLE_SORT: u8 = 0x01;
+pub(crate) const CORE_MEMORY_SORT: u8 = 0x02;
+pub(crate) const CORE_GLOBAL_SORT: u8 = 0x03;
+pub(crate) const CORE_TAG_SORT: u8 = 0x04;
+
+/// A WebAssembly module section.
+///
+/// Various builders defined in this crate already implement this trait, but you
+/// can also implement it yourself for your own custom section builders, or use
+/// `RawSection` to use a bunch of raw bytes as a section.
+pub trait Section: Encode {
+ /// Gets the section identifier for this section.
+ fn id(&self) -> u8;
+
+ /// Appends this section to the specified destination list of bytes.
+ fn append_to(&self, dst: &mut Vec<u8>) {
+ dst.push(self.id());
+ self.encode(dst);
+ }
+}
+
+/// Known section identifiers of WebAssembly modules.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+#[repr(u8)]
+pub enum SectionId {
+ /// The custom section.
+ Custom = 0,
+ /// The type section.
+ Type = 1,
+ /// The import section.
+ Import = 2,
+ /// The function section.
+ Function = 3,
+ /// The table section.
+ Table = 4,
+ /// The memory section.
+ Memory = 5,
+ /// The global section.
+ Global = 6,
+ /// The export section.
+ Export = 7,
+ /// The start section.
+ Start = 8,
+ /// The element section.
+ Element = 9,
+ /// The code section.
+ Code = 10,
+ /// The data section.
+ Data = 11,
+ /// The data count section.
+ DataCount = 12,
+ /// The tag section.
+ ///
+ /// This section is supported by the exception handling proposal.
+ Tag = 13,
+}
+
+impl From<SectionId> for u8 {
+ #[inline]
+ fn from(id: SectionId) -> u8 {
+ id as u8
+ }
+}
+
+impl Encode for SectionId {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(*self as u8);
+ }
+}
+
+/// Represents a WebAssembly component that is being encoded.
+///
+/// Sections within a WebAssembly module are encoded in a specific order.
+///
+/// Modules may also added as a section to a WebAssembly component.
+#[derive(Clone, Debug)]
+pub struct Module {
+ pub(crate) bytes: Vec<u8>,
+}
+
+impl Module {
+ /// The 8-byte header at the beginning of all core wasm modules.
+ #[rustfmt::skip]
+ pub const HEADER: [u8; 8] = [
+ // Magic
+ 0x00, 0x61, 0x73, 0x6D,
+ // Version
+ 0x01, 0x00, 0x00, 0x00,
+ ];
+
+ /// Begin writing a new `Module`.
+ #[rustfmt::skip]
+ pub fn new() -> Self {
+ Module {
+ bytes: Self::HEADER.to_vec(),
+ }
+ }
+
+ /// Write a section into this module.
+ ///
+ /// It is your responsibility to define the sections in the [proper
+ /// order](https://webassembly.github.io/spec/core/binary/modules.html#binary-module),
+ /// and to ensure that each kind of section (other than custom sections) is
+ /// only defined once. While this is a potential footgun, it also allows you
+ /// to use this crate to easily construct test cases for bad Wasm module
+ /// encodings.
+ pub fn section(&mut self, section: &impl Section) -> &mut Self {
+ self.bytes.push(section.id());
+ section.encode(&mut self.bytes);
+ self
+ }
+
+ /// Get the encoded Wasm module as a slice.
+ pub fn as_slice(&self) -> &[u8] {
+ &self.bytes
+ }
+
+ /// Finish writing this Wasm module and extract ownership of the encoded
+ /// bytes.
+ pub fn finish(self) -> Vec<u8> {
+ self.bytes
+ }
+}
+
+impl Default for Module {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/code.rs b/third_party/rust/wasm-encoder/src/core/code.rs
new file mode 100644
index 0000000000..641231d04f
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/code.rs
@@ -0,0 +1,2894 @@
+use crate::{encode_section, Encode, HeapType, Section, SectionId, ValType};
+use std::borrow::Cow;
+
+/// An encoder for the code section.
+///
+/// Code sections are only supported for modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{
+/// CodeSection, Function, FunctionSection, Instruction, Module,
+/// TypeSection, ValType
+/// };
+///
+/// let mut types = TypeSection::new();
+/// types.function(vec![], vec![ValType::I32]);
+///
+/// let mut functions = FunctionSection::new();
+/// let type_index = 0;
+/// functions.function(type_index);
+///
+/// let locals = vec![];
+/// let mut func = Function::new(locals);
+/// func.instruction(&Instruction::I32Const(42));
+/// let mut code = CodeSection::new();
+/// code.function(&func);
+///
+/// let mut module = Module::new();
+/// module
+/// .section(&types)
+/// .section(&functions)
+/// .section(&code);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct CodeSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl CodeSection {
+ /// Create a new code section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of functions in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// The number of bytes already added to this section.
+ ///
+ /// This number doesn't include the vector length that precedes the
+ /// code entries, since it has a variable size that isn't known until all
+ /// functions are added.
+ pub fn byte_len(&self) -> usize {
+ self.bytes.len()
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Write a function body into this code section.
+ pub fn function(&mut self, func: &Function) -> &mut Self {
+ func.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Add a raw byte slice into this code section as a function body.
+ ///
+ /// The length prefix of the function body will be automatically prepended,
+ /// and should not be included in the raw byte slice.
+ ///
+ /// # Example
+ ///
+ /// You can use the `raw` method to copy an already-encoded function body
+ /// into a new code section encoder:
+ ///
+ /// ```
+ /// // id, size, # entries, entry
+ /// let code_section = [10, 6, 1, 4, 0, 65, 0, 11];
+ ///
+ /// // Parse the code section.
+ /// let reader = wasmparser::CodeSectionReader::new(&code_section, 0).unwrap();
+ /// let body = reader.into_iter().next().unwrap().unwrap();
+ /// let body_range = body.range();
+ ///
+ /// // Add the body to a new code section encoder by copying bytes rather
+ /// // than re-parsing and re-encoding it.
+ /// let mut encoder = wasm_encoder::CodeSection::new();
+ /// encoder.raw(&code_section[body_range.start..body_range.end]);
+ /// ```
+ pub fn raw(&mut self, data: &[u8]) -> &mut Self {
+ data.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for CodeSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for CodeSection {
+ fn id(&self) -> u8 {
+ SectionId::Code.into()
+ }
+}
+
+/// An encoder for a function body within the code section.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{CodeSection, Function, Instruction};
+///
+/// // Define the function body for:
+/// //
+/// // (func (param i32 i32) (result i32)
+/// // local.get 0
+/// // local.get 1
+/// // i32.add)
+/// let locals = vec![];
+/// let mut func = Function::new(locals);
+/// func.instruction(&Instruction::LocalGet(0));
+/// func.instruction(&Instruction::LocalGet(1));
+/// func.instruction(&Instruction::I32Add);
+///
+/// // Add our function to the code section.
+/// let mut code = CodeSection::new();
+/// code.function(&func);
+/// ```
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Function {
+ bytes: Vec<u8>,
+}
+
+impl Function {
+ /// Create a new function body with the given locals.
+ ///
+ /// The argument is an iterator over `(N, Ty)`, which defines
+ /// that the next `N` locals will be of type `Ty`.
+ ///
+ /// For example, a function with locals 0 and 1 of type I32 and
+ /// local 2 of type F32 would be created as:
+ ///
+ /// ```
+ /// # use wasm_encoder::{Function, ValType};
+ /// let f = Function::new([(2, ValType::I32), (1, ValType::F32)]);
+ /// ```
+ ///
+ /// For more information about the code section (and function definition) in the WASM binary format
+ /// see the [WebAssembly spec](https://webassembly.github.io/spec/core/binary/modules.html#binary-func)
+ pub fn new<L>(locals: L) -> Self
+ where
+ L: IntoIterator<Item = (u32, ValType)>,
+ L::IntoIter: ExactSizeIterator,
+ {
+ let locals = locals.into_iter();
+ let mut bytes = vec![];
+ locals.len().encode(&mut bytes);
+ for (count, ty) in locals {
+ count.encode(&mut bytes);
+ ty.encode(&mut bytes);
+ }
+ Function { bytes }
+ }
+
+ /// Create a function from a list of locals' types.
+ ///
+ /// Unlike [`Function::new`], this constructor simply takes a list of types
+ /// which are in order associated with locals.
+ ///
+ /// For example:
+ ///
+ /// ```
+ /// # use wasm_encoder::{Function, ValType};
+ /// let f = Function::new([(2, ValType::I32), (1, ValType::F32)]);
+ /// let g = Function::new_with_locals_types([
+ /// ValType::I32, ValType::I32, ValType::F32
+ /// ]);
+ ///
+ /// assert_eq!(f, g)
+ /// ```
+ pub fn new_with_locals_types<L>(locals: L) -> Self
+ where
+ L: IntoIterator<Item = ValType>,
+ {
+ let locals = locals.into_iter();
+
+ let mut locals_collected: Vec<(u32, ValType)> = vec![];
+ for l in locals {
+ if let Some((last_count, last_type)) = locals_collected.last_mut() {
+ if l == *last_type {
+ // Increment the count of consecutive locals of this type
+ *last_count += 1;
+ continue;
+ }
+ }
+ // If we didn't increment, a new type of local appeared
+ locals_collected.push((1, l));
+ }
+
+ Function::new(locals_collected)
+ }
+
+ /// Write an instruction into this function body.
+ pub fn instruction(&mut self, instruction: &Instruction) -> &mut Self {
+ instruction.encode(&mut self.bytes);
+ self
+ }
+
+ /// Add raw bytes to this function's body.
+ pub fn raw<B>(&mut self, bytes: B) -> &mut Self
+ where
+ B: IntoIterator<Item = u8>,
+ {
+ self.bytes.extend(bytes);
+ self
+ }
+
+ /// The number of bytes already added to this function.
+ ///
+ /// This number doesn't include the variable-width size field that `encode`
+ /// will write before the added bytes, since the size of that field isn't
+ /// known until all the instructions are added to this function.
+ pub fn byte_len(&self) -> usize {
+ self.bytes.len()
+ }
+}
+
+impl Encode for Function {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.bytes.encode(sink);
+ }
+}
+
+/// The immediate for a memory instruction.
+#[derive(Clone, Copy, Debug)]
+pub struct MemArg {
+ /// A static offset to add to the instruction's dynamic address operand.
+ ///
+ /// This is a `u64` field for the memory64 proposal, but 32-bit memories
+ /// limit offsets to at most `u32::MAX` bytes. This will be encoded as a LEB
+ /// but it won't generate a valid module if an offset is specified which is
+ /// larger than the maximum size of the index space for the memory indicated
+ /// by `memory_index`.
+ pub offset: u64,
+ /// The expected alignment of the instruction's dynamic address operand
+ /// (expressed the exponent of a power of two).
+ pub align: u32,
+ /// The index of the memory this instruction is operating upon.
+ pub memory_index: u32,
+}
+
+impl Encode for MemArg {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ if self.memory_index == 0 {
+ self.align.encode(sink);
+ self.offset.encode(sink);
+ } else {
+ (self.align | (1 << 6)).encode(sink);
+ self.memory_index.encode(sink);
+ self.offset.encode(sink);
+ }
+ }
+}
+
+/// Describe an unchecked SIMD lane index.
+pub type Lane = u8;
+
+/// The type for a `block`/`if`/`loop`.
+#[derive(Clone, Copy, Debug)]
+pub enum BlockType {
+ /// `[] -> []`
+ Empty,
+ /// `[] -> [t]`
+ Result(ValType),
+ /// The `n`th function type.
+ FunctionType(u32),
+}
+
+impl Encode for BlockType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match *self {
+ Self::Empty => sink.push(0x40),
+ Self::Result(ty) => ty.encode(sink),
+ Self::FunctionType(f) => (f as i64).encode(sink),
+ }
+ }
+}
+
+/// WebAssembly instructions.
+#[derive(Clone, Debug)]
+#[non_exhaustive]
+#[allow(missing_docs, non_camel_case_types)]
+pub enum Instruction<'a> {
+ // Control instructions.
+ Unreachable,
+ Nop,
+ Block(BlockType),
+ Loop(BlockType),
+ If(BlockType),
+ Else,
+ Try(BlockType),
+ Delegate(u32),
+ Catch(u32),
+ CatchAll,
+ End,
+ Br(u32),
+ BrIf(u32),
+ BrTable(Cow<'a, [u32]>, u32),
+ BrOnNull(u32),
+ BrOnNonNull(u32),
+ Return,
+ Call(u32),
+ CallRef(HeapType),
+ CallIndirect { ty: u32, table: u32 },
+ ReturnCallRef(HeapType),
+ ReturnCall(u32),
+ ReturnCallIndirect { ty: u32, table: u32 },
+ Throw(u32),
+ Rethrow(u32),
+
+ // Parametric instructions.
+ Drop,
+ Select,
+
+ // Variable instructions.
+ LocalGet(u32),
+ LocalSet(u32),
+ LocalTee(u32),
+ GlobalGet(u32),
+ GlobalSet(u32),
+
+ // Memory instructions.
+ I32Load(MemArg),
+ I64Load(MemArg),
+ F32Load(MemArg),
+ F64Load(MemArg),
+ I32Load8S(MemArg),
+ I32Load8U(MemArg),
+ I32Load16S(MemArg),
+ I32Load16U(MemArg),
+ I64Load8S(MemArg),
+ I64Load8U(MemArg),
+ I64Load16S(MemArg),
+ I64Load16U(MemArg),
+ I64Load32S(MemArg),
+ I64Load32U(MemArg),
+ I32Store(MemArg),
+ I64Store(MemArg),
+ F32Store(MemArg),
+ F64Store(MemArg),
+ I32Store8(MemArg),
+ I32Store16(MemArg),
+ I64Store8(MemArg),
+ I64Store16(MemArg),
+ I64Store32(MemArg),
+ MemorySize(u32),
+ MemoryGrow(u32),
+ MemoryInit { mem: u32, data_index: u32 },
+ DataDrop(u32),
+ MemoryCopy { src_mem: u32, dst_mem: u32 },
+ MemoryFill(u32),
+ MemoryDiscard(u32),
+
+ // Numeric instructions.
+ I32Const(i32),
+ I64Const(i64),
+ F32Const(f32),
+ F64Const(f64),
+ I32Eqz,
+ I32Eq,
+ I32Ne,
+ I32LtS,
+ I32LtU,
+ I32GtS,
+ I32GtU,
+ I32LeS,
+ I32LeU,
+ I32GeS,
+ I32GeU,
+ I64Eqz,
+ I64Eq,
+ I64Ne,
+ I64LtS,
+ I64LtU,
+ I64GtS,
+ I64GtU,
+ I64LeS,
+ I64LeU,
+ I64GeS,
+ I64GeU,
+ F32Eq,
+ F32Ne,
+ F32Lt,
+ F32Gt,
+ F32Le,
+ F32Ge,
+ F64Eq,
+ F64Ne,
+ F64Lt,
+ F64Gt,
+ F64Le,
+ F64Ge,
+ I32Clz,
+ I32Ctz,
+ I32Popcnt,
+ I32Add,
+ I32Sub,
+ I32Mul,
+ I32DivS,
+ I32DivU,
+ I32RemS,
+ I32RemU,
+ I32And,
+ I32Or,
+ I32Xor,
+ I32Shl,
+ I32ShrS,
+ I32ShrU,
+ I32Rotl,
+ I32Rotr,
+ I64Clz,
+ I64Ctz,
+ I64Popcnt,
+ I64Add,
+ I64Sub,
+ I64Mul,
+ I64DivS,
+ I64DivU,
+ I64RemS,
+ I64RemU,
+ I64And,
+ I64Or,
+ I64Xor,
+ I64Shl,
+ I64ShrS,
+ I64ShrU,
+ I64Rotl,
+ I64Rotr,
+ F32Abs,
+ F32Neg,
+ F32Ceil,
+ F32Floor,
+ F32Trunc,
+ F32Nearest,
+ F32Sqrt,
+ F32Add,
+ F32Sub,
+ F32Mul,
+ F32Div,
+ F32Min,
+ F32Max,
+ F32Copysign,
+ F64Abs,
+ F64Neg,
+ F64Ceil,
+ F64Floor,
+ F64Trunc,
+ F64Nearest,
+ F64Sqrt,
+ F64Add,
+ F64Sub,
+ F64Mul,
+ F64Div,
+ F64Min,
+ F64Max,
+ F64Copysign,
+ I32WrapI64,
+ I32TruncF32S,
+ I32TruncF32U,
+ I32TruncF64S,
+ I32TruncF64U,
+ I64ExtendI32S,
+ I64ExtendI32U,
+ I64TruncF32S,
+ I64TruncF32U,
+ I64TruncF64S,
+ I64TruncF64U,
+ F32ConvertI32S,
+ F32ConvertI32U,
+ F32ConvertI64S,
+ F32ConvertI64U,
+ F32DemoteF64,
+ F64ConvertI32S,
+ F64ConvertI32U,
+ F64ConvertI64S,
+ F64ConvertI64U,
+ F64PromoteF32,
+ I32ReinterpretF32,
+ I64ReinterpretF64,
+ F32ReinterpretI32,
+ F64ReinterpretI64,
+ I32Extend8S,
+ I32Extend16S,
+ I64Extend8S,
+ I64Extend16S,
+ I64Extend32S,
+ I32TruncSatF32S,
+ I32TruncSatF32U,
+ I32TruncSatF64S,
+ I32TruncSatF64U,
+ I64TruncSatF32S,
+ I64TruncSatF32U,
+ I64TruncSatF64S,
+ I64TruncSatF64U,
+
+ // Reference types instructions.
+ TypedSelect(ValType),
+ RefNull(HeapType),
+ RefIsNull,
+ RefFunc(u32),
+ RefAsNonNull,
+
+ // Bulk memory instructions.
+ TableInit { elem_index: u32, table: u32 },
+ ElemDrop(u32),
+ TableFill(u32),
+ TableSet(u32),
+ TableGet(u32),
+ TableGrow(u32),
+ TableSize(u32),
+ TableCopy { src_table: u32, dst_table: u32 },
+
+ // SIMD instructions.
+ V128Load(MemArg),
+ V128Load8x8S(MemArg),
+ V128Load8x8U(MemArg),
+ V128Load16x4S(MemArg),
+ V128Load16x4U(MemArg),
+ V128Load32x2S(MemArg),
+ V128Load32x2U(MemArg),
+ V128Load8Splat(MemArg),
+ V128Load16Splat(MemArg),
+ V128Load32Splat(MemArg),
+ V128Load64Splat(MemArg),
+ V128Load32Zero(MemArg),
+ V128Load64Zero(MemArg),
+ V128Store(MemArg),
+ V128Load8Lane { memarg: MemArg, lane: Lane },
+ V128Load16Lane { memarg: MemArg, lane: Lane },
+ V128Load32Lane { memarg: MemArg, lane: Lane },
+ V128Load64Lane { memarg: MemArg, lane: Lane },
+ V128Store8Lane { memarg: MemArg, lane: Lane },
+ V128Store16Lane { memarg: MemArg, lane: Lane },
+ V128Store32Lane { memarg: MemArg, lane: Lane },
+ V128Store64Lane { memarg: MemArg, lane: Lane },
+ V128Const(i128),
+ I8x16Shuffle([Lane; 16]),
+ I8x16ExtractLaneS(Lane),
+ I8x16ExtractLaneU(Lane),
+ I8x16ReplaceLane(Lane),
+ I16x8ExtractLaneS(Lane),
+ I16x8ExtractLaneU(Lane),
+ I16x8ReplaceLane(Lane),
+ I32x4ExtractLane(Lane),
+ I32x4ReplaceLane(Lane),
+ I64x2ExtractLane(Lane),
+ I64x2ReplaceLane(Lane),
+ F32x4ExtractLane(Lane),
+ F32x4ReplaceLane(Lane),
+ F64x2ExtractLane(Lane),
+ F64x2ReplaceLane(Lane),
+ I8x16Swizzle,
+ I8x16Splat,
+ I16x8Splat,
+ I32x4Splat,
+ I64x2Splat,
+ F32x4Splat,
+ F64x2Splat,
+ I8x16Eq,
+ I8x16Ne,
+ I8x16LtS,
+ I8x16LtU,
+ I8x16GtS,
+ I8x16GtU,
+ I8x16LeS,
+ I8x16LeU,
+ I8x16GeS,
+ I8x16GeU,
+ I16x8Eq,
+ I16x8Ne,
+ I16x8LtS,
+ I16x8LtU,
+ I16x8GtS,
+ I16x8GtU,
+ I16x8LeS,
+ I16x8LeU,
+ I16x8GeS,
+ I16x8GeU,
+ I32x4Eq,
+ I32x4Ne,
+ I32x4LtS,
+ I32x4LtU,
+ I32x4GtS,
+ I32x4GtU,
+ I32x4LeS,
+ I32x4LeU,
+ I32x4GeS,
+ I32x4GeU,
+ I64x2Eq,
+ I64x2Ne,
+ I64x2LtS,
+ I64x2GtS,
+ I64x2LeS,
+ I64x2GeS,
+ F32x4Eq,
+ F32x4Ne,
+ F32x4Lt,
+ F32x4Gt,
+ F32x4Le,
+ F32x4Ge,
+ F64x2Eq,
+ F64x2Ne,
+ F64x2Lt,
+ F64x2Gt,
+ F64x2Le,
+ F64x2Ge,
+ V128Not,
+ V128And,
+ V128AndNot,
+ V128Or,
+ V128Xor,
+ V128Bitselect,
+ V128AnyTrue,
+ I8x16Abs,
+ I8x16Neg,
+ I8x16Popcnt,
+ I8x16AllTrue,
+ I8x16Bitmask,
+ I8x16NarrowI16x8S,
+ I8x16NarrowI16x8U,
+ I8x16Shl,
+ I8x16ShrS,
+ I8x16ShrU,
+ I8x16Add,
+ I8x16AddSatS,
+ I8x16AddSatU,
+ I8x16Sub,
+ I8x16SubSatS,
+ I8x16SubSatU,
+ I8x16MinS,
+ I8x16MinU,
+ I8x16MaxS,
+ I8x16MaxU,
+ I8x16AvgrU,
+ I16x8ExtAddPairwiseI8x16S,
+ I16x8ExtAddPairwiseI8x16U,
+ I16x8Abs,
+ I16x8Neg,
+ I16x8Q15MulrSatS,
+ I16x8AllTrue,
+ I16x8Bitmask,
+ I16x8NarrowI32x4S,
+ I16x8NarrowI32x4U,
+ I16x8ExtendLowI8x16S,
+ I16x8ExtendHighI8x16S,
+ I16x8ExtendLowI8x16U,
+ I16x8ExtendHighI8x16U,
+ I16x8Shl,
+ I16x8ShrS,
+ I16x8ShrU,
+ I16x8Add,
+ I16x8AddSatS,
+ I16x8AddSatU,
+ I16x8Sub,
+ I16x8SubSatS,
+ I16x8SubSatU,
+ I16x8Mul,
+ I16x8MinS,
+ I16x8MinU,
+ I16x8MaxS,
+ I16x8MaxU,
+ I16x8AvgrU,
+ I16x8ExtMulLowI8x16S,
+ I16x8ExtMulHighI8x16S,
+ I16x8ExtMulLowI8x16U,
+ I16x8ExtMulHighI8x16U,
+ I32x4ExtAddPairwiseI16x8S,
+ I32x4ExtAddPairwiseI16x8U,
+ I32x4Abs,
+ I32x4Neg,
+ I32x4AllTrue,
+ I32x4Bitmask,
+ I32x4ExtendLowI16x8S,
+ I32x4ExtendHighI16x8S,
+ I32x4ExtendLowI16x8U,
+ I32x4ExtendHighI16x8U,
+ I32x4Shl,
+ I32x4ShrS,
+ I32x4ShrU,
+ I32x4Add,
+ I32x4Sub,
+ I32x4Mul,
+ I32x4MinS,
+ I32x4MinU,
+ I32x4MaxS,
+ I32x4MaxU,
+ I32x4DotI16x8S,
+ I32x4ExtMulLowI16x8S,
+ I32x4ExtMulHighI16x8S,
+ I32x4ExtMulLowI16x8U,
+ I32x4ExtMulHighI16x8U,
+ I64x2Abs,
+ I64x2Neg,
+ I64x2AllTrue,
+ I64x2Bitmask,
+ I64x2ExtendLowI32x4S,
+ I64x2ExtendHighI32x4S,
+ I64x2ExtendLowI32x4U,
+ I64x2ExtendHighI32x4U,
+ I64x2Shl,
+ I64x2ShrS,
+ I64x2ShrU,
+ I64x2Add,
+ I64x2Sub,
+ I64x2Mul,
+ I64x2ExtMulLowI32x4S,
+ I64x2ExtMulHighI32x4S,
+ I64x2ExtMulLowI32x4U,
+ I64x2ExtMulHighI32x4U,
+ F32x4Ceil,
+ F32x4Floor,
+ F32x4Trunc,
+ F32x4Nearest,
+ F32x4Abs,
+ F32x4Neg,
+ F32x4Sqrt,
+ F32x4Add,
+ F32x4Sub,
+ F32x4Mul,
+ F32x4Div,
+ F32x4Min,
+ F32x4Max,
+ F32x4PMin,
+ F32x4PMax,
+ F64x2Ceil,
+ F64x2Floor,
+ F64x2Trunc,
+ F64x2Nearest,
+ F64x2Abs,
+ F64x2Neg,
+ F64x2Sqrt,
+ F64x2Add,
+ F64x2Sub,
+ F64x2Mul,
+ F64x2Div,
+ F64x2Min,
+ F64x2Max,
+ F64x2PMin,
+ F64x2PMax,
+ I32x4TruncSatF32x4S,
+ I32x4TruncSatF32x4U,
+ F32x4ConvertI32x4S,
+ F32x4ConvertI32x4U,
+ I32x4TruncSatF64x2SZero,
+ I32x4TruncSatF64x2UZero,
+ F64x2ConvertLowI32x4S,
+ F64x2ConvertLowI32x4U,
+ F32x4DemoteF64x2Zero,
+ F64x2PromoteLowF32x4,
+
+ // Relaxed simd proposal
+ I8x16RelaxedSwizzle,
+ I32x4RelaxedTruncF32x4S,
+ I32x4RelaxedTruncF32x4U,
+ I32x4RelaxedTruncF64x2SZero,
+ I32x4RelaxedTruncF64x2UZero,
+ F32x4RelaxedMadd,
+ F32x4RelaxedNmadd,
+ F64x2RelaxedMadd,
+ F64x2RelaxedNmadd,
+ I8x16RelaxedLaneselect,
+ I16x8RelaxedLaneselect,
+ I32x4RelaxedLaneselect,
+ I64x2RelaxedLaneselect,
+ F32x4RelaxedMin,
+ F32x4RelaxedMax,
+ F64x2RelaxedMin,
+ F64x2RelaxedMax,
+ I16x8RelaxedQ15mulrS,
+ I16x8RelaxedDotI8x16I7x16S,
+ I32x4RelaxedDotI8x16I7x16AddS,
+
+ // Atomic instructions (the threads proposal)
+ MemoryAtomicNotify(MemArg),
+ MemoryAtomicWait32(MemArg),
+ MemoryAtomicWait64(MemArg),
+ AtomicFence,
+ I32AtomicLoad(MemArg),
+ I64AtomicLoad(MemArg),
+ I32AtomicLoad8U(MemArg),
+ I32AtomicLoad16U(MemArg),
+ I64AtomicLoad8U(MemArg),
+ I64AtomicLoad16U(MemArg),
+ I64AtomicLoad32U(MemArg),
+ I32AtomicStore(MemArg),
+ I64AtomicStore(MemArg),
+ I32AtomicStore8(MemArg),
+ I32AtomicStore16(MemArg),
+ I64AtomicStore8(MemArg),
+ I64AtomicStore16(MemArg),
+ I64AtomicStore32(MemArg),
+ I32AtomicRmwAdd(MemArg),
+ I64AtomicRmwAdd(MemArg),
+ I32AtomicRmw8AddU(MemArg),
+ I32AtomicRmw16AddU(MemArg),
+ I64AtomicRmw8AddU(MemArg),
+ I64AtomicRmw16AddU(MemArg),
+ I64AtomicRmw32AddU(MemArg),
+ I32AtomicRmwSub(MemArg),
+ I64AtomicRmwSub(MemArg),
+ I32AtomicRmw8SubU(MemArg),
+ I32AtomicRmw16SubU(MemArg),
+ I64AtomicRmw8SubU(MemArg),
+ I64AtomicRmw16SubU(MemArg),
+ I64AtomicRmw32SubU(MemArg),
+ I32AtomicRmwAnd(MemArg),
+ I64AtomicRmwAnd(MemArg),
+ I32AtomicRmw8AndU(MemArg),
+ I32AtomicRmw16AndU(MemArg),
+ I64AtomicRmw8AndU(MemArg),
+ I64AtomicRmw16AndU(MemArg),
+ I64AtomicRmw32AndU(MemArg),
+ I32AtomicRmwOr(MemArg),
+ I64AtomicRmwOr(MemArg),
+ I32AtomicRmw8OrU(MemArg),
+ I32AtomicRmw16OrU(MemArg),
+ I64AtomicRmw8OrU(MemArg),
+ I64AtomicRmw16OrU(MemArg),
+ I64AtomicRmw32OrU(MemArg),
+ I32AtomicRmwXor(MemArg),
+ I64AtomicRmwXor(MemArg),
+ I32AtomicRmw8XorU(MemArg),
+ I32AtomicRmw16XorU(MemArg),
+ I64AtomicRmw8XorU(MemArg),
+ I64AtomicRmw16XorU(MemArg),
+ I64AtomicRmw32XorU(MemArg),
+ I32AtomicRmwXchg(MemArg),
+ I64AtomicRmwXchg(MemArg),
+ I32AtomicRmw8XchgU(MemArg),
+ I32AtomicRmw16XchgU(MemArg),
+ I64AtomicRmw8XchgU(MemArg),
+ I64AtomicRmw16XchgU(MemArg),
+ I64AtomicRmw32XchgU(MemArg),
+ I32AtomicRmwCmpxchg(MemArg),
+ I64AtomicRmwCmpxchg(MemArg),
+ I32AtomicRmw8CmpxchgU(MemArg),
+ I32AtomicRmw16CmpxchgU(MemArg),
+ I64AtomicRmw8CmpxchgU(MemArg),
+ I64AtomicRmw16CmpxchgU(MemArg),
+ I64AtomicRmw32CmpxchgU(MemArg),
+}
+
+impl Encode for Instruction<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match *self {
+ // Control instructions.
+ Instruction::Unreachable => sink.push(0x00),
+ Instruction::Nop => sink.push(0x01),
+ Instruction::Block(bt) => {
+ sink.push(0x02);
+ bt.encode(sink);
+ }
+ Instruction::Loop(bt) => {
+ sink.push(0x03);
+ bt.encode(sink);
+ }
+ Instruction::If(bt) => {
+ sink.push(0x04);
+ bt.encode(sink);
+ }
+ Instruction::Else => sink.push(0x05),
+ Instruction::Try(bt) => {
+ sink.push(0x06);
+ bt.encode(sink);
+ }
+ Instruction::Catch(t) => {
+ sink.push(0x07);
+ t.encode(sink);
+ }
+ Instruction::Throw(t) => {
+ sink.push(0x08);
+ t.encode(sink);
+ }
+ Instruction::Rethrow(l) => {
+ sink.push(0x09);
+ l.encode(sink);
+ }
+ Instruction::End => sink.push(0x0B),
+ Instruction::Br(l) => {
+ sink.push(0x0C);
+ l.encode(sink);
+ }
+ Instruction::BrIf(l) => {
+ sink.push(0x0D);
+ l.encode(sink);
+ }
+ Instruction::BrTable(ref ls, l) => {
+ sink.push(0x0E);
+ ls.encode(sink);
+ l.encode(sink);
+ }
+ Instruction::BrOnNull(l) => {
+ sink.push(0xD4);
+ l.encode(sink);
+ }
+ Instruction::BrOnNonNull(l) => {
+ sink.push(0xD6);
+ l.encode(sink);
+ }
+ Instruction::Return => sink.push(0x0F),
+ Instruction::Call(f) => {
+ sink.push(0x10);
+ f.encode(sink);
+ }
+ Instruction::CallRef(ty) => {
+ sink.push(0x14);
+ ty.encode(sink);
+ }
+ Instruction::CallIndirect { ty, table } => {
+ sink.push(0x11);
+ ty.encode(sink);
+ table.encode(sink);
+ }
+ Instruction::ReturnCallRef(ty) => {
+ sink.push(0x15);
+ ty.encode(sink);
+ }
+
+ Instruction::ReturnCall(f) => {
+ sink.push(0x12);
+ f.encode(sink);
+ }
+ Instruction::ReturnCallIndirect { ty, table } => {
+ sink.push(0x13);
+ ty.encode(sink);
+ table.encode(sink);
+ }
+ Instruction::Delegate(l) => {
+ sink.push(0x18);
+ l.encode(sink);
+ }
+ Instruction::CatchAll => {
+ sink.push(0x19);
+ }
+
+ // Parametric instructions.
+ Instruction::Drop => sink.push(0x1A),
+ Instruction::Select => sink.push(0x1B),
+ Instruction::TypedSelect(ty) => {
+ sink.push(0x1c);
+ [ty].encode(sink);
+ }
+
+ // Variable instructions.
+ Instruction::LocalGet(l) => {
+ sink.push(0x20);
+ l.encode(sink);
+ }
+ Instruction::LocalSet(l) => {
+ sink.push(0x21);
+ l.encode(sink);
+ }
+ Instruction::LocalTee(l) => {
+ sink.push(0x22);
+ l.encode(sink);
+ }
+ Instruction::GlobalGet(g) => {
+ sink.push(0x23);
+ g.encode(sink);
+ }
+ Instruction::GlobalSet(g) => {
+ sink.push(0x24);
+ g.encode(sink);
+ }
+ Instruction::TableGet(table) => {
+ sink.push(0x25);
+ table.encode(sink);
+ }
+ Instruction::TableSet(table) => {
+ sink.push(0x26);
+ table.encode(sink);
+ }
+
+ // Memory instructions.
+ Instruction::I32Load(m) => {
+ sink.push(0x28);
+ m.encode(sink);
+ }
+ Instruction::I64Load(m) => {
+ sink.push(0x29);
+ m.encode(sink);
+ }
+ Instruction::F32Load(m) => {
+ sink.push(0x2A);
+ m.encode(sink);
+ }
+ Instruction::F64Load(m) => {
+ sink.push(0x2B);
+ m.encode(sink);
+ }
+ Instruction::I32Load8S(m) => {
+ sink.push(0x2C);
+ m.encode(sink);
+ }
+ Instruction::I32Load8U(m) => {
+ sink.push(0x2D);
+ m.encode(sink);
+ }
+ Instruction::I32Load16S(m) => {
+ sink.push(0x2E);
+ m.encode(sink);
+ }
+ Instruction::I32Load16U(m) => {
+ sink.push(0x2F);
+ m.encode(sink);
+ }
+ Instruction::I64Load8S(m) => {
+ sink.push(0x30);
+ m.encode(sink);
+ }
+ Instruction::I64Load8U(m) => {
+ sink.push(0x31);
+ m.encode(sink);
+ }
+ Instruction::I64Load16S(m) => {
+ sink.push(0x32);
+ m.encode(sink);
+ }
+ Instruction::I64Load16U(m) => {
+ sink.push(0x33);
+ m.encode(sink);
+ }
+ Instruction::I64Load32S(m) => {
+ sink.push(0x34);
+ m.encode(sink);
+ }
+ Instruction::I64Load32U(m) => {
+ sink.push(0x35);
+ m.encode(sink);
+ }
+ Instruction::I32Store(m) => {
+ sink.push(0x36);
+ m.encode(sink);
+ }
+ Instruction::I64Store(m) => {
+ sink.push(0x37);
+ m.encode(sink);
+ }
+ Instruction::F32Store(m) => {
+ sink.push(0x38);
+ m.encode(sink);
+ }
+ Instruction::F64Store(m) => {
+ sink.push(0x39);
+ m.encode(sink);
+ }
+ Instruction::I32Store8(m) => {
+ sink.push(0x3A);
+ m.encode(sink);
+ }
+ Instruction::I32Store16(m) => {
+ sink.push(0x3B);
+ m.encode(sink);
+ }
+ Instruction::I64Store8(m) => {
+ sink.push(0x3C);
+ m.encode(sink);
+ }
+ Instruction::I64Store16(m) => {
+ sink.push(0x3D);
+ m.encode(sink);
+ }
+ Instruction::I64Store32(m) => {
+ sink.push(0x3E);
+ m.encode(sink);
+ }
+ Instruction::MemorySize(i) => {
+ sink.push(0x3F);
+ i.encode(sink);
+ }
+ Instruction::MemoryGrow(i) => {
+ sink.push(0x40);
+ i.encode(sink);
+ }
+ Instruction::MemoryInit { mem, data_index } => {
+ sink.push(0xfc);
+ sink.push(0x08);
+ data_index.encode(sink);
+ mem.encode(sink);
+ }
+ Instruction::DataDrop(data) => {
+ sink.push(0xfc);
+ sink.push(0x09);
+ data.encode(sink);
+ }
+ Instruction::MemoryCopy { src_mem, dst_mem } => {
+ sink.push(0xfc);
+ sink.push(0x0a);
+ dst_mem.encode(sink);
+ src_mem.encode(sink);
+ }
+ Instruction::MemoryFill(mem) => {
+ sink.push(0xfc);
+ sink.push(0x0b);
+ mem.encode(sink);
+ }
+ Instruction::MemoryDiscard(mem) => {
+ sink.push(0xfc);
+ sink.push(0x12);
+ mem.encode(sink);
+ }
+
+ // Numeric instructions.
+ Instruction::I32Const(x) => {
+ sink.push(0x41);
+ x.encode(sink);
+ }
+ Instruction::I64Const(x) => {
+ sink.push(0x42);
+ x.encode(sink);
+ }
+ Instruction::F32Const(x) => {
+ sink.push(0x43);
+ let x = x.to_bits();
+ sink.extend(x.to_le_bytes().iter().copied());
+ }
+ Instruction::F64Const(x) => {
+ sink.push(0x44);
+ let x = x.to_bits();
+ sink.extend(x.to_le_bytes().iter().copied());
+ }
+ Instruction::I32Eqz => sink.push(0x45),
+ Instruction::I32Eq => sink.push(0x46),
+ Instruction::I32Ne => sink.push(0x47),
+ Instruction::I32LtS => sink.push(0x48),
+ Instruction::I32LtU => sink.push(0x49),
+ Instruction::I32GtS => sink.push(0x4A),
+ Instruction::I32GtU => sink.push(0x4B),
+ Instruction::I32LeS => sink.push(0x4C),
+ Instruction::I32LeU => sink.push(0x4D),
+ Instruction::I32GeS => sink.push(0x4E),
+ Instruction::I32GeU => sink.push(0x4F),
+ Instruction::I64Eqz => sink.push(0x50),
+ Instruction::I64Eq => sink.push(0x51),
+ Instruction::I64Ne => sink.push(0x52),
+ Instruction::I64LtS => sink.push(0x53),
+ Instruction::I64LtU => sink.push(0x54),
+ Instruction::I64GtS => sink.push(0x55),
+ Instruction::I64GtU => sink.push(0x56),
+ Instruction::I64LeS => sink.push(0x57),
+ Instruction::I64LeU => sink.push(0x58),
+ Instruction::I64GeS => sink.push(0x59),
+ Instruction::I64GeU => sink.push(0x5A),
+ Instruction::F32Eq => sink.push(0x5B),
+ Instruction::F32Ne => sink.push(0x5C),
+ Instruction::F32Lt => sink.push(0x5D),
+ Instruction::F32Gt => sink.push(0x5E),
+ Instruction::F32Le => sink.push(0x5F),
+ Instruction::F32Ge => sink.push(0x60),
+ Instruction::F64Eq => sink.push(0x61),
+ Instruction::F64Ne => sink.push(0x62),
+ Instruction::F64Lt => sink.push(0x63),
+ Instruction::F64Gt => sink.push(0x64),
+ Instruction::F64Le => sink.push(0x65),
+ Instruction::F64Ge => sink.push(0x66),
+ Instruction::I32Clz => sink.push(0x67),
+ Instruction::I32Ctz => sink.push(0x68),
+ Instruction::I32Popcnt => sink.push(0x69),
+ Instruction::I32Add => sink.push(0x6A),
+ Instruction::I32Sub => sink.push(0x6B),
+ Instruction::I32Mul => sink.push(0x6C),
+ Instruction::I32DivS => sink.push(0x6D),
+ Instruction::I32DivU => sink.push(0x6E),
+ Instruction::I32RemS => sink.push(0x6F),
+ Instruction::I32RemU => sink.push(0x70),
+ Instruction::I32And => sink.push(0x71),
+ Instruction::I32Or => sink.push(0x72),
+ Instruction::I32Xor => sink.push(0x73),
+ Instruction::I32Shl => sink.push(0x74),
+ Instruction::I32ShrS => sink.push(0x75),
+ Instruction::I32ShrU => sink.push(0x76),
+ Instruction::I32Rotl => sink.push(0x77),
+ Instruction::I32Rotr => sink.push(0x78),
+ Instruction::I64Clz => sink.push(0x79),
+ Instruction::I64Ctz => sink.push(0x7A),
+ Instruction::I64Popcnt => sink.push(0x7B),
+ Instruction::I64Add => sink.push(0x7C),
+ Instruction::I64Sub => sink.push(0x7D),
+ Instruction::I64Mul => sink.push(0x7E),
+ Instruction::I64DivS => sink.push(0x7F),
+ Instruction::I64DivU => sink.push(0x80),
+ Instruction::I64RemS => sink.push(0x81),
+ Instruction::I64RemU => sink.push(0x82),
+ Instruction::I64And => sink.push(0x83),
+ Instruction::I64Or => sink.push(0x84),
+ Instruction::I64Xor => sink.push(0x85),
+ Instruction::I64Shl => sink.push(0x86),
+ Instruction::I64ShrS => sink.push(0x87),
+ Instruction::I64ShrU => sink.push(0x88),
+ Instruction::I64Rotl => sink.push(0x89),
+ Instruction::I64Rotr => sink.push(0x8A),
+ Instruction::F32Abs => sink.push(0x8B),
+ Instruction::F32Neg => sink.push(0x8C),
+ Instruction::F32Ceil => sink.push(0x8D),
+ Instruction::F32Floor => sink.push(0x8E),
+ Instruction::F32Trunc => sink.push(0x8F),
+ Instruction::F32Nearest => sink.push(0x90),
+ Instruction::F32Sqrt => sink.push(0x91),
+ Instruction::F32Add => sink.push(0x92),
+ Instruction::F32Sub => sink.push(0x93),
+ Instruction::F32Mul => sink.push(0x94),
+ Instruction::F32Div => sink.push(0x95),
+ Instruction::F32Min => sink.push(0x96),
+ Instruction::F32Max => sink.push(0x97),
+ Instruction::F32Copysign => sink.push(0x98),
+ Instruction::F64Abs => sink.push(0x99),
+ Instruction::F64Neg => sink.push(0x9A),
+ Instruction::F64Ceil => sink.push(0x9B),
+ Instruction::F64Floor => sink.push(0x9C),
+ Instruction::F64Trunc => sink.push(0x9D),
+ Instruction::F64Nearest => sink.push(0x9E),
+ Instruction::F64Sqrt => sink.push(0x9F),
+ Instruction::F64Add => sink.push(0xA0),
+ Instruction::F64Sub => sink.push(0xA1),
+ Instruction::F64Mul => sink.push(0xA2),
+ Instruction::F64Div => sink.push(0xA3),
+ Instruction::F64Min => sink.push(0xA4),
+ Instruction::F64Max => sink.push(0xA5),
+ Instruction::F64Copysign => sink.push(0xA6),
+ Instruction::I32WrapI64 => sink.push(0xA7),
+ Instruction::I32TruncF32S => sink.push(0xA8),
+ Instruction::I32TruncF32U => sink.push(0xA9),
+ Instruction::I32TruncF64S => sink.push(0xAA),
+ Instruction::I32TruncF64U => sink.push(0xAB),
+ Instruction::I64ExtendI32S => sink.push(0xAC),
+ Instruction::I64ExtendI32U => sink.push(0xAD),
+ Instruction::I64TruncF32S => sink.push(0xAE),
+ Instruction::I64TruncF32U => sink.push(0xAF),
+ Instruction::I64TruncF64S => sink.push(0xB0),
+ Instruction::I64TruncF64U => sink.push(0xB1),
+ Instruction::F32ConvertI32S => sink.push(0xB2),
+ Instruction::F32ConvertI32U => sink.push(0xB3),
+ Instruction::F32ConvertI64S => sink.push(0xB4),
+ Instruction::F32ConvertI64U => sink.push(0xB5),
+ Instruction::F32DemoteF64 => sink.push(0xB6),
+ Instruction::F64ConvertI32S => sink.push(0xB7),
+ Instruction::F64ConvertI32U => sink.push(0xB8),
+ Instruction::F64ConvertI64S => sink.push(0xB9),
+ Instruction::F64ConvertI64U => sink.push(0xBA),
+ Instruction::F64PromoteF32 => sink.push(0xBB),
+ Instruction::I32ReinterpretF32 => sink.push(0xBC),
+ Instruction::I64ReinterpretF64 => sink.push(0xBD),
+ Instruction::F32ReinterpretI32 => sink.push(0xBE),
+ Instruction::F64ReinterpretI64 => sink.push(0xBF),
+ Instruction::I32Extend8S => sink.push(0xC0),
+ Instruction::I32Extend16S => sink.push(0xC1),
+ Instruction::I64Extend8S => sink.push(0xC2),
+ Instruction::I64Extend16S => sink.push(0xC3),
+ Instruction::I64Extend32S => sink.push(0xC4),
+
+ Instruction::I32TruncSatF32S => {
+ sink.push(0xFC);
+ sink.push(0x00);
+ }
+ Instruction::I32TruncSatF32U => {
+ sink.push(0xFC);
+ sink.push(0x01);
+ }
+ Instruction::I32TruncSatF64S => {
+ sink.push(0xFC);
+ sink.push(0x02);
+ }
+ Instruction::I32TruncSatF64U => {
+ sink.push(0xFC);
+ sink.push(0x03);
+ }
+ Instruction::I64TruncSatF32S => {
+ sink.push(0xFC);
+ sink.push(0x04);
+ }
+ Instruction::I64TruncSatF32U => {
+ sink.push(0xFC);
+ sink.push(0x05);
+ }
+ Instruction::I64TruncSatF64S => {
+ sink.push(0xFC);
+ sink.push(0x06);
+ }
+ Instruction::I64TruncSatF64U => {
+ sink.push(0xFC);
+ sink.push(0x07);
+ }
+
+ // Reference types instructions.
+ Instruction::RefNull(ty) => {
+ sink.push(0xd0);
+ ty.encode(sink);
+ }
+ Instruction::RefIsNull => sink.push(0xd1),
+ Instruction::RefFunc(f) => {
+ sink.push(0xd2);
+ f.encode(sink);
+ }
+ Instruction::RefAsNonNull => sink.push(0xD3),
+
+ // Bulk memory instructions.
+ Instruction::TableInit { elem_index, table } => {
+ sink.push(0xfc);
+ sink.push(0x0c);
+ elem_index.encode(sink);
+ table.encode(sink);
+ }
+ Instruction::ElemDrop(segment) => {
+ sink.push(0xfc);
+ sink.push(0x0d);
+ segment.encode(sink);
+ }
+ Instruction::TableCopy {
+ src_table,
+ dst_table,
+ } => {
+ sink.push(0xfc);
+ sink.push(0x0e);
+ dst_table.encode(sink);
+ src_table.encode(sink);
+ }
+ Instruction::TableGrow(table) => {
+ sink.push(0xfc);
+ sink.push(0x0f);
+ table.encode(sink);
+ }
+ Instruction::TableSize(table) => {
+ sink.push(0xfc);
+ sink.push(0x10);
+ table.encode(sink);
+ }
+ Instruction::TableFill(table) => {
+ sink.push(0xfc);
+ sink.push(0x11);
+ table.encode(sink);
+ }
+
+ // SIMD instructions.
+ Instruction::V128Load(memarg) => {
+ sink.push(0xFD);
+ 0x00u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load8x8S(memarg) => {
+ sink.push(0xFD);
+ 0x01u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load8x8U(memarg) => {
+ sink.push(0xFD);
+ 0x02u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load16x4S(memarg) => {
+ sink.push(0xFD);
+ 0x03u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load16x4U(memarg) => {
+ sink.push(0xFD);
+ 0x04u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load32x2S(memarg) => {
+ sink.push(0xFD);
+ 0x05u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load32x2U(memarg) => {
+ sink.push(0xFD);
+ 0x06u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load8Splat(memarg) => {
+ sink.push(0xFD);
+ 0x07u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load16Splat(memarg) => {
+ sink.push(0xFD);
+ 0x08u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load32Splat(memarg) => {
+ sink.push(0xFD);
+ 0x09u32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load64Splat(memarg) => {
+ sink.push(0xFD);
+ 0x0Au32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Store(memarg) => {
+ sink.push(0xFD);
+ 0x0Bu32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Const(x) => {
+ sink.push(0xFD);
+ 0x0Cu32.encode(sink);
+ sink.extend(x.to_le_bytes().iter().copied());
+ }
+ Instruction::I8x16Shuffle(lanes) => {
+ sink.push(0xFD);
+ 0x0Du32.encode(sink);
+ assert!(lanes.iter().all(|l: &u8| *l < 32));
+ sink.extend(lanes.iter().copied());
+ }
+ Instruction::I8x16Swizzle => {
+ sink.push(0xFD);
+ 0x0Eu32.encode(sink);
+ }
+ Instruction::I8x16Splat => {
+ sink.push(0xFD);
+ 0x0Fu32.encode(sink);
+ }
+ Instruction::I16x8Splat => {
+ sink.push(0xFD);
+ 0x10u32.encode(sink);
+ }
+ Instruction::I32x4Splat => {
+ sink.push(0xFD);
+ 0x11u32.encode(sink);
+ }
+ Instruction::I64x2Splat => {
+ sink.push(0xFD);
+ 0x12u32.encode(sink);
+ }
+ Instruction::F32x4Splat => {
+ sink.push(0xFD);
+ 0x13u32.encode(sink);
+ }
+ Instruction::F64x2Splat => {
+ sink.push(0xFD);
+ 0x14u32.encode(sink);
+ }
+ Instruction::I8x16ExtractLaneS(lane) => {
+ sink.push(0xFD);
+ 0x15u32.encode(sink);
+ assert!(lane < 16);
+ sink.push(lane);
+ }
+ Instruction::I8x16ExtractLaneU(lane) => {
+ sink.push(0xFD);
+ 0x16u32.encode(sink);
+ assert!(lane < 16);
+ sink.push(lane);
+ }
+ Instruction::I8x16ReplaceLane(lane) => {
+ sink.push(0xFD);
+ 0x17u32.encode(sink);
+ assert!(lane < 16);
+ sink.push(lane);
+ }
+ Instruction::I16x8ExtractLaneS(lane) => {
+ sink.push(0xFD);
+ 0x18u32.encode(sink);
+ assert!(lane < 8);
+ sink.push(lane);
+ }
+ Instruction::I16x8ExtractLaneU(lane) => {
+ sink.push(0xFD);
+ 0x19u32.encode(sink);
+ assert!(lane < 8);
+ sink.push(lane);
+ }
+ Instruction::I16x8ReplaceLane(lane) => {
+ sink.push(0xFD);
+ 0x1Au32.encode(sink);
+ assert!(lane < 8);
+ sink.push(lane);
+ }
+ Instruction::I32x4ExtractLane(lane) => {
+ sink.push(0xFD);
+ 0x1Bu32.encode(sink);
+ assert!(lane < 4);
+ sink.push(lane);
+ }
+ Instruction::I32x4ReplaceLane(lane) => {
+ sink.push(0xFD);
+ 0x1Cu32.encode(sink);
+ assert!(lane < 4);
+ sink.push(lane);
+ }
+ Instruction::I64x2ExtractLane(lane) => {
+ sink.push(0xFD);
+ 0x1Du32.encode(sink);
+ assert!(lane < 2);
+ sink.push(lane);
+ }
+ Instruction::I64x2ReplaceLane(lane) => {
+ sink.push(0xFD);
+ 0x1Eu32.encode(sink);
+ assert!(lane < 2);
+ sink.push(lane);
+ }
+ Instruction::F32x4ExtractLane(lane) => {
+ sink.push(0xFD);
+ 0x1Fu32.encode(sink);
+ assert!(lane < 4);
+ sink.push(lane);
+ }
+ Instruction::F32x4ReplaceLane(lane) => {
+ sink.push(0xFD);
+ 0x20u32.encode(sink);
+ assert!(lane < 4);
+ sink.push(lane);
+ }
+ Instruction::F64x2ExtractLane(lane) => {
+ sink.push(0xFD);
+ 0x21u32.encode(sink);
+ assert!(lane < 2);
+ sink.push(lane);
+ }
+ Instruction::F64x2ReplaceLane(lane) => {
+ sink.push(0xFD);
+ 0x22u32.encode(sink);
+ assert!(lane < 2);
+ sink.push(lane);
+ }
+
+ Instruction::I8x16Eq => {
+ sink.push(0xFD);
+ 0x23u32.encode(sink);
+ }
+ Instruction::I8x16Ne => {
+ sink.push(0xFD);
+ 0x24u32.encode(sink);
+ }
+ Instruction::I8x16LtS => {
+ sink.push(0xFD);
+ 0x25u32.encode(sink);
+ }
+ Instruction::I8x16LtU => {
+ sink.push(0xFD);
+ 0x26u32.encode(sink);
+ }
+ Instruction::I8x16GtS => {
+ sink.push(0xFD);
+ 0x27u32.encode(sink);
+ }
+ Instruction::I8x16GtU => {
+ sink.push(0xFD);
+ 0x28u32.encode(sink);
+ }
+ Instruction::I8x16LeS => {
+ sink.push(0xFD);
+ 0x29u32.encode(sink);
+ }
+ Instruction::I8x16LeU => {
+ sink.push(0xFD);
+ 0x2Au32.encode(sink);
+ }
+ Instruction::I8x16GeS => {
+ sink.push(0xFD);
+ 0x2Bu32.encode(sink);
+ }
+ Instruction::I8x16GeU => {
+ sink.push(0xFD);
+ 0x2Cu32.encode(sink);
+ }
+ Instruction::I16x8Eq => {
+ sink.push(0xFD);
+ 0x2Du32.encode(sink);
+ }
+ Instruction::I16x8Ne => {
+ sink.push(0xFD);
+ 0x2Eu32.encode(sink);
+ }
+ Instruction::I16x8LtS => {
+ sink.push(0xFD);
+ 0x2Fu32.encode(sink);
+ }
+ Instruction::I16x8LtU => {
+ sink.push(0xFD);
+ 0x30u32.encode(sink);
+ }
+ Instruction::I16x8GtS => {
+ sink.push(0xFD);
+ 0x31u32.encode(sink);
+ }
+ Instruction::I16x8GtU => {
+ sink.push(0xFD);
+ 0x32u32.encode(sink);
+ }
+ Instruction::I16x8LeS => {
+ sink.push(0xFD);
+ 0x33u32.encode(sink);
+ }
+ Instruction::I16x8LeU => {
+ sink.push(0xFD);
+ 0x34u32.encode(sink);
+ }
+ Instruction::I16x8GeS => {
+ sink.push(0xFD);
+ 0x35u32.encode(sink);
+ }
+ Instruction::I16x8GeU => {
+ sink.push(0xFD);
+ 0x36u32.encode(sink);
+ }
+ Instruction::I32x4Eq => {
+ sink.push(0xFD);
+ 0x37u32.encode(sink);
+ }
+ Instruction::I32x4Ne => {
+ sink.push(0xFD);
+ 0x38u32.encode(sink);
+ }
+ Instruction::I32x4LtS => {
+ sink.push(0xFD);
+ 0x39u32.encode(sink);
+ }
+ Instruction::I32x4LtU => {
+ sink.push(0xFD);
+ 0x3Au32.encode(sink);
+ }
+ Instruction::I32x4GtS => {
+ sink.push(0xFD);
+ 0x3Bu32.encode(sink);
+ }
+ Instruction::I32x4GtU => {
+ sink.push(0xFD);
+ 0x3Cu32.encode(sink);
+ }
+ Instruction::I32x4LeS => {
+ sink.push(0xFD);
+ 0x3Du32.encode(sink);
+ }
+ Instruction::I32x4LeU => {
+ sink.push(0xFD);
+ 0x3Eu32.encode(sink);
+ }
+ Instruction::I32x4GeS => {
+ sink.push(0xFD);
+ 0x3Fu32.encode(sink);
+ }
+ Instruction::I32x4GeU => {
+ sink.push(0xFD);
+ 0x40u32.encode(sink);
+ }
+ Instruction::F32x4Eq => {
+ sink.push(0xFD);
+ 0x41u32.encode(sink);
+ }
+ Instruction::F32x4Ne => {
+ sink.push(0xFD);
+ 0x42u32.encode(sink);
+ }
+ Instruction::F32x4Lt => {
+ sink.push(0xFD);
+ 0x43u32.encode(sink);
+ }
+ Instruction::F32x4Gt => {
+ sink.push(0xFD);
+ 0x44u32.encode(sink);
+ }
+ Instruction::F32x4Le => {
+ sink.push(0xFD);
+ 0x45u32.encode(sink);
+ }
+ Instruction::F32x4Ge => {
+ sink.push(0xFD);
+ 0x46u32.encode(sink);
+ }
+ Instruction::F64x2Eq => {
+ sink.push(0xFD);
+ 0x47u32.encode(sink);
+ }
+ Instruction::F64x2Ne => {
+ sink.push(0xFD);
+ 0x48u32.encode(sink);
+ }
+ Instruction::F64x2Lt => {
+ sink.push(0xFD);
+ 0x49u32.encode(sink);
+ }
+ Instruction::F64x2Gt => {
+ sink.push(0xFD);
+ 0x4Au32.encode(sink);
+ }
+ Instruction::F64x2Le => {
+ sink.push(0xFD);
+ 0x4Bu32.encode(sink);
+ }
+ Instruction::F64x2Ge => {
+ sink.push(0xFD);
+ 0x4Cu32.encode(sink);
+ }
+ Instruction::V128Not => {
+ sink.push(0xFD);
+ 0x4Du32.encode(sink);
+ }
+ Instruction::V128And => {
+ sink.push(0xFD);
+ 0x4Eu32.encode(sink);
+ }
+ Instruction::V128AndNot => {
+ sink.push(0xFD);
+ 0x4Fu32.encode(sink);
+ }
+ Instruction::V128Or => {
+ sink.push(0xFD);
+ 0x50u32.encode(sink);
+ }
+ Instruction::V128Xor => {
+ sink.push(0xFD);
+ 0x51u32.encode(sink);
+ }
+ Instruction::V128Bitselect => {
+ sink.push(0xFD);
+ 0x52u32.encode(sink);
+ }
+ Instruction::V128AnyTrue => {
+ sink.push(0xFD);
+ 0x53u32.encode(sink);
+ }
+ Instruction::I8x16Abs => {
+ sink.push(0xFD);
+ 0x60u32.encode(sink);
+ }
+ Instruction::I8x16Neg => {
+ sink.push(0xFD);
+ 0x61u32.encode(sink);
+ }
+ Instruction::I8x16Popcnt => {
+ sink.push(0xFD);
+ 0x62u32.encode(sink);
+ }
+ Instruction::I8x16AllTrue => {
+ sink.push(0xFD);
+ 0x63u32.encode(sink);
+ }
+ Instruction::I8x16Bitmask => {
+ sink.push(0xFD);
+ 0x64u32.encode(sink);
+ }
+ Instruction::I8x16NarrowI16x8S => {
+ sink.push(0xFD);
+ 0x65u32.encode(sink);
+ }
+ Instruction::I8x16NarrowI16x8U => {
+ sink.push(0xFD);
+ 0x66u32.encode(sink);
+ }
+ Instruction::I8x16Shl => {
+ sink.push(0xFD);
+ 0x6bu32.encode(sink);
+ }
+ Instruction::I8x16ShrS => {
+ sink.push(0xFD);
+ 0x6cu32.encode(sink);
+ }
+ Instruction::I8x16ShrU => {
+ sink.push(0xFD);
+ 0x6du32.encode(sink);
+ }
+ Instruction::I8x16Add => {
+ sink.push(0xFD);
+ 0x6eu32.encode(sink);
+ }
+ Instruction::I8x16AddSatS => {
+ sink.push(0xFD);
+ 0x6fu32.encode(sink);
+ }
+ Instruction::I8x16AddSatU => {
+ sink.push(0xFD);
+ 0x70u32.encode(sink);
+ }
+ Instruction::I8x16Sub => {
+ sink.push(0xFD);
+ 0x71u32.encode(sink);
+ }
+ Instruction::I8x16SubSatS => {
+ sink.push(0xFD);
+ 0x72u32.encode(sink);
+ }
+ Instruction::I8x16SubSatU => {
+ sink.push(0xFD);
+ 0x73u32.encode(sink);
+ }
+ Instruction::I8x16MinS => {
+ sink.push(0xFD);
+ 0x76u32.encode(sink);
+ }
+ Instruction::I8x16MinU => {
+ sink.push(0xFD);
+ 0x77u32.encode(sink);
+ }
+ Instruction::I8x16MaxS => {
+ sink.push(0xFD);
+ 0x78u32.encode(sink);
+ }
+ Instruction::I8x16MaxU => {
+ sink.push(0xFD);
+ 0x79u32.encode(sink);
+ }
+ Instruction::I8x16AvgrU => {
+ sink.push(0xFD);
+ 0x7Bu32.encode(sink);
+ }
+ Instruction::I16x8ExtAddPairwiseI8x16S => {
+ sink.push(0xFD);
+ 0x7Cu32.encode(sink);
+ }
+ Instruction::I16x8ExtAddPairwiseI8x16U => {
+ sink.push(0xFD);
+ 0x7Du32.encode(sink);
+ }
+ Instruction::I32x4ExtAddPairwiseI16x8S => {
+ sink.push(0xFD);
+ 0x7Eu32.encode(sink);
+ }
+ Instruction::I32x4ExtAddPairwiseI16x8U => {
+ sink.push(0xFD);
+ 0x7Fu32.encode(sink);
+ }
+ Instruction::I16x8Abs => {
+ sink.push(0xFD);
+ 0x80u32.encode(sink);
+ }
+ Instruction::I16x8Neg => {
+ sink.push(0xFD);
+ 0x81u32.encode(sink);
+ }
+ Instruction::I16x8Q15MulrSatS => {
+ sink.push(0xFD);
+ 0x82u32.encode(sink);
+ }
+ Instruction::I16x8AllTrue => {
+ sink.push(0xFD);
+ 0x83u32.encode(sink);
+ }
+ Instruction::I16x8Bitmask => {
+ sink.push(0xFD);
+ 0x84u32.encode(sink);
+ }
+ Instruction::I16x8NarrowI32x4S => {
+ sink.push(0xFD);
+ 0x85u32.encode(sink);
+ }
+ Instruction::I16x8NarrowI32x4U => {
+ sink.push(0xFD);
+ 0x86u32.encode(sink);
+ }
+ Instruction::I16x8ExtendLowI8x16S => {
+ sink.push(0xFD);
+ 0x87u32.encode(sink);
+ }
+ Instruction::I16x8ExtendHighI8x16S => {
+ sink.push(0xFD);
+ 0x88u32.encode(sink);
+ }
+ Instruction::I16x8ExtendLowI8x16U => {
+ sink.push(0xFD);
+ 0x89u32.encode(sink);
+ }
+ Instruction::I16x8ExtendHighI8x16U => {
+ sink.push(0xFD);
+ 0x8Au32.encode(sink);
+ }
+ Instruction::I16x8Shl => {
+ sink.push(0xFD);
+ 0x8Bu32.encode(sink);
+ }
+ Instruction::I16x8ShrS => {
+ sink.push(0xFD);
+ 0x8Cu32.encode(sink);
+ }
+ Instruction::I16x8ShrU => {
+ sink.push(0xFD);
+ 0x8Du32.encode(sink);
+ }
+ Instruction::I16x8Add => {
+ sink.push(0xFD);
+ 0x8Eu32.encode(sink);
+ }
+ Instruction::I16x8AddSatS => {
+ sink.push(0xFD);
+ 0x8Fu32.encode(sink);
+ }
+ Instruction::I16x8AddSatU => {
+ sink.push(0xFD);
+ 0x90u32.encode(sink);
+ }
+ Instruction::I16x8Sub => {
+ sink.push(0xFD);
+ 0x91u32.encode(sink);
+ }
+ Instruction::I16x8SubSatS => {
+ sink.push(0xFD);
+ 0x92u32.encode(sink);
+ }
+ Instruction::I16x8SubSatU => {
+ sink.push(0xFD);
+ 0x93u32.encode(sink);
+ }
+ Instruction::I16x8Mul => {
+ sink.push(0xFD);
+ 0x95u32.encode(sink);
+ }
+ Instruction::I16x8MinS => {
+ sink.push(0xFD);
+ 0x96u32.encode(sink);
+ }
+ Instruction::I16x8MinU => {
+ sink.push(0xFD);
+ 0x97u32.encode(sink);
+ }
+ Instruction::I16x8MaxS => {
+ sink.push(0xFD);
+ 0x98u32.encode(sink);
+ }
+ Instruction::I16x8MaxU => {
+ sink.push(0xFD);
+ 0x99u32.encode(sink);
+ }
+ Instruction::I16x8AvgrU => {
+ sink.push(0xFD);
+ 0x9Bu32.encode(sink);
+ }
+ Instruction::I16x8ExtMulLowI8x16S => {
+ sink.push(0xFD);
+ 0x9Cu32.encode(sink);
+ }
+ Instruction::I16x8ExtMulHighI8x16S => {
+ sink.push(0xFD);
+ 0x9Du32.encode(sink);
+ }
+ Instruction::I16x8ExtMulLowI8x16U => {
+ sink.push(0xFD);
+ 0x9Eu32.encode(sink);
+ }
+ Instruction::I16x8ExtMulHighI8x16U => {
+ sink.push(0xFD);
+ 0x9Fu32.encode(sink);
+ }
+ Instruction::I32x4Abs => {
+ sink.push(0xFD);
+ 0xA0u32.encode(sink);
+ }
+ Instruction::I32x4Neg => {
+ sink.push(0xFD);
+ 0xA1u32.encode(sink);
+ }
+ Instruction::I32x4AllTrue => {
+ sink.push(0xFD);
+ 0xA3u32.encode(sink);
+ }
+ Instruction::I32x4Bitmask => {
+ sink.push(0xFD);
+ 0xA4u32.encode(sink);
+ }
+ Instruction::I32x4ExtendLowI16x8S => {
+ sink.push(0xFD);
+ 0xA7u32.encode(sink);
+ }
+ Instruction::I32x4ExtendHighI16x8S => {
+ sink.push(0xFD);
+ 0xA8u32.encode(sink);
+ }
+ Instruction::I32x4ExtendLowI16x8U => {
+ sink.push(0xFD);
+ 0xA9u32.encode(sink);
+ }
+ Instruction::I32x4ExtendHighI16x8U => {
+ sink.push(0xFD);
+ 0xAAu32.encode(sink);
+ }
+ Instruction::I32x4Shl => {
+ sink.push(0xFD);
+ 0xABu32.encode(sink);
+ }
+ Instruction::I32x4ShrS => {
+ sink.push(0xFD);
+ 0xACu32.encode(sink);
+ }
+ Instruction::I32x4ShrU => {
+ sink.push(0xFD);
+ 0xADu32.encode(sink);
+ }
+ Instruction::I32x4Add => {
+ sink.push(0xFD);
+ 0xAEu32.encode(sink);
+ }
+ Instruction::I32x4Sub => {
+ sink.push(0xFD);
+ 0xB1u32.encode(sink);
+ }
+ Instruction::I32x4Mul => {
+ sink.push(0xFD);
+ 0xB5u32.encode(sink);
+ }
+ Instruction::I32x4MinS => {
+ sink.push(0xFD);
+ 0xB6u32.encode(sink);
+ }
+ Instruction::I32x4MinU => {
+ sink.push(0xFD);
+ 0xB7u32.encode(sink);
+ }
+ Instruction::I32x4MaxS => {
+ sink.push(0xFD);
+ 0xB8u32.encode(sink);
+ }
+ Instruction::I32x4MaxU => {
+ sink.push(0xFD);
+ 0xB9u32.encode(sink);
+ }
+ Instruction::I32x4DotI16x8S => {
+ sink.push(0xFD);
+ 0xBAu32.encode(sink);
+ }
+ Instruction::I32x4ExtMulLowI16x8S => {
+ sink.push(0xFD);
+ 0xBCu32.encode(sink);
+ }
+ Instruction::I32x4ExtMulHighI16x8S => {
+ sink.push(0xFD);
+ 0xBDu32.encode(sink);
+ }
+ Instruction::I32x4ExtMulLowI16x8U => {
+ sink.push(0xFD);
+ 0xBEu32.encode(sink);
+ }
+ Instruction::I32x4ExtMulHighI16x8U => {
+ sink.push(0xFD);
+ 0xBFu32.encode(sink);
+ }
+ Instruction::I64x2Abs => {
+ sink.push(0xFD);
+ 0xC0u32.encode(sink);
+ }
+ Instruction::I64x2Neg => {
+ sink.push(0xFD);
+ 0xC1u32.encode(sink);
+ }
+ Instruction::I64x2AllTrue => {
+ sink.push(0xFD);
+ 0xC3u32.encode(sink);
+ }
+ Instruction::I64x2Bitmask => {
+ sink.push(0xFD);
+ 0xC4u32.encode(sink);
+ }
+ Instruction::I64x2ExtendLowI32x4S => {
+ sink.push(0xFD);
+ 0xC7u32.encode(sink);
+ }
+ Instruction::I64x2ExtendHighI32x4S => {
+ sink.push(0xFD);
+ 0xC8u32.encode(sink);
+ }
+ Instruction::I64x2ExtendLowI32x4U => {
+ sink.push(0xFD);
+ 0xC9u32.encode(sink);
+ }
+ Instruction::I64x2ExtendHighI32x4U => {
+ sink.push(0xFD);
+ 0xCAu32.encode(sink);
+ }
+ Instruction::I64x2Shl => {
+ sink.push(0xFD);
+ 0xCBu32.encode(sink);
+ }
+ Instruction::I64x2ShrS => {
+ sink.push(0xFD);
+ 0xCCu32.encode(sink);
+ }
+ Instruction::I64x2ShrU => {
+ sink.push(0xFD);
+ 0xCDu32.encode(sink);
+ }
+ Instruction::I64x2Add => {
+ sink.push(0xFD);
+ 0xCEu32.encode(sink);
+ }
+ Instruction::I64x2Sub => {
+ sink.push(0xFD);
+ 0xD1u32.encode(sink);
+ }
+ Instruction::I64x2Mul => {
+ sink.push(0xFD);
+ 0xD5u32.encode(sink);
+ }
+ Instruction::I64x2ExtMulLowI32x4S => {
+ sink.push(0xFD);
+ 0xDCu32.encode(sink);
+ }
+ Instruction::I64x2ExtMulHighI32x4S => {
+ sink.push(0xFD);
+ 0xDDu32.encode(sink);
+ }
+ Instruction::I64x2ExtMulLowI32x4U => {
+ sink.push(0xFD);
+ 0xDEu32.encode(sink);
+ }
+ Instruction::I64x2ExtMulHighI32x4U => {
+ sink.push(0xFD);
+ 0xDFu32.encode(sink);
+ }
+ Instruction::F32x4Ceil => {
+ sink.push(0xFD);
+ 0x67u32.encode(sink);
+ }
+ Instruction::F32x4Floor => {
+ sink.push(0xFD);
+ 0x68u32.encode(sink);
+ }
+ Instruction::F32x4Trunc => {
+ sink.push(0xFD);
+ 0x69u32.encode(sink);
+ }
+ Instruction::F32x4Nearest => {
+ sink.push(0xFD);
+ 0x6Au32.encode(sink);
+ }
+ Instruction::F32x4Abs => {
+ sink.push(0xFD);
+ 0xE0u32.encode(sink);
+ }
+ Instruction::F32x4Neg => {
+ sink.push(0xFD);
+ 0xE1u32.encode(sink);
+ }
+ Instruction::F32x4Sqrt => {
+ sink.push(0xFD);
+ 0xE3u32.encode(sink);
+ }
+ Instruction::F32x4Add => {
+ sink.push(0xFD);
+ 0xE4u32.encode(sink);
+ }
+ Instruction::F32x4Sub => {
+ sink.push(0xFD);
+ 0xE5u32.encode(sink);
+ }
+ Instruction::F32x4Mul => {
+ sink.push(0xFD);
+ 0xE6u32.encode(sink);
+ }
+ Instruction::F32x4Div => {
+ sink.push(0xFD);
+ 0xE7u32.encode(sink);
+ }
+ Instruction::F32x4Min => {
+ sink.push(0xFD);
+ 0xE8u32.encode(sink);
+ }
+ Instruction::F32x4Max => {
+ sink.push(0xFD);
+ 0xE9u32.encode(sink);
+ }
+ Instruction::F32x4PMin => {
+ sink.push(0xFD);
+ 0xEAu32.encode(sink);
+ }
+ Instruction::F32x4PMax => {
+ sink.push(0xFD);
+ 0xEBu32.encode(sink);
+ }
+ Instruction::F64x2Ceil => {
+ sink.push(0xFD);
+ 0x74u32.encode(sink);
+ }
+ Instruction::F64x2Floor => {
+ sink.push(0xFD);
+ 0x75u32.encode(sink);
+ }
+ Instruction::F64x2Trunc => {
+ sink.push(0xFD);
+ 0x7Au32.encode(sink);
+ }
+ Instruction::F64x2Nearest => {
+ sink.push(0xFD);
+ 0x94u32.encode(sink);
+ }
+ Instruction::F64x2Abs => {
+ sink.push(0xFD);
+ 0xECu32.encode(sink);
+ }
+ Instruction::F64x2Neg => {
+ sink.push(0xFD);
+ 0xEDu32.encode(sink);
+ }
+ Instruction::F64x2Sqrt => {
+ sink.push(0xFD);
+ 0xEFu32.encode(sink);
+ }
+ Instruction::F64x2Add => {
+ sink.push(0xFD);
+ 0xF0u32.encode(sink);
+ }
+ Instruction::F64x2Sub => {
+ sink.push(0xFD);
+ 0xF1u32.encode(sink);
+ }
+ Instruction::F64x2Mul => {
+ sink.push(0xFD);
+ 0xF2u32.encode(sink);
+ }
+ Instruction::F64x2Div => {
+ sink.push(0xFD);
+ 0xF3u32.encode(sink);
+ }
+ Instruction::F64x2Min => {
+ sink.push(0xFD);
+ 0xF4u32.encode(sink);
+ }
+ Instruction::F64x2Max => {
+ sink.push(0xFD);
+ 0xF5u32.encode(sink);
+ }
+ Instruction::F64x2PMin => {
+ sink.push(0xFD);
+ 0xF6u32.encode(sink);
+ }
+ Instruction::F64x2PMax => {
+ sink.push(0xFD);
+ 0xF7u32.encode(sink);
+ }
+ Instruction::I32x4TruncSatF32x4S => {
+ sink.push(0xFD);
+ 0xF8u32.encode(sink);
+ }
+ Instruction::I32x4TruncSatF32x4U => {
+ sink.push(0xFD);
+ 0xF9u32.encode(sink);
+ }
+ Instruction::F32x4ConvertI32x4S => {
+ sink.push(0xFD);
+ 0xFAu32.encode(sink);
+ }
+ Instruction::F32x4ConvertI32x4U => {
+ sink.push(0xFD);
+ 0xFBu32.encode(sink);
+ }
+ Instruction::I32x4TruncSatF64x2SZero => {
+ sink.push(0xFD);
+ 0xFCu32.encode(sink);
+ }
+ Instruction::I32x4TruncSatF64x2UZero => {
+ sink.push(0xFD);
+ 0xFDu32.encode(sink);
+ }
+ Instruction::F64x2ConvertLowI32x4S => {
+ sink.push(0xFD);
+ 0xFEu32.encode(sink);
+ }
+ Instruction::F64x2ConvertLowI32x4U => {
+ sink.push(0xFD);
+ 0xFFu32.encode(sink);
+ }
+ Instruction::F32x4DemoteF64x2Zero => {
+ sink.push(0xFD);
+ 0x5Eu32.encode(sink);
+ }
+ Instruction::F64x2PromoteLowF32x4 => {
+ sink.push(0xFD);
+ 0x5Fu32.encode(sink);
+ }
+ Instruction::V128Load32Zero(memarg) => {
+ sink.push(0xFD);
+ 0x5Cu32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load64Zero(memarg) => {
+ sink.push(0xFD);
+ 0x5Du32.encode(sink);
+ memarg.encode(sink);
+ }
+ Instruction::V128Load8Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x54u32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 16);
+ sink.push(lane);
+ }
+ Instruction::V128Load16Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x55u32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 8);
+ sink.push(lane);
+ }
+ Instruction::V128Load32Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x56u32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 4);
+ sink.push(lane);
+ }
+ Instruction::V128Load64Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x57u32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 2);
+ sink.push(lane);
+ }
+ Instruction::V128Store8Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x58u32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 16);
+ sink.push(lane);
+ }
+ Instruction::V128Store16Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x59u32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 8);
+ sink.push(lane);
+ }
+ Instruction::V128Store32Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x5Au32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 4);
+ sink.push(lane);
+ }
+ Instruction::V128Store64Lane { memarg, lane } => {
+ sink.push(0xFD);
+ 0x5Bu32.encode(sink);
+ memarg.encode(sink);
+ assert!(lane < 2);
+ sink.push(lane);
+ }
+ Instruction::I64x2Eq => {
+ sink.push(0xFD);
+ 0xD6u32.encode(sink);
+ }
+ Instruction::I64x2Ne => {
+ sink.push(0xFD);
+ 0xD7u32.encode(sink);
+ }
+ Instruction::I64x2LtS => {
+ sink.push(0xFD);
+ 0xD8u32.encode(sink);
+ }
+ Instruction::I64x2GtS => {
+ sink.push(0xFD);
+ 0xD9u32.encode(sink);
+ }
+ Instruction::I64x2LeS => {
+ sink.push(0xFD);
+ 0xDAu32.encode(sink);
+ }
+ Instruction::I64x2GeS => {
+ sink.push(0xFD);
+ 0xDBu32.encode(sink);
+ }
+ Instruction::I8x16RelaxedSwizzle => {
+ sink.push(0xFD);
+ 0x100u32.encode(sink);
+ }
+ Instruction::I32x4RelaxedTruncF32x4S => {
+ sink.push(0xFD);
+ 0x101u32.encode(sink);
+ }
+ Instruction::I32x4RelaxedTruncF32x4U => {
+ sink.push(0xFD);
+ 0x102u32.encode(sink);
+ }
+ Instruction::I32x4RelaxedTruncF64x2SZero => {
+ sink.push(0xFD);
+ 0x103u32.encode(sink);
+ }
+ Instruction::I32x4RelaxedTruncF64x2UZero => {
+ sink.push(0xFD);
+ 0x104u32.encode(sink);
+ }
+ Instruction::F32x4RelaxedMadd => {
+ sink.push(0xFD);
+ 0x105u32.encode(sink);
+ }
+ Instruction::F32x4RelaxedNmadd => {
+ sink.push(0xFD);
+ 0x106u32.encode(sink);
+ }
+ Instruction::F64x2RelaxedMadd => {
+ sink.push(0xFD);
+ 0x107u32.encode(sink);
+ }
+ Instruction::F64x2RelaxedNmadd => {
+ sink.push(0xFD);
+ 0x108u32.encode(sink);
+ }
+ Instruction::I8x16RelaxedLaneselect => {
+ sink.push(0xFD);
+ 0x109u32.encode(sink);
+ }
+ Instruction::I16x8RelaxedLaneselect => {
+ sink.push(0xFD);
+ 0x10Au32.encode(sink);
+ }
+ Instruction::I32x4RelaxedLaneselect => {
+ sink.push(0xFD);
+ 0x10Bu32.encode(sink);
+ }
+ Instruction::I64x2RelaxedLaneselect => {
+ sink.push(0xFD);
+ 0x10Cu32.encode(sink);
+ }
+ Instruction::F32x4RelaxedMin => {
+ sink.push(0xFD);
+ 0x10Du32.encode(sink);
+ }
+ Instruction::F32x4RelaxedMax => {
+ sink.push(0xFD);
+ 0x10Eu32.encode(sink);
+ }
+ Instruction::F64x2RelaxedMin => {
+ sink.push(0xFD);
+ 0x10Fu32.encode(sink);
+ }
+ Instruction::F64x2RelaxedMax => {
+ sink.push(0xFD);
+ 0x110u32.encode(sink);
+ }
+ Instruction::I16x8RelaxedQ15mulrS => {
+ sink.push(0xFD);
+ 0x111u32.encode(sink);
+ }
+ Instruction::I16x8RelaxedDotI8x16I7x16S => {
+ sink.push(0xFD);
+ 0x112u32.encode(sink);
+ }
+ Instruction::I32x4RelaxedDotI8x16I7x16AddS => {
+ sink.push(0xFD);
+ 0x113u32.encode(sink);
+ }
+
+ // Atmoic instructions from the thread proposal
+ Instruction::MemoryAtomicNotify(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x00);
+ memarg.encode(sink);
+ }
+ Instruction::MemoryAtomicWait32(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x01);
+ memarg.encode(sink);
+ }
+ Instruction::MemoryAtomicWait64(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x02);
+ memarg.encode(sink);
+ }
+ Instruction::AtomicFence => {
+ sink.push(0xFE);
+ sink.push(0x03);
+ sink.push(0x00);
+ }
+ Instruction::I32AtomicLoad(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x10);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicLoad(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x11);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicLoad8U(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x12);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicLoad16U(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x13);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicLoad8U(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x14);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicLoad16U(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x15);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicLoad32U(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x16);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicStore(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x17);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicStore(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x18);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicStore8(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x19);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicStore16(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x1A);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicStore8(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x1B);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicStore16(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x1C);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicStore32(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x1D);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwAdd(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x1E);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwAdd(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x1F);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8AddU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x20);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16AddU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x21);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8AddU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x22);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16AddU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x23);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32AddU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x24);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwSub(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x25);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwSub(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x26);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8SubU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x27);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16SubU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x28);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8SubU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x29);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16SubU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x2A);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32SubU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x2B);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwAnd(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x2C);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwAnd(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x2D);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8AndU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x2E);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16AndU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x2F);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8AndU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x30);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16AndU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x31);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32AndU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x32);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwOr(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x33);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwOr(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x34);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8OrU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x35);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16OrU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x36);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8OrU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x37);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16OrU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x38);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32OrU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x39);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwXor(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x3A);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwXor(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x3B);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8XorU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x3C);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16XorU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x3D);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8XorU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x3E);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16XorU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x3F);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32XorU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x40);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwXchg(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x41);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwXchg(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x42);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8XchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x43);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16XchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x44);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8XchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x45);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16XchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x46);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32XchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x47);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmwCmpxchg(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x48);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmwCmpxchg(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x49);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw8CmpxchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x4A);
+ memarg.encode(sink);
+ }
+ Instruction::I32AtomicRmw16CmpxchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x4B);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw8CmpxchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x4C);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw16CmpxchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x4D);
+ memarg.encode(sink);
+ }
+ Instruction::I64AtomicRmw32CmpxchgU(memarg) => {
+ sink.push(0xFE);
+ sink.push(0x4E);
+ memarg.encode(sink);
+ }
+ }
+ }
+}
+
+/// A constant expression.
+///
+/// Usable in contexts such as offsets or initializers.
+#[derive(Debug)]
+pub struct ConstExpr {
+ bytes: Vec<u8>,
+}
+
+impl ConstExpr {
+ /// Create a new empty constant expression builder.
+ pub fn empty() -> Self {
+ Self { bytes: Vec::new() }
+ }
+
+ /// Create a constant expression with the specified raw encoding of instructions.
+ pub fn raw(bytes: impl IntoIterator<Item = u8>) -> Self {
+ Self {
+ bytes: bytes.into_iter().collect(),
+ }
+ }
+
+ fn new_insn(insn: Instruction) -> Self {
+ let mut bytes = vec![];
+ insn.encode(&mut bytes);
+ Self { bytes }
+ }
+
+ /// Create a constant expression containing a single `global.get` instruction.
+ pub fn global_get(index: u32) -> Self {
+ Self::new_insn(Instruction::GlobalGet(index))
+ }
+
+ /// Create a constant expression containing a single `ref.null` instruction.
+ pub fn ref_null(ty: HeapType) -> Self {
+ Self::new_insn(Instruction::RefNull(ty))
+ }
+
+ /// Create a constant expression containing a single `ref.func` instruction.
+ pub fn ref_func(func: u32) -> Self {
+ Self::new_insn(Instruction::RefFunc(func))
+ }
+
+ /// Create a constant expression containing a single `i32.const` instruction.
+ pub fn i32_const(value: i32) -> Self {
+ Self::new_insn(Instruction::I32Const(value))
+ }
+
+ /// Create a constant expression containing a single `i64.const` instruction.
+ pub fn i64_const(value: i64) -> Self {
+ Self::new_insn(Instruction::I64Const(value))
+ }
+
+ /// Create a constant expression containing a single `f32.const` instruction.
+ pub fn f32_const(value: f32) -> Self {
+ Self::new_insn(Instruction::F32Const(value))
+ }
+
+ /// Create a constant expression containing a single `f64.const` instruction.
+ pub fn f64_const(value: f64) -> Self {
+ Self::new_insn(Instruction::F64Const(value))
+ }
+
+ /// Create a constant expression containing a single `v128.const` instruction.
+ pub fn v128_const(value: i128) -> Self {
+ Self::new_insn(Instruction::V128Const(value))
+ }
+}
+
+impl Encode for ConstExpr {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.extend(&self.bytes);
+ Instruction::End.encode(sink);
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn function_new_with_locals_test() {
+ use super::*;
+
+ // Test the algorithm for conversion is correct
+ let f1 = Function::new_with_locals_types([
+ ValType::I32,
+ ValType::I32,
+ ValType::I64,
+ ValType::F32,
+ ValType::F32,
+ ValType::F32,
+ ValType::I32,
+ ValType::I64,
+ ValType::I64,
+ ]);
+ let f2 = Function::new([
+ (2, ValType::I32),
+ (1, ValType::I64),
+ (3, ValType::F32),
+ (1, ValType::I32),
+ (2, ValType::I64),
+ ]);
+
+ assert_eq!(f1.bytes, f2.bytes)
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/custom.rs b/third_party/rust/wasm-encoder/src/core/custom.rs
new file mode 100644
index 0000000000..47d78d458c
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/custom.rs
@@ -0,0 +1,53 @@
+use crate::{encoding_size, Encode, Section, SectionId};
+
+/// A custom section holding arbitrary data.
+#[derive(Clone, Debug)]
+pub struct CustomSection<'a> {
+ /// The name of this custom section.
+ pub name: &'a str,
+ /// This custom section's data.
+ pub data: &'a [u8],
+}
+
+impl Encode for CustomSection<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let encoded_name_len = encoding_size(u32::try_from(self.name.len()).unwrap());
+ (encoded_name_len + self.name.len() + self.data.len()).encode(sink);
+ self.name.encode(sink);
+ sink.extend(self.data);
+ }
+}
+
+impl Section for CustomSection<'_> {
+ fn id(&self) -> u8 {
+ SectionId::Custom.into()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_custom_section() {
+ let custom = CustomSection {
+ name: "test",
+ data: &[11, 22, 33, 44],
+ };
+
+ let mut encoded = vec![];
+ custom.encode(&mut encoded);
+
+ #[rustfmt::skip]
+ assert_eq!(encoded, vec![
+ // LEB128 length of section.
+ 9,
+ // LEB128 length of name.
+ 4,
+ // Name.
+ b't', b'e', b's', b't',
+ // Data.
+ 11, 22, 33, 44,
+ ]);
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/data.rs b/third_party/rust/wasm-encoder/src/core/data.rs
new file mode 100644
index 0000000000..6439b66e2e
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/data.rs
@@ -0,0 +1,185 @@
+use crate::{encode_section, encoding_size, ConstExpr, Encode, Section, SectionId};
+
+/// An encoder for the data section.
+///
+/// Data sections are only supported for modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{
+/// ConstExpr, DataSection, Instruction, MemorySection, MemoryType,
+/// Module,
+/// };
+///
+/// let mut memory = MemorySection::new();
+/// memory.memory(MemoryType {
+/// minimum: 1,
+/// maximum: None,
+/// memory64: false,
+/// shared: false,
+/// });
+///
+/// let mut data = DataSection::new();
+/// let memory_index = 0;
+/// let offset = ConstExpr::i32_const(42);
+/// let segment_data = b"hello";
+/// data.active(memory_index, &offset, segment_data.iter().copied());
+///
+/// let mut module = Module::new();
+/// module
+/// .section(&memory)
+/// .section(&data);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct DataSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+/// A segment in the data section.
+#[derive(Clone, Debug)]
+pub struct DataSegment<'a, D> {
+ /// This data segment's mode.
+ pub mode: DataSegmentMode<'a>,
+ /// This data segment's data.
+ pub data: D,
+}
+
+/// A data segment's mode.
+#[derive(Clone, Debug)]
+pub enum DataSegmentMode<'a> {
+ /// An active data segment.
+ Active {
+ /// The memory this segment applies to.
+ memory_index: u32,
+ /// The offset where this segment's data is initialized at.
+ offset: &'a ConstExpr,
+ },
+ /// A passive data segment.
+ ///
+ /// Passive data segments are part of the bulk memory proposal.
+ Passive,
+}
+
+impl DataSection {
+ /// Create a new data section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of data segments in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a data segment.
+ pub fn segment<D>(&mut self, segment: DataSegment<D>) -> &mut Self
+ where
+ D: IntoIterator<Item = u8>,
+ D::IntoIter: ExactSizeIterator,
+ {
+ match segment.mode {
+ DataSegmentMode::Passive => {
+ self.bytes.push(0x01);
+ }
+ DataSegmentMode::Active {
+ memory_index: 0,
+ offset,
+ } => {
+ self.bytes.push(0x00);
+ offset.encode(&mut self.bytes);
+ }
+ DataSegmentMode::Active {
+ memory_index,
+ offset,
+ } => {
+ self.bytes.push(0x02);
+ memory_index.encode(&mut self.bytes);
+ offset.encode(&mut self.bytes);
+ }
+ }
+
+ let data = segment.data.into_iter();
+ data.len().encode(&mut self.bytes);
+ self.bytes.extend(data);
+
+ self.num_added += 1;
+ self
+ }
+
+ /// Define an active data segment.
+ pub fn active<D>(&mut self, memory_index: u32, offset: &ConstExpr, data: D) -> &mut Self
+ where
+ D: IntoIterator<Item = u8>,
+ D::IntoIter: ExactSizeIterator,
+ {
+ self.segment(DataSegment {
+ mode: DataSegmentMode::Active {
+ memory_index,
+ offset,
+ },
+ data,
+ })
+ }
+
+ /// Define a passive data segment.
+ ///
+ /// Passive data segments are part of the bulk memory proposal.
+ pub fn passive<D>(&mut self, data: D) -> &mut Self
+ where
+ D: IntoIterator<Item = u8>,
+ D::IntoIter: ExactSizeIterator,
+ {
+ self.segment(DataSegment {
+ mode: DataSegmentMode::Passive,
+ data,
+ })
+ }
+
+ /// Copy an already-encoded data segment into this data section.
+ pub fn raw(&mut self, already_encoded_data_segment: &[u8]) -> &mut Self {
+ self.bytes.extend_from_slice(already_encoded_data_segment);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for DataSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for DataSection {
+ fn id(&self) -> u8 {
+ SectionId::Data.into()
+ }
+}
+
+/// An encoder for the data count section.
+#[derive(Clone, Copy, Debug)]
+pub struct DataCountSection {
+ /// The number of segments in the data section.
+ pub count: u32,
+}
+
+impl Encode for DataCountSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encoding_size(self.count).encode(sink);
+ self.count.encode(sink);
+ }
+}
+
+impl Section for DataCountSection {
+ fn id(&self) -> u8 {
+ SectionId::DataCount.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/elements.rs b/third_party/rust/wasm-encoder/src/core/elements.rs
new file mode 100644
index 0000000000..3325c3d429
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/elements.rs
@@ -0,0 +1,227 @@
+use crate::{encode_section, ConstExpr, Encode, RefType, Section, SectionId};
+
+/// An encoder for the element section.
+///
+/// Element sections are only supported for modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{
+/// Elements, ElementSection, Module, TableSection, TableType,
+/// RefType, ConstExpr
+/// };
+///
+/// let mut tables = TableSection::new();
+/// tables.table(TableType {
+/// element_type: RefType::FUNCREF,
+/// minimum: 128,
+/// maximum: None,
+/// });
+///
+/// let mut elements = ElementSection::new();
+/// let table_index = 0;
+/// let offset = ConstExpr::i32_const(42);
+/// let element_type = RefType::FUNCREF;
+/// let functions = Elements::Functions(&[
+/// // Function indices...
+/// ]);
+/// elements.active(Some(table_index), &offset, element_type, functions);
+///
+/// let mut module = Module::new();
+/// module
+/// .section(&tables)
+/// .section(&elements);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct ElementSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+/// A sequence of elements in a segment in the element section.
+#[derive(Clone, Copy, Debug)]
+pub enum Elements<'a> {
+ /// A sequences of references to functions by their indices.
+ Functions(&'a [u32]),
+ /// A sequence of reference expressions.
+ Expressions(&'a [ConstExpr]),
+}
+
+/// An element segment's mode.
+#[derive(Clone, Debug)]
+pub enum ElementMode<'a> {
+ /// A passive element segment.
+ ///
+ /// Passive segments are part of the bulk memory proposal.
+ Passive,
+ /// A declared element segment.
+ ///
+ /// Declared segments are part of the bulk memory proposal.
+ Declared,
+ /// An active element segment.
+ Active {
+ /// The table index.
+ ///
+ /// `Active` element specifying a `None` table forces the MVP encoding and refers to the
+ /// 0th table holding `funcref`s. Non-`None` tables use the encoding introduced with the
+ /// bulk memory proposal and can refer to tables with any valid reference type.
+ table: Option<u32>,
+ /// The offset within the table to place this segment.
+ offset: &'a ConstExpr,
+ },
+}
+
+/// An element segment in the element section.
+#[derive(Clone, Debug)]
+pub struct ElementSegment<'a> {
+ /// The element segment's mode.
+ pub mode: ElementMode<'a>,
+ /// The element segment's type.
+ pub element_type: RefType,
+ /// This segment's elements.
+ pub elements: Elements<'a>,
+}
+
+impl ElementSection {
+ /// Create a new element section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of element segments in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an element segment.
+ pub fn segment<'a>(&mut self, segment: ElementSegment<'a>) -> &mut Self {
+ let expr_bit = match segment.elements {
+ Elements::Expressions(_) => 0b100u32,
+ Elements::Functions(_) => 0b000u32,
+ };
+ match &segment.mode {
+ ElementMode::Active {
+ table: None,
+ offset,
+ } => {
+ (/* 0x00 | */expr_bit).encode(&mut self.bytes);
+ offset.encode(&mut self.bytes);
+ }
+ ElementMode::Passive => {
+ (0x01 | expr_bit).encode(&mut self.bytes);
+ if expr_bit == 0 {
+ self.bytes.push(0x00); // elemkind == funcref
+ } else {
+ segment.element_type.encode(&mut self.bytes);
+ }
+ }
+ ElementMode::Active {
+ table: Some(i),
+ offset,
+ } => {
+ (0x02 | expr_bit).encode(&mut self.bytes);
+ i.encode(&mut self.bytes);
+ offset.encode(&mut self.bytes);
+ if expr_bit == 0 {
+ self.bytes.push(0x00); // elemkind == funcref
+ } else {
+ segment.element_type.encode(&mut self.bytes);
+ }
+ }
+ ElementMode::Declared => {
+ (0x03 | expr_bit).encode(&mut self.bytes);
+ if expr_bit == 0 {
+ self.bytes.push(0x00); // elemkind == funcref
+ } else {
+ segment.element_type.encode(&mut self.bytes);
+ }
+ }
+ }
+
+ match segment.elements {
+ Elements::Functions(fs) => {
+ fs.encode(&mut self.bytes);
+ }
+ Elements::Expressions(e) => {
+ e.len().encode(&mut self.bytes);
+ for expr in e {
+ expr.encode(&mut self.bytes);
+ }
+ }
+ }
+
+ self.num_added += 1;
+ self
+ }
+
+ /// Define an active element segment.
+ ///
+ /// `Active` element specifying a `None` table forces the MVP encoding and refers to the 0th
+ /// table holding `funcref`s. Non-`None` tables use the encoding introduced with the bulk
+ /// memory proposal and can refer to tables with any valid reference type.
+ pub fn active(
+ &mut self,
+ table_index: Option<u32>,
+ offset: &ConstExpr,
+ element_type: RefType,
+ elements: Elements<'_>,
+ ) -> &mut Self {
+ self.segment(ElementSegment {
+ mode: ElementMode::Active {
+ table: table_index,
+ offset,
+ },
+ element_type,
+ elements,
+ })
+ }
+
+ /// Encode a passive element segment.
+ ///
+ /// Passive segments are part of the bulk memory proposal.
+ pub fn passive<'a>(&mut self, element_type: RefType, elements: Elements<'a>) -> &mut Self {
+ self.segment(ElementSegment {
+ mode: ElementMode::Passive,
+ element_type,
+ elements,
+ })
+ }
+
+ /// Encode a declared element segment.
+ ///
+ /// Declared segments are part of the bulk memory proposal.
+ pub fn declared<'a>(&mut self, element_type: RefType, elements: Elements<'a>) -> &mut Self {
+ self.segment(ElementSegment {
+ mode: ElementMode::Declared,
+ element_type,
+ elements,
+ })
+ }
+
+ /// Copy a raw, already-encoded element segment into this elements section.
+ pub fn raw(&mut self, raw_bytes: &[u8]) -> &mut Self {
+ self.bytes.extend_from_slice(raw_bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ElementSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for ElementSection {
+ fn id(&self) -> u8 {
+ SectionId::Element.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/exports.rs b/third_party/rust/wasm-encoder/src/core/exports.rs
new file mode 100644
index 0000000000..36c7896362
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/exports.rs
@@ -0,0 +1,85 @@
+use super::{
+ CORE_FUNCTION_SORT, CORE_GLOBAL_SORT, CORE_MEMORY_SORT, CORE_TABLE_SORT, CORE_TAG_SORT,
+};
+use crate::{encode_section, Encode, Section, SectionId};
+
+/// Represents the kind of an export from a WebAssembly module.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[repr(u8)]
+pub enum ExportKind {
+ /// The export is a function.
+ Func = CORE_FUNCTION_SORT,
+ /// The export is a table.
+ Table = CORE_TABLE_SORT,
+ /// The export is a memory.
+ Memory = CORE_MEMORY_SORT,
+ /// The export is a global.
+ Global = CORE_GLOBAL_SORT,
+ /// The export is a tag.
+ Tag = CORE_TAG_SORT,
+}
+
+impl Encode for ExportKind {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(*self as u8);
+ }
+}
+
+/// An encoder for the export section of WebAssembly module.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Module, ExportSection, ExportKind};
+///
+/// let mut exports = ExportSection::new();
+/// exports.export("foo", ExportKind::Func, 0);
+///
+/// let mut module = Module::new();
+/// module.section(&exports);
+///
+/// let bytes = module.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ExportSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ExportSection {
+ /// Create a new export section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of exports in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an export in the export section.
+ pub fn export(&mut self, name: &str, kind: ExportKind, index: u32) -> &mut Self {
+ name.encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ExportSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for ExportSection {
+ fn id(&self) -> u8 {
+ SectionId::Export.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/functions.rs b/third_party/rust/wasm-encoder/src/core/functions.rs
new file mode 100644
index 0000000000..e21d8c10a7
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/functions.rs
@@ -0,0 +1,63 @@
+use crate::{encode_section, Encode, Section, SectionId};
+
+/// An encoder for the function section of WebAssembly modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Module, FunctionSection, ValType};
+///
+/// let mut functions = FunctionSection::new();
+/// let type_index = 0;
+/// functions.function(type_index);
+///
+/// let mut module = Module::new();
+/// module.section(&functions);
+///
+/// // Note: this will generate an invalid module because we didn't generate a
+/// // code section containing the function body. See the documentation for
+/// // `CodeSection` for details.
+///
+/// let bytes = module.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct FunctionSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl FunctionSection {
+ /// Construct a new module function section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of functions in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a function in a module's function section.
+ pub fn function(&mut self, type_index: u32) -> &mut Self {
+ type_index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for FunctionSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for FunctionSection {
+ fn id(&self) -> u8 {
+ SectionId::Function.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/globals.rs b/third_party/rust/wasm-encoder/src/core/globals.rs
new file mode 100644
index 0000000000..16f23c2891
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/globals.rs
@@ -0,0 +1,90 @@
+use crate::{encode_section, ConstExpr, Encode, Section, SectionId, ValType};
+
+/// An encoder for the global section.
+///
+/// Global sections are only supported for modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{ConstExpr, Module, GlobalSection, GlobalType, Instruction, ValType};
+///
+/// let mut globals = GlobalSection::new();
+/// globals.global(
+/// GlobalType {
+/// val_type: ValType::I32,
+/// mutable: false,
+/// },
+/// &ConstExpr::i32_const(42),
+/// );
+///
+/// let mut module = Module::new();
+/// module.section(&globals);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct GlobalSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl GlobalSection {
+ /// Create a new global section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of globals in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a global.
+ pub fn global(&mut self, global_type: GlobalType, init_expr: &ConstExpr) -> &mut Self {
+ global_type.encode(&mut self.bytes);
+ init_expr.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Add a raw byte slice into this code section as a global.
+ pub fn raw(&mut self, data: &[u8]) -> &mut Self {
+ self.bytes.extend(data);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for GlobalSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for GlobalSection {
+ fn id(&self) -> u8 {
+ SectionId::Global.into()
+ }
+}
+
+/// A global's type.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct GlobalType {
+ /// This global's value type.
+ pub val_type: ValType,
+ /// Whether this global is mutable or not.
+ pub mutable: bool,
+}
+
+impl Encode for GlobalType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.val_type.encode(sink);
+ sink.push(self.mutable as u8);
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/imports.rs b/third_party/rust/wasm-encoder/src/core/imports.rs
new file mode 100644
index 0000000000..455170f227
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/imports.rs
@@ -0,0 +1,142 @@
+use crate::{
+ encode_section, Encode, GlobalType, MemoryType, Section, SectionId, TableType, TagType,
+ CORE_FUNCTION_SORT, CORE_GLOBAL_SORT, CORE_MEMORY_SORT, CORE_TABLE_SORT, CORE_TAG_SORT,
+};
+
+/// The type of an entity.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum EntityType {
+ /// A function type.
+ ///
+ /// The value is an index into the types section.
+ Function(u32),
+ /// A table type.
+ Table(TableType),
+ /// A memory type.
+ Memory(MemoryType),
+ /// A global type.
+ Global(GlobalType),
+ /// A tag type.
+ ///
+ /// This variant is used with the exception handling proposal.
+ Tag(TagType),
+}
+
+impl Encode for EntityType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Function(i) => {
+ sink.push(CORE_FUNCTION_SORT);
+ i.encode(sink);
+ }
+ Self::Table(t) => {
+ sink.push(CORE_TABLE_SORT);
+ t.encode(sink);
+ }
+ Self::Memory(t) => {
+ sink.push(CORE_MEMORY_SORT);
+ t.encode(sink);
+ }
+ Self::Global(t) => {
+ sink.push(CORE_GLOBAL_SORT);
+ t.encode(sink);
+ }
+ Self::Tag(t) => {
+ sink.push(CORE_TAG_SORT);
+ t.encode(sink);
+ }
+ }
+ }
+}
+
+impl From<TableType> for EntityType {
+ fn from(t: TableType) -> Self {
+ Self::Table(t)
+ }
+}
+
+impl From<MemoryType> for EntityType {
+ fn from(t: MemoryType) -> Self {
+ Self::Memory(t)
+ }
+}
+
+impl From<GlobalType> for EntityType {
+ fn from(t: GlobalType) -> Self {
+ Self::Global(t)
+ }
+}
+
+impl From<TagType> for EntityType {
+ fn from(t: TagType) -> Self {
+ Self::Tag(t)
+ }
+}
+
+/// An encoder for the import section of WebAssembly modules.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{MemoryType, Module, ImportSection};
+///
+/// let mut imports = ImportSection::new();
+/// imports.import(
+/// "env",
+/// "memory",
+/// MemoryType {
+/// minimum: 1,
+/// maximum: None,
+/// memory64: false,
+/// shared: false,
+/// }
+/// );
+///
+/// let mut module = Module::new();
+/// module.section(&imports);
+///
+/// let bytes = module.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ImportSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ImportSection {
+ /// Create a new import section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of imports in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an import in the import section.
+ pub fn import(&mut self, module: &str, field: &str, ty: impl Into<EntityType>) -> &mut Self {
+ module.encode(&mut self.bytes);
+ field.encode(&mut self.bytes);
+ ty.into().encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ImportSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for ImportSection {
+ fn id(&self) -> u8 {
+ SectionId::Import.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/linking.rs b/third_party/rust/wasm-encoder/src/core/linking.rs
new file mode 100644
index 0000000000..3309277be3
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/linking.rs
@@ -0,0 +1,261 @@
+use crate::{encode_section, CustomSection, Encode, Section, SectionId};
+
+const VERSION: u32 = 2;
+
+/// An encoder for the [linking custom
+/// section](https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md#linking-metadata-section).
+///
+/// This section is a non-standard convention that is supported by the LLVM
+/// toolchain. It, along with associated "reloc.*" custom sections, allows you
+/// to treat a Wasm module as a low-level object file that can be linked with
+/// other Wasm object files to produce a final, complete Wasm module.
+///
+/// The linking section must come before the reloc sections.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{LinkingSection, Module, SymbolTable};
+///
+/// // Create a new linking section.
+/// let mut linking = LinkingSection::new();
+///
+/// // Define a symbol table.
+/// let mut sym_tab = SymbolTable::new();
+///
+/// // Define a function symbol in the symbol table.
+/// let flags = SymbolTable::WASM_SYM_BINDING_LOCAL | SymbolTable::WASM_SYM_EXPORTED;
+/// let func_index = 42;
+/// let sym_name = "my_exported_func";
+/// sym_tab.function(flags, func_index, Some(sym_name));
+///
+/// // Add the symbol table to our linking section.
+/// linking.symbol_table(&sym_tab);
+///
+/// // Add the linking section to a new Wasm module and get the encoded bytes.
+/// let mut module = Module::new();
+/// module.section(&linking);
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct LinkingSection {
+ bytes: Vec<u8>,
+}
+
+impl LinkingSection {
+ /// Construct a new encoder for the linking custom section.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ // TODO: `fn segment_info` for the `WASM_SEGMENT_INFO` linking subsection.
+
+ // TODO: `fn init_funcs` for the `WASM_INIT_FUNCS` linking subsection.
+
+ // TODO: `fn comdat_info` for the `WASM_COMDAT_INFO` linking subsection.
+
+ /// Add a symbol table subsection.
+ pub fn symbol_table(&mut self, symbol_table: &SymbolTable) -> &mut Self {
+ symbol_table.encode(&mut self.bytes);
+ self
+ }
+}
+
+impl Default for LinkingSection {
+ fn default() -> Self {
+ let mut bytes = Vec::new();
+ VERSION.encode(&mut bytes);
+ Self { bytes }
+ }
+}
+
+impl Encode for LinkingSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ CustomSection {
+ name: "linking",
+ data: &self.bytes,
+ }
+ .encode(sink);
+ }
+}
+
+impl Section for LinkingSection {
+ fn id(&self) -> u8 {
+ SectionId::Custom.into()
+ }
+}
+
+#[allow(unused)]
+const WASM_SEGMENT_INFO: u8 = 5;
+#[allow(unused)]
+const WASM_INIT_FUNCS: u8 = 6;
+#[allow(unused)]
+const WASM_COMDAT_INFO: u8 = 7;
+const WASM_SYMBOL_TABLE: u8 = 8;
+
+/// A subsection of the [linking custom section][crate::LinkingSection] that
+/// provides extra information about the symbols present in this Wasm object
+/// file.
+#[derive(Clone, Debug, Default)]
+pub struct SymbolTable {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+const SYMTAB_FUNCTION: u32 = 0;
+const SYMTAB_DATA: u32 = 1;
+const SYMTAB_GLOBAL: u32 = 2;
+#[allow(unused)]
+const SYMTAB_SECTION: u32 = 3;
+#[allow(unused)]
+const SYMTAB_TAG: u32 = 4;
+const SYMTAB_TABLE: u32 = 5;
+
+impl SymbolTable {
+ /// Construct a new symbol table subsection encoder.
+ pub fn new() -> Self {
+ SymbolTable {
+ bytes: vec![],
+ num_added: 0,
+ }
+ }
+
+ /// Define a function symbol in this symbol table.
+ ///
+ /// The `name` must be omitted if `index` references an imported table and
+ /// the `WASM_SYM_EXPLICIT_NAME` flag is not set.
+ pub fn function(&mut self, flags: u32, index: u32, name: Option<&str>) -> &mut Self {
+ SYMTAB_FUNCTION.encode(&mut self.bytes);
+ flags.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ if let Some(name) = name {
+ name.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Define a global symbol in this symbol table.
+ ///
+ /// The `name` must be omitted if `index` references an imported table and
+ /// the `WASM_SYM_EXPLICIT_NAME` flag is not set.
+ pub fn global(&mut self, flags: u32, index: u32, name: Option<&str>) -> &mut Self {
+ SYMTAB_GLOBAL.encode(&mut self.bytes);
+ flags.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ if let Some(name) = name {
+ name.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ // TODO: tags
+
+ /// Define a table symbol in this symbol table.
+ ///
+ /// The `name` must be omitted if `index` references an imported table and
+ /// the `WASM_SYM_EXPLICIT_NAME` flag is not set.
+ pub fn table(&mut self, flags: u32, index: u32, name: Option<&str>) -> &mut Self {
+ SYMTAB_TABLE.encode(&mut self.bytes);
+ flags.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ if let Some(name) = name {
+ name.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Add a data symbol to this symbol table.
+ pub fn data(
+ &mut self,
+ flags: u32,
+ name: &str,
+ definition: Option<DataSymbolDefinition>,
+ ) -> &mut Self {
+ SYMTAB_DATA.encode(&mut self.bytes);
+ flags.encode(&mut self.bytes);
+ name.encode(&mut self.bytes);
+ if let Some(def) = definition {
+ def.index.encode(&mut self.bytes);
+ def.offset.encode(&mut self.bytes);
+ def.size.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ // TODO: sections
+
+ /// This is a weak symbol.
+ ///
+ /// This flag is mutually exclusive with `WASM_SYM_BINDING_LOCAL`.
+ ///
+ /// When linking multiple modules defining the same symbol, all weak
+ /// definitions are discarded if any strong definitions exist; then if
+ /// multiple weak definitions exist all but one (unspecified) are discarded;
+ /// and finally it is an error if more than one definition remains.
+ pub const WASM_SYM_BINDING_WEAK: u32 = 0x1;
+
+ /// This is a local symbol.
+ ///
+ /// This flag is mutually exclusive with `WASM_SYM_BINDING_WEAK`.
+ ///
+ /// Local symbols are not to be exported, or linked to other
+ /// modules/sections. The names of all non-local symbols must be unique, but
+ /// the names of local symbols are not considered for uniqueness. A local
+ /// function or global symbol cannot reference an import.
+ pub const WASM_SYM_BINDING_LOCAL: u32 = 0x02;
+
+ /// This is a hidden symbol.
+ ///
+ /// Hidden symbols are not to be exported when performing the final link,
+ /// but may be linked to other modules.
+ pub const WASM_SYM_VISIBILITY_HIDDEN: u32 = 0x04;
+
+ /// This symbol is not defined.
+ ///
+ /// For non-data symbols, this must match whether the symbol is an import or
+ /// is defined; for data symbols, determines whether a segment is specified.
+ pub const WASM_SYM_UNDEFINED: u32 = 0x10;
+
+ /// This symbol is intended to be exported from the wasm module to the host
+ /// environment.
+ ///
+ /// This differs from the visibility flags in that it effects the static
+ /// linker.
+ pub const WASM_SYM_EXPORTED: u32 = 0x20;
+
+ /// This symbol uses an explicit symbol name, rather than reusing the name
+ /// from a wasm import.
+ ///
+ /// This allows it to remap imports from foreign WebAssembly modules into
+ /// local symbols with different names.
+ pub const WASM_SYM_EXPLICIT_NAME: u32 = 0x40;
+
+ /// This symbol is intended to be included in the linker output, regardless
+ /// of whether it is used by the program.
+ pub const WASM_SYM_NO_STRIP: u32 = 0x80;
+}
+
+impl Encode for SymbolTable {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(WASM_SYMBOL_TABLE);
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+/// The definition of a data symbol within a symbol table.
+#[derive(Clone, Debug)]
+pub struct DataSymbolDefinition {
+ /// The index of the data segment that this symbol is in.
+ pub index: u32,
+ /// The offset of this symbol within its segment.
+ pub offset: u32,
+ /// The byte size (which can be zero) of this data symbol.
+ ///
+ /// Note that `offset + size` must be less than or equal to the segment's
+ /// size.
+ pub size: u32,
+}
diff --git a/third_party/rust/wasm-encoder/src/core/memories.rs b/third_party/rust/wasm-encoder/src/core/memories.rs
new file mode 100644
index 0000000000..c651768bdc
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/memories.rs
@@ -0,0 +1,99 @@
+use crate::{encode_section, Encode, Section, SectionId};
+
+/// An encoder for the memory section.
+///
+/// Memory sections are only supported for modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Module, MemorySection, MemoryType};
+///
+/// let mut memories = MemorySection::new();
+/// memories.memory(MemoryType {
+/// minimum: 1,
+/// maximum: None,
+/// memory64: false,
+/// shared: false,
+/// });
+///
+/// let mut module = Module::new();
+/// module.section(&memories);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct MemorySection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl MemorySection {
+ /// Create a new memory section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of memories in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a memory.
+ pub fn memory(&mut self, memory_type: MemoryType) -> &mut Self {
+ memory_type.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for MemorySection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for MemorySection {
+ fn id(&self) -> u8 {
+ SectionId::Memory.into()
+ }
+}
+
+/// A memory's type.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct MemoryType {
+ /// Minimum size, in pages, of this memory
+ pub minimum: u64,
+ /// Maximum size, in pages, of this memory
+ pub maximum: Option<u64>,
+ /// Whether or not this is a 64-bit memory.
+ pub memory64: bool,
+ /// Whether or not this memory is shared.
+ pub shared: bool,
+}
+
+impl Encode for MemoryType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let mut flags = 0;
+ if self.maximum.is_some() {
+ flags |= 0b001;
+ }
+ if self.shared {
+ flags |= 0b010;
+ }
+ if self.memory64 {
+ flags |= 0b100;
+ }
+
+ sink.push(flags);
+ self.minimum.encode(sink);
+ if let Some(max) = self.maximum {
+ max.encode(sink);
+ }
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/names.rs b/third_party/rust/wasm-encoder/src/core/names.rs
new file mode 100644
index 0000000000..a1c31506fd
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/names.rs
@@ -0,0 +1,263 @@
+use crate::{encoding_size, CustomSection, Encode, Section, SectionId};
+
+/// An encoder for the custom `name` section.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Module, NameSection, NameMap};
+///
+/// let mut names = NameSection::new();
+/// names.module("the module name");
+///
+/// let mut function_names = NameMap::new();
+/// function_names.append(0, "name of function 0");
+/// function_names.append(1, "a better function");
+/// function_names.append(3, "the best function");
+/// names.functions(&function_names);
+///
+/// let mut module = Module::new();
+/// module.section(&names);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct NameSection {
+ bytes: Vec<u8>,
+}
+
+enum Subsection {
+ // Currently specified in the wasm spec's appendix
+ Module = 0,
+ Function = 1,
+ Local = 2,
+
+ // specified as part of the extended name section proposal
+ //
+ // https://github.com/WebAssembly/extended-name-section/blob/main/proposals/extended-name-section/Overview.md
+ Label = 3,
+ Type = 4,
+ Table = 5,
+ Memory = 6,
+ Global = 7,
+ Element = 8,
+ Data = 9,
+}
+
+impl NameSection {
+ /// Creates a new blank `name` custom section.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Appends a module name subsection to this section.
+ ///
+ /// This will indicate that the name of the entire module should be the
+ /// `name` specified. Note that this should be encoded first before other
+ /// subsections.
+ pub fn module(&mut self, name: &str) {
+ let len = encoding_size(u32::try_from(name.len()).unwrap());
+ self.subsection_header(Subsection::Module, len + name.len());
+ name.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all functions in this wasm module.
+ ///
+ /// Function names are declared in the `names` map provided where the index
+ /// in the map corresponds to the wasm index of the function. This section
+ /// should come after the module name subsection (if present) and before the
+ /// locals subsection (if present).
+ pub fn functions(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Function, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of locals within functions in the
+ /// wasm module.
+ ///
+ /// This section should come after the function name subsection (if present)
+ /// and before the labels subsection (if present).
+ pub fn locals(&mut self, names: &IndirectNameMap) {
+ self.subsection_header(Subsection::Local, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of labels within functions in the
+ /// wasm module.
+ ///
+ /// This section should come after the local name subsection (if present)
+ /// and before the type subsection (if present).
+ pub fn labels(&mut self, names: &IndirectNameMap) {
+ self.subsection_header(Subsection::Label, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all types in this wasm module.
+ ///
+ /// This section should come after the label name subsection (if present)
+ /// and before the table subsection (if present).
+ pub fn types(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Type, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all tables in this wasm module.
+ ///
+ /// This section should come after the type name subsection (if present)
+ /// and before the memory subsection (if present).
+ pub fn tables(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Table, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all memories in this wasm module.
+ ///
+ /// This section should come after the table name subsection (if present)
+ /// and before the global subsection (if present).
+ pub fn memories(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Memory, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all globals in this wasm module.
+ ///
+ /// This section should come after the memory name subsection (if present)
+ /// and before the element subsection (if present).
+ pub fn globals(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Global, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all elements in this wasm module.
+ ///
+ /// This section should come after the global name subsection (if present)
+ /// and before the data subsection (if present).
+ pub fn elements(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Element, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ /// Appends a subsection for the names of all data in this wasm module.
+ ///
+ /// This section should come after the element name subsection (if present).
+ pub fn data(&mut self, names: &NameMap) {
+ self.subsection_header(Subsection::Data, names.size());
+ names.encode(&mut self.bytes);
+ }
+
+ fn subsection_header(&mut self, id: Subsection, len: usize) {
+ self.bytes.push(id as u8);
+ len.encode(&mut self.bytes);
+ }
+
+ /// View the encoded section as a CustomSection.
+ pub fn as_custom<'a>(&'a self) -> CustomSection<'a> {
+ CustomSection {
+ name: "name",
+ data: &self.bytes,
+ }
+ }
+}
+
+impl Encode for NameSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.as_custom().encode(sink);
+ }
+}
+
+impl Section for NameSection {
+ fn id(&self) -> u8 {
+ SectionId::Custom.into()
+ }
+}
+
+/// A map used to name items in a wasm module, organized by naming each
+/// individual index.
+///
+/// This is used in conjunction with [`NameSection::functions`] and simlar
+/// methods.
+#[derive(Clone, Debug, Default)]
+pub struct NameMap {
+ bytes: Vec<u8>,
+ count: u32,
+}
+
+impl NameMap {
+ /// Creates a new empty `NameMap`.
+ pub fn new() -> NameMap {
+ NameMap {
+ bytes: vec![],
+ count: 0,
+ }
+ }
+
+ /// Adds a an entry where the item at `idx` has the `name` specified.
+ ///
+ /// Note that indices should be appended in ascending order of the index
+ /// value. Each index may only be named once, but not all indices must be
+ /// named (e.g. `0 foo; 1 bar; 7 qux` is valid but `0 foo; 0 bar` is not).
+ /// Names do not have to be unique (e.g. `0 foo; 1 foo; 2 foo` is valid).
+ pub fn append(&mut self, idx: u32, name: &str) {
+ idx.encode(&mut self.bytes);
+ name.encode(&mut self.bytes);
+ self.count += 1;
+ }
+
+ pub(crate) fn size(&self) -> usize {
+ encoding_size(self.count) + self.bytes.len()
+ }
+
+ /// Returns whether no names have been added to this map.
+ pub fn is_empty(&self) -> bool {
+ self.count == 0
+ }
+}
+
+impl Encode for NameMap {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.count.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
+
+/// A map used to describe names with two levels of indirection, as opposed to a
+/// [`NameMap`] which has one level of indirection.
+///
+/// This naming map is used with [`NameSection::locals`], for example.
+#[derive(Clone, Debug, Default)]
+pub struct IndirectNameMap {
+ bytes: Vec<u8>,
+ count: u32,
+}
+
+impl IndirectNameMap {
+ /// Creates a new empty name map.
+ pub fn new() -> IndirectNameMap {
+ IndirectNameMap {
+ bytes: vec![],
+ count: 0,
+ }
+ }
+
+ /// Adds a new entry where the item at `idx` has sub-items named within
+ /// `names` as specified.
+ ///
+ /// For example if this is describing local names then `idx` is a function
+ /// index where the indexes within `names` are local indices.
+ pub fn append(&mut self, idx: u32, names: &NameMap) {
+ idx.encode(&mut self.bytes);
+ names.encode(&mut self.bytes);
+ self.count += 1;
+ }
+
+ fn size(&self) -> usize {
+ encoding_size(self.count) + self.bytes.len()
+ }
+}
+
+impl Encode for IndirectNameMap {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.count.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/producers.rs b/third_party/rust/wasm-encoder/src/core/producers.rs
new file mode 100644
index 0000000000..ace908a7bd
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/producers.rs
@@ -0,0 +1,178 @@
+use crate::{CustomSection, Encode, Section, SectionId};
+
+/// An encoder for the [producers custom
+/// section](https://github.com/WebAssembly/tool-conventions/blob/main/ProducersSection.md).
+///
+/// This section is a non-standard convention that is supported by many toolchains.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{ProducersSection, ProducersField, Module};
+///
+/// // Create a new producers section.
+/// let mut field = ProducersField::new();
+/// field.value("clang", "14.0.4");
+/// field.value("rustc", "1.66.1 (90743e729 2023-01-10)");
+/// let mut producers = ProducersSection::new();
+/// producers.field("processed-by", &field);
+///
+/// // Add the producers section to a new Wasm module and get the encoded bytes.
+/// let mut module = Module::new();
+/// module.section(&producers);
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct ProducersSection {
+ bytes: Vec<u8>,
+ num_fields: u32,
+}
+
+impl ProducersSection {
+ /// Construct an empty encoder for the producers custom section.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Add a field to the section. The spec recommends names for this section
+ /// are "language", "processed-by", and "sdk". Each field in section must
+ /// have a unique name.
+ pub fn field(&mut self, name: &str, values: &ProducersField) -> &mut Self {
+ name.encode(&mut self.bytes);
+ values.encode(&mut self.bytes);
+ self.num_fields += 1;
+ self
+ }
+}
+
+impl Default for ProducersSection {
+ fn default() -> Self {
+ Self {
+ bytes: Vec::new(),
+ num_fields: 0,
+ }
+ }
+}
+
+impl Encode for ProducersSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let mut data = Vec::new();
+ self.num_fields.encode(&mut data);
+ data.extend(&self.bytes);
+
+ CustomSection {
+ name: "producers",
+ data: &data,
+ }
+ .encode(sink);
+ }
+}
+
+impl Section for ProducersSection {
+ fn id(&self) -> u8 {
+ SectionId::Custom.into()
+ }
+}
+
+/// The value of a field in the producers custom section
+#[derive(Clone, Debug)]
+pub struct ProducersField {
+ bytes: Vec<u8>,
+ num_values: u32,
+}
+
+impl ProducersField {
+ /// Construct an empty encoder for a producers field value
+ pub fn new() -> Self {
+ ProducersField::default()
+ }
+
+ /// Add a value to the field encoder. Each value in a field must have a
+ /// unique name. If there is no sensible value for `version`, use the
+ /// empty string.
+ pub fn value(&mut self, name: &str, version: &str) -> &mut Self {
+ name.encode(&mut self.bytes);
+ version.encode(&mut self.bytes);
+ self.num_values += 1;
+ self
+ }
+}
+
+impl Default for ProducersField {
+ fn default() -> Self {
+ Self {
+ bytes: Vec::new(),
+ num_values: 0,
+ }
+ }
+}
+
+impl Encode for ProducersField {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.num_values.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
+
+#[cfg(test)]
+mod test {
+ #[test]
+ fn roundtrip_example() {
+ use crate::{Module, ProducersField, ProducersSection};
+ use wasmparser::{Parser, Payload, ProducersSectionReader};
+
+ // Create a new producers section.
+ let mut field = ProducersField::new();
+ field.value("clang", "14.0.4");
+ field.value("rustc", "1.66.1");
+ let mut producers = ProducersSection::new();
+ producers.field("processed-by", &field);
+
+ // Add the producers section to a new Wasm module and get the encoded bytes.
+ let mut module = Module::new();
+ module.section(&producers);
+ let wasm_bytes = module.finish();
+
+ let mut parser = Parser::new(0).parse_all(&wasm_bytes);
+ let payload = parser
+ .next()
+ .expect("parser is not empty")
+ .expect("element is a payload");
+ match payload {
+ Payload::Version { .. } => {}
+ _ => panic!(""),
+ }
+ let payload = parser
+ .next()
+ .expect("parser is not empty")
+ .expect("element is a payload");
+ match payload {
+ Payload::CustomSection(c) => {
+ assert_eq!(c.name(), "producers");
+ let mut section = ProducersSectionReader::new(c.data(), c.data_offset())
+ .expect("readable as a producers section")
+ .into_iter();
+ let field = section
+ .next()
+ .expect("section has an element")
+ .expect("element is a producers field");
+ assert_eq!(field.name, "processed-by");
+ let mut values = field.values.into_iter();
+ let value = values
+ .next()
+ .expect("values has an element")
+ .expect("element is a producers field value");
+ assert_eq!(value.name, "clang");
+ assert_eq!(value.version, "14.0.4");
+
+ let value = values
+ .next()
+ .expect("values has another element")
+ .expect("element is a producers field value");
+ assert_eq!(value.name, "rustc");
+ assert_eq!(value.version, "1.66.1");
+ }
+ _ => panic!("unexpected payload"),
+ }
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/start.rs b/third_party/rust/wasm-encoder/src/core/start.rs
new file mode 100644
index 0000000000..8f12c0d0ef
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/start.rs
@@ -0,0 +1,39 @@
+use crate::{encoding_size, Encode, Section, SectionId};
+
+/// An encoder for the start section of WebAssembly modules.
+///
+/// # Example
+///
+/// Note: this doesn't actually define the function at index 0, its type, or its
+/// code body, so the resulting Wasm module will be invalid. See `TypeSection`,
+/// `FunctionSection`, and `CodeSection` for details on how to generate those
+/// things.
+///
+/// ```
+/// use wasm_encoder::{Module, StartSection};
+///
+/// let start = StartSection { function_index: 0 };
+///
+/// let mut module = Module::new();
+/// module.section(&start);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Copy, Debug)]
+pub struct StartSection {
+ /// The index of the start function.
+ pub function_index: u32,
+}
+
+impl Encode for StartSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encoding_size(self.function_index).encode(sink);
+ self.function_index.encode(sink);
+ }
+}
+
+impl Section for StartSection {
+ fn id(&self) -> u8 {
+ SectionId::Start.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/tables.rs b/third_party/rust/wasm-encoder/src/core/tables.rs
new file mode 100644
index 0000000000..cbb2048a64
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/tables.rs
@@ -0,0 +1,104 @@
+use crate::{encode_section, ConstExpr, Encode, RefType, Section, SectionId};
+
+/// An encoder for the table section.
+///
+/// Table sections are only supported for modules.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Module, TableSection, TableType, RefType};
+///
+/// let mut tables = TableSection::new();
+/// tables.table(TableType {
+/// element_type: RefType::FUNCREF,
+/// minimum: 128,
+/// maximum: None,
+/// });
+///
+/// let mut module = Module::new();
+/// module.section(&tables);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct TableSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl TableSection {
+ /// Construct a new table section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of tables in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a table.
+ pub fn table(&mut self, table_type: TableType) -> &mut Self {
+ table_type.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Define a table with an explicit initialization expression.
+ ///
+ /// Note that this is part of the function-references proposal.
+ pub fn table_with_init(&mut self, table_type: TableType, init: &ConstExpr) -> &mut Self {
+ self.bytes.push(0x40);
+ self.bytes.push(0x00);
+ table_type.encode(&mut self.bytes);
+ init.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for TableSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for TableSection {
+ fn id(&self) -> u8 {
+ SectionId::Table.into()
+ }
+}
+
+/// A table's type.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct TableType {
+ /// The table's element type.
+ pub element_type: RefType,
+ /// Minimum size, in elements, of this table
+ pub minimum: u32,
+ /// Maximum size, in elements, of this table
+ pub maximum: Option<u32>,
+}
+
+impl Encode for TableType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let mut flags = 0;
+ if self.maximum.is_some() {
+ flags |= 0b001;
+ }
+
+ self.element_type.encode(sink);
+ sink.push(flags);
+ self.minimum.encode(sink);
+
+ if let Some(max) = self.maximum {
+ max.encode(sink);
+ }
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/tags.rs b/third_party/rust/wasm-encoder/src/core/tags.rs
new file mode 100644
index 0000000000..413055f2af
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/tags.rs
@@ -0,0 +1,85 @@
+use crate::{encode_section, Encode, Section, SectionId};
+
+/// An encoder for the tag section.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Module, TagSection, TagType, TagKind};
+///
+/// let mut tags = TagSection::new();
+/// tags.tag(TagType {
+/// kind: TagKind::Exception,
+/// func_type_idx: 0,
+/// });
+///
+/// let mut module = Module::new();
+/// module.section(&tags);
+///
+/// let wasm_bytes = module.finish();
+/// ```
+#[derive(Clone, Default, Debug)]
+pub struct TagSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl TagSection {
+ /// Create a new tag section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of tags in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a tag.
+ pub fn tag(&mut self, tag_type: TagType) -> &mut Self {
+ tag_type.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for TagSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for TagSection {
+ fn id(&self) -> u8 {
+ SectionId::Tag.into()
+ }
+}
+
+/// Represents a tag kind.
+#[repr(u8)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum TagKind {
+ /// The tag is an exception type.
+ Exception = 0x0,
+}
+
+/// A tag's type.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct TagType {
+ /// The kind of tag
+ pub kind: TagKind,
+ /// The function type this tag uses
+ pub func_type_idx: u32,
+}
+
+impl Encode for TagType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(self.kind as u8);
+ self.func_type_idx.encode(sink);
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/core/types.rs b/third_party/rust/wasm-encoder/src/core/types.rs
new file mode 100644
index 0000000000..d21dbbc960
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/core/types.rs
@@ -0,0 +1,191 @@
+use crate::{encode_section, Encode, Section, SectionId};
+
+/// The type of a core WebAssembly value.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub enum ValType {
+ /// The `i32` type.
+ I32,
+ /// The `i64` type.
+ I64,
+ /// The `f32` type.
+ F32,
+ /// The `f64` type.
+ F64,
+ /// The `v128` type.
+ ///
+ /// Part of the SIMD proposal.
+ V128,
+ /// A reference type.
+ ///
+ /// The `funcref` and `externref` type fall into this category and the full
+ /// generalization here is due to the implementation of the
+ /// function-references proposal.
+ Ref(RefType),
+}
+
+impl ValType {
+ /// Alias for the `funcref` type in WebAssembly
+ pub const FUNCREF: ValType = ValType::Ref(RefType::FUNCREF);
+ /// Alias for the `externref` type in WebAssembly
+ pub const EXTERNREF: ValType = ValType::Ref(RefType::EXTERNREF);
+}
+
+impl Encode for ValType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ ValType::I32 => sink.push(0x7F),
+ ValType::I64 => sink.push(0x7E),
+ ValType::F32 => sink.push(0x7D),
+ ValType::F64 => sink.push(0x7C),
+ ValType::V128 => sink.push(0x7B),
+ ValType::Ref(rt) => rt.encode(sink),
+ }
+ }
+}
+
+/// A reference type.
+///
+/// This is largely part of the function references proposal for WebAssembly but
+/// additionally is used by the `funcref` and `externref` types. The full
+/// generality of this type is only exercised with function-references.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
+#[allow(missing_docs)]
+pub struct RefType {
+ pub nullable: bool,
+ pub heap_type: HeapType,
+}
+
+impl RefType {
+ /// Alias for the `funcref` type in WebAssembly
+ pub const FUNCREF: RefType = RefType {
+ nullable: true,
+ heap_type: HeapType::Func,
+ };
+
+ /// Alias for the `externref` type in WebAssembly
+ pub const EXTERNREF: RefType = RefType {
+ nullable: true,
+ heap_type: HeapType::Extern,
+ };
+}
+
+impl Encode for RefType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ if self.nullable {
+ // Favor the original encodings of `funcref` and `externref` where
+ // possible
+ match self.heap_type {
+ HeapType::Func => return sink.push(0x70),
+ HeapType::Extern => return sink.push(0x6f),
+ _ => {}
+ }
+ }
+
+ if self.nullable {
+ sink.push(0x6C);
+ } else {
+ sink.push(0x6B);
+ }
+ self.heap_type.encode(sink);
+ }
+}
+
+impl From<RefType> for ValType {
+ fn from(ty: RefType) -> ValType {
+ ValType::Ref(ty)
+ }
+}
+
+/// Part of the function references proposal.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub enum HeapType {
+ /// A function reference. When nullable, equivalent to `funcref`
+ Func,
+ /// An extern reference. When nullable, equivalent to `externref`
+ Extern,
+ /// A reference to a particular index in a table.
+ TypedFunc(u32),
+}
+
+impl Encode for HeapType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ HeapType::Func => sink.push(0x70),
+ HeapType::Extern => sink.push(0x6F),
+ // Note that this is encoded as a signed type rather than unsigned
+ // as it's decoded as an s33
+ HeapType::TypedFunc(i) => i64::from(*i).encode(sink),
+ }
+ }
+}
+
+/// An encoder for the type section of WebAssembly modules.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Module, TypeSection, ValType};
+///
+/// let mut types = TypeSection::new();
+///
+/// types.function([ValType::I32, ValType::I32], [ValType::I64]);
+///
+/// let mut module = Module::new();
+/// module.section(&types);
+///
+/// let bytes = module.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct TypeSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl TypeSection {
+ /// Create a new module type section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of types in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a function type in this type section.
+ pub fn function<P, R>(&mut self, params: P, results: R) -> &mut Self
+ where
+ P: IntoIterator<Item = ValType>,
+ P::IntoIter: ExactSizeIterator,
+ R: IntoIterator<Item = ValType>,
+ R::IntoIter: ExactSizeIterator,
+ {
+ let params = params.into_iter();
+ let results = results.into_iter();
+
+ self.bytes.push(0x60);
+ params.len().encode(&mut self.bytes);
+ params.for_each(|p| p.encode(&mut self.bytes));
+ results.len().encode(&mut self.bytes);
+ results.for_each(|p| p.encode(&mut self.bytes));
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for TypeSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl Section for TypeSection {
+ fn id(&self) -> u8 {
+ SectionId::Type.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/lib.rs b/third_party/rust/wasm-encoder/src/lib.rs
new file mode 100644
index 0000000000..3f36562508
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/lib.rs
@@ -0,0 +1,188 @@
+//! A WebAssembly encoder.
+//!
+//! The main builder is the [`Module`]. You can build a section with a
+//! section-specific builder, like [`TypeSection`] or [`ImportSection`], and
+//! then add it to the module with [`Module::section`]. When you are finished
+//! building the module, call either [`Module::as_slice`] or [`Module::finish`]
+//! to get the encoded bytes. The former gives a shared reference to the
+//! underlying bytes as a slice, while the latter gives you ownership of them as
+//! a vector.
+//!
+//! # Example
+//!
+//! If we wanted to build this module:
+//!
+//! ```wasm
+//! (module
+//! (type (func (param i32 i32) (result i32)))
+//! (func (type 0)
+//! local.get 0
+//! local.get 1
+//! i32.add)
+//! (export "f" (func 0)))
+//! ```
+//!
+//! then we would do this:
+//!
+//! ```
+//! use wasm_encoder::{
+//! CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction,
+//! Module, TypeSection, ValType,
+//! };
+//!
+//! let mut module = Module::new();
+//!
+//! // Encode the type section.
+//! let mut types = TypeSection::new();
+//! let params = vec![ValType::I32, ValType::I32];
+//! let results = vec![ValType::I32];
+//! types.function(params, results);
+//! module.section(&types);
+//!
+//! // Encode the function section.
+//! let mut functions = FunctionSection::new();
+//! let type_index = 0;
+//! functions.function(type_index);
+//! module.section(&functions);
+//!
+//! // Encode the export section.
+//! let mut exports = ExportSection::new();
+//! exports.export("f", ExportKind::Func, 0);
+//! module.section(&exports);
+//!
+//! // Encode the code section.
+//! let mut codes = CodeSection::new();
+//! let locals = vec![];
+//! let mut f = Function::new(locals);
+//! f.instruction(&Instruction::LocalGet(0));
+//! f.instruction(&Instruction::LocalGet(1));
+//! f.instruction(&Instruction::I32Add);
+//! f.instruction(&Instruction::End);
+//! codes.function(&f);
+//! module.section(&codes);
+//!
+//! // Extract the encoded Wasm bytes for this module.
+//! let wasm_bytes = module.finish();
+//!
+//! // We generated a valid Wasm module!
+//! assert!(wasmparser::validate(&wasm_bytes).is_ok());
+//! ```
+
+#![deny(missing_docs, missing_debug_implementations)]
+
+mod component;
+mod core;
+mod raw;
+
+pub use self::component::*;
+pub use self::core::*;
+pub use self::raw::*;
+
+/// Implemented by types that can be encoded into a byte sink.
+pub trait Encode {
+ /// Encode the type into the given byte sink.
+ fn encode(&self, sink: &mut Vec<u8>);
+}
+
+impl<T: Encode + ?Sized> Encode for &'_ T {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ T::encode(self, sink)
+ }
+}
+
+impl<T: Encode> Encode for [T] {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.len().encode(sink);
+ for item in self {
+ item.encode(sink);
+ }
+ }
+}
+
+impl Encode for [u8] {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.len().encode(sink);
+ sink.extend(self);
+ }
+}
+
+impl Encode for str {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.len().encode(sink);
+ sink.extend_from_slice(self.as_bytes());
+ }
+}
+
+impl Encode for usize {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ assert!(*self <= u32::max_value() as usize);
+ (*self as u32).encode(sink)
+ }
+}
+
+impl Encode for u32 {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ leb128::write::unsigned(sink, (*self).into()).unwrap();
+ }
+}
+
+impl Encode for i32 {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ leb128::write::signed(sink, (*self).into()).unwrap();
+ }
+}
+
+impl Encode for u64 {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ leb128::write::unsigned(sink, *self).unwrap();
+ }
+}
+
+impl Encode for i64 {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ leb128::write::signed(sink, *self).unwrap();
+ }
+}
+
+impl<T> Encode for Option<T>
+where
+ T: Encode,
+{
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Some(v) => {
+ sink.push(0x01);
+ v.encode(sink);
+ }
+ None => sink.push(0x00),
+ }
+ }
+}
+
+fn encoding_size(n: u32) -> usize {
+ let mut buf = [0u8; 5];
+ leb128::write::unsigned(&mut &mut buf[..], n.into()).unwrap()
+}
+
+fn encode_section(sink: &mut Vec<u8>, count: u32, bytes: &[u8]) {
+ (encoding_size(count) + bytes.len()).encode(sink);
+ count.encode(sink);
+ sink.extend(bytes);
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn it_encodes_an_empty_module() {
+ let bytes = Module::new().finish();
+ assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x01, 0x00, 0x00, 0x00]);
+ }
+
+ #[test]
+ fn it_encodes_an_empty_component() {
+ let bytes = Component::new().finish();
+ assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x0c, 0x00, 0x01, 0x00]);
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/raw.rs b/third_party/rust/wasm-encoder/src/raw.rs
new file mode 100644
index 0000000000..a1323ca88e
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/raw.rs
@@ -0,0 +1,30 @@
+use crate::{ComponentSection, Encode, Section};
+
+/// A section made up of uninterpreted, raw bytes.
+///
+/// Allows you to splat any data into a module or component.
+#[derive(Clone, Copy, Debug)]
+pub struct RawSection<'a> {
+ /// The id for this section.
+ pub id: u8,
+ /// The raw data for this section.
+ pub data: &'a [u8],
+}
+
+impl Encode for RawSection<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.data.encode(sink);
+ }
+}
+
+impl Section for RawSection<'_> {
+ fn id(&self) -> u8 {
+ self.id
+ }
+}
+
+impl ComponentSection for RawSection<'_> {
+ fn id(&self) -> u8 {
+ self.id
+ }
+}