use crate::bytecode::MoveModule;
use anyhow::Result;
use wasm_encoder::{Module, ValType};
mod exports;
mod functions;
mod imports;
mod instructions;
mod types;
pub(super) use imports::{SCRATCH_KEY_OFFSET, SCRATCH_VALUE_OFFSET};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueKind {
I32,
I64,
}
impl ValueKind {
pub fn val_type(self) -> ValType {
match self {
ValueKind::I32 => ValType::I32,
ValueKind::I64 => ValType::I64,
}
}
}
#[derive(Debug, Default)]
pub struct ImportLayout {
pub storage_get: Option<u32>,
pub storage_put: Option<u32>,
pub storage_delete: Option<u32>,
}
pub fn translate_to_wasm(module: &MoveModule) -> Result<Vec<u8>> {
let needs_storage = module
.functions
.iter()
.any(|f| f.code.iter().any(super::resources::is_resource_opcode));
let (types, func_type_indices, _next_type_index) = types::build_types(module, needs_storage)?;
let (imports, import_layout, imported_functions) = imports::build_imports(needs_storage)?;
let (functions, code) = functions::build_functions(
module,
&func_type_indices,
imported_functions,
&import_layout,
needs_storage,
)?;
let (exports, memory) = exports::build_exports(module, imported_functions, needs_storage)?;
let mut module_bytes = Module::new();
module_bytes.section(&types);
if imported_functions > 0 {
module_bytes.section(&imports);
}
module_bytes.section(&functions);
if let Some(mem) = memory {
module_bytes.section(&mem);
}
module_bytes.section(&exports);
module_bytes.section(&code);
Ok(module_bytes.finish())
}