cranelift_wasm/
translation_utils.rs

1//! Helper functions and structures for the translation.
2use crate::environ::TargetEnvironment;
3use crate::WasmResult;
4use core::convert::TryInto;
5use core::u32;
6use cranelift_codegen::ir;
7use cranelift_frontend::FunctionBuilder;
8#[cfg(feature = "enable-serde")]
9use serde::{Deserialize, Serialize};
10use wasmparser::{FuncValidator, WasmFuncType, WasmModuleResources};
11
12/// Get the parameter and result types for the given Wasm blocktype.
13pub fn blocktype_params_results<'a, T>(
14    validator: &'a FuncValidator<T>,
15    ty: wasmparser::BlockType,
16) -> WasmResult<(
17    impl ExactSizeIterator<Item = wasmparser::ValType> + Clone + 'a,
18    impl ExactSizeIterator<Item = wasmparser::ValType> + Clone + 'a,
19)>
20where
21    T: WasmModuleResources,
22{
23    return Ok(match ty {
24        wasmparser::BlockType::Empty => {
25            let params: &'static [wasmparser::ValType] = &[];
26            let results: &'static [wasmparser::ValType] = &[];
27            (
28                itertools::Either::Left(params.iter().copied()),
29                itertools::Either::Left(results.iter().copied()),
30            )
31        }
32        wasmparser::BlockType::Type(ty) => {
33            let params: &'static [wasmparser::ValType] = &[];
34            let results: &'static [wasmparser::ValType] = match ty {
35                wasmparser::ValType::I32 => &[wasmparser::ValType::I32],
36                wasmparser::ValType::I64 => &[wasmparser::ValType::I64],
37                wasmparser::ValType::F32 => &[wasmparser::ValType::F32],
38                wasmparser::ValType::F64 => &[wasmparser::ValType::F64],
39                wasmparser::ValType::V128 => &[wasmparser::ValType::V128],
40                wasmparser::ValType::EXTERNREF => &[wasmparser::ValType::EXTERNREF],
41                wasmparser::ValType::FUNCREF => &[wasmparser::ValType::FUNCREF],
42                wasmparser::ValType::Ref(_) => unimplemented!("function references proposal"),
43            };
44            (
45                itertools::Either::Left(params.iter().copied()),
46                itertools::Either::Left(results.iter().copied()),
47            )
48        }
49        wasmparser::BlockType::FuncType(ty_index) => {
50            let ty = validator
51                .resources()
52                .func_type_at(ty_index)
53                .expect("should be valid");
54            (
55                itertools::Either::Right(ty.inputs()),
56                itertools::Either::Right(ty.outputs()),
57            )
58        }
59    });
60}
61
62/// Create a `Block` with the given Wasm parameters.
63pub fn block_with_params<PE: TargetEnvironment + ?Sized>(
64    builder: &mut FunctionBuilder,
65    params: impl IntoIterator<Item = wasmparser::ValType>,
66    environ: &PE,
67) -> WasmResult<ir::Block> {
68    let block = builder.create_block();
69    for ty in params {
70        match ty {
71            wasmparser::ValType::I32 => {
72                builder.append_block_param(block, ir::types::I32);
73            }
74            wasmparser::ValType::I64 => {
75                builder.append_block_param(block, ir::types::I64);
76            }
77            wasmparser::ValType::F32 => {
78                builder.append_block_param(block, ir::types::F32);
79            }
80            wasmparser::ValType::F64 => {
81                builder.append_block_param(block, ir::types::F64);
82            }
83            wasmparser::ValType::Ref(ty) => {
84                builder.append_block_param(block, environ.reference_type(ty.try_into()?));
85            }
86            wasmparser::ValType::V128 => {
87                builder.append_block_param(block, ir::types::I8X16);
88            }
89        }
90    }
91    Ok(block)
92}
93
94/// Turns a `wasmparser` `f32` into a `Cranelift` one.
95pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
96    ir::immediates::Ieee32::with_bits(x.bits())
97}
98
99/// Turns a `wasmparser` `f64` into a `Cranelift` one.
100pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
101    ir::immediates::Ieee64::with_bits(x.bits())
102}
103
104/// Special VMContext value label. It is tracked as 0xffff_fffe label.
105pub fn get_vmctx_value_label() -> ir::ValueLabel {
106    const VMCTX_LABEL: u32 = 0xffff_fffe;
107    ir::ValueLabel::from_u32(VMCTX_LABEL)
108}