waffle/ir.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
//! Intermediate representation for Wasm.
use crate::{declare_entity, entity::EntityRef};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
/// Types in waffle's IR.
///
/// These types correspond to (a subset of) the primitive Wasm value
/// types: integers, floats, SIMD vectors, and function references
/// (optionally typed).
///
/// Every SSA value in a function body has a `Type`, unless it is a
/// tuple (multi-value or zero-value result).
pub enum Type {
/// A 32-bit integer. Signedness is unspecified: individual
/// operators specify how they handle sign.
I32,
/// A 64-bit integer. Signedness is unspecified: individual
/// operators specify how they handle sign.
I64,
/// A 32-bit IEEE 754 floating point value. Semantics around NaNs
/// are defined by individual operators; from the point of view of
/// IR scaffolding, floating-point values are bags of bits.
F32,
/// A 64-bit IEEE 754 floating point value. Semantics around NaNs
/// are defined by individual operators; from the point of view of
/// IR scaffolding, floating-point values are bags of bits.
F64,
/// A 128-bit SIMD vector value. Lanes and lane types are
/// specified by individual operators; from the point of view of
/// IR scaffolding, SIMD vector values are bags of bits.
V128,
/// A function reference.
FuncRef,
ExternRef,
TypedFuncRef {
nullable: bool,
sig_index: Signature,
},
}
impl From<wasmparser::ValType> for Type {
fn from(ty: wasmparser::ValType) -> Self {
match ty {
wasmparser::ValType::I32 => Type::I32,
wasmparser::ValType::I64 => Type::I64,
wasmparser::ValType::F32 => Type::F32,
wasmparser::ValType::F64 => Type::F64,
wasmparser::ValType::V128 => Type::V128,
wasmparser::ValType::Ref(r) => r.into(),
}
}
}
impl From<wasmparser::RefType> for Type {
fn from(ty: wasmparser::RefType) -> Self {
if ty.is_extern_ref() {
return Type::ExternRef;
}
match ty.type_index() {
Some(idx) => {
let nullable = ty.is_nullable();
Type::TypedFuncRef {
nullable: nullable,
sig_index: Signature::new(idx.as_module_index().unwrap() as usize),
}
}
None => Type::FuncRef,
}
}
}
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Type::I32 => write!(f, "i32"),
Type::I64 => write!(f, "i64"),
Type::F32 => write!(f, "f32"),
Type::F64 => write!(f, "f64"),
Type::V128 => write!(f, "v128"),
Type::FuncRef => write!(f, "funcref"),
Type::ExternRef => write!(f, "externref"),
Type::TypedFuncRef {
nullable,
sig_index,
} => write!(
f,
"funcref({}, {})",
if *nullable { "null" } else { "not_null" },
sig_index
),
}
}
}
impl From<Type> for wasm_encoder::ValType {
fn from(ty: Type) -> wasm_encoder::ValType {
match ty {
Type::I32 => wasm_encoder::ValType::I32,
Type::I64 => wasm_encoder::ValType::I64,
Type::F32 => wasm_encoder::ValType::F32,
Type::F64 => wasm_encoder::ValType::F64,
Type::V128 => wasm_encoder::ValType::V128,
Type::FuncRef | Type::TypedFuncRef { .. } | Type::ExternRef => {
wasm_encoder::ValType::Ref(ty.into())
}
}
}
}
impl From<Type> for wasm_encoder::RefType {
fn from(ty: Type) -> wasm_encoder::RefType {
match ty {
Type::ExternRef => wasm_encoder::RefType::EXTERNREF,
Type::FuncRef => wasm_encoder::RefType::FUNCREF,
Type::TypedFuncRef{nullable,sig_index} => wasm_encoder::RefType {
nullable,
heap_type: wasm_encoder::HeapType::Concrete(sig_index.0),
},
_ => panic!("Cannot convert {:?} into reftype", ty),
}
}
}
// Per-module index spaces:
// A signature (list of parameter types and list of return types) in
// the module.
declare_entity!(Signature, "sig");
// A function in the module.
declare_entity!(Func, "func");
// A global variable in the module.
declare_entity!(Global, "global");
// A table in the module.
declare_entity!(Table, "table");
// A memory in the module.
declare_entity!(Memory, "memory");
// Per-function index spaces:
// A basic block in one function body.
declare_entity!(Block, "block");
// A local variable (storage slot) in one function body.
declare_entity!(Local, "local");
// An SSA value in one function body.
declare_entity!(Value, "v");
mod module;
pub use module::*;
mod func;
pub use func::*;
mod value;
pub use value::*;
mod display;
pub use display::*;
mod debug;
pub use debug::*;