use crate::environ::{TargetEnvironment, WasmResult};
use crate::state::ModuleTranslationState;
use crate::wasm_unsupported;
use core::u32;
use cranelift_codegen::entity::entity_impl;
use cranelift_codegen::ir;
use cranelift_codegen::ir::immediates::V128Imm;
use cranelift_frontend::FunctionBuilder;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use wasmparser;
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct FuncIndex(u32);
entity_impl!(FuncIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedFuncIndex(u32);
entity_impl!(DefinedFuncIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedTableIndex(u32);
entity_impl!(DefinedTableIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedMemoryIndex(u32);
entity_impl!(DefinedMemoryIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedGlobalIndex(u32);
entity_impl!(DefinedGlobalIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct TableIndex(u32);
entity_impl!(TableIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct GlobalIndex(u32);
entity_impl!(GlobalIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct MemoryIndex(u32);
entity_impl!(MemoryIndex);
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct SignatureIndex(u32);
entity_impl!(SignatureIndex);
#[derive(Debug, Clone, Copy, Hash)]
pub struct Global {
pub ty: ir::Type,
pub mutability: bool,
pub initializer: GlobalInit,
}
#[derive(Debug, Clone, Copy, Hash)]
pub enum GlobalInit {
I32Const(i32),
I64Const(i64),
F32Const(u32),
F64Const(u64),
V128Const(V128Imm),
GetGlobal(GlobalIndex),
RefNullConst,
Import,
}
#[derive(Debug, Clone, Copy, Hash)]
pub struct Table {
pub ty: TableElementType,
pub minimum: u32,
pub maximum: Option<u32>,
}
#[derive(Debug, Clone, Copy, Hash)]
pub enum TableElementType {
Val(ir::Type),
Func,
}
#[derive(Debug, Clone, Copy, Hash)]
pub struct Memory {
pub minimum: u32,
pub maximum: Option<u32>,
pub shared: bool,
}
pub fn type_to_type<PE: TargetEnvironment + ?Sized>(
ty: wasmparser::Type,
environ: &PE,
) -> WasmResult<ir::Type> {
match ty {
wasmparser::Type::I32 => Ok(ir::types::I32),
wasmparser::Type::I64 => Ok(ir::types::I64),
wasmparser::Type::F32 => Ok(ir::types::F32),
wasmparser::Type::F64 => Ok(ir::types::F64),
wasmparser::Type::V128 => Ok(ir::types::I8X16),
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc => Ok(environ.reference_type()),
ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)),
}
}
pub fn tabletype_to_type<PE: TargetEnvironment + ?Sized>(
ty: wasmparser::Type,
environ: &PE,
) -> WasmResult<Option<ir::Type>> {
match ty {
wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
wasmparser::Type::AnyRef => Ok(Some(environ.reference_type())),
wasmparser::Type::AnyFunc => Ok(None),
ty => Err(wasm_unsupported!(
"tabletype_to_type: table wasm type {:?}",
ty
)),
}
}
pub fn blocktype_params_results(
module_translation_state: &ModuleTranslationState,
ty_or_ft: wasmparser::TypeOrFuncType,
) -> WasmResult<(&[wasmparser::Type], &[wasmparser::Type])> {
Ok(match ty_or_ft {
wasmparser::TypeOrFuncType::Type(ty) => match ty {
wasmparser::Type::I32 => (&[], &[wasmparser::Type::I32]),
wasmparser::Type::I64 => (&[], &[wasmparser::Type::I64]),
wasmparser::Type::F32 => (&[], &[wasmparser::Type::F32]),
wasmparser::Type::F64 => (&[], &[wasmparser::Type::F64]),
wasmparser::Type::V128 => (&[], &[wasmparser::Type::V128]),
wasmparser::Type::AnyRef => (&[], &[wasmparser::Type::AnyRef]),
wasmparser::Type::AnyFunc => (&[], &[wasmparser::Type::AnyFunc]),
wasmparser::Type::EmptyBlockType => (&[], &[]),
ty => return Err(wasm_unsupported!("blocktype_params_results: type {:?}", ty)),
},
wasmparser::TypeOrFuncType::FuncType(ty_index) => {
let sig_idx = SignatureIndex::from_u32(ty_index);
let (ref params, ref returns) = module_translation_state.wasm_types[sig_idx];
(&*params, &*returns)
}
})
}
pub fn ebb_with_params<PE: TargetEnvironment + ?Sized>(
builder: &mut FunctionBuilder,
params: &[wasmparser::Type],
environ: &PE,
) -> WasmResult<ir::Ebb> {
let ebb = builder.create_ebb();
for ty in params.iter() {
match ty {
wasmparser::Type::I32 => {
builder.append_ebb_param(ebb, ir::types::I32);
}
wasmparser::Type::I64 => {
builder.append_ebb_param(ebb, ir::types::I64);
}
wasmparser::Type::F32 => {
builder.append_ebb_param(ebb, ir::types::F32);
}
wasmparser::Type::F64 => {
builder.append_ebb_param(ebb, ir::types::F64);
}
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc => {
builder.append_ebb_param(ebb, environ.reference_type());
}
wasmparser::Type::V128 => {
builder.append_ebb_param(ebb, ir::types::I8X16);
}
ty => {
return Err(wasm_unsupported!(
"ebb_with_params: type {:?} in multi-value block's signature",
ty
))
}
}
}
Ok(ebb)
}
pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
ir::immediates::Ieee32::with_bits(x.bits())
}
pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
ir::immediates::Ieee64::with_bits(x.bits())
}
pub fn get_vmctx_value_label() -> ir::ValueLabel {
const VMCTX_LABEL: u32 = 0xffff_fffe;
ir::ValueLabel::from_u32(VMCTX_LABEL)
}