use crate::component::*;
use crate::prelude::*;
use crate::{EntityIndex, PrimaryMap, WasmValType};
use serde_derive::{Deserialize, Serialize};
use wasmtime_types::ModuleInternedTypeIndex;
pub struct ComponentTranslation {
pub component: Component,
pub trampolines: PrimaryMap<TrampolineIndex, Trampoline>,
}
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Component {
pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
pub exports: NameMap<String, ExportIndex>,
pub export_items: PrimaryMap<ExportIndex, Export>,
pub initializers: Vec<GlobalInitializer>,
pub num_runtime_instances: u32,
pub num_runtime_component_instances: u32,
pub num_runtime_memories: u32,
pub num_runtime_reallocs: u32,
pub num_runtime_post_returns: u32,
pub trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
pub num_lowerings: u32,
pub num_resource_tables: usize,
pub num_resources: u32,
pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
pub defined_resource_instances: PrimaryMap<DefinedResourceIndex, RuntimeComponentInstanceIndex>,
}
impl Component {
pub fn defined_resource_index(&self, idx: ResourceIndex) -> Option<DefinedResourceIndex> {
let idx = idx
.as_u32()
.checked_sub(self.imported_resources.len() as u32)?;
Some(DefinedResourceIndex::from_u32(idx))
}
pub fn resource_index(&self, idx: DefinedResourceIndex) -> ResourceIndex {
ResourceIndex::from_u32(self.imported_resources.len() as u32 + idx.as_u32())
}
}
#[derive(Debug, Serialize, Deserialize)]
pub enum GlobalInitializer {
InstantiateModule(InstantiateModule),
LowerImport {
index: LoweredIndex,
import: RuntimeImportIndex,
},
ExtractMemory(ExtractMemory),
ExtractRealloc(ExtractRealloc),
ExtractPostReturn(ExtractPostReturn),
Resource(Resource),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractMemory {
pub index: RuntimeMemoryIndex,
pub export: CoreExport<MemoryIndex>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractRealloc {
pub index: RuntimeReallocIndex,
pub def: CoreDef,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractPostReturn {
pub index: RuntimePostReturnIndex,
pub def: CoreDef,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum InstantiateModule {
Static(StaticModuleIndex, Box<[CoreDef]>),
Import(
RuntimeImportIndex,
IndexMap<String, IndexMap<String, CoreDef>>,
),
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub enum CoreDef {
Export(CoreExport<EntityIndex>),
InstanceFlags(RuntimeComponentInstanceIndex),
Trampoline(TrampolineIndex),
}
impl<T> From<CoreExport<T>> for CoreDef
where
EntityIndex: From<T>,
{
fn from(export: CoreExport<T>) -> CoreDef {
CoreDef::Export(export.map_index(|i| i.into()))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub struct CoreExport<T> {
pub instance: RuntimeInstanceIndex,
pub item: ExportItem<T>,
}
impl<T> CoreExport<T> {
pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
CoreExport {
instance: self.instance,
item: match self.item {
ExportItem::Index(i) => ExportItem::Index(f(i)),
ExportItem::Name(s) => ExportItem::Name(s),
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub enum ExportItem<T> {
Index(T),
Name(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Export {
LiftedFunction {
ty: TypeFuncIndex,
func: CoreDef,
options: CanonicalOptions,
},
ModuleStatic {
ty: TypeModuleIndex,
index: StaticModuleIndex,
},
ModuleImport {
ty: TypeModuleIndex,
import: RuntimeImportIndex,
},
Instance {
ty: TypeComponentInstanceIndex,
exports: NameMap<String, ExportIndex>,
},
Type(TypeDef),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CanonicalOptions {
pub instance: RuntimeComponentInstanceIndex,
pub string_encoding: StringEncoding,
pub memory: Option<RuntimeMemoryIndex>,
pub realloc: Option<RuntimeReallocIndex>,
pub post_return: Option<RuntimePostReturnIndex>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
#[repr(u8)]
pub enum StringEncoding {
Utf8,
Utf16,
CompactUtf16,
}
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub enum Transcode {
Copy(FixedEncoding),
Latin1ToUtf16,
Latin1ToUtf8,
Utf16ToCompactProbablyUtf16,
Utf16ToCompactUtf16,
Utf16ToLatin1,
Utf16ToUtf8,
Utf8ToCompactUtf16,
Utf8ToLatin1,
Utf8ToUtf16,
}
impl Transcode {
pub fn symbol_fragment(&self) -> &'static str {
match self {
Transcode::Copy(x) => match x {
FixedEncoding::Utf8 => "copy_utf8",
FixedEncoding::Utf16 => "copy_utf16",
FixedEncoding::Latin1 => "copy_latin1",
},
Transcode::Latin1ToUtf16 => "latin1_to_utf16",
Transcode::Latin1ToUtf8 => "latin1_to_utf8",
Transcode::Utf16ToCompactProbablyUtf16 => "utf16_to_compact_probably_utf16",
Transcode::Utf16ToCompactUtf16 => "utf16_to_compact_utf16",
Transcode::Utf16ToLatin1 => "utf16_to_latin1",
Transcode::Utf16ToUtf8 => "utf16_to_utf8",
Transcode::Utf8ToCompactUtf16 => "utf8_to_compact_utf16",
Transcode::Utf8ToLatin1 => "utf8_to_latin1",
Transcode::Utf8ToUtf16 => "utf8_to_utf16",
}
}
pub fn desc(&self) -> &'static str {
match self {
Transcode::Copy(FixedEncoding::Utf8) => "utf8-to-utf8",
Transcode::Copy(FixedEncoding::Utf16) => "utf16-to-utf16",
Transcode::Copy(FixedEncoding::Latin1) => "latin1-to-latin1",
Transcode::Latin1ToUtf16 => "latin1-to-utf16",
Transcode::Latin1ToUtf8 => "latin1-to-utf8",
Transcode::Utf16ToCompactProbablyUtf16 => "utf16-to-compact-probably-utf16",
Transcode::Utf16ToCompactUtf16 => "utf16-to-compact-utf16",
Transcode::Utf16ToLatin1 => "utf16-to-latin1",
Transcode::Utf16ToUtf8 => "utf16-to-utf8",
Transcode::Utf8ToCompactUtf16 => "utf8-to-compact-utf16",
Transcode::Utf8ToLatin1 => "utf8-to-latin1",
Transcode::Utf8ToUtf16 => "utf8-to-utf16",
}
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
#[allow(missing_docs)]
pub enum FixedEncoding {
Utf8,
Utf16,
Latin1,
}
impl FixedEncoding {
pub fn width(&self) -> u8 {
match self {
FixedEncoding::Utf8 => 1,
FixedEncoding::Utf16 => 2,
FixedEncoding::Latin1 => 1,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Resource {
pub index: DefinedResourceIndex,
pub rep: WasmValType,
pub dtor: Option<CoreDef>,
pub instance: RuntimeComponentInstanceIndex,
}
pub enum Trampoline {
LowerImport {
index: LoweredIndex,
lower_ty: TypeFuncIndex,
options: CanonicalOptions,
},
Transcoder {
op: Transcode,
from: RuntimeMemoryIndex,
from64: bool,
to: RuntimeMemoryIndex,
to64: bool,
},
AlwaysTrap,
ResourceNew(TypeResourceTableIndex),
ResourceRep(TypeResourceTableIndex),
ResourceDrop(TypeResourceTableIndex),
ResourceTransferOwn,
ResourceTransferBorrow,
ResourceEnterCall,
ResourceExitCall,
}
impl Trampoline {
pub fn symbol_name(&self) -> String {
use Trampoline::*;
match self {
LowerImport { index, .. } => {
format!("component-lower-import[{}]", index.as_u32())
}
Transcoder {
op, from64, to64, ..
} => {
let op = op.symbol_fragment();
let from = if *from64 { "64" } else { "32" };
let to = if *to64 { "64" } else { "32" };
format!("component-transcode-{op}-m{from}-m{to}")
}
AlwaysTrap => format!("component-always-trap"),
ResourceNew(i) => format!("component-resource-new[{}]", i.as_u32()),
ResourceRep(i) => format!("component-resource-rep[{}]", i.as_u32()),
ResourceDrop(i) => format!("component-resource-drop[{}]", i.as_u32()),
ResourceTransferOwn => format!("component-resource-transfer-own"),
ResourceTransferBorrow => format!("component-resource-transfer-borrow"),
ResourceEnterCall => format!("component-resource-enter-call"),
ResourceExitCall => format!("component-resource-exit-call"),
}
}
}